use crate::helpers::{TestApp, fake_post_body}; use sqlx::PgPool; #[sqlx::test] async fn visitor_can_leave_a_comment(connection_pool: PgPool) { let app = TestApp::spawn(connection_pool).await; app.admin_login().await; app.post_create_post(&fake_post_body()).await; let post_id = { let record = sqlx::query!("SELECT post_id FROM posts") .fetch_one(&app.connection_pool) .await .unwrap(); record.post_id }; let comment_author = "Author"; let comment_content = "Content"; let comment_body = serde_json::json!({ "author": comment_author, "content": comment_content, "idempotency_key": "key", }); app.post_comment(&post_id, &comment_body).await; let post = app.get_post_html(&post_id).await; assert!(post.contains(comment_author)); assert!(post.contains(comment_content)); } #[sqlx::test] async fn visitor_can_comment_anonymously(connection_pool: PgPool) { let app = TestApp::spawn(connection_pool).await; app.admin_login().await; app.post_create_post(&fake_post_body()).await; let post_id = { let record = sqlx::query!("SELECT post_id FROM posts") .fetch_one(&app.connection_pool) .await .unwrap(); record.post_id }; let comment_content = "Content"; let comment_body = serde_json::json!({ "content": comment_content, "idempotency_key": "key", }); app.post_comment(&post_id, &comment_body).await; let post = app.get_post_html(&post_id).await; assert!(post.contains("Anonymous")); assert!(post.contains(comment_content)); } #[sqlx::test] async fn comment_with_invalid_body_is_rejected(connection_pool: PgPool) { let app = TestApp::spawn(connection_pool).await; app.admin_login().await; app.post_create_post(&fake_post_body()).await; let post_id = { let record = sqlx::query!("SELECT post_id FROM posts") .fetch_one(&app.connection_pool) .await .unwrap(); record.post_id }; let test_cases = [ ( serde_json::json!({ "idempotency_key": "key" }), "a missing content", ), ( serde_json::json!({ "idempotency_key": "key", "content": "" }), "an empty content", ), ]; for (invalid_body, message) in test_cases { let response = app.post_comment(&post_id, &invalid_body).await; let html = response.text().await.unwrap(); dbg!(&html); assert!( !html.contains("Your comment has been posted"), "The API did not reject the request when the body had {}", message ); } } #[sqlx::test] async fn comment_is_deleted_when_post_is_deleted(connection_pool: PgPool) { let app = TestApp::spawn(connection_pool).await; app.admin_login().await; app.post_create_post(&fake_post_body()).await; let post_id = { let record = sqlx::query!("SELECT post_id FROM posts") .fetch_one(&app.connection_pool) .await .unwrap(); record.post_id }; let comment_author = "Author"; let comment_content = "Content"; let comment_body = serde_json::json!({ "author": comment_author, "content": comment_content, "idempotency_key": "key", }); app.post_comment(&post_id, &comment_body).await; let comment_id = { let record = sqlx::query!("SELECT comment_id FROM comments") .fetch_one(&app.connection_pool) .await .unwrap(); record.comment_id }; app.delete_post(post_id).await; let record = sqlx::query!("SELECT * FROM comments WHERE comment_id = $1", comment_id) .fetch_optional(&app.connection_pool) .await .unwrap(); assert!(record.is_none()); } #[sqlx::test] async fn comment_posting_is_idempotent(connection_pool: PgPool) { let app = TestApp::spawn(connection_pool).await; app.admin_login().await; app.post_create_post(&fake_post_body()).await; let post_id = { let record = sqlx::query!("SELECT post_id FROM posts") .fetch_one(&app.connection_pool) .await .unwrap(); record.post_id }; let comment_body = serde_json::json!({ "author": "author", "content": "content", "idempotency_key": "key", }); let response = app.post_comment(&post_id, &comment_body).await; assert!( response .text() .await .unwrap() .contains("Your comment has been posted") ); let response = app.post_comment(&post_id, &comment_body).await; assert!( response .text() .await .unwrap() .contains("Your comment has been posted") ); let count = sqlx::query_scalar!("SELECT count(*) FROM comments") .fetch_one(&app.connection_pool) .await .unwrap() .unwrap_or(0); assert_eq!(count, 1); }