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 }