#![allow(dead_code)]
use std::path::{Path, PathBuf};
use std::process::Output;
use std::time::{SystemTime, UNIX_EPOCH};
use assert_cmd::Command;
pub struct TempCache {
path: PathBuf,
}
impl TempCache {
pub fn new(tag: &str) -> Self {
let mut path = std::env::temp_dir();
path.push(format!(
"rss-cli-test-{tag}-{}-{}",
std::process::id(),
unique_suffix()
));
std::fs::create_dir_all(&path).expect("create temp cache dir");
Self { path }
}
pub fn path(&self) -> &Path {
&self.path
}
}
impl Drop for TempCache {
fn drop(&mut self) {
let _ = std::fs::remove_dir_all(&self.path);
}
}
fn unique_suffix() -> u128 {
SystemTime::now()
.duration_since(UNIX_EPOCH)
.map(|d| d.as_nanos())
.unwrap_or(0)
}
pub fn rss() -> Command {
Command::cargo_bin("rss").expect("the `rss` binary should be built by `cargo test`")
}
pub fn fixture(name: &str) -> String {
let path = Path::new(env!("CARGO_MANIFEST_DIR"))
.join("tests")
.join("fixtures")
.join(name);
std::fs::read_to_string(&path)
.unwrap_or_else(|e| panic!("read fixture {}: {e}", path.display()))
}
pub fn mock_server(
path: &str,
content_type: &str,
body: &str,
) -> (mockito::ServerGuard, mockito::Mock) {
let mut server = mockito::Server::new();
let mock = server
.mock("GET", path)
.with_status(200)
.with_header("content-type", content_type)
.with_body(body)
.create();
(server, mock)
}
pub fn run_fetch(feed_url: &str, cache_dir: &Path, format: &str) -> Output {
rss()
.arg("--quiet")
.arg("--cache-dir")
.arg(cache_dir)
.arg("fetch")
.arg(feed_url)
.arg("--format")
.arg(format)
.output()
.expect("spawn rss")
}
pub fn is_stub_panic(output: &Output) -> bool {
String::from_utf8_lossy(&output.stderr).contains("not yet implemented")
}
pub fn skip_note(test: &str, output: &Output) {
eprintln!(
"[qa] SKIP {test}: binary is still on a `todo!()` stub (exit {:?}); \
live assertions will run automatically once fetch/parse/render land.",
output.status.code()
);
}
pub fn item_ids(output: &Output) -> std::collections::BTreeSet<String> {
let v: serde_json::Value =
serde_json::from_slice(&output.stdout).expect("fetch json stdout should parse");
v["feeds"]
.as_array()
.expect("feeds array")
.iter()
.flat_map(|f| f["items"].as_array().cloned().unwrap_or_default())
.map(|it| {
it["id"]
.as_str()
.expect("item id should be a string")
.to_string()
})
.collect()
}