xl-cli-tools

CLI tools for viewing and editing Excel files
Log | Files | Refs | README | LICENSE

test_xldiff.rs (7029B)


      1 mod common;
      2 
      3 use assert_cmd::Command;
      4 use predicates::prelude::*;
      5 use tempfile::TempDir;
      6 
      7 fn xldiff() -> Command {
      8     Command::cargo_bin("xldiff").unwrap()
      9 }
     10 
     11 // ---------------------------------------------------------------------------
     12 // test_no_diff
     13 // ---------------------------------------------------------------------------
     14 
     15 #[test]
     16 fn test_no_diff() {
     17     let dir = TempDir::new().unwrap();
     18     let path_a = dir.path().join("a.xlsx");
     19     let path_b = dir.path().join("b.xlsx");
     20     common::create_simple(&path_a);
     21     common::create_simple(&path_b);
     22 
     23     xldiff()
     24         .arg(&path_a)
     25         .arg(&path_b)
     26         .arg("--no-color")
     27         .assert()
     28         .success()
     29         .stdout(predicate::str::contains("No differences found."));
     30 }
     31 
     32 // ---------------------------------------------------------------------------
     33 // test_positional_diff
     34 // ---------------------------------------------------------------------------
     35 
     36 #[test]
     37 fn test_positional_diff() {
     38     let dir = TempDir::new().unwrap();
     39     let path_a = dir.path().join("a.xlsx");
     40     let path_b = dir.path().join("b.xlsx");
     41     common::create_diff_pair(&path_a, &path_b);
     42 
     43     xldiff()
     44         .arg(&path_a)
     45         .arg(&path_b)
     46         .arg("--no-color")
     47         .assert()
     48         .code(1)
     49         .stdout(predicate::str::contains("Removed: 1"))
     50         .stdout(predicate::str::contains("Added: 1"))
     51         .stdout(predicate::str::contains("Bob"));
     52 }
     53 
     54 // ---------------------------------------------------------------------------
     55 // test_keyed_diff
     56 // ---------------------------------------------------------------------------
     57 
     58 #[test]
     59 fn test_keyed_diff() {
     60     let dir = TempDir::new().unwrap();
     61     let path_a = dir.path().join("a.xlsx");
     62     let path_b = dir.path().join("b.xlsx");
     63     common::create_diff_pair_with_keys(&path_a, &path_b);
     64 
     65     xldiff()
     66         .arg(&path_a)
     67         .arg(&path_b)
     68         .args(["--key", "ID", "--no-color"])
     69         .assert()
     70         .code(1)
     71         .stdout(predicate::str::contains("Modified: 1"))
     72         .stdout(predicate::str::contains("Removed: 1"))
     73         .stdout(predicate::str::contains("Added: 1"));
     74 }
     75 
     76 // ---------------------------------------------------------------------------
     77 // test_tolerance
     78 // ---------------------------------------------------------------------------
     79 
     80 #[test]
     81 fn test_tolerance() {
     82     let dir = TempDir::new().unwrap();
     83     let path_a = dir.path().join("a.xlsx");
     84     let path_b = dir.path().join("b.xlsx");
     85     common::create_diff_pair_with_floats(&path_a, &path_b);
     86 
     87     // With tolerance 0.01: ID=1 diff is 0.001 (within tolerance), ID=2 diff is 0.1 (exceeds)
     88     xldiff()
     89         .arg(&path_a)
     90         .arg(&path_b)
     91         .args(["--key", "ID", "--tolerance", "0.01", "--no-color"])
     92         .assert()
     93         .code(1)
     94         .stdout(predicate::str::contains("Modified: 1"));
     95 }
     96 
     97 // ---------------------------------------------------------------------------
     98 // test_json_format
     99 // ---------------------------------------------------------------------------
    100 
    101 #[test]
    102 fn test_json_format() {
    103     let dir = TempDir::new().unwrap();
    104     let path_a = dir.path().join("a.xlsx");
    105     let path_b = dir.path().join("b.xlsx");
    106     common::create_diff_pair_with_keys(&path_a, &path_b);
    107 
    108     xldiff()
    109         .arg(&path_a)
    110         .arg(&path_b)
    111         .args(["--key", "ID", "--format", "json"])
    112         .assert()
    113         .code(1)
    114         .stdout(predicate::str::contains("\"added\""))
    115         .stdout(predicate::str::contains("\"removed\""))
    116         .stdout(predicate::str::contains("\"modified\""));
    117 }
    118 
    119 // ---------------------------------------------------------------------------
    120 // test_markdown_format
    121 // ---------------------------------------------------------------------------
    122 
    123 #[test]
    124 fn test_markdown_format() {
    125     let dir = TempDir::new().unwrap();
    126     let path_a = dir.path().join("a.xlsx");
    127     let path_b = dir.path().join("b.xlsx");
    128     common::create_diff_pair_with_keys(&path_a, &path_b);
    129 
    130     xldiff()
    131         .arg(&path_a)
    132         .arg(&path_b)
    133         .args(["--key", "ID", "--format", "markdown"])
    134         .assert()
    135         .code(1)
    136         .stdout(predicate::str::contains("## Added"))
    137         .stdout(predicate::str::contains("## Removed"))
    138         .stdout(predicate::str::contains("## Modified"));
    139 }
    140 
    141 // ---------------------------------------------------------------------------
    142 // test_csv_format
    143 // ---------------------------------------------------------------------------
    144 
    145 #[test]
    146 fn test_csv_format() {
    147     let dir = TempDir::new().unwrap();
    148     let path_a = dir.path().join("a.xlsx");
    149     let path_b = dir.path().join("b.xlsx");
    150     common::create_diff_pair_with_keys(&path_a, &path_b);
    151 
    152     xldiff()
    153         .arg(&path_a)
    154         .arg(&path_b)
    155         .args(["--key", "ID", "--format", "csv"])
    156         .assert()
    157         .code(1)
    158         .stdout(predicate::str::contains("_status"))
    159         .stdout(predicate::str::contains("added"))
    160         .stdout(predicate::str::contains("removed"))
    161         .stdout(predicate::str::contains("modified"));
    162 }
    163 
    164 // ---------------------------------------------------------------------------
    165 // test_file_not_found
    166 // ---------------------------------------------------------------------------
    167 
    168 #[test]
    169 fn test_file_not_found() {
    170     xldiff()
    171         .arg("nonexistent_a.xlsx")
    172         .arg("nonexistent_b.xlsx")
    173         .assert()
    174         .code(2)
    175         .stderr(predicate::str::contains("file not found"));
    176 }
    177 
    178 // ---------------------------------------------------------------------------
    179 // test_sheet_selector
    180 // ---------------------------------------------------------------------------
    181 
    182 #[test]
    183 fn test_sheet_selector() {
    184     let dir = TempDir::new().unwrap();
    185     let path = dir.path().join("multi.xlsx");
    186     common::create_multi_sheet(&path);
    187 
    188     // Revenue and Expenses sheets have different schemas and data
    189     let arg_revenue = format!("{}:Revenue", path.display());
    190     let arg_expenses = format!("{}:Expenses", path.display());
    191 
    192     xldiff()
    193         .arg(&arg_revenue)
    194         .arg(&arg_expenses)
    195         .assert()
    196         .code(1);
    197 }
    198 
    199 // ---------------------------------------------------------------------------
    200 // test_cols_filter
    201 // ---------------------------------------------------------------------------
    202 
    203 #[test]
    204 fn test_cols_filter() {
    205     let dir = TempDir::new().unwrap();
    206     let path_a = dir.path().join("a.xlsx");
    207     let path_b = dir.path().join("b.xlsx");
    208     common::create_diff_pair_with_keys(&path_a, &path_b);
    209 
    210     // With --cols ID,Name: Score column is excluded from comparison.
    211     // ID=1: Score changed 90→95, but Score is excluded, so Name is same → no modification.
    212     // ID=3: removed, ID=4: added.
    213     // Modified should be 0.
    214     xldiff()
    215         .arg(&path_a)
    216         .arg(&path_b)
    217         .args(["--key", "ID", "--cols", "ID,Name", "--no-color"])
    218         .assert()
    219         .code(1)
    220         .stdout(predicate::str::contains("Modified: 0"))
    221         .stdout(predicate::str::contains("Added: 1"))
    222         .stdout(predicate::str::contains("Removed: 1"));
    223 }