@@ -3,6 +3,7 @@ import { AngularFirestore } from '../firestore';
3
3
import { AngularFirestoreModule } from '../firestore.module' ;
4
4
import { AngularFirestoreDocument } from '../document/document' ;
5
5
import { AngularFirestoreCollection } from './collection' ;
6
+ import { QueryFn } from '../interfaces' ;
6
7
7
8
import * as firebase from 'firebase/app' ;
8
9
import * as firestore from 'firestore' ;
@@ -16,6 +17,15 @@ import { COMMON_CONFIG } from '../test-config';
16
17
17
18
import { Stock , randomName , FAKE_STOCK_DATA , createRandomStocks , delayAdd , delayDelete , delayUpdate , deleteThemAll } from '../utils.spec' ;
18
19
20
+ async function collectionHarness ( afs : AngularFirestore , items : number , queryFn ?: QueryFn ) {
21
+ const randomCollectionName = randomName ( afs . firestore ) ;
22
+ const ref = afs . firestore . collection ( `${ randomCollectionName } ` ) ;
23
+ if ( ! queryFn ) { queryFn = ( ref ) => ref ; }
24
+ const stocks = new AngularFirestoreCollection < Stock > ( ref , queryFn ( ref ) ) ;
25
+ let names = await createRandomStocks ( afs . firestore , ref , items ) ;
26
+ return { randomCollectionName, ref, stocks, names } ;
27
+ }
28
+
19
29
describe ( 'AngularFirestoreCollection' , ( ) => {
20
30
let app : firebase . app . App ;
21
31
let afs : AngularFirestore ;
@@ -39,76 +49,168 @@ describe('AngularFirestoreCollection', () => {
39
49
done ( ) ;
40
50
} ) ;
41
51
42
- it ( 'should get unwrapped snapshot' , async ( done : any ) => {
43
- const randomCollectionName = randomName ( afs . firestore ) ;
44
- const ref = afs . firestore . collection ( `${ randomCollectionName } ` ) ;
45
- const stocks = new AngularFirestoreCollection < Stock > ( ref , ref ) ;
46
- const ITEMS = 4 ;
47
-
48
- const names = await createRandomStocks ( afs . firestore , ref , ITEMS )
49
-
50
- const sub = stocks . valueChanges ( ) . subscribe ( data => {
51
- // unsub immediately as we will be deleting data at the bottom
52
- // and that will trigger another subscribe callback and fail
53
- // the test
54
- sub . unsubscribe ( ) ;
55
- // We added four things. This should be four.
56
- // This could not be four if the batch failed or
57
- // if the collection state is altered during a test run
58
- expect ( data . length ) . toEqual ( ITEMS ) ;
59
- data . forEach ( stock => {
60
- // We used the same piece of data so they should all equal
61
- expect ( stock ) . toEqual ( FAKE_STOCK_DATA ) ;
52
+ describe ( 'valueChanges()' , ( ) => {
53
+
54
+ it ( 'should get unwrapped snapshot' , async ( done : any ) => {
55
+ const ITEMS = 4 ;
56
+ const { randomCollectionName, ref, stocks, names } = await collectionHarness ( afs , ITEMS ) ;
57
+
58
+ const sub = stocks . valueChanges ( ) . subscribe ( data => {
59
+ // unsub immediately as we will be deleting data at the bottom
60
+ // and that will trigger another subscribe callback and fail
61
+ // the test
62
+ sub . unsubscribe ( ) ;
63
+ // We added four things. This should be four.
64
+ // This could not be four if the batch failed or
65
+ // if the collection state is altered during a test run
66
+ expect ( data . length ) . toEqual ( ITEMS ) ;
67
+ data . forEach ( stock => {
68
+ // We used the same piece of data so they should all equal
69
+ expect ( stock ) . toEqual ( FAKE_STOCK_DATA ) ;
70
+ } ) ;
71
+ // Delete them all
72
+ const promises = names . map ( name => ref . doc ( name ) . delete ( ) ) ;
73
+ Promise . all ( promises ) . then ( done ) . catch ( fail ) ;
62
74
} ) ;
63
- // Delete them all
64
- const promises = names . map ( name => ref . doc ( name ) . delete ( ) ) ;
65
- Promise . all ( promises ) . then ( done ) . catch ( fail ) ;
75
+
66
76
} ) ;
67
-
68
77
} ) ;
69
78
70
- it ( 'should get stateChanges() updates' , async ( done : any ) => {
71
- const randomCollectionName = randomName ( afs . firestore ) ;
72
- const ref = afs . firestore . collection ( `${ randomCollectionName } ` ) ;
73
- const stocks = new AngularFirestoreCollection < Stock > ( ref , ref ) ;
74
- const ITEMS = 10 ;
75
-
76
- const names = await createRandomStocks ( afs . firestore , ref , ITEMS ) ;
77
-
78
- const sub = stocks . stateChanges ( ) . subscribe ( data => {
79
- // unsub immediately as we will be deleting data at the bottom
80
- // and that will trigger another subscribe callback and fail
81
- // the test
82
- sub . unsubscribe ( ) ;
83
- // We added ten things. This should be ten.
84
- // This could not be ten if the batch failed or
85
- // if the collection state is altered during a test run
86
- expect ( data . length ) . toEqual ( ITEMS ) ;
87
- data . forEach ( action => {
88
- // We used the same piece of data so they should all equal
89
- expect ( action . payload . doc . data ( ) ) . toEqual ( FAKE_STOCK_DATA ) ;
79
+ describe ( 'snapshotChanges()' , ( ) => {
80
+
81
+ it ( 'should listen to all snapshotChanges() by default' , async ( done ) => {
82
+ const ITEMS = 10 ;
83
+ let count = 0 ;
84
+ const { randomCollectionName, ref, stocks, names } = await collectionHarness ( afs , ITEMS ) ;
85
+ const sub = stocks . snapshotChanges ( ) . subscribe ( data => {
86
+ count = count + 1 ;
87
+ // the first time should all be 'added'
88
+ if ( count === 1 ) {
89
+ // make an update
90
+ stocks . doc ( names [ 0 ] ) . update ( { price : 2 } ) ;
91
+ }
92
+ // on the second round, make sure the array is still the same
93
+ // length but the updated item is now modified
94
+ if ( count === 2 ) {
95
+ expect ( data . length ) . toEqual ( ITEMS ) ;
96
+ const change = data . filter ( x => x . payload . doc . id === names [ 0 ] ) [ 0 ] ;
97
+ expect ( change . type ) . toEqual ( 'modified' ) ;
98
+ sub . unsubscribe ( ) ;
99
+ deleteThemAll ( names , ref ) . then ( done ) . catch ( done . fail ) ;
100
+ }
90
101
} ) ;
91
- deleteThemAll ( names , ref ) . then ( done ) . catch ( done . fail ) ;
92
102
} ) ;
93
-
94
- } ) ;
95
103
96
- fdescribe ( 'snapshotChanges()' , ( ) => {
104
+ it ( 'should update order on queries' , async ( done ) => {
105
+ const ITEMS = 10 ;
106
+ let count = 0 ;
107
+ let firstIndex = 0 ;
108
+ const { randomCollectionName, ref, stocks, names } =
109
+ await collectionHarness ( afs , ITEMS , ref => ref . orderBy ( 'price' , 'desc' ) ) ;
110
+ const sub = stocks . snapshotChanges ( ) . subscribe ( data => {
111
+ debugger ;
112
+ count = count + 1 ;
113
+ // the first time should all be 'added'
114
+ if ( count === 1 ) {
115
+ // make an update
116
+ firstIndex = data . filter ( d => d . payload . doc . id === names [ 0 ] ) [ 0 ] . payload . newIndex ;
117
+ stocks . doc ( names [ 0 ] ) . update ( { price : 2 } ) ;
118
+ }
119
+ // on the second round, make sure the array is still the same
120
+ // length but the updated item is now modified
121
+ if ( count === 2 ) {
122
+ expect ( data . length ) . toEqual ( ITEMS ) ;
123
+ const change = data . filter ( x => x . payload . doc . id === names [ 0 ] ) [ 0 ] ;
124
+ expect ( change . type ) . toEqual ( 'modified' ) ;
125
+ expect ( change . payload . oldIndex ) . toEqual ( firstIndex ) ;
126
+ sub . unsubscribe ( ) ;
127
+ deleteThemAll ( names , ref ) . then ( done ) . catch ( done . fail ) ;
128
+ }
129
+ } ) ;
130
+ } ) ;
131
+
132
+ it ( 'should be able to filter snapshotChanges() types - modified' , async ( done ) => {
133
+ const ITEMS = 10 ;
134
+ const { randomCollectionName, ref, stocks, names } = await collectionHarness ( afs , ITEMS ) ;
135
+
136
+ const sub = stocks . snapshotChanges ( [ 'modified' ] ) . subscribe ( data => {
137
+ sub . unsubscribe ( ) ;
138
+ const change = data . filter ( x => x . payload . doc . id === names [ 0 ] ) [ 0 ] ;
139
+ expect ( data . length ) . toEqual ( 1 ) ;
140
+ expect ( change . payload . doc . data ( ) . price ) . toEqual ( 2 ) ;
141
+ expect ( change . type ) . toEqual ( 'modified' ) ;
142
+ deleteThemAll ( names , ref ) . then ( done ) . catch ( done . fail ) ;
143
+ } ) ;
144
+
145
+ delayUpdate ( stocks , names [ 0 ] , { price : 2 } ) ;
146
+ } ) ;
97
147
98
- it ( 'should listen to all snapshotChanges() by default' , async ( done ) => {
148
+ it ( 'should be able to filter snapshotChanges() types - added' , async ( done ) => {
149
+ const ITEMS = 10 ;
150
+ let { randomCollectionName, ref, stocks, names } = await collectionHarness ( afs , ITEMS ) ;
151
+ const nextId = ref . doc ( 'a' ) . id ;
99
152
153
+ const sub = stocks . snapshotChanges ( [ 'added' ] ) . skip ( 1 ) . subscribe ( data => {
154
+ sub . unsubscribe ( ) ;
155
+ const change = data . filter ( x => x . payload . doc . id === nextId ) [ 0 ] ;
156
+ expect ( data . length ) . toEqual ( ITEMS + 1 ) ;
157
+ expect ( change . payload . doc . data ( ) . price ) . toEqual ( 2 ) ;
158
+ expect ( change . type ) . toEqual ( 'added' ) ;
159
+ deleteThemAll ( names , ref ) . then ( done ) . catch ( done . fail ) ;
160
+ done ( ) ;
161
+ } ) ;
162
+
163
+
164
+ names = names . concat ( [ nextId ] ) ;
165
+ delayAdd ( stocks , nextId , { price : 2 } ) ;
100
166
} ) ;
101
167
168
+ it ( 'should be able to filter snapshotChanges() types - removed' , async ( done ) => {
169
+ const ITEMS = 10 ;
170
+ const { randomCollectionName, ref, stocks, names } = await collectionHarness ( afs , ITEMS ) ;
171
+
172
+ const sub = stocks . snapshotChanges ( [ 'added' , 'removed' ] ) . skip ( 1 ) . subscribe ( data => {
173
+ sub . unsubscribe ( ) ;
174
+ const change = data . filter ( x => x . payload . doc . id === names [ 0 ] ) ;
175
+ expect ( data . length ) . toEqual ( ITEMS - 1 ) ;
176
+ expect ( change . length ) . toEqual ( 0 ) ;
177
+ deleteThemAll ( names , ref ) . then ( done ) . catch ( done . fail ) ;
178
+ done ( ) ;
179
+ } ) ;
180
+
181
+ delayDelete ( stocks , names [ 0 ] , 400 ) ;
182
+ } ) ;
183
+
102
184
} ) ;
103
185
104
186
describe ( 'stateChanges()' , ( ) => {
187
+
188
+ it ( 'should get stateChanges() updates' , async ( done : any ) => {
189
+ const ITEMS = 10 ;
190
+ const { randomCollectionName, ref, stocks, names } = await collectionHarness ( afs , ITEMS ) ;
191
+
192
+ const sub = stocks . stateChanges ( ) . subscribe ( data => {
193
+ // unsub immediately as we will be deleting data at the bottom
194
+ // and that will trigger another subscribe callback and fail
195
+ // the test
196
+ sub . unsubscribe ( ) ;
197
+ // We added ten things. This should be ten.
198
+ // This could not be ten if the batch failed or
199
+ // if the collection state is altered during a test run
200
+ expect ( data . length ) . toEqual ( ITEMS ) ;
201
+ data . forEach ( action => {
202
+ // We used the same piece of data so they should all equal
203
+ expect ( action . payload . doc . data ( ) ) . toEqual ( FAKE_STOCK_DATA ) ;
204
+ } ) ;
205
+ deleteThemAll ( names , ref ) . then ( done ) . catch ( done . fail ) ;
206
+ } ) ;
207
+
208
+ } ) ;
209
+
105
210
it ( 'should listen to all stateChanges() by default' , async ( done ) => {
106
- const randomCollectionName = randomName ( afs . firestore ) ;
107
- const ref = afs . firestore . collection ( `${ randomCollectionName } ` ) ;
108
- const stocks = new AngularFirestoreCollection < Stock > ( ref , ref ) ;
109
211
const ITEMS = 10 ;
110
212
let count = 0 ;
111
- const names = await createRandomStocks ( afs . firestore , ref , ITEMS ) ;
213
+ const { randomCollectionName , ref , stocks , names } = await collectionHarness ( afs , ITEMS ) ;
112
214
const sub = stocks . stateChanges ( ) . subscribe ( data => {
113
215
count = count + 1 ;
114
216
if ( count === 1 ) {
@@ -123,12 +225,9 @@ describe('AngularFirestoreCollection', () => {
123
225
} ) ;
124
226
125
227
it ( 'should be able to filter stateChanges() types - modified' , async ( done ) => {
126
- const randomCollectionName = randomName ( afs . firestore ) ;
127
- const ref = afs . firestore . collection ( `${ randomCollectionName } ` ) ;
128
- const stocks = new AngularFirestoreCollection < Stock > ( ref , ref ) ;
129
228
const ITEMS = 10 ;
130
229
let count = 0 ;
131
- const names = await createRandomStocks ( afs . firestore , ref , ITEMS ) ;
230
+ const { randomCollectionName , ref , stocks , names } = await collectionHarness ( afs , ITEMS ) ;
132
231
133
232
const sub = stocks . stateChanges ( [ 'modified' ] ) . subscribe ( data => {
134
233
sub . unsubscribe ( ) ;
@@ -143,12 +242,9 @@ describe('AngularFirestoreCollection', () => {
143
242
} ) ;
144
243
145
244
it ( 'should be able to filter stateChanges() types - added' , async ( done ) => {
146
- const randomCollectionName = randomName ( afs . firestore ) ;
147
- const ref = afs . firestore . collection ( `${ randomCollectionName } ` ) ;
148
- const stocks = new AngularFirestoreCollection < Stock > ( ref , ref ) ;
149
245
const ITEMS = 10 ;
150
246
let count = 0 ;
151
- let names = await createRandomStocks ( afs . firestore , ref , ITEMS ) ;
247
+ let { randomCollectionName , ref , stocks , names } = await collectionHarness ( afs , ITEMS ) ;
152
248
153
249
const sub = stocks . stateChanges ( [ 'added' ] ) . skip ( 1 ) . subscribe ( data => {
154
250
sub . unsubscribe ( ) ;
@@ -165,11 +261,8 @@ describe('AngularFirestoreCollection', () => {
165
261
} ) ;
166
262
167
263
it ( 'should be able to filter stateChanges() types - removed' , async ( done ) => {
168
- const randomCollectionName = randomName ( afs . firestore ) ;
169
- const ref = afs . firestore . collection ( `${ randomCollectionName } ` ) ;
170
- const stocks = new AngularFirestoreCollection < Stock > ( ref , ref ) ;
171
264
const ITEMS = 10 ;
172
- let names = await createRandomStocks ( afs . firestore , ref , ITEMS ) ;
265
+ const { randomCollectionName , ref , stocks , names } = await collectionHarness ( afs , ITEMS ) ;
173
266
174
267
const sub = stocks . stateChanges ( [ 'removed' ] ) . subscribe ( data => {
175
268
sub . unsubscribe ( ) ;
@@ -183,4 +276,39 @@ describe('AngularFirestoreCollection', () => {
183
276
} ) ;
184
277
} ) ;
185
278
279
+ describe ( 'auditTrail()' , ( ) => {
280
+ it ( 'should listen to all events for auditTrail() by default' , async ( done ) => {
281
+ const ITEMS = 10 ;
282
+ let count = 0 ;
283
+ const { randomCollectionName, ref, stocks, names } = await collectionHarness ( afs , ITEMS ) ;
284
+ const sub = stocks . auditTrail ( ) . subscribe ( data => {
285
+ count = count + 1 ;
286
+ if ( count === 1 ) {
287
+ stocks . doc ( names [ 0 ] ) . update ( { price : 2 } ) ;
288
+ }
289
+ if ( count === 2 ) {
290
+ sub . unsubscribe ( ) ;
291
+ expect ( data . length ) . toEqual ( ITEMS + 1 ) ;
292
+ expect ( data [ data . length - 1 ] . type ) . toEqual ( 'modified' ) ;
293
+ deleteThemAll ( names , ref ) . then ( done ) . catch ( done . fail ) ;
294
+ }
295
+ } ) ;
296
+ } ) ;
297
+
298
+ it ( 'should be able to filter auditTrail() types - removed' , async ( done ) => {
299
+ const ITEMS = 10 ;
300
+ const { randomCollectionName, ref, stocks, names } = await collectionHarness ( afs , ITEMS ) ;
301
+
302
+ const sub = stocks . auditTrail ( [ 'removed' ] ) . subscribe ( data => {
303
+ sub . unsubscribe ( ) ;
304
+ expect ( data . length ) . toEqual ( 1 ) ;
305
+ expect ( data [ 0 ] . type ) . toEqual ( 'removed' ) ;
306
+ deleteThemAll ( names , ref ) . then ( done ) . catch ( done . fail ) ;
307
+ done ( ) ;
308
+ } ) ;
309
+
310
+ delayDelete ( stocks , names [ 0 ] , 400 ) ;
311
+ } ) ;
312
+ } ) ;
313
+
186
314
} ) ;
0 commit comments