@fat-zebra/sdk 1.0.1 → 1.0.3

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (75) hide show
  1. package/dist/index.d.ts +1 -1
  2. package/dist/index.js +2 -5
  3. package/dist/react/VerifyCard.js +11 -17
  4. package/dist/react/index.js +2 -8
  5. package/dist/react/url.js +10 -14
  6. package/dist/react/useFatZebra.js +23 -63
  7. package/dist/sca/cardinal.d.ts +2 -1
  8. package/dist/sca/cardinal.js +22 -61
  9. package/dist/sca/eci-mappings.js +4 -8
  10. package/dist/sca/index.js +182 -296
  11. package/dist/sca/scenarios/enrollment.d.ts +2 -1
  12. package/dist/sca/scenarios/enrollment.js +25 -28
  13. package/dist/sca/scenarios/index.d.ts +4 -2
  14. package/dist/sca/scenarios/index.js +2 -7
  15. package/dist/sca/scenarios/validation.d.ts +2 -1
  16. package/dist/sca/scenarios/validation.js +16 -19
  17. package/dist/sca/types.d.ts +2 -1
  18. package/dist/sca/types.js +6 -8
  19. package/dist/shared/api-gateway-client.js +37 -81
  20. package/dist/shared/bridge-client.js +5 -8
  21. package/dist/shared/constants.js +6 -13
  22. package/dist/shared/event-manager.d.ts +2 -1
  23. package/dist/shared/event-manager.js +3 -9
  24. package/dist/shared/post-message-client.d.ts +2 -1
  25. package/dist/shared/post-message-client.js +38 -75
  26. package/dist/shared/types.d.ts +2 -1
  27. package/dist/shared/types.js +5 -7
  28. package/dist/shared/util.js +18 -31
  29. package/fat-zebra-sdk-1.0.2.tgz +0 -0
  30. package/package.json +2 -2
  31. package/tsconfig.json +6 -4
  32. package/dist/index.js.map +0 -1
  33. package/dist/react/VerifyCard.js.map +0 -1
  34. package/dist/react/index.js.map +0 -1
  35. package/dist/react/url.js.map +0 -1
  36. package/dist/react/useFatZebra.js.map +0 -1
  37. package/dist/sca/cardinal.js.map +0 -1
  38. package/dist/sca/eci-mappings.js.map +0 -1
  39. package/dist/sca/index.js.map +0 -1
  40. package/dist/sca/scenarios/enrollment.js.map +0 -1
  41. package/dist/sca/scenarios/index.js.map +0 -1
  42. package/dist/sca/scenarios/validation.js.map +0 -1
  43. package/dist/sca/types.js.map +0 -1
  44. package/dist/shared/api-gateway-client.js.map +0 -1
  45. package/dist/shared/bridge-client.js.map +0 -1
  46. package/dist/shared/constants.js.map +0 -1
  47. package/dist/shared/event-manager.js.map +0 -1
  48. package/dist/shared/post-message-client.js.map +0 -1
  49. package/dist/shared/types.js.map +0 -1
  50. package/dist/shared/util.js.map +0 -1
  51. package/src/index.ts +0 -9
  52. package/src/react/VerifyCard.tsx +0 -36
  53. package/src/react/index.ts +0 -3
  54. package/src/react/url.ts +0 -97
  55. package/src/react/useFatZebra.ts +0 -154
  56. package/src/sca/__tests__/eci-mappings.test.ts +0 -35
  57. package/src/sca/__tests__/index.test.ts +0 -514
  58. package/src/sca/cardinal.ts +0 -136
  59. package/src/sca/eci-mappings.ts +0 -63
  60. package/src/sca/index.ts +0 -329
  61. package/src/sca/scenarios/enrollment.ts +0 -164
  62. package/src/sca/scenarios/index.ts +0 -2
  63. package/src/sca/scenarios/validation.ts +0 -142
  64. package/src/sca/types.ts +0 -206
  65. package/src/shared/api-gateway-client.ts +0 -71
  66. package/src/shared/bridge-client.ts +0 -26
  67. package/src/shared/constants.ts +0 -19
  68. package/src/shared/event-manager.ts +0 -44
  69. package/src/shared/post-message-client.test.ts +0 -73
  70. package/src/shared/post-message-client.ts +0 -125
  71. package/src/shared/types.test.ts +0 -65
  72. package/src/shared/types.ts +0 -182
  73. package/src/shared/util.test.ts +0 -164
  74. package/src/shared/util.ts +0 -98
  75. package/tests/helpers/api-gateway-mock.ts +0 -46
@@ -1,154 +0,0 @@
1
- import { useEffect, useMemo } from "react";
2
- import * as FatZebra from "../shared/types"
3
- import { generatePaymentURL } from "./url";
4
- import Sca from "../sca"
5
- import GatewayClient from "../shared/api-gateway-client";
6
-
7
-
8
- interface SuccessEventDetail {
9
- message: string;
10
- data: any;
11
- }
12
-
13
- interface ErrorEventDetail {
14
- errors: string[];
15
- data: any;
16
- }
17
-
18
- type UseFatZebraProps = {
19
- username: string,
20
- handlers: FatZebra.Handlers,
21
- config: FatZebra.VerificationConfig,
22
- bridge: React.MutableRefObject<HTMLIFrameElement>,
23
- }
24
-
25
-
26
- const useFatZebra = ({ username, config, handlers, bridge }: UseFatZebraProps) => {
27
- const { options, accessToken, paymentIntent, verification } = config;
28
-
29
- const sca = useMemo(() => {
30
- const gatewayClient = new GatewayClient({ accessToken, username })
31
- return new Sca({ gatewayClient })
32
- }, [config, username])
33
-
34
-
35
- const emit = (
36
- event: FatZebra.PublicEvent,
37
- data: SuccessEventDetail | ErrorEventDetail
38
- ) => {
39
- const handler = handlers[event]
40
- if (handler) {
41
- handler(new CustomEvent(event, { detail: data }))
42
- }
43
- };
44
-
45
- const handleCreatePaymentResponse = (data: FatZebra.CreatePaymentResponse) => {
46
- const transactionPayload: FatZebra.TransactionPayload = {
47
- transactionId: data.transaction_id,
48
- responseCode: data.response_code,
49
- message: data.message,
50
- amount: data.amount,
51
- currency: data.currency,
52
- reference: data.reference,
53
- cardNumber: data.card_number,
54
- cardHolder: data.card_holder,
55
- cardExpiry: data.card_expiry,
56
- cardType: data.card_type,
57
- verification: data.v,
58
- }
59
-
60
- if (data.errors) {
61
- emit(FatZebra.PublicEvent.PAYMENT_ERROR, {
62
- message: 'Payment failed.',
63
- errors: data.errors,
64
- data: transactionPayload,
65
- })
66
- } else {
67
- emit(FatZebra.PublicEvent.PAYMENT_SUCCESS, {
68
- message: 'Payment successful.',
69
- data: transactionPayload,
70
- })
71
- }
72
- }
73
-
74
- const handleTokenizeCardResponse = (data: FatZebra.TokenizeCardResponse) => {
75
- if (data.errors) {
76
- emit(FatZebra.PublicEvent.TOKENIZATION_ERROR, {
77
- message: "Card tokenization failed.",
78
- errors: data.errors,
79
- data: null,
80
- });
81
- return;
82
- } else {
83
- emit(FatZebra.PublicEvent.TOKENIZATION_SUCCESS, {
84
- message: "Card tokenization success.",
85
- data: {
86
- token: data.token,
87
- },
88
- });
89
- }
90
-
91
- if (options.tokenizeOnly) return
92
-
93
- if (options.enableSca) {
94
- sca.run({ paymentIntent, bin: data.bin, cardToken: data.token })
95
- }
96
- }
97
-
98
- const messageHandler = (event: any) => {
99
- if (
100
- event.data &&
101
- event.data.source &&
102
- event.data.source.includes("react-devtools")
103
- )
104
- return;
105
- if (event.data.subject === FatZebra.BridgeEvent.BIN_LOOKUP) return;
106
-
107
- if (event.data.subject === FatZebra.BridgeEvent.FORM_VALIDATION_ERROR) {
108
- emit(FatZebra.PublicEvent.FORM_VALIDATION_ERROR, {
109
- errors: event.data.data,
110
- data: null,
111
- });
112
- return;
113
- }
114
-
115
- if (event.data.subject === FatZebra.BridgeEvent.FORM_VALIDATION_SUCCESS) {
116
- emit(FatZebra.PublicEvent.FORM_VALIDATION_SUCCESS, {
117
- errors: event.data.data,
118
- data: null,
119
- });
120
- return;
121
- }
122
-
123
- if (event.data.subject === FatZebra.BridgeEvent.CREATE_PAYMENT_RESPONSE) {
124
- handleCreatePaymentResponse(event.data.data)
125
- }
126
-
127
- if (event.data.subject === FatZebra.BridgeEvent.TOKENIZE_CARD_RESPONSE) {
128
- handleTokenizeCardResponse(event.data.data)
129
- }
130
- };
131
-
132
- useEffect(() => {
133
- window.addEventListener("message", messageHandler);
134
-
135
- return () => {
136
- window.removeEventListener("message", messageHandler);
137
- };
138
- }, []);
139
-
140
- const payment = paymentIntent.payment
141
-
142
- const url = generatePaymentURL({
143
- ...options,
144
- merchant: username,
145
- reference: payment.reference,
146
- amount: payment.amount,
147
- currency: payment.currency,
148
- hash: verification,
149
- })
150
-
151
- return { url }
152
- };
153
-
154
- export default useFatZebra;
@@ -1,35 +0,0 @@
1
- import { eciMappings, toFzSli } from '../eci-mappings'
2
-
3
- describe ('toFzSli', () => {
4
- describe ('ECI mapping exists', () => {
5
- it ('sli mapping => cardinal: 00, fz: 07', () => {
6
- expect(toFzSli('00')).toEqual('07')
7
- })
8
-
9
- it ('sli mapping => cardinal: 01, fz: 06', () => {
10
- expect(toFzSli('01')).toEqual('06')
11
- })
12
-
13
- it ('sli mapping => cardinal: 02, fz: 05', () => {
14
- expect(toFzSli('02')).toEqual('05')
15
- })
16
-
17
- it ('sli mapping => cardinal: 05, fz: 05', () => {
18
- expect(toFzSli('05')).toEqual('05')
19
- })
20
-
21
- it ('sli mapping => cardinal: 06, fz: 06', () => {
22
- expect(toFzSli('06')).toEqual('06')
23
- })
24
-
25
- it ('sli mapping => cardinal: 07, fz: 07', () => {
26
- expect(toFzSli('07')).toEqual('07')
27
- })
28
- })
29
-
30
- describe ('ECI mapping does not exist', () => {
31
- it ('sli mapping => cardinal: 09, fz: 09', () => {
32
- expect(toFzSli('09')).toEqual('09')
33
- })
34
- })
35
- })
@@ -1,514 +0,0 @@
1
- /**
2
- * @jest-environment jsdom
3
- */
4
-
5
- import Sca, { ScaConfig, ScaRunProps } from '..'
6
- import {
7
- Customer,
8
- PaymentIntent,
9
- PublicEvent,
10
- } from '../../shared/types'
11
- import { LocalStorageAccessTokenKey } from '../../shared/constants'
12
- import { mockRequest } from '../../../tests/helpers/api-gateway-mock'
13
- import * as nock from 'nock'
14
- import { CardinalManager } from '../cardinal'
15
- import { ChallengeWindowSize, EnrollSCARequest, ThreedsData } from '../types'
16
- import {
17
- enrollmentScenarios,
18
- EnrollmentScenario,
19
- } from '../scenarios'
20
- import GatewayClient from '../../shared/api-gateway-client'
21
-
22
- jest.mock('../cardinal')
23
- // mock module function
24
- const eventManager = require('../../shared/event-manager')
25
- eventManager.emit = jest.fn()
26
-
27
- interface ResponseOverride {
28
- status: number
29
- body: unknown
30
- }
31
-
32
- const mockCardinalManager = () => {
33
- // @ts-ignore
34
- CardinalManager.mockImplementation(() => {
35
- return {
36
- processBin: () => ['success'],
37
- setup: () => true,
38
- onPaymentSetupComplete: () => {
39
- return {
40
- sessionId: 'session_123'
41
- }
42
- },
43
- onPaymentValidated: () => true,
44
- continue: () => jest.fn()
45
- }
46
- })
47
- }
48
-
49
- const gatewayClient = new GatewayClient({
50
- accessToken: "abc1234",
51
- username: "TEST"
52
- })
53
-
54
- const scaTests = (config: ScaRunProps) => {
55
- const { paymentIntent, cardToken, customer } = config
56
-
57
- const requestCustomer = (customer: ScaRunProps['customer']): EnrollSCARequest['customer'] => {
58
- let properties: EnrollSCARequest['customer'] = {};
59
- if (!customer) return properties;
60
- if (customer.firstName) properties.first_name = customer.firstName
61
- if (customer.lastName) properties.last_name = customer.lastName
62
- if (customer.email) properties.email = customer.email
63
- if (customer.address) properties.address = customer.address
64
- if (customer.city) properties.city = customer.city
65
- if (customer.state) properties.state = customer.state
66
- if (customer.postcode) properties.postcode = customer.postcode
67
- if (customer.country) properties.country = customer.country
68
- return properties
69
- }
70
-
71
- const enrollmentRequestBody: EnrollSCARequest = {
72
- amount: paymentIntent.payment.amount,
73
- card_token: cardToken,
74
- currency: paymentIntent.payment.currency,
75
- reference: paymentIntent.payment.reference,
76
- hide_card_holder: paymentIntent.payment.hide_card_holder,
77
- verification: paymentIntent.verification,
78
- session_id: 'session_123',
79
- challenge_window_size: ChallengeWindowSize.SIZE_FULL_PAGE,
80
- customer: requestCustomer(customer),
81
- }
82
-
83
- const mockCreateSCASessionSuccess = () => {
84
- mockRequest({
85
- request: {
86
- action: 'POST',
87
- path: '/sca/session',
88
- body: {
89
- amount: paymentIntent.payment.amount,
90
- currency: paymentIntent.payment.currency,
91
- hide_card_holder: paymentIntent.payment.hide_card_holder,
92
- }
93
- },
94
- response: {
95
- status: 200,
96
- body: {
97
- data: {
98
- jwt: 'thisisajwt'
99
- }
100
- }
101
- }
102
- })
103
- }
104
-
105
- const mockSCASession = (override?: ResponseOverride) => {
106
- const responseBody = {
107
- data: {
108
- jwt: 'thisisajwt'
109
- }
110
- }
111
-
112
- mockRequest({
113
- request: {
114
- action: 'POST',
115
- path: '/sca/session',
116
- body: {
117
- amount: paymentIntent.payment.amount,
118
- currency: paymentIntent.payment.currency,
119
- hide_card_holder: paymentIntent.payment.hide_card_holder,
120
- }
121
- },
122
- response: {
123
- status: (override ? override.status : 200),
124
- body: (override ? override.body : responseBody)
125
- }
126
- })
127
- }
128
-
129
- const mockSCAEnrollment = (override?: ResponseOverride) => {
130
- const responseBody = {
131
- data: {
132
- action: {
133
- proceed: true
134
- },
135
- version: '1.0',
136
- enrolled: 'Y',
137
- acs_url: '',
138
- pareq: 'asdfasdf',
139
- pares: '',
140
- decision: 'ACCEPT',
141
- }
142
- }
143
-
144
- mockRequest({
145
- request: {
146
- action: 'POST',
147
- path: '/sca/enrollment',
148
- body: enrollmentRequestBody
149
- },
150
- response: {
151
- status: (override ? override.status : 200),
152
- body: (override ? override.body : responseBody)
153
- }
154
- })
155
- }
156
-
157
- describe('SCA session failed', () => {
158
- it('Emits fz.validation.error event with detail', async () => {
159
-
160
- mockRequest({
161
- request: {
162
- action: 'POST',
163
- path: '/sca/session',
164
- body: {
165
- amount: paymentIntent.payment.amount,
166
- currency: paymentIntent.payment.currency,
167
- hide_card_holder: paymentIntent.payment.hide_card_holder,
168
- }
169
- },
170
- response: {
171
- status: 422,
172
- body: {
173
- errors: ['Create SCA session error.']
174
- }
175
- }
176
- })
177
-
178
- mockSCAEnrollment()
179
-
180
- const sca = new Sca({ gatewayClient })
181
-
182
- await sca.run(config)
183
-
184
- const eventDetail: any = {
185
- detail: {
186
- errors: ['FatZebra.3DS: JWT creation failed.'],
187
- data: null
188
- }
189
- }
190
- expect(eventManager.emit).toHaveBeenCalledTimes(1)
191
- expect(eventManager.emit.mock.calls[0][0]).toBe(PublicEvent.SCA_ERROR)
192
- expect(eventManager.emit.mock.calls[0][1]).toMatchObject(eventDetail.detail)
193
- })
194
- })
195
-
196
- describe('Bin processing failed', () => {
197
- it('Emits fz.validation.error event without detail', async () => {
198
- //@ts-ignore
199
- CardinalManager.mockImplementation(() => {
200
- return {
201
- processBin: () => {
202
- throw new Error('GG')
203
- },
204
- setup: () => true,
205
- onPaymentSetupComplete: () => {
206
- return {
207
- sessionId: '123'
208
- }
209
- },
210
- onPaymentValidated: () => true
211
- }
212
- })
213
-
214
- mockCreateSCASessionSuccess()
215
- mockSCAEnrollment()
216
-
217
- const sca = new Sca({ gatewayClient })
218
- sca.cardinal = new CardinalManager()
219
- await sca.run(config)
220
-
221
- const eventDetail: any = {
222
- detail: {
223
- errors: ['FatZebra.3DS: BIN verification failed.'],
224
- data: null
225
- }
226
- }
227
-
228
- expect(eventManager.emit).toHaveBeenCalledTimes(1)
229
- expect(eventManager.emit.mock.calls[0][0]).toBe(PublicEvent.SCA_ERROR)
230
- expect(eventManager.emit.mock.calls[0][1]).toMatchObject(eventDetail.detail)
231
- })
232
- })
233
-
234
- describe('3DS version 2', () => {
235
- const scenarios = enrollmentScenarios.filter((item) => item.threedsVersion[0] == '2')
236
-
237
- scenarios.forEach((scenario: EnrollmentScenario) => {
238
- describe(`Enrollment: ${scenario.description}`, () => {
239
- beforeEach(() => {
240
- mockCardinalManager()
241
- mockSCASession()
242
- mockSCAEnrollment({
243
- status: 200,
244
- body: {
245
- data: {
246
- version: '2.1.0',
247
- cavv: 'cavv',
248
- eci: '05',
249
- xid: 'xid',
250
- pareq: 'pareq',
251
- pares: scenario.pares,
252
- enrolled: scenario.veresEnrolled,
253
- reason_code: scenario.reasonCode,
254
- directory_server_txn_id: 'txn123',
255
- ucaf_collection_indicator: 'ucaf123',
256
- }
257
- }
258
- })
259
- })
260
-
261
- it('SCA', async () => {
262
- const sca = new Sca({ gatewayClient})
263
- sca.cardinal = new CardinalManager()
264
- const spy = jest.spyOn(sca.cardinal, 'continue')
265
-
266
- await sca.run(config)
267
-
268
- if (scenario.outcome.authenticationType === 'challenge') {
269
- expect(spy).toHaveBeenCalledTimes(1)
270
- expect(eventManager.emit).toHaveBeenCalledTimes(0)
271
- return
272
- }
273
-
274
- if (scenario.outcome.success) {
275
- const eventDetail = {
276
- detail: {
277
- message: `FatZebra.3DS: 3DS success - ${scenario.description}.`,
278
- data: {
279
- cavv: 'cavv',
280
- par: scenario.pares,
281
- sli: '05',
282
- xid: 'xid',
283
- ver: 'Y',
284
- threedsVersion: '2.1.0',
285
- directoryServerTxnId: 'txn123',
286
- } as ThreedsData,
287
- }
288
- }
289
- expect(eventManager.emit).toHaveBeenCalledTimes(1)
290
- expect(eventManager.emit.mock.calls[0][0]).toBe(PublicEvent.SCA_SUCCESS)
291
- expect(eventManager.emit.mock.calls[0][1]).toMatchObject(eventDetail.detail)
292
- } else {
293
- const eventDetail = {
294
- detail: {
295
- errors: [`FatZebra.3DS: 3DS error - ${scenario.description}`],
296
- data: {
297
- errorCode: scenario.outcome.errorCode
298
- },
299
- }
300
- }
301
- expect(eventManager.emit).toHaveBeenCalledTimes(1)
302
- expect(eventManager.emit.mock.calls[0][0]).toBe(PublicEvent.SCA_ERROR)
303
- expect(eventManager.emit.mock.calls[0][1]).toMatchObject(eventDetail.detail)
304
- }
305
- })
306
- })
307
- })
308
- })
309
-
310
- describe('3DS version 1', () => {
311
- const scenarios = enrollmentScenarios.filter((item) => item.threedsVersion[0] == '1')
312
-
313
- scenarios.forEach((scenario: EnrollmentScenario) => {
314
- describe(`Enrollment: ${scenario.description}`, () => {
315
- beforeEach(() => {
316
- mockCardinalManager()
317
- mockSCASession()
318
- mockSCAEnrollment({
319
- status: 200,
320
- body: {
321
- data: {
322
- version: '1.0.2',
323
- cavv: 'cavv',
324
- eci: '05',
325
- xid: 'xid',
326
- pareq: 'pareq',
327
- pares: scenario.pares,
328
- enrolled: scenario.veresEnrolled,
329
- reason_code: scenario.reasonCode,
330
- directory_server_txn_id: 'txn123',
331
- ucaf_collection_indicator: 'ucaf123',
332
- }
333
- }
334
- })
335
- })
336
-
337
- it('SCA', async () => {
338
- const sca = new Sca({ gatewayClient })
339
- sca.cardinal = new CardinalManager()
340
- const spy = jest.spyOn(sca.cardinal, 'continue')
341
-
342
- await sca.run(config)
343
-
344
- if (scenario.outcome.authenticationType === 'challenge') {
345
- expect(spy).toHaveBeenCalledTimes(1)
346
- expect(eventManager.emit).toHaveBeenCalledTimes(0)
347
- return
348
- }
349
-
350
- if (scenario.outcome.success) {
351
- const eventDetail = {
352
- detail: {
353
- message: `FatZebra.3DS: 3DS success - ${scenario.description}.`,
354
- data: {
355
- cavv: 'cavv',
356
- par: scenario.pares,
357
- sli: '05',
358
- xid: 'xid',
359
- ver: scenario.veresEnrolled,
360
- threedsVersion: '1.0.2',
361
- directoryServerTxnId: 'txn123',
362
- } as ThreedsData,
363
- }
364
- }
365
- expect(eventManager.emit).toHaveBeenCalledTimes(1)
366
- expect(eventManager.emit.mock.calls[0][0]).toBe(PublicEvent.SCA_SUCCESS)
367
- expect(eventManager.emit.mock.calls[0][1]).toMatchObject(eventDetail.detail)
368
- } else {
369
- const eventDetail = {
370
- detail: {
371
- errors: [`FatZebra.3DS: 3DS error - ${scenario.description}`],
372
- data: {
373
- errorCode: scenario.outcome.errorCode
374
- },
375
- }
376
- }
377
- expect(eventManager.emit).toHaveBeenCalledTimes(1)
378
- expect(eventManager.emit.mock.calls[0][0]).toBe(PublicEvent.SCA_ERROR)
379
- expect(eventManager.emit.mock.calls[0][1]).toMatchObject(eventDetail.detail)
380
- }
381
- })
382
- })
383
- })
384
- })
385
- }
386
-
387
- describe('Sca', () => {
388
- beforeEach(() => {
389
- jest.clearAllMocks()
390
- nock.disableNetConnect()
391
- nock.cleanAll()
392
-
393
- mockCardinalManager()
394
-
395
- localStorage.setItem(LocalStorageAccessTokenKey, 'TOKEN')
396
- })
397
-
398
- const bin = '400000'
399
- const cardToken = 'token_12345'
400
- const paymentIntent: PaymentIntent = {
401
- payment: {
402
- amount: 1000,
403
- currency: 'AUD',
404
- reference: 'ref_12345',
405
- hide_card_holder: false,
406
- },
407
- verification: 'ver_12345'
408
- }
409
-
410
- describe('#run', () => {
411
- describe('customer details: full', () => {
412
- const customer: Customer = {
413
- firstName: 'Ziggy',
414
- lastName: 'Zebra',
415
- email: 'ziggy.zebra@fatzebra.com',
416
- address: '2/58-62 Kippax Street',
417
- city: 'Surry Hills',
418
- postcode: '2010',
419
- state: 'NSW',
420
- country: 'Australia'
421
- }
422
- const config = {
423
- bin,
424
- cardToken,
425
- customer,
426
- paymentIntent,
427
- }
428
-
429
- scaTests(config)
430
- })
431
-
432
- describe('customer details: partial', () => {
433
- const customer: Customer = {
434
- firstName: 'Ziggy',
435
- lastName: '',
436
- email: 'ziggy.zebra@fatzebra.com',
437
- address: null,
438
- city: undefined,
439
- postcode: '',
440
- }
441
-
442
- const config = {
443
- bin,
444
- cardToken,
445
- customer,
446
- paymentIntent,
447
- }
448
-
449
- scaTests(config)
450
- })
451
-
452
- describe('customer details: empty', () => {
453
- const customer: Customer = {}
454
-
455
- const config = {
456
- bin,
457
- cardToken,
458
- customer,
459
- paymentIntent,
460
- }
461
-
462
- scaTests(config)
463
- })
464
-
465
- describe('no customer', () => {
466
- const config = {
467
- bin,
468
- cardToken,
469
- paymentIntent,
470
- }
471
-
472
- scaTests(config)
473
- })
474
- })
475
-
476
- describe('#customerProperties', () => {
477
- const sca = new Sca({ gatewayClient })
478
-
479
- it('formats the property keys into snake_case', () => {
480
- const customer: Customer = {
481
- firstName: 'Ziggy',
482
- lastName: 'Zebra',
483
- }
484
-
485
- const expectedProperties = {
486
- first_name: 'Ziggy',
487
- last_name: 'Zebra',
488
- }
489
-
490
- expect(sca.customerProperties(customer)).toEqual(expectedProperties)
491
- })
492
-
493
- it('only retains non-empty customer properties', () => {
494
- const customer: Customer = {
495
- firstName: 'Ziggy',
496
- lastName: 'Zebra',
497
- email: 'ziggy.zebra@fatzebra.com',
498
- address: null,
499
- city: null,
500
- postcode: undefined,
501
- state: undefined,
502
- country: ''
503
- }
504
-
505
- const expectedProperties = {
506
- first_name: 'Ziggy',
507
- last_name: 'Zebra',
508
- email: 'ziggy.zebra@fatzebra.com',
509
- }
510
-
511
- expect(sca.customerProperties(customer)).toEqual(expectedProperties)
512
- })
513
- })
514
- })