use crate::helpers::{TestApp, assert_is_redirect_to, when_sending_an_email}; use sqlx::PgPool; use std::time::Duration; use uuid::Uuid; use wiremock::ResponseTemplate; #[sqlx::test] async fn newsletters_are_not_delivered_to_unconfirmed_subscribers(connection_pool: PgPool) { let app = TestApp::spawn(connection_pool).await; app.create_unconfirmed_subscriber().await; app.admin_login().await; when_sending_an_email() .respond_with(ResponseTemplate::new(200)) .expect(0) .mount(&app.email_server) .await; let newsletter_request_body = serde_json::json!({ "title": "Newsletter title", "text": "Newsletter body as plain text", "html": "
Newsletter body as HTML
" }); app.post_newsletters(&newsletter_request_body).await; app.dispatch_all_pending_emails().await; } #[sqlx::test] async fn requests_without_authentication_are_redirected(connection_pool: PgPool) { let app = TestApp::spawn(connection_pool).await; when_sending_an_email() .respond_with(ResponseTemplate::new(200)) .expect(0) .mount(&app.email_server) .await; let newsletter_request_body = serde_json::json!({ "title": "Newsletter title", "text": "Newsletter body as plain text", "html": "Newsletter body as HTML
" }); let response = app.post_newsletters(&newsletter_request_body).await; assert_is_redirect_to(&response, "/login"); } #[sqlx::test] async fn newsletters_are_delivered_to_confirmed_subscribers(connection_pool: PgPool) { let app = TestApp::spawn(connection_pool).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 newsletter_title = "Newsletter title"; let newsletter_request_body = serde_json::json!({ "title": newsletter_title, "text": "Newsletter body as plain text", "html": "Newsletter body as HTML
", "idempotency_key": Uuid::new_v4().to_string(), }); let response = app.post_newsletters(&newsletter_request_body).await; assert!(response.status().is_success()); let html_fragment = response.text().await.unwrap(); assert!(html_fragment.contains("Your email has been queued for delivery")); app.dispatch_all_pending_emails().await; } #[sqlx::test] async fn form_shows_error_for_invalid_data(connection_pool: PgPool) { let app = TestApp::spawn(connection_pool).await; app.admin_login().await; when_sending_an_email() .respond_with(ResponseTemplate::new(200)) .expect(0) .mount(&app.email_server) .await; let test_cases = [ ( serde_json::json!({ "title": "", "text": "Newsletter body as plain text", "html": "Newsletter body as HTML
", "idempotency_key": Uuid::new_v4().to_string(), }), "The title was empty", ), ( serde_json::json!({ "title": "Newsletter", "text": "", "html": "", "idempotency_key": Uuid::new_v4().to_string(), }), "The content was empty", ), ]; for (invalid_body, error_message) in test_cases { let html_fragment = app .post_newsletters(&invalid_body) .await .text() .await .unwrap(); assert!(html_fragment.contains(error_message)); } } #[sqlx::test] async fn newsletter_creation_is_idempotent(connection_pool: PgPool) { let app = TestApp::spawn(connection_pool).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 newsletter_title = "Newsletter title"; let newsletter_request_body = serde_json::json!({ "title": newsletter_title, "text": "Newsletter body as plain text", "html": "Newsletter body as HTML
", "idempotency_key": Uuid::new_v4().to_string(), }); let response = app.post_newsletters(&newsletter_request_body).await; assert!(response.status().is_success()); let html_fragment = response.text().await.unwrap(); assert!(html_fragment.contains("Your email has been queued for delivery")); let response = app.post_newsletters(&newsletter_request_body).await; assert!(response.status().is_success()); let html_fragment = response.text().await.unwrap(); assert!(html_fragment.contains("Your email has been queued for delivery")); app.dispatch_all_pending_emails().await; } #[sqlx::test] async fn concurrent_form_submission_is_handled_gracefully(connection_pool: PgPool) { let app = TestApp::spawn(connection_pool).await; app.create_confirmed_subscriber().await; app.admin_login().await; when_sending_an_email() .respond_with(ResponseTemplate::new(200).set_delay(Duration::from_secs(2))) .expect(1) .mount(&app.email_server) .await; let newsletter_request_body = serde_json::json!({ "title": "Newsletter title", "text": "Newsletter body as plain text", "html": "Newsletter body as HTML
", "idempotency_key": Uuid::new_v4().to_string(), }); let response1 = app.post_newsletters(&newsletter_request_body); let response2 = app.post_newsletters(&newsletter_request_body); let (response1, response2) = tokio::join!(response1, response2); assert_eq!(response1.status(), response2.status()); assert_eq!( response1.text().await.unwrap(), response2.text().await.unwrap(), ); app.dispatch_all_pending_emails().await; }