1
+ import { FirebaseApp , FirebaseAppConfig , AngularFireModule } from 'angularfire2' ;
2
+ import { AngularFirestore } from '../firestore' ;
3
+ import { AngularFirestoreModule } from '../firestore.module' ;
4
+ import { AngularFirestoreDocument } from '../document/document' ;
5
+ import { AngularFirestoreCollection } from './collection' ;
6
+
7
+ import * as firebase from 'firebase/app' ;
8
+ import * as firestore from 'firestore' ;
9
+ import { Observable } from 'rxjs/Observable' ;
10
+ import { of } from 'rxjs/observable/of' ;
11
+ import { Subscription } from 'rxjs/Subscription' ;
12
+ import 'rxjs/add/operator/skip' ;
13
+
14
+ import { TestBed , inject } from '@angular/core/testing' ;
15
+ import { COMMON_CONFIG } from '../test-config' ;
16
+
17
+ interface Stock {
18
+ name : string ;
19
+ price : number ;
20
+ }
21
+
22
+ const FAKE_STOCK_DATA = { name : 'FAKE' , price : 1 } ;
23
+
24
+ const randomName = ( firestore ) : string => firestore . collection ( 'a' ) . doc ( ) . id ;
25
+
26
+ const createRandomStocks = async ( firestore : firestore . Firestore , collectionRef : firestore . CollectionReference , numberOfItems ) => {
27
+ // Create a batch to update everything at once
28
+ const batch = firestore . batch ( ) ;
29
+ // Store the random names to delete them later
30
+ let count = 0 ;
31
+ let names : string [ ] = [ ] ;
32
+ Array . from ( Array ( numberOfItems ) ) . forEach ( ( a , i ) => {
33
+ const name = randomName ( firestore ) ;
34
+ batch . set ( collectionRef . doc ( name ) , FAKE_STOCK_DATA ) ;
35
+ names = [ ...names , name ] ;
36
+ } ) ;
37
+ // Create the batch entries
38
+ // Commit!
39
+ await batch . commit ( ) ;
40
+ return names ;
41
+ }
42
+
43
+ describe ( 'AngularFirestoreCollection' , ( ) => {
44
+ let app : firebase . app . App ;
45
+ let afs : AngularFirestore ;
46
+ let sub : Subscription ;
47
+
48
+ beforeEach ( ( ) => {
49
+ TestBed . configureTestingModule ( {
50
+ imports : [
51
+ AngularFireModule . initializeApp ( COMMON_CONFIG ) ,
52
+ AngularFirestoreModule
53
+ ]
54
+ } ) ;
55
+ inject ( [ FirebaseApp , AngularFirestore ] , ( _app : firebase . app . App , _afs : AngularFirestore ) => {
56
+ app = _app ;
57
+ afs = _afs ;
58
+ } ) ( ) ;
59
+ } ) ;
60
+
61
+ afterEach ( async ( done ) => {
62
+ await app . delete ( ) ;
63
+ done ( ) ;
64
+ } ) ;
65
+
66
+ function deleteThemAll ( names , ref ) {
67
+ const promises = names . map ( name => ref . doc ( name ) . delete ( ) ) ;
68
+ return Promise . all ( promises ) ;
69
+ }
70
+
71
+ function delayUpdate < T > ( collection : AngularFirestoreCollection < T > , path , data , delay = 250 ) {
72
+ setTimeout ( ( ) => {
73
+ collection . doc ( path ) . update ( data ) ;
74
+ } , delay ) ;
75
+ }
76
+
77
+ function delayAdd < T > ( collection : AngularFirestoreCollection < T > , path , data , delay = 250 ) {
78
+ setTimeout ( ( ) => {
79
+ collection . doc ( path ) . set ( data ) ;
80
+ } , delay ) ;
81
+ }
82
+
83
+ function delayDelete < T > ( collection : AngularFirestoreCollection < T > , path , delay = 250 ) {
84
+ setTimeout ( ( ) => {
85
+ collection . doc ( path ) . delete ( ) ;
86
+ } , delay ) ;
87
+ }
88
+
89
+ it ( 'should get unwrapped snapshot' , async ( done : any ) => {
90
+ const randomCollectionName = randomName ( afs . firestore ) ;
91
+ const ref = afs . firestore . collection ( `${ randomCollectionName } ` ) ;
92
+ const stocks = new AngularFirestoreCollection < Stock > ( ref , ref ) ;
93
+ const ITEMS = 4 ;
94
+
95
+ const names = await createRandomStocks ( afs . firestore , ref , ITEMS )
96
+
97
+ const sub = stocks . valueChanges ( ) . subscribe ( data => {
98
+ // unsub immediately as we will be deleting data at the bottom
99
+ // and that will trigger another subscribe callback and fail
100
+ // the test
101
+ sub . unsubscribe ( ) ;
102
+ // We added four things. This should be four.
103
+ // This could not be four if the batch failed or
104
+ // if the collection state is altered during a test run
105
+ expect ( data . length ) . toEqual ( ITEMS ) ;
106
+ data . forEach ( stock => {
107
+ // We used the same piece of data so they should all equal
108
+ expect ( stock ) . toEqual ( FAKE_STOCK_DATA ) ;
109
+ } ) ;
110
+ // Delete them all
111
+ const promises = names . map ( name => ref . doc ( name ) . delete ( ) ) ;
112
+ Promise . all ( promises ) . then ( done ) . catch ( fail ) ;
113
+ } ) ;
114
+
115
+ } ) ;
116
+
117
+ it ( 'should get snapshot updates' , async ( done : any ) => {
118
+ const randomCollectionName = randomName ( afs . firestore ) ;
119
+ const ref = afs . firestore . collection ( `${ randomCollectionName } ` ) ;
120
+ const stocks = new AngularFirestoreCollection < Stock > ( ref , ref ) ;
121
+ const ITEMS = 10 ;
122
+
123
+ const names = await createRandomStocks ( afs . firestore , ref , ITEMS ) ;
124
+
125
+ const sub = stocks . snapshotChanges ( ) . subscribe ( data => {
126
+ // unsub immediately as we will be deleting data at the bottom
127
+ // and that will trigger another subscribe callback and fail
128
+ // the test
129
+ sub . unsubscribe ( ) ;
130
+ // We added ten things. This should be ten.
131
+ // This could not be ten if the batch failed or
132
+ // if the collection state is altered during a test run
133
+ expect ( data . length ) . toEqual ( ITEMS ) ;
134
+ data . forEach ( action => {
135
+ // We used the same piece of data so they should all equal
136
+ expect ( action . payload . doc . data ( ) ) . toEqual ( FAKE_STOCK_DATA ) ;
137
+ } ) ;
138
+ deleteThemAll ( names , ref ) . then ( done ) . catch ( done . fail ) ;
139
+ } ) ;
140
+
141
+ } ) ;
142
+
143
+ it ( 'should listen to all changes by default' , async ( done ) => {
144
+ const randomCollectionName = randomName ( afs . firestore ) ;
145
+ const ref = afs . firestore . collection ( `${ randomCollectionName } ` ) ;
146
+ const stocks = new AngularFirestoreCollection < Stock > ( ref , ref ) ;
147
+ const ITEMS = 10 ;
148
+ let count = 0 ;
149
+ const names = await createRandomStocks ( afs . firestore , ref , ITEMS ) ;
150
+ const sub = stocks . snapshotChanges ( ) . subscribe ( data => {
151
+ count = count + 1 ;
152
+ if ( count === 1 ) {
153
+ stocks . doc ( names [ 0 ] ) . update ( { price : 2 } ) ;
154
+ }
155
+ if ( count === 2 ) {
156
+ expect ( data . length ) . toEqual ( 1 ) ;
157
+ expect ( data [ 0 ] . type ) . toEqual ( 'modified' ) ;
158
+ deleteThemAll ( names , ref ) . then ( done ) . catch ( done . fail ) ;
159
+ }
160
+ } ) ;
161
+ } ) ;
162
+
163
+ it ( 'should be able to filter change types - modified' , async ( done ) => {
164
+ const randomCollectionName = randomName ( afs . firestore ) ;
165
+ const ref = afs . firestore . collection ( `${ randomCollectionName } ` ) ;
166
+ const stocks = new AngularFirestoreCollection < Stock > ( ref , ref ) ;
167
+ const ITEMS = 10 ;
168
+ let count = 0 ;
169
+ const names = await createRandomStocks ( afs . firestore , ref , ITEMS ) ;
170
+
171
+ const sub = stocks . snapshotChanges ( [ 'modified' ] ) . subscribe ( data => {
172
+ expect ( data . length ) . toEqual ( 1 ) ;
173
+ expect ( data [ 0 ] . payload . doc . data ( ) . price ) . toEqual ( 2 ) ;
174
+ expect ( data [ 0 ] . type ) . toEqual ( 'modified' ) ;
175
+ deleteThemAll ( names , ref ) . then ( done ) . catch ( done . fail ) ;
176
+ done ( ) ;
177
+ } ) ;
178
+
179
+ delayUpdate ( stocks , names [ 0 ] , { price : 2 } ) ;
180
+ } ) ;
181
+
182
+ it ( 'should be able to filter change types - added' , async ( done ) => {
183
+ const randomCollectionName = randomName ( afs . firestore ) ;
184
+ const ref = afs . firestore . collection ( `${ randomCollectionName } ` ) ;
185
+ const stocks = new AngularFirestoreCollection < Stock > ( ref , ref ) ;
186
+ const ITEMS = 10 ;
187
+ let count = 0 ;
188
+ let names = await createRandomStocks ( afs . firestore , ref , ITEMS ) ;
189
+
190
+ const sub = stocks . snapshotChanges ( [ 'added' ] ) . skip ( 1 ) . subscribe ( data => {
191
+ expect ( data . length ) . toEqual ( 1 ) ;
192
+ expect ( data [ 0 ] . payload . doc . data ( ) . price ) . toEqual ( 2 ) ;
193
+ expect ( data [ 0 ] . type ) . toEqual ( 'added' ) ;
194
+ deleteThemAll ( names , ref ) . then ( done ) . catch ( done . fail ) ;
195
+ done ( ) ;
196
+ } ) ;
197
+
198
+ const nextId = ref . doc ( 'a' ) . id ;
199
+ names = names . concat ( [ nextId ] ) ;
200
+ delayAdd ( stocks , nextId , { price : 2 } ) ;
201
+ } ) ;
202
+
203
+ fit ( 'should be able to filter change types - removed' , async ( done ) => {
204
+ const randomCollectionName = randomName ( afs . firestore ) ;
205
+ const ref = afs . firestore . collection ( `${ randomCollectionName } ` ) ;
206
+ const stocks = new AngularFirestoreCollection < Stock > ( ref , ref ) ;
207
+ const ITEMS = 10 ;
208
+ let count = 0 ;
209
+ let names = await createRandomStocks ( afs . firestore , ref , ITEMS ) ;
210
+
211
+ const sub = stocks . snapshotChanges ( [ 'removed' ] ) . subscribe ( data => {
212
+ debugger ;
213
+ expect ( data . length ) . toEqual ( 1 ) ;
214
+ expect ( data [ 0 ] . type ) . toEqual ( 'removed' ) ;
215
+ deleteThemAll ( names , ref ) . then ( done ) . catch ( done . fail ) ;
216
+ done ( ) ;
217
+ } ) ;
218
+
219
+ debugger ;
220
+ delayDelete ( stocks , names [ 0 ] , 400 ) ;
221
+ } ) ;
222
+
223
+ } ) ;
0 commit comments