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 // This file contains code ported from: | |
11 // https://github.com/rafaelw/ChangeSummary/blob/master/tests/test.js | |
12 | |
13 main() => dirtyCheckZone().run(listChangeTests); | |
14 | |
15 // TODO(jmesserly): port or write array fuzzer tests | |
16 listChangeTests() { | |
17 StreamSubscription sub; | |
18 var model; | |
19 | |
20 tearDown(() { | |
21 sub.cancel(); | |
22 model = null; | |
23 }); | |
24 | |
25 _delta(i, r, a) => new ListChangeRecord(model, i, removed: r, addedCount: a); | |
26 | |
27 test('sequential adds', () { | |
28 model = toObservable([]); | |
29 model.add(0); | |
30 | |
31 var summary; | |
32 sub = model.listChanges.listen((r) { summary = r; }); | |
33 | |
34 model.add(1); | |
35 model.add(2); | |
36 | |
37 expect(summary, null); | |
38 return new Future(() => expectChanges(summary, [_delta(1, [], 2)])); | |
39 }); | |
40 | |
41 test('List Splice Truncate And Expand With Length', () { | |
42 model = toObservable(['a', 'b', 'c', 'd', 'e']); | |
43 | |
44 var summary; | |
45 sub = model.listChanges.listen((r) { summary = r; }); | |
46 | |
47 model.length = 2; | |
48 | |
49 return new Future(() { | |
50 expectChanges(summary, [_delta(2, ['c', 'd', 'e'], 0)]); | |
51 summary = null; | |
52 model.length = 5; | |
53 | |
54 }).then(newMicrotask).then((_) { | |
55 | |
56 expectChanges(summary, [_delta(2, [], 3)]); | |
57 }); | |
58 }); | |
59 | |
60 group('List deltas can be applied', () { | |
61 | |
62 applyAndCheckDeltas(model, copy, changes) => changes.then((summary) { | |
63 // apply deltas to the copy | |
64 for (var delta in summary) { | |
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 test('Contained', () { | |
76 var model = toObservable(['a', 'b']); | |
77 var copy = model.toList(); | |
78 var changes = model.listChanges.first; | |
79 | |
80 model.removeAt(1); | |
81 model.insertAll(0, ['c', 'd', 'e']); | |
82 model.removeRange(1, 3); | |
83 model.insert(1, 'f'); | |
84 | |
85 return applyAndCheckDeltas(model, copy, changes); | |
86 }); | |
87 | |
88 test('Delete Empty', () { | |
89 var model = toObservable([1]); | |
90 var copy = model.toList(); | |
91 var changes = model.listChanges.first; | |
92 | |
93 model.removeAt(0); | |
94 model.insertAll(0, ['a', 'b', 'c']); | |
95 | |
96 return applyAndCheckDeltas(model, copy, changes); | |
97 }); | |
98 | |
99 test('Right Non Overlap', () { | |
100 var model = toObservable(['a', 'b', 'c', 'd']); | |
101 var copy = model.toList(); | |
102 var changes = model.listChanges.first; | |
103 | |
104 model.removeRange(0, 1); | |
105 model.insert(0, 'e'); | |
106 model.removeRange(2, 3); | |
107 model.insertAll(2, ['f', 'g']); | |
108 | |
109 return applyAndCheckDeltas(model, copy, changes); | |
110 }); | |
111 | |
112 test('Left Non Overlap', () { | |
113 var model = toObservable(['a', 'b', 'c', 'd']); | |
114 var copy = model.toList(); | |
115 var changes = model.listChanges.first; | |
116 | |
117 model.removeRange(3, 4); | |
118 model.insertAll(3, ['f', 'g']); | |
119 model.removeRange(0, 1); | |
120 model.insert(0, 'e'); | |
121 | |
122 return applyAndCheckDeltas(model, copy, changes); | |
123 }); | |
124 | |
125 test('Right Adjacent', () { | |
126 var model = toObservable(['a', 'b', 'c', 'd']); | |
127 var copy = model.toList(); | |
128 var changes = model.listChanges.first; | |
129 | |
130 model.removeRange(1, 2); | |
131 model.insert(3, 'e'); | |
132 model.removeRange(2, 3); | |
133 model.insertAll(0, ['f', 'g']); | |
134 | |
135 return applyAndCheckDeltas(model, copy, changes); | |
136 }); | |
137 | |
138 test('Left Adjacent', () { | |
139 var model = toObservable(['a', 'b', 'c', 'd']); | |
140 var copy = model.toList(); | |
141 var changes = model.listChanges.first; | |
142 | |
143 model.removeRange(2, 4); | |
144 model.insert(2, 'e'); | |
145 | |
146 model.removeAt(1); | |
147 model.insertAll(1, ['f', 'g']); | |
148 | |
149 return applyAndCheckDeltas(model, copy, changes); | |
150 }); | |
151 | |
152 test('Right Overlap', () { | |
153 var model = toObservable(['a', 'b', 'c', 'd']); | |
154 var copy = model.toList(); | |
155 var changes = model.listChanges.first; | |
156 | |
157 model.removeAt(1); | |
158 model.insert(1, 'e'); | |
159 model.removeAt(1); | |
160 model.insertAll(1, ['f', 'g']); | |
161 | |
162 return applyAndCheckDeltas(model, copy, changes); | |
163 }); | |
164 | |
165 test('Left Overlap', () { | |
166 var model = toObservable(['a', 'b', 'c', 'd']); | |
167 var copy = model.toList(); | |
168 var changes = model.listChanges.first; | |
169 | |
170 model.removeAt(2); | |
171 model.insertAll(2, ['e', 'f', 'g']); | |
172 // a b [e f g] d | |
173 model.removeRange(1, 3); | |
174 model.insertAll(1, ['h', 'i', 'j']); | |
175 // a [h i j] f g d | |
176 | |
177 return applyAndCheckDeltas(model, copy, changes); | |
178 }); | |
179 | |
180 test('Prefix And Suffix One In', () { | |
181 var model = toObservable(['a', 'b', 'c', 'd']); | |
182 var copy = model.toList(); | |
183 var changes = model.listChanges.first; | |
184 | |
185 model.insert(0, 'z'); | |
186 model.add('z'); | |
187 | |
188 return applyAndCheckDeltas(model, copy, changes); | |
189 }); | |
190 | |
191 test('Remove First', () { | |
192 var model = toObservable([16, 15, 15]); | |
193 var copy = model.toList(); | |
194 var changes = model.listChanges.first; | |
195 | |
196 model.removeAt(0); | |
197 | |
198 return applyAndCheckDeltas(model, copy, changes); | |
199 }); | |
200 | |
201 test('Update Remove', () { | |
202 var model = toObservable(['a', 'b', 'c', 'd']); | |
203 var copy = model.toList(); | |
204 var changes = model.listChanges.first; | |
205 | |
206 model.removeAt(2); | |
207 model.insertAll(2, ['e', 'f', 'g']); // a b [e f g] d | |
208 model[0] = 'h'; | |
209 model.removeAt(1); | |
210 | |
211 return applyAndCheckDeltas(model, copy, changes); | |
212 }); | |
213 | |
214 test('Remove Mid List', () { | |
215 var model = toObservable(['a', 'b', 'c', 'd']); | |
216 var copy = model.toList(); | |
217 var changes = model.listChanges.first; | |
218 | |
219 model.removeAt(2); | |
220 | |
221 return applyAndCheckDeltas(model, copy, changes); | |
222 }); | |
223 }); | |
224 | |
225 group('edit distance', () { | |
226 | |
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 } | |
232 | |
233 expect(actualDistance, expectedDist); | |
234 }); | |
235 | |
236 test('add items', () { | |
237 var model = toObservable([]); | |
238 var changes = model.listChanges.first; | |
239 model.addAll([1, 2, 3]); | |
240 return assertEditDistance(model, changes, 3); | |
241 }); | |
242 | |
243 test('trunacte and add, sharing a contiguous block', () { | |
244 var model = toObservable(['x', 'x', 'x', 'x', '1', '2', '3']); | |
245 var changes = model.listChanges.first; | |
246 model.length = 0; | |
247 model.addAll(['1', '2', '3', 'y', 'y', 'y', 'y']); | |
248 return assertEditDistance(model, changes, 8); | |
249 }); | |
250 | |
251 test('truncate and add, sharing a discontiguous block', () { | |
252 var model = toObservable(['1', '2', '3', '4', '5']); | |
253 var changes = model.listChanges.first; | |
254 model.length = 0; | |
255 model.addAll(['a', '2', 'y', 'y', '4', '5', 'z', 'z']); | |
256 return assertEditDistance(model, changes, 7); | |
257 }); | |
258 | |
259 test('insert at beginning and end', () { | |
260 var model = toObservable([2, 3, 4]); | |
261 var changes = model.listChanges.first; | |
262 model.insert(0, 5); | |
263 model[2] = 6; | |
264 model.add(7); | |
265 return assertEditDistance(model, changes, 4); | |
266 }); | |
267 }); | |
268 } | |
OLD | NEW |