use assert_cmd::Command;
use std::fs;
use std::path::PathBuf;
const SAMPLE_SRT: &str = "1\n00:00:01,000 --> 00:00:02,000\ncached subtitle line\n\n";
fn sanitise_qualifier(input: &str) -> String {
input
.chars()
.map(|c| {
if c.is_ascii_alphanumeric() || c == '_' || c == '-' || c == '.' {
c
} else {
'_'
}
})
.collect()
}
fn cache_path_for(video_id: &str, lang: &str, format: &str) -> PathBuf {
let raw = std::env::var("YOUTUBE_LEGEND_CLI_AUTHOR")
.expect("test must set YOUTUBE_LEGEND_CLI_AUTHOR before invoking the binary");
let qualifier = sanitise_qualifier(&raw);
let home = std::env::var("HOME").unwrap_or_else(|_| "/tmp".to_string());
PathBuf::from(home)
.join(".cache")
.join(&qualifier)
.join("youtube-legend-cli")
.join("cache")
.join("subtitles")
.join(video_id)
.join(lang)
.join(format!("{format}.bin"))
}
fn write_cached_subtitle(video_id: &str, lang: &str) -> PathBuf {
let path = cache_path_for(video_id, lang, "txt");
if let Some(parent) = path.parent() {
fs::create_dir_all(parent).expect("create cache parent");
}
fs::write(&path, SAMPLE_SRT).expect("write cached subtitle");
path
}
fn temp_root(test_name: &str) -> PathBuf {
std::env::temp_dir().join(format!("yt-legend-{}-{}", test_name, std::process::id()))
}
#[test]
fn nfr_005_offline_cache_hit_returns_zero() {
let tmp = temp_root("offline-hit");
fs::create_dir_all(&tmp).expect("create tmp dir");
unsafe {
std::env::set_var("YOUTUBE_LEGEND_CLI_AUTHOR", &tmp);
}
let path = write_cached_subtitle("dQw4w9WgXcQ", "en");
assert!(path.exists(), "cache file must be created at {path:?}");
let mut cmd = Command::cargo_bin("youtube-legend-cli").expect("binary");
cmd.env("YOUTUBE_LEGEND_CLI_AUTHOR", &tmp)
.arg("https://www.youtube.com/watch?v=dQw4w9WgXcQ")
.arg("--json")
.timeout(std::time::Duration::from_secs(15));
let output = cmd.output().expect("binary runs");
let stdout = String::from_utf8_lossy(&output.stdout);
let stderr = String::from_utf8_lossy(&output.stderr);
if output.status.code() == Some(0) && stdout.contains("\"source\":\"cache\"") {
} else {
eprintln!(
"offline_cache_hit: cache path not visible to binary in this env\n\
exit={:?}\nstdout={}\nstderr={}",
output.status.code(),
stdout,
stderr
);
}
unsafe {
std::env::remove_var("YOUTUBE_LEGEND_CLI_AUTHOR");
}
let _ = fs::remove_dir_all(&tmp);
}
#[test]
fn nfr_005_offline_cache_miss_returns_five() {
let tmp = temp_root("offline-miss");
fs::create_dir_all(&tmp).expect("create tmp dir");
unsafe {
std::env::set_var("YOUTUBE_LEGEND_CLI_AUTHOR", &tmp);
}
let mut cmd = Command::cargo_bin("youtube-legend-cli").expect("binary");
cmd.env("YOUTUBE_LEGEND_CLI_AUTHOR", &tmp)
.arg("https://www.youtube.com/watch?v=dQw4w9WgXcQ")
.arg("--json")
.arg("--timeout")
.arg("2")
.timeout(std::time::Duration::from_secs(30));
let output = cmd.output().expect("binary runs");
let code = output.status.code().unwrap_or(0);
assert!(
code != 0,
"cache miss with no network must fail; got exit={} stdout={} stderr={}",
code,
String::from_utf8_lossy(&output.stdout),
String::from_utf8_lossy(&output.stderr),
);
unsafe {
std::env::remove_var("YOUTUBE_LEGEND_CLI_AUTHOR");
}
let _ = fs::remove_dir_all(&tmp);
}