Skip to content

Commit 88db4fe

Browse files
committed
chore: refactored
1 parent 4e763bc commit 88db4fe

File tree

4 files changed

+91
-22
lines changed

4 files changed

+91
-22
lines changed

Diff for: Cargo.lock

+15
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

Diff for: Cargo.toml

+1
Original file line numberDiff line numberDiff line change
@@ -15,6 +15,7 @@ name = "robust-rust"
1515
[dependencies]
1616
actix-web = "4"
1717
tokio = { version = "1", features = ["macros", "rt-multi-thread"] }
18+
serde = {version = "1.0.163", features = ["derive"]}
1819

1920
[dev-dependencies]
2021
reqwest = "0.11.18"

Diff for: src/lib.rs

+13-8
Original file line numberDiff line numberDiff line change
@@ -1,21 +1,26 @@
1-
use actix_web::{dev::Server, web, App, HttpRequest, HttpResponse, HttpServer, Responder};
1+
use actix_web::{dev::Server, web, App, HttpResponse, HttpServer};
22
use std::net::TcpListener;
33

4-
async fn greet(req: HttpRequest) -> impl Responder {
5-
let name = req.match_info().get("name").unwrap_or("world");
6-
format!("Hello {}!", name)
4+
#[allow(dead_code)]
5+
#[derive(serde::Deserialize)]
6+
struct FormData {
7+
email: String,
8+
name: String,
79
}
810

9-
async fn health_check() -> impl Responder {
10-
HttpResponse::Ok()
11+
async fn health_check() -> HttpResponse {
12+
HttpResponse::Ok().into()
13+
}
14+
15+
async fn subscribe(_form: web::Form<FormData>) -> HttpResponse {
16+
HttpResponse::Ok().finish()
1117
}
1218

1319
pub fn run(listener: TcpListener) -> Result<Server, std::io::Error> {
1420
let server = HttpServer::new(|| {
1521
App::new()
16-
.route("/", web::get().to(greet))
17-
.route("/{name}", web::get().to(greet))
1822
.route("/health_check", web::get().to(health_check))
23+
.route("/subscriptions", web::post().to(subscribe))
1924
})
2025
.listen(listener)?
2126
.run();

Diff for: tests/health_check.rs

+62-14
Original file line numberDiff line numberDiff line change
@@ -2,6 +2,22 @@ use reqwest::Client;
22
use robust_rust::run;
33
use std::net::TcpListener;
44

5+
#[allow(clippy::let_underscore_future)]
6+
fn spawn_app() -> String {
7+
let listener = TcpListener::bind("127.0.0.1:0").expect("Failed to bind random port");
8+
9+
// Retrieve the port assigned to us by the OS
10+
let port = listener.local_addr().unwrap().port();
11+
12+
// Launch our application as a background task
13+
let server = run(listener).expect("Failed to bind address");
14+
15+
let _ = tokio::spawn(server);
16+
17+
// Return the application address to the caller!
18+
format!("http://127.0.0.1:{}", port)
19+
}
20+
521
#[tokio::test]
622
async fn health_check_works() {
723
// Arrange
@@ -17,21 +33,53 @@ async fn health_check_works() {
1733
.expect("Failed to execute request.");
1834
// Assert
1935
assert!(response.status().is_success());
20-
assert_eq!(Some(19), response.content_length());
36+
assert_eq!(Some(0), response.content_length());
2137
}
2238

23-
#[allow(clippy::let_underscore_future)]
24-
fn spawn_app() -> String {
25-
let listener = TcpListener::bind("127.0.0.1:0").expect("Failed to bind random port");
26-
27-
// Retrieve the port assigned to us by the OS
28-
let port = listener.local_addr().unwrap().port();
29-
30-
// Launch our application as a background task
31-
let server = run(listener).expect("Failed to bind address");
32-
33-
let _ = tokio::spawn(server);
39+
#[tokio::test]
40+
async fn subscribe_returns_a_200_for_valid_form_data() {
41+
// Arrange
42+
let app_address = spawn_app();
43+
let client = reqwest::Client::new();
44+
// Act
45+
let body = "name=le%20guin&email=ursula_le_guin%40gmail.com";
46+
let response = client
47+
.post(&format!("{}/subscriptions", &app_address))
48+
.header("Content-Type", "application/x-www-form-urlencoded")
49+
.body(body)
50+
.send()
51+
.await
52+
.expect("Failed to execute request.");
53+
// Assert
54+
assert_eq!(200, response.status().as_u16());
55+
}
3456

35-
// Return the application address to the caller!
36-
format!("http://127.0.0.1:{}", port)
57+
#[tokio::test]
58+
async fn subscribe_returns_a_400_when_data_is_missing() {
59+
// Arrange
60+
let app_address = spawn_app();
61+
let client = reqwest::Client::new();
62+
let test_cases = vec![
63+
("name=le%20guin", "missing the email"),
64+
("email=ursula_le_guin%40gmail.com", "missing the name"),
65+
("", "missing both name and email"),
66+
];
67+
for (invalid_body, error_message) in test_cases {
68+
// Act
69+
let response = client
70+
.post(&format!("{}/subscriptions", &app_address))
71+
.header("Content-Type", "application/x-www-form-urlencoded")
72+
.body(invalid_body)
73+
.send()
74+
.await
75+
.expect("Failed to execute request.");
76+
// Assert
77+
assert_eq!(
78+
400,
79+
response.status().as_u16(),
80+
// Additional customised error message on test failure
81+
"The API did not fail with 400 Bad Request when the payload was {}.",
82+
error_message
83+
);
84+
}
3785
}

0 commit comments

Comments
 (0)