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 'package:observe/observe.dart'; | 5 import 'package:observe/observe.dart'; |
6 import 'package:unittest/unittest.dart'; | 6 import 'package:unittest/unittest.dart'; |
7 import 'observe_test_utils.dart'; | 7 import 'observe_test_utils.dart'; |
8 | 8 |
9 // This file contains code ported from: | 9 // This file contains code ported from: |
10 // https://github.com/rafaelw/ChangeSummary/blob/master/tests/test.js | 10 // https://github.com/rafaelw/ChangeSummary/blob/master/tests/test.js |
11 | 11 |
12 main() { | 12 main() { |
13 group('PathObserver', observePathTests); | 13 group('PathObserver', observePathTests); |
14 } | 14 } |
15 | 15 |
16 observePath(obj, path) => new PathObserver(obj, path); | 16 observePath(obj, path) => new PathObserver(obj, path); |
17 | 17 |
18 toSymbolMap(Map map) { | |
19 var result = new ObservableMap.linked(); | |
20 map.forEach((key, value) { | |
21 if (value is Map) value = toSymbolMap(value); | |
22 result[new Symbol(key)] = value; | |
23 }); | |
24 return result; | |
25 } | |
26 | |
27 observePathTests() { | 18 observePathTests() { |
28 observeTest('Degenerate Values', () { | 19 observeTest('Degenerate Values', () { |
29 expect(observePath(null, '').value, null); | 20 expect(observePath(null, '').value, null); |
30 expect(observePath(123, '').value, 123); | 21 expect(observePath(123, '').value, 123); |
31 expect(observePath(123, 'foo.bar.baz').value, null); | 22 expect(observePath(123, 'foo.bar.baz').value, null); |
32 | 23 |
33 // shouldn't throw: | 24 // shouldn't throw: |
34 observePath(123, '').changes.listen((_) {}).cancel(); | 25 observePath(123, '').changes.listen((_) {}).cancel(); |
35 observePath(null, '').value = null; | 26 observePath(null, '').value = null; |
36 observePath(123, '').value = 42; | 27 observePath(123, '').value = 42; |
(...skipping 22 matching lines...) Expand all Loading... |
59 obj.value.value = new ObservableBox(3); | 50 obj.value.value = new ObservableBox(3); |
60 expect(observePath(obj, 'value.value.value').value, 3); | 51 expect(observePath(obj, 'value.value.value').value, 3); |
61 | 52 |
62 obj.value = new ObservableBox(4); | 53 obj.value = new ObservableBox(4); |
63 expect(observePath(obj, 'value.value.value').value, null); | 54 expect(observePath(obj, 'value.value.value').value, null); |
64 expect(observePath(obj, 'value.value').value, 4); | 55 expect(observePath(obj, 'value.value').value, 4); |
65 }); | 56 }); |
66 | 57 |
67 | 58 |
68 observeTest('get value at path ObservableMap', () { | 59 observeTest('get value at path ObservableMap', () { |
69 var obj = toSymbolMap({'a': {'b': {'c': 1}}}); | 60 var obj = toObservable({'a': {'b': {'c': 1}}}); |
70 | 61 |
71 expect(observePath(obj, '').value, obj); | 62 expect(observePath(obj, '').value, obj); |
72 expect(observePath(obj, 'a').value, obj[#a]); | 63 expect(observePath(obj, 'a').value, obj['a']); |
73 expect(observePath(obj, 'a.b').value, obj[#a][#b]); | 64 expect(observePath(obj, 'a.b').value, obj['a']['b']); |
74 expect(observePath(obj, 'a.b.c').value, 1); | 65 expect(observePath(obj, 'a.b.c').value, 1); |
75 | 66 |
76 obj[#a][#b][#c] = 2; | 67 obj['a']['b']['c'] = 2; |
77 expect(observePath(obj, 'a.b.c').value, 2); | 68 expect(observePath(obj, 'a.b.c').value, 2); |
78 | 69 |
79 obj[#a][#b] = toSymbolMap({'c': 3}); | 70 obj['a']['b'] = toObservable({'c': 3}); |
80 expect(observePath(obj, 'a.b.c').value, 3); | 71 expect(observePath(obj, 'a.b.c').value, 3); |
81 | 72 |
82 obj[#a] = toSymbolMap({'b': 4}); | 73 obj['a'] = toObservable({'b': 4}); |
83 expect(observePath(obj, 'a.b.c').value, null); | 74 expect(observePath(obj, 'a.b.c').value, null); |
84 expect(observePath(obj, 'a.b').value, 4); | 75 expect(observePath(obj, 'a.b').value, 4); |
85 }); | 76 }); |
86 | 77 |
87 observeTest('set value at path', () { | 78 observeTest('set value at path', () { |
88 var obj = toSymbolMap({}); | 79 var obj = toObservable({}); |
89 observePath(obj, 'foo').value = 3; | 80 observePath(obj, 'foo').value = 3; |
90 expect(obj[#foo], 3); | 81 expect(obj['foo'], 3); |
91 | 82 |
92 var bar = toSymbolMap({ 'baz': 3 }); | 83 var bar = toObservable({ 'baz': 3 }); |
93 observePath(obj, 'bar').value = bar; | 84 observePath(obj, 'bar').value = bar; |
94 expect(obj[#bar], bar); | 85 expect(obj['bar'], bar); |
95 | 86 |
96 observePath(obj, 'bar.baz.bat').value = 'not here'; | 87 observePath(obj, 'bar.baz.bat').value = 'not here'; |
97 expect(observePath(obj, 'bar.baz.bat').value, null); | 88 expect(observePath(obj, 'bar.baz.bat').value, null); |
98 }); | 89 }); |
99 | 90 |
100 observeTest('set value back to same', () { | 91 observeTest('set value back to same', () { |
101 var obj = toSymbolMap({}); | 92 var obj = toObservable({}); |
102 var path = observePath(obj, 'foo'); | 93 var path = observePath(obj, 'foo'); |
103 var values = []; | 94 var values = []; |
104 path.changes.listen((_) { values.add(path.value); }); | 95 path.changes.listen((_) { values.add(path.value); }); |
105 | 96 |
106 path.value = 3; | 97 path.value = 3; |
107 expect(obj[#foo], 3); | 98 expect(obj['foo'], 3); |
108 expect(path.value, 3); | 99 expect(path.value, 3); |
109 | 100 |
110 observePath(obj, 'foo').value = 2; | 101 observePath(obj, 'foo').value = 2; |
111 performMicrotaskCheckpoint(); | 102 performMicrotaskCheckpoint(); |
112 expect(path.value, 2); | 103 expect(path.value, 2); |
113 expect(observePath(obj, 'foo').value, 2); | 104 expect(observePath(obj, 'foo').value, 2); |
114 | 105 |
115 observePath(obj, 'foo').value = 3; | 106 observePath(obj, 'foo').value = 3; |
116 performMicrotaskCheckpoint(); | 107 performMicrotaskCheckpoint(); |
117 expect(path.value, 3); | 108 expect(path.value, 3); |
118 | 109 |
119 performMicrotaskCheckpoint(); | 110 performMicrotaskCheckpoint(); |
120 expect(values, [2, 3]); | 111 expect(values, [2, 3]); |
121 }); | 112 }); |
122 | 113 |
123 observeTest('Observe and Unobserve - Paths', () { | 114 observeTest('Observe and Unobserve - Paths', () { |
124 var arr = toSymbolMap({}); | 115 var arr = toObservable({}); |
125 | 116 |
126 arr[#foo] = 'bar'; | 117 arr['foo'] = 'bar'; |
127 var fooValues = []; | 118 var fooValues = []; |
128 var fooPath = observePath(arr, 'foo'); | 119 var fooPath = observePath(arr, 'foo'); |
129 var fooSub = fooPath.changes.listen((_) { | 120 var fooSub = fooPath.changes.listen((_) { |
130 fooValues.add(fooPath.value); | 121 fooValues.add(fooPath.value); |
131 }); | 122 }); |
132 arr[#foo] = 'baz'; | 123 arr['foo'] = 'baz'; |
133 arr[#bat] = 'bag'; | 124 arr['bat'] = 'bag'; |
134 var batValues = []; | 125 var batValues = []; |
135 var batPath = observePath(arr, 'bat'); | 126 var batPath = observePath(arr, 'bat'); |
136 var batSub = batPath.changes.listen((_) { | 127 var batSub = batPath.changes.listen((_) { |
137 batValues.add(batPath.value); | 128 batValues.add(batPath.value); |
138 }); | 129 }); |
139 | 130 |
140 performMicrotaskCheckpoint(); | 131 performMicrotaskCheckpoint(); |
141 expect(fooValues, ['baz']); | 132 expect(fooValues, ['baz']); |
142 expect(batValues, []); | 133 expect(batValues, []); |
143 | 134 |
144 arr[#foo] = 'bar'; | 135 arr['foo'] = 'bar'; |
145 fooSub.cancel(); | 136 fooSub.cancel(); |
146 arr[#bat] = 'boo'; | 137 arr['bat'] = 'boo'; |
147 batSub.cancel(); | 138 batSub.cancel(); |
148 arr[#bat] = 'boot'; | 139 arr['bat'] = 'boot'; |
149 | 140 |
150 performMicrotaskCheckpoint(); | 141 performMicrotaskCheckpoint(); |
151 expect(fooValues, ['baz']); | 142 expect(fooValues, ['baz']); |
152 expect(batValues, []); | 143 expect(batValues, []); |
153 }); | 144 }); |
154 | 145 |
155 observeTest('Path Value With Indices', () { | 146 observeTest('Path Value With Indices', () { |
156 var model = toObservable([]); | 147 var model = toObservable([]); |
157 var path = observePath(model, '0'); | 148 var path = observePath(model, '0'); |
158 path.changes.listen(expectAsync1((_) { | 149 path.changes.listen(expectAsync1((_) { |
(...skipping 40 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
199 // Resume observing | 190 // Resume observing |
200 sub = path.changes.listen((_) { lastValue = path.value; }); | 191 sub = path.changes.listen((_) { lastValue = path.value; }); |
201 | 192 |
202 model.a.b.c = 'hello. Back for reals'; | 193 model.a.b.c = 'hello. Back for reals'; |
203 performMicrotaskCheckpoint(); | 194 performMicrotaskCheckpoint(); |
204 expect(lastValue, 'hello. Back for reals'); | 195 expect(lastValue, 'hello. Back for reals'); |
205 }); | 196 }); |
206 } | 197 } |
207 | 198 |
208 observeTest('observe map', () { | 199 observeTest('observe map', () { |
209 var model = toSymbolMap({'a': 1}); | 200 var model = toObservable({'a': 1}); |
210 var path = observePath(model, 'a'); | 201 var path = observePath(model, 'a'); |
211 | 202 |
212 var values = [path.value]; | 203 var values = [path.value]; |
213 var sub = path.changes.listen((_) { values.add(path.value); }); | 204 var sub = path.changes.listen((_) { values.add(path.value); }); |
214 expect(values, [1]); | 205 expect(values, [1]); |
215 | 206 |
216 model[#a] = 2; | 207 model['a'] = 2; |
217 performMicrotaskCheckpoint(); | 208 performMicrotaskCheckpoint(); |
218 expect(values, [1, 2]); | 209 expect(values, [1, 2]); |
219 | 210 |
220 sub.cancel(); | 211 sub.cancel(); |
221 model[#a] = 3; | 212 model['a'] = 3; |
222 performMicrotaskCheckpoint(); | 213 performMicrotaskCheckpoint(); |
223 expect(values, [1, 2]); | 214 expect(values, [1, 2]); |
224 }); | 215 }); |
225 } | 216 } |
226 | 217 |
227 @reflectable | 218 @reflectable |
228 class TestModel extends ChangeNotifierBase { | 219 class TestModel extends ChangeNotifier { |
229 var _a, _b, _c; | 220 var _a, _b, _c; |
230 | 221 |
231 TestModel(); | 222 TestModel(); |
232 | 223 |
233 get a => _a; | 224 get a => _a; |
234 | 225 |
235 void set a(newValue) { | 226 void set a(newValue) { |
236 _a = notifyPropertyChange(#a, _a, newValue); | 227 _a = notifyPropertyChange(#a, _a, newValue); |
237 } | 228 } |
238 | 229 |
239 get b => _b; | 230 get b => _b; |
240 | 231 |
241 void set b(newValue) { | 232 void set b(newValue) { |
242 _b = notifyPropertyChange(#b, _b, newValue); | 233 _b = notifyPropertyChange(#b, _b, newValue); |
243 } | 234 } |
244 | 235 |
245 get c => _c; | 236 get c => _c; |
246 | 237 |
247 void set c(newValue) { | 238 void set c(newValue) { |
248 _c = notifyPropertyChange(#c, _c, newValue); | 239 _c = notifyPropertyChange(#c, _c, newValue); |
249 } | 240 } |
250 } | 241 } |
251 | 242 |
252 class WatcherModel extends ObservableBase { | 243 class WatcherModel extends Observable { |
253 // TODO(jmesserly): dart2js does not let these be on the same line: | 244 // TODO(jmesserly): dart2js does not let these be on the same line: |
254 // @observable var a, b, c; | 245 // @observable var a, b, c; |
255 @observable var a; | 246 @observable var a; |
256 @observable var b; | 247 @observable var b; |
257 @observable var c; | 248 @observable var c; |
258 | 249 |
259 WatcherModel(); | 250 WatcherModel(); |
260 } | 251 } |
OLD | NEW |