sheeter-engine 1.2.0

Convert, inspect, and transform data files across ten formats with streaming where it matters and auto-detection where it can.
Documentation
use assert_cmd::Command;
use std::fs;
use tempfile::tempdir;

fn run_in(dir: &std::path::Path, args: &[&str]) -> Result<String, String> {
    let output = Command::cargo_bin("sheeter")
        .unwrap()
        .current_dir(dir)
        .args(args)
        .output()
        .unwrap();
    if !output.status.success() {
        return Err(String::from_utf8_lossy(&output.stderr).to_string());
    }
    Ok(String::from_utf8(output.stdout).unwrap())
}

#[test]
fn view_single_csv() {
    let dir = tempdir().unwrap();
    fs::write(dir.path().join("a.csv"), "name,age\nAlice,30\nBob,25\n").unwrap();
    let out = run_in(dir.path(), &["view", "a.csv"]).unwrap();
    assert!(out.contains("Output table No. 1"));
    assert!(out.contains("a"));
    assert!(out.contains("Alice"));
    assert!(out.contains("Bob"));
    assert!(out.contains("name"));
    assert!(out.contains("age"));
}

#[test]
fn view_multiple_inputs() {
    let dir = tempdir().unwrap();
    fs::write(dir.path().join("a.csv"), "x\n1\n").unwrap();
    fs::write(dir.path().join("b.tsv"), "y\n2\n").unwrap();
    let out = run_in(dir.path(), &["view", "a.csv", "b.tsv"]).unwrap();
    assert!(out.contains("Output table No. 1"));
    assert!(out.contains("Output table No. 2"));
    assert!(out.contains("x"));
    assert!(out.contains("y"));
}

#[test]
fn view_xlsx_multi_sheet() {
    use sheeter_engine::CanonicalValue;
    let dir = tempdir().unwrap();
    let s1 = CanonicalValue::from_csv("a\n1\n").unwrap();
    let s2 = CanonicalValue::from_csv("b\n2\n").unwrap();
    let bytes = CanonicalValue::to_xlsx_workbook(&[
        ("Funcionarios".to_string(), s1),
        ("Clientes".to_string(), s2),
    ])
    .unwrap();
    fs::write(dir.path().join("book.xlsx"), bytes).unwrap();
    let out = run_in(dir.path(), &["view", "book.xlsx"]).unwrap();
    assert!(out.contains("Output table No. 1"));
    assert!(out.contains("Output table No. 2"));
    assert!(out.contains("Funcionarios"));
    assert!(out.contains("Clientes"));
}

#[test]
fn view_to_json_single() {
    let dir = tempdir().unwrap();
    fs::write(dir.path().join("a.csv"), "x\n1\n2\n").unwrap();
    let out = run_in(dir.path(), &["view", "a.csv", "--to-json"]).unwrap();
    assert_eq!(out.trim(), r#"[{"x":"1"},{"x":"2"}]"#);
}

#[test]
fn view_to_json_multi() {
    let dir = tempdir().unwrap();
    fs::write(dir.path().join("a.csv"), "x\n1\n").unwrap();
    fs::write(dir.path().join("b.csv"), "y\n2\n").unwrap();
    let out = run_in(dir.path(), &["view", "a.csv", "b.csv", "--to-json"]).unwrap();
    let parsed: serde_json::Value = serde_json::from_str(out.trim()).unwrap();
    assert!(parsed.get("a").is_some());
    assert!(parsed.get("b").is_some());
}

#[test]
fn view_missing_file_errors() {
    let dir = tempdir().unwrap();
    let err = run_in(dir.path(), &["view", "nope.csv"]).unwrap_err();
    assert!(!err.is_empty());
}