Skip to content

Commit

Permalink
tests: add test subscribe_sends_a_confirmation_email_with_a_link
Browse files Browse the repository at this point in the history
  • Loading branch information
alexsavio committed Apr 3, 2024
1 parent 25a84fb commit 08dae16
Show file tree
Hide file tree
Showing 4 changed files with 64 additions and 1 deletion.
10 changes: 10 additions & 0 deletions Cargo.lock

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

1 change: 1 addition & 0 deletions Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -54,3 +54,4 @@ quickcheck_macros = "1.0.0"
rand = "0.8.5"
wiremock = "0.6.0"
serde_json = "1.0.115"
linkify = "0.10.0"
30 changes: 30 additions & 0 deletions tests/api/helpers.rs
Original file line number Diff line number Diff line change
Expand Up @@ -13,6 +13,12 @@ pub struct TestApp {
pub email_server: MockServer,
}

/// Confirmation links embedded in the request to the email API.
pub struct ConfirmationLinks {
pub html: reqwest::Url,
pub plain_text: reqwest::Url,
}

impl TestApp {
pub async fn post_subscriptions(&self, body: String) -> reqwest::Response {
reqwest::Client::new()
Expand All @@ -23,6 +29,30 @@ impl TestApp {
.await
.expect("Failed to execute request.")
}

/// Extract the confirmation link embedded in the request to the email API.
pub fn get_confirmation_links(&self, email_request: &wiremock::Request) -> ConfirmationLinks {
let body: serde_json::Value = serde_json::from_slice(&email_request.body).unwrap();

// Extract the link from one of the request fields.
let get_link = |s: &str| {
let links: Vec<_> = linkify::LinkFinder::new()
.links(s)
.filter(|l| *l.kind() == linkify::LinkKind::Url)
.collect();
assert_eq!(links.len(), 1);
let raw_link = links[0].as_str().to_owned();
let mut confirmation_link = reqwest::Url::parse(&raw_link).unwrap();
// Let's make sure we don't call random APIs on the web
assert_eq!(confirmation_link.host_str().unwrap(), "127.0.0.1");
confirmation_link.set_port(Some(8000)).unwrap();
confirmation_link
};

let html = get_link(body["HtmlBody"].as_str().unwrap());
let plain_text = get_link(body["TextBody"].as_str().unwrap());
ConfirmationLinks { html, plain_text }
}
}

static TRACING: Lazy<()> = Lazy::new(|| {
Expand Down
24 changes: 23 additions & 1 deletion tests/api/subscriptions.rs
Original file line number Diff line number Diff line change
Expand Up @@ -21,6 +21,29 @@ async fn subscribe_returns_a_200_for_valid_form_data() {
assert_eq!(200, response.status().as_u16());
}

#[tokio::test]
async fn subscribe_sends_a_confirmation_email_with_a_link() {
// Arrange
let app = spawn_app().await;
let body = "name=le%20guin&email=ursula_le_guin%40gmail.com";

Mock::given(path("/email"))
.and(method("POST"))
.respond_with(ResponseTemplate::new(200))
.mount(&app.email_server)
.await;

// Act
app.post_subscriptions(body.into()).await;

// Assert
let email_request = &app.email_server.received_requests().await.unwrap()[0];
let confirmation_links = app.get_confirmation_links(email_request);

// The two links should be identical
assert_eq!(confirmation_links.html, confirmation_links.plain_text);
}

#[tokio::test]
async fn subscribe_persists_the_new_subscriber() {
// Arrange
Expand Down Expand Up @@ -84,7 +107,6 @@ async fn subscribe_returns_a_400_when_data_is_missing() {
}
}


#[tokio::test]
async fn subscribe_returns_a_400_when_fields_are_present_but_invalid() {
// Arrange
Expand Down

0 comments on commit 08dae16

Please sign in to comment.