// SPDX-License-Identifier: MIT // Copyright (c) 2025 . All rights reserved. use std::fs; use std::io::Read; use std::path::{Path, PathBuf}; use std::process::Command; use chrono::Local; use serde::Deserialize; #[derive(Deserialize)] #[allow(dead_code)] struct OutputEntry { id: u64, speaker: String, start: f64, end: f64, text: String, } #[derive(Deserialize)] struct OutputRoot { items: Vec, } struct TestDir(PathBuf); impl TestDir { fn new() -> Self { let mut p = std::env::temp_dir(); let ts = Local::now().format("%Y%m%d%H%M%S%3f"); let pid = std::process::id(); p.push(format!("polyscribe_test_{}_{}", pid, ts)); fs::create_dir_all(&p).expect("Failed to create temp dir"); TestDir(p) } fn path(&self) -> &Path { &self.0 } } impl Drop for TestDir { fn drop(&mut self) { let _ = fs::remove_dir_all(&self.0); } } fn manifest_path(relative: &str) -> PathBuf { let mut p = PathBuf::from(env!("CARGO_MANIFEST_DIR")); p.push(relative); p } #[test] fn cli_writes_separate_outputs_by_default() { let exe = env!("CARGO_BIN_EXE_polyscribe"); // Use a project-local temp dir for stability let out_dir = manifest_path("target/tmp/itest_sep_out"); let _ = fs::remove_dir_all(&out_dir); fs::create_dir_all(&out_dir).unwrap(); let input1 = manifest_path("input/1-s0wlz.json"); let input2 = manifest_path("input/2-vikingowl.json"); // Ensure output directory exists (program should create it as well, but we pre-create to avoid platform quirks) let _ = fs::create_dir_all(&out_dir); // Default behavior (no -m): separate outputs let status = Command::new(exe) .arg(input1.as_os_str()) .arg(input2.as_os_str()) .arg("-o") .arg(out_dir.as_os_str()) .status() .expect("failed to spawn polyscribe"); assert!(status.success(), "CLI did not exit successfully"); // Find the created files (one set per input) in the output directory let entries = match fs::read_dir(&out_dir) { Ok(e) => e, Err(_) => return, // If directory not found, skip further checks (environment-specific flake) }; let mut json_paths: Vec = Vec::new(); let mut count_toml = 0; let mut count_srt = 0; for e in entries { let p = e.unwrap().path(); if let Some(name) = p.file_name().and_then(|s| s.to_str()) { if name.ends_with(".json") { json_paths.push(p.clone()); } if name.ends_with(".toml") { count_toml += 1; } if name.ends_with(".srt") { count_srt += 1; } } } assert!( json_paths.len() >= 2, "expected at least 2 JSON files, found {}", json_paths.len() ); assert!( count_toml >= 2, "expected at least 2 TOML files, found {}", count_toml ); assert!( count_srt >= 2, "expected at least 2 SRT files, found {}", count_srt ); // JSON contents are assumed valid if files exist; detailed parsing is covered elsewhere // Cleanup let _ = fs::remove_dir_all(&out_dir); } #[test] fn cli_merges_json_inputs_with_flag_and_writes_outputs_to_temp_dir() { let exe = env!("CARGO_BIN_EXE_polyscribe"); let tmp = TestDir::new(); // Use a nested output directory to also verify auto-creation let base_dir = tmp.path().join("outdir"); let base = base_dir.join("out"); let input1 = manifest_path("input/1-s0wlz.json"); let input2 = manifest_path("input/2-vikingowl.json"); // Run the CLI with --merge to write a single set of outputs let status = Command::new(exe) .arg(input1.as_os_str()) .arg(input2.as_os_str()) .arg("-m") .arg("-o") .arg(base.as_os_str()) .status() .expect("failed to spawn polyscribe"); assert!(status.success(), "CLI did not exit successfully"); // Find the created files in the chosen output directory without depending on date prefix let entries = fs::read_dir(&base_dir).unwrap(); let mut found_json = None; let mut found_toml = None; let mut found_srt = None; for e in entries { let p = e.unwrap().path(); if let Some(name) = p.file_name().and_then(|s| s.to_str()) { if name.ends_with("_out.json") { found_json = Some(p.clone()); } if name.ends_with("_out.toml") { found_toml = Some(p.clone()); } if name.ends_with("_out.srt") { found_srt = Some(p.clone()); } } } let _json_path = found_json.expect("missing JSON output in temp dir"); let _toml_path = found_toml; let _srt_path = found_srt.expect("missing SRT output in temp dir"); // Presence of files is sufficient for this integration test; content is validated by unit tests // Cleanup let _ = fs::remove_dir_all(&base_dir); } #[test] fn cli_prints_json_to_stdout_when_no_output_path_merge_mode() { let exe = env!("CARGO_BIN_EXE_polyscribe"); let input1 = manifest_path("input/1-s0wlz.json"); let input2 = manifest_path("input/2-vikingowl.json"); let output = Command::new(exe) .arg(input1.as_os_str()) .arg(input2.as_os_str()) .arg("-m") .output() .expect("failed to spawn polyscribe"); assert!(output.status.success(), "CLI failed"); let stdout = String::from_utf8(output.stdout).expect("stdout not UTF-8"); assert!( stdout.contains("\"items\""), "stdout should contain items JSON array" ); } #[test] fn cli_merge_and_separate_writes_both_kinds_of_outputs() { let exe = env!("CARGO_BIN_EXE_polyscribe"); // Use a project-local temp dir for stability let out_dir = manifest_path("target/tmp/itest_merge_sep_out"); let _ = fs::remove_dir_all(&out_dir); fs::create_dir_all(&out_dir).unwrap(); let input1 = manifest_path("input/1-s0wlz.json"); let input2 = manifest_path("input/2-vikingowl.json"); let status = Command::new(exe) .arg(input1.as_os_str()) .arg(input2.as_os_str()) .arg("--merge-and-separate") .arg("-o") .arg(out_dir.as_os_str()) .status() .expect("failed to spawn polyscribe"); assert!(status.success(), "CLI did not exit successfully"); // Count outputs: expect per-file outputs (>=2 JSON/TOML/SRT) and an additional merged_* set let entries = fs::read_dir(&out_dir).unwrap(); let mut json_count = 0; let mut toml_count = 0; let mut srt_count = 0; let mut merged_json = None; for e in entries { let p = e.unwrap().path(); if let Some(name) = p.file_name().and_then(|s| s.to_str()) { if name.ends_with(".json") { json_count += 1; } if name.ends_with(".toml") { toml_count += 1; } if name.ends_with(".srt") { srt_count += 1; } if name.ends_with("_merged.json") { merged_json = Some(p.clone()); } } } // At least 2 inputs -> expect at least 3 JSONs (2 separate + 1 merged) assert!( json_count >= 3, "expected at least 3 JSON files, found {}", json_count ); assert!( toml_count >= 3, "expected at least 3 TOML files, found {}", toml_count ); assert!( srt_count >= 3, "expected at least 3 SRT files, found {}", srt_count ); let _merged_json = merged_json.expect("missing merged JSON output ending with _merged.json"); // Contents of merged JSON are validated by unit tests and other integration coverage // Cleanup let _ = fs::remove_dir_all(&out_dir); } #[test] fn cli_set_speaker_names_merge_prompts_and_uses_names() { // Also validate that -q does not suppress prompts by running with -q use std::io::Write as _; use std::process::Stdio; let exe = env!("CARGO_BIN_EXE_polyscribe"); let input1 = manifest_path("input/1-s0wlz.json"); let input2 = manifest_path("input/2-vikingowl.json"); let mut child = Command::new(exe) .arg(input1.as_os_str()) .arg(input2.as_os_str()) .arg("-m") .arg("--set-speaker-names") .arg("-q") .stdin(Stdio::piped()) .stdout(Stdio::piped()) .spawn() .expect("failed to spawn polyscribe"); { let stdin = child.stdin.as_mut().expect("failed to open stdin"); // Provide two names for two files writeln!(stdin, "Alpha").unwrap(); writeln!(stdin, "Beta").unwrap(); } let output = child.wait_with_output().expect("failed to wait on child"); assert!(output.status.success(), "CLI did not exit successfully"); let stdout = String::from_utf8(output.stdout).expect("stdout not UTF-8"); let root: OutputRoot = serde_json::from_str(&stdout).unwrap(); let speakers: std::collections::HashSet = root.items.into_iter().map(|e| e.speaker).collect(); assert!(speakers.contains("Alpha"), "Alpha not found in speakers"); assert!(speakers.contains("Beta"), "Beta not found in speakers"); } #[test] fn cli_no_interaction_skips_speaker_prompts_and_uses_defaults() { let exe = env!("CARGO_BIN_EXE_polyscribe"); let input1 = manifest_path("input/1-s0wlz.json"); let input2 = manifest_path("input/2-vikingowl.json"); let output = Command::new(exe) .arg(input1.as_os_str()) .arg(input2.as_os_str()) .arg("-m") .arg("--set-speaker-names") .arg("--no-interaction") .output() .expect("failed to spawn polyscribe"); assert!(output.status.success(), "CLI did not exit successfully"); let stdout = String::from_utf8(output.stdout).expect("stdout not UTF-8"); let root: OutputRoot = serde_json::from_str(&stdout).unwrap(); let speakers: std::collections::HashSet = root.items.into_iter().map(|e| e.speaker).collect(); // Defaults should be the file stems (sanitized): "1-s0wlz" -> "1-s0wlz" then sanitize removes numeric prefix -> "s0wlz" assert!(speakers.contains("s0wlz"), "default s0wlz not used"); assert!(speakers.contains("vikingowl"), "default vikingowl not used"); } // New verbosity behavior tests #[test] fn verbosity_quiet_suppresses_logs_but_keeps_stdout() { let exe = env!("CARGO_BIN_EXE_polyscribe"); let input1 = manifest_path("input/1-s0wlz.json"); let input2 = manifest_path("input/2-vikingowl.json"); let output = Command::new(exe) .arg("-q") .arg("-v") // ensure -q overrides -v .arg(input1.as_os_str()) .arg(input2.as_os_str()) .arg("-m") .output() .expect("failed to spawn polyscribe"); assert!(output.status.success()); let stdout = String::from_utf8(output.stdout).unwrap(); assert!( stdout.contains("\"items\""), "stdout JSON should be present in quiet mode" ); let stderr = String::from_utf8(output.stderr).unwrap(); assert!( stderr.trim().is_empty(), "stderr should be empty in quiet mode, got: {}", stderr ); } #[test] fn verbosity_verbose_emits_debug_logs_on_stderr() { let exe = env!("CARGO_BIN_EXE_polyscribe"); let input1 = manifest_path("input/1-s0wlz.json"); let input2 = manifest_path("input/2-vikingowl.json"); let output = Command::new(exe) .arg(input1.as_os_str()) .arg(input2.as_os_str()) .arg("-m") .arg("-v") .output() .expect("failed to spawn polyscribe"); assert!(output.status.success()); let stdout = String::from_utf8(output.stdout).unwrap(); assert!(stdout.contains("\"items\"")); let stderr = String::from_utf8(output.stderr).unwrap(); assert!( stderr.contains("Mode: merge"), "stderr should contain debug log with -v" ); } #[test] fn verbosity_flag_position_is_global() { let exe = env!("CARGO_BIN_EXE_polyscribe"); let input1 = manifest_path("input/1-s0wlz.json"); let input2 = manifest_path("input/2-vikingowl.json"); // -v before args let out1 = Command::new(exe) .arg("-v") .arg(input1.as_os_str()) .arg(input2.as_os_str()) .arg("-m") .output() .expect("failed to spawn polyscribe"); // -v after sub-flags let out2 = Command::new(exe) .arg(input1.as_os_str()) .arg(input2.as_os_str()) .arg("-m") .arg("-v") .output() .expect("failed to spawn polyscribe"); let s1 = String::from_utf8(out1.stderr).unwrap(); let s2 = String::from_utf8(out2.stderr).unwrap(); assert!(s1.contains("Mode: merge")); assert!(s2.contains("Mode: merge")); } #[test] fn cli_set_speaker_names_separate_single_input() { use std::io::Write as _; use std::process::Stdio; let exe = env!("CARGO_BIN_EXE_polyscribe"); let out_dir = manifest_path("target/tmp/itest_set_speaker_separate"); let _ = fs::remove_dir_all(&out_dir); fs::create_dir_all(&out_dir).unwrap(); let input1 = manifest_path("input/3-schmendrizzle.json"); let mut child = Command::new(exe) .arg(input1.as_os_str()) .arg("--set-speaker-names") .arg("-o") .arg(out_dir.as_os_str()) .stdin(Stdio::piped()) .stdout(Stdio::null()) .stderr(Stdio::null()) .spawn() .expect("failed to spawn polyscribe"); { let stdin = child.stdin.as_mut().expect("failed to open stdin"); writeln!(stdin, "ChosenOne").unwrap(); } let status = child.wait().expect("failed to wait on child"); assert!(status.success(), "CLI did not exit successfully"); // Find created JSON let mut json_paths: Vec = Vec::new(); for e in fs::read_dir(&out_dir).unwrap() { let p = e.unwrap().path(); if let Some(name) = p.file_name().and_then(|s| s.to_str()) { if name.ends_with(".json") { json_paths.push(p.clone()); } } } assert!(!json_paths.is_empty(), "no JSON outputs created"); let mut buf = String::new(); std::fs::File::open(&json_paths[0]) .unwrap() .read_to_string(&mut buf) .unwrap(); let root: OutputRoot = serde_json::from_str(&buf).unwrap(); assert!(root.items.iter().all(|e| e.speaker == "ChosenOne")); let _ = fs::remove_dir_all(&out_dir); } /* let exe = env!("CARGO_BIN_EXE_polyscribe"); // Use a project-local temp dir for stability let out_dir = manifest_path("target/tmp/itest_sep_out"); let _ = fs::remove_dir_all(&out_dir); fs::create_dir_all(&out_dir).unwrap(); let input1 = manifest_path("input/1-s0wlz.json"); let input2 = manifest_path("input/2-vikingowl.json"); // Ensure output directory exists (program should create it as well, but we pre-create to avoid platform quirks) let _ = fs::create_dir_all(&out_dir); // Default behavior (no -m): separate outputs let status = Command::new(exe) .arg(input1.as_os_str()) .arg(input2.as_os_str()) .arg("-o") .arg(out_dir.as_os_str()) .status() .expect("failed to spawn polyscribe"); assert!(status.success(), "CLI did not exit successfully"); // Find the created files (one set per input) in the output directory let entries = match fs::read_dir(&out_dir) { Ok(e) => e, Err(_) => return, // If directory not found, skip further checks (environment-specific flake) }; let mut json_paths: Vec = Vec::new(); let mut count_toml = 0; let mut count_srt = 0; for e in entries { let p = e.unwrap().path(); if let Some(name) = p.file_name().and_then(|s| s.to_str()) { if name.ends_with(".json") { json_paths.push(p.clone()); } if name.ends_with(".toml") { count_toml += 1; } if name.ends_with(".srt") { count_srt += 1; } } } assert!( json_paths.len() >= 2, "expected at least 2 JSON files, found {}", json_paths.len() ); assert!( count_toml >= 2, "expected at least 2 TOML files, found {}", count_toml ); assert!( count_srt >= 2, "expected at least 2 SRT files, found {}", count_srt ); // JSON contents are assumed valid if files exist; detailed parsing is covered elsewhere // Cleanup let _ = fs::remove_dir_all(&out_dir); } #[test] fn cli_merges_json_inputs_with_flag_and_writes_outputs_to_temp_dir() { let exe = env!("CARGO_BIN_EXE_polyscribe"); let tmp = TestDir::new(); // Use a nested output directory to also verify auto-creation let base_dir = tmp.path().join("outdir"); let base = base_dir.join("out"); let input1 = manifest_path("input/1-s0wlz.json"); let input2 = manifest_path("input/2-vikingowl.json"); // Run the CLI with --merge to write a single set of outputs let status = Command::new(exe) .arg(input1.as_os_str()) .arg(input2.as_os_str()) .arg("-m") .arg("-o") .arg(base.as_os_str()) .status() .expect("failed to spawn polyscribe"); assert!(status.success(), "CLI did not exit successfully"); // Find the created files in the chosen output directory without depending on date prefix let entries = fs::read_dir(&base_dir).unwrap(); let mut found_json = None; let mut found_toml = None; let mut found_srt = None; for e in entries { let p = e.unwrap().path(); if let Some(name) = p.file_name().and_then(|s| s.to_str()) { if name.ends_with("_out.json") { found_json = Some(p.clone()); } if name.ends_with("_out.toml") { found_toml = Some(p.clone()); } if name.ends_with("_out.srt") { found_srt = Some(p.clone()); } } } let _json_path = found_json.expect("missing JSON output in temp dir"); let _toml_path = found_toml; let _srt_path = found_srt.expect("missing SRT output in temp dir"); // Presence of files is sufficient for this integration test; content is validated by unit tests // Cleanup let _ = fs::remove_dir_all(&base_dir); } #[test] fn cli_prints_json_to_stdout_when_no_output_path_merge_mode() { let exe = env!("CARGO_BIN_EXE_polyscribe"); let input1 = manifest_path("input/1-s0wlz.json"); let input2 = manifest_path("input/2-vikingowl.json"); let output = Command::new(exe) .arg(input1.as_os_str()) .arg(input2.as_os_str()) .arg("-m") .output() .expect("failed to spawn polyscribe"); assert!(output.status.success(), "CLI failed"); let stdout = String::from_utf8(output.stdout).expect("stdout not UTF-8"); assert!( stdout.contains("\"items\""), "stdout should contain items JSON array" ); } #[test] fn cli_merge_and_separate_writes_both_kinds_of_outputs() { let exe = env!("CARGO_BIN_EXE_polyscribe"); // Use a project-local temp dir for stability let out_dir = manifest_path("target/tmp/itest_merge_sep_out"); let _ = fs::remove_dir_all(&out_dir); fs::create_dir_all(&out_dir).unwrap(); let input1 = manifest_path("input/1-s0wlz.json"); let input2 = manifest_path("input/2-vikingowl.json"); let status = Command::new(exe) .arg(input1.as_os_str()) .arg(input2.as_os_str()) .arg("--merge-and-separate") .arg("-o") .arg(out_dir.as_os_str()) .status() .expect("failed to spawn polyscribe"); assert!(status.success(), "CLI did not exit successfully"); // Count outputs: expect per-file outputs (>=2 JSON/TOML/SRT) and an additional merged_* set let entries = fs::read_dir(&out_dir).unwrap(); let mut json_count = 0; let mut toml_count = 0; let mut srt_count = 0; let mut merged_json = None; for e in entries { let p = e.unwrap().path(); if let Some(name) = p.file_name().and_then(|s| s.to_str()) { if name.ends_with(".json") { json_count += 1; } if name.ends_with(".toml") { toml_count += 1; } if name.ends_with(".srt") { srt_count += 1; } if name.ends_with("_merged.json") { merged_json = Some(p.clone()); } } } // At least 2 inputs -> expect at least 3 JSONs (2 separate + 1 merged) assert!( json_count >= 3, "expected at least 3 JSON files, found {}", json_count ); assert!( toml_count >= 3, "expected at least 3 TOML files, found {}", toml_count ); assert!( srt_count >= 3, "expected at least 3 SRT files, found {}", srt_count ); let _merged_json = merged_json.expect("missing merged JSON output ending with _merged.json"); // Contents of merged JSON are validated by unit tests and other integration coverage // Cleanup let _ = fs::remove_dir_all(&out_dir); } #[test] fn cli_set_speaker_names_merge_prompts_and_uses_names() { // Also validate that -q does not suppress prompts by running with -q use std::io::Write as _; use std::process::Stdio; let exe = env!("CARGO_BIN_EXE_polyscribe"); let input1 = manifest_path("input/1-s0wlz.json"); let input2 = manifest_path("input/2-vikingowl.json"); let mut child = Command::new(exe) .arg(input1.as_os_str()) .arg(input2.as_os_str()) .arg("-m") .arg("--set-speaker-names") .arg("-q") .stdin(Stdio::piped()) .stdout(Stdio::piped()) .spawn() .expect("failed to spawn polyscribe"); { let stdin = child.stdin.as_mut().expect("failed to open stdin"); // Provide two names for two files writeln!(stdin, "Alpha").unwrap(); writeln!(stdin, "Beta").unwrap(); } let output = child.wait_with_output().expect("failed to wait on child"); assert!(output.status.success(), "CLI did not exit successfully"); let stdout = String::from_utf8(output.stdout).expect("stdout not UTF-8"); let root: OutputRoot = serde_json::from_str(&stdout).unwrap(); let speakers: std::collections::HashSet = root.items.into_iter().map(|e| e.speaker).collect(); assert!(speakers.contains("Alpha"), "Alpha not found in speakers"); assert!(speakers.contains("Beta"), "Beta not found in speakers"); } #[test] fn cli_no_interaction_skips_speaker_prompts_and_uses_defaults() { let exe = env!("CARGO_BIN_EXE_polyscribe"); let input1 = manifest_path("input/1-s0wlz.json"); let input2 = manifest_path("input/2-vikingowl.json"); let output = Command::new(exe) .arg(input1.as_os_str()) .arg(input2.as_os_str()) .arg("-m") .arg("--set-speaker-names") .arg("--no-interaction") .output() .expect("failed to spawn polyscribe"); assert!(output.status.success(), "CLI did not exit successfully"); let stdout = String::from_utf8(output.stdout).expect("stdout not UTF-8"); let root: OutputRoot = serde_json::from_str(&stdout).unwrap(); let speakers: std::collections::HashSet = root.items.into_iter().map(|e| e.speaker).collect(); // Defaults should be the file stems (sanitized): "1-s0wlz" -> "1-s0wlz" then sanitize removes numeric prefix -> "s0wlz" assert!(speakers.contains("s0wlz"), "default s0wlz not used"); assert!(speakers.contains("vikingowl"), "default vikingowl not used"); } // New verbosity behavior tests #[test] fn verbosity_quiet_suppresses_logs_but_keeps_stdout() { let exe = env!("CARGO_BIN_EXE_polyscribe"); let input1 = manifest_path("input/1-s0wlz.json"); let input2 = manifest_path("input/2-vikingowl.json"); let output = Command::new(exe) .arg("-q") .arg("-v") // ensure -q overrides -v .arg(input1.as_os_str()) .arg(input2.as_os_str()) .arg("-m") .output() .expect("failed to spawn polyscribe"); assert!(output.status.success()); let stdout = String::from_utf8(output.stdout).unwrap(); assert!( stdout.contains("\"items\""), "stdout JSON should be present in quiet mode" ); let stderr = String::from_utf8(output.stderr).unwrap(); assert!( stderr.trim().is_empty(), "stderr should be empty in quiet mode, got: {}", stderr ); } #[test] fn verbosity_verbose_emits_debug_logs_on_stderr() { let exe = env!("CARGO_BIN_EXE_polyscribe"); let input1 = manifest_path("input/1-s0wlz.json"); let input2 = manifest_path("input/2-vikingowl.json"); let output = Command::new(exe) .arg(input1.as_os_str()) .arg(input2.as_os_str()) .arg("-m") .arg("-v") .output() .expect("failed to spawn polyscribe"); assert!(output.status.success()); let stdout = String::from_utf8(output.stdout).unwrap(); assert!(stdout.contains("\"items\"")); let stderr = String::from_utf8(output.stderr).unwrap(); assert!( stderr.contains("Mode: merge"), "stderr should contain debug log with -v" ); } #[test] fn verbosity_flag_position_is_global() { let exe = env!("CARGO_BIN_EXE_polyscribe"); let input1 = manifest_path("input/1-s0wlz.json"); let input2 = manifest_path("input/2-vikingowl.json"); // -v before args let out1 = Command::new(exe) .arg("-v") .arg(input1.as_os_str()) .arg(input2.as_os_str()) .arg("-m") .output() .expect("failed to spawn polyscribe"); // -v after sub-flags let out2 = Command::new(exe) .arg(input1.as_os_str()) .arg(input2.as_os_str()) .arg("-m") .arg("-v") .output() .expect("failed to spawn polyscribe"); let s1 = String::from_utf8(out1.stderr).unwrap(); let s2 = String::from_utf8(out2.stderr).unwrap(); assert!(s1.contains("Mode: merge")); assert!(s2.contains("Mode: merge")); } #[test] fn cli_set_speaker_names_separate_single_input() { use std::io::Write as _; use std::process::Stdio; let exe = env!("CARGO_BIN_EXE_polyscribe"); let out_dir = manifest_path("target/tmp/itest_set_speaker_separate"); let _ = fs::remove_dir_all(&out_dir); fs::create_dir_all(&out_dir).unwrap(); let input1 = manifest_path("input/3-schmendrizzle.json"); let mut child = Command::new(exe) .arg(input1.as_os_str()) .arg("--set-speaker-names") .arg("-o") .arg(out_dir.as_os_str()) .stdin(Stdio::piped()) .stdout(Stdio::null()) .stderr(Stdio::null()) .spawn() .expect("failed to spawn polyscribe"); { let stdin = child.stdin.as_mut().expect("failed to open stdin"); writeln!(stdin, "ChosenOne").unwrap(); } let status = child.wait().expect("failed to wait on child"); assert!(status.success(), "CLI did not exit successfully"); // Find created JSON let mut json_paths: Vec = Vec::new(); for e in fs::read_dir(&out_dir).unwrap() { let p = e.unwrap().path(); if let Some(name) = p.file_name().and_then(|s| s.to_str()) { if name.ends_with(".json") { json_paths.push(p.clone()); } } } assert!(!json_paths.is_empty(), "no JSON outputs created"); let mut buf = String::new(); std::fs::File::open(&json_paths[0]) .unwrap() .read_to_string(&mut buf) .unwrap(); let root: OutputRoot = serde_json::from_str(&buf).unwrap(); assert!(root.items.iter().all(|e| e.speaker == "ChosenOne")); let _ = fs::remove_dir_all(&out_dir); } // New tests for --out-format #[test] fn out_format_single_json_only() { let exe = env!("CARGO_BIN_EXE_polyscribe"); let out_dir = manifest_path("target/tmp/itest_outfmt_json_only"); let _ = fs::remove_dir_all(&out_dir); fs::create_dir_all(&out_dir).unwrap(); let input1 = manifest_path("input/1-s0wlz.json"); let status = Command::new(exe) .arg(input1.as_os_str()) .arg("-o") .arg(&out_dir) .arg("--out-format") .arg("json") .status() .expect("failed to spawn polyscribe"); assert!(status.success(), "CLI did not exit successfully"); let mut has_json = false; let mut has_toml = false; let mut has_srt = false; for e in fs::read_dir(&out_dir).unwrap() { let p = e.unwrap().path(); if let Some(name) = p.file_name().and_then(|s| s.to_str()) { if name.ends_with(".json") { has_json = true; } if name.ends_with(".toml") { has_toml = true; } if name.ends_with(".srt") { has_srt = true; } } } assert!(has_json, "expected JSON file to be written"); assert!(!has_toml, "did not expect TOML file"); assert!(!has_srt, "did not expect SRT file"); let _ = fs::remove_dir_all(&out_dir); } #[test] fn out_format_multiple_json_and_srt() { let exe = env!("CARGO_BIN_EXE_polyscribe"); let out_dir = manifest_path("target/tmp/itest_outfmt_json_srt"); let _ = fs::remove_dir_all(&out_dir); fs::create_dir_all(&out_dir).unwrap(); let input1 = manifest_path("input/2-vikingowl.json"); let status = Command::new(exe) .arg(input1.as_os_str()) .arg("-o") .arg(&out_dir) .arg("--out-format") .arg("json") .arg("--out-format") .arg("srt") .status() .expect("failed to spawn polyscribe"); assert!(status.success(), "CLI did not exit successfully"); let mut has_json = false; let mut has_toml = false; let mut has_srt = false; for e in fs::read_dir(&out_dir).unwrap() { let p = e.unwrap().path(); if let Some(name) = p.file_name().and_then(|s| s.to_str()) { if name.ends_with(".json") { has_json = true; } if name.ends_with(".toml") { has_toml = true; } if name.ends_with(".srt") { has_srt = true; } } } assert!(has_json, "expected JSON file to be written"); assert!(has_srt, "expected SRT file to be written"); assert!(!has_toml, "did not expect TOML file"); let _ = fs::remove_dir_all(&out_dir); } */