| OLD | NEW |
| 1 // Copyright (c) 2013, the Dart project authors. Please see the AUTHORS file | 1 // Copyright (c) 2016, 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 |
| 7 import 'package:unittest/unittest.dart'; | 7 import 'package:observable/observable.dart'; |
| 8 import 'observe_test_utils.dart'; | 8 import 'package:test/test.dart'; |
| 9 |
| 10 import 'observable_test_utils.dart'; |
| 9 | 11 |
| 10 // This file contains code ported from: | 12 // This file contains code ported from: |
| 11 // https://github.com/rafaelw/ChangeSummary/blob/master/tests/test.js | 13 // https://github.com/rafaelw/ChangeSummary/blob/master/tests/test.js |
| 12 | 14 |
| 13 main() => dirtyCheckZone().run(listChangeTests); | 15 main() => listChangeTests(); |
| 14 | 16 |
| 15 // TODO(jmesserly): port or write array fuzzer tests | 17 // TODO(jmesserly): port or write array fuzzer tests |
| 16 listChangeTests() { | 18 listChangeTests() { |
| 17 StreamSubscription sub; | 19 StreamSubscription sub; |
| 18 var model; | 20 var model; |
| 19 | 21 |
| 20 tearDown(() { | 22 tearDown(() { |
| 21 sub.cancel(); | 23 sub.cancel(); |
| 22 model = null; | 24 model = null; |
| 23 }); | 25 }); |
| 24 | 26 |
| 25 _delta(i, r, a) => new ListChangeRecord(model, i, removed: r, addedCount: a); | 27 _delta(i, r, a) => new ListChangeRecord(model, i, removed: r, addedCount: a); |
| 26 | 28 |
| 27 test('sequential adds', () { | 29 test('sequential adds', () { |
| 28 model = toObservable([]); | 30 model = toObservable([]); |
| 29 model.add(0); | 31 model.add(0); |
| 30 | 32 |
| 31 var summary; | 33 var summary; |
| 32 sub = model.listChanges.listen((r) { summary = r; }); | 34 sub = model.listChanges.listen((r) => summary = r); |
| 33 | 35 |
| 34 model.add(1); | 36 model.add(1); |
| 35 model.add(2); | 37 model.add(2); |
| 36 | 38 |
| 37 expect(summary, null); | 39 expect(summary, null); |
| 38 return new Future(() => expectChanges(summary, [_delta(1, [], 2)])); | 40 return new Future(() => expectChanges(summary, [_delta(1, [], 2)])); |
| 39 }); | 41 }); |
| 40 | 42 |
| 41 test('List Splice Truncate And Expand With Length', () { | 43 test('List Splice Truncate And Expand With Length', () { |
| 42 model = toObservable(['a', 'b', 'c', 'd', 'e']); | 44 model = toObservable(['a', 'b', 'c', 'd', 'e']); |
| 43 | 45 |
| 44 var summary; | 46 var summary; |
| 45 sub = model.listChanges.listen((r) { summary = r; }); | 47 sub = model.listChanges.listen((r) => summary = r); |
| 46 | 48 |
| 47 model.length = 2; | 49 model.length = 2; |
| 48 | 50 |
| 49 return new Future(() { | 51 return new Future(() { |
| 50 expectChanges(summary, [_delta(2, ['c', 'd', 'e'], 0)]); | 52 expectChanges(summary, [ |
| 53 _delta(2, ['c', 'd', 'e'], 0) |
| 54 ]); |
| 51 summary = null; | 55 summary = null; |
| 52 model.length = 5; | 56 model.length = 5; |
| 53 | |
| 54 }).then(newMicrotask).then((_) { | 57 }).then(newMicrotask).then((_) { |
| 55 | |
| 56 expectChanges(summary, [_delta(2, [], 3)]); | 58 expectChanges(summary, [_delta(2, [], 3)]); |
| 57 }); | 59 }); |
| 58 }); | 60 }); |
| 59 | 61 |
| 60 group('List deltas can be applied', () { | 62 group('List deltas can be applied', () { |
| 63 applyAndCheckDeltas(model, copy, changes) => changes.then((summary) { |
| 64 // apply deltas to the copy |
| 65 for (var delta in summary) { |
| 66 copy.removeRange(delta.index, delta.index + delta.removed.length); |
| 67 for (int i = delta.addedCount - 1; i >= 0; i--) { |
| 68 copy.insert(delta.index, model[delta.index + i]); |
| 69 } |
| 70 } |
| 61 | 71 |
| 62 applyAndCheckDeltas(model, copy, changes) => changes.then((summary) { | 72 // Note: compare strings for easier debugging. |
| 63 // apply deltas to the copy | 73 expect('$copy', '$model', reason: 'summary $summary'); |
| 64 for (var delta in summary) { | 74 }); |
| 65 copy.removeRange(delta.index, delta.index + delta.removed.length); | |
| 66 for (int i = delta.addedCount - 1; i >= 0; i--) { | |
| 67 copy.insert(delta.index, model[delta.index + i]); | |
| 68 } | |
| 69 } | |
| 70 | |
| 71 // Note: compare strings for easier debugging. | |
| 72 expect('$copy', '$model', reason: 'summary $summary'); | |
| 73 }); | |
| 74 | 75 |
| 75 test('Contained', () { | 76 test('Contained', () { |
| 76 var model = toObservable(['a', 'b']); | 77 var model = toObservable(['a', 'b']); |
| 77 var copy = model.toList(); | 78 var copy = model.toList(); |
| 78 var changes = model.listChanges.first; | 79 var changes = model.listChanges.first; |
| 79 | 80 |
| 80 model.removeAt(1); | 81 model.removeAt(1); |
| 81 model.insertAll(0, ['c', 'd', 'e']); | 82 model.insertAll(0, ['c', 'd', 'e']); |
| 82 model.removeRange(1, 3); | 83 model.removeRange(1, 3); |
| 83 model.insert(1, 'f'); | 84 model.insert(1, 'f'); |
| (...skipping 113 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 197 | 198 |
| 198 return applyAndCheckDeltas(model, copy, changes); | 199 return applyAndCheckDeltas(model, copy, changes); |
| 199 }); | 200 }); |
| 200 | 201 |
| 201 test('Update Remove', () { | 202 test('Update Remove', () { |
| 202 var model = toObservable(['a', 'b', 'c', 'd']); | 203 var model = toObservable(['a', 'b', 'c', 'd']); |
| 203 var copy = model.toList(); | 204 var copy = model.toList(); |
| 204 var changes = model.listChanges.first; | 205 var changes = model.listChanges.first; |
| 205 | 206 |
| 206 model.removeAt(2); | 207 model.removeAt(2); |
| 207 model.insertAll(2, ['e', 'f', 'g']); // a b [e f g] d | 208 model.insertAll(2, ['e', 'f', 'g']); // a b [e f g] d |
| 208 model[0] = 'h'; | 209 model[0] = 'h'; |
| 209 model.removeAt(1); | 210 model.removeAt(1); |
| 210 | 211 |
| 211 return applyAndCheckDeltas(model, copy, changes); | 212 return applyAndCheckDeltas(model, copy, changes); |
| 212 }); | 213 }); |
| 213 | 214 |
| 214 test('Remove Mid List', () { | 215 test('Remove Mid List', () { |
| 215 var model = toObservable(['a', 'b', 'c', 'd']); | 216 var model = toObservable(['a', 'b', 'c', 'd']); |
| 216 var copy = model.toList(); | 217 var copy = model.toList(); |
| 217 var changes = model.listChanges.first; | 218 var changes = model.listChanges.first; |
| 218 | 219 |
| 219 model.removeAt(2); | 220 model.removeAt(2); |
| 220 | 221 |
| 221 return applyAndCheckDeltas(model, copy, changes); | 222 return applyAndCheckDeltas(model, copy, changes); |
| 222 }); | 223 }); |
| 223 }); | 224 }); |
| 224 | 225 |
| 225 group('edit distance', () { | 226 group('edit distance', () { |
| 227 assertEditDistance(orig, changes, expectedDist) => changes.then((summary) { |
| 228 var actualDistance = 0; |
| 229 for (var delta in summary) { |
| 230 actualDistance += delta.addedCount + delta.removed.length; |
| 231 } |
| 226 | 232 |
| 227 assertEditDistance(orig, changes, expectedDist) => changes.then((summary) { | 233 expect(actualDistance, expectedDist); |
| 228 var actualDistance = 0; | 234 }); |
| 229 for (var delta in summary) { | |
| 230 actualDistance += delta.addedCount + delta.removed.length; | |
| 231 } | |
| 232 | |
| 233 expect(actualDistance, expectedDist); | |
| 234 }); | |
| 235 | 235 |
| 236 test('add items', () { | 236 test('add items', () { |
| 237 var model = toObservable([]); | 237 var model = toObservable([]); |
| 238 var changes = model.listChanges.first; | 238 var changes = model.listChanges.first; |
| 239 model.addAll([1, 2, 3]); | 239 model.addAll([1, 2, 3]); |
| 240 return assertEditDistance(model, changes, 3); | 240 return assertEditDistance(model, changes, 3); |
| 241 }); | 241 }); |
| 242 | 242 |
| 243 test('trunacte and add, sharing a contiguous block', () { | 243 test('trunacte and add, sharing a contiguous block', () { |
| 244 var model = toObservable(['x', 'x', 'x', 'x', '1', '2', '3']); | 244 var model = toObservable(['x', 'x', 'x', 'x', '1', '2', '3']); |
| (...skipping 14 matching lines...) Expand all Loading... |
| 259 test('insert at beginning and end', () { | 259 test('insert at beginning and end', () { |
| 260 var model = toObservable([2, 3, 4]); | 260 var model = toObservable([2, 3, 4]); |
| 261 var changes = model.listChanges.first; | 261 var changes = model.listChanges.first; |
| 262 model.insert(0, 5); | 262 model.insert(0, 5); |
| 263 model[2] = 6; | 263 model[2] = 6; |
| 264 model.add(7); | 264 model.add(7); |
| 265 return assertEditDistance(model, changes, 4); | 265 return assertEditDistance(model, changes, 4); |
| 266 }); | 266 }); |
| 267 }); | 267 }); |
| 268 } | 268 } |
| OLD | NEW |