@@ -8,7 +8,13 @@ import {
8
8
} from '../shared'
9
9
import { AudienceSettings } from '../generated-types'
10
10
import { UpdateHandlerPayload } from '../types'
11
- import { UpdateUsersDataResponse , ErrorCode , ErrorInfo } from '../proto/protofile'
11
+ import {
12
+ UpdateUsersDataResponseSchema ,
13
+ UpdateUsersDataRequestSchema ,
14
+ ErrorCode ,
15
+ ErrorInfoSchema
16
+ } from '../proto/protofile'
17
+ import * as protobuf from '@bufbuild/protobuf'
12
18
import { StatsContext , Response } from '@segment/actions-core'
13
19
import createRequestClient from '../../../../../core/src/create-request-client'
14
20
@@ -20,6 +26,9 @@ const oneMockPayload: UpdateHandlerPayload = {
20
26
enable_batching : true
21
27
}
22
28
29
+ const normalizeJson = ( jsonString : string ) =>
30
+ JSON . stringify ( JSON . parse ( jsonString ) , Object . keys ( JSON . parse ( jsonString ) ) . sort ( ) )
31
+
23
32
const mockRequestClient = createRequestClient ( )
24
33
25
34
const manyMockPayloads : UpdateHandlerPayload [ ] = [
@@ -67,24 +76,25 @@ const getRandomError = () => {
67
76
68
77
// Mock only the error code. The contents of the response are not important.
69
78
const createMockResponse = ( errorCode : ErrorCode , payload : UpdateHandlerPayload [ ] ) => {
70
- const responseHandler = new UpdateUsersDataResponse ( )
79
+ const responseHandler = protobuf . create ( UpdateUsersDataResponseSchema , { } )
71
80
responseHandler . status = errorCode
72
81
73
82
if ( errorCode === ErrorCode . PARTIAL_SUCCESS ) {
74
83
// Making assumptions about IdType and UserId here because
75
84
// we are not currently testing their content therefore, it doesn't matter.
76
85
77
86
responseHandler . errors = payload . map ( ( p ) => {
78
- const errorInfo = new ErrorInfo ( )
79
- errorInfo . errorCode = getRandomError ( )
80
- errorInfo . userListId = BigInt ( p . external_audience_id . split ( '/' ) . pop ( ) || '-1' )
81
- errorInfo . userIdType = 0
82
- errorInfo . userId = p . google_gid || p . mobile_advertising_id || p . partner_provided_id || ''
87
+ const errorInfo = protobuf . create ( ErrorInfoSchema , {
88
+ errorCode : getRandomError ( ) ,
89
+ userListId : BigInt ( p . external_audience_id . split ( '/' ) . pop ( ) || '-1' ) ,
90
+ userIdType : 0 ,
91
+ userId : p . google_gid || p . mobile_advertising_id || p . partner_provided_id || ''
92
+ } )
83
93
return errorInfo
84
94
} )
85
95
}
86
96
87
- const b = Buffer . from ( responseHandler . toBinary ( ) )
97
+ const b = Buffer . from ( protobuf . toBinary ( UpdateUsersDataResponseSchema , responseHandler ) )
88
98
const arrayBuffer = b . buffer . slice ( b . byteOffset , b . byteOffset + b . byteLength )
89
99
90
100
return new Response ( arrayBuffer , { status : errorCode === ErrorCode . NO_ERROR ? 200 : 400 } )
@@ -202,8 +212,19 @@ describe('shared', () => {
202
212
const r = createUpdateRequest ( manyMockPayloads , 'add' )
203
213
expect ( r . ops . length ) . toEqual ( 5 )
204
214
expect ( r . processConsent ) . toEqual ( true )
205
- expect ( r . toJsonString ( ) ) . toMatchInlineSnapshot (
206
- `"{\\"ops\\":[{\\"userId\\":\\"CAESEHIV8HXNp0pFdHgi2rElMfk\\",\\"userIdType\\":\\"GOOGLE_USER_ID\\",\\"userListId\\":\\"456\\",\\"delete\\":false},{\\"userId\\":\\"3b6e47b3-1437-4ba2-b3c9-446e4d0cd1e5\\",\\"userIdType\\":\\"IDFA\\",\\"userListId\\":\\"456\\",\\"delete\\":false},{\\"userId\\":\\"my-anon-id-42\\",\\"userIdType\\":\\"PARTNER_PROVIDED_ID\\",\\"userListId\\":\\"456\\",\\"delete\\":false},{\\"userId\\":\\"my-anon-id-43\\",\\"userIdType\\":\\"PARTNER_PROVIDED_ID\\",\\"userListId\\":\\"456\\",\\"delete\\":false},{\\"userId\\":\\"XNp0pFdHgi2rElMfk\\",\\"userIdType\\":\\"GOOGLE_USER_ID\\",\\"userListId\\":\\"456\\",\\"delete\\":false}],\\"processConsent\\":true}"`
215
+ expect ( normalizeJson ( protobuf . toJsonString ( UpdateUsersDataRequestSchema , r ) ) ) . toEqual (
216
+ normalizeJson (
217
+ JSON . stringify ( {
218
+ ops : [
219
+ { userId : 'CAESEHIV8HXNp0pFdHgi2rElMfk' , userIdType : 'GOOGLE_USER_ID' , userListId : '456' , delete : false } ,
220
+ { userId : '3b6e47b3-1437-4ba2-b3c9-446e4d0cd1e5' , userIdType : 'IDFA' , userListId : '456' , delete : false } ,
221
+ { userId : 'my-anon-id-42' , userIdType : 'PARTNER_PROVIDED_ID' , userListId : '456' , delete : false } ,
222
+ { userId : 'my-anon-id-43' , userIdType : 'PARTNER_PROVIDED_ID' , userListId : '456' , delete : false } ,
223
+ { userId : 'XNp0pFdHgi2rElMfk' , userIdType : 'GOOGLE_USER_ID' , userListId : '456' , delete : false }
224
+ ] ,
225
+ processConsent : true
226
+ } )
227
+ )
207
228
)
208
229
} )
209
230
@@ -230,25 +251,33 @@ describe('shared', () => {
230
251
// The response will contain a list of errors. Its content is unknown.
231
252
// The endpoint will return a 400 status code.
232
253
it ( 'should gracefully fail' , async ( ) => {
233
- nock ( 'https://cm.g.doubleclick.net' ) . post ( '/upload?nid=segment' ) . reply ( 400 )
234
-
235
- UpdateUsersDataResponse . prototype . fromBinary = jest . fn ( ( ) => {
236
- const responseHandler = new UpdateUsersDataResponse ( )
237
- responseHandler . status = ErrorCode . PARTIAL_SUCCESS
238
- responseHandler . errors = [
239
- {
254
+ jest . spyOn ( protobuf , 'fromBinary' ) . mockImplementation ( ( ) => ( {
255
+ status : ErrorCode . PARTIAL_SUCCESS ,
256
+ errors : [
257
+ protobuf . create ( ErrorInfoSchema , {
240
258
errorCode : ErrorCode . BAD_DATA ,
241
259
userListId : BigInt ( 456 ) ,
242
260
userIdType : 0 ,
243
261
userId : 'CAESEHIV8HXNp0pFdHgi2rElMfk'
244
- } as ErrorInfo
245
- ]
246
- return responseHandler
247
- } )
262
+ } )
263
+ ] ,
264
+ $typeName : 'UpdateUsersDataResponse'
265
+ } ) )
248
266
249
- const r = createUpdateRequest ( manyMockPayloads , 'add' )
250
- await sendUpdateRequest ( mockRequestClient , r , 'addToAudience' , mockStatsContext )
251
- expect ( mockStatsClient . incr ) . toHaveBeenCalledWith ( 'addToAudience.error.PARTIAL_SUCCESS' , 1 , mockStatsContext . tags )
267
+ try {
268
+ nock ( 'https://cm.g.doubleclick.net' ) . post ( '/upload?nid=segment' ) . reply ( 400 )
269
+
270
+ const r = createUpdateRequest ( manyMockPayloads , 'add' )
271
+ await sendUpdateRequest ( mockRequestClient , r , 'addToAudience' , mockStatsContext )
272
+
273
+ expect ( mockStatsClient . incr ) . toHaveBeenCalledWith (
274
+ 'addToAudience.error.PARTIAL_SUCCESS' ,
275
+ 1 ,
276
+ mockStatsContext . tags
277
+ )
278
+ } finally {
279
+ jest . restoreAllMocks ( )
280
+ }
252
281
} )
253
282
254
283
it ( 'should abruptly fail' , async ( ) => {
0 commit comments