use super::*;
use std::fs;
const SIMPLE_WORKFLOW: &str = r#"[workflow]
name = "test-update"
description = "Test workflow for update module"
[[step]]
name = "hello"
prompt = "Say hello"
"#;
#[test]
fn workflow_kind_from_path_detects_zipped() {
let zipped = Path::new("/tmp/thing.zwfz");
assert_eq!(WorkflowKind::from_path(zipped), WorkflowKind::Zipped);
}
#[test]
fn workflow_kind_from_path_defaults_to_plain() {
let plain = Path::new("/tmp/thing.zwf");
assert_eq!(WorkflowKind::from_path(plain), WorkflowKind::Plain);
let other = Path::new("/tmp/thing.toml");
assert_eq!(WorkflowKind::from_path(other), WorkflowKind::Plain);
}
#[test]
fn prepare_update_plain_copies_file_to_staging() {
let dir = tempfile::tempdir().unwrap();
let original = dir.path().join("simple.zwf");
fs::write(&original, SIMPLE_WORKFLOW).unwrap();
let params = prepare_update(original.to_str().unwrap()).unwrap();
assert_eq!(params.kind, WorkflowKind::Plain);
assert_eq!(params.original_path, original);
assert!(params.staging_path.exists(), "staging file should exist");
assert_ne!(
params.staging_path, original,
"staging path should differ from original"
);
let staged = fs::read_to_string(¶ms.staging_path).unwrap();
assert_eq!(staged, SIMPLE_WORKFLOW);
}
#[test]
fn prepare_update_builds_prompts_pointing_at_staging_path() {
let dir = tempfile::tempdir().unwrap();
let original = dir.path().join("prompts-check.zwf");
fs::write(&original, SIMPLE_WORKFLOW).unwrap();
let params = prepare_update(original.to_str().unwrap()).unwrap();
assert!(
params
.initial_prompt
.contains(params.staging_path.to_str().unwrap()),
"initial prompt should reference staging path"
);
assert!(
params.initial_prompt.contains("do not rename"),
"initial prompt should forbid renaming"
);
assert!(!params.system_prompt.contains("{{zwf_format_spec}}"));
assert!(!params.system_prompt.contains("{{examples_reference}}"));
assert!(params.system_prompt.contains("revision specialist"));
}
#[test]
fn prepare_update_fails_on_invalid_workflow() {
let dir = tempfile::tempdir().unwrap();
let original = dir.path().join("broken.zwf");
fs::write(&original, "this is not valid toml [[[").unwrap();
let result = prepare_update(original.to_str().unwrap());
assert!(result.is_err(), "should reject unparseable workflow");
}
#[test]
fn prepare_update_zipped_unzips_into_staging_dir() {
use std::io::Write;
let dir = tempfile::tempdir().unwrap();
let zipped = dir.path().join("zipped.zwfz");
let file = fs::File::create(&zipped).unwrap();
let mut zip_writer = zip::ZipWriter::new(file);
let options =
zip::write::SimpleFileOptions::default().compression_method(zip::CompressionMethod::Stored);
zip_writer.start_file("workflow.zwf", options).unwrap();
zip_writer.write_all(SIMPLE_WORKFLOW.as_bytes()).unwrap();
zip_writer.finish().unwrap();
let params = prepare_update(zipped.to_str().unwrap()).unwrap();
assert_eq!(params.kind, WorkflowKind::Zipped);
assert_eq!(params.original_path, zipped);
assert!(params.staging_path.exists(), "staging file should exist");
assert_eq!(
params.staging_path.extension().and_then(|s| s.to_str()),
Some("zwf")
);
let staged = fs::read_to_string(¶ms.staging_path).unwrap();
assert_eq!(staged, SIMPLE_WORKFLOW);
}
#[test]
fn commit_update_plain_writes_through_sibling_temp() {
let dir = tempfile::tempdir().unwrap();
let original = dir.path().join("commit-plain.zwf");
fs::write(&original, SIMPLE_WORKFLOW).unwrap();
let params = prepare_update(original.to_str().unwrap()).unwrap();
let edited = SIMPLE_WORKFLOW.replace("Say hello", "Say hello, world");
fs::write(¶ms.staging_path, &edited).unwrap();
commit_update(¶ms).unwrap();
let final_contents = fs::read_to_string(&original).unwrap();
assert_eq!(final_contents, edited);
let siblings: Vec<_> = fs::read_dir(dir.path())
.unwrap()
.filter_map(|e| e.ok())
.map(|e| e.file_name().to_string_lossy().to_string())
.collect();
assert!(
!siblings.iter().any(|n| n.contains(".update.")),
"no leftover sibling temp file, found: {siblings:?}"
);
}
#[test]
fn commit_update_zipped_repacks_into_place() {
use std::io::Write;
let dir = tempfile::tempdir().unwrap();
let zipped = dir.path().join("commit-zipped.zwfz");
let file = fs::File::create(&zipped).unwrap();
let mut zip_writer = zip::ZipWriter::new(file);
let options =
zip::write::SimpleFileOptions::default().compression_method(zip::CompressionMethod::Stored);
zip_writer.start_file("workflow.zwf", options).unwrap();
zip_writer.write_all(SIMPLE_WORKFLOW.as_bytes()).unwrap();
zip_writer.finish().unwrap();
let params = prepare_update(zipped.to_str().unwrap()).unwrap();
let edited = SIMPLE_WORKFLOW.replace("Say hello", "Say hello, world");
fs::write(¶ms.staging_path, &edited).unwrap();
commit_update(¶ms).unwrap();
let (wf, _source) = crate::workflow::parser::parse_workflow(&zipped).unwrap();
assert_eq!(wf.workflow.name, "test-update");
assert_eq!(wf.steps.len(), 1);
assert_eq!(wf.steps[0].prompt, "Say hello, world");
}