Skip to content

Commit 5cbd12f

Browse files
committed
reorganize tests: better structure
1 parent 0695cfe commit 5cbd12f

35 files changed

+921
-995
lines changed

tests/basic/mod.rs

Lines changed: 85 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,85 @@
1+
use actix_web::{
2+
body::MessageBody,
3+
http::{self, StatusCode},
4+
test,
5+
};
6+
use sqlpage::webserver::http::main_handler;
7+
8+
use crate::common::{get_request_to, req_path};
9+
10+
#[actix_web::test]
11+
async fn test_index_ok() {
12+
let resp = req_path("/").await.unwrap();
13+
assert_eq!(resp.status(), http::StatusCode::OK);
14+
let body = test::read_body(resp).await;
15+
assert!(body.starts_with(b"<!DOCTYPE html>"));
16+
let body = String::from_utf8(body.to_vec()).unwrap();
17+
assert!(body.contains("It works !"));
18+
assert!(!body.contains("error"));
19+
}
20+
21+
#[actix_web::test]
22+
async fn test_access_config_forbidden() {
23+
let resp_result = req_path("/sqlpage/sqlpage.json").await;
24+
assert!(resp_result.is_err(), "Accessing the config file should be forbidden, but we received a response: {resp_result:?}");
25+
let resp = resp_result.unwrap_err().error_response();
26+
assert_eq!(resp.status(), http::StatusCode::FORBIDDEN);
27+
assert!(
28+
String::from_utf8_lossy(&resp.into_body().try_into_bytes().unwrap())
29+
.to_lowercase()
30+
.contains("forbidden"),
31+
);
32+
}
33+
34+
#[actix_web::test]
35+
async fn test_404() {
36+
for f in [
37+
"/does_not_exist.sql",
38+
"/does_not_exist.html",
39+
"/does_not_exist/",
40+
] {
41+
let resp_result = req_path(f).await;
42+
let resp = resp_result.unwrap_err().error_response();
43+
assert_eq!(resp.status(), http::StatusCode::NOT_FOUND, "{f} isnt 404");
44+
}
45+
}
46+
47+
#[actix_web::test]
48+
async fn test_404_fallback() {
49+
for f in [
50+
"/tests/does_not_exist.sql",
51+
"/tests/does_not_exist.html",
52+
"/tests/does_not_exist/",
53+
] {
54+
let resp_result = req_path(f).await;
55+
let resp = resp_result.unwrap();
56+
assert_eq!(resp.status(), http::StatusCode::OK, "{f} isnt 200");
57+
58+
let body = test::read_body(resp).await;
59+
assert!(body.starts_with(b"<!DOCTYPE html>"));
60+
let body = String::from_utf8(body.to_vec()).unwrap();
61+
assert!(body.contains("But the "));
62+
assert!(body.contains("404.sql"));
63+
assert!(body.contains("file saved the day!"));
64+
assert!(!body.contains("error"));
65+
}
66+
}
67+
68+
#[actix_web::test]
69+
async fn test_static_files() {
70+
let resp = req_path("/tests/it_works.txt").await.unwrap();
71+
assert_eq!(resp.status(), http::StatusCode::OK);
72+
let body = test::read_body(resp).await;
73+
assert_eq!(&body, &b"It works !"[..]);
74+
}
75+
76+
#[actix_web::test]
77+
async fn test_spaces_in_file_names() {
78+
let resp = req_path("/tests/core/spaces%20in%20file%20name.sql")
79+
.await
80+
.unwrap();
81+
assert_eq!(resp.status(), http::StatusCode::OK);
82+
let body = test::read_body(resp).await;
83+
let body_str = String::from_utf8(body.to_vec()).unwrap();
84+
assert!(body_str.contains("It works !"), "{body_str}");
85+
}

tests/common/mod.rs

Lines changed: 104 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,104 @@
1+
use std::{collections::HashMap, path::PathBuf, time::Duration};
2+
3+
use actix_web::{
4+
http::header::ContentType,
5+
test::{self, TestRequest},
6+
web::Data,
7+
};
8+
use sqlpage::{
9+
app_config::{test_database_url, AppConfig},
10+
webserver::{
11+
http::{form_config, main_handler, payload_config},
12+
},
13+
AppState,
14+
};
15+
16+
pub async fn get_request_to_with_data(
17+
path: &str,
18+
data: Data<AppState>,
19+
) -> actix_web::Result<TestRequest> {
20+
Ok(test::TestRequest::get()
21+
.uri(path)
22+
.insert_header(ContentType::plaintext())
23+
.app_data(payload_config(&data))
24+
.app_data(form_config(&data))
25+
.app_data(data))
26+
}
27+
28+
pub async fn get_request_to(path: &str) -> actix_web::Result<TestRequest> {
29+
let data = make_app_data().await;
30+
get_request_to_with_data(path, data).await
31+
}
32+
33+
pub async fn make_app_data_from_config(config: AppConfig) -> Data<AppState> {
34+
let state = AppState::init(&config).await.unwrap();
35+
Data::new(state)
36+
}
37+
38+
pub async fn make_app_data() -> Data<AppState> {
39+
init_log();
40+
let config = test_config();
41+
make_app_data_from_config(config).await
42+
}
43+
44+
pub async fn req_path(
45+
path: impl AsRef<str>,
46+
) -> Result<actix_web::dev::ServiceResponse, actix_web::Error> {
47+
let req = get_request_to(path.as_ref()).await?.to_srv_request();
48+
main_handler(req).await
49+
}
50+
51+
pub async fn srv_req_path_with_app_data(
52+
path: impl AsRef<str>,
53+
app_data: Data<AppState>,
54+
) -> actix_web::dev::ServiceRequest {
55+
test::TestRequest::get()
56+
.uri(path.as_ref())
57+
.app_data(app_data)
58+
.insert_header(("cookie", "test_cook=123"))
59+
.insert_header(("authorization", "Basic dGVzdDp0ZXN0")) // test:test
60+
.to_srv_request()
61+
}
62+
63+
const REQ_TIMEOUT: Duration = Duration::from_secs(8);
64+
pub async fn req_path_with_app_data(
65+
path: impl AsRef<str>,
66+
app_data: Data<AppState>,
67+
) -> anyhow::Result<actix_web::dev::ServiceResponse> {
68+
let path = path.as_ref();
69+
let req = srv_req_path_with_app_data(path, app_data).await;
70+
let resp = tokio::time::timeout(REQ_TIMEOUT, main_handler(req))
71+
.await
72+
.map_err(|e| anyhow::anyhow!("Request to {path} timed out: {e}"))?
73+
.map_err(|e| {
74+
anyhow::anyhow!(
75+
"Request to {path} failed with status {}: {e:#}",
76+
e.as_response_error().status_code()
77+
)
78+
})?;
79+
Ok(resp)
80+
}
81+
82+
pub fn test_config() -> AppConfig {
83+
let db_url = test_database_url();
84+
serde_json::from_str::<AppConfig>(&format!(
85+
r#"{{
86+
"database_url": "{db_url}",
87+
"max_database_pool_connections": 1,
88+
"database_connection_retries": 3,
89+
"database_connection_acquire_timeout_seconds": 15,
90+
"allow_exec": true,
91+
"max_uploaded_file_size": 123456,
92+
"listen_on": "111.111.111.111:1",
93+
"system_root_ca_certificates" : false
94+
}}"#
95+
))
96+
.unwrap()
97+
}
98+
99+
pub fn init_log() {
100+
let _ = env_logger::builder()
101+
.parse_default_env()
102+
.is_test(true)
103+
.try_init();
104+
}

tests/components/mod.rs

Lines changed: 28 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,28 @@
1+
use actix_web::{
2+
http::StatusCode,
3+
test,
4+
};
5+
use sqlpage::webserver::http::main_handler;
6+
7+
use crate::common::get_request_to;
8+
9+
#[actix_web::test]
10+
async fn test_overwrite_variable() -> actix_web::Result<()> {
11+
let req = get_request_to("/tests/sql_test_files/it_works_set_variable.sql")
12+
.await?
13+
.set_form(std::collections::HashMap::<&str, &str>::from_iter([(
14+
"what_does_it_do",
15+
"does not overwrite variables",
16+
)]))
17+
.to_srv_request();
18+
let resp = main_handler(req).await?;
19+
20+
assert_eq!(resp.status(), StatusCode::OK);
21+
let body = test::read_body(resp).await;
22+
let body_str = String::from_utf8(body.to_vec()).unwrap();
23+
assert!(
24+
body_str.contains("It works !"),
25+
"{body_str}\nexpected to contain: It works !"
26+
);
27+
Ok(())
28+
}

0 commit comments

Comments
 (0)