1package diff 2 3import ( 4 "encoding/json" 5 "errors" 6 "io" 7 "strings" 8 "testing" 9) 10 11func TestResultString(t *testing.T) { 12 t.Run("nil", func(t *testing.T) { 13 var r *Result 14 expected := "" 15 if result := r.String(); result != expected { 16 t.Errorf("Unexpected result: %s", result) 17 } 18 }) 19 t.Run("diff", func(t *testing.T) { 20 expected := "foo" 21 r := &Result{diff: expected} 22 if result := r.String(); result != expected { 23 t.Errorf("Unexpected result: %s", result) 24 } 25 }) 26} 27 28func TestSliceDiff(t *testing.T) { 29 tests := []struct { 30 name string 31 expected, actual []string 32 result string 33 }{ 34 { 35 name: "equal", 36 expected: []string{"foo"}, 37 actual: []string{"foo"}, 38 }, 39 { 40 name: "different", 41 expected: []string{"foo"}, 42 actual: []string{"bar"}, 43 result: "--- expected\n+++ actual\n@@ -1 +1 @@\n-foo+bar", 44 }, 45 } 46 for _, test := range tests { 47 result := sliceDiff(test.expected, test.actual) 48 var resultText string 49 if result != nil { 50 resultText = result.String() 51 } 52 if resultText != test.result { 53 t.Errorf("Unexpected result:\n%s\n", resultText) 54 } 55 } 56} 57 58func TestTextSlices(t *testing.T) { 59 tests := []struct { 60 name string 61 expected, actual []string 62 result string 63 }{ 64 { 65 name: "equal", 66 expected: []string{"foo", "bar"}, 67 actual: []string{"foo", "bar"}, 68 }, 69 { 70 name: "different", 71 expected: []string{"foo", "bar"}, 72 actual: []string{"bar", "bar"}, 73 result: "--- expected\n+++ actual\n@@ -1,2 +1,2 @@\n-foo\n bar\n+bar\n", 74 }, 75 } 76 for _, test := range tests { 77 result := TextSlices(test.expected, test.actual) 78 var resultText string 79 if result != nil { 80 resultText = result.String() 81 } 82 if resultText != test.result { 83 t.Errorf("Unexpected result:\n%s\n", resultText) 84 } 85 } 86} 87 88func TestText(t *testing.T) { 89 tests := []struct { 90 name string 91 expected, actual interface{} 92 result string 93 }{ 94 { 95 name: "equal", 96 expected: "foo\nbar\n", 97 actual: "foo\nbar\n", 98 }, 99 { 100 name: "different", 101 expected: "foo\nbar", 102 actual: "bar\nbar", 103 result: "--- expected\n+++ actual\n@@ -1,2 +1,2 @@\n-foo\n bar\n+bar\n", 104 }, 105 { 106 name: "string vs []byte", 107 expected: "foo", 108 actual: []byte("foo"), 109 }, 110 { 111 name: "invalid exp type", 112 expected: 123, 113 result: "[diff] expected: input must be of type string, []byte, or io.Reader", 114 }, 115 { 116 name: "invalid act type", 117 expected: "123", 118 actual: 123, 119 result: "[diff] actual: input must be of type string, []byte, or io.Reader", 120 }, 121 { 122 name: "string vs io.Reader", 123 expected: strings.NewReader("foo"), 124 actual: "foo", 125 }, 126 { 127 name: "string vs nil", 128 expected: "foo", 129 actual: nil, 130 result: "--- expected\n+++ actual\n@@ -1 +1 @@\n-foo\n+\n", 131 }, 132 } 133 for _, test := range tests { 134 t.Run(test.name, func(t *testing.T) { 135 result := Text(test.expected, test.actual) 136 var resultText string 137 if result != nil { 138 resultText = result.String() 139 } 140 if resultText != test.result { 141 t.Errorf("Unexpected result:\n%s\n", resultText) 142 } 143 }) 144 } 145} 146 147func TestIsJSON(t *testing.T) { 148 tests := []struct { 149 name string 150 input interface{} 151 isJSON bool 152 result string 153 }{ 154 { 155 name: "io.Reader", 156 input: strings.NewReader("foo"), 157 isJSON: true, 158 result: "foo", 159 }, 160 { 161 name: "byte slice", 162 input: []byte("foo"), 163 isJSON: true, 164 result: "foo", 165 }, 166 { 167 name: "json.RawMessage", 168 input: json.RawMessage("foo"), 169 isJSON: true, 170 result: "foo", 171 }, 172 { 173 name: "string", 174 input: "foo", 175 isJSON: false, 176 }, 177 } 178 for _, test := range tests { 179 t.Run(test.name, func(t *testing.T) { 180 isJSON, result, _ := isJSON(test.input) 181 if isJSON != test.isJSON { 182 t.Errorf("Unexpected result: %t", isJSON) 183 } 184 if string(result) != test.result { 185 t.Errorf("Unexpected result: %s", string(result)) 186 } 187 }) 188 } 189} 190 191type errorReader struct{} 192 193var _ io.Reader = &errorReader{} 194 195func (r *errorReader) Read(_ []byte) (int, error) { 196 return 0, errors.New("read error") 197} 198 199func TestMarshal(t *testing.T) { 200 tests := []struct { 201 name string 202 input interface{} 203 expected string 204 err string 205 }{ 206 { 207 name: "byte slice", 208 input: []byte(`"foo"`), 209 expected: `"foo"`, 210 }, 211 { 212 name: "string", 213 input: "foo", 214 expected: `"foo"`, 215 }, 216 { 217 name: "invalid json", 218 input: []byte("invalid json"), 219 err: "invalid character 'i' looking for beginning of value", 220 }, 221 { 222 name: "error reader", 223 input: &errorReader{}, 224 err: "read error", 225 }, 226 } 227 for _, test := range tests { 228 t.Run(test.name, func(t *testing.T) { 229 result, err := marshal(test.input) 230 var errMsg string 231 if err != nil { 232 errMsg = err.Error() 233 } 234 if test.err != errMsg { 235 t.Errorf("Unexpected error: %s", errMsg) 236 } 237 if string(result) != test.expected { 238 t.Errorf("Unexpected result: %s", string(result)) 239 } 240 }) 241 } 242} 243 244func TestAsJSON(t *testing.T) { 245 tests := []struct { 246 name string 247 expected, actual interface{} 248 result string 249 }{ 250 { 251 name: "equal", 252 expected: []string{"foo", "bar"}, 253 actual: []string{"foo", "bar"}, 254 }, 255 { 256 name: "different", 257 expected: []string{"foo", "bar"}, 258 actual: []string{"bar", "bar"}, 259 result: `--- expected 260+++ actual 261@@ -1,4 +1,4 @@ 262 [ 263- "foo", 264+ "bar", 265 "bar" 266 ] 267`, 268 }, 269 { 270 name: "Unmarshalable expected", 271 expected: make(chan int), 272 actual: "foo", 273 result: "failed to marshal expected value: json: unsupported type: chan int", 274 }, 275 { 276 name: "Unmarshalable actual", 277 expected: "foo", 278 actual: make(chan int), 279 result: "failed to marshal actual value: json: unsupported type: chan int", 280 }, 281 { 282 name: "empty reader", 283 expected: strings.NewReader(""), 284 actual: nil, 285 result: "", 286 }, 287 } 288 for _, test := range tests { 289 result := AsJSON(test.expected, test.actual) 290 var resultText string 291 if result != nil { 292 resultText = result.String() 293 } 294 if resultText != test.result { 295 t.Errorf("Unexpected result:\n%s\n", resultText) 296 } 297 } 298} 299 300func TestJSON(t *testing.T) { 301 tests := []struct { 302 name string 303 expected, actual string 304 result string 305 }{ 306 { 307 name: "equal", 308 expected: `["foo","bar"]`, 309 actual: `["foo","bar"]`, 310 }, 311 { 312 name: "different", 313 expected: `["foo","bar"]`, 314 actual: `["bar","bar"]`, 315 result: `--- expected 316+++ actual 317@@ -1,4 +1,4 @@ 318 [ 319- "foo", 320+ "bar", 321 "bar" 322 ] 323`, 324 }, 325 { 326 name: "invalid expected", 327 expected: "invalid json", 328 actual: `"foo"`, 329 result: "failed to unmarshal expected value: invalid character 'i' looking for beginning of value", 330 }, 331 { 332 name: "invalid actual", 333 expected: `"foo"`, 334 actual: "invalid json", 335 result: "failed to unmarshal actual value: invalid character 'i' looking for beginning of value", 336 }, 337 { 338 name: "empty", 339 expected: "", 340 actual: "", 341 }, 342 } 343 for _, test := range tests { 344 result := JSON([]byte(test.expected), []byte(test.actual)) 345 var resultText string 346 if result != nil { 347 resultText = result.String() 348 } 349 if resultText != test.result { 350 t.Errorf("Unexpected result:\n%s\n", resultText) 351 } 352 } 353} 354 355func TestInterface(t *testing.T) { 356 tests := []struct { 357 name string 358 expected, actual interface{} 359 result string 360 }{ 361 { 362 name: "equal", 363 expected: []string{"foo", "bar"}, 364 actual: []string{"foo", "bar"}, 365 }, 366 { 367 name: "different", 368 expected: []string{"foo", "bar"}, 369 actual: []string{"bar", "bar"}, 370 result: `--- expected 371+++ actual 372@@ -1,4 +1,4 @@ 373 ([]string) (len=2) { 374- (string) (len=3) "foo", 375+ (string) (len=3) "bar", 376 (string) (len=3) "bar" 377 } 378`, 379 }, 380 } 381 for _, test := range tests { 382 result := Interface(test.expected, test.actual) 383 var resultText string 384 if result != nil { 385 resultText = result.String() 386 } 387 if resultText != test.result { 388 t.Errorf("Unexpected result:\n%s\n", resultText) 389 } 390 } 391} 392