WIP: Add (smoke) integration tests
All checks were successful
/ build (push) Successful in 3m42s

This commit is contained in:
Simon Bruder 2024-07-27 22:16:12 +02:00
parent b22588cd0d
commit 0d6d92207e
Signed by: simon
GPG key ID: 347FF8699CDA0776
4 changed files with 163 additions and 0 deletions

1
Cargo.lock generated
View file

@ -1221,6 +1221,7 @@ dependencies = [
name = "li7y" name = "li7y"
version = "0.0.0" version = "0.0.0"
dependencies = [ dependencies = [
"actix-http",
"actix-identity", "actix-identity",
"actix-session", "actix-session",
"actix-web", "actix-web",

View file

@ -36,6 +36,7 @@ time = { version = "0.3.36", features = ["parsing", "serde"] }
uuid = { version = "1.9.0", features = ["serde", "v4"] } uuid = { version = "1.9.0", features = ["serde", "v4"] }
[dev-dependencies] [dev-dependencies]
actix-http = "3.8.0"
quickcheck = "1.0.3" quickcheck = "1.0.3"
quickcheck_macros = "1.0.0" quickcheck_macros = "1.0.0"

68
tests/common/mod.rs Normal file
View file

@ -0,0 +1,68 @@
// SPDX-FileCopyrightText: 2024 Simon Bruder <simon@sbruder.de>
//
// SPDX-License-Identifier: AGPL-3.0-or-later
use std::env;
use actix_http::header;
use actix_web::{cookie::Cookie, dev::ServiceResponse, test};
use clap::Parser;
use serde::Serialize;
use li7y::Config;
pub const SUPERUSER_PASSWORD: &str = "correct horse battery staple";
#[derive(Serialize)]
pub struct LoginForm {
password: String,
}
impl Default for LoginForm {
fn default() -> Self {
Self {
password: SUPERUSER_PASSWORD.to_string(),
}
}
}
pub fn config() -> Config {
env::set_var("SUPERUSER_PASSWORD", SUPERUSER_PASSWORD);
Config::parse_from(Vec::<std::ffi::OsString>::new().iter())
}
pub fn assert_redirect(res: ServiceResponse) -> String {
assert!(res.status().is_redirection());
res.headers()
.get(header::LOCATION)
.expect("No location header set when expected")
.to_str()
.expect("Location header is not valid UTF-8")
.to_string()
}
pub async fn session_cookie<'a>(
srv: &impl actix_web::dev::Service<
actix_http::Request,
Response = ServiceResponse<actix_web::body::EitherBody<actix_web::body::BoxBody>>,
Error = actix_web::Error,
>,
) -> Cookie<'a> {
let req = test::TestRequest::post()
.uri("/login")
.set_form(LoginForm::default())
.to_request();
Cookie::parse_encoded(
test::call_service(&srv, req)
.await
.headers()
.get(header::SET_COOKIE)
.unwrap()
.to_str()
.unwrap()
.to_string(),
)
.unwrap()
}

93
tests/smoke.rs Normal file
View file

@ -0,0 +1,93 @@
// SPDX-FileCopyrightText: 2024 Simon Bruder <simon@sbruder.de>
//
// SPDX-License-Identifier: AGPL-3.0-or-later
use actix_http::header;
use actix_web::{cookie::Cookie, test};
use sqlx::PgPool;
mod common;
#[sqlx::test]
async fn index(pool: PgPool) {
let srv = test::init_service(li7y::app(&common::config(), &pool)).await;
let req = test::TestRequest::get().uri("/").to_request();
let res = test::call_service(&srv, req).await;
assert!(common::assert_redirect(res.map_into_boxed_body()).starts_with("/login"));
}
#[sqlx::test]
async fn login(pool: PgPool) {
let srv = test::init_service(li7y::app(&common::config(), &pool)).await;
// This is identical to common::session_cookie,
// but copied here explicitly to ensure the right functionality is tested.
let req = test::TestRequest::post()
.uri("/login")
.set_form(common::LoginForm::default())
.to_request();
let res = test::call_service(&srv, req).await;
let session = Cookie::parse_encoded(
res.headers()
.clone()
.get(header::SET_COOKIE)
.unwrap()
.to_str()
.unwrap()
.to_string(),
)
.unwrap();
assert!(common::assert_redirect(res.map_into_boxed_body()).starts_with("/"));
let req = test::TestRequest::get()
.uri("/")
.cookie(session.clone())
.to_request();
let res = test::call_service(&srv, req).await;
assert!(res.status().is_success());
}
#[ignore = "actix_session::CookieSessionStore does not support invalidating sessions"]
#[sqlx::test]
async fn logout(pool: PgPool) {
let srv = test::init_service(li7y::app(&common::config(), &pool)).await;
let session_cookie = common::session_cookie(&srv).await;
let req = test::TestRequest::post()
.uri("/logout")
.cookie(session_cookie.clone())
.to_request();
test::call_service(&srv, req).await;
let req = test::TestRequest::get()
.uri("/items")
.cookie(session_cookie.clone())
.to_request();
let res = test::call_service(&srv, req).await;
assert!(common::assert_redirect(res.map_into_boxed_body()).starts_with("/login"));
}
#[sqlx::test]
async fn list_items(pool: PgPool) {
let srv = test::init_service(li7y::app(&common::config(), &pool)).await;
let session_cookie = common::session_cookie(&srv).await;
let req = test::TestRequest::get()
.uri("/items")
.cookie(session_cookie.clone())
.to_request();
let res = test::call_service(&srv, req).await;
assert!(res.status().is_success());
}