Test suite refactoring to match new htmx HTML swapping in pages
This commit is contained in:
@@ -21,14 +21,12 @@ async fn logout_clears_session_state() {
|
||||
assert_is_redirect_to(&response, "/admin/dashboard");
|
||||
|
||||
let html_page = app.get_admin_dashboard_html().await;
|
||||
assert!(html_page.contains(&format!("Welcome {}", app.test_user.username)));
|
||||
assert!(html_page.contains("Connected as"));
|
||||
assert!(html_page.contains(&app.test_user.username));
|
||||
|
||||
let response = app.post_logout().await;
|
||||
assert_is_redirect_to(&response, "/login");
|
||||
|
||||
let html_page = app.get_login_html().await;
|
||||
assert!(html_page.contains("You have successfully logged out"));
|
||||
|
||||
let response = app.get_admin_dashboard().await;
|
||||
assert_is_redirect_to(&response, "/login");
|
||||
}
|
||||
|
||||
@@ -1,15 +1,5 @@
|
||||
use uuid::Uuid;
|
||||
|
||||
use crate::helpers::{TestApp, assert_is_redirect_to};
|
||||
|
||||
#[tokio::test]
|
||||
async fn you_must_be_logged_in_to_see_the_change_password_form() {
|
||||
let app = TestApp::spawn().await;
|
||||
|
||||
let response = app.get_change_password().await;
|
||||
|
||||
assert_is_redirect_to(&response, "/login");
|
||||
}
|
||||
use uuid::Uuid;
|
||||
|
||||
#[tokio::test]
|
||||
async fn you_must_be_logged_in_to_change_your_password() {
|
||||
@@ -46,10 +36,10 @@ async fn new_password_fields_must_match() {
|
||||
"new_password_check": another_new_password,
|
||||
}))
|
||||
.await;
|
||||
assert_is_redirect_to(&response, "/admin/password");
|
||||
assert!(response.status().is_success());
|
||||
|
||||
let html_page = app.get_change_password_html().await;
|
||||
assert!(html_page.contains("You entered two different passwords"));
|
||||
let html_fragment = response.text().await.unwrap();
|
||||
assert!(html_fragment.contains("You entered two different passwords"));
|
||||
}
|
||||
|
||||
#[tokio::test]
|
||||
@@ -70,10 +60,10 @@ async fn current_password_is_invalid() {
|
||||
"new_password_check": new_password,
|
||||
}))
|
||||
.await;
|
||||
assert_is_redirect_to(&response, "/admin/password");
|
||||
assert!(response.status().is_success());
|
||||
|
||||
let html_page = app.get_change_password_html().await;
|
||||
assert!(html_page.contains("The current password is incorrect"));
|
||||
let html_fragment = response.text().await.unwrap();
|
||||
assert!(html_fragment.contains("The current password is incorrect"));
|
||||
}
|
||||
|
||||
#[tokio::test]
|
||||
@@ -95,17 +85,14 @@ async fn changing_password_works() {
|
||||
"new_password_check": new_password,
|
||||
}))
|
||||
.await;
|
||||
assert_is_redirect_to(&response, "/admin/password");
|
||||
assert!(response.status().is_success());
|
||||
|
||||
let html_page = app.get_change_password_html().await;
|
||||
assert!(html_page.contains("Your password has been changed"));
|
||||
let html_page_fragment = response.text().await.unwrap();
|
||||
assert!(html_page_fragment.contains("Your password has been changed"));
|
||||
|
||||
let response = app.post_logout().await;
|
||||
assert_is_redirect_to(&response, "/login");
|
||||
|
||||
let html_page = app.get_login_html().await;
|
||||
assert!(html_page.contains("You have successfully logged out"));
|
||||
|
||||
let login_body = &serde_json::json!({
|
||||
"username": app.test_user.username,
|
||||
"password": new_password,
|
||||
|
||||
@@ -6,7 +6,10 @@ use linkify::LinkFinder;
|
||||
use once_cell::sync::Lazy;
|
||||
use sqlx::{Connection, Executor, PgConnection, PgPool};
|
||||
use uuid::Uuid;
|
||||
use wiremock::MockServer;
|
||||
use wiremock::{
|
||||
Mock, MockBuilder, MockServer,
|
||||
matchers::{method, path},
|
||||
};
|
||||
use zero2prod::{
|
||||
configuration::{DatabaseSettings, get_configuration},
|
||||
email_client::EmailClient,
|
||||
@@ -149,17 +152,6 @@ impl TestApp {
|
||||
ConfirmationLinks { html, text }
|
||||
}
|
||||
|
||||
pub async fn get_login_html(&self) -> String {
|
||||
self.api_client
|
||||
.get(format!("{}/login", &self.address))
|
||||
.send()
|
||||
.await
|
||||
.expect("Failed to execute request")
|
||||
.text()
|
||||
.await
|
||||
.unwrap()
|
||||
}
|
||||
|
||||
pub async fn get_admin_dashboard(&self) -> reqwest::Response {
|
||||
self.api_client
|
||||
.get(format!("{}/admin/dashboard", &self.address))
|
||||
@@ -172,29 +164,6 @@ impl TestApp {
|
||||
self.get_admin_dashboard().await.text().await.unwrap()
|
||||
}
|
||||
|
||||
pub async fn get_register_html(&self) -> String {
|
||||
self.api_client
|
||||
.get(format!("{}/register", &self.address))
|
||||
.send()
|
||||
.await
|
||||
.expect("Failed to execute request")
|
||||
.text()
|
||||
.await
|
||||
.unwrap()
|
||||
}
|
||||
|
||||
pub async fn get_change_password(&self) -> reqwest::Response {
|
||||
self.api_client
|
||||
.get(format!("{}/admin/password", &self.address))
|
||||
.send()
|
||||
.await
|
||||
.expect("Failed to execute request")
|
||||
}
|
||||
|
||||
pub async fn get_change_password_html(&self) -> String {
|
||||
self.get_change_password().await.text().await.unwrap()
|
||||
}
|
||||
|
||||
pub async fn post_subscriptions(&self, body: String) -> reqwest::Response {
|
||||
self.api_client
|
||||
.post(format!("{}/subscriptions", self.address))
|
||||
@@ -205,18 +174,6 @@ impl TestApp {
|
||||
.expect("Failed to execute request")
|
||||
}
|
||||
|
||||
pub async fn get_newsletter_form(&self) -> reqwest::Response {
|
||||
self.api_client
|
||||
.get(format!("{}/admin/password", &self.address))
|
||||
.send()
|
||||
.await
|
||||
.expect("Failed to execute request")
|
||||
}
|
||||
|
||||
pub async fn get_newsletter_form_html(&self) -> String {
|
||||
self.get_newsletter_form().await.text().await.unwrap()
|
||||
}
|
||||
|
||||
pub async fn post_newsletters<Body>(&self, body: &Body) -> reqwest::Response
|
||||
where
|
||||
Body: serde::Serialize,
|
||||
@@ -291,6 +248,11 @@ async fn configure_database(config: &DatabaseSettings) -> PgPool {
|
||||
}
|
||||
|
||||
pub fn assert_is_redirect_to(response: &reqwest::Response, location: &str) {
|
||||
assert_eq!(response.status().as_u16(), 303);
|
||||
assert_eq!(response.headers().get("Location").unwrap(), location);
|
||||
dbg!(&response);
|
||||
assert_eq!(response.status().as_u16(), 200);
|
||||
assert_eq!(response.headers().get("hx-redirect").unwrap(), location);
|
||||
}
|
||||
|
||||
pub fn when_sending_an_email() -> MockBuilder {
|
||||
Mock::given(path("/email")).and(method("POST"))
|
||||
}
|
||||
|
||||
@@ -1,14 +1,8 @@
|
||||
use crate::helpers::{ConfirmationLinks, TestApp, assert_is_redirect_to};
|
||||
use fake::{
|
||||
Fake,
|
||||
faker::{internet::en::SafeEmail, name::fr_fr::Name},
|
||||
};
|
||||
use crate::helpers::{ConfirmationLinks, TestApp, assert_is_redirect_to, when_sending_an_email};
|
||||
use fake::{Fake, faker::internet::en::SafeEmail};
|
||||
use std::time::Duration;
|
||||
use uuid::Uuid;
|
||||
use wiremock::{
|
||||
Mock, MockBuilder, ResponseTemplate,
|
||||
matchers::{method, path},
|
||||
};
|
||||
use wiremock::ResponseTemplate;
|
||||
|
||||
#[tokio::test]
|
||||
async fn newsletters_are_not_delivered_to_unconfirmed_subscribers() {
|
||||
@@ -72,11 +66,11 @@ async fn newsletters_are_delivered_to_confirmed_subscribers() {
|
||||
});
|
||||
|
||||
let response = app.post_newsletters(&newsletter_request_body).await;
|
||||
assert_is_redirect_to(&response, "/admin/newsletters");
|
||||
assert!(response.status().is_success());
|
||||
|
||||
let html_page = app.get_newsletter_form_html().await;
|
||||
assert!(html_page.contains(&format!(
|
||||
"The newsletter issue '{}' has been published",
|
||||
let html_fragment = response.text().await.unwrap();
|
||||
assert!(html_fragment.contains(&format!(
|
||||
r#"The newsletter issue "{}" has been published"#,
|
||||
newsletter_title
|
||||
)));
|
||||
|
||||
@@ -116,9 +110,13 @@ async fn form_shows_error_for_invalid_data() {
|
||||
];
|
||||
|
||||
for (invalid_body, error_message) in test_cases {
|
||||
app.post_newsletters(&invalid_body).await;
|
||||
let html_page = app.get_newsletter_form_html().await;
|
||||
assert!(html_page.contains(error_message));
|
||||
let html_fragment = app
|
||||
.post_newsletters(&invalid_body)
|
||||
.await
|
||||
.text()
|
||||
.await
|
||||
.unwrap();
|
||||
assert!(html_fragment.contains(error_message));
|
||||
}
|
||||
}
|
||||
|
||||
@@ -143,20 +141,20 @@ async fn newsletter_creation_is_idempotent() {
|
||||
});
|
||||
|
||||
let response = app.post_newsletters(&newsletter_request_body).await;
|
||||
assert_is_redirect_to(&response, "/admin/newsletters");
|
||||
assert!(response.status().is_success());
|
||||
|
||||
let html_page = app.get_newsletter_form_html().await;
|
||||
assert!(html_page.contains(&format!(
|
||||
"The newsletter issue '{}' has been published",
|
||||
let html_fragment = response.text().await.unwrap();
|
||||
assert!(html_fragment.contains(&format!(
|
||||
r#"The newsletter issue "{}" has been published"#,
|
||||
newsletter_title
|
||||
)));
|
||||
|
||||
let response = app.post_newsletters(&newsletter_request_body).await;
|
||||
assert_is_redirect_to(&response, "/admin/newsletters");
|
||||
assert!(response.status().is_success());
|
||||
|
||||
let html_page = app.get_newsletter_form_html().await;
|
||||
assert!(html_page.contains(&format!(
|
||||
"The newsletter issue '{}' has been published",
|
||||
let html_fragment = response.text().await.unwrap();
|
||||
assert!(html_fragment.contains(&format!(
|
||||
r#"The newsletter issue "{}" has been published"#,
|
||||
newsletter_title
|
||||
)));
|
||||
|
||||
@@ -195,22 +193,16 @@ async fn concurrent_form_submission_is_handled_gracefully() {
|
||||
}
|
||||
|
||||
async fn create_unconfirmed_subscriber(app: &TestApp) -> ConfirmationLinks {
|
||||
let name: String = Name().fake();
|
||||
let email: String = SafeEmail().fake();
|
||||
let body = serde_urlencoded::to_string(serde_json::json!({
|
||||
"name": name,
|
||||
"email": email,
|
||||
"email_check": email
|
||||
}))
|
||||
.unwrap();
|
||||
let body = format!("email={email}");
|
||||
|
||||
let _mock_guard = Mock::given(path("/v1/email"))
|
||||
.and(method("POST"))
|
||||
let _mock_guard = when_sending_an_email()
|
||||
.respond_with(ResponseTemplate::new(200))
|
||||
.named("Create unconfirmed subscriber")
|
||||
.expect(1)
|
||||
.mount_as_scoped(&app.email_server)
|
||||
.await;
|
||||
|
||||
app.post_subscriptions(body)
|
||||
.await
|
||||
.error_for_status()
|
||||
@@ -223,6 +215,7 @@ async fn create_unconfirmed_subscriber(app: &TestApp) -> ConfirmationLinks {
|
||||
.unwrap()
|
||||
.pop()
|
||||
.unwrap();
|
||||
|
||||
app.get_confirmation_links(email_request)
|
||||
}
|
||||
|
||||
@@ -234,7 +227,3 @@ async fn create_confirmed_subscriber(app: &TestApp) {
|
||||
.error_for_status()
|
||||
.unwrap();
|
||||
}
|
||||
|
||||
fn when_sending_an_email() -> MockBuilder {
|
||||
Mock::given(path("/v1/email")).and(method("POST"))
|
||||
}
|
||||
|
||||
@@ -1,34 +1,11 @@
|
||||
use crate::helpers::{TestApp, assert_is_redirect_to};
|
||||
use wiremock::{
|
||||
Mock, ResponseTemplate,
|
||||
matchers::{method, path},
|
||||
};
|
||||
use crate::helpers::{TestApp, when_sending_an_email};
|
||||
use wiremock::ResponseTemplate;
|
||||
|
||||
#[tokio::test]
|
||||
async fn subscribe_displays_a_confirmation_message_for_valid_form_data() {
|
||||
let app = TestApp::spawn().await;
|
||||
|
||||
Mock::given(path("/v1/email"))
|
||||
.and(method("POST"))
|
||||
.respond_with(ResponseTemplate::new(200))
|
||||
.mount(&app.email_server)
|
||||
.await;
|
||||
|
||||
let email = "alphonse.paix@outlook.com";
|
||||
let body = format!("name=Alphonse&email={0}&email_check={0}", email);
|
||||
let response = app.post_subscriptions(body).await;
|
||||
|
||||
assert_is_redirect_to(&response, "/register");
|
||||
let page_html = app.get_register_html().await;
|
||||
assert!(page_html.contains("A confirmation email has been sent"));
|
||||
}
|
||||
|
||||
#[tokio::test]
|
||||
async fn subscribe_persists_the_new_subscriber() {
|
||||
let app = TestApp::spawn().await;
|
||||
|
||||
Mock::given(path("/v1/email"))
|
||||
.and(method("POST"))
|
||||
when_sending_an_email()
|
||||
.respond_with(ResponseTemplate::new(200))
|
||||
.mount(&app.email_server)
|
||||
.await;
|
||||
@@ -37,9 +14,27 @@ async fn subscribe_persists_the_new_subscriber() {
|
||||
let body = format!("email={email}");
|
||||
let response = app.post_subscriptions(body).await;
|
||||
|
||||
assert_is_redirect_to(&response, "/register");
|
||||
let page_html = app.get_register_html().await;
|
||||
assert!(page_html.contains("A confirmation email has been sent"));
|
||||
assert!(response.status().is_success());
|
||||
let html_fragment = response.text().await.unwrap();
|
||||
assert!(html_fragment.contains("A confirmation email has been sent"));
|
||||
}
|
||||
|
||||
#[tokio::test]
|
||||
async fn subscribe_persists_the_new_subscriber() {
|
||||
let app = TestApp::spawn().await;
|
||||
|
||||
when_sending_an_email()
|
||||
.respond_with(ResponseTemplate::new(200))
|
||||
.mount(&app.email_server)
|
||||
.await;
|
||||
|
||||
let email = "alphonse.paix@outlook.com";
|
||||
let body = format!("email={email}");
|
||||
let response = app.post_subscriptions(body).await;
|
||||
|
||||
assert!(response.status().is_success());
|
||||
let html_fragment = response.text().await.unwrap();
|
||||
assert!(html_fragment.contains("A confirmation email has been sent"));
|
||||
|
||||
let saved = sqlx::query!("SELECT email, status FROM subscriptions")
|
||||
.fetch_one(&app.connection_pool)
|
||||
@@ -100,10 +95,9 @@ async fn subscribe_sends_a_confirmation_email_for_valid_data() {
|
||||
let app = TestApp::spawn().await;
|
||||
|
||||
let email = "alphonse.paix@outlook.com";
|
||||
let body = format!("name=Alphonse&email={0}&email_check={0}", email);
|
||||
let body = format!("email={email}");
|
||||
|
||||
Mock::given(path("v1/email"))
|
||||
.and(method("POST"))
|
||||
when_sending_an_email()
|
||||
.respond_with(ResponseTemplate::new(200))
|
||||
.expect(1)
|
||||
.mount(&app.email_server)
|
||||
@@ -117,10 +111,9 @@ async fn subscribe_sends_a_confirmation_email_with_a_link() {
|
||||
let app = TestApp::spawn().await;
|
||||
|
||||
let email = "alphonse.paix@outlook.com";
|
||||
let body = format!("name=Alphonse&email={0}&email_check={0}", email);
|
||||
let body = format!("email={email}");
|
||||
|
||||
Mock::given(path("v1/email"))
|
||||
.and(method("POST"))
|
||||
when_sending_an_email()
|
||||
.respond_with(ResponseTemplate::new(200))
|
||||
.expect(1)
|
||||
.mount(&app.email_server)
|
||||
|
||||
@@ -1,8 +1,5 @@
|
||||
use crate::helpers::TestApp;
|
||||
use wiremock::{
|
||||
Mock, ResponseTemplate,
|
||||
matchers::{method, path},
|
||||
};
|
||||
use crate::helpers::{TestApp, when_sending_an_email};
|
||||
use wiremock::ResponseTemplate;
|
||||
|
||||
#[tokio::test]
|
||||
async fn confirmation_links_without_token_are_rejected_with_a_400() {
|
||||
@@ -15,14 +12,13 @@ async fn confirmation_links_without_token_are_rejected_with_a_400() {
|
||||
}
|
||||
|
||||
#[tokio::test]
|
||||
async fn clicking_on_the_link_shows_a_confiramtion_message() {
|
||||
async fn clicking_on_the_link_shows_a_confirmation_message() {
|
||||
let app = TestApp::spawn().await;
|
||||
|
||||
let email = "alphonse.paix@outlook.com";
|
||||
let body = format!("name=Alphonse&email={email}&email_check={email}");
|
||||
let body = format!("email={email}");
|
||||
|
||||
Mock::given(path("v1/email"))
|
||||
.and(method("POST"))
|
||||
when_sending_an_email()
|
||||
.respond_with(ResponseTemplate::new(200))
|
||||
.expect(1)
|
||||
.mount(&app.email_server)
|
||||
@@ -39,7 +35,7 @@ async fn clicking_on_the_link_shows_a_confiramtion_message() {
|
||||
.text()
|
||||
.await
|
||||
.unwrap()
|
||||
.contains("Your account has been confirmed")
|
||||
.contains("Subscription confirmed")
|
||||
);
|
||||
}
|
||||
|
||||
@@ -50,8 +46,7 @@ async fn clicking_on_the_confirmation_link_confirms_a_subscriber() {
|
||||
let email = "alphonse.paix@outlook.com";
|
||||
let body = format!("email={email}");
|
||||
|
||||
Mock::given(path("v1/email"))
|
||||
.and(method("POST"))
|
||||
when_sending_an_email()
|
||||
.respond_with(ResponseTemplate::new(200))
|
||||
.expect(1)
|
||||
.mount(&app.email_server)
|
||||
|
||||
Reference in New Issue
Block a user