Skip to content

Commit

Permalink
Migrated tests in email_client to tests dir
Browse files Browse the repository at this point in the history
  • Loading branch information
whompratt committed Oct 20, 2024
1 parent 892c78c commit 4f52238
Show file tree
Hide file tree
Showing 2 changed files with 134 additions and 138 deletions.
138 changes: 0 additions & 138 deletions src/email_client.rs
Original file line number Diff line number Diff line change
Expand Up @@ -64,141 +64,3 @@ struct SendEmailRequest<'a> {
html_body: &'a str,
text_body: &'a str,
}

#[cfg(test)]
mod tests {
use crate::domain::UserEmail;
use crate::email_client::EmailClient;
use claims::{assert_err, assert_ok};
use fake::faker::internet::en::SafeEmail;
use fake::faker::lorem::en::{Paragraph, Sentence};
use fake::{Fake, Faker};
use secrecy::SecretString;
use wiremock::matchers::{any, header, header_exists, method, path};
use wiremock::Request;
use wiremock::{Mock, MockServer, ResponseTemplate};
struct SendEmailBodyMatcher;

fn subject() -> String {
Sentence(1..2).fake()
}

fn content() -> String {
Paragraph(1..10).fake()
}

fn email() -> UserEmail {
UserEmail::parse(SafeEmail().fake()).unwrap()
}

fn email_client(base_url: String) -> EmailClient {
EmailClient::new(
base_url,
email(),
SecretString::new(Faker.fake::<String>().into()),
std::time::Duration::from_millis(200),
)
}

impl wiremock::Match for SendEmailBodyMatcher {
fn matches(&self, request: &Request) -> bool {
let result: Result<serde_json::Value, _> = serde_json::from_slice(&request.body);
if let Ok(body) = result {
dbg!(&body);
body.get("From").is_some()
&& body.get("To").is_some()
&& body.get("Subject").is_some()
&& body.get("HtmlBody").is_some()
&& body.get("TextBody").is_some()
} else {
false
}
}
}

#[tokio::test]
async fn send_email_sends_the_expected_request() {
// Arrange
let mock_server = MockServer::start().await;
let email_client = email_client(mock_server.uri());

Mock::given(header_exists("X-Postmark-Server-Token"))
.and(header("Content-Type", "application/json"))
.and(path("/email"))
.and(method("POST"))
.and(SendEmailBodyMatcher)
.respond_with(ResponseTemplate::new(200))
.expect(1)
.mount(&mock_server)
.await;

// Act
let _ = email_client
.send_email(&email(), &subject(), &content(), &content())
.await;
}

#[tokio::test]
async fn send_email_succeeds_if_the_server_returns_200() {
// Arrange
let mock_server = MockServer::start().await;
let email_client = email_client(mock_server.uri());

Mock::given(any())
.respond_with(ResponseTemplate::new(200))
.expect(1)
.mount(&mock_server)
.await;

// Act
let outcome = email_client
.send_email(&email(), &subject(), &content(), &content())
.await;

// Assert
assert_ok!(outcome);
}

#[tokio::test]
async fn send_email_fails_if_the_server_returns_500() {
// Arrange
let mock_server = MockServer::start().await;
let email_client = email_client(mock_server.uri());

Mock::given(any())
.respond_with(ResponseTemplate::new(500))
.expect(1)
.mount(&mock_server)
.await;

// Act
let outcome = email_client
.send_email(&email(), &subject(), &content(), &content())
.await;

// Assert
assert_err!(outcome);
}

#[tokio::test]
async fn send_email_times_out_if_the_server_takes_too_long() {
// Arrange
let mock_server = MockServer::start().await;
let email_client = email_client(mock_server.uri());

let response = ResponseTemplate::new(200).set_delay(std::time::Duration::from_secs(180));
Mock::given(any())
.respond_with(response)
.expect(1)
.mount(&mock_server)
.await;

// Act
let outcome = email_client
.send_email(&email(), &subject(), &content(), &content())
.await;

// Assert
assert_err!(outcome);
}
}
134 changes: 134 additions & 0 deletions tests/api/email_client.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,134 @@
use claans_api::domain::UserEmail;
use claans_api::email_client::EmailClient;
use claims::{assert_err, assert_ok};
use fake::faker::internet::en::SafeEmail;
use fake::faker::lorem::en::{Paragraph, Sentence};
use fake::{Fake, Faker};
use secrecy::SecretString;
use wiremock::matchers::{any, header, header_exists, method, path};
use wiremock::Request;
use wiremock::{Mock, MockServer, ResponseTemplate};
struct SendEmailBodyMatcher;

fn subject() -> String {
Sentence(1..2).fake()
}

fn content() -> String {
Paragraph(1..10).fake()
}

fn email() -> UserEmail {
UserEmail::parse(SafeEmail().fake()).unwrap()
}

fn email_client(base_url: String) -> EmailClient {
EmailClient::new(
base_url,
email(),
SecretString::new(Faker.fake::<String>().into()),
std::time::Duration::from_millis(200),
)
}

impl wiremock::Match for SendEmailBodyMatcher {
fn matches(&self, request: &Request) -> bool {
let result: Result<serde_json::Value, _> = serde_json::from_slice(&request.body);
if let Ok(body) = result {
dbg!(&body);
body.get("From").is_some()
&& body.get("To").is_some()
&& body.get("Subject").is_some()
&& body.get("HtmlBody").is_some()
&& body.get("TextBody").is_some()
} else {
false
}
}
}

#[tokio::test]
async fn send_email_sends_the_expected_request() {
// Arrange
let mock_server = MockServer::start().await;
let email_client = email_client(mock_server.uri());

Mock::given(header_exists("X-Postmark-Server-Token"))
.and(header("Content-Type", "application/json"))
.and(path("/email"))
.and(method("POST"))
.and(SendEmailBodyMatcher)
.respond_with(ResponseTemplate::new(200))
.expect(1)
.mount(&mock_server)
.await;

// Act
let _ = email_client
.send_email(&email(), &subject(), &content(), &content())
.await;
}

#[tokio::test]
async fn send_email_succeeds_if_the_server_returns_200() {
// Arrange
let mock_server = MockServer::start().await;
let email_client = email_client(mock_server.uri());

Mock::given(any())
.respond_with(ResponseTemplate::new(200))
.expect(1)
.mount(&mock_server)
.await;

// Act
let outcome = email_client
.send_email(&email(), &subject(), &content(), &content())
.await;

// Assert
assert_ok!(outcome);
}

#[tokio::test]
async fn send_email_fails_if_the_server_returns_500() {
// Arrange
let mock_server = MockServer::start().await;
let email_client = email_client(mock_server.uri());

Mock::given(any())
.respond_with(ResponseTemplate::new(500))
.expect(1)
.mount(&mock_server)
.await;

// Act
let outcome = email_client
.send_email(&email(), &subject(), &content(), &content())
.await;

// Assert
assert_err!(outcome);
}

#[tokio::test]
async fn send_email_times_out_if_the_server_takes_too_long() {
// Arrange
let mock_server = MockServer::start().await;
let email_client = email_client(mock_server.uri());

let response = ResponseTemplate::new(200).set_delay(std::time::Duration::from_secs(180));
Mock::given(any())
.respond_with(response)
.expect(1)
.mount(&mock_server)
.await;

// Act
let outcome = email_client
.send_email(&email(), &subject(), &content(), &content())
.await;

// Assert
assert_err!(outcome);
}

0 comments on commit 4f52238

Please sign in to comment.