Index: pkg/observe/test/path_observer_test.dart |
diff --git a/pkg/observe/test/path_observer_test.dart b/pkg/observe/test/path_observer_test.dart |
index 8d71680a39e0c3af1f3cfc1d27889e87c083db18..674f8b27f0c470b51be97bfcbb1087758f131201 100644 |
--- a/pkg/observe/test/path_observer_test.dart |
+++ b/pkg/observe/test/path_observer_test.dart |
@@ -9,7 +9,9 @@ import 'observe_test_utils.dart'; |
// This file contains code ported from: |
// https://github.com/rafaelw/ChangeSummary/blob/master/tests/test.js |
- |
+// Dart note: getting invalid properties is an error, unlike in JS where it |
+// returns undefined. This difference comes up where we check for _throwsNSM in |
+// the tests below. |
main() => dirtyCheckZone().run(() { |
group('PathObserver', observePathTests); |
@@ -68,19 +70,18 @@ main() => dirtyCheckZone().run(() { |
}); |
}); |
- |
observePathTests() { |
test('Degenerate Values', () { |
expect(new PathObserver(null, '').value, null); |
expect(new PathObserver(123, '').value, 123); |
- expect(new PathObserver(123, 'foo.bar.baz').value, null); |
+ expect(() => new PathObserver(123, 'foo.bar.baz').value, _throwsNSM('foo')); |
// shouldn't throw: |
new PathObserver(123, '')..open((_) {})..close(); |
new PropertyPath('').setValueFrom(null, null); |
new PropertyPath('').setValueFrom(123, 42); |
- new PropertyPath('foo.bar.baz').setValueFrom(123, 42); |
- |
+ expect(() => new PropertyPath('foo.bar.baz').setValueFrom(123, 42), |
+ _throwsNSM('foo')); |
var foo = {}; |
expect(new PathObserver(foo, '').value, foo); |
@@ -105,7 +106,8 @@ observePathTests() { |
expect(new PathObserver(obj, 'value.value.value').value, 3); |
obj.value = new ObservableBox(4); |
- expect(new PathObserver(obj, 'value.value.value').value, null); |
+ expect(() => new PathObserver(obj, 'value.value.value').value, |
+ _throwsNSM('value')); |
expect(new PathObserver(obj, 'value.value').value, 4); |
}); |
@@ -125,7 +127,7 @@ observePathTests() { |
expect(new PathObserver(obj, 'a.b.c').value, 3); |
obj['a'] = toObservable({'b': 4}); |
- expect(new PathObserver(obj, 'a.b.c').value, null); |
+ expect(() => new PathObserver(obj, 'a.b.c').value, _throwsNSM('c')); |
expect(new PathObserver(obj, 'a.b').value, 4); |
}); |
@@ -138,8 +140,9 @@ observePathTests() { |
new PropertyPath('bar').setValueFrom(obj, bar); |
expect(obj['bar'], bar); |
- new PropertyPath('bar.baz.bat').setValueFrom(obj, 'not here'); |
- expect(new PathObserver(obj, 'bar.baz.bat').value, null); |
+ expect(() => new PropertyPath('bar.baz.bat').setValueFrom(obj, 'not here'), |
+ _throwsNSM('bat=')); |
+ expect(() => new PathObserver(obj, 'bar.baz.bat').value, _throwsNSM('bat')); |
}); |
test('set value back to same', () { |
@@ -239,7 +242,13 @@ observePathTests() { |
var path = new PathObserver(model, 'a.b.c'); |
var lastValue = null; |
- path.open((x) { lastValue = x; }); |
+ var errorSeen = false; |
+ runZoned(() { |
+ path.open((x) { lastValue = x; }); |
+ }, onError: (e) { |
+ expect(e, _isNoSuchMethodOf('c')); |
+ errorSeen = true; |
+ }); |
model.a.b.c = 'hello, mom'; |
@@ -257,15 +266,17 @@ observePathTests() { |
expect(lastValue, 'hello, you'); |
model.a.b = 1; |
+ expect(errorSeen, isFalse); |
}).then(newMicrotask).then((_) { |
- expect(lastValue, null); |
+ expect(errorSeen, isTrue); |
+ expect(lastValue, 'hello, you'); |
// Stop observing |
path.close(); |
model.a.b = createModel()..c = 'hello, back again -- but not observing'; |
}).then(newMicrotask).then((_) { |
- expect(lastValue, null); |
+ expect(lastValue, 'hello, you'); |
// Resume observing |
new PathObserver(model, 'a.b.c').open((x) { lastValue = x; }); |
@@ -300,10 +311,10 @@ observePathTests() { |
var model = new ObjectWithErrors(); |
var observer = new PathObserver(model, 'foo'); |
- expect(() => observer.value, throws); |
+ expect(() => observer.value, _throwsNSM('bar')); |
expect(model.getFooCalled, 1); |
- expect(() { observer.value = 123; }, throws); |
+ expect(() { observer.value = 123; }, _throwsNSM('bar=')); |
expect(model.setFooCalled, [123]); |
}); |
@@ -352,6 +363,19 @@ observePathTests() { |
}); |
} |
+/// A matcher that checks that a closure throws a NoSuchMethodError matching the |
+/// given [name]. |
+_throwsNSM(String name) => throwsA(_isNoSuchMethodOf(name)); |
+ |
+/// A matcher that checkes whether an exception is a NoSuchMethodError matching |
+/// the given [name]. |
+_isNoSuchMethodOf(String name) => predicate((e) => |
+ e is NoSuchMethodError && |
+ // Dart2js and VM error messages are a bit different, but they both contain |
+ // the name. |
+ ('$e'.contains("'$name'") || // VM error |
+ '$e'.contains('\'Symbol("$name")\''))); // dart2js error |
+ |
class ObjectWithErrors { |
int getFooCalled = 0; |
List setFooCalled = []; |
@@ -383,7 +407,7 @@ class NoSuchMethodModel { |
} |
} |
-class IndexerModel { |
+class IndexerModel implements Indexable<String, dynamic> { |
var _foo = 42; |
List log = []; |