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:observe/observe.dart'; | 6 import 'package:observe/observe.dart'; |
7 import 'package:unittest/unittest.dart'; | 7 import 'package:unittest/unittest.dart'; |
8 import 'observe_test_utils.dart'; | 8 import 'observe_test_utils.dart'; |
9 | 9 |
10 main() { | 10 main() => dirtyCheckZone().run(_runTests); |
| 11 |
| 12 _runTests() { |
11 // TODO(jmesserly): need all standard List API tests. | 13 // TODO(jmesserly): need all standard List API tests. |
12 | 14 |
13 StreamSubscription sub, sub2; | 15 StreamSubscription sub, sub2; |
14 | 16 |
15 sharedTearDown() { | 17 sharedTearDown() { |
16 list = null; | 18 list = null; |
17 sub.cancel(); | 19 sub.cancel(); |
18 if (sub2 != null) { | 20 if (sub2 != null) { |
19 sub2.cancel(); | 21 sub2.cancel(); |
20 sub2 = null; | 22 sub2 = null; |
21 } | 23 } |
22 } | 24 } |
23 | 25 |
24 group('observe length', () { | 26 group('observe length', () { |
25 | 27 |
26 ObservableList list; | 28 ObservableList list; |
27 List<ChangeRecord> changes; | 29 List<ChangeRecord> changes; |
28 | 30 |
29 setUp(() { | 31 setUp(() { |
30 list = toObservable([1, 2, 3]); | 32 list = toObservable([1, 2, 3]); |
31 changes = null; | 33 changes = null; |
32 sub = list.changes.listen((records) { | 34 sub = list.changes.listen((records) { |
33 changes = getPropertyChangeRecords(records, #length); | 35 changes = getPropertyChangeRecords(records, #length); |
34 }); | 36 }); |
35 }); | 37 }); |
36 | 38 |
37 tearDown(sharedTearDown); | 39 tearDown(sharedTearDown); |
38 | 40 |
39 observeTest('add changes length', () { | 41 test('add changes length', () { |
40 list.add(4); | 42 list.add(4); |
41 expect(list, [1, 2, 3, 4]); | 43 expect(list, [1, 2, 3, 4]); |
42 performMicrotaskCheckpoint(); | 44 return new Future(() { |
43 expectChanges(changes, [_lengthChange(3, 4)]); | 45 expectChanges(changes, [_lengthChange(3, 4)]); |
| 46 }); |
44 }); | 47 }); |
45 | 48 |
46 observeTest('removeObject', () { | 49 test('removeObject', () { |
47 list.remove(2); | 50 list.remove(2); |
48 expect(list, orderedEquals([1, 3])); | 51 expect(list, orderedEquals([1, 3])); |
49 | 52 |
50 performMicrotaskCheckpoint(); | 53 return new Future(() { |
51 expectChanges(changes, [_lengthChange(3, 2)]); | 54 expectChanges(changes, [_lengthChange(3, 2)]); |
| 55 }); |
52 }); | 56 }); |
53 | 57 |
54 observeTest('removeRange changes length', () { | 58 test('removeRange changes length', () { |
55 list.add(4); | 59 list.add(4); |
56 list.removeRange(1, 3); | 60 list.removeRange(1, 3); |
57 expect(list, [1, 4]); | 61 expect(list, [1, 4]); |
58 performMicrotaskCheckpoint(); | 62 return new Future(() { |
59 expectChanges(changes, [_lengthChange(3, 4), _lengthChange(4, 2)]); | 63 expectChanges(changes, [_lengthChange(3, 4), _lengthChange(4, 2)]); |
| 64 }); |
60 }); | 65 }); |
61 | 66 |
62 observeTest('length= changes length', () { | 67 test('length= changes length', () { |
63 list.length = 5; | 68 list.length = 5; |
64 expect(list, [1, 2, 3, null, null]); | 69 expect(list, [1, 2, 3, null, null]); |
65 performMicrotaskCheckpoint(); | 70 return new Future(() { |
66 expectChanges(changes, [_lengthChange(3, 5)]); | 71 expectChanges(changes, [_lengthChange(3, 5)]); |
| 72 }); |
67 }); | 73 }); |
68 | 74 |
69 observeTest('[]= does not change length', () { | 75 test('[]= does not change length', () { |
70 list[2] = 9000; | 76 list[2] = 9000; |
71 expect(list, [1, 2, 9000]); | 77 expect(list, [1, 2, 9000]); |
72 performMicrotaskCheckpoint(); | 78 return new Future(() { |
73 expectChanges(changes, null); | 79 expectChanges(changes, null); |
| 80 }); |
74 }); | 81 }); |
75 | 82 |
76 observeTest('clear changes length', () { | 83 test('clear changes length', () { |
77 list.clear(); | 84 list.clear(); |
78 expect(list, []); | 85 expect(list, []); |
79 performMicrotaskCheckpoint(); | 86 return new Future(() { |
80 expectChanges(changes, [_lengthChange(3, 0)]); | 87 expectChanges(changes, [_lengthChange(3, 0)]); |
| 88 }); |
81 }); | 89 }); |
82 }); | 90 }); |
83 | 91 |
84 group('observe index', () { | 92 group('observe index', () { |
85 List<ListChangeRecord> changes; | 93 List<ListChangeRecord> changes; |
86 | 94 |
87 setUp(() { | 95 setUp(() { |
88 list = toObservable([1, 2, 3]); | 96 list = toObservable([1, 2, 3]); |
89 changes = null; | 97 changes = null; |
90 sub = list.listChanges.listen((records) { | 98 sub = list.listChanges.listen((records) { |
91 changes = getListChangeRecords(records, 1); | 99 changes = getListChangeRecords(records, 1); |
92 }); | 100 }); |
93 }); | 101 }); |
94 | 102 |
95 tearDown(sharedTearDown); | 103 tearDown(sharedTearDown); |
96 | 104 |
97 observeTest('add does not change existing items', () { | 105 test('add does not change existing items', () { |
98 list.add(4); | 106 list.add(4); |
99 expect(list, [1, 2, 3, 4]); | 107 expect(list, [1, 2, 3, 4]); |
100 performMicrotaskCheckpoint(); | 108 return new Future(() { |
101 expectChanges(changes, []); | 109 expectChanges(changes, []); |
| 110 }); |
102 }); | 111 }); |
103 | 112 |
104 observeTest('[]= changes item', () { | 113 test('[]= changes item', () { |
105 list[1] = 777; | 114 list[1] = 777; |
106 expect(list, [1, 777, 3]); | 115 expect(list, [1, 777, 3]); |
107 performMicrotaskCheckpoint(); | 116 return new Future(() { |
108 expectChanges(changes, [_change(1, addedCount: 1, removed: [2])]); | 117 expectChanges(changes, [_change(1, addedCount: 1, removed: [2])]); |
| 118 }); |
109 }); | 119 }); |
110 | 120 |
111 observeTest('[]= on a different item does not fire change', () { | 121 test('[]= on a different item does not fire change', () { |
112 list[2] = 9000; | 122 list[2] = 9000; |
113 expect(list, [1, 2, 9000]); | 123 expect(list, [1, 2, 9000]); |
114 performMicrotaskCheckpoint(); | 124 return new Future(() { |
115 expectChanges(changes, []); | 125 expectChanges(changes, []); |
| 126 }); |
116 }); | 127 }); |
117 | 128 |
118 observeTest('set multiple times results in one change', () { | 129 test('set multiple times results in one change', () { |
119 list[1] = 777; | 130 list[1] = 777; |
120 list[1] = 42; | 131 list[1] = 42; |
121 expect(list, [1, 42, 3]); | 132 expect(list, [1, 42, 3]); |
122 performMicrotaskCheckpoint(); | 133 return new Future(() { |
123 expectChanges(changes, [ | 134 expectChanges(changes, [ |
124 _change(1, addedCount: 1, removed: [2]), | 135 _change(1, addedCount: 1, removed: [2]), |
125 ]); | 136 ]); |
| 137 }); |
126 }); | 138 }); |
127 | 139 |
128 observeTest('set length without truncating item means no change', () { | 140 test('set length without truncating item means no change', () { |
129 list.length = 2; | 141 list.length = 2; |
130 expect(list, [1, 2]); | 142 expect(list, [1, 2]); |
131 performMicrotaskCheckpoint(); | 143 return new Future(() { |
132 expectChanges(changes, []); | 144 expectChanges(changes, []); |
| 145 }); |
133 }); | 146 }); |
134 | 147 |
135 observeTest('truncate removes item', () { | 148 test('truncate removes item', () { |
136 list.length = 1; | 149 list.length = 1; |
137 expect(list, [1]); | 150 expect(list, [1]); |
138 performMicrotaskCheckpoint(); | 151 return new Future(() { |
139 expectChanges(changes, [_change(1, removed: [2, 3])]); | 152 expectChanges(changes, [_change(1, removed: [2, 3])]); |
| 153 }); |
140 }); | 154 }); |
141 | 155 |
142 observeTest('truncate and add new item', () { | 156 test('truncate and add new item', () { |
143 list.length = 1; | 157 list.length = 1; |
144 list.add(42); | 158 list.add(42); |
145 expect(list, [1, 42]); | 159 expect(list, [1, 42]); |
146 performMicrotaskCheckpoint(); | 160 return new Future(() { |
147 expectChanges(changes, [ | 161 expectChanges(changes, [ |
148 _change(1, removed: [2, 3], addedCount: 1) | 162 _change(1, removed: [2, 3], addedCount: 1) |
149 ]); | 163 ]); |
| 164 }); |
150 }); | 165 }); |
151 | 166 |
152 observeTest('truncate and add same item', () { | 167 test('truncate and add same item', () { |
153 list.length = 1; | 168 list.length = 1; |
154 list.add(2); | 169 list.add(2); |
155 expect(list, [1, 2]); | 170 expect(list, [1, 2]); |
156 performMicrotaskCheckpoint(); | 171 return new Future(() { |
157 expectChanges(changes, []); | 172 expectChanges(changes, []); |
| 173 }); |
158 }); | 174 }); |
159 }); | 175 }); |
160 | 176 |
161 observeTest('toString', () { | 177 test('toString', () { |
162 var list = toObservable([1, 2, 3]); | 178 var list = toObservable([1, 2, 3]); |
163 expect(list.toString(), '[1, 2, 3]'); | 179 expect(list.toString(), '[1, 2, 3]'); |
164 }); | 180 }); |
165 | 181 |
166 group('change records', () { | 182 group('change records', () { |
167 | 183 |
168 List<ChangeRecord> propRecords; | 184 List<ChangeRecord> propRecords; |
169 List<ListChangeRecord> listRecords; | 185 List<ListChangeRecord> listRecords; |
170 | 186 |
171 setUp(() { | 187 setUp(() { |
172 list = toObservable([1, 2, 3, 1, 3, 4]); | 188 list = toObservable([1, 2, 3, 1, 3, 4]); |
173 propRecords = null; | 189 propRecords = null; |
174 listRecords = null; | 190 listRecords = null; |
175 sub = list.changes.listen((r) { propRecords = r; }); | 191 sub = list.changes.listen((r) { propRecords = r; }); |
176 sub2 = list.listChanges.listen((r) { listRecords = r; }); | 192 sub2 = list.listChanges.listen((r) { listRecords = r; }); |
177 }); | 193 }); |
178 | 194 |
179 tearDown(sharedTearDown); | 195 tearDown(sharedTearDown); |
180 | 196 |
181 observeTest('read operations', () { | 197 test('read operations', () { |
182 expect(list.length, 6); | 198 expect(list.length, 6); |
183 expect(list[0], 1); | 199 expect(list[0], 1); |
184 expect(list.indexOf(4), 5); | 200 expect(list.indexOf(4), 5); |
185 expect(list.indexOf(1), 0); | 201 expect(list.indexOf(1), 0); |
186 expect(list.indexOf(1, 1), 3); | 202 expect(list.indexOf(1, 1), 3); |
187 expect(list.lastIndexOf(1), 3); | 203 expect(list.lastIndexOf(1), 3); |
188 expect(list.last, 4); | 204 expect(list.last, 4); |
189 var copy = new List<int>(); | 205 var copy = new List<int>(); |
190 list.forEach((i) { copy.add(i); }); | 206 list.forEach((i) { copy.add(i); }); |
191 expect(copy, orderedEquals([1, 2, 3, 1, 3, 4])); | 207 expect(copy, orderedEquals([1, 2, 3, 1, 3, 4])); |
192 performMicrotaskCheckpoint(); | 208 return new Future(() { |
193 | 209 // no change from read-only operators |
194 // no change from read-only operators | 210 expectChanges(propRecords, null); |
195 expectChanges(propRecords, null); | 211 expectChanges(listRecords, null); |
196 expectChanges(listRecords, null); | 212 }); |
197 }); | 213 }); |
198 | 214 |
199 observeTest('add', () { | 215 test('add', () { |
200 list.add(5); | 216 list.add(5); |
201 list.add(6); | 217 list.add(6); |
202 expect(list, orderedEquals([1, 2, 3, 1, 3, 4, 5, 6])); | 218 expect(list, orderedEquals([1, 2, 3, 1, 3, 4, 5, 6])); |
203 | 219 |
204 performMicrotaskCheckpoint(); | 220 return new Future(() { |
205 expectChanges(propRecords, [ | 221 expectChanges(propRecords, [ |
206 _lengthChange(6, 7), | 222 _lengthChange(6, 7), |
207 _lengthChange(7, 8), | 223 _lengthChange(7, 8), |
208 ]); | 224 ]); |
209 expectChanges(listRecords, [ _change(6, addedCount: 2) ]); | 225 expectChanges(listRecords, [ _change(6, addedCount: 2) ]); |
| 226 }); |
210 }); | 227 }); |
211 | 228 |
212 observeTest('[]=', () { | 229 test('[]=', () { |
213 list[1] = list.last; | 230 list[1] = list.last; |
214 expect(list, orderedEquals([1, 4, 3, 1, 3, 4])); | 231 expect(list, orderedEquals([1, 4, 3, 1, 3, 4])); |
215 | 232 |
216 performMicrotaskCheckpoint(); | 233 return new Future(() { |
217 expectChanges(propRecords, null); | 234 expectChanges(propRecords, null); |
218 expectChanges(listRecords, [ _change(1, addedCount: 1, removed: [2]) ]); | 235 expectChanges(listRecords, [ _change(1, addedCount: 1, removed: [2]) ]); |
| 236 }); |
219 }); | 237 }); |
220 | 238 |
221 observeTest('removeLast', () { | 239 test('removeLast', () { |
222 expect(list.removeLast(), 4); | 240 expect(list.removeLast(), 4); |
223 expect(list, orderedEquals([1, 2, 3, 1, 3])); | 241 expect(list, orderedEquals([1, 2, 3, 1, 3])); |
224 | 242 |
225 performMicrotaskCheckpoint(); | 243 return new Future(() { |
226 expectChanges(propRecords, [_lengthChange(6, 5)]); | 244 expectChanges(propRecords, [_lengthChange(6, 5)]); |
227 expectChanges(listRecords, [_change(5, removed: [4])]); | 245 expectChanges(listRecords, [_change(5, removed: [4])]); |
| 246 }); |
228 }); | 247 }); |
229 | 248 |
230 observeTest('removeRange', () { | 249 test('removeRange', () { |
231 list.removeRange(1, 4); | 250 list.removeRange(1, 4); |
232 expect(list, orderedEquals([1, 3, 4])); | 251 expect(list, orderedEquals([1, 3, 4])); |
233 | 252 |
234 performMicrotaskCheckpoint(); | 253 return new Future(() { |
235 expectChanges(propRecords, [_lengthChange(6, 3)]); | 254 expectChanges(propRecords, [_lengthChange(6, 3)]); |
236 expectChanges(listRecords, [_change(1, removed: [2, 3, 1])]); | 255 expectChanges(listRecords, [_change(1, removed: [2, 3, 1])]); |
| 256 }); |
237 }); | 257 }); |
238 | 258 |
239 observeTest('sort', () { | 259 test('sort', () { |
240 list.sort((x, y) => x - y); | 260 list.sort((x, y) => x - y); |
241 expect(list, orderedEquals([1, 1, 2, 3, 3, 4])); | 261 expect(list, orderedEquals([1, 1, 2, 3, 3, 4])); |
242 | 262 |
243 performMicrotaskCheckpoint(); | 263 return new Future(() { |
244 expectChanges(propRecords, null); | 264 expectChanges(propRecords, null); |
245 expectChanges(listRecords, [ | 265 expectChanges(listRecords, [ |
246 _change(1, addedCount: 1), | 266 _change(1, addedCount: 1), |
247 _change(4, removed: [1]) | 267 _change(4, removed: [1]) |
248 ]); | 268 ]); |
| 269 }); |
249 }); | 270 }); |
250 | 271 |
251 observeTest('clear', () { | 272 test('clear', () { |
252 list.clear(); | 273 list.clear(); |
253 expect(list, []); | 274 expect(list, []); |
254 | 275 |
255 performMicrotaskCheckpoint(); | 276 return new Future(() { |
256 expectChanges(propRecords, [ | 277 expectChanges(propRecords, [ |
257 _lengthChange(6, 0), | 278 _lengthChange(6, 0), |
258 new PropertyChangeRecord(list, #isEmpty, false, true), | 279 new PropertyChangeRecord(list, #isEmpty, false, true), |
259 new PropertyChangeRecord(list, #isNotEmpty, true, false), | 280 new PropertyChangeRecord(list, #isNotEmpty, true, false), |
260 ]); | 281 ]); |
261 expectChanges(listRecords, [_change(0, removed: [1, 2, 3, 1, 3, 4])]); | 282 expectChanges(listRecords, [_change(0, removed: [1, 2, 3, 1, 3, 4])]); |
| 283 }); |
262 }); | 284 }); |
263 }); | 285 }); |
264 } | 286 } |
265 | 287 |
266 ObservableList list; | 288 ObservableList list; |
267 | 289 |
268 _lengthChange(int oldValue, int newValue) => | 290 _lengthChange(int oldValue, int newValue) => |
269 new PropertyChangeRecord(list, #length, oldValue, newValue); | 291 new PropertyChangeRecord(list, #length, oldValue, newValue); |
270 | 292 |
271 _change(index, {removed: const [], addedCount: 0}) => new ListChangeRecord( | 293 _change(index, {removed: const [], addedCount: 0}) => new ListChangeRecord( |
272 list, index, removed: removed, addedCount: addedCount); | 294 list, index, removed: removed, addedCount: addedCount); |
OLD | NEW |