| OLD | NEW |
| 1 // Copyright (c) 2013, the Dart project authors. Please see the AUTHORS file | 1 // Copyright (c) 2013, 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 import 'dart:async'; | 5 import 'dart:async'; |
| 6 import 'package:logging/logging.dart'; | 6 import 'package:logging/logging.dart'; |
| 7 import 'package:observe/observe.dart'; | 7 import 'package:observe/observe.dart'; |
| 8 import 'package:observe/src/dirty_check.dart' as dirty_check; | 8 import 'package:observe/src/dirty_check.dart' as dirty_check; |
| 9 import 'package:unittest/unittest.dart'; | 9 import 'package:unittest/unittest.dart'; |
| 10 import 'observe_test_utils.dart'; | 10 import 'observe_test_utils.dart'; |
| 11 | 11 |
| 12 // Note: this ensures we run the dartanalyzer on the @observe package. | 12 // Note: this ensures we run the dartanalyzer on the @observe package. |
| 13 // @static-clean | 13 // @static-clean |
| 14 | 14 |
| 15 const _VALUE = const Symbol('value'); | 15 const _VALUE = const Symbol('value'); |
| 16 | 16 |
| 17 main() { | 17 void main() { |
| 18 // Note: to test the basic Observable system, we use ObservableBox due to its | 18 // Note: to test the basic Observable system, we use ObservableBox due to its |
| 19 // simplicity. We also test a variant that is based on dirty-checking. | 19 // simplicity. We also test a variant that is based on dirty-checking. |
| 20 | 20 |
| 21 observeTest('no observers at the start', () { | 21 observeTest('no observers at the start', () { |
| 22 expect(dirty_check.allObservablesCount, 0); | 22 expect(dirty_check.allObservablesCount, 0); |
| 23 }); | 23 }); |
| 24 | 24 |
| 25 group('WatcherModel', () { observeTests(watch: true); }); | 25 group('WatcherModel', () { _observeTests(watch: true); }); |
| 26 | 26 |
| 27 group('ObservableBox', () { observeTests(); }); | 27 group('ObservableBox', () { _observeTests(); }); |
| 28 | 28 |
| 29 group('dirtyCheck loops can be debugged', () { | 29 group('dirtyCheck loops can be debugged', () { |
| 30 var messages; | 30 var messages; |
| 31 var subscription; | 31 var subscription; |
| 32 setUp(() { | 32 setUp(() { |
| 33 messages = []; | 33 messages = []; |
| 34 subscription = Logger.root.onRecord.listen((record) { | 34 subscription = Logger.root.onRecord.listen((record) { |
| 35 messages.add(record.message); | 35 messages.add(record.message); |
| 36 }); | 36 }); |
| 37 }); | 37 }); |
| (...skipping 15 matching lines...) Expand all Loading... |
| 53 | 53 |
| 54 expect(messages[0], contains('Possible loop')); | 54 expect(messages[0], contains('Possible loop')); |
| 55 expect(messages[1], contains('index 0')); | 55 expect(messages[1], contains('index 0')); |
| 56 expect(messages[1], contains('object: $x')); | 56 expect(messages[1], contains('object: $x')); |
| 57 | 57 |
| 58 sub.cancel(); | 58 sub.cancel(); |
| 59 }); | 59 }); |
| 60 }); | 60 }); |
| 61 } | 61 } |
| 62 | 62 |
| 63 observeTests({bool watch: false}) { | 63 void _observeTests({bool watch: false}) { |
| 64 | |
| 65 final createModel = watch ? (x) => new WatcherModel(x) | 64 final createModel = watch ? (x) => new WatcherModel(x) |
| 66 : (x) => new ObservableBox(x); | 65 : (x) => new ObservableBox(x); |
| 67 | 66 |
| 68 // Track the subscriptions so we can clean them up in tearDown. | 67 // Track the subscriptions so we can clean them up in tearDown. |
| 69 List subs; | 68 List subs; |
| 70 | 69 |
| 71 int initialObservers; | 70 int initialObservers; |
| 72 setUp(() { | 71 setUp(() { |
| 73 initialObservers = dirty_check.allObservablesCount; | 72 initialObservers = dirty_check.allObservablesCount; |
| 74 subs = []; | 73 subs = []; |
| 75 | 74 |
| 76 if (watch) runAsync(Observable.dirtyCheck); | 75 if (watch) runAsync(Observable.dirtyCheck); |
| 77 }); | 76 }); |
| 78 | 77 |
| 79 tearDown(() { | 78 tearDown(() { |
| 80 for (var sub in subs) sub.cancel(); | 79 for (var sub in subs) sub.cancel(); |
| 81 performMicrotaskCheckpoint(); | 80 performMicrotaskCheckpoint(); |
| 82 | 81 |
| 83 expect(dirty_check.allObservablesCount, initialObservers, | 82 expect(dirty_check.allObservablesCount, initialObservers, |
| 84 reason: 'Observable object leaked'); | 83 reason: 'Observable object leaked'); |
| 85 }); | 84 }); |
| 86 | 85 |
| 86 observeTest('handle future result', () { |
| 87 var callback = expectAsync0((){}); |
| 88 return new Future(callback); |
| 89 }); |
| 90 |
| 87 observeTest('no observers', () { | 91 observeTest('no observers', () { |
| 88 var t = createModel(123); | 92 var t = createModel(123); |
| 89 expect(t.value, 123); | 93 expect(t.value, 123); |
| 90 t.value = 42; | 94 t.value = 42; |
| 91 expect(t.value, 42); | 95 expect(t.value, 42); |
| 92 expect(t.hasObservers, false); | 96 expect(t.hasObservers, false); |
| 93 }); | 97 }); |
| 94 | 98 |
| 95 observeTest('listen adds an observer', () { | 99 observeTest('listen adds an observer', () { |
| 96 var t = createModel(123); | 100 var t = createModel(123); |
| (...skipping 147 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 244 _changedValue(len) => new List.filled(len, new PropertyChangeRecord(_VALUE)); | 248 _changedValue(len) => new List.filled(len, new PropertyChangeRecord(_VALUE)); |
| 245 | 249 |
| 246 // A test model based on dirty checking. | 250 // A test model based on dirty checking. |
| 247 class WatcherModel<T> extends ObservableBase { | 251 class WatcherModel<T> extends ObservableBase { |
| 248 @observable T value; | 252 @observable T value; |
| 249 | 253 |
| 250 WatcherModel([T initialValue]) : value = initialValue; | 254 WatcherModel([T initialValue]) : value = initialValue; |
| 251 | 255 |
| 252 String toString() => '#<$runtimeType value: $value>'; | 256 String toString() => '#<$runtimeType value: $value>'; |
| 253 } | 257 } |
| OLD | NEW |