Skip to content

Commit 0ded42e

Browse files
committed
performed comprehensive tests on user-sign-up.
1 parent b8c0b5e commit 0ded42e

14 files changed

Lines changed: 595 additions & 20 deletions

‎Cargo.lock‎

Lines changed: 376 additions & 17 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

‎Cargo.toml‎

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -17,6 +17,7 @@ argon2 = "0.5.3"
1717
async-trait = "0.1.89"
1818
axum = { version = "0.8.8", features = ["json", "macros"] }
1919
axum-extra = { version = "0.12.5", features = ["cookie", "typed-header", "typed-routing"] }
20+
axum-test = { version = "19.1.1", features = ["typed-routing"] }
2021
chrono = { version = "0.4.44", features = ["serde"] }
2122
clap = { version = "4.5.60", features = ["derive"] }
2223
color-eyre = "0.6.5"
@@ -42,6 +43,8 @@ uuid = { version = "1.22.0", features = ["v4", "serde"] }
4243
validator = { version = "0.20.0", features = ["derive"] }
4344

4445
[dev-dependencies]
46+
axum-test = { version = "19.1.1", features = ["typed-routing"] }
4547
insta = { version = "1.46.3", features = ["redactions", "filters"] }
48+
rstest = "0.26.1"
4649
serial = "0.4.0"
4750
serial_test = "3.4.0"

‎src/controllers/auth.rs‎

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -33,7 +33,7 @@ async fn register(
3333

3434
let user = UserModel::register_user(ctx.db(), validated).await?;
3535

36-
Ok((StatusCode::OK, Json(UserResponse::new(&user))).into_response())
36+
Ok((StatusCode::CREATED, Json(UserResponse::new(&user))).into_response())
3737
}
3838

3939
#[debug_handler]

‎tests/mod.rs‎

Lines changed: 31 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,11 +1,18 @@
1-
use std::sync::{Arc, OnceLock};
1+
use std::{
2+
future::Future,
3+
sync::{Arc, OnceLock},
4+
};
25

36
use auth::{
4-
AppContext, Result,
7+
App, AppContext, Result,
58
config::{Config, Environment},
9+
controllers,
610
};
11+
use axum_test::{TestServer, TestServerConfig};
12+
use sqlx::PgPool;
713

814
mod repository;
15+
mod requests;
916
mod seed;
1017

1118
pub async fn boot_test() -> Result<Arc<AppContext>> {
@@ -17,6 +24,28 @@ pub async fn boot_test() -> Result<Arc<AppContext>> {
1724
Ok(ctx)
1825
}
1926

27+
pub async fn request<F, Fut>(f: F)
28+
where
29+
F: FnOnce(TestServer, Arc<AppContext>) -> Fut,
30+
Fut: Future<Output = ()>,
31+
{
32+
let ctx = boot_test().await.unwrap();
33+
34+
let cfg = TestServerConfig {
35+
default_content_type: Some("application/json".into()),
36+
save_cookies: true,
37+
..Default::default()
38+
};
39+
40+
let server = TestServer::new_with_config(controllers::router(&ctx), cfg);
41+
42+
f(server, ctx).await
43+
}
44+
45+
pub async fn seed_data(db: &PgPool) -> Result<()> {
46+
App::seed(db).await
47+
}
48+
2049
static CLEANUP_UUID: OnceLock<Vec<(&'static str, &'static str)>> = OnceLock::new();
2150
static CLEANUP_DATE: OnceLock<Vec<(&'static str, &'static str)>> = OnceLock::new();
2251
static CLEANUP_PASSWORD: OnceLock<Vec<(&'static str, &'static str)>> = OnceLock::new();

‎tests/requests/auth.rs‎

Lines changed: 111 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,111 @@
1+
use insta::{Settings, assert_debug_snapshot, with_settings};
2+
use rstest::rstest;
3+
use serial_test::serial;
4+
5+
macro_rules! configure_insta {
6+
($(expr:expr),*) => {
7+
let mut settings = Settings::clone_current();
8+
settings.set_prepend_module_to_snapshot(false);
9+
settings.set_snapshot_path("snapshots/auth");
10+
settings.set_snapshot_suffix("auth");
11+
let _guard = settings.bind_to_scope();
12+
};
13+
}
14+
15+
#[rstest]
16+
#[case(
17+
"can_successfully_register_user",
18+
serde_json::json!({
19+
"email": "test1@example.com",
20+
"username": "test_user1",
21+
"password": "SafePassWord11!",
22+
"confirmPassword": "SafePassWord11!"
23+
})
24+
)]
25+
#[case(
26+
"when_passwords_do_not_match_registration_fails",
27+
serde_json::json!({
28+
"email": "test1@example.com",
29+
"username": "test_user1",
30+
"password": "SafePassWord11!",
31+
"confirmPassword": "SafePassWord11"
32+
})
33+
)]
34+
#[case(
35+
"when_password_is_under_eight_chars_registration_fails",
36+
serde_json::json!({
37+
"email": "test1@example.com",
38+
"username": "test_user1",
39+
"password": "Safe",
40+
"confirmPassword": "Safe"
41+
})
42+
)]
43+
#[case(
44+
"when_password_contains_whitespace_char_registration_fails",
45+
serde_json::json!({
46+
"email": "test1@example.com",
47+
"username": "test_user1",
48+
"password": "ChangeMe 123!",
49+
"confirmPassword": "ChangeMe 123!"
50+
})
51+
)]
52+
#[case(
53+
"when_password_contains_comma_char_registration_fails",
54+
serde_json::json!({
55+
"email": "test1@example.com",
56+
"username": "test_user1",
57+
"password": "ChangeMe,123!",
58+
"confirmPassword": "ChangeMe,123!"
59+
})
60+
)]
61+
#[case(
62+
"when_email_is_not_an_email_registration_fails",
63+
serde_json::json!({
64+
"email": "test1:example.com",
65+
"username": "test_user1",
66+
"password": "Password123",
67+
"confirmPassword": "Password123"
68+
})
69+
)]
70+
#[case(
71+
"when_username_is_under_six_chars_registration_fails",
72+
serde_json::json!({
73+
"email": "test1@example.com",
74+
"username": "test",
75+
"password": "Password123",
76+
"confirmPassword": "Password123"
77+
})
78+
)]
79+
#[case(
80+
"when_username_contains_non_alphanumeric_chars_registration_fails",
81+
serde_json::json!({
82+
"email": "test1@example.com",
83+
"username": "test user;+",
84+
"password": "Password123",
85+
"confirmPassword": "Password123"
86+
})
87+
)]
88+
#[tokio::test]
89+
#[serial]
90+
async fn can_register_user(#[case] test_name: &str, #[case] params: serde_json::Value) {
91+
crate::request(|server, ctx| async move {
92+
configure_insta!();
93+
94+
crate::seed_data(ctx.db())
95+
.await
96+
.expect("Failed to seed data");
97+
98+
let response = server.post("/auth/sign-up").json(&params).await;
99+
100+
with_settings!({
101+
filters => {
102+
let mut filters = crate::cleanup_date().to_vec();
103+
filters.extend(crate::cleanup_uuid().to_vec());
104+
filters
105+
}
106+
}, {
107+
assert_debug_snapshot!(test_name, (response.status_code(), response.text()))
108+
})
109+
})
110+
.await;
111+
}

‎tests/requests/mod.rs‎

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1 @@
1+
mod auth;
Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,9 @@
1+
---
2+
source: tests/requests/auth.rs
3+
assertion_line: 55
4+
expression: "(response.status_code(), response.text())"
5+
---
6+
(
7+
201,
8+
"{\"id\":\"ID\",\"email\":\"test1@example.com\",\"username\":\"test_user1\",\"imageUrl\":null,\"verified\":false,\"createdAt\":\"DATEZ\",\"updatedAt\":\"DATEZ\"}",
9+
)
Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,9 @@
1+
---
2+
source: tests/requests/auth.rs
3+
assertion_line: 71
4+
expression: "(response.status_code(), response.text())"
5+
---
6+
(
7+
422,
8+
"{\"error\":\"{\\\"email\\\":\\\"Invalid email address\\\"}\"}",
9+
)
Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,9 @@
1+
---
2+
source: tests/requests/auth.rs
3+
assertion_line: 107
4+
expression: "(response.status_code(), response.text())"
5+
---
6+
(
7+
422,
8+
"{\"error\":\"{\\\"password\\\":\\\"password cannot have commas\\\"}\"}",
9+
)
Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,9 @@
1+
---
2+
source: tests/requests/auth.rs
3+
assertion_line: 107
4+
expression: "(response.status_code(), response.text())"
5+
---
6+
(
7+
422,
8+
"{\"error\":\"{\\\"password\\\":\\\"password cannot have spaces\\\"}\"}",
9+
)

0 commit comments

Comments
 (0)