use crate::helpers::{TestApp, assert_is_redirect_to, when_sending_an_email}; use fake::{ Fake, faker::lorem::en::{Paragraph, Sentence}, }; use sqlx::PgPool; use uuid::Uuid; use wiremock::ResponseTemplate; fn subject() -> String { Sentence(1..2).fake() } fn content() -> String { Paragraph(1..10).fake() } #[sqlx::test] async fn you_must_be_logged_in_to_create_a_new_post(connection_pool: PgPool) { let app = TestApp::spawn(connection_pool).await; let title = subject(); let content = content(); let body = serde_json::json!({ "title": title, "content": content, }); let response = app.post_create_post(&body).await; assert_is_redirect_to(&response, "/login"); } #[sqlx::test] async fn new_posts_are_stored_in_the_database(connection_pool: PgPool) { let app = TestApp::spawn(connection_pool).await; app.admin_login().await; let title = subject(); let content = content(); let body = serde_json::json!({ "title": title, "content": content, "idempotency_key": Uuid::new_v4(), }); let response = app.post_create_post(&body).await; assert!(response.status().is_success()); let html_fragment = response.text().await.unwrap(); assert!(html_fragment.contains("Your new post has been published")); let saved = sqlx::query!("SELECT title, content FROM posts") .fetch_one(&app.connection_pool) .await .expect("Failed to fetch saved post"); assert_eq!(saved.title, title); assert_eq!(saved.content, content); } #[sqlx::test] async fn confirmed_subscribers_are_notified_when_a_new_post_is_published(connection_pool: PgPool) { let app = TestApp::spawn(connection_pool).await; app.create_unconfirmed_subscriber().await; app.create_confirmed_subscriber().await; app.admin_login().await; when_sending_an_email() .respond_with(ResponseTemplate::new(200)) .expect(1) .mount(&app.email_server) .await; let title = subject(); let content = content(); let body = serde_json::json!({ "title": title, "content": content, "idempotency_key": Uuid::new_v4(), }); app.post_create_post(&body).await; app.dispatch_all_pending_emails().await; } #[sqlx::test] async fn new_posts_are_visible_on_the_website(connection_pool: PgPool) { let app = TestApp::spawn(connection_pool).await; let html = app.get_posts_html().await; assert!(html.contains("No posts yet")); let title = subject(); let content = content(); let body = serde_json::json!({ "title": title, "content": content, "idempotency_key": Uuid::new_v4(), }); app.admin_login().await; app.post_create_post(&body).await; app.logout().await; let html = app.get_posts_html().await; assert!(html.contains(&title)); let post = sqlx::query!("SELECT post_id FROM posts") .fetch_one(&app.connection_pool) .await .unwrap(); let html = app.get_post_html(post.post_id).await; assert!(html.contains(&title)); } #[sqlx::test] async fn visitor_can_read_a_blog_post(connection_pool: PgPool) { let app = TestApp::spawn(connection_pool).await; let title = subject(); let content = content(); let body = serde_json::json!({ "title": title, "content": content, "idempotency_key": Uuid::new_v4(), }); app.admin_login().await; app.post_create_post(&body).await; app.logout().await; let html = app.get_posts_html().await; assert!(html.contains(&title)); let post = sqlx::query!("SELECT post_id FROM posts") .fetch_one(&app.connection_pool) .await .unwrap(); let html = app.get_post_html(post.post_id).await; assert!(html.contains(&title)); } #[sqlx::test] async fn a_deleted_blog_post_returns_404(connection_pool: PgPool) { let app = TestApp::spawn(connection_pool).await; app.admin_login().await; let title = subject(); let content = content(); let body = serde_json::json!({ "title": title, "content": content, "idempotency_key": Uuid::new_v4(), }); app.post_create_post(&body).await; let post = sqlx::query!("SELECT post_id FROM posts") .fetch_one(&app.connection_pool) .await .unwrap(); app.delete_post(post.post_id).await; let html = app.get_post_html(post.post_id).await; assert!(html.contains("Not Found")); }