use super::*;
use std::fs;
use tempfile::TempDir;
#[test]
fn a_source_folder_overlapping_the_output_dir_is_rejected() {
let out = TempDir::new().unwrap();
let nested = out.path().join("styles");
fs::create_dir(&nested).unwrap();
let result = Builder::new(out.path()).unwrap().source_folder(&nested);
assert!(
matches!(result, Err(BuildError::Config(_))),
"a source folder under the output dir must be refused"
);
}
#[test]
fn an_output_dir_inside_a_source_folder_is_rejected() {
let src = TempDir::new().unwrap();
let out = src.path().join("public");
fs::create_dir(&out).unwrap();
let result = Builder::new(&out).unwrap().source_folder(src.path());
assert!(
matches!(result, Err(BuildError::Config(_))),
"overlap must be caught in both directions, not just one"
);
}
#[test]
fn two_overlapping_input_folders_are_rejected() {
let out = TempDir::new().unwrap();
let src = TempDir::new().unwrap();
let nested = src.path().join("nested");
fs::create_dir(&nested).unwrap();
let result = Builder::new(out.path())
.unwrap()
.source_folder(src.path())
.unwrap()
.asset_folder(&nested);
assert!(matches!(result, Err(BuildError::Config(_))));
}
#[test]
fn disjoint_folders_are_accepted() {
let out = TempDir::new().unwrap();
let src = TempDir::new().unwrap();
let assets = TempDir::new().unwrap();
let builder = Builder::new(out.path())
.unwrap()
.source_folder(src.path())
.unwrap()
.asset_folder(assets.path());
assert!(builder.is_ok());
}
#[test]
fn a_missing_folder_is_an_io_error_not_a_config_error() {
let out = TempDir::new().unwrap();
let result = Builder::new(out.path())
.unwrap()
.source_folder(Path::new("/definitely/not/here"));
assert!(
matches!(result, Err(BuildError::Io(_))),
"a nonexistent path is an I/O problem, distinct from a rejected relationship"
);
}
#[test]
fn a_js_entry_outside_every_source_folder_is_rejected() {
let out = TempDir::new().unwrap();
let src = TempDir::new().unwrap();
let stray = TempDir::new().unwrap();
let entry = stray.path().join("main.js");
fs::write(&entry, b"export default 1;").unwrap();
let result = Builder::new(out.path())
.unwrap()
.source_folder(src.path())
.unwrap()
.js_tool(
JsTool::Esbuild,
JsOptions::default().bundle_entry(&entry, "bundle.js"),
);
assert!(matches!(result, Err(BuildError::Config(_))));
}
#[test]
fn a_js_entry_under_a_source_folder_is_accepted() {
let out = TempDir::new().unwrap();
let src = TempDir::new().unwrap();
let entry = src.path().join("main.js");
fs::write(&entry, b"export default 1;").unwrap();
let result = Builder::new(out.path())
.unwrap()
.source_folder(src.path())
.unwrap()
.js_tool(
JsTool::Esbuild,
JsOptions::default().bundle_entry(&entry, "bundle.js"),
);
assert!(result.is_ok());
}
#[test]
fn a_missing_tool_binary_fails_before_any_output_is_written() {
let out = TempDir::new().unwrap();
let src = TempDir::new().unwrap();
fs::write(src.path().join("a.css"), b"body{color:red}").unwrap();
let result = Builder::new(out.path())
.unwrap()
.source_folder(src.path())
.unwrap()
.css_tool(CssTool::TestMissing, CssOptions::default().minify(true))
.build();
assert!(
matches!(result, Err(BuildError::ToolMissing(_))),
"expected ToolMissing, got: {result:?}"
);
assert_eq!(
fs::read_dir(out.path()).unwrap().count(),
0,
"nothing may be written when a required tool is absent"
);
}
#[test]
fn a_passthrough_tool_does_not_require_its_binary() {
let out = TempDir::new().unwrap();
let src = TempDir::new().unwrap();
fs::write(src.path().join("a.css"), b"body{color:red}").unwrap();
let result = Builder::new(out.path())
.unwrap()
.source_folder(src.path())
.unwrap()
.css_tool(
CssTool::TestMissing,
CssOptions::default().bundle(false).minify(false),
)
.build();
assert!(
result.is_ok(),
"passthrough must not need a binary: {result:?}"
);
assert_eq!(
fs::read(out.path().join("a.css")).unwrap(),
b"body{color:red}",
"passthrough copies the source byte-for-byte"
);
}