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