use std::path::PathBuf;
use tempfile::TempDir;
use zenith_cli::commands::{new, validate};
use zenith_core::{KdlAdapter, KdlSource as _};
use zenith_session::StorePaths;
fn store_in(tmp: &TempDir) -> StorePaths {
StorePaths::new(tmp.path())
}
fn doc_path(tmp: &TempDir, name: &str) -> PathBuf {
tmp.path().join(name)
}
#[test]
fn creates_valid_document_with_doc_id() {
let tmp = TempDir::new().unwrap();
let paths = store_in(&tmp);
let path = doc_path(&tmp, "poster.zen");
let result = new::run_in(&paths, &path, Some("Launch Poster")).expect("new must succeed");
assert_eq!(
result.doc_id.len(),
26,
"doc-id must be a 26-char ULID; got {:?}",
result.doc_id
);
let bytes = std::fs::read(&path).expect("created file must exist");
let doc = KdlAdapter.parse(&bytes).expect("created file must parse");
assert_eq!(doc.doc_id.as_deref(), Some(result.doc_id.as_str()));
let src = String::from_utf8(bytes).expect("utf8");
let out = validate::run(
&src,
path.parent(),
false,
&zenith_cli::config::CliPolicyFlags::default(),
);
assert_eq!(
out.exit_code, 0,
"scaffolded document must validate clean; got:\n{}",
out.stdout
);
}
#[test]
fn refuses_to_overwrite_existing_file() {
let tmp = TempDir::new().unwrap();
let paths = store_in(&tmp);
let path = doc_path(&tmp, "exists.zen");
std::fs::write(&path, b"ORIGINAL").unwrap();
let err = new::run_in(&paths, &path, None).expect_err("must refuse to overwrite");
assert_ne!(err.exit_code, 0, "overwrite refusal must be non-zero exit");
assert!(
err.message.contains("refusing to overwrite"),
"message must explain the refusal; got: {}",
err.message
);
let on_disk = std::fs::read(&path).unwrap();
assert_eq!(on_disk, b"ORIGINAL", "existing file must be left untouched");
}
#[test]
fn slug_derives_from_name() {
let tmp = TempDir::new().unwrap();
let paths = store_in(&tmp);
let path = doc_path(&tmp, "whatever.zen");
new::run_in(&paths, &path, Some("Acme Brand")).expect("new must succeed");
let src = std::fs::read_to_string(&path).unwrap();
assert!(
src.contains("doc.acme-brand"),
"doc id from name; got:\n{src}"
);
assert!(
src.contains("proj.acme-brand"),
"proj id from name; got:\n{src}"
);
}
#[test]
fn slug_derives_from_file_stem() {
let tmp = TempDir::new().unwrap();
let paths = store_in(&tmp);
let path = doc_path(&tmp, "my-flyer.zen");
new::run_in(&paths, &path, None).expect("new must succeed");
let src = std::fs::read_to_string(&path).unwrap();
assert!(
src.contains("doc.my-flyer"),
"doc id from stem; got:\n{src}"
);
assert!(src.contains("Untitled"), "default title; got:\n{src}");
}
#[test]
fn appends_zen_extension_when_absent() {
let tmp = TempDir::new().unwrap();
let paths = store_in(&tmp);
let path = doc_path(&tmp, "poster");
let result = new::run_in(&paths, &path, Some("Poster")).expect("new must succeed");
let expected = tmp.path().join("poster.zen");
assert_eq!(result.path, expected, "must append .zen");
assert!(expected.exists(), "poster.zen must be created");
assert!(
!path.exists(),
"the extension-less path must not be created"
);
}
#[test]
fn creates_missing_parent_directories() {
let tmp = TempDir::new().unwrap();
let paths = store_in(&tmp);
let path = tmp.path().join("sub").join("deep").join("doc.zen");
new::run_in(&paths, &path, Some("Deep")).expect("new must create parent dirs");
assert!(path.exists(), "doc.zen must be created in the new subtree");
}
#[test]
fn rejects_directory_path() {
let tmp = TempDir::new().unwrap();
let paths = store_in(&tmp);
let dir = tmp.path().join("adir");
std::fs::create_dir(&dir).unwrap();
let err = new::run_in(&paths, &dir, None).expect_err("must reject a directory");
assert_ne!(err.exit_code, 0);
assert!(
err.message.contains("is a directory"),
"message must identify a directory; got: {}",
err.message
);
}