test: clothing

This commit is contained in:
Max Hohlfeld 2025-05-22 22:15:45 +02:00
parent 045a509daf
commit f874fcd788
7 changed files with 309 additions and 1 deletions

View File

@ -0,0 +1,36 @@
---
source: web/src/endpoints/clothing/get_edit.rs
expression: body
snapshot_kind: text
---
<form hx-post="/clothing/1" hx-target="closest a" hx-target-422="find p">
<div class="level">
<div class="level-left">
<div class="level-item">
<div class="field">
<label class="label"></label>
<div class="control">
<input class="input" name="name" type="text" value="Tuchuniform"
_="on input put '' into the next <p/>" placeholder="Tuchuniform" minlength="3" />
</div>
<p class="help is-danger"></p>
</div>
</div>
<div class="level-item buttons are-small">
<button class="button is-success">
<svg class="icon">
<use href="/static/feather-sprite.svg#check-circle" />
</svg>
</button>
<button class="button is-warning is-light" type="button" hx-get="/clothing/1" hx-target="closest a">
<svg class="icon">
<use href="/static/feather-sprite.svg#x-circle" />
</svg>
</button>
</div>
</div>
</div>
</form>

View File

@ -0,0 +1,72 @@
---
source: web/src/endpoints/clothing/get_overview.rs
expression: body
snapshot_kind: text
---
<section class="section">
<div class="container">
<h3 class="title is-3">
Anzugsordnungen
</h3>
<p class="subtitle is-5">zur Auswahl bei der Erstellung von Events</p>
<div class="panel p-2">
<a class="panel-block is-active">
<div class="level">
<div class="level-left">
<div class="level-item">
Tuchuniform
</div>
<div class="level-item buttons are-small">
<button class="button is-success is-light" hx-get="/clothing/edit/1" hx-target="closest a">
<svg class="icon">
<use href="/static/feather-sprite.svg#edit" />
</svg>
</button>
<button class="button is-danger is-light" hx-delete="/clothing/1" hx-swap="delete"
hx-target="closest a" hx-trigger="confirmed">
<svg class="icon">
<use href="/static/feather-sprite.svg#trash-2" />
</svg>
</button>
</div>
</div>
</div>
</a>
<a class="panel-block is-active">
<div class="level">
<div class="level-left">
<div class="level-item">
Schutzkleidung Form 1
</div>
<div class="level-item buttons are-small">
<button class="button is-success is-light" hx-get="/clothing/edit/2" hx-target="closest a">
<svg class="icon">
<use href="/static/feather-sprite.svg#edit" />
</svg>
</button>
<button class="button is-danger is-light" hx-delete="/clothing/2" hx-swap="delete"
hx-target="closest a" hx-trigger="confirmed">
<svg class="icon">
<use href="/static/feather-sprite.svg#trash-2" />
</svg>
</button>
</div>
</div>
</div>
</a>
<div class="panel-block">
<button class="button is-link is-light" hx-get="/clothing/new" hx-swap="beforebegin" hx-target="closest div">
<svg class="icon">
<use href="/static/feather-sprite.svg#plus-circle" />
</svg>
<span>neue Anzugsordnung</span>
</button>
</div>
</div>
</section>

View File

@ -0,0 +1,26 @@
---
source: web/src/endpoints/clothing/get_read.rs
expression: body
snapshot_kind: text
---
<div class="level">
<div class="level-left">
<div class="level-item">
Tuchuniform
</div>
<div class="level-item buttons are-small">
<button class="button is-success is-light" hx-get="/clothing/edit/1" hx-target="closest a">
<svg class="icon">
<use href="/static/feather-sprite.svg#edit" />
</svg>
</button>
<button class="button is-danger is-light" hx-delete="/clothing/1" hx-swap="delete"
hx-target="closest a" hx-trigger="confirmed">
<svg class="icon">
<use href="/static/feather-sprite.svg#trash-2" />
</svg>
</button>
</div>
</div>
</div>

View File

@ -165,7 +165,7 @@ snapshot_kind: text
<div class="field-body">
<div class="field">
<div class="control">
<input class="input" name="clothing" placeholder="Tuchuniform" required value="Tuchuniform"
<input class="input" name="clothing" placeholder="Tuchuniform" required value="1"
/>
</div>
</div>

View File

@ -25,3 +25,67 @@ pub async fn delete(
Ok(HttpResponse::Ok().finish())
}
#[cfg(test)]
mod tests {
use crate::{
models::{Clothing, Role},
utils::test_helper::{
test_delete, DbTestContext, RequestConfig,
StatusCode,
},
};
use brass_macros::db_test;
#[db_test]
async fn deletes_clothing_fine_when_user_is_admin(context: &DbTestContext) {
let app = context.app().await;
Clothing::create(&context.db_pool, "Tuchuniform")
.await
.unwrap();
assert_eq!(2, Clothing::read_all(&context.db_pool).await.unwrap().len());
let config = RequestConfig::new("/clothing/1").with_role(Role::Admin);
let response = test_delete(&context.db_pool, app, &config).await;
assert_eq!(StatusCode::OK, response.status());
assert_eq!(1, Clothing::read_all(&context.db_pool).await.unwrap().len());
// TODO: reduce numbers by one when db migrations are joined together
}
#[db_test]
async fn returns_unauthorized_when_user_is_user(context: &DbTestContext) {
let app = context.app().await;
let response = test_delete(&context.db_pool, app, &RequestConfig::new("/clothing/1")).await;
assert_eq!(StatusCode::UNAUTHORIZED, response.status());
}
#[db_test]
async fn returns_unauthorized_when_user_is_area_manager(context: &DbTestContext) {
let app = context.app().await;
let response = test_delete(
&context.db_pool,
app,
&RequestConfig::new("/clothing/1").with_role(Role::AreaManager),
)
.await;
assert_eq!(StatusCode::UNAUTHORIZED, response.status());
}
#[db_test]
async fn returns_not_found_when_clothing_does_not_exist(context: &DbTestContext) {
let app = context.app().await;
let response = test_delete(
&context.db_pool,
app,
&RequestConfig::new("/clothing/100").with_role(Role::Admin),
)
.await;
assert_eq!(StatusCode::NOT_FOUND, response.status());
}
}

View File

@ -28,3 +28,58 @@ pub async fn get(
Ok(template.to_response()?)
}
#[cfg(test)]
mod tests {
use crate::{
models::{Clothing, Role},
utils::test_helper::{
assert_snapshot, read_body, test_get, DbTestContext, RequestConfig, StatusCode,
},
};
use brass_macros::db_test;
#[db_test]
async fn user_cant_view_edit_entity(context: &DbTestContext) {
Clothing::create(&context.db_pool, "Tuchuniform")
.await
.unwrap();
let app = context.app().await;
let config = RequestConfig::new("/clothing/edit/1");
let response = test_get(&context.db_pool, &app, &config).await;
assert_eq!(StatusCode::UNAUTHORIZED, response.status());
}
#[db_test]
async fn area_manager_cant_view_edit_entity(context: &DbTestContext) {
Clothing::create(&context.db_pool, "Tuchuniform")
.await
.unwrap();
let app = context.app().await;
let config = RequestConfig::new("/clothing/edit/1").with_role(Role::AreaManager);
let response = test_get(&context.db_pool, &app, &config).await;
assert_eq!(StatusCode::UNAUTHORIZED, response.status());
}
#[db_test]
async fn produces_template_fine_when_user_is_admin(context: &DbTestContext) {
let app = context.app().await;
Clothing::create(&context.db_pool, "Schutzkleidung Form 1")
.await
.unwrap();
let config = RequestConfig::new("/clothing/edit/1").with_role(Role::Admin);
let response = test_get(&context.db_pool, &app, &config).await;
assert_eq!(StatusCode::OK, response.status());
let body = read_body(response).await;
assert_snapshot!(body);
}
}

View File

@ -25,3 +25,58 @@ pub async fn get(
Ok(template.to_response()?)
}
#[cfg(test)]
mod tests {
use crate::{
models::{Clothing, Role},
utils::test_helper::{
assert_snapshot, read_body, test_get, DbTestContext, RequestConfig, StatusCode,
},
};
use brass_macros::db_test;
#[db_test]
async fn user_cant_view_single_entity(context: &DbTestContext) {
Clothing::create(&context.db_pool, "Tuchuniform")
.await
.unwrap();
let app = context.app().await;
let config = RequestConfig::new("/clothing/1");
let response = test_get(&context.db_pool, &app, &config).await;
assert_eq!(StatusCode::UNAUTHORIZED, response.status());
}
#[db_test]
async fn area_manager_cant_view_single_entity(context: &DbTestContext) {
Clothing::create(&context.db_pool, "Tuchuniform")
.await
.unwrap();
let app = context.app().await;
let config = RequestConfig::new("/clothing/1").with_role(Role::AreaManager);
let response = test_get(&context.db_pool, &app, &config).await;
assert_eq!(StatusCode::UNAUTHORIZED, response.status());
}
#[db_test]
async fn produces_template_fine_when_user_is_admin(context: &DbTestContext) {
let app = context.app().await;
Clothing::create(&context.db_pool, "Schutzkleidung Form 1")
.await
.unwrap();
let config = RequestConfig::new("/clothing/1").with_role(Role::Admin);
let response = test_get(&context.db_pool, &app, &config).await;
assert_eq!(StatusCode::OK, response.status());
let body = read_body(response).await;
assert_snapshot!(body);
}
}