| 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 = [];
|
|
|
|
|