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