feat: test helper, snapshot testing
This commit is contained in:
parent
ed7ce14990
commit
931b7e159d
43
Cargo.lock
generated
43
Cargo.lock
generated
@ -748,6 +748,7 @@ dependencies = [
|
||||
"dotenv",
|
||||
"futures-util",
|
||||
"idna 1.0.2",
|
||||
"insta",
|
||||
"lettre",
|
||||
"pico-args",
|
||||
"quick-xml",
|
||||
@ -886,6 +887,18 @@ dependencies = [
|
||||
"crossbeam-utils",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "console"
|
||||
version = "0.15.8"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "0e1f83fc076bd6dd27517eacdf25fef6c4dfe5f1d7448bafaaf3a26f13b5e4eb"
|
||||
dependencies = [
|
||||
"encode_unicode",
|
||||
"lazy_static",
|
||||
"libc",
|
||||
"windows-sys 0.52.0",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "const-oid"
|
||||
version = "0.9.6"
|
||||
@ -1180,6 +1193,12 @@ version = "0.2.9"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "e079f19b08ca6239f47f8ba8509c11cf3ea30095831f7fed61441475edd8c449"
|
||||
|
||||
[[package]]
|
||||
name = "encode_unicode"
|
||||
version = "0.3.6"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "a357d28ed41a50f9c765dbfe56cbc04a64e53e5fc58ba79fbc34c10ef3df831f"
|
||||
|
||||
[[package]]
|
||||
name = "encoding_rs"
|
||||
version = "0.8.35"
|
||||
@ -1825,6 +1844,18 @@ dependencies = [
|
||||
"generic-array",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "insta"
|
||||
version = "1.41.1"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "7e9ffc4d4892617c50a928c52b2961cb5174b6fc6ebf252b2fac9d21955c48b8"
|
||||
dependencies = [
|
||||
"console",
|
||||
"lazy_static",
|
||||
"linked-hash-map",
|
||||
"similar",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "instant"
|
||||
version = "0.1.13"
|
||||
@ -1951,6 +1982,12 @@ dependencies = [
|
||||
"vcpkg",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "linked-hash-map"
|
||||
version = "0.5.6"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "0717cef1bc8b636c6e1c1bbdefc09e6322da8a9321966e8928ef80d20f7f770f"
|
||||
|
||||
[[package]]
|
||||
name = "linux-raw-sys"
|
||||
version = "0.3.8"
|
||||
@ -2774,6 +2811,12 @@ dependencies = [
|
||||
"rand_core",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "similar"
|
||||
version = "2.6.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "1de1d4f81173b03af4c0cbed3c898f6bff5b870e4a7f5d6f4057d62a7a4b686e"
|
||||
|
||||
[[package]]
|
||||
name = "slab"
|
||||
version = "0.4.9"
|
||||
|
@ -41,6 +41,9 @@ actix-http = "3.9.0"
|
||||
built = "0.7.4"
|
||||
static-files = "0.2.1"
|
||||
|
||||
[dev-dependencies]
|
||||
insta = "1.41.1"
|
||||
|
||||
# [dev-dependencies]
|
||||
# brass-web = { path = "." }
|
||||
|
||||
|
@ -1,4 +1,5 @@
|
||||
use actix_web::{web, HttpResponse, Responder};
|
||||
use brass_macros::db_test;
|
||||
use sqlx::PgPool;
|
||||
|
||||
use crate::{
|
||||
@ -7,6 +8,11 @@ use crate::{
|
||||
utils::ApplicationError,
|
||||
};
|
||||
|
||||
#[cfg(test)]
|
||||
use crate::utils::test_helper::{test_delete, DbTestContext, RequestConfig};
|
||||
#[cfg(test)]
|
||||
use actix_http::StatusCode;
|
||||
|
||||
#[actix_web::delete("/area/delete/{id}")]
|
||||
pub async fn delete(
|
||||
user: web::ReqData<User>,
|
||||
@ -25,3 +31,49 @@ pub async fn delete(
|
||||
|
||||
return Ok(HttpResponse::Ok().finish());
|
||||
}
|
||||
|
||||
#[db_test]
|
||||
async fn works_when_user_is_admin(context: &DbTestContext) {
|
||||
Area::create(&context.db_pool, "Area to delete")
|
||||
.await
|
||||
.unwrap();
|
||||
assert!(Area::read_by_id(&context.db_pool, 2)
|
||||
.await
|
||||
.unwrap()
|
||||
.is_some());
|
||||
|
||||
let app = context.app().await;
|
||||
let config = RequestConfig {
|
||||
uri: "/area/delete/2".to_string(),
|
||||
role: Role::Admin,
|
||||
function: crate::models::Function::Posten,
|
||||
user_area: 1,
|
||||
};
|
||||
let response = test_delete(&context.db_pool, app, &config).await;
|
||||
|
||||
assert_eq!(StatusCode::OK, response.status());
|
||||
assert!(Area::read_by_id(&context.db_pool, 2)
|
||||
.await
|
||||
.unwrap()
|
||||
.is_none());
|
||||
}
|
||||
|
||||
#[db_test]
|
||||
async fn does_not_work_when_user_is_not_admin(context: &DbTestContext) {
|
||||
Area::create(&context.db_pool, "Area to delete")
|
||||
.await
|
||||
.unwrap();
|
||||
assert!(Area::read_by_id(&context.db_pool, 2)
|
||||
.await
|
||||
.unwrap()
|
||||
.is_some());
|
||||
|
||||
let app = context.app().await;
|
||||
let response = test_delete(&context.db_pool, app, &RequestConfig::new("/area/delete/2")).await;
|
||||
|
||||
assert_eq!(StatusCode::UNAUTHORIZED, response.status());
|
||||
assert!(Area::read_by_id(&context.db_pool, 2)
|
||||
.await
|
||||
.unwrap()
|
||||
.is_some());
|
||||
}
|
||||
|
@ -1,7 +1,18 @@
|
||||
use actix_web::{web, HttpResponse, Responder};
|
||||
use actix_web::{body::MessageBody, test::read_body, web, HttpResponse, Responder};
|
||||
use askama_actix::TemplateToResponse;
|
||||
use brass_macros::db_test;
|
||||
use insta::assert_snapshot;
|
||||
|
||||
use crate::{endpoints::area::NewOrEditAreaTemplate, models::{Role, User}};
|
||||
use crate::{
|
||||
endpoints::area::NewOrEditAreaTemplate,
|
||||
models::{Role, User},
|
||||
utils::test_helper::DbTestContext,
|
||||
};
|
||||
|
||||
#[cfg(test)]
|
||||
use crate::utils::test_helper::{test_get, RequestConfig};
|
||||
#[cfg(test)]
|
||||
use actix_http::StatusCode;
|
||||
|
||||
#[actix_web::get("/area/new")]
|
||||
async fn get(user: web::ReqData<User>) -> impl Responder {
|
||||
@ -11,8 +22,25 @@ async fn get(user: web::ReqData<User>) -> impl Responder {
|
||||
|
||||
let template = NewOrEditAreaTemplate {
|
||||
user: user.into_inner(),
|
||||
area: None
|
||||
area: None,
|
||||
};
|
||||
|
||||
template.to_response()
|
||||
}
|
||||
|
||||
#[db_test]
|
||||
async fn produces_template(context: &DbTestContext) {
|
||||
let app = context.app().await;
|
||||
let config = RequestConfig {
|
||||
uri: "/area/new".to_string(),
|
||||
role: Role::Admin,
|
||||
function: crate::models::Function::Posten,
|
||||
user_area: 1,
|
||||
};
|
||||
let response = test_get(&context.db_pool, app, &config).await;
|
||||
|
||||
assert_eq!(StatusCode::OK, response.status());
|
||||
|
||||
let body = String::from_utf8(read_body(response).await.to_vec()).unwrap();
|
||||
assert_snapshot!(body);
|
||||
}
|
||||
|
@ -36,3 +36,9 @@ impl TryFrom<u8> for Function {
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl Default for Function {
|
||||
fn default() -> Self {
|
||||
Self::Posten
|
||||
}
|
||||
}
|
||||
|
@ -1,26 +1,11 @@
|
||||
use actix_http::StatusCode;
|
||||
use actix_identity::Identity;
|
||||
use actix_web::test;
|
||||
use actix_web::test::call_service;
|
||||
use actix_web::test::TestRequest;
|
||||
use actix_web::HttpMessage;
|
||||
use brass_macros::db_test;
|
||||
use sqlx::{query, PgPool};
|
||||
|
||||
use crate::auth::utils::generate_salt_and_hash_plain_password;
|
||||
use crate::auth::utils::hash_plain_password_with_salt;
|
||||
use crate::endpoints::user::post_login::LoginForm;
|
||||
use crate::models::Function;
|
||||
use crate::models::Role;
|
||||
use crate::models::User;
|
||||
use crate::utils::test_helper::DbTestContext;
|
||||
|
||||
use super::Area;
|
||||
|
||||
use super::Result;
|
||||
|
||||
#[derive(Debug)]
|
||||
pub struct Location {
|
||||
pub struct Location {
|
||||
pub id: i32,
|
||||
pub name: String,
|
||||
pub area_id: i32,
|
||||
@ -133,55 +118,3 @@ impl Location {
|
||||
Ok(())
|
||||
}
|
||||
}
|
||||
|
||||
#[db_test]
|
||||
async fn test_read_all(context: &DbTestContext) {
|
||||
let app = context.app().await;
|
||||
|
||||
let (hash, salt) = generate_salt_and_hash_plain_password("abc").unwrap();
|
||||
User::create_with_password(&context.db_pool, "abc", "abc", &hash, &salt, Role::Admin, Function::Wachhabender, 1).await.unwrap();
|
||||
|
||||
Location::create(&context.db_pool, "wundervolle location", 1).await.unwrap();
|
||||
|
||||
//let locations = Location::read_all(&context.db_pool).await.unwrap();
|
||||
//
|
||||
//assert_eq!(1, locations.len());
|
||||
|
||||
let login_form = LoginForm {
|
||||
email: "abc".to_string(),
|
||||
password: "abc".to_string()
|
||||
};
|
||||
|
||||
let login_req = TestRequest::post()
|
||||
.uri("/login")
|
||||
.set_form(login_form)
|
||||
.to_request();
|
||||
|
||||
let login_resp = call_service(&app, login_req).await;
|
||||
//println!("{:?}", log);
|
||||
let cookie = login_resp.response().cookies().next().unwrap().to_owned();
|
||||
|
||||
let req = TestRequest::get()
|
||||
.uri("/locations")
|
||||
.cookie(cookie)
|
||||
.to_request();
|
||||
|
||||
//let http_req = TestRequest::get()
|
||||
// .uri("/locations")
|
||||
// .to_http_request();
|
||||
//let service_req = TestRequest::get()
|
||||
// .uri("/locations")
|
||||
// .to_srv_request();
|
||||
|
||||
//Identity::login(&req.extensions(), "1".to_string()).unwrap();
|
||||
let resp = call_service(&context.app().await, req).await;
|
||||
//let resp = test::call_and_read_body(&context.app().await, http_req).await;
|
||||
|
||||
println!("{:?}", resp.headers());
|
||||
assert_eq!(StatusCode::OK, resp.status());
|
||||
|
||||
|
||||
let body = test::read_body(resp).await;
|
||||
let body_string = String::from_utf8(body.to_vec()).unwrap();
|
||||
assert!(body_string.contains("wundervolle location"));
|
||||
}
|
||||
|
@ -23,3 +23,9 @@ impl TryFrom<u8> for Role {
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl Default for Role {
|
||||
fn default() -> Self {
|
||||
Self::Staff
|
||||
}
|
||||
}
|
||||
|
@ -4,6 +4,8 @@ pub mod password_help;
|
||||
pub mod token_generation;
|
||||
pub mod event_planning_template;
|
||||
mod application_error;
|
||||
|
||||
#[cfg(test)]
|
||||
pub mod test_helper;
|
||||
|
||||
pub use application_error::ApplicationError;
|
||||
|
@ -7,14 +7,20 @@ use actix_web::{
|
||||
test::init_service,
|
||||
};
|
||||
use brass_config::{load_config, Config, Environment};
|
||||
use lettre::{transport::stub::StubTransport, Transport};
|
||||
use lettre::transport::stub::StubTransport;
|
||||
use rand::{distributions::Alphanumeric, thread_rng, Rng};
|
||||
use regex::{Captures, Regex};
|
||||
use sqlx::{
|
||||
postgres::{PgConnectOptions, PgPoolOptions},
|
||||
Connection, Executor, PgConnection, PgPool,
|
||||
Connection, Executor, PgConnection, PgPool, Pool, Postgres,
|
||||
};
|
||||
|
||||
mod test_requests;
|
||||
pub use test_requests::test_delete;
|
||||
pub use test_requests::test_get;
|
||||
pub use test_requests::test_post;
|
||||
pub use test_requests::RequestConfig;
|
||||
|
||||
use crate::create_app;
|
||||
|
||||
#[derive(Debug)]
|
||||
|
131
web/src/utils/test_helper/test_requests.rs
Normal file
131
web/src/utils/test_helper/test_requests.rs
Normal file
@ -0,0 +1,131 @@
|
||||
use crate::{
|
||||
endpoints::user::post_login::LoginForm,
|
||||
models::{Function, Role, User},
|
||||
};
|
||||
use actix_http::Request;
|
||||
use actix_web::{
|
||||
body::MessageBody,
|
||||
cookie::Cookie,
|
||||
dev::{Service, ServiceResponse},
|
||||
error::Error,
|
||||
test,
|
||||
};
|
||||
use serde::Serialize;
|
||||
use sqlx::{Pool, Postgres};
|
||||
|
||||
pub struct RequestConfig {
|
||||
pub uri: String,
|
||||
pub role: Role,
|
||||
pub function: Function,
|
||||
pub user_area: i32,
|
||||
}
|
||||
|
||||
impl RequestConfig {
|
||||
pub fn new(uri: &str) -> Self {
|
||||
Self {
|
||||
uri: uri.to_string(),
|
||||
role: Role::Staff,
|
||||
function: Function::Posten,
|
||||
user_area: 1,
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
async fn create_user_and_get_login_cookie<'a, T, R>(
|
||||
pool: &Pool<Postgres>,
|
||||
app: &T,
|
||||
config: &RequestConfig,
|
||||
) -> Cookie<'a>
|
||||
where
|
||||
T: Service<Request, Response = ServiceResponse<R>, Error = Error>,
|
||||
R: MessageBody + 'a,
|
||||
{
|
||||
const HASH: &str = "$argon2id$v=19$m=19456,t=2,p=1$IPiLaPCFZOK69MA1a6GUzw$ZZinpbkP7pXhN7g7dGkh87kGTeuFd/2er1U+y+4IKWo";
|
||||
const SALT: &str = "IPiLaPCFZOK69MA1a6GUzw";
|
||||
|
||||
User::create_with_password(
|
||||
pool,
|
||||
"abc",
|
||||
"abc",
|
||||
&HASH,
|
||||
&SALT,
|
||||
config.role,
|
||||
config.function,
|
||||
config.user_area,
|
||||
)
|
||||
.await
|
||||
.unwrap();
|
||||
|
||||
let login_form = LoginForm {
|
||||
email: "abc".to_string(),
|
||||
password: "abc".to_string(),
|
||||
};
|
||||
|
||||
let login_req = test::TestRequest::post()
|
||||
.uri("/login")
|
||||
.set_form(login_form)
|
||||
.to_request();
|
||||
|
||||
let login_resp = test::call_service(&app, login_req).await;
|
||||
login_resp.response().cookies().next().unwrap().into_owned()
|
||||
}
|
||||
|
||||
pub async fn test_get<T, R>(
|
||||
pool: &Pool<Postgres>,
|
||||
app: T,
|
||||
config: &RequestConfig,
|
||||
) -> ServiceResponse<R>
|
||||
where
|
||||
T: Service<Request, Response = ServiceResponse<R>, Error = Error>,
|
||||
R: MessageBody,
|
||||
{
|
||||
let cookie = create_user_and_get_login_cookie(&pool, &app, &config).await;
|
||||
|
||||
let get_request = test::TestRequest::get()
|
||||
.uri(&config.uri)
|
||||
.cookie(cookie)
|
||||
.to_request();
|
||||
|
||||
test::call_service(&app, get_request).await
|
||||
}
|
||||
|
||||
pub async fn test_post<T, R, F>(
|
||||
pool: &Pool<Postgres>,
|
||||
app: T,
|
||||
config: &RequestConfig,
|
||||
form: F,
|
||||
) -> ServiceResponse<R>
|
||||
where
|
||||
T: Service<Request, Response = ServiceResponse<R>, Error = Error>,
|
||||
R: MessageBody,
|
||||
F: Serialize,
|
||||
{
|
||||
let cookie = create_user_and_get_login_cookie(&pool, &app, config).await;
|
||||
|
||||
let post_request = test::TestRequest::post()
|
||||
.uri(&config.uri)
|
||||
.cookie(cookie)
|
||||
.set_form(form)
|
||||
.to_request();
|
||||
|
||||
test::call_service(&app, post_request).await
|
||||
}
|
||||
|
||||
pub async fn test_delete<T, R>(
|
||||
pool: &Pool<Postgres>,
|
||||
app: T,
|
||||
config: &RequestConfig,
|
||||
) -> ServiceResponse<R>
|
||||
where
|
||||
T: Service<Request, Response = ServiceResponse<R>, Error = Error>,
|
||||
R: MessageBody,
|
||||
{
|
||||
let cookie = create_user_and_get_login_cookie(&pool, &app, config).await;
|
||||
|
||||
let delete_request = test::TestRequest::delete()
|
||||
.uri(&config.uri)
|
||||
.cookie(cookie)
|
||||
.to_request();
|
||||
|
||||
test::call_service(&app, delete_request).await
|
||||
}
|
Loading…
x
Reference in New Issue
Block a user