OLD | NEW |
---|---|
1 // Copyright (c) 2015, the Dart project authors. Please see the AUTHORS file | 1 // Copyright (c) 2015, 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 @TestOn('browser') | 4 @TestOn('browser') |
5 library polymer_elements.test.firebase_collection_test; | 5 library polymer_elements.test.firebase_collection_test; |
6 | 6 |
7 import 'dart:async'; | 7 import 'dart:async'; |
8 import 'dart:js'; | 8 import 'dart:js'; |
9 import 'package:polymer/polymer.dart'; | 9 import 'package:polymer/polymer.dart'; |
10 import 'package:polymer_elements/firebase_collection.dart'; | 10 import 'package:polymer_elements/firebase_collection.dart'; |
11 import 'package:web_components/web_components.dart'; | 11 import 'package:web_components/web_components.dart'; |
12 import 'package:test/test.dart'; | 12 import 'package:test/test.dart'; |
13 import 'common.dart'; | 13 import 'common.dart'; |
14 import 'firebase_test_helpers.dart'; | |
14 | 15 |
15 main() async { | 16 main() async { |
16 await initWebComponents(); | 17 await initWebComponents(); |
17 | 18 |
18 group('<firebase-collection>', () { | 19 group('firebase-collection', () { |
19 FirebaseCollection firebase; | 20 FirebaseCollection firebase; |
20 | 21 |
21 group('collection manipulation', () { | 22 tearDown(() { |
23 if (firebase != null) removeFirebase(firebase); | |
24 }); | |
25 | |
26 group('basic usage', () { | |
27 var numberOfItems; | |
28 | |
29 setUp(() { | |
30 numberOfItems = 3; | |
31 firebase = | |
32 fixtureFirebase('TrivialCollection', arrayOfObjects(numberOfItems)); | |
33 return wait(1); | |
34 }); | |
35 | |
36 test('exposes data as an array', () { | |
37 expect(firebase.data is List, isTrue); | |
38 expect(firebase.data.length, numberOfItems); | |
39 }); | |
40 | |
41 test('receives data from Firebase location', () { | |
42 expect(firebase.data[0]['value'] is num, isTrue); | |
43 }); | |
44 }); | |
45 | |
46 group('ordered primitives', () { | |
47 var numberOfItems; | |
48 | |
49 setUp(() { | |
50 numberOfItems = 5; | |
51 firebase = fixtureFirebase( | |
52 'TrivialCollection', arrayOfPrimitives(numberOfItems)); | |
53 firebase.orderByValue = true; | |
54 }); | |
55 | |
56 test('converts primitives into objects with a value key', () { | |
57 expect(firebase.data[0] is JsObject, isTrue); | |
58 }); | |
59 | |
60 test('orders primitives by value', () { | |
61 var lastValue = -1; | |
62 | |
63 expect(firebase.data.length, numberOfItems); | |
64 | |
65 firebase.data.forEach((datum) { | |
66 expect(datum['value'], isNot(lessThan(lastValue))); | |
67 lastValue = datum['value']; | |
68 }); | |
69 }); | |
70 }); | |
71 | |
72 group('removing a value locally', () { | |
73 var numberOfItems; | |
74 setUp(() { | |
75 numberOfItems = 3; | |
76 firebase = | |
77 fixtureFirebase('TrivialCollection', arrayOfObjects(numberOfItems)); | |
78 }); | |
79 | |
80 test('works for data-bound changes', () { | |
81 firebase.removeAt('data', 0); | |
82 expect(firebase.data.length, numberOfItems - 1); | |
83 }); | |
84 | |
85 test('can be done with `remove`', () { | |
86 var objectToBeRemoved = firebase.data[0]; | |
87 firebase.removeItem(objectToBeRemoved); | |
88 | |
89 expect(firebase.data.length, numberOfItems - 1); | |
90 expect(firebase.data.indexOf(objectToBeRemoved), -1); | |
91 }); | |
92 }); | |
93 | |
94 group('adding a value locally', () { | |
95 setUp(() { | |
96 firebase = fixtureFirebase('TrivialCollection'); | |
97 }); | |
98 | |
99 test('works for data-bound changes', () { | |
100 var done = new Completer(); | |
101 var intendedValue = randomInt(); | |
102 // Can't call `add` since it is overridden | |
103 var index = | |
104 firebase.jsElement.callMethod('push', ['data', intendedValue]) - 1; | |
Siggi Cherem (dart-lang)
2015/10/28 22:35:16
should `push` be exposed in the Dart API? Is it pa
jakemac
2015/10/29 16:07:29
I guess what should really happen here is changing
| |
105 | |
106 // NOTE(cdata): See polymer/polymer#2491. | |
107 firebase.async(() { | |
108 expect(firebase.data[index]['value'], isNotNull); | |
109 expect(firebase.data[index]['value'], intendedValue); | |
110 done.complete(); | |
111 }, waitTime: 1); | |
112 | |
113 return done.future; | |
114 }); | |
115 | |
116 test('can be done with `add`', () { | |
117 var done = new Completer(); | |
118 var object = randomObject(); | |
119 var length = firebase.data.length; | |
120 var foundObject; | |
121 | |
122 firebase.add(new JsObject.jsify(object)); | |
123 | |
124 // NOTE(cdata): See polymer/polymer#2491. | |
125 firebase.async(() { | |
126 expect(firebase.data.length, length + 1); | |
127 | |
128 firebase.data.forEach((datum) { | |
129 if (datum['value'] == object['value']) { | |
130 foundObject = datum; | |
131 } | |
132 }); | |
133 | |
134 expect(foundObject, isNotNull); | |
135 expect(foundObject['value'], object['value']); | |
136 done.complete(); | |
137 }, waitTime: 1); | |
138 | |
139 return done.future; | |
140 }); | |
141 }); | |
142 | |
143 group('a changing child', () { | |
144 var numberOfItems; | |
145 var remoteFirebase; | |
146 | |
147 setUp(() { | |
148 numberOfItems = 3; | |
149 firebase = | |
150 fixtureFirebase('TrivialCollection', arrayOfObjects(numberOfItems)); | |
151 remoteFirebase = new JsObject(context['Firebase'], [firebase.location]); | |
152 }); | |
153 | |
154 test('updates the child key in place with the new value', () { | |
155 var datum = firebase.data[0]; | |
156 var newValue = 99999; | |
157 var key = context['Polymer']['Collection'] | |
158 .callMethod('get', [firebase.data]).callMethod('getKey', [datum]); | |
159 | |
160 firebase.set('data.$key.value', newValue); | |
161 | |
162 expect(firebase.data[0]['value'], newValue); | |
163 }); | |
164 }); | |
165 | |
166 group('syncing collections', () { | |
167 var numberOfItems; | |
168 var remoteFirebase; | |
169 | |
170 setUp(() { | |
171 numberOfItems = 3; | |
172 | |
173 firebase = fixtureFirebase('TrivialCollection', arrayOfObjects(3)); | |
174 firebase.orderValueType = 'number'; | |
175 firebase.orderByValue = true; | |
176 | |
177 remoteFirebase = new JsObject(context['Firebase'], [firebase.location]); | |
178 }); | |
179 | |
180 test('sync a new item at the correct index', () { | |
181 var firstValue = firebase.data[0]; | |
182 var secondValue = firebase.data[1]; | |
183 var datum = firebase.data[0]; | |
184 var key = context['Polymer']['Collection'] | |
Siggi Cherem (dart-lang)
2015/10/28 22:35:16
do we want to eventually wrap these static APIs as
jakemac
2015/10/29 16:07:29
These collection apis are not really useful in gen
| |
185 .callMethod('get', [firebase.data]).callMethod('getKey', [datum]); | |
186 var remoteValue; | |
187 | |
188 remoteFirebase.callMethod('on', [ | |
189 'value', | |
190 (snapshot) { | |
191 remoteValue = snapshot.callMethod('val'); | |
192 } | |
193 ]); | |
194 | |
195 expect(remoteValue[0]['value'], firebase.data[0]['value']); | |
196 }); | |
197 }); | |
198 | |
199 group('data-bound collection manipulation', () { | |
200 var numberOfItems; | |
201 var elements; | |
22 DomBind domBind; | 202 DomBind domBind; |
23 var dom; | 203 |
24 | 204 setUp(() { |
25 setUp(() { | 205 elements = fixture('BoundCollection'); |
26 dom = fixture('BoundCollection'); | 206 domBind = elements.querySelector('[is=dom-bind]'); |
27 domBind = dom.querySelector('[is=dom-bind]'); | 207 firebase = elements.querySelector('firebase-collection'); |
28 firebase = dom.querySelector('firebase-collection'); | 208 firebase.location = fixtureLocation(arrayOfObjects(3)); |
29 }); | 209 numberOfItems = 3; |
30 | 210 }); |
31 test('added values reflect 1-to-1 in the DOM', () { | 211 |
32 return firebase.on['firebase-value'].first.then((_) { | 212 test('splices reflect in Firebase data', () { |
33 var done = firebase.on['firebase-child-added'].first.then((_) { | 213 var done = new Completer(); |
34 expect(dom.querySelectorAll('div').length, firebase.data.length); | 214 domBind.removeAt('data', 0); |
35 }); | 215 domBind.add('data', randomObject()); |
36 domBind.insert('data', 0, {'value': 'blah'}); | 216 domBind.removeAt('data', 0); |
37 domBind.render(); | 217 domBind.addAll('data', arrayOfObjects(2)); |
38 return done; | 218 |
39 }); | 219 // NOTE(cdata): See polymer/polymer#2491. |
40 }); | 220 firebase.async(() { |
41 }, skip: 'https://github.com/dart-lang/polymer_elements/issues/62'); | 221 expect(firebase.data.length, domBind['data'].length); |
42 | 222 |
43 group('basic usage', () { | 223 for (int i = 0; i < firebase.data.length; i++) { |
44 setUp(() { | 224 var datum = firebase.data[i]; |
45 firebase = fixture('TrivialCollection'); | 225 expect(domBind['data'][i]['value'], datum['value']); |
46 }); | 226 } |
47 | 227 |
48 tearDown(() { | 228 done.complete(); |
49 firebase.disconnect(); | 229 }, waitTime: 1); |
50 }); | 230 |
51 | 231 done.future; |
52 test('exposes data as an array', () { | 232 }); |
53 return firebase.on['firebase-child-added'].first.then((_) { | 233 |
54 expect(firebase.data is List, isTrue); | 234 test('splices reflect in the DOM', () { |
55 }); | 235 var divs; |
56 }); | 236 var done = new Completer(); |
57 | 237 |
58 test('receives data from Firebase location', () { | 238 firebase.jsElement.callMethod('push', |
59 return firebase.on['data-changed'].first.then((_) { | 239 ['data']..addAll(new JsObject.jsify(arrayOfObjects(3)) as JsArray)); |
60 expect(firebase.data[0]['value'], true); | 240 |
61 }); | 241 firebase.async(() { |
62 }); | 242 divs = elements.querySelectorAll('div'); |
63 }); | 243 expect(divs.length, firebase.data.length); |
64 | 244 |
65 group('ordered primitives', () { | 245 domBind.removeAt('data', 2); |
66 setUp(() { | 246 domBind.add('data', randomObject()); |
67 firebase = fixture('PrimitiveCollection'); | 247 |
68 }); | 248 firebase.async(() { |
69 | 249 divs = elements.querySelectorAll('div'); |
70 tearDown(() { | 250 expect(divs.length, firebase.data.length); |
71 firebase.disconnect(); | 251 |
72 }); | 252 for (int i = 0; i < firebase.data.length; i++) { |
73 | 253 var datum = firebase.data[i]; |
74 test('converts primitives into objects with a value key', () { | 254 var divValue = int.parse(divs[i].text); |
75 return firebase.on['firebase-child-added'].first.then((_) { | 255 expect(datum.value, divValue); |
76 expect(firebase.data[0], isNotNull); | 256 } |
77 }); | 257 |
78 }); | 258 done.complete(); |
79 | 259 }, waitTime: 1); |
80 test('orders primitives by value', () { | 260 }, waitTime: 1); |
81 return firebase.on['firebase-value'].first.then((_) { | 261 |
82 var lastValue = -1.0 / 0; | 262 return done.future; |
83 expect(firebase.data.length, greaterThan(0)); | 263 }, skip: 'https://github.com/dart-lang/polymer_elements/issues/62'); |
84 firebase.data.forEach((item) { | |
85 expect(item['value'], greaterThanOrEqualTo(lastValue)); | |
86 lastValue = item['value']; | |
87 }); | |
88 }); | |
89 }); | |
90 | |
91 group('adding a value locally', () { | |
92 setUp(() { | |
93 return firebase.on['firebase-value'].first; | |
94 }); | |
95 | |
96 test('can be done with `add`', () { | |
97 var length = firebase.data.length; | |
98 var newValue = firebase.data[firebase.data.length - 1]['value'] + 1; | |
99 var key; | |
100 | |
101 var done = firebase.on['firebase-child-added'].first.then((_) { | |
102 expect(firebase.data.length, length + 1); | |
103 expect(firebase.data[firebase.data.length - 1]['value'], newValue); | |
104 }).then((_) async { | |
105 await wait(1); | |
106 firebase.removeByKey(key); | |
107 }); | |
108 | |
109 key = firebase.add(newValue).callMethod('key'); | |
110 return done; | |
111 }); | |
112 }); | |
113 }); | |
114 | |
115 group('a child changes', () { | |
116 setUp(() { | |
117 firebase = fixture('ChangingChildren'); | |
118 return firebase.on['firebase-value'].first; | |
119 }); | |
120 | |
121 test('updates the child key in place with the new value', () { | |
122 var childrenKeys = []; | |
123 | |
124 var done = firebase.on['firebase-value'].first.then((_) async { | |
125 // Wait for childrenKeys to be populated | |
126 await new Future(() {}); | |
127 var middleValue = firebase.getByKey(childrenKeys[1]); | |
128 var changes; | |
129 | |
130 expect(middleValue['foo'], 1); | |
131 expect(middleValue['bar'], 1); | |
132 | |
133 changes = firebase.on['firebase-child-changed'].first; | |
134 | |
135 firebase.set('data.${firebase.data.indexOf(middleValue)}.bar', 2); | |
136 | |
137 return changes; | |
138 }).then((_) { | |
139 var middleValue = firebase.getByKey(childrenKeys[1]); | |
140 | |
141 expect(middleValue['foo'], 1); | |
142 expect(middleValue['bar'], 2); | |
143 }).then((_) { | |
144 childrenKeys.forEach((key) { | |
145 firebase.removeByKey(key); | |
146 }); | |
147 }); | |
148 | |
149 var index = -1; | |
150 childrenKeys = [0, 1, 2].map((value) { | |
151 index++; | |
152 return firebase | |
153 .add(new JsObject.jsify({'foo': value, 'bar': index})) | |
154 .callMethod('key'); | |
155 }).toList(); | |
156 | |
157 return done; | |
158 }); | |
159 }); | |
160 | |
161 group('syncing collections', () { | |
162 FirebaseCollection localFirebase; | |
163 FirebaseCollection remoteFirebase; | |
164 | |
165 setUp(() { | |
166 var children = fixture('SyncingCollections'); | |
167 localFirebase = children[0]; | |
168 remoteFirebase = children[1]; | |
169 return Future.wait([ | |
170 localFirebase.on['firebase-value'].first, | |
171 remoteFirebase.on['firebase-value'].first | |
172 ]); | |
173 }); | |
174 | |
175 test('syncs a new item at the correct index', () { | |
176 var data = {'foo': 100}; | |
177 var key; | |
178 | |
179 var done = remoteFirebase.on['firebase-value'].first.then((_) async { | |
180 await wait(1); | |
181 var value = remoteFirebase.getByKey(key); | |
182 var lowValue = remoteFirebase.getByKey('lowValue'); | |
183 var highValue = remoteFirebase.getByKey('highValue'); | |
184 | |
185 var index = remoteFirebase.data.indexOf(value); | |
186 var lowIndex = remoteFirebase.data.indexOf(lowValue); | |
187 var highIndex = remoteFirebase.data.indexOf(highValue); | |
188 | |
189 expect(value, isNotNull); | |
190 expect(index, lessThan(highIndex)); | |
191 expect(index, greaterThan(lowIndex)); | |
192 }).then((_) { | |
193 localFirebase.removeByKey(key); | |
194 }); | |
195 | |
196 key = localFirebase.add(new JsObject.jsify(data)).callMethod('key'); | |
197 | |
198 return done; | |
199 }); | |
200 }); | 264 }); |
201 }); | 265 }); |
202 } | 266 } |
OLD | NEW |