OLD | NEW |
1 // Copyright (c) 2012, the Dart project authors. Please see the AUTHORS file | 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 | 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. | 3 // BSD-style license that can be found in the LICENSE file. |
4 | 4 |
5 part of matcher; | 5 part of matcher; |
6 | 6 |
7 /** | 7 /** |
8 * Returns a matcher that matches empty strings, maps or iterables | 8 * Returns a matcher that matches empty strings, maps or iterables |
9 * (including collections). | 9 * (including collections). |
10 */ | 10 */ |
(...skipping 155 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
166 'with key <${key}> ${location}', depth+1); | 166 'with key <${key}> ${location}', depth+1); |
167 if (reason != null) { | 167 if (reason != null) { |
168 break; | 168 break; |
169 } | 169 } |
170 } | 170 } |
171 } | 171 } |
172 } | 172 } |
173 } | 173 } |
174 } else { | 174 } else { |
175 reason = new StringDescription(); | 175 reason = new StringDescription(); |
176 var eType = typeName(expected); | |
177 var aType = typeName(actual); | |
178 var includeTypes = eType != aType; | |
179 // If we have recursed, show the expected value too; if not, | 176 // If we have recursed, show the expected value too; if not, |
180 // expect() will show it for us. | 177 // expect() will show it for us. |
181 if (depth > 0) { | 178 if (depth > 0) { |
182 reason.add('expected '); | 179 reason.add('expected '); |
183 if (includeTypes) { | |
184 reason.add(eType).add(':'); | |
185 } | |
186 reason.addDescriptionOf(expected).add(' but '); | 180 reason.addDescriptionOf(expected).add(' but '); |
187 } | 181 } |
188 reason.add('was '); | 182 reason.add('was '); |
189 if (includeTypes) { | |
190 reason.add(aType).add(':'); | |
191 } | |
192 reason.addDescriptionOf(actual); | 183 reason.addDescriptionOf(actual); |
193 if (includeTypes && depth == 0) { | |
194 reason.add(' (not type ').add(eType).add(')'); | |
195 } | |
196 } | 184 } |
197 } | 185 } |
198 if (reason != null && location.length > 0) { | 186 if (reason != null && location.length > 0) { |
199 reason.add(' ').add(location); | 187 reason.add(' ').add(location); |
200 } | 188 } |
201 return reason; | 189 return reason; |
202 } | 190 } |
203 | 191 |
204 String typeName(x) { | |
205 // dart2js blows up on some objects (e.g. window.navigator). | |
206 // So we play safe here. | |
207 try { | |
208 if (x == null) return "null"; | |
209 return x.runtimeType.toString(); | |
210 } catch (e) { | |
211 return "Unknown"; | |
212 } | |
213 } | |
214 | |
215 String _match(expected, actual) { | 192 String _match(expected, actual) { |
216 Description reason = _recursiveMatch(expected, actual, '', 0); | 193 Description reason = _recursiveMatch(expected, actual, '', 0); |
217 return reason == null ? null : reason.toString(); | 194 return reason == null ? null : reason.toString(); |
218 } | 195 } |
219 | 196 |
220 // TODO(gram) - see if we can make use of matchState here to avoid | 197 // TODO(gram) - see if we can make use of matchState here to avoid |
221 // recursing again in describeMismatch. | 198 // recursing again in describeMismatch. |
222 bool matches(item, MatchState matchState) => _match(_expected, item) == null; | 199 bool matches(item, MatchState matchState) => _match(_expected, item) == null; |
223 | 200 |
224 Description describe(Description description) => | 201 Description describe(Description description) => |
(...skipping 351 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
576 bool matches(item, MatchState matchState) { | 553 bool matches(item, MatchState matchState) { |
577 return _matcher.matches(item.length, matchState); | 554 return _matcher.matches(item.length, matchState); |
578 } | 555 } |
579 | 556 |
580 Description describe(Description description) => | 557 Description describe(Description description) => |
581 description.add('an object with length of '). | 558 description.add('an object with length of '). |
582 addDescriptionOf(_matcher); | 559 addDescriptionOf(_matcher); |
583 | 560 |
584 Description describeMismatch(item, Description mismatchDescription, | 561 Description describeMismatch(item, Description mismatchDescription, |
585 MatchState matchState, bool verbose) { | 562 MatchState matchState, bool verbose) { |
586 super.describeMismatch(item, mismatchDescription, matchState, verbose); | |
587 try { | 563 try { |
588 // We want to generate a different description if there is no length | 564 // We want to generate a different description if there is no length |
589 // property. This is harmless code that will throw if no length property | 565 // property. This is harmless code that will throw if no length property |
590 // but subtle enough that an optimizer shouldn't strip it out. | 566 // but subtle enough that an optimizer shouldn't strip it out. |
591 if (item.length * item.length >= 0) { | 567 if (item.length * item.length >= 0) { |
592 return mismatchDescription.add(' with length of '). | 568 return mismatchDescription.add('had length of '). |
593 addDescriptionOf(item.length); | 569 addDescriptionOf(item.length); |
594 } | 570 } |
595 } catch (e) { | 571 } catch (e) { |
596 return mismatchDescription.add(' has no length property'); | 572 return mismatchDescription.add('had no length property'); |
597 } | 573 } |
598 } | 574 } |
599 } | 575 } |
600 | 576 |
601 /** | 577 /** |
602 * Returns a matcher that matches if the match argument contains | 578 * Returns a matcher that matches if the match argument contains |
603 * the expected value. For [String]s this means substring matching; | 579 * the expected value. For [String]s this means substring matching; |
604 * for [Map]s it means the map has the key, and for [Iterable]s | 580 * for [Map]s it means the map has the key, and for [Iterable]s |
605 * (including [Iterable]s) it means the iterable has a matching | 581 * (including [Iterable]s) it means the iterable has a matching |
606 * element. In the case of iterables, [expected] can itself be a | 582 * element. In the case of iterables, [expected] can itself be a |
(...skipping 118 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
725 description.add(_featureDescription).add(' ').addDescriptionOf(_matcher); | 701 description.add(_featureDescription).add(' ').addDescriptionOf(_matcher); |
726 | 702 |
727 Description describeMismatch(item, Description mismatchDescription, | 703 Description describeMismatch(item, Description mismatchDescription, |
728 MatchState matchState, bool verbose) { | 704 MatchState matchState, bool verbose) { |
729 mismatchDescription.add(_featureName).add(' '); | 705 mismatchDescription.add(_featureName).add(' '); |
730 _matcher.describeMismatch(matchState.state['feature'], mismatchDescription, | 706 _matcher.describeMismatch(matchState.state['feature'], mismatchDescription, |
731 matchState.state['innerState'], verbose); | 707 matchState.state['innerState'], verbose); |
732 return mismatchDescription; | 708 return mismatchDescription; |
733 } | 709 } |
734 } | 710 } |
OLD | NEW |