@easyflow/javascript-sdk 2.1.8 → 2.1.9
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.
- package/README.md +71 -7
- package/dist/index.d.ts +421 -0
- package/package.json +19 -6
- package/.babelrc +0 -5
- package/.github/workflows/deploy-sdk-cf.yml +0 -49
- package/.github/workflows/release-sdk-cdn.yml +0 -144
- package/.github/workflows/release-sdk.yml +0 -112
- package/.prettierrc +0 -6
- package/CDN-DEPLOYMENT.md +0 -175
- package/DEMO.md +0 -258
- package/DEPLOYMENT.md +0 -224
- package/INTEGRATION-GUIDE.md +0 -521
- package/coverage/base.css +0 -224
- package/coverage/block-navigation.js +0 -87
- package/coverage/easyflow-javascript-sdk/index.html +0 -116
- package/coverage/easyflow-javascript-sdk/libs/constants.mjs.html +0 -268
- package/coverage/easyflow-javascript-sdk/libs/errors.mjs.html +0 -271
- package/coverage/easyflow-javascript-sdk/libs/exception-handler.mjs.html +0 -148
- package/coverage/easyflow-javascript-sdk/libs/fingerprint.mjs.html +0 -895
- package/coverage/easyflow-javascript-sdk/libs/http.mjs.html +0 -502
- package/coverage/easyflow-javascript-sdk/libs/index.html +0 -266
- package/coverage/easyflow-javascript-sdk/libs/logger.mjs.html +0 -568
- package/coverage/easyflow-javascript-sdk/libs/sanitizer.mjs.html +0 -1099
- package/coverage/easyflow-javascript-sdk/libs/security.mjs.html +0 -733
- package/coverage/easyflow-javascript-sdk/libs/types.mjs.html +0 -508
- package/coverage/easyflow-javascript-sdk/libs/utils.mjs.html +0 -379
- package/coverage/easyflow-javascript-sdk/libs/validator.mjs.html +0 -2623
- package/coverage/easyflow-javascript-sdk/sdk.mjs.html +0 -2434
- package/coverage/favicon.png +0 -0
- package/coverage/index.html +0 -131
- package/coverage/lcov-report/base.css +0 -224
- package/coverage/lcov-report/block-navigation.js +0 -87
- package/coverage/lcov-report/easyflow-javascript-sdk/index.html +0 -116
- package/coverage/lcov-report/easyflow-javascript-sdk/libs/constants.mjs.html +0 -268
- package/coverage/lcov-report/easyflow-javascript-sdk/libs/errors.mjs.html +0 -271
- package/coverage/lcov-report/easyflow-javascript-sdk/libs/exception-handler.mjs.html +0 -148
- package/coverage/lcov-report/easyflow-javascript-sdk/libs/fingerprint.mjs.html +0 -895
- package/coverage/lcov-report/easyflow-javascript-sdk/libs/http.mjs.html +0 -502
- package/coverage/lcov-report/easyflow-javascript-sdk/libs/index.html +0 -266
- package/coverage/lcov-report/easyflow-javascript-sdk/libs/logger.mjs.html +0 -568
- package/coverage/lcov-report/easyflow-javascript-sdk/libs/sanitizer.mjs.html +0 -1099
- package/coverage/lcov-report/easyflow-javascript-sdk/libs/security.mjs.html +0 -733
- package/coverage/lcov-report/easyflow-javascript-sdk/libs/types.mjs.html +0 -508
- package/coverage/lcov-report/easyflow-javascript-sdk/libs/utils.mjs.html +0 -379
- package/coverage/lcov-report/easyflow-javascript-sdk/libs/validator.mjs.html +0 -2623
- package/coverage/lcov-report/easyflow-javascript-sdk/sdk.mjs.html +0 -2434
- package/coverage/lcov-report/favicon.png +0 -0
- package/coverage/lcov-report/index.html +0 -131
- package/coverage/lcov-report/prettify.css +0 -1
- package/coverage/lcov-report/prettify.js +0 -2
- package/coverage/lcov-report/sort-arrow-sprite.png +0 -0
- package/coverage/lcov-report/sorter.js +0 -196
- package/coverage/lcov.info +0 -1429
- package/coverage/prettify.css +0 -1
- package/coverage/prettify.js +0 -2
- package/coverage/sort-arrow-sprite.png +0 -0
- package/coverage/sorter.js +0 -196
- package/dist/435.easyflow-sdk.min.js +0 -1
- package/dist/easyflow-sdk.min.js +0 -1
- package/dist/easyflow-sdk.min.js.LICENSE.txt +0 -1
- package/dist/index.html +0 -756
- package/docs/index.html +0 -775
- package/examples/lovable-integration.html +0 -410
- package/index.html +0 -981
- package/jest.config.js +0 -37
- package/jsdoc.json +0 -42
- package/libs/auto-integration.mjs +0 -333
- package/libs/constants.mjs +0 -61
- package/libs/constants.spec.js +0 -198
- package/libs/errors.mjs +0 -62
- package/libs/errors.spec.js +0 -178
- package/libs/exception-handler.mjs +0 -21
- package/libs/exception-handler.spec.js +0 -237
- package/libs/fingerprint.mjs +0 -270
- package/libs/http.mjs +0 -163
- package/libs/http.spec.js +0 -427
- package/libs/integration-wrapper.mjs +0 -285
- package/libs/logger.mjs +0 -161
- package/libs/logger.spec.js +0 -389
- package/libs/sanitizer.mjs +0 -340
- package/libs/sanitizer.spec.js +0 -583
- package/libs/security.mjs +0 -217
- package/libs/types.mjs +0 -141
- package/libs/utils.mjs +0 -368
- package/libs/utils.spec.js +0 -231
- package/libs/validator.mjs +0 -952
- package/libs/validator.spec.js +0 -615
- package/mocks/offer.mock.js +0 -77
- package/scripts/publish-npm.sh +0 -82
- package/sdk.mjs +0 -945
- package/sdk.spec.js +0 -796
- package/test-setup.cjs +0 -211
- package/test.html +0 -154
- package/webpack.config.cjs +0 -41
package/libs/http.spec.js
DELETED
|
@@ -1,427 +0,0 @@
|
|
|
1
|
-
import { jest } from '@jest/globals'
|
|
2
|
-
|
|
3
|
-
// Mock dependencies ESM-safe
|
|
4
|
-
await jest.unstable_mockModule('./utils.mjs', () => ({
|
|
5
|
-
buildApiUrl: jest.fn(),
|
|
6
|
-
getBrowserFingerprint: jest.fn(() => 'mock-fingerprint-123'),
|
|
7
|
-
}))
|
|
8
|
-
|
|
9
|
-
await jest.unstable_mockModule('./exception-handler.mjs', () => ({
|
|
10
|
-
throwsError: jest.fn((error) => {
|
|
11
|
-
throw error
|
|
12
|
-
}),
|
|
13
|
-
}))
|
|
14
|
-
|
|
15
|
-
await jest.unstable_mockModule('./security.mjs', () => ({
|
|
16
|
-
SecureFetch: {
|
|
17
|
-
request: jest.fn(),
|
|
18
|
-
},
|
|
19
|
-
}))
|
|
20
|
-
|
|
21
|
-
await jest.unstable_mockModule('./errors.mjs', () => ({
|
|
22
|
-
NetworkError: jest.fn().mockImplementation((message) => ({
|
|
23
|
-
name: 'NetworkError',
|
|
24
|
-
message,
|
|
25
|
-
code: 'NETWORK_ERROR',
|
|
26
|
-
})),
|
|
27
|
-
SecurityError: jest.fn().mockImplementation((message) => ({
|
|
28
|
-
name: 'SecurityError',
|
|
29
|
-
message,
|
|
30
|
-
code: 'SECURITY_VIOLATION',
|
|
31
|
-
})),
|
|
32
|
-
ValidationError: jest.fn().mockImplementation((message) => ({
|
|
33
|
-
name: 'ValidationError',
|
|
34
|
-
message,
|
|
35
|
-
code: 'VALIDATION_ERROR',
|
|
36
|
-
})),
|
|
37
|
-
}))
|
|
38
|
-
|
|
39
|
-
await jest.unstable_mockModule('./constants.mjs', () => ({
|
|
40
|
-
DEFAULT_CONFIG: {
|
|
41
|
-
baseUrl: 'https://api.example.com',
|
|
42
|
-
},
|
|
43
|
-
HTTP_REQUEST_METHODS: {
|
|
44
|
-
POST: 'POST',
|
|
45
|
-
},
|
|
46
|
-
TARGETS: {
|
|
47
|
-
CHARGE: 'charge',
|
|
48
|
-
PLACE_ORDER: 'place-order',
|
|
49
|
-
ENCRYPT: 'encrypt',
|
|
50
|
-
GET_OFFER: 'get-offer',
|
|
51
|
-
GET_ORDER: 'get-order',
|
|
52
|
-
},
|
|
53
|
-
}))
|
|
54
|
-
|
|
55
|
-
const { callSecureApi } = await import('./http.mjs')
|
|
56
|
-
const { buildApiUrl } = await import('./utils.mjs')
|
|
57
|
-
const { SecureFetch } = await import('./security.mjs')
|
|
58
|
-
const { throwsError } = await import('./exception-handler.mjs')
|
|
59
|
-
|
|
60
|
-
describe('HTTP Module', () => {
|
|
61
|
-
let mockBuildApiUrl
|
|
62
|
-
let mockSecureFetchRequest
|
|
63
|
-
let mockThrowsError
|
|
64
|
-
|
|
65
|
-
beforeEach(() => {
|
|
66
|
-
jest.clearAllMocks()
|
|
67
|
-
mockBuildApiUrl = buildApiUrl
|
|
68
|
-
mockSecureFetchRequest = SecureFetch.request
|
|
69
|
-
mockThrowsError = throwsError
|
|
70
|
-
})
|
|
71
|
-
|
|
72
|
-
describe('callSecureApi', () => {
|
|
73
|
-
test('should make GET request for get-offer target', async () => {
|
|
74
|
-
const mockResponse = { data: { id: 'offer-123' } }
|
|
75
|
-
mockSecureFetchRequest.mockResolvedValue({
|
|
76
|
-
json: jest.fn().mockResolvedValue(mockResponse),
|
|
77
|
-
})
|
|
78
|
-
mockBuildApiUrl.mockReturnValue(
|
|
79
|
-
'https://api.example.com/api/proxy?target=get-offer&offerId=123'
|
|
80
|
-
)
|
|
81
|
-
|
|
82
|
-
const result = await callSecureApi('get-offer', { offerId: '123' })
|
|
83
|
-
|
|
84
|
-
expect(result).toEqual(mockResponse)
|
|
85
|
-
expect(mockBuildApiUrl).toHaveBeenCalledWith(
|
|
86
|
-
'https://api.example.com',
|
|
87
|
-
'get-offer',
|
|
88
|
-
{ offerId: '123' }
|
|
89
|
-
)
|
|
90
|
-
expect(mockSecureFetchRequest).toHaveBeenCalledWith(
|
|
91
|
-
'https://api.example.com/api/proxy?target=get-offer&offerId=123',
|
|
92
|
-
{
|
|
93
|
-
method: 'POST',
|
|
94
|
-
headers: { 'x-fingerprint-id': 'mock-fingerprint-123' },
|
|
95
|
-
}
|
|
96
|
-
)
|
|
97
|
-
})
|
|
98
|
-
|
|
99
|
-
test('should make GET request for get-order target', async () => {
|
|
100
|
-
const mockResponse = { data: { id: 'order-123' } }
|
|
101
|
-
mockSecureFetchRequest.mockResolvedValue({
|
|
102
|
-
json: jest.fn().mockResolvedValue(mockResponse),
|
|
103
|
-
})
|
|
104
|
-
mockBuildApiUrl.mockReturnValue(
|
|
105
|
-
'https://api.example.com/api/proxy?target=get-order&orderId=123'
|
|
106
|
-
)
|
|
107
|
-
|
|
108
|
-
const result = await callSecureApi('get-order', { orderId: '123' })
|
|
109
|
-
|
|
110
|
-
expect(result).toEqual(mockResponse)
|
|
111
|
-
expect(mockBuildApiUrl).toHaveBeenCalledWith(
|
|
112
|
-
'https://api.example.com',
|
|
113
|
-
'get-order',
|
|
114
|
-
{ orderId: '123' }
|
|
115
|
-
)
|
|
116
|
-
})
|
|
117
|
-
|
|
118
|
-
test('should make POST request for other targets', async () => {
|
|
119
|
-
const mockResponse = { data: { orderId: 'order-123' } }
|
|
120
|
-
mockSecureFetchRequest.mockResolvedValue({
|
|
121
|
-
json: jest.fn().mockResolvedValue(mockResponse),
|
|
122
|
-
})
|
|
123
|
-
mockBuildApiUrl.mockReturnValue(
|
|
124
|
-
'https://api.example.com/api/proxy?target=charge'
|
|
125
|
-
)
|
|
126
|
-
|
|
127
|
-
const payload = { businessId: '123', amount: 1000 }
|
|
128
|
-
const result = await callSecureApi('charge', payload, {
|
|
129
|
-
'Content-Type': 'application/json',
|
|
130
|
-
})
|
|
131
|
-
|
|
132
|
-
expect(result).toEqual(mockResponse)
|
|
133
|
-
expect(mockBuildApiUrl).toHaveBeenCalledWith(
|
|
134
|
-
'https://api.example.com',
|
|
135
|
-
'charge'
|
|
136
|
-
)
|
|
137
|
-
expect(mockSecureFetchRequest).toHaveBeenCalledWith(
|
|
138
|
-
'https://api.example.com/api/proxy?target=charge',
|
|
139
|
-
{
|
|
140
|
-
method: 'POST',
|
|
141
|
-
headers: {
|
|
142
|
-
'Content-Type': 'application/json',
|
|
143
|
-
'x-fingerprint-id': 'mock-fingerprint-123',
|
|
144
|
-
},
|
|
145
|
-
body: JSON.stringify(payload),
|
|
146
|
-
}
|
|
147
|
-
)
|
|
148
|
-
})
|
|
149
|
-
|
|
150
|
-
test('should handle API error responses', async () => {
|
|
151
|
-
mockSecureFetchRequest.mockResolvedValue({
|
|
152
|
-
json: jest.fn().mockResolvedValue({ error: 'API Error' }),
|
|
153
|
-
})
|
|
154
|
-
mockBuildApiUrl.mockReturnValue(
|
|
155
|
-
'https://api.example.com/api/proxy?target=charge'
|
|
156
|
-
)
|
|
157
|
-
await expect(callSecureApi('charge', {})).resolves.toEqual({
|
|
158
|
-
error: 'API Error',
|
|
159
|
-
})
|
|
160
|
-
})
|
|
161
|
-
|
|
162
|
-
test('should handle network errors', async () => {
|
|
163
|
-
mockSecureFetchRequest.mockResolvedValue({
|
|
164
|
-
json: jest.fn().mockResolvedValue({
|
|
165
|
-
error: 'Network error: Network timeout',
|
|
166
|
-
}),
|
|
167
|
-
})
|
|
168
|
-
mockBuildApiUrl.mockReturnValue(
|
|
169
|
-
'https://api.example.com/api/proxy?target=charge'
|
|
170
|
-
)
|
|
171
|
-
await expect(callSecureApi('charge', {})).resolves.toEqual({
|
|
172
|
-
error: 'Network error: Network timeout',
|
|
173
|
-
})
|
|
174
|
-
})
|
|
175
|
-
|
|
176
|
-
test('should handle known SDK errors', async () => {
|
|
177
|
-
mockSecureFetchRequest.mockResolvedValue({
|
|
178
|
-
json: jest
|
|
179
|
-
.fn()
|
|
180
|
-
.mockResolvedValue({ error: 'Security violation' }),
|
|
181
|
-
})
|
|
182
|
-
mockBuildApiUrl.mockReturnValue(
|
|
183
|
-
'https://api.example.com/api/proxy?target=charge'
|
|
184
|
-
)
|
|
185
|
-
await expect(callSecureApi('charge', {})).resolves.toEqual({
|
|
186
|
-
error: 'Security violation',
|
|
187
|
-
})
|
|
188
|
-
})
|
|
189
|
-
|
|
190
|
-
test('should handle validation errors', async () => {
|
|
191
|
-
mockSecureFetchRequest.mockResolvedValue({
|
|
192
|
-
json: jest.fn().mockResolvedValue({ error: 'Invalid input' }),
|
|
193
|
-
})
|
|
194
|
-
mockBuildApiUrl.mockReturnValue(
|
|
195
|
-
'https://api.example.com/api/proxy?target=charge'
|
|
196
|
-
)
|
|
197
|
-
await expect(callSecureApi('charge', {})).resolves.toEqual({
|
|
198
|
-
error: 'Invalid input',
|
|
199
|
-
})
|
|
200
|
-
})
|
|
201
|
-
|
|
202
|
-
test('should handle network errors from SecureFetch', async () => {
|
|
203
|
-
mockSecureFetchRequest.mockResolvedValue({
|
|
204
|
-
json: jest.fn().mockResolvedValue({
|
|
205
|
-
error: 'HTTP 500: Internal Server Error',
|
|
206
|
-
}),
|
|
207
|
-
})
|
|
208
|
-
mockBuildApiUrl.mockReturnValue(
|
|
209
|
-
'https://api.example.com/api/proxy?target=charge'
|
|
210
|
-
)
|
|
211
|
-
await expect(callSecureApi('charge', {})).resolves.toEqual({
|
|
212
|
-
error: 'HTTP 500: Internal Server Error',
|
|
213
|
-
})
|
|
214
|
-
})
|
|
215
|
-
|
|
216
|
-
test('should pass headers to SecureFetch', async () => {
|
|
217
|
-
const mockResponse = { data: { orderId: 'order-123' } }
|
|
218
|
-
mockSecureFetchRequest.mockResolvedValue({
|
|
219
|
-
json: jest.fn().mockResolvedValue(mockResponse),
|
|
220
|
-
})
|
|
221
|
-
mockBuildApiUrl.mockReturnValue(
|
|
222
|
-
'https://api.example.com/api/proxy?target=charge'
|
|
223
|
-
)
|
|
224
|
-
|
|
225
|
-
const customHeaders = { 'Content-Type': 'application/json' }
|
|
226
|
-
const result = await callSecureApi(
|
|
227
|
-
'charge',
|
|
228
|
-
{ amount: 1000 },
|
|
229
|
-
customHeaders
|
|
230
|
-
)
|
|
231
|
-
|
|
232
|
-
expect(result).toEqual(mockResponse)
|
|
233
|
-
expect(mockSecureFetchRequest).toHaveBeenCalledWith(
|
|
234
|
-
'https://api.example.com/api/proxy?target=charge',
|
|
235
|
-
{
|
|
236
|
-
method: 'POST',
|
|
237
|
-
headers: {
|
|
238
|
-
...customHeaders,
|
|
239
|
-
'x-fingerprint-id': 'mock-fingerprint-123',
|
|
240
|
-
},
|
|
241
|
-
body: JSON.stringify({ amount: 1000 }),
|
|
242
|
-
}
|
|
243
|
-
)
|
|
244
|
-
})
|
|
245
|
-
|
|
246
|
-
test('should handle empty headers', async () => {
|
|
247
|
-
const mockResponse = { data: { success: true } }
|
|
248
|
-
mockSecureFetchRequest.mockResolvedValue({
|
|
249
|
-
json: jest.fn().mockResolvedValue(mockResponse),
|
|
250
|
-
})
|
|
251
|
-
mockBuildApiUrl.mockReturnValue(
|
|
252
|
-
'https://api.example.com/api/proxy?target=charge'
|
|
253
|
-
)
|
|
254
|
-
|
|
255
|
-
await callSecureApi('charge', { amount: 1000 }, {})
|
|
256
|
-
|
|
257
|
-
expect(mockSecureFetchRequest).toHaveBeenCalledWith(
|
|
258
|
-
'https://api.example.com/api/proxy?target=charge',
|
|
259
|
-
{
|
|
260
|
-
method: 'POST',
|
|
261
|
-
headers: { 'x-fingerprint-id': 'mock-fingerprint-123' },
|
|
262
|
-
body: JSON.stringify({ amount: 1000 }),
|
|
263
|
-
}
|
|
264
|
-
)
|
|
265
|
-
})
|
|
266
|
-
|
|
267
|
-
test('should handle undefined headers', async () => {
|
|
268
|
-
const mockResponse = { data: { success: true } }
|
|
269
|
-
mockSecureFetchRequest.mockResolvedValue({
|
|
270
|
-
json: jest.fn().mockResolvedValue(mockResponse),
|
|
271
|
-
})
|
|
272
|
-
mockBuildApiUrl.mockReturnValue(
|
|
273
|
-
'https://api.example.com/api/proxy?target=charge'
|
|
274
|
-
)
|
|
275
|
-
|
|
276
|
-
await callSecureApi('charge', { amount: 1000 })
|
|
277
|
-
|
|
278
|
-
expect(mockSecureFetchRequest).toHaveBeenCalledWith(
|
|
279
|
-
'https://api.example.com/api/proxy?target=charge',
|
|
280
|
-
{
|
|
281
|
-
method: 'POST',
|
|
282
|
-
headers: { 'x-fingerprint-id': 'mock-fingerprint-123' },
|
|
283
|
-
body: JSON.stringify({ amount: 1000 }),
|
|
284
|
-
}
|
|
285
|
-
)
|
|
286
|
-
})
|
|
287
|
-
|
|
288
|
-
test('should handle complex payload objects', async () => {
|
|
289
|
-
const mockResponse = { data: { orderId: 'order-123' } }
|
|
290
|
-
mockSecureFetchRequest.mockResolvedValue({
|
|
291
|
-
json: jest.fn().mockResolvedValue(mockResponse),
|
|
292
|
-
})
|
|
293
|
-
mockBuildApiUrl.mockReturnValue(
|
|
294
|
-
'https://api.example.com/api/proxy?target=place-order'
|
|
295
|
-
)
|
|
296
|
-
|
|
297
|
-
const complexPayload = {
|
|
298
|
-
businessId: 'business-123',
|
|
299
|
-
payments: [
|
|
300
|
-
{
|
|
301
|
-
method: 'credit-card',
|
|
302
|
-
creditCard: {
|
|
303
|
-
cardNumber: '4111111111111111',
|
|
304
|
-
holderName: 'John Doe',
|
|
305
|
-
month: '12',
|
|
306
|
-
year: '2025',
|
|
307
|
-
cvv: '123',
|
|
308
|
-
},
|
|
309
|
-
numberInstallments: 1,
|
|
310
|
-
},
|
|
311
|
-
],
|
|
312
|
-
buyer: {
|
|
313
|
-
name: 'John Doe',
|
|
314
|
-
email: 'john@example.com',
|
|
315
|
-
},
|
|
316
|
-
}
|
|
317
|
-
|
|
318
|
-
await callSecureApi('place-order', complexPayload)
|
|
319
|
-
|
|
320
|
-
expect(mockSecureFetchRequest).toHaveBeenCalledWith(
|
|
321
|
-
'https://api.example.com/api/proxy?target=place-order',
|
|
322
|
-
{
|
|
323
|
-
method: 'POST',
|
|
324
|
-
headers: { 'x-fingerprint-id': 'mock-fingerprint-123' },
|
|
325
|
-
body: JSON.stringify(complexPayload),
|
|
326
|
-
}
|
|
327
|
-
)
|
|
328
|
-
})
|
|
329
|
-
|
|
330
|
-
test('should handle empty payload for GET requests', async () => {
|
|
331
|
-
const mockResponse = { data: { id: 'offer-123' } }
|
|
332
|
-
mockSecureFetchRequest.mockResolvedValue({
|
|
333
|
-
json: jest.fn().mockResolvedValue(mockResponse),
|
|
334
|
-
})
|
|
335
|
-
mockBuildApiUrl.mockReturnValue(
|
|
336
|
-
'https://api.example.com/api/proxy?target=get-offer'
|
|
337
|
-
)
|
|
338
|
-
|
|
339
|
-
await callSecureApi('get-offer', {})
|
|
340
|
-
|
|
341
|
-
expect(mockSecureFetchRequest).toHaveBeenCalledWith(
|
|
342
|
-
'https://api.example.com/api/proxy?target=get-offer',
|
|
343
|
-
{
|
|
344
|
-
method: 'POST',
|
|
345
|
-
headers: { 'x-fingerprint-id': 'mock-fingerprint-123' },
|
|
346
|
-
}
|
|
347
|
-
)
|
|
348
|
-
})
|
|
349
|
-
|
|
350
|
-
test('should generate fingerprint when not provided in headers', async () => {
|
|
351
|
-
const mockResponse = { data: { success: true } }
|
|
352
|
-
mockSecureFetchRequest.mockResolvedValue({
|
|
353
|
-
json: jest.fn().mockResolvedValue(mockResponse),
|
|
354
|
-
})
|
|
355
|
-
mockBuildApiUrl.mockReturnValue(
|
|
356
|
-
'https://api.example.com/api/proxy?target=charge'
|
|
357
|
-
)
|
|
358
|
-
|
|
359
|
-
// Call without fingerprint header
|
|
360
|
-
await callSecureApi('charge', { amount: 1000 })
|
|
361
|
-
|
|
362
|
-
expect(mockSecureFetchRequest).toHaveBeenCalledWith(
|
|
363
|
-
'https://api.example.com/api/proxy?target=charge',
|
|
364
|
-
{
|
|
365
|
-
method: 'POST',
|
|
366
|
-
headers: { 'x-fingerprint-id': 'mock-fingerprint-123' },
|
|
367
|
-
body: JSON.stringify({ amount: 1000 }),
|
|
368
|
-
}
|
|
369
|
-
)
|
|
370
|
-
})
|
|
371
|
-
|
|
372
|
-
test('should preserve custom fingerprint when provided', async () => {
|
|
373
|
-
const mockResponse = { data: { success: true } }
|
|
374
|
-
mockSecureFetchRequest.mockResolvedValue({
|
|
375
|
-
json: jest.fn().mockResolvedValue(mockResponse),
|
|
376
|
-
})
|
|
377
|
-
mockBuildApiUrl.mockReturnValue(
|
|
378
|
-
'https://api.example.com/api/proxy?target=charge'
|
|
379
|
-
)
|
|
380
|
-
|
|
381
|
-
// Call with custom fingerprint header
|
|
382
|
-
const customHeaders = {
|
|
383
|
-
'x-fingerprint-id': 'custom-fingerprint-456',
|
|
384
|
-
}
|
|
385
|
-
await callSecureApi('charge', { amount: 1000 }, customHeaders)
|
|
386
|
-
|
|
387
|
-
expect(mockSecureFetchRequest).toHaveBeenCalledWith(
|
|
388
|
-
'https://api.example.com/api/proxy?target=charge',
|
|
389
|
-
{
|
|
390
|
-
method: 'POST',
|
|
391
|
-
headers: { 'x-fingerprint-id': 'custom-fingerprint-456' },
|
|
392
|
-
body: JSON.stringify({ amount: 1000 }),
|
|
393
|
-
}
|
|
394
|
-
)
|
|
395
|
-
})
|
|
396
|
-
|
|
397
|
-
test('should handle fingerprint generation failure gracefully', async () => {
|
|
398
|
-
// Mock fingerprint generation to fail
|
|
399
|
-
const mockUtils = await import('./utils.mjs')
|
|
400
|
-
jest.spyOn(mockUtils, 'getBrowserFingerprint').mockImplementation(
|
|
401
|
-
() => {
|
|
402
|
-
throw new Error('Fingerprint generation failed')
|
|
403
|
-
}
|
|
404
|
-
)
|
|
405
|
-
|
|
406
|
-
const mockResponse = { data: { success: true } }
|
|
407
|
-
mockSecureFetchRequest.mockResolvedValue({
|
|
408
|
-
json: jest.fn().mockResolvedValue(mockResponse),
|
|
409
|
-
})
|
|
410
|
-
mockBuildApiUrl.mockReturnValue(
|
|
411
|
-
'https://api.example.com/api/proxy?target=charge'
|
|
412
|
-
)
|
|
413
|
-
|
|
414
|
-
// Should still work without fingerprint
|
|
415
|
-
await callSecureApi('charge', { amount: 1000 })
|
|
416
|
-
|
|
417
|
-
expect(mockSecureFetchRequest).toHaveBeenCalledWith(
|
|
418
|
-
'https://api.example.com/api/proxy?target=charge',
|
|
419
|
-
{
|
|
420
|
-
method: 'POST',
|
|
421
|
-
headers: {},
|
|
422
|
-
body: JSON.stringify({ amount: 1000 }),
|
|
423
|
-
}
|
|
424
|
-
)
|
|
425
|
-
})
|
|
426
|
-
})
|
|
427
|
-
})
|