Chromium Code Reviews| Index: pkg/unittest/lib/src/core_matchers.dart |
| =================================================================== |
| --- pkg/unittest/lib/src/core_matchers.dart (revision 25630) |
| +++ pkg/unittest/lib/src/core_matchers.dart (working copy) |
| @@ -849,13 +849,8 @@ |
| * have a Widget class where each Widget has a price; we could make a |
| * [CustomMatcher] that can make assertions about prices with: |
| * |
| -<<<<<<< .mine |
| * class HasPrice extends CustomMatcher { |
| * const HasPrice(matcher) : |
| -======= |
| - * class HasPrice extends CustomMatcher { |
| - * HasPrice(matcher) : |
| ->>>>>>> .r25321 |
| * super("Widget with price that is", "price", matcher); |
| * featureValueOf(actual) => actual.price; |
| * } |
| @@ -899,3 +894,65 @@ |
| } |
| } |
| +/** |
| + * Returns a matcher that checks if a class instance has a property |
| + * with name [name], and optionally, if that property in turn satisfies |
| + * a [matcher]. |
| + */ |
| +Matcher hasProperty(String name, [matcher]) => |
| + new _HasProperty(name, matcher == null ? null : wrapMatcher(matcher)); |
| + |
| +class _HasProperty extends Matcher { |
| + final String _name; |
| + final Matcher _matcher; |
| + |
| + const _HasProperty(this._name, [this._matcher]); |
| + |
| + bool matches(item, Map matchState) { |
| + if (item is! Object) { |
| + addStateInfo(matchState, {'reason': 'Not an object'}); |
| + return false; |
| + } |
| + var mirror = reflect(item); |
| + var classMirror = mirror.type; |
| + var symbol = new Symbol(_name); |
| + if (!classMirror.getters.containsKey(symbol)) { |
| + addStateInfo(matchState, {'reason': 'No property named $_name'}); |
| + return false; |
| + } |
| + if (_matcher == null) return true; |
| + var result = mirror.getField(symbol); |
| + var resultMatches = _matcher.matches(result.reflectee, matchState); |
| + if (!resultMatches) { |
| + addStateInfo(matchState, {'value': result.reflectee}); |
| + } |
| + return resultMatches; |
| + } |
| + |
| + Description describe(Description description) { |
| + description.add('has property $_name'); |
|
Siggi Cherem (dart-lang)
2013/07/31 00:23:30
might be good to quote the name "$_name"
|
| + if (_matcher != null) { |
| + description.add(' which matches ').addDescriptionOf(_matcher); |
| + } |
| + return description; |
| + } |
| + |
| + Description describeMismatch(item, Description mismatchDescription, |
| + Map matchState, bool verbose) { |
| + var reason = matchState == null ? null : matchState['reason']; |
| + if (reason != null) { |
| + mismatchDescription.add(reason); |
| + } else { |
| + mismatchDescription.add('has property $_name with value '). |
|
Siggi Cherem (dart-lang)
2013/07/31 00:23:30
same here, so it reads:
has property "length" with
|
| + addDescriptionOf(matchState['value']); |
| + var innerDescription = new StringDescription(); |
| + _matcher.describeMismatch(matchState['value'], innerDescription, |
| + matchState['state'], verbose); |
| + if (innerDescription.length > 0) { |
| + mismatchDescription.add(' which ').add(innerDescription.toString()); |
| + } |
| + } |
| + return mismatchDescription; |
| + } |
| +} |
| + |