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 /** | |
6 * Returns a matcher which matches collections in which all elements | |
7 * match the given [matcher]. | |
8 */ | |
9 Matcher everyElement(matcher) => new _EveryElement(wrapMatcher(matcher)); | |
10 | |
11 class _EveryElement extends _CollectionMatcher { | |
12 Matcher _matcher; | |
13 | |
14 _EveryElement(Matcher this._matcher); | |
15 | |
16 bool matches(item) { | |
17 return item.every((e) => _matcher.matches(e)); | |
18 } | |
19 | |
20 Description describe(Description description) => | |
21 description.add('every element ').addDescriptionOf(_matcher); | |
22 } | |
23 | |
24 /** | |
25 * Returns a matcher which matches collections in which at least one | |
26 * element matches the given [matcher]. | |
27 */ | |
28 Matcher someElement(matcher) => new _SomeElement(wrapMatcher(matcher)); | |
29 | |
30 class _SomeElement extends _CollectionMatcher { | |
31 Matcher _matcher; | |
32 | |
33 _SomeElement(this._matcher); | |
34 | |
35 bool matches(item) { | |
36 return item.some( (e) => _matcher.matches(e) ); | |
37 } | |
38 | |
39 Description describe(Description description) => | |
40 description.add('some element ').addDescriptionOf(_matcher); | |
41 } | |
42 | |
43 /** | |
44 * Returns a matcher which matches Iterables that have the same | |
Siggi Cherem (dart-lang)
2012/06/06 00:26:08
dart-doc style: Iterables => [Iterable]s
(here and
gram
2012/06/06 16:23:56
Done.
| |
45 * length and the same elements as [expected], and in the same order. | |
46 */ | |
47 Matcher orderedEquals(Iterable expected) => new _OrderedEquals(expected); | |
48 | |
49 class _OrderedEquals extends BaseMatcher { | |
50 Iterable _expected; | |
51 | |
52 _OrderedEquals(this._expected); | |
53 | |
54 String _test(item) { | |
55 return _compareIterables(_expected, item, | |
56 (expected, actual, location) => expected == actual? null : location); | |
57 } | |
58 | |
59 bool matches(item) => (_test(item) == null); | |
60 | |
61 Description describe(Description description) => | |
62 description.add('equals ').addDescriptionOf(_expected).add(' ordered'); | |
63 | |
64 Description describeMismatch(item, Description mismatchDescription) => | |
65 mismatchDescription.add(_test(item)); | |
66 } | |
67 | |
68 /** | |
69 * Returns a matcher which matches Iterables that have the same | |
70 * length and the same elements as [expected], but not necessarily in | |
71 * the same order. Note that this is O(n^2) so should only be used on | |
72 * small objects. | |
73 */ | |
74 Matcher unorderedEquals(Iterable expected) => | |
75 new _UnorderedEquals(expected); | |
76 | |
77 class _UnorderedEquals extends BaseMatcher { | |
78 Iterable _expected; | |
79 | |
80 _UnorderedEquals(Iterable this._expected); | |
81 | |
82 String _test(item) { | |
83 if (item is !Iterable) { | |
84 return 'not iterable'; | |
85 } | |
86 // Check the lengths are the same. | |
87 var expectedLength = 0; | |
88 if (_expected is Collection) { | |
89 Collection cast = _expected; // "_expected as Collection" | |
90 expectedLength = cast.length; | |
91 } else { | |
92 for (var element in _expected) { | |
93 ++expectedLength; | |
94 } | |
95 } | |
96 var actualLength = 0; | |
97 if (item is Collection) { | |
98 actualLength = item.length; | |
99 } else { | |
100 for (var element in item) { | |
101 ++actualLength; | |
102 } | |
103 } | |
104 if (expectedLength > actualLength) { | |
105 return 'has too few elements (${actualLength} < ${expectedLength})'; | |
106 } else if (expectedLength < actualLength) { | |
107 return 'has too many elements (${actualLength} > ${expectedLength})'; | |
108 } | |
109 List<bool> matched = new List<bool>(actualLength); | |
110 var expectedPosition = 0; | |
111 for (var expectedElement in _expected) { | |
112 var actualPosition = 0; | |
113 var gotMatch = false; | |
114 for (var actualElement in item) { | |
115 if (!matched[actualPosition]) { | |
116 if (expectedElement == actualElement) { | |
117 matched[actualPosition] = gotMatch = true; | |
118 break; | |
119 } | |
120 } | |
121 ++actualPosition; | |
122 } | |
123 if (!gotMatch) { | |
124 return 'has no match for element ${expectedElement} ' | |
125 'at position ${expectedPosition}'; | |
126 } | |
127 ++expectedPosition; | |
128 } | |
129 return null; | |
130 } | |
131 | |
132 bool matches(item) => (_test(item) == null); | |
133 | |
134 Description describe(Description description) => | |
135 description.add('equals ').addDescriptionOf(_expected).add(' unordered'); | |
136 | |
137 Description describeMismatch(item, Description mismatchDescription) => | |
138 mismatchDescription.add(_test(item)); | |
139 } | |
140 | |
141 /** | |
142 * Collection matchers match against a collection. We add this intermediate | |
143 * class to give better mismatch error messages than the base Matcher class. | |
144 */ | |
145 | |
146 /*abstract*/ class _CollectionMatcher extends BaseMatcher { | |
147 const _CollectionMatcher(); | |
148 Description describeMismatch(item, Description mismatchDescription) { | |
149 if (item is !Collection) { | |
150 return mismatchDescription. | |
151 addDescriptionOf(item). | |
152 add(' not a collection'); | |
153 } else { | |
154 return super.describeMismatch(item, mismatchDescription); | |
155 } | |
156 } | |
157 } | |
OLD | NEW |