use assert_cmd::Command;
use std::fs;
use tempfile::tempdir;
#[test]
fn duplicate_csv_headers_error() {
let dir = tempdir().unwrap();
let input = dir.path().join("input.csv");
let output = dir.path().join("output.json");
fs::write(&input, "name,name\nAlice,Bob").unwrap();
Command::cargo_bin("sheeter")
.unwrap()
.args([
"convert",
"--from",
"csv",
"--to",
"json",
input.to_str().unwrap(),
output.to_str().unwrap(),
])
.assert()
.failure();
}
#[test]
fn extra_json_keys_preserved() {
let dir = tempdir().unwrap();
let input = dir.path().join("input.json");
let output = dir.path().join("output.csv");
fs::write(&input, r#"[{"a":1},{"a":2,"b":3}]"#).unwrap();
Command::cargo_bin("sheeter")
.unwrap()
.args([
"convert",
"--from",
"json",
"--to",
"csv",
input.to_str().unwrap(),
output.to_str().unwrap(),
])
.assert()
.success();
let csv = fs::read_to_string(output).unwrap();
assert_eq!(csv, "a,b\n1,\n2,3\n");
}
#[test]
fn nested_json_value_error() {
let dir = tempdir().unwrap();
let input = dir.path().join("input.json");
let output = dir.path().join("output.csv");
fs::write(&input, r#"[{"a":{"b":1}}]"#).unwrap();
Command::cargo_bin("sheeter")
.unwrap()
.args([
"convert",
"--from",
"json",
"--to",
"csv",
input.to_str().unwrap(),
output.to_str().unwrap(),
])
.assert()
.failure();
}
#[test]
fn csv_bom_is_stripped() {
let csv = "\u{feff}name,age\nAlice,30";
let json = sheeter_engine::csv_to_json(csv).unwrap();
assert_eq!(json, r#"[{"name":"Alice","age":"30"}]"#);
}
#[test]
fn yaml_norway_problem_avoided() {
let yaml = "- country: NO\n- country: yes\n";
let json = sheeter_engine::yaml_to_json(yaml).unwrap();
assert!(json.contains("\"NO\""));
assert!(json.contains("\"yes\""));
}
#[test]
fn yaml_null_preserved() {
let yaml = "- a: null\n";
let json = sheeter_engine::yaml_to_json(yaml).unwrap();
assert!(json.contains("null"));
}
#[test]
fn json_key_order_union_is_stable() {
let json = r#"[{"b":2,"a":1},{"a":3,"b":4}]"#;
let csv = sheeter_engine::json_to_csv(json).unwrap();
let headers = csv.lines().next().unwrap();
assert_eq!(headers, "b,a");
}
#[test]
fn tsv_roundtrips_tabs_in_cells() {
let json = r#"[{"a":"1\t2","b":"3"}]"#;
let tsv = sheeter_engine::json_to_tsv(json).unwrap();
assert!(
tsv.contains("1\t2"),
"tab-containing cell must appear: {tsv:?}"
);
let back = sheeter_engine::tsv_to_json(&tsv).unwrap();
assert_eq!(back, json);
}
#[test]
fn csv_roundtrips_commas_and_quotes() {
let json = r#"[{"a":"hello, world","b":"say \"hi\""}]"#;
let csv = sheeter_engine::json_to_csv(json).unwrap();
let back = sheeter_engine::csv_to_json(&csv).unwrap();
assert_eq!(back, json);
}
#[test]
fn yaml_binary_tag_treated_as_string() {
let yaml = "- data: !!binary aGVsbG8=\n";
let json = sheeter_engine::yaml_to_json(yaml).unwrap();
assert!(
json.contains("aGVsbG8="),
"binary tag must not be base64-decoded: {json}"
);
}
#[test]
fn csv_ragged_rows_error() {
let csv = "a,b\n1,2,3";
assert!(sheeter_engine::csv_to_json(csv).is_err());
}
#[test]
fn yaml_non_string_keys_stringified() {
let yaml = "- 1: value\n";
let json = sheeter_engine::yaml_to_json(yaml).unwrap();
assert_eq!(json, r#"[{"1":"value"}]"#);
}
#[test]
fn toml_dot_notation_becomes_nested() {
let json = sheeter_engine::toml_to_json("a.b = 1\n").unwrap();
assert_eq!(json, r#"{"a":{"b":1}}"#);
}
#[test]
fn toml_array_of_tables_at_depth() {
let toml = "[config]\n[[config.items]]\nx = 1\n[[config.items]]\nx = 2\n";
let csv = sheeter_engine::toml_to_csv(toml).unwrap();
assert_eq!(csv, "x\n1\n2\n");
}
#[test]
fn xml_markers_survive_toml_roundtrip() {
let xml = r#"<r><item id="1">Alice</item></r>"#;
let toml = sheeter_engine::xml_to_toml(xml).unwrap();
let xml_back = sheeter_engine::toml_to_xml(&toml).unwrap();
assert!(xml_back.contains(r#"id="1""#), "attribute lost: {xml_back}");
assert!(xml_back.contains("Alice"), "text lost: {xml_back}");
}
#[test]
fn toml_preserves_insertion_order() {
let json = sheeter_engine::toml_to_json("name = \"Alice\"\nage = 30\n").unwrap();
assert_eq!(json, r#"{"name":"Alice","age":30}"#);
}
#[test]
fn convert_str_rejects_xlsx() {
use sheeter_engine::{convert, Format};
let err = convert(Format::Xlsx, Format::Json, "not binary").unwrap_err();
assert!(err.to_string().contains("convert_workbook"));
}