use std::fs;
use std::time::Duration;
use mini_static::Server;
use tempfile::TempDir;
#[tokio::test]
async fn js_source_folder_minifies_per_file_into_output() {
let src = TempDir::new().unwrap();
let out = TempDir::new().unwrap();
let source_js = "const greeting = 'hello';\n\nfunction greet() {\n console.log(greeting);\n}\n\ngreet();\n";
fs::write(src.path().join("app.js"), source_js).unwrap();
let server = Server::new(out.path())
.unwrap()
.with_source_folder(src.path())
.unwrap();
let (_port, handle) = server.run_ephemeral().await.unwrap();
tokio::time::sleep(Duration::from_millis(200)).await;
let out_js = fs::read(out.path().join("app.js")).unwrap();
assert!(
!out_js.is_empty(),
"expected a mirrored minified app.js in the output dir"
);
assert!(
out_js.len() < source_js.len(),
"expected minified output ({} bytes) to be smaller than source ({} bytes)",
out_js.len(),
source_js.len()
);
handle.shutdown().await;
}
#[tokio::test]
async fn js_source_change_rebuilds_the_changed_file() {
let src = TempDir::new().unwrap();
let out = TempDir::new().unwrap();
fs::write(src.path().join("app.js"), "const value = 1;\n").unwrap();
let server = Server::new(out.path())
.unwrap()
.with_live_reload()
.with_source_folder(src.path())
.unwrap();
let (_port, handle) = server.run_ephemeral().await.unwrap();
tokio::time::sleep(Duration::from_millis(800)).await;
fs::write(src.path().join("app.js"), "const value = 2;\n").unwrap();
tokio::time::sleep(Duration::from_millis(1500)).await;
let out_js = fs::read_to_string(out.path().join("app.js")).unwrap();
assert!(
out_js.contains("value=2"),
"expected the changed source to be re-minified into the output, got: {out_js}"
);
handle.shutdown().await;
}
#[tokio::test]
async fn malformed_js_source_degrades_to_raw_output() {
let src = TempDir::new().unwrap();
let out = TempDir::new().unwrap();
let malformed = b"function( {{{ !!!";
fs::write(src.path().join("broken.js"), malformed).unwrap();
let server = Server::new(out.path())
.unwrap()
.with_source_folder(src.path())
.unwrap();
let (_port, handle) = server.run_ephemeral().await.unwrap();
tokio::time::sleep(Duration::from_millis(200)).await;
let out_js = fs::read(out.path().join("broken.js")).unwrap();
assert_eq!(
out_js, malformed,
"a file the minifier cannot parse must still be mirrored (raw) so the page stays in sync"
);
handle.shutdown().await;
}
#[tokio::test]
async fn prune_output_removes_stale_css_bundle_when_no_css_sources_remain() {
let src = TempDir::new().unwrap();
let out = TempDir::new().unwrap();
fs::write(out.path().join("styles.css"), "/* stale */").unwrap();
let server = Server::new(out.path())
.unwrap()
.with_source_folder(src.path())
.unwrap()
.with_css_bundle()
.with_prune_output();
let (_port, handle) = server.run_ephemeral().await.unwrap();
tokio::time::sleep(Duration::from_millis(200)).await;
assert!(
!out.path().join("styles.css").exists(),
"prune is opt-in: with_prune_output should delete the stale bundle produced by no css sources"
);
handle.shutdown().await;
}
#[tokio::test]
async fn without_prune_stale_css_bundle_is_left_in_place() {
let src = TempDir::new().unwrap();
let out = TempDir::new().unwrap();
fs::write(out.path().join("styles.css"), "/* stale */").unwrap();
let server = Server::new(out.path())
.unwrap()
.with_source_folder(src.path())
.unwrap()
.with_css_bundle();
let (_port, handle) = server.run_ephemeral().await.unwrap();
tokio::time::sleep(Duration::from_millis(200)).await;
assert!(
out.path().join("styles.css").exists(),
"without with_prune_output the stale bundle must be left in place"
);
handle.shutdown().await;
}