web: add unit tests
parent
1af4579519
commit
c4f7ea1822
|
@ -2019,14 +2019,17 @@ dependencies = [
|
|||
"axum-sessions",
|
||||
"build-info",
|
||||
"build-info-build",
|
||||
"cfg-if 1.0.0",
|
||||
"chrono",
|
||||
"convert_case",
|
||||
"dyn-clone",
|
||||
"eyre",
|
||||
"http",
|
||||
"hyper",
|
||||
"indexmap",
|
||||
"lazy_static",
|
||||
"mailpot",
|
||||
"mailpot-tests",
|
||||
"minijinja",
|
||||
"percent-encoding",
|
||||
"rand",
|
||||
|
@ -2034,6 +2037,7 @@ dependencies = [
|
|||
"serde_json",
|
||||
"tempfile",
|
||||
"tokio",
|
||||
"tower",
|
||||
"tower-http 0.3.5",
|
||||
"tower-service",
|
||||
"zstd",
|
||||
|
|
|
@ -14,16 +14,13 @@ categories = ["email"]
|
|||
name = "mpot-web"
|
||||
path = "src/main.rs"
|
||||
|
||||
[features]
|
||||
default = ["zstd"]
|
||||
zstd = ["dep:zstd"]
|
||||
|
||||
[dependencies]
|
||||
axum = { version = "^0.6" }
|
||||
axum-extra = { version = "^0.7", features = ["typed-routing"] }
|
||||
axum-login = { version = "^0.5" }
|
||||
axum-sessions = { version = "^0.5" }
|
||||
build-info = { version = "0.0.31" }
|
||||
cfg-if = { version = "1" }
|
||||
chrono = { version = "^0.4" }
|
||||
convert_case = { version = "^0.4" }
|
||||
dyn-clone = { version = "^1" }
|
||||
|
@ -41,8 +38,14 @@ tempfile = { version = "^3.5" }
|
|||
tokio = { version = "1", features = ["full"] }
|
||||
tower-http = { version = "^0.3" }
|
||||
tower-service = { version = "^0.3" }
|
||||
zstd = { version = "0.12.3", optional = true, default-features = false }
|
||||
zstd = { version = "0.12", default-features = false }
|
||||
|
||||
[dev-dependencies]
|
||||
hyper = { version = "0.14" }
|
||||
mailpot-tests = { version = "^0.1", path = "../mailpot-tests" }
|
||||
tempfile = "3.3"
|
||||
tower = { version = "^0.4" }
|
||||
|
||||
[build-dependencies]
|
||||
build-info-build = { version = "0.0.31" }
|
||||
zstd = { version = "0.12.3", optional = true, default-features = false }
|
||||
zstd = { version = "0.12", default-features = false }
|
||||
|
|
|
@ -4,9 +4,7 @@
|
|||
cargo run --bin mpot-web -- /path/to/conf.toml
|
||||
```
|
||||
|
||||
By default on release builds templates are compressed with `zstd` and bundled in the binary.
|
||||
|
||||
You can disable this behavior by disabling the `zstd` feature: `cargo build --release --no-default-features`
|
||||
Templates are compressed with `zstd` and bundled in the binary.
|
||||
|
||||
## Configuration
|
||||
|
||||
|
|
|
@ -44,7 +44,6 @@ fn commit_sha() {
|
|||
}
|
||||
}
|
||||
|
||||
#[cfg(feature = "zstd")]
|
||||
fn main() -> Result<(), Box<dyn std::error::Error>> {
|
||||
// Embed HTML templates as zstd compressed byte slices into binary.
|
||||
// [tag:embed_templates]
|
||||
|
@ -104,8 +103,3 @@ fn main() -> Result<(), Box<dyn std::error::Error>> {
|
|||
commit_sha();
|
||||
Ok(())
|
||||
}
|
||||
|
||||
#[cfg(not(feature = "zstd"))]
|
||||
fn main() {
|
||||
commit_sha();
|
||||
}
|
||||
|
|
108
web/src/main.rs
108
web/src/main.rs
|
@ -26,19 +26,7 @@ use minijinja::value::Value;
|
|||
use rand::Rng;
|
||||
use tokio::sync::RwLock;
|
||||
|
||||
#[tokio::main]
|
||||
async fn main() {
|
||||
let config_path = std::env::args()
|
||||
.nth(1)
|
||||
.expect("Expected configuration file path as first argument.");
|
||||
if ["-v", "--version", "info"].contains(&config_path.as_str()) {
|
||||
println!("{}", crate::get_git_sha());
|
||||
println!("{CLI_INFO}");
|
||||
|
||||
return;
|
||||
}
|
||||
let conf = Configuration::from_file(config_path).unwrap();
|
||||
|
||||
fn create_app(conf: Configuration) -> Router {
|
||||
let store = MemoryStore::new();
|
||||
let secret = rand::thread_rng().gen::<[u8; 128]>();
|
||||
let session_layer = SessionLayer::new(store, &secret).with_secure(false);
|
||||
|
@ -60,7 +48,7 @@ async fn main() {
|
|||
|
||||
let login_url =
|
||||
Arc::new(format!("{}{}", shared_state.root_url_prefix, LoginPath.to_crumb()).into());
|
||||
let app = Router::new()
|
||||
Router::new()
|
||||
.route("/", get(root))
|
||||
.typed_get(list)
|
||||
.typed_get(list_post)
|
||||
|
@ -152,7 +140,22 @@ async fn main() {
|
|||
)
|
||||
.layer(auth_layer)
|
||||
.layer(session_layer)
|
||||
.with_state(shared_state);
|
||||
.with_state(shared_state)
|
||||
}
|
||||
|
||||
#[tokio::main]
|
||||
async fn main() {
|
||||
let config_path = std::env::args()
|
||||
.nth(1)
|
||||
.expect("Expected configuration file path as first argument.");
|
||||
if ["-v", "--version", "info"].contains(&config_path.as_str()) {
|
||||
println!("{}", crate::get_git_sha());
|
||||
println!("{CLI_INFO}");
|
||||
|
||||
return;
|
||||
}
|
||||
let conf = Configuration::from_file(config_path).unwrap();
|
||||
let app = create_app(conf);
|
||||
|
||||
let hostname = std::env::var("HOSTNAME").unwrap_or_else(|_| "0.0.0.0".to_string());
|
||||
let port = std::env::var("PORT").unwrap_or_else(|_| "3000".to_string());
|
||||
|
@ -206,3 +209,78 @@ async fn root(
|
|||
};
|
||||
Ok(Html(TEMPLATES.get_template("lists.html")?.render(context)?))
|
||||
}
|
||||
|
||||
#[cfg(test)]
|
||||
mod tests {
|
||||
|
||||
use axum::{
|
||||
body::Body,
|
||||
http::{method::Method, Request, StatusCode},
|
||||
};
|
||||
use mailpot::{Configuration, Connection, SendMail};
|
||||
use mailpot_tests::init_stderr_logging;
|
||||
use tempfile::TempDir;
|
||||
use tower::ServiceExt;
|
||||
|
||||
use super::*;
|
||||
|
||||
#[tokio::test]
|
||||
async fn test_routes() {
|
||||
init_stderr_logging();
|
||||
|
||||
let tmp_dir = TempDir::new().unwrap();
|
||||
|
||||
let db_path = tmp_dir.path().join("mpot.db");
|
||||
std::fs::copy("../mailpot-tests/for_testing.db", &db_path).unwrap();
|
||||
let config = Configuration {
|
||||
send_mail: SendMail::ShellCommand("/usr/bin/false".to_string()),
|
||||
db_path,
|
||||
data_path: tmp_dir.path().to_path_buf(),
|
||||
administrators: vec![],
|
||||
};
|
||||
let db = Connection::open_db(config.clone()).unwrap();
|
||||
let list = db.lists().unwrap().remove(0);
|
||||
|
||||
// ------------------------------------------------------------
|
||||
// list()
|
||||
|
||||
let cl = |url, config| async move {
|
||||
let response = create_app(config)
|
||||
.oneshot(
|
||||
Request::builder()
|
||||
.uri(&url)
|
||||
.method(Method::GET)
|
||||
.body(Body::empty())
|
||||
.unwrap(),
|
||||
)
|
||||
.await
|
||||
.unwrap();
|
||||
|
||||
assert_eq!(response.status(), StatusCode::OK);
|
||||
|
||||
hyper::body::to_bytes(response.into_body()).await.unwrap()
|
||||
};
|
||||
assert_eq!(
|
||||
cl(format!("/list/{}/", list.id), config.clone()).await,
|
||||
cl(format!("/list/{}/", list.pk), config.clone()).await
|
||||
);
|
||||
|
||||
// ------------------------------------------------------------
|
||||
// help(), ssh_signin(), root()
|
||||
|
||||
for path in ["/help/", "/login/", "/"] {
|
||||
let response = create_app(config.clone())
|
||||
.oneshot(
|
||||
Request::builder()
|
||||
.uri(path)
|
||||
.method(Method::GET)
|
||||
.body(Body::empty())
|
||||
.unwrap(),
|
||||
)
|
||||
.await
|
||||
.unwrap();
|
||||
|
||||
assert_eq!(response.status(), StatusCode::OK);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -21,8 +21,6 @@
|
|||
|
||||
use super::*;
|
||||
|
||||
#[cfg(feature = "zstd")]
|
||||
#[cfg(not(debug_assertions))]
|
||||
mod compressed;
|
||||
|
||||
lazy_static::lazy_static! {
|
||||
|
@ -54,28 +52,16 @@ lazy_static::lazy_static! {
|
|||
post_eml_path
|
||||
);
|
||||
add!(filter pluralize);
|
||||
#[cfg(not(feature = "zstd"))]
|
||||
#[cfg(debug_assertions)]
|
||||
env.set_source(minijinja::Source::from_path("web/src/templates/"));
|
||||
#[cfg(feature = "zstd")]
|
||||
#[cfg(debug_assertions)]
|
||||
env.set_source(minijinja::Source::from_path("web/src/templates/"));
|
||||
#[cfg(not(feature = "zstd"))]
|
||||
#[cfg(not(debug_assertions))]
|
||||
env.set_source(minijinja::Source::from_path("web/src/templates/"));
|
||||
#[cfg(feature = "zstd")]
|
||||
#[cfg(not(debug_assertions))]
|
||||
{
|
||||
// Load compressed templates. They are constructed in build.rs. See
|
||||
// [ref:embed_templates]
|
||||
let mut source = minijinja::Source::new();
|
||||
for (name, bytes) in compressed::COMPRESSED {
|
||||
let mut de_bytes = vec![];
|
||||
zstd::stream::copy_decode(*bytes,&mut de_bytes).unwrap();
|
||||
source.add_template(*name, String::from_utf8(de_bytes).unwrap()).unwrap();
|
||||
}
|
||||
env.set_source(source);
|
||||
// Load compressed templates. They are constructed in build.rs. See
|
||||
// [ref:embed_templates]
|
||||
let mut source = minijinja::Source::new();
|
||||
for (name, bytes) in compressed::COMPRESSED {
|
||||
let mut de_bytes = vec![];
|
||||
zstd::stream::copy_decode(*bytes,&mut de_bytes).unwrap();
|
||||
source.add_template(*name, String::from_utf8(de_bytes).unwrap()).unwrap();
|
||||
}
|
||||
env.set_source(source);
|
||||
|
||||
env.add_global("root_url_prefix", Value::from_safe_string( std::env::var("ROOT_URL_PREFIX").unwrap_or_default()));
|
||||
env.add_global("public_url",Value::from_safe_string(std::env::var("PUBLIC_URL").unwrap_or_default()));
|
||||
env.add_global("site_title", Value::from_safe_string(std::env::var("SITE_TITLE").unwrap_or_else(|_| "mailing list archive".to_string())));
|
||||
|
|
Loading…
Reference in New Issue