Initial commit: Book management system with Rust Loco backend and Vue 3 frontend
This commit is contained in:
@@ -0,0 +1,185 @@
|
||||
use book_manager::app::App;
|
||||
use loco_rs::testing::prelude::*;
|
||||
use serial_test::serial;
|
||||
|
||||
use super::prepare_data;
|
||||
|
||||
#[tokio::test]
|
||||
#[serial]
|
||||
async fn can_list_books_with_pagination() {
|
||||
request::<App, _, _>(|request, _ctx| async move {
|
||||
// First test if auth endpoint works (to verify routing is working)
|
||||
let auth_response = request.get("/api/auth/current").await;
|
||||
println!("Auth endpoint status: {}", auth_response.status_code());
|
||||
|
||||
// Now test books endpoint
|
||||
let response = request.get("/api/books").await;
|
||||
|
||||
let status = response.status_code();
|
||||
let body = response.text();
|
||||
|
||||
println!("Books endpoint status: {}", status);
|
||||
println!("Books response (first 300 chars): {}", &body[..body.len().min(300)]);
|
||||
|
||||
// The route should return 200 with JSON, not HTML
|
||||
assert_eq!(
|
||||
status,
|
||||
200,
|
||||
"List books request should succeed"
|
||||
);
|
||||
|
||||
// Check if it's JSON (not HTML)
|
||||
assert!(
|
||||
body.trim_start().starts_with('{'),
|
||||
"Response should be JSON, but got: {}",
|
||||
&body[..body.len().min(100)]
|
||||
);
|
||||
|
||||
// Try to parse as JSON
|
||||
let json: serde_json::Value = serde_json::from_str(&body)
|
||||
.expect("Response should be valid JSON");
|
||||
|
||||
// Verify response structure
|
||||
assert!(json.get("books").is_some(), "Response should contain 'books' field");
|
||||
assert!(json.get("total").is_some(), "Response should contain 'total' field");
|
||||
assert!(json.get("page").is_some(), "Response should contain 'page' field");
|
||||
assert!(json.get("per_page").is_some(), "Response should contain 'per_page' field");
|
||||
assert!(json.get("total_pages").is_some(), "Response should contain 'total_pages' field");
|
||||
|
||||
// Verify default values
|
||||
assert_eq!(json["page"], 1, "Default page should be 1");
|
||||
assert_eq!(json["per_page"], 12, "Default per_page should be 12");
|
||||
})
|
||||
.await;
|
||||
}
|
||||
|
||||
#[tokio::test]
|
||||
#[serial]
|
||||
async fn can_list_books_with_custom_pagination() {
|
||||
request::<App, _, _>(|request, _ctx| async move {
|
||||
// Test custom pagination parameters
|
||||
let response = request.get("/api/books?page=2&per_page=5").await;
|
||||
|
||||
assert_eq!(
|
||||
response.status_code(),
|
||||
200,
|
||||
"List books with custom pagination should succeed"
|
||||
);
|
||||
|
||||
let json: serde_json::Value = response.json();
|
||||
|
||||
assert_eq!(json["page"], 2, "Page should be 2");
|
||||
assert_eq!(json["per_page"], 5, "Per page should be 5");
|
||||
})
|
||||
.await;
|
||||
}
|
||||
|
||||
#[tokio::test]
|
||||
#[serial]
|
||||
async fn can_get_single_book() {
|
||||
request::<App, _, _>(|request, ctx| async move {
|
||||
// First create a test book
|
||||
let user = prepare_data::init_user_login(&request, &ctx).await;
|
||||
|
||||
let book_payload = serde_json::json!({
|
||||
"title": "Test Book",
|
||||
"author": "Test Author",
|
||||
"description": "A test book description",
|
||||
"content": "This is the content of the test book."
|
||||
});
|
||||
|
||||
let (auth_key, auth_value) = prepare_data::auth_header(&user.token);
|
||||
|
||||
let create_response = request
|
||||
.post("/api/books")
|
||||
.add_header(auth_key, auth_value.clone())
|
||||
.json(&book_payload)
|
||||
.await;
|
||||
|
||||
assert_eq!(
|
||||
create_response.status_code(),
|
||||
200,
|
||||
"Create book request should succeed"
|
||||
);
|
||||
|
||||
let created_book: serde_json::Value = create_response.json();
|
||||
let book_id = created_book["id"].as_i64().unwrap();
|
||||
|
||||
// Now get the book by ID
|
||||
let get_response = request.get(&format!("/api/books/{}", book_id)).await;
|
||||
|
||||
assert_eq!(
|
||||
get_response.status_code(),
|
||||
200,
|
||||
"Get single book request should succeed"
|
||||
);
|
||||
|
||||
let retrieved_book: serde_json::Value = get_response.json();
|
||||
|
||||
assert_eq!(retrieved_book["title"], "Test Book");
|
||||
assert_eq!(retrieved_book["author"], "Test Author");
|
||||
assert_eq!(retrieved_book["description"], "A test book description");
|
||||
})
|
||||
.await;
|
||||
}
|
||||
|
||||
#[tokio::test]
|
||||
#[serial]
|
||||
async fn can_create_book_with_auth() {
|
||||
request::<App, _, _>(|request, ctx| async move {
|
||||
let user = prepare_data::init_user_login(&request, &ctx).await;
|
||||
|
||||
let book_payload = serde_json::json!({
|
||||
"title": "Rust Programming",
|
||||
"author": "Steve Klabnik",
|
||||
"description": "Learn Rust programming",
|
||||
"content": "Rust is a systems programming language..."
|
||||
});
|
||||
|
||||
let (auth_key, auth_value) = prepare_data::auth_header(&user.token);
|
||||
|
||||
let response = request
|
||||
.post("/api/books")
|
||||
.add_header(auth_key, auth_value)
|
||||
.json(&book_payload)
|
||||
.await;
|
||||
|
||||
assert_eq!(
|
||||
response.status_code(),
|
||||
200,
|
||||
"Create book request should succeed with authentication"
|
||||
);
|
||||
|
||||
let json: serde_json::Value = response.json();
|
||||
|
||||
assert_eq!(json["title"], "Rust Programming");
|
||||
assert_eq!(json["author"], "Steve Klabnik");
|
||||
assert!(json.get("id").is_some(), "Created book should have an ID");
|
||||
})
|
||||
.await;
|
||||
}
|
||||
|
||||
#[tokio::test]
|
||||
#[serial]
|
||||
async fn cannot_create_book_without_auth() {
|
||||
request::<App, _, _>(|request, _ctx| async move {
|
||||
let book_payload = serde_json::json!({
|
||||
"title": "Unauthorized Book",
|
||||
"author": "No Auth",
|
||||
"content": "This should fail"
|
||||
});
|
||||
|
||||
let response = request
|
||||
.post("/api/books")
|
||||
.json(&book_payload)
|
||||
.await;
|
||||
|
||||
// Should return 401 Unauthorized or similar error
|
||||
assert_ne!(
|
||||
response.status_code(),
|
||||
200,
|
||||
"Create book should fail without authentication"
|
||||
);
|
||||
})
|
||||
.await;
|
||||
}
|
||||
Reference in New Issue
Block a user