| Index: packages/observable/test/observable_test.dart
|
| diff --git a/packages/observe/test/observe_test.dart b/packages/observable/test/observable_test.dart
|
| similarity index 52%
|
| rename from packages/observe/test/observe_test.dart
|
| rename to packages/observable/test/observable_test.dart
|
| index 1f40953b4b84bfbe539c69c5a96a5ddde6d7280e..b89d654b18292ff25cf2e61367d7a56b6377a1ee 100644
|
| --- a/packages/observe/test/observe_test.dart
|
| +++ b/packages/observable/test/observable_test.dart
|
| @@ -1,94 +1,30 @@
|
| -// Copyright (c) 2013, the Dart project authors. Please see the AUTHORS file
|
| +// Copyright (c) 2016, the Dart project authors. Please see the AUTHORS file
|
| // for details. All rights reserved. Use of this source code is governed by a
|
| // BSD-style license that can be found in the LICENSE file.
|
|
|
| import 'dart:async';
|
| -import 'package:logging/logging.dart';
|
| -import 'package:observe/observe.dart';
|
| -import 'package:observe/src/dirty_check.dart' as dirty_check;
|
| -import 'package:unittest/unittest.dart';
|
| -import 'observe_test_utils.dart';
|
| -
|
| -import 'package:observe/mirrors_used.dart'; // make test smaller.
|
| -import 'package:smoke/mirrors.dart';
|
| -
|
| -main() {
|
| - useMirrors();
|
| - dirtyCheckZone().run(_tests);
|
| -}
|
| -
|
| -void _tests() {
|
| - // Note: to test the basic Observable system, we use ObservableBox due to its
|
| - // simplicity. We also test a variant that is based on dirty-checking.
|
| -
|
| - test('no observers at the start', () {
|
| - expect(dirty_check.allObservablesCount, 0);
|
| - });
|
| -
|
| - group('WatcherModel', () => _observeTests((x) => new WatcherModel(x)));
|
|
|
| - group('ObservableBox', () => _observeTests((x) => new ObservableBox(x)));
|
| +import 'package:observable/observable.dart';
|
| +import 'package:test/test.dart';
|
|
|
| - group('ModelSubclass', () => _observeTests((x) => new ModelSubclass(x)));
|
| -
|
| - group('dirtyCheck loops can be debugged', () {
|
| - var messages;
|
| - var subscription;
|
| - setUp(() {
|
| - messages = [];
|
| - subscription = Logger.root.onRecord.listen((record) {
|
| - messages.add(record.message);
|
| - });
|
| - });
|
| -
|
| - tearDown(() {
|
| - subscription.cancel();
|
| - });
|
| +import 'observable_test_utils.dart';
|
|
|
| - test('logs debug information', () {
|
| - var maxNumIterations = dirty_check.MAX_DIRTY_CHECK_CYCLES;
|
| -
|
| - var x = new WatcherModel(0);
|
| - var sub = x.changes.listen(expectAsync((_) { x.value++; },
|
| - count: maxNumIterations));
|
| - x.value = 1;
|
| - Observable.dirtyCheck();
|
| - expect(x.value, maxNumIterations + 1);
|
| - expect(messages.length, 2);
|
| -
|
| - expect(messages[0], contains('Possible loop'));
|
| - expect(messages[1], contains('index 0'));
|
| - expect(messages[1], contains('object: $x'));
|
| -
|
| - sub.cancel();
|
| - });
|
| - });
|
| -}
|
| -
|
| -void _observeTests(createModel(x)) {
|
| - final watch = createModel(null) is! ChangeNotifier;
|
| +main() => observableTests();
|
|
|
| +void observableTests() {
|
| // Track the subscriptions so we can clean them up in tearDown.
|
| List subs;
|
|
|
| - int initialObservers;
|
| setUp(() {
|
| - initialObservers = dirty_check.allObservablesCount;
|
| subs = [];
|
| -
|
| - if (watch) scheduleMicrotask(Observable.dirtyCheck);
|
| });
|
|
|
| tearDown(() {
|
| for (var sub in subs) sub.cancel();
|
| - return new Future(() {
|
| - expect(dirty_check.allObservablesCount, initialObservers,
|
| - reason: 'Observable object leaked');
|
| - });
|
| });
|
|
|
| test('handle future result', () {
|
| - var callback = expectAsync((){});
|
| + var callback = expectAsync(() {});
|
| return new Future(callback);
|
| });
|
|
|
| @@ -114,7 +50,7 @@ void _observeTests(createModel(x)) {
|
|
|
| subs.add(t.changes.listen(expectAsync((records) {
|
| called++;
|
| - expectPropertyChanges(records, watch ? 1 : 2);
|
| + expectPropertyChanges(records, 2);
|
| })));
|
|
|
| t.value = 41;
|
| @@ -142,8 +78,8 @@ void _observeTests(createModel(x)) {
|
| var t = createModel(123);
|
|
|
| verifyRecords(records) {
|
| - expectPropertyChanges(records, watch ? 1 : 2);
|
| - };
|
| + expectPropertyChanges(records, 2);
|
| + }
|
|
|
| subs.add(t.changes.listen(expectAsync(verifyRecords)));
|
| subs.add(t.changes.listen(expectAsync(verifyRecords)));
|
| @@ -155,24 +91,21 @@ void _observeTests(createModel(x)) {
|
| test('async processing model', () {
|
| var t = createModel(123);
|
| var records = [];
|
| - subs.add(t.changes.listen((r) { records.addAll(r); }));
|
| + subs.add(t.changes.listen((r) {
|
| + records.addAll(r);
|
| + }));
|
| t.value = 41;
|
| t.value = 42;
|
| expectChanges(records, [], reason: 'changes delived async');
|
|
|
| return new Future(() {
|
| - expectPropertyChanges(records, watch ? 1 : 2);
|
| + expectPropertyChanges(records, 2);
|
| records.clear();
|
|
|
| t.value = 777;
|
| expectChanges(records, [], reason: 'changes delived async');
|
| -
|
| }).then(newMicrotask).then((_) {
|
| expectPropertyChanges(records, 1);
|
| -
|
| - // Has no effect if there are no changes
|
| - Observable.dirtyCheck();
|
| - expectPropertyChanges(records, 1);
|
| });
|
| });
|
|
|
| @@ -183,7 +116,6 @@ void _observeTests(createModel(x)) {
|
| expectPropertyChanges(records, 1);
|
| sub.cancel();
|
| t.value = 777;
|
| - scheduleMicrotask(Observable.dirtyCheck);
|
| }));
|
| t.value = 42;
|
| });
|
| @@ -195,21 +127,22 @@ void _observeTests(createModel(x)) {
|
| expectPropertyChanges(records, 1);
|
| sub.cancel();
|
|
|
| - scheduleMicrotask(expectAsync(() {
|
| + scheduleMicrotask(() {
|
| subs.add(t.changes.listen(expectAsync((records) {
|
| expectPropertyChanges(records, 1);
|
| })));
|
| t.value = 777;
|
| - scheduleMicrotask(Observable.dirtyCheck);
|
| - }));
|
| + });
|
| }));
|
| t.value = 42;
|
| });
|
|
|
| test('cannot modify changes list', () {
|
| var t = createModel(123);
|
| - var records = null;
|
| - subs.add(t.changes.listen((r) { records = r; }));
|
| + var records;
|
| + subs.add(t.changes.listen((r) {
|
| + records = r;
|
| + }));
|
| t.value = 42;
|
|
|
| return new Future(() {
|
| @@ -221,16 +154,22 @@ void _observeTests(createModel(x)) {
|
| records[0] = new PropertyChangeRecord(t, #value, 0, 1);
|
| }, throwsUnsupportedError);
|
|
|
| - expect(() { records.clear(); }, throwsUnsupportedError);
|
| + expect(() {
|
| + records.clear();
|
| + }, throwsUnsupportedError);
|
|
|
| - expect(() { records.length = 0; }, throwsUnsupportedError);
|
| + expect(() {
|
| + records.length = 0;
|
| + }, throwsUnsupportedError);
|
| });
|
| });
|
|
|
| test('notifyChange', () {
|
| var t = createModel(123);
|
| var records = [];
|
| - subs.add(t.changes.listen((r) { records.addAll(r); }));
|
| + subs.add(t.changes.listen((r) {
|
| + records.addAll(r);
|
| + }));
|
| t.notifyChange(new PropertyChangeRecord(t, #value, 123, 42));
|
|
|
| return new Future(() {
|
| @@ -241,8 +180,10 @@ void _observeTests(createModel(x)) {
|
|
|
| test('notifyPropertyChange', () {
|
| var t = createModel(123);
|
| - var records = null;
|
| - subs.add(t.changes.listen((r) { records = r; }));
|
| + var records;
|
| + subs.add(t.changes.listen((r) {
|
| + records = r;
|
| + }));
|
| expect(t.notifyPropertyChange(#value, t.value, 42), 42,
|
| reason: 'notifyPropertyChange returns newValue');
|
|
|
| @@ -256,22 +197,26 @@ void _observeTests(createModel(x)) {
|
| expectPropertyChanges(records, int number) {
|
| expect(records.length, number, reason: 'expected $number change records');
|
| for (var record in records) {
|
| - expect(record is PropertyChangeRecord, true, reason:
|
| - 'record should be PropertyChangeRecord');
|
| - expect((record as PropertyChangeRecord).name, #value, reason:
|
| - 'record should indicate a change to the "value" property');
|
| + expect(record is PropertyChangeRecord, true,
|
| + reason: 'record should be PropertyChangeRecord');
|
| + expect((record as PropertyChangeRecord).name, #value,
|
| + reason: 'record should indicate a change to the "value" property');
|
| }
|
| }
|
|
|
| -// A test model based on dirty checking.
|
| -class WatcherModel<T> extends Observable {
|
| - @observable T value;
|
| +createModel(int number) => new ObservableSubclass(number);
|
|
|
| - WatcherModel([T initialValue]) : value = initialValue;
|
| +class ObservableSubclass<T> extends Observable {
|
| + ObservableSubclass([T initialValue]) : _value = initialValue;
|
|
|
| - String toString() => '#<$runtimeType value: $value>';
|
| -}
|
| + T get value => _value;
|
| + set value(T newValue) {
|
| + T oldValue = _value;
|
| + _value = newValue;
|
| + notifyPropertyChange(#value, oldValue, newValue);
|
| + }
|
|
|
| -class ModelSubclass<T> extends WatcherModel<T> {
|
| - ModelSubclass([T initialValue]) : super(initialValue);
|
| + T _value;
|
| +
|
| + String toString() => '#<$runtimeType value: $value>';
|
| }
|
|
|