@@ -24,140 +24,192 @@ import { expect } from 'chai';
24
24
import * as functions from 'firebase-functions' ;
25
25
import { set } from 'lodash' ;
26
26
27
- import { mockConfig , makeChange , _makeResourceName , wrap } from '../src/main' ;
27
+ import {
28
+ mockConfig ,
29
+ makeChange ,
30
+ _makeResourceName ,
31
+ _extractParams ,
32
+ wrap ,
33
+ } from '../src/main' ;
34
+ import { features } from '../src/features' ;
35
+ import { FirebaseFunctionsTest } from '../src/lifecycle' ;
28
36
29
37
describe ( 'main' , ( ) => {
30
38
describe ( '#wrap' , ( ) => {
31
- describe ( 'background functions' , ( ) => {
32
- const constructBackgroundCF = ( eventType ?: string ) => {
33
- const cloudFunction = ( input ) => input ;
34
- set ( cloudFunction , 'run' , ( data , context ) => {
35
- return { data, context } ;
36
- } ) ;
37
- set ( cloudFunction , '__trigger' , {
38
- eventTrigger : {
39
- resource : 'ref/{wildcard}/nested/{anotherWildcard}' ,
40
- eventType : eventType || 'event' ,
41
- service : 'service' ,
42
- } ,
43
- } ) ;
44
- return cloudFunction as functions . CloudFunction < any > ;
45
- } ;
46
-
47
- it ( 'should invoke the function with the supplied data' , ( ) => {
48
- const wrapped = wrap ( constructBackgroundCF ( ) ) ;
49
- expect ( wrapped ( 'data' ) . data ) . to . equal ( 'data' ) ;
39
+ const constructCF = ( eventType ?: string ) => {
40
+ const cloudFunction = ( input ) => input ;
41
+ set ( cloudFunction , 'run' , ( data , context ) => {
42
+ return { data, context } ;
43
+ } ) ;
44
+ set ( cloudFunction , '__trigger' , {
45
+ eventTrigger : {
46
+ resource : 'ref/{wildcard}/nested/{anotherWildcard}' ,
47
+ eventType : eventType || 'event' ,
48
+ service : 'service' ,
49
+ } ,
50
50
} ) ;
51
+ return cloudFunction as functions . CloudFunction < any > ;
52
+ } ;
53
+
54
+ it ( 'should invoke the function with the supplied data' , ( ) => {
55
+ const wrapped = wrap ( constructCF ( ) ) ;
56
+ expect ( wrapped ( 'data' ) . data ) . to . equal ( 'data' ) ;
57
+ } ) ;
58
+
59
+ it ( 'should generate the appropriate context if no fields specified' , ( ) => {
60
+ const context = wrap ( constructCF ( ) ) ( 'data' ) . context ;
61
+ expect ( typeof context . eventId ) . to . equal ( 'string' ) ;
62
+ expect ( context . resource . service ) . to . equal ( 'service' ) ;
63
+ expect (
64
+ / r e f \/ w i l d c a r d [ 1 - 9 ] \/ n e s t e d \/ a n o t h e r W i l d c a r d [ 1 - 9 ] / . test (
65
+ context . resource . name
66
+ )
67
+ ) . to . be . true ;
68
+ expect ( context . eventType ) . to . equal ( 'event' ) ;
69
+ expect ( Date . parse ( context . timestamp ) ) . to . be . greaterThan ( 0 ) ;
70
+ expect ( context . params ) . to . deep . equal ( { } ) ;
71
+ expect ( context . auth ) . to . be . undefined ;
72
+ expect ( context . authType ) . to . be . undefined ;
73
+ } ) ;
74
+
75
+ it ( 'should allow specification of context fields' , ( ) => {
76
+ const wrapped = wrap ( constructCF ( ) ) ;
77
+ const context = wrapped ( 'data' , {
78
+ eventId : '111' ,
79
+ timestamp : '2018-03-28T18:58:50.370Z' ,
80
+ } ) . context ;
81
+ expect ( context . eventId ) . to . equal ( '111' ) ;
82
+ expect ( context . timestamp ) . to . equal ( '2018-03-28T18:58:50.370Z' ) ;
83
+ } ) ;
84
+
85
+ describe ( 'database functions' , ( ) => {
86
+ let test ;
87
+ let change ;
51
88
52
- it ( 'should generate the appropriate context if no fields specified' , ( ) => {
53
- const context = wrap ( constructBackgroundCF ( ) ) ( 'data' ) . context ;
54
- expect ( typeof context . eventId ) . to . equal ( 'string' ) ;
55
- expect ( context . resource . service ) . to . equal ( 'service' ) ;
56
- expect (
57
- / r e f \/ w i l d c a r d [ 1 - 9 ] \/ n e s t e d \/ a n o t h e r W i l d c a r d [ 1 - 9 ] / . test (
58
- context . resource . name
59
- )
60
- ) . to . be . true ;
61
- expect ( context . eventType ) . to . equal ( 'event' ) ;
62
- expect ( Date . parse ( context . timestamp ) ) . to . be . greaterThan ( 0 ) ;
63
- expect ( context . params ) . to . deep . equal ( { } ) ;
64
- expect ( context . auth ) . to . be . undefined ;
65
- expect ( context . authType ) . to . be . undefined ;
89
+ beforeEach ( ( ) => {
90
+ test = new FirebaseFunctionsTest ( ) ;
91
+ test . init ( ) ;
92
+ change = features . database . exampleDataSnapshotChange ( ) ;
66
93
} ) ;
67
94
68
- it ( 'should allow specification of context fields' , ( ) => {
69
- const wrapped = wrap ( constructBackgroundCF ( ) ) ;
70
- const context = wrapped ( 'data' , {
71
- eventId : '111' ,
72
- timestamp : '2018-03-28T18:58:50.370Z' ,
73
- } ) . context ;
74
- expect ( context . eventId ) . to . equal ( '111' ) ;
75
- expect ( context . timestamp ) . to . equal ( '2018-03-28T18:58:50.370Z' ) ;
95
+ afterEach ( ( ) => {
96
+ test . cleanup ( ) ;
76
97
} ) ;
77
98
78
- it ( 'should generate auth and authType for database functions' , ( ) => {
79
- const context = wrap ( constructBackgroundCF ( 'google.firebase.database.ref.write' ) ) (
80
- 'data'
81
- ) . context ;
99
+ it ( 'should generate auth and authType' , ( ) => {
100
+ const wrapped = wrap ( constructCF ( 'google.firebase.database.ref.write' ) ) ;
101
+ const context = wrapped ( change ) . context ;
82
102
expect ( context . auth ) . to . equal ( null ) ;
83
103
expect ( context . authType ) . to . equal ( 'UNAUTHENTICATED' ) ;
84
104
} ) ;
85
105
86
- it ( 'should allow auth and authType to be specified for database functions ' , ( ) => {
87
- const wrapped = wrap ( constructBackgroundCF ( 'google.firebase.database.ref.write' ) ) ;
88
- const context = wrapped ( 'data' , {
106
+ it ( 'should allow auth and authType to be specified' , ( ) => {
107
+ const wrapped = wrap ( constructCF ( 'google.firebase.database.ref.write' ) ) ;
108
+ const context = wrapped ( change , {
89
109
auth : { uid : 'abc' } ,
90
110
authType : 'USER' ,
91
111
} ) . context ;
92
112
expect ( context . auth ) . to . deep . equal ( { uid : 'abc' } ) ;
93
113
expect ( context . authType ) . to . equal ( 'USER' ) ;
94
114
} ) ;
115
+ } ) ;
95
116
96
- it ( 'should throw when passed invalid options' , ( ) => {
97
- const wrapped = wrap ( constructBackgroundCF ( ) ) ;
98
- expect ( ( ) =>
99
- wrapped ( 'data' , {
100
- auth : { uid : 'abc' } ,
101
- isInvalid : true ,
102
- } as any )
103
- ) . to . throw ( ) ;
104
- } ) ;
117
+ it ( 'should throw when passed invalid options' , ( ) => {
118
+ const wrapped = wrap ( constructCF ( ) ) ;
119
+ expect ( ( ) =>
120
+ wrapped ( 'data' , {
121
+ auth : { uid : 'abc' } ,
122
+ isInvalid : true ,
123
+ } as any )
124
+ ) . to . throw ( ) ;
125
+ } ) ;
105
126
106
- it ( 'should generate the appropriate resource based on params' , ( ) => {
107
- const params = {
108
- wildcard : 'a' ,
109
- anotherWildcard : 'b' ,
110
- } ;
111
- const wrapped = wrap ( constructBackgroundCF ( ) ) ;
112
- const context = wrapped ( 'data' , { params } ) . context ;
113
- expect ( context . params ) . to . deep . equal ( params ) ;
114
- expect ( context . resource . name ) . to . equal ( 'ref/a/nested/b' ) ;
115
- } ) ;
127
+ it ( 'should generate the appropriate resource based on params' , ( ) => {
128
+ const params = {
129
+ wildcard : 'a' ,
130
+ anotherWildcard : 'b' ,
131
+ } ;
132
+ const wrapped = wrap ( constructCF ( ) ) ;
133
+ const context = wrapped ( 'data' , { params } ) . context ;
134
+ expect ( context . params ) . to . deep . equal ( params ) ;
135
+ expect ( context . resource . name ) . to . equal ( 'ref/a/nested/b' ) ;
116
136
} ) ;
117
137
118
- describe ( 'callable functions ' , ( ) => {
119
- let wrappedCF ;
138
+ describe ( 'Params extraction ' , ( ) => {
139
+ let test ;
120
140
121
- before ( ( ) => {
122
- const cloudFunction = ( input ) => input ;
123
- set ( cloudFunction , 'run' , ( data , context ) => {
124
- return { data, context } ;
125
- } ) ;
126
- set ( cloudFunction , '__trigger' , {
127
- labels : {
128
- 'deployment-callable' : 'true' ,
129
- } ,
130
- httpsTrigger : { } ,
131
- } ) ;
132
- wrappedCF = wrap ( cloudFunction as functions . CloudFunction < any > ) ;
141
+ beforeEach ( ( ) => {
142
+ test = new FirebaseFunctionsTest ( ) ;
143
+ test . init ( ) ;
133
144
} ) ;
134
145
135
- it ( 'should invoke the function with the supplied data' , ( ) => {
136
- expect ( wrappedCF ( 'data' ) . data ) . to . equal ( 'data' ) ;
146
+ afterEach ( ( ) => {
147
+ test . cleanup ( ) ;
137
148
} ) ;
138
149
139
- it ( 'should allow specification of context fields' , ( ) => {
140
- const context = wrappedCF ( 'data' , {
141
- auth : { uid : 'abc' } ,
142
- app : { appId : 'efg' } ,
143
- instanceIdToken : '123' ,
144
- rawRequest : { body : 'hello' }
145
- } ) . context ;
146
- expect ( context . auth ) . to . deep . equal ( { uid : 'abc' } ) ;
147
- expect ( context . app ) . to . deep . equal ( { appId : 'efg' } ) ;
148
- expect ( context . instanceIdToken ) . to . equal ( '123' ) ;
149
- expect ( context . rawRequest ) . to . deep . equal ( { body : 'hello' } ) ;
150
+ it ( 'should extract the appropriate params for database function trigger' , ( ) => {
151
+ const cf = constructCF ( 'google.firebase.database.ref.create' ) ;
152
+ cf . __trigger . eventTrigger . resource = 'companies/{company}/users/{user}' ;
153
+ const wrapped = wrap ( cf ) ;
154
+ const context = wrapped (
155
+ features . database . makeDataSnapshot (
156
+ { foo : 'bar' } ,
157
+ 'companies/Google/users/Lauren'
158
+ )
159
+ ) . context ;
160
+ expect ( context . params ) . to . deep . equal ( {
161
+ company : 'Google' ,
162
+ user : 'Lauren' ,
163
+ } ) ;
164
+ expect ( context . resource . name ) . to . equal ( 'companies/Google/users/Lauren' ) ;
150
165
} ) ;
151
166
152
- it ( 'should throw when passed invalid options' , ( ) => {
153
- expect ( ( ) =>
154
- wrappedCF ( 'data' , {
155
- auth : { uid : 'abc' } ,
156
- isInvalid : true ,
157
- } as any )
158
- ) . to . throw ( ) ;
167
+ it ( 'should extract the appropriate params for Firestore function trigger' , ( ) => {
168
+ const cf = constructCF ( 'google.firestore.document.create' ) ;
169
+ cf . __trigger . eventTrigger . resource =
170
+ 'databases/(default)/documents/companies/{company}/users/{user}' ;
171
+ const wrapped = wrap ( cf ) ;
172
+ const context = wrapped (
173
+ features . firestore . makeDocumentSnapshot (
174
+ { foo : 'bar' } ,
175
+ 'companies/Google/users/Lauren'
176
+ )
177
+ ) . context ;
178
+ expect ( context . params ) . to . deep . equal ( {
179
+ company : 'Google' ,
180
+ user : 'Lauren' ,
181
+ } ) ;
182
+ expect ( context . resource . name ) . to . equal (
183
+ 'databases/(default)/documents/companies/Google/users/Lauren'
184
+ ) ;
159
185
} ) ;
160
186
187
+ it ( 'should prefer provided context.params over the extracted params' , ( ) => {
188
+ const cf = constructCF ( 'google.firebase.database.ref.create' ) ;
189
+ cf . __trigger . eventTrigger . resource = 'companies/{company}/users/{user}' ;
190
+ const wrapped = wrap ( cf ) ;
191
+ const context = wrapped (
192
+ features . database . makeDataSnapshot (
193
+ { foo : 'bar' } ,
194
+ 'companies/Google/users/Lauren'
195
+ ) ,
196
+ {
197
+ params : {
198
+ company : 'Alphabet' ,
199
+ user : 'Lauren' ,
200
+ foo : 'bar' ,
201
+ } ,
202
+ }
203
+ ) . context ;
204
+ expect ( context . params ) . to . deep . equal ( {
205
+ company : 'Alphabet' ,
206
+ user : 'Lauren' ,
207
+ foo : 'bar' ,
208
+ } ) ;
209
+ expect ( context . resource . name ) . to . equal (
210
+ 'companies/Alphabet/users/Lauren'
211
+ ) ;
212
+ } ) ;
161
213
} ) ;
162
214
} ) ;
163
215
@@ -171,6 +223,24 @@ describe('main', () => {
171
223
} ) ;
172
224
} ) ;
173
225
226
+ describe ( '#_extractParams' , ( ) => {
227
+ it ( 'should not extract any params' , ( ) => {
228
+ const params = _extractParams ( 'users/foo' , 'users/foo' ) ;
229
+ expect ( params ) . to . deep . equal ( { } ) ;
230
+ } ) ;
231
+
232
+ it ( 'should extract params' , ( ) => {
233
+ const params = _extractParams (
234
+ 'companies/{company}/users/{user}' ,
235
+ 'companies/Google/users/Lauren'
236
+ ) ;
237
+ expect ( params ) . to . deep . equal ( {
238
+ company : 'Google' ,
239
+ user : 'Lauren' ,
240
+ } ) ;
241
+ } ) ;
242
+ } ) ;
243
+
174
244
describe ( '#makeChange' , ( ) => {
175
245
it ( 'should make a Change object with the correct before and after' , ( ) => {
176
246
const change = makeChange ( 'before' , 'after' ) ;
0 commit comments