2022-04-27 10:51:39 +05:30
|
|
|
/*
|
|
|
|
* Copyright (C) 2022 Aravinth Manivannan <realaravinth@batsense.net>
|
|
|
|
*
|
|
|
|
* This program is free software: you can redistribute it and/or modify
|
|
|
|
* it under the terms of the GNU Affero General Public License as
|
|
|
|
* published by the Free Software Foundation, either version 3 of the
|
|
|
|
* License, or (at your option) any later version.
|
|
|
|
*
|
|
|
|
* This program is distributed in the hope that it will be useful,
|
|
|
|
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
|
|
|
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
|
|
|
* GNU Affero General Public License for more details.
|
|
|
|
*
|
|
|
|
* You should have received a copy of the GNU Affero General Public License
|
|
|
|
* along with this program. If not, see <https://www.gnu.org/licenses/>.
|
|
|
|
*/
|
2022-04-27 11:48:30 +05:30
|
|
|
use std::path::Path;
|
2022-04-27 10:51:39 +05:30
|
|
|
use std::sync::Arc;
|
|
|
|
|
2022-09-16 13:23:19 +05:30
|
|
|
use actix_web::{
|
|
|
|
body::{BoxBody, EitherBody},
|
|
|
|
dev::ServiceResponse,
|
|
|
|
error::ResponseError,
|
|
|
|
http::StatusCode,
|
|
|
|
};
|
2022-04-27 11:48:30 +05:30
|
|
|
use mktemp::Temp;
|
2022-09-16 13:23:19 +05:30
|
|
|
use serde::Serialize;
|
2022-04-27 11:48:30 +05:30
|
|
|
|
2022-09-16 13:23:19 +05:30
|
|
|
use crate::ctx::api::v1::auth::{Login, Register};
|
2022-04-27 10:51:39 +05:30
|
|
|
use crate::ctx::Ctx;
|
2022-09-16 13:23:19 +05:30
|
|
|
use crate::errors::*;
|
2022-04-27 11:48:30 +05:30
|
|
|
use crate::page::Page;
|
2022-04-27 10:51:39 +05:30
|
|
|
use crate::settings::Settings;
|
2022-09-16 13:23:19 +05:30
|
|
|
use crate::*;
|
2022-04-27 10:51:39 +05:30
|
|
|
|
2022-09-16 13:23:19 +05:30
|
|
|
pub async fn get_ctx() -> (Temp, Arc<Ctx>) {
|
2022-04-27 14:34:35 +05:30
|
|
|
// mktemp::Temp is returned because the temp directory created
|
|
|
|
// is removed once the variable goes out of scope
|
2022-04-27 11:48:30 +05:30
|
|
|
let mut settings = Settings::new().unwrap();
|
|
|
|
|
|
|
|
let tmp_dir = Temp::new_dir().unwrap();
|
|
|
|
println!("[log] Test temp directory: {}", tmp_dir.to_str().unwrap());
|
|
|
|
let mut pages = Vec::with_capacity(settings.pages.len());
|
|
|
|
for page in settings.pages.iter() {
|
|
|
|
let name = Path::new(&page.path).file_name().unwrap().to_str().unwrap();
|
2022-04-27 14:34:35 +05:30
|
|
|
let path = tmp_dir.as_path().join(name);
|
2022-04-27 11:48:30 +05:30
|
|
|
let page = Page {
|
|
|
|
path: path.to_str().unwrap().to_string(),
|
|
|
|
secret: page.secret.clone(),
|
|
|
|
branch: page.branch.clone(),
|
|
|
|
repo: page.repo.clone(),
|
2022-09-07 10:28:26 +05:30
|
|
|
domain: "mcaptcha.org".into(),
|
2022-04-27 11:48:30 +05:30
|
|
|
};
|
|
|
|
|
|
|
|
pages.push(Arc::new(page));
|
|
|
|
}
|
|
|
|
|
|
|
|
settings.pages = pages;
|
2022-09-16 13:23:19 +05:30
|
|
|
settings.init();
|
2022-04-27 11:48:30 +05:30
|
|
|
println!("[log] Initialzing settings again with test config");
|
|
|
|
settings.init();
|
|
|
|
|
2022-09-10 19:21:49 +05:30
|
|
|
(tmp_dir, Ctx::new(settings).await)
|
2022-04-27 10:51:39 +05:30
|
|
|
}
|
|
|
|
|
|
|
|
#[allow(dead_code, clippy::upper_case_acronyms)]
|
|
|
|
pub struct FORM;
|
|
|
|
|
|
|
|
#[macro_export]
|
|
|
|
macro_rules! post_request {
|
|
|
|
($uri:expr) => {
|
2022-09-16 13:23:19 +05:30
|
|
|
actix_web::test::TestRequest::post().uri($uri)
|
2022-04-27 10:51:39 +05:30
|
|
|
};
|
|
|
|
|
|
|
|
($serializable:expr, $uri:expr) => {
|
2022-09-16 13:23:19 +05:30
|
|
|
actix_web::test::TestRequest::post()
|
2022-04-27 10:51:39 +05:30
|
|
|
.uri($uri)
|
|
|
|
.insert_header((actix_web::http::header::CONTENT_TYPE, "application/json"))
|
|
|
|
.set_payload(serde_json::to_string($serializable).unwrap())
|
|
|
|
};
|
|
|
|
|
|
|
|
($serializable:expr, $uri:expr, FORM) => {
|
2022-09-16 13:23:19 +05:30
|
|
|
actix_web::test::TestRequest::post()
|
|
|
|
.uri($uri)
|
|
|
|
.set_form($serializable)
|
2022-04-27 10:51:39 +05:30
|
|
|
};
|
|
|
|
}
|
|
|
|
|
|
|
|
#[macro_export]
|
|
|
|
macro_rules! get_request {
|
|
|
|
($app:expr,$route:expr ) => {
|
|
|
|
test::call_service(&$app, test::TestRequest::get().uri($route).to_request()).await
|
|
|
|
};
|
|
|
|
|
|
|
|
($app:expr, $route:expr, $cookies:expr) => {
|
|
|
|
test::call_service(
|
|
|
|
&$app,
|
|
|
|
test::TestRequest::get()
|
|
|
|
.uri($route)
|
|
|
|
.cookie($cookies)
|
|
|
|
.to_request(),
|
|
|
|
)
|
|
|
|
.await
|
|
|
|
};
|
|
|
|
}
|
|
|
|
|
|
|
|
#[macro_export]
|
|
|
|
macro_rules! delete_request {
|
|
|
|
($app:expr,$route:expr ) => {
|
|
|
|
test::call_service(&$app, test::TestRequest::delete().uri($route).to_request()).await
|
|
|
|
};
|
|
|
|
|
|
|
|
($app:expr, $route:expr, $cookies:expr) => {
|
|
|
|
test::call_service(
|
|
|
|
&$app,
|
|
|
|
test::TestRequest::delete()
|
|
|
|
.uri($route)
|
|
|
|
.cookie($cookies)
|
|
|
|
.to_request(),
|
|
|
|
)
|
|
|
|
.await
|
|
|
|
};
|
|
|
|
}
|
|
|
|
|
|
|
|
#[macro_export]
|
|
|
|
macro_rules! get_app {
|
|
|
|
($ctx:expr) => {
|
2022-09-16 13:23:19 +05:30
|
|
|
actix_web::test::init_service(
|
|
|
|
actix_web::App::new()
|
|
|
|
.app_data($crate::get_json_err())
|
|
|
|
.wrap($crate::get_identity_service(&$ctx.settings))
|
|
|
|
.wrap(actix_web::middleware::NormalizePath::new(
|
|
|
|
actix_web::middleware::TrailingSlash::Trim,
|
|
|
|
))
|
|
|
|
.configure($crate::routes::services)
|
|
|
|
.app_data($crate::WebData::new($ctx.clone())),
|
|
|
|
)
|
2022-04-27 10:51:39 +05:30
|
|
|
};
|
|
|
|
}
|
2022-04-27 11:48:30 +05:30
|
|
|
|
|
|
|
/// Utility function to check for status of a test response, attempt response payload serialization
|
|
|
|
/// and print payload if response status doesn't match expected status
|
2022-04-27 13:47:46 +05:30
|
|
|
#[macro_export]
|
|
|
|
macro_rules! check_status {
|
|
|
|
($resp:expr, $expected:expr) => {
|
|
|
|
let status = $resp.status();
|
|
|
|
if status != $expected {
|
|
|
|
eprintln!(
|
|
|
|
"[error] Expected status code: {} received: {status}",
|
|
|
|
$expected
|
|
|
|
);
|
|
|
|
let response: serde_json::Value = actix_web::test::read_body_json($resp).await;
|
|
|
|
eprintln!("[error] Body:\n{:#?}", response);
|
|
|
|
assert_eq!(status, $expected);
|
|
|
|
panic!()
|
|
|
|
}
|
|
|
|
{
|
|
|
|
assert_eq!(status, $expected);
|
|
|
|
}
|
|
|
|
};
|
2022-04-27 11:48:30 +05:30
|
|
|
}
|
2022-09-16 13:23:19 +05:30
|
|
|
|
|
|
|
#[macro_export]
|
|
|
|
macro_rules! get_cookie {
|
|
|
|
($resp:expr) => {
|
|
|
|
$resp.response().cookies().next().unwrap().to_owned()
|
|
|
|
};
|
|
|
|
}
|
|
|
|
|
|
|
|
impl Ctx {
|
|
|
|
/// register and signin utility
|
|
|
|
pub async fn register_and_signin(
|
|
|
|
&self,
|
|
|
|
name: &str,
|
|
|
|
email: &str,
|
|
|
|
password: &str,
|
|
|
|
) -> (Login, ServiceResponse<EitherBody<BoxBody>>) {
|
|
|
|
self.register_test(name, email, password).await;
|
|
|
|
self.signin_test(name, password).await
|
|
|
|
}
|
|
|
|
|
|
|
|
pub fn to_arc(&self) -> Arc<Self> {
|
|
|
|
Arc::new(self.clone())
|
|
|
|
}
|
|
|
|
|
|
|
|
/// register utility
|
|
|
|
pub async fn register_test(&self, name: &str, email: &str, password: &str) {
|
|
|
|
let app = get_app!(self.to_arc()).await;
|
|
|
|
|
|
|
|
// 1. Register
|
|
|
|
let msg = Register {
|
|
|
|
username: name.into(),
|
|
|
|
password: password.into(),
|
|
|
|
confirm_password: password.into(),
|
|
|
|
email: email.into(),
|
|
|
|
};
|
|
|
|
println!("{:?}", msg);
|
|
|
|
let resp = actix_web::test::call_service(
|
|
|
|
&app,
|
|
|
|
post_request!(&msg, crate::V1_API_ROUTES.auth.register).to_request(),
|
|
|
|
)
|
|
|
|
.await;
|
|
|
|
// let resp_err: ErrorToResponse = actix_web::test::read_body_json(resp).await;
|
|
|
|
// panic!("{}", resp_err.error);
|
|
|
|
assert_eq!(resp.status(), StatusCode::OK);
|
|
|
|
}
|
|
|
|
|
|
|
|
/// signin util
|
|
|
|
pub async fn signin_test(
|
|
|
|
&self,
|
|
|
|
|
|
|
|
name: &str,
|
|
|
|
password: &str,
|
|
|
|
) -> (Login, ServiceResponse<EitherBody<BoxBody>>) {
|
|
|
|
let app = get_app!(self.to_arc()).await;
|
|
|
|
|
|
|
|
// 2. signin
|
|
|
|
let creds = Login {
|
|
|
|
login: name.into(),
|
|
|
|
password: password.into(),
|
|
|
|
};
|
|
|
|
let signin_resp = actix_web::test::call_service(
|
|
|
|
&app,
|
|
|
|
post_request!(&creds, V1_API_ROUTES.auth.login).to_request(),
|
|
|
|
)
|
|
|
|
.await;
|
|
|
|
assert_eq!(signin_resp.status(), StatusCode::OK);
|
|
|
|
(creds, signin_resp)
|
|
|
|
}
|
|
|
|
|
|
|
|
/// pub duplicate test
|
|
|
|
pub async fn bad_post_req_test<T: Serialize>(
|
|
|
|
&self,
|
|
|
|
|
|
|
|
name: &str,
|
|
|
|
password: &str,
|
|
|
|
url: &str,
|
|
|
|
payload: &T,
|
|
|
|
err: ServiceError,
|
|
|
|
) {
|
|
|
|
let (_, signin_resp) = self.signin_test(name, password).await;
|
|
|
|
let cookies = get_cookie!(signin_resp);
|
|
|
|
let app = get_app!(self.to_arc()).await;
|
|
|
|
|
|
|
|
let resp = actix_web::test::call_service(
|
|
|
|
&app,
|
|
|
|
post_request!(&payload, url)
|
|
|
|
.cookie(cookies.clone())
|
|
|
|
.to_request(),
|
|
|
|
)
|
|
|
|
.await;
|
|
|
|
assert_eq!(resp.status(), err.status_code());
|
|
|
|
let resp_err: ErrorToResponse = actix_web::test::read_body_json(resp).await;
|
|
|
|
//println!("{}", txt.error);
|
|
|
|
assert_eq!(resp_err.error, format!("{}", err));
|
|
|
|
}
|
|
|
|
|
|
|
|
/// bad post req test without payload
|
|
|
|
pub async fn bad_post_req_test_witout_payload(
|
|
|
|
&self,
|
|
|
|
name: &str,
|
|
|
|
password: &str,
|
|
|
|
url: &str,
|
|
|
|
err: ServiceError,
|
|
|
|
) {
|
|
|
|
let (_, signin_resp) = self.signin_test(name, password).await;
|
|
|
|
let app = get_app!(self.to_arc()).await;
|
|
|
|
let cookies = get_cookie!(signin_resp);
|
|
|
|
|
|
|
|
let resp = actix_web::test::call_service(
|
|
|
|
&app,
|
|
|
|
post_request!(url).cookie(cookies.clone()).to_request(),
|
|
|
|
)
|
|
|
|
.await;
|
|
|
|
assert_eq!(resp.status(), err.status_code());
|
|
|
|
let resp_err: ErrorToResponse = actix_web::test::read_body_json(resp).await;
|
|
|
|
//println!("{}", resp_err.error);
|
|
|
|
assert_eq!(resp_err.error, format!("{}", err));
|
|
|
|
}
|
|
|
|
}
|