OLD | NEW |
| (Empty) |
1 // Copyright (c) 2012, the Dart project authors. Please see the AUTHORS file | |
2 // for details. All rights reserved. Use of this source code is governed by a | |
3 // BSD-style license that can be found in the LICENSE file. | |
4 | |
5 import 'dart:async'; | |
6 import 'dart:collection'; | |
7 | |
8 import 'package:unittest/unittest.dart'; | |
9 | |
10 import 'test_utils.dart'; | |
11 | |
12 void main() { | |
13 | |
14 initUtils(); | |
15 | |
16 // Core matchers | |
17 | |
18 group('Core matchers', () { | |
19 | |
20 test('isTrue', () { | |
21 shouldPass(true, isTrue); | |
22 shouldFail(false, isTrue, "Expected: true Actual: <false>"); | |
23 }); | |
24 | |
25 test('isFalse', () { | |
26 shouldPass(false, isFalse); | |
27 shouldFail(10, isFalse, "Expected: false Actual: <10>"); | |
28 shouldFail(true, isFalse, "Expected: false Actual: <true>"); | |
29 }); | |
30 | |
31 test('isNull', () { | |
32 shouldPass(null, isNull); | |
33 shouldFail(false, isNull, "Expected: null Actual: <false>"); | |
34 }); | |
35 | |
36 test('isNotNull', () { | |
37 shouldPass(false, isNotNull); | |
38 shouldFail(null, isNotNull, "Expected: not null Actual: <null>"); | |
39 }); | |
40 | |
41 test('same', () { | |
42 var a = new Map(); | |
43 var b = new Map(); | |
44 shouldPass(a, same(a)); | |
45 shouldFail(b, same(a), "Expected: same instance as {} Actual: {}"); | |
46 }); | |
47 | |
48 test('equals', () { | |
49 var a = new Map(); | |
50 var b = new Map(); | |
51 shouldPass(a, equals(a)); | |
52 shouldPass(a, equals(b)); | |
53 }); | |
54 | |
55 test('anything', () { | |
56 var a = new Map(); | |
57 shouldPass(0, anything); | |
58 shouldPass(null, anything); | |
59 shouldPass(a, anything); | |
60 shouldFail(a, isNot(anything), "Expected: not anything Actual: {}"); | |
61 }); | |
62 | |
63 test('throws', () { | |
64 shouldFail(doesNotThrow, throws, | |
65 matches( | |
66 r"Expected: throws" | |
67 r" Actual: <Closure(: \(\) => dynamic " | |
68 r"from Function 'doesNotThrow': static\.)?>" | |
69 r" Which: did not throw")); | |
70 shouldPass(doesThrow, throws); | |
71 shouldFail(true, throws, | |
72 "Expected: throws" | |
73 " Actual: <true>" | |
74 " Which: is not a Function or Future"); | |
75 }); | |
76 | |
77 test('throwsA', () { | |
78 shouldPass(doesThrow, throwsA(equals('X'))); | |
79 shouldFail(doesThrow, throwsA(equals('Y')), | |
80 matches( | |
81 r"Expected: throws 'Y'" | |
82 r" Actual: <Closure(: \(\) => dynamic " | |
83 r"from Function 'doesThrow': static\.)?>" | |
84 r" Which: threw 'X'")); | |
85 }); | |
86 | |
87 test('returnsNormally', () { | |
88 shouldPass(doesNotThrow, returnsNormally); | |
89 shouldFail(doesThrow, returnsNormally, | |
90 matches( | |
91 r"Expected: return normally" | |
92 r" Actual: <Closure(: \(\) => dynamic " | |
93 r"from Function 'doesThrow': static\.)?>" | |
94 r" Which: threw 'X'")); | |
95 }); | |
96 | |
97 | |
98 test('hasLength', () { | |
99 var a = new Map(); | |
100 var b = new List(); | |
101 shouldPass(a, hasLength(0)); | |
102 shouldPass(b, hasLength(0)); | |
103 shouldPass('a', hasLength(1)); | |
104 shouldFail(0, hasLength(0), new PrefixMatcher( | |
105 "Expected: an object with length of <0> " | |
106 "Actual: <0> " | |
107 "Which: has no length property")); | |
108 | |
109 b.add(0); | |
110 shouldPass(b, hasLength(1)); | |
111 shouldFail(b, hasLength(2), | |
112 "Expected: an object with length of <2> " | |
113 "Actual: [0] " | |
114 "Which: has length of <1>"); | |
115 | |
116 b.add(0); | |
117 shouldFail(b, hasLength(1), | |
118 "Expected: an object with length of <1> " | |
119 "Actual: [0, 0] " | |
120 "Which: has length of <2>"); | |
121 shouldPass(b, hasLength(2)); | |
122 }); | |
123 | |
124 test('scalar type mismatch', () { | |
125 shouldFail('error', equals(5.1), | |
126 "Expected: <5.1> " | |
127 "Actual: 'error'"); | |
128 }); | |
129 | |
130 test('nested type mismatch', () { | |
131 shouldFail(['error'], equals([5.1]), | |
132 "Expected: [5.1] " | |
133 "Actual: ['error'] " | |
134 "Which: was 'error' instead of <5.1> at location [0]"); | |
135 }); | |
136 | |
137 test('doubly-nested type mismatch', () { | |
138 shouldFail([['error']], equals([[5.1]]), | |
139 "Expected: [[5.1]] " | |
140 "Actual: [['error']] " | |
141 "Which: was 'error' instead of <5.1> at location [0][0]"); | |
142 }); | |
143 | |
144 test('doubly nested inequality', () { | |
145 var actual1 = [['foo', 'bar'], ['foo'], 3, []]; | |
146 var expected1 = [['foo', 'bar'], ['foo'], 4, []]; | |
147 var reason1 = "Expected: [['foo', 'bar'], ['foo'], 4, []] " | |
148 "Actual: [['foo', 'bar'], ['foo'], 3, []] " | |
149 "Which: was <3> instead of <4> at location [2]"; | |
150 | |
151 var actual2 = [['foo', 'barry'], ['foo'], 4, []]; | |
152 var expected2 = [['foo', 'bar'], ['foo'], 4, []]; | |
153 var reason2 = "Expected: [['foo', 'bar'], ['foo'], 4, []] " | |
154 "Actual: [['foo', 'barry'], ['foo'], 4, []] " | |
155 "Which: was 'barry' instead of 'bar' at location [0][1]"; | |
156 | |
157 var actual3 = [['foo', 'bar'], ['foo'], 4, {'foo':'bar'}]; | |
158 var expected3 = [['foo', 'bar'], ['foo'], 4, {'foo':'barry'}]; | |
159 var reason3 = "Expected: [['foo', 'bar'], ['foo'], 4, {'foo': 'barry'}] " | |
160 "Actual: [['foo', 'bar'], ['foo'], 4, {'foo': 'bar'}] " | |
161 "Which: was 'bar' instead of 'barry' at location [3]['foo']"; | |
162 | |
163 shouldFail(actual1, equals(expected1), reason1); | |
164 shouldFail(actual2, equals(expected2), reason2); | |
165 shouldFail(actual3, equals(expected3), reason3); | |
166 }); | |
167 }); | |
168 | |
169 group('Numeric Matchers', () { | |
170 | |
171 test('greaterThan', () { | |
172 shouldPass(10, greaterThan(9)); | |
173 shouldFail(9, greaterThan(10), | |
174 "Expected: a value greater than <10> " | |
175 "Actual: <9> " | |
176 "Which: is not a value greater than <10>"); | |
177 }); | |
178 | |
179 test('greaterThanOrEqualTo', () { | |
180 shouldPass(10, greaterThanOrEqualTo(10)); | |
181 shouldFail(9, greaterThanOrEqualTo(10), | |
182 "Expected: a value greater than or equal to <10> " | |
183 "Actual: <9> " | |
184 "Which: is not a value greater than or equal to <10>"); | |
185 }); | |
186 | |
187 test('lessThan', () { | |
188 shouldFail(10, lessThan(9), | |
189 "Expected: a value less than <9> " | |
190 "Actual: <10> " | |
191 "Which: is not a value less than <9>"); | |
192 shouldPass(9, lessThan(10)); | |
193 }); | |
194 | |
195 test('lessThanOrEqualTo', () { | |
196 shouldPass(10, lessThanOrEqualTo(10)); | |
197 shouldFail(11, lessThanOrEqualTo(10), | |
198 "Expected: a value less than or equal to <10> " | |
199 "Actual: <11> " | |
200 "Which: is not a value less than or equal to <10>"); | |
201 }); | |
202 | |
203 test('isZero', () { | |
204 shouldPass(0, isZero); | |
205 shouldFail(1, isZero, | |
206 "Expected: a value equal to <0> " | |
207 "Actual: <1> " | |
208 "Which: is not a value equal to <0>"); | |
209 }); | |
210 | |
211 test('isNonZero', () { | |
212 shouldFail(0, isNonZero, | |
213 "Expected: a value not equal to <0> " | |
214 "Actual: <0> " | |
215 "Which: is not a value not equal to <0>"); | |
216 shouldPass(1, isNonZero); | |
217 }); | |
218 | |
219 test('isPositive', () { | |
220 shouldFail(-1, isPositive, | |
221 "Expected: a positive value " | |
222 "Actual: <-1> " | |
223 "Which: is not a positive value"); | |
224 shouldFail(0, isPositive, | |
225 "Expected: a positive value " | |
226 "Actual: <0> " | |
227 "Which: is not a positive value"); | |
228 shouldPass(1, isPositive); | |
229 }); | |
230 | |
231 test('isNegative', () { | |
232 shouldPass(-1, isNegative); | |
233 shouldFail(0, isNegative, | |
234 "Expected: a negative value " | |
235 "Actual: <0> " | |
236 "Which: is not a negative value"); | |
237 }); | |
238 | |
239 test('isNonPositive', () { | |
240 shouldPass(-1, isNonPositive); | |
241 shouldPass(0, isNonPositive); | |
242 shouldFail(1, isNonPositive, | |
243 "Expected: a non-positive value " | |
244 "Actual: <1> " | |
245 "Which: is not a non-positive value"); | |
246 }); | |
247 | |
248 test('isNonNegative', () { | |
249 shouldPass(1, isNonNegative); | |
250 shouldPass(0, isNonNegative); | |
251 shouldFail(-1, isNonNegative, | |
252 "Expected: a non-negative value " | |
253 "Actual: <-1> " | |
254 "Which: is not a non-negative value"); | |
255 }); | |
256 | |
257 test('closeTo', () { | |
258 shouldPass(0, closeTo(0, 1)); | |
259 shouldPass(-1, closeTo(0, 1)); | |
260 shouldPass(1, closeTo(0, 1)); | |
261 shouldFail(1.001, closeTo(0, 1), | |
262 "Expected: a numeric value within <1> of <0> " | |
263 "Actual: <1.001> " | |
264 "Which: differs by <1.001>"); | |
265 shouldFail(-1.001, closeTo(0, 1), | |
266 "Expected: a numeric value within <1> of <0> " | |
267 "Actual: <-1.001> " | |
268 "Which: differs by <1.001>"); | |
269 }); | |
270 | |
271 test('inInclusiveRange', () { | |
272 shouldFail(-1, inInclusiveRange(0,2), | |
273 "Expected: be in range from 0 (inclusive) to 2 (inclusive) " | |
274 "Actual: <-1>"); | |
275 shouldPass(0, inInclusiveRange(0,2)); | |
276 shouldPass(1, inInclusiveRange(0,2)); | |
277 shouldPass(2, inInclusiveRange(0,2)); | |
278 shouldFail(3, inInclusiveRange(0,2), | |
279 "Expected: be in range from 0 (inclusive) to 2 (inclusive) " | |
280 "Actual: <3>"); | |
281 }); | |
282 | |
283 test('inExclusiveRange', () { | |
284 shouldFail(0, inExclusiveRange(0,2), | |
285 "Expected: be in range from 0 (exclusive) to 2 (exclusive) " | |
286 "Actual: <0>"); | |
287 shouldPass(1, inExclusiveRange(0,2)); | |
288 shouldFail(2, inExclusiveRange(0,2), | |
289 "Expected: be in range from 0 (exclusive) to 2 (exclusive) " | |
290 "Actual: <2>"); | |
291 }); | |
292 | |
293 test('inOpenClosedRange', () { | |
294 shouldFail(0, inOpenClosedRange(0,2), | |
295 "Expected: be in range from 0 (exclusive) to 2 (inclusive) " | |
296 "Actual: <0>"); | |
297 shouldPass(1, inOpenClosedRange(0,2)); | |
298 shouldPass(2, inOpenClosedRange(0,2)); | |
299 }); | |
300 | |
301 test('inClosedOpenRange', () { | |
302 shouldPass(0, inClosedOpenRange(0,2)); | |
303 shouldPass(1, inClosedOpenRange(0,2)); | |
304 shouldFail(2, inClosedOpenRange(0,2), | |
305 "Expected: be in range from 0 (inclusive) to 2 (exclusive) " | |
306 "Actual: <2>"); | |
307 }); | |
308 }); | |
309 | |
310 group('String Matchers', () { | |
311 | |
312 test('isEmpty', () { | |
313 shouldPass('', isEmpty); | |
314 shouldFail(null, isEmpty, | |
315 "Expected: empty Actual: <null>"); | |
316 shouldFail(0, isEmpty, | |
317 "Expected: empty Actual: <0>"); | |
318 shouldFail('a', isEmpty, "Expected: empty Actual: 'a'"); | |
319 }); | |
320 | |
321 test('equalsIgnoringCase', () { | |
322 shouldPass('hello', equalsIgnoringCase('HELLO')); | |
323 shouldFail('hi', equalsIgnoringCase('HELLO'), | |
324 "Expected: 'HELLO' ignoring case Actual: 'hi'"); | |
325 }); | |
326 | |
327 test('equalsIgnoringWhitespace', () { | |
328 shouldPass(' hello world ', equalsIgnoringWhitespace('hello world')); | |
329 shouldFail(' helloworld ', equalsIgnoringWhitespace('hello world'), | |
330 "Expected: 'hello world' ignoring whitespace " | |
331 "Actual: ' helloworld ' " | |
332 "Which: is 'helloworld' with whitespace compressed"); | |
333 }); | |
334 | |
335 test('startsWith', () { | |
336 shouldPass('hello', startsWith('')); | |
337 shouldPass('hello', startsWith('hell')); | |
338 shouldPass('hello', startsWith('hello')); | |
339 shouldFail('hello', startsWith('hello '), | |
340 "Expected: a string starting with 'hello ' " | |
341 "Actual: 'hello'"); | |
342 }); | |
343 | |
344 test('endsWith', () { | |
345 shouldPass('hello', endsWith('')); | |
346 shouldPass('hello', endsWith('lo')); | |
347 shouldPass('hello', endsWith('hello')); | |
348 shouldFail('hello', endsWith(' hello'), | |
349 "Expected: a string ending with ' hello' " | |
350 "Actual: 'hello'"); | |
351 }); | |
352 | |
353 test('contains', () { | |
354 shouldPass('hello', contains('')); | |
355 shouldPass('hello', contains('h')); | |
356 shouldPass('hello', contains('o')); | |
357 shouldPass('hello', contains('hell')); | |
358 shouldPass('hello', contains('hello')); | |
359 shouldFail('hello', contains(' '), | |
360 "Expected: contains ' ' Actual: 'hello'"); | |
361 }); | |
362 | |
363 test('stringContainsInOrder', () { | |
364 shouldPass('goodbye cruel world', stringContainsInOrder([''])); | |
365 shouldPass('goodbye cruel world', stringContainsInOrder(['goodbye'])); | |
366 shouldPass('goodbye cruel world', stringContainsInOrder(['cruel'])); | |
367 shouldPass('goodbye cruel world', stringContainsInOrder(['world'])); | |
368 shouldPass('goodbye cruel world', | |
369 stringContainsInOrder(['good', 'bye', 'world'])); | |
370 shouldPass('goodbye cruel world', | |
371 stringContainsInOrder(['goodbye', 'cruel'])); | |
372 shouldPass('goodbye cruel world', | |
373 stringContainsInOrder(['cruel', 'world'])); | |
374 shouldPass('goodbye cruel world', | |
375 stringContainsInOrder(['goodbye', 'cruel', 'world'])); | |
376 shouldFail('goodbye cruel world', | |
377 stringContainsInOrder(['goo', 'cruel', 'bye']), | |
378 "Expected: a string containing 'goo', 'cruel', 'bye' in order " | |
379 "Actual: 'goodbye cruel world'"); | |
380 }); | |
381 | |
382 test('matches', () { | |
383 shouldPass('c0d', matches('[a-z][0-9][a-z]')); | |
384 shouldPass('c0d', matches(new RegExp('[a-z][0-9][a-z]'))); | |
385 shouldFail('cOd', matches('[a-z][0-9][a-z]'), | |
386 "Expected: match '[a-z][0-9][a-z]' Actual: 'cOd'"); | |
387 }); | |
388 }); | |
389 | |
390 group('Iterable Matchers', () { | |
391 | |
392 test('isEmpty', () { | |
393 shouldPass([], isEmpty); | |
394 shouldFail([1], isEmpty, "Expected: empty Actual: [1]"); | |
395 }); | |
396 | |
397 test('contains', () { | |
398 var d = [1, 2]; | |
399 shouldPass(d, contains(1)); | |
400 shouldFail(d, contains(0), "Expected: contains <0> " | |
401 "Actual: [1, 2]"); | |
402 }); | |
403 | |
404 test('equals with matcher element', () { | |
405 var d = ['foo', 'bar']; | |
406 shouldPass(d, equals(['foo', startsWith('ba')])); | |
407 shouldFail(d, equals(['foo', endsWith('ba')]), | |
408 "Expected: ['foo', <a string ending with 'ba'>] " | |
409 "Actual: ['foo', 'bar'] " | |
410 "Which: does not match a string ending with 'ba' at location [1]"); | |
411 }); | |
412 | |
413 test('isIn', () { | |
414 var d = [1, 2]; | |
415 shouldPass(1, isIn(d)); | |
416 shouldFail(0, isIn(d), "Expected: is in [1, 2] Actual: <0>"); | |
417 }); | |
418 | |
419 test('everyElement', () { | |
420 var d = [1, 2]; | |
421 var e = [1, 1, 1]; | |
422 shouldFail(d, everyElement(1), | |
423 "Expected: every element(<1>) " | |
424 "Actual: [1, 2] " | |
425 "Which: has value <2> which doesn't match <1> at index 1"); | |
426 shouldPass(e, everyElement(1)); | |
427 }); | |
428 | |
429 test('nested everyElement', () { | |
430 var d = [['foo', 'bar'], ['foo'], []]; | |
431 var e = [['foo', 'bar'], ['foo'], 3, []]; | |
432 shouldPass(d, everyElement(anyOf(isEmpty, contains('foo')))); | |
433 shouldFail(d, everyElement(everyElement(equals('foo'))), | |
434 "Expected: every element(every element('foo')) " | |
435 "Actual: [['foo', 'bar'], ['foo'], []] " | |
436 "Which: has value ['foo', 'bar'] which has value 'bar' " | |
437 "which is different. Expected: foo Actual: bar ^ " | |
438 "Differ at offset 0 at index 1 at index 0"); | |
439 shouldFail(d, everyElement(allOf(hasLength(greaterThan(0)), | |
440 contains('foo'))), | |
441 "Expected: every element((an object with length of a value " | |
442 "greater than <0> and contains 'foo')) " | |
443 "Actual: [['foo', 'bar'], ['foo'], []] " | |
444 "Which: has value [] which has length of <0> at index 2"); | |
445 shouldFail(d, everyElement(allOf(contains('foo'), | |
446 hasLength(greaterThan(0)))), | |
447 "Expected: every element((contains 'foo' and " | |
448 "an object with length of a value greater than <0>)) " | |
449 "Actual: [['foo', 'bar'], ['foo'], []] " | |
450 "Which: has value [] which doesn't match (contains 'foo' and " | |
451 "an object with length of a value greater than <0>) at index 2"); | |
452 shouldFail(e, everyElement(allOf(contains('foo'), | |
453 hasLength(greaterThan(0)))), | |
454 "Expected: every element((contains 'foo' and an object with " | |
455 "length of a value greater than <0>)) " | |
456 "Actual: [['foo', 'bar'], ['foo'], 3, []] " | |
457 "Which: has value <3> which is not a string, map or iterable " | |
458 "at index 2"); | |
459 }); | |
460 | |
461 test('anyElement', () { | |
462 var d = [1, 2]; | |
463 var e = [1, 1, 1]; | |
464 shouldPass(d, anyElement(2)); | |
465 shouldFail(e, anyElement(2), | |
466 "Expected: some element <2> Actual: [1, 1, 1]"); | |
467 }); | |
468 | |
469 test('orderedEquals', () { | |
470 shouldPass([null], orderedEquals([null])); | |
471 var d = [1, 2]; | |
472 shouldPass(d, orderedEquals([1, 2])); | |
473 shouldFail(d, orderedEquals([2, 1]), | |
474 "Expected: equals [2, 1] ordered " | |
475 "Actual: [1, 2] " | |
476 "Which: was <1> instead of <2> at location [0]"); | |
477 }); | |
478 | |
479 test('unorderedEquals', () { | |
480 var d = [1, 2]; | |
481 shouldPass(d, unorderedEquals([2, 1])); | |
482 shouldFail(d, unorderedEquals([1]), | |
483 "Expected: equals [1] unordered " | |
484 "Actual: [1, 2] " | |
485 "Which: has too many elements (2 > 1)"); | |
486 shouldFail(d, unorderedEquals([3, 2, 1]), | |
487 "Expected: equals [3, 2, 1] unordered " | |
488 "Actual: [1, 2] " | |
489 "Which: has too few elements (2 < 3)"); | |
490 shouldFail(d, unorderedEquals([3, 1]), | |
491 "Expected: equals [3, 1] unordered " | |
492 "Actual: [1, 2] " | |
493 "Which: has no match for <3> at index 0"); | |
494 }); | |
495 | |
496 test('unorderedMatchess', () { | |
497 var d = [1, 2]; | |
498 shouldPass(d, unorderedMatches([2, 1])); | |
499 shouldPass(d, unorderedMatches([greaterThan(1), greaterThan(0)])); | |
500 shouldFail(d, unorderedMatches([greaterThan(0)]), | |
501 "Expected: matches [a value greater than <0>] unordered " | |
502 "Actual: [1, 2] " | |
503 "Which: has too many elements (2 > 1)"); | |
504 shouldFail(d, unorderedMatches([3, 2, 1]), | |
505 "Expected: matches [<3>, <2>, <1>] unordered " | |
506 "Actual: [1, 2] " | |
507 "Which: has too few elements (2 < 3)"); | |
508 shouldFail(d, unorderedMatches([3, 1]), | |
509 "Expected: matches [<3>, <1>] unordered " | |
510 "Actual: [1, 2] " | |
511 "Which: has no match for <3> at index 0"); | |
512 shouldFail(d, unorderedMatches([greaterThan(3), greaterThan(0)]), | |
513 "Expected: matches [a value greater than <3>, a value greater than " | |
514 "<0>] unordered " | |
515 "Actual: [1, 2] " | |
516 "Which: has no match for a value greater than <3> at index 0"); | |
517 }); | |
518 | |
519 test('pairwise compare', () { | |
520 var c = [1, 2]; | |
521 var d = [1, 2, 3]; | |
522 var e = [1, 4, 9]; | |
523 shouldFail('x', pairwiseCompare(e, (e,a) => a <= e, | |
524 "less than or equal"), | |
525 "Expected: pairwise less than or equal [1, 4, 9] " | |
526 "Actual: 'x' " | |
527 "Which: is not an Iterable"); | |
528 shouldFail(c, pairwiseCompare(e, (e,a) => a <= e, "less than or equal"), | |
529 "Expected: pairwise less than or equal [1, 4, 9] " | |
530 "Actual: [1, 2] " | |
531 "Which: has length 2 instead of 3"); | |
532 shouldPass(d, pairwiseCompare(e, (e,a) => a <= e, "less than or equal")); | |
533 shouldFail(d, pairwiseCompare(e, (e,a) => a < e, "less than"), | |
534 "Expected: pairwise less than [1, 4, 9] " | |
535 "Actual: [1, 2, 3] " | |
536 "Which: has <1> which is not less than <1> at index 0"); | |
537 shouldPass(d, pairwiseCompare(e, (e,a) => a * a == e, "square root of")); | |
538 shouldFail(d, pairwiseCompare(e, (e,a) => a + a == e, "double"), | |
539 "Expected: pairwise double [1, 4, 9] " | |
540 "Actual: [1, 2, 3] " | |
541 "Which: has <1> which is not double <1> at index 0"); | |
542 }); | |
543 }); | |
544 | |
545 group('Map Matchers', () { | |
546 | |
547 test('isEmpty', () { | |
548 var a = new Map(); | |
549 shouldPass({}, isEmpty); | |
550 shouldPass(a, isEmpty); | |
551 a['foo'] = 'bar'; | |
552 shouldFail(a, isEmpty, "Expected: empty " | |
553 "Actual: {'foo': 'bar'}"); | |
554 }); | |
555 | |
556 test('equals', () { | |
557 var a = new Map(); | |
558 a['foo'] = 'bar'; | |
559 var b = new Map(); | |
560 b['foo'] = 'bar'; | |
561 var c = new Map(); | |
562 c['bar'] = 'foo'; | |
563 shouldPass(a, equals(b)); | |
564 shouldFail(b, equals(c), | |
565 "Expected: {'bar': 'foo'} " | |
566 "Actual: {'foo': 'bar'} " | |
567 "Which: is missing map key 'bar'"); | |
568 }); | |
569 | |
570 test('equals with different lengths', () { | |
571 var a = new LinkedHashMap(); | |
572 a['foo'] = 'bar'; | |
573 var b = new LinkedHashMap(); | |
574 b['foo'] = 'bar'; | |
575 b['bar'] = 'foo'; | |
576 var c = new LinkedHashMap(); | |
577 c['bar'] = 'foo'; | |
578 c['barrista'] = 'caffeine'; | |
579 shouldFail(a, equals(b), | |
580 "Expected: {'foo': 'bar', 'bar': 'foo'} " | |
581 "Actual: {'foo': 'bar'} " | |
582 "Which: has different length and is missing map key 'bar'"); | |
583 shouldFail(b, equals(a), | |
584 "Expected: {'foo': 'bar'} " | |
585 "Actual: {'foo': 'bar', 'bar': 'foo'} " | |
586 "Which: has different length and has extra map key 'bar'"); | |
587 shouldFail(b, equals(c), | |
588 "Expected: {'bar': 'foo', 'barrista': 'caffeine'} " | |
589 "Actual: {'foo': 'bar', 'bar': 'foo'} " | |
590 "Which: is missing map key 'barrista'"); | |
591 shouldFail(c, equals(b), | |
592 "Expected: {'foo': 'bar', 'bar': 'foo'} " | |
593 "Actual: {'bar': 'foo', 'barrista': 'caffeine'} " | |
594 "Which: is missing map key 'foo'"); | |
595 shouldFail(a, equals(c), | |
596 "Expected: {'bar': 'foo', 'barrista': 'caffeine'} " | |
597 "Actual: {'foo': 'bar'} " | |
598 "Which: has different length and is missing map key 'bar'"); | |
599 shouldFail(c, equals(a), | |
600 "Expected: {'foo': 'bar'} " | |
601 "Actual: {'bar': 'foo', 'barrista': 'caffeine'} " | |
602 "Which: has different length and is missing map key 'foo'"); | |
603 }); | |
604 | |
605 test('equals with matcher value', () { | |
606 var a = new Map(); | |
607 a['foo'] = 'bar'; | |
608 shouldPass(a, equals({'foo': startsWith('ba')})); | |
609 shouldFail(a, equals({'foo': endsWith('ba')}), | |
610 "Expected: {'foo': <a string ending with 'ba'>} " | |
611 "Actual: {'foo': 'bar'} " | |
612 "Which: does not match a string ending with 'ba' " | |
613 "at location ['foo']"); | |
614 }); | |
615 | |
616 test('contains', () { | |
617 var a = new Map(); | |
618 a['foo'] = 'bar'; | |
619 var b = new Map(); | |
620 shouldPass(a, contains('foo')); | |
621 shouldFail(b, contains('foo'), | |
622 "Expected: contains 'foo' Actual: {}"); | |
623 shouldFail(10, contains('foo'), | |
624 "Expected: contains 'foo' Actual: <10> " | |
625 "Which: is not a string, map or iterable"); | |
626 }); | |
627 | |
628 test('containsValue', () { | |
629 var a = new Map(); | |
630 a['foo'] = 'bar'; | |
631 shouldPass(a, containsValue('bar')); | |
632 shouldFail(a, containsValue('ba'), | |
633 "Expected: contains value 'ba' " | |
634 "Actual: {'foo': 'bar'}"); | |
635 }); | |
636 | |
637 test('containsPair', () { | |
638 var a = new Map(); | |
639 a['foo'] = 'bar'; | |
640 shouldPass(a, containsPair('foo', 'bar')); | |
641 shouldFail(a, containsPair('foo', 'ba'), | |
642 "Expected: contains pair 'foo' => 'ba' " | |
643 "Actual: {'foo': 'bar'} " | |
644 "Which: is different. Both strings start the same, but " | |
645 "the given value also has the following trailing characters: r"); | |
646 shouldFail(a, containsPair('fo', 'bar'), | |
647 "Expected: contains pair 'fo' => 'bar' " | |
648 "Actual: {'foo': 'bar'} " | |
649 "Which: doesn't contain key 'fo'"); | |
650 }); | |
651 | |
652 test('hasLength', () { | |
653 var a = new Map(); | |
654 a['foo'] = 'bar'; | |
655 var b = new Map(); | |
656 shouldPass(a, hasLength(1)); | |
657 shouldFail(b, hasLength(1), | |
658 "Expected: an object with length of <1> " | |
659 "Actual: {} " | |
660 "Which: has length of <0>"); | |
661 }); | |
662 }); | |
663 | |
664 group('Operator Matchers', () { | |
665 | |
666 test('anyOf', () { | |
667 shouldFail(0, anyOf([equals(1), equals(2)]), | |
668 "Expected: (<1> or <2>) Actual: <0>"); | |
669 shouldPass(1, anyOf([equals(1), equals(2)])); | |
670 }); | |
671 | |
672 test('allOf', () { | |
673 shouldPass(1, allOf([lessThan(10), greaterThan(0)])); | |
674 shouldFail(-1, allOf([lessThan(10), greaterThan(0)]), | |
675 "Expected: (a value less than <10> and a value greater than <0>) " | |
676 "Actual: <-1> " | |
677 "Which: is not a value greater than <0>"); | |
678 }); | |
679 }); | |
680 | |
681 group('Future Matchers', () { | |
682 | |
683 test('completes - unexpected error', () { | |
684 var completer = new Completer(); | |
685 completer.completeError('X'); | |
686 shouldFail(completer.future, completes, | |
687 contains('Expected future to complete successfully, ' | |
688 'but it failed with X'), | |
689 isAsync: true); | |
690 }); | |
691 | |
692 test('completes - successfully', () { | |
693 var completer = new Completer(); | |
694 completer.complete('1'); | |
695 shouldPass(completer.future, completes, isAsync: true); | |
696 }); | |
697 | |
698 test('throws - unexpected to see normal completion', () { | |
699 var completer = new Completer(); | |
700 completer.complete('1'); | |
701 shouldFail(completer.future, throws, | |
702 contains("Expected future to fail, but succeeded with '1'"), | |
703 isAsync: true); | |
704 }); | |
705 | |
706 test('throws - expected to see exception', () { | |
707 var completer = new Completer(); | |
708 completer.completeError('X'); | |
709 shouldPass(completer.future, throws, isAsync: true); | |
710 }); | |
711 | |
712 test('throws - expected to see exception thrown later on', () { | |
713 var completer = new Completer(); | |
714 var chained = completer.future.then((_) { throw 'X'; }); | |
715 shouldPass(chained, throws, isAsync: true); | |
716 completer.complete('1'); | |
717 }); | |
718 | |
719 test('throwsA - unexpected normal completion', () { | |
720 var completer = new Completer(); | |
721 completer.complete('1'); | |
722 shouldFail(completer.future, throwsA(equals('X')), | |
723 contains("Expected future to fail, but succeeded with '1'"), | |
724 isAsync: true); | |
725 }); | |
726 | |
727 test('throwsA - correct error', () { | |
728 var completer = new Completer(); | |
729 completer.completeError('X'); | |
730 shouldPass(completer.future, throwsA(equals('X')), isAsync: true); | |
731 }); | |
732 | |
733 test('throwsA - wrong error', () { | |
734 var completer = new Completer(); | |
735 completer.completeError('X'); | |
736 shouldFail(completer.future, throwsA(equals('Y')), | |
737 "Expected: 'Y' Actual: 'X' " | |
738 "Which: is different. " | |
739 "Expected: Y Actual: X ^ Differ at offset 0", | |
740 isAsync: true); | |
741 }); | |
742 }); | |
743 | |
744 group('Predicate Matchers', () { | |
745 test('isInstanceOf', () { | |
746 shouldFail(0, predicate((x) => x is String, "an instance of String"), | |
747 "Expected: an instance of String Actual: <0>"); | |
748 shouldPass('cow', predicate((x) => x is String, "an instance of String")); | |
749 }); | |
750 }); | |
751 | |
752 group('exception/error matchers', () { | |
753 // TODO(gram): extend this to more types; for now this is just | |
754 // the types being added in this CL. | |
755 | |
756 // TODO: enable this test when it works. | |
757 // See issue 12052. | |
758 skip_test('throwsCyclicInitializationError', () { | |
759 expect(() => new Bicycle(), throwsCyclicInitializationError); | |
760 }); | |
761 | |
762 test('throwsAbstractClassInstantiationError', () { | |
763 expect(() => new Abstraction(), throwsAbstractClassInstantiationError); | |
764 }); | |
765 | |
766 test('throwsConcurrentModificationError', () { | |
767 expect(() { | |
768 var a = { 'foo': 'bar' }; | |
769 for (var k in a.keys) { | |
770 a.remove(k); | |
771 } | |
772 }, throwsConcurrentModificationError); | |
773 }); | |
774 | |
775 test('throwsNullThrownError', () { | |
776 expect(() => throw null, throwsNullThrownError); | |
777 }); | |
778 | |
779 test('throwsFallThroughError', () { | |
780 expect(() { | |
781 var a = 0; | |
782 switch (a) { | |
783 case 0: | |
784 a += 1; | |
785 case 1: | |
786 return; | |
787 } | |
788 }, throwsFallThroughError); | |
789 }); | |
790 }); | |
791 } | |
792 | |
793 class Bicycle { | |
794 static var foo = bar(); | |
795 | |
796 static bar() { | |
797 return foo + 1; | |
798 } | |
799 | |
800 X() { | |
801 print(foo); | |
802 } | |
803 } | |
804 | |
805 abstract class Abstraction { | |
806 void norealization(); | |
807 } | |
808 | |
OLD | NEW |