@apollo/gateway 2.4.5 → 2.4.6

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 (64) hide show
  1. package/dist/__generated__/graphqlTypes.d.ts +19 -1
  2. package/dist/__generated__/graphqlTypes.d.ts.map +1 -1
  3. package/dist/__generated__/graphqlTypes.js +1 -0
  4. package/dist/__generated__/graphqlTypes.js.map +1 -1
  5. package/package.json +4 -4
  6. package/src/__generated__/graphqlTypes.ts +33 -2
  7. package/src/__mocks__/tsconfig.json +0 -7
  8. package/src/__tests__/.gitkeep +0 -0
  9. package/src/__tests__/CucumberREADME.md +0 -96
  10. package/src/__tests__/build-query-plan.feature +0 -1471
  11. package/src/__tests__/buildQueryPlan.test.ts +0 -1225
  12. package/src/__tests__/executeQueryPlan.conditions.test.ts +0 -1488
  13. package/src/__tests__/executeQueryPlan.introspection.test.ts +0 -140
  14. package/src/__tests__/executeQueryPlan.test.ts +0 -6140
  15. package/src/__tests__/execution-utils.ts +0 -124
  16. package/src/__tests__/gateway/__snapshots__/opentelemetry.test.ts.snap +0 -195
  17. package/src/__tests__/gateway/buildService.test.ts +0 -249
  18. package/src/__tests__/gateway/endToEnd.test.ts +0 -486
  19. package/src/__tests__/gateway/executor.test.ts +0 -96
  20. package/src/__tests__/gateway/extensions.test.ts +0 -37
  21. package/src/__tests__/gateway/lifecycle-hooks.test.ts +0 -239
  22. package/src/__tests__/gateway/opentelemetry.test.ts +0 -123
  23. package/src/__tests__/gateway/queryPlanCache.test.ts +0 -231
  24. package/src/__tests__/gateway/queryPlannerConfig.test.ts +0 -101
  25. package/src/__tests__/gateway/reporting.test.ts +0 -616
  26. package/src/__tests__/gateway/supergraphSdl.test.ts +0 -396
  27. package/src/__tests__/gateway/testUtils.ts +0 -89
  28. package/src/__tests__/integration/abstract-types.test.ts +0 -1861
  29. package/src/__tests__/integration/aliases.test.ts +0 -180
  30. package/src/__tests__/integration/boolean.test.ts +0 -279
  31. package/src/__tests__/integration/complex-key.test.ts +0 -197
  32. package/src/__tests__/integration/configuration.test.ts +0 -404
  33. package/src/__tests__/integration/custom-directives.test.ts +0 -174
  34. package/src/__tests__/integration/execution-style.test.ts +0 -35
  35. package/src/__tests__/integration/fragments.test.ts +0 -237
  36. package/src/__tests__/integration/list-key.test.ts +0 -128
  37. package/src/__tests__/integration/logger.test.ts +0 -122
  38. package/src/__tests__/integration/managed.test.ts +0 -319
  39. package/src/__tests__/integration/merge-arrays.test.ts +0 -34
  40. package/src/__tests__/integration/multiple-key.test.ts +0 -327
  41. package/src/__tests__/integration/mutations.test.ts +0 -287
  42. package/src/__tests__/integration/networkRequests.test.ts +0 -542
  43. package/src/__tests__/integration/nockMocks.ts +0 -157
  44. package/src/__tests__/integration/provides.test.ts +0 -77
  45. package/src/__tests__/integration/requires.test.ts +0 -359
  46. package/src/__tests__/integration/scope.test.ts +0 -557
  47. package/src/__tests__/integration/single-service.test.ts +0 -119
  48. package/src/__tests__/integration/unions.test.ts +0 -79
  49. package/src/__tests__/integration/value-types.test.ts +0 -382
  50. package/src/__tests__/integration/variables.test.ts +0 -120
  51. package/src/__tests__/nockAssertions.ts +0 -20
  52. package/src/__tests__/queryPlanCucumber.test.ts +0 -55
  53. package/src/__tests__/resultShaping.test.ts +0 -605
  54. package/src/__tests__/testSetup.ts +0 -1
  55. package/src/__tests__/tsconfig.json +0 -8
  56. package/src/core/__tests__/core.test.ts +0 -412
  57. package/src/datasources/__tests__/LocalGraphQLDataSource.test.ts +0 -51
  58. package/src/datasources/__tests__/RemoteGraphQLDataSource.test.ts +0 -574
  59. package/src/schema-helper/__tests__/addExtensions.test.ts +0 -70
  60. package/src/supergraphManagers/IntrospectAndCompose/__tests__/IntrospectAndCompose.test.ts +0 -364
  61. package/src/supergraphManagers/IntrospectAndCompose/__tests__/loadServicesFromRemoteEndpoint.test.ts +0 -40
  62. package/src/supergraphManagers/UplinkSupergraphManager/__tests__/UplinkSupergraphManager.test.ts +0 -65
  63. package/src/supergraphManagers/UplinkSupergraphManager/__tests__/loadSupergraphSdlFromStorage.test.ts +0 -511
  64. package/src/utilities/__tests__/deepMerge.test.ts +0 -77
@@ -1,511 +0,0 @@
1
- import nock from 'nock';
2
- import {
3
- loadSupergraphSdlFromStorage,
4
- loadSupergraphSdlFromUplinks,
5
- UplinkFetcherError,
6
- } from '../loadSupergraphSdlFromStorage';
7
- import fetcher from 'make-fetch-happen';
8
- import {
9
- graphRef,
10
- apiKey,
11
- mockCloudConfigUrl1,
12
- mockCloudConfigUrl2,
13
- mockOutOfBandReporterUrl,
14
- mockSupergraphSdlRequest,
15
- mockOutOfBandReportRequestSuccess,
16
- mockSupergraphSdlRequestSuccess,
17
- mockSupergraphSdlRequestIfAfterUnchanged,
18
- mockSupergraphSdlRequestIfAfter,
19
- } from '../../../__tests__/integration/nockMocks';
20
- import { getTestingSupergraphSdl } from '../../../__tests__/execution-utils';
21
- import {
22
- nockAfterEach,
23
- nockBeforeEach,
24
- } from '../../../__tests__/nockAssertions';
25
- import { FetcherRequestInit } from '@apollo/utils.fetcher';
26
-
27
- const logger = {
28
- warn: jest.fn(),
29
- debug: jest.fn(),
30
- error: jest.fn(),
31
- info: jest.fn(),
32
- };
33
-
34
- const requestTimeoutMs = 100;
35
-
36
- describe('loadSupergraphSdlFromStorage', () => {
37
- beforeEach(nockBeforeEach);
38
- afterEach(nockAfterEach);
39
-
40
- it('fetches Supergraph SDL as expected', async () => {
41
- mockSupergraphSdlRequestSuccess();
42
- const result = await loadSupergraphSdlFromStorage({
43
- graphRef,
44
- apiKey,
45
- endpoint: mockCloudConfigUrl1,
46
- errorReportingEndpoint: undefined,
47
- fetcher,
48
- requestTimeoutMs,
49
- compositionId: null,
50
- logger,
51
- });
52
- expect(result).toMatchObject({
53
- id: 'originalId-1234',
54
- supergraphSdl: getTestingSupergraphSdl(),
55
- });
56
- });
57
-
58
- it('Queries alternate Uplink URL if first one fails', async () => {
59
- mockSupergraphSdlRequest('originalId-1234', mockCloudConfigUrl1).reply(500);
60
- mockSupergraphSdlRequestIfAfter(
61
- 'originalId-1234',
62
- mockCloudConfigUrl2,
63
- ).reply(
64
- 200,
65
- JSON.stringify({
66
- data: {
67
- routerConfig: {
68
- __typename: 'RouterConfigResult',
69
- id: 'originalId-1234',
70
- supergraphSdl: getTestingSupergraphSdl(),
71
- },
72
- },
73
- }),
74
- );
75
-
76
- const result = await loadSupergraphSdlFromUplinks({
77
- graphRef,
78
- apiKey,
79
- endpoints: [mockCloudConfigUrl1, mockCloudConfigUrl2],
80
- errorReportingEndpoint: undefined,
81
- fetcher,
82
- requestTimeoutMs,
83
- compositionId: 'originalId-1234',
84
- maxRetries: 1,
85
- roundRobinSeed: 0,
86
- logger,
87
- });
88
-
89
- expect(result).toMatchObject({
90
- id: 'originalId-1234',
91
- supergraphSdl: getTestingSupergraphSdl(),
92
- });
93
- });
94
-
95
- it('Queries alternate Uplink URL if first one times out', async () => {
96
- mockSupergraphSdlRequest('originalId-1234', mockCloudConfigUrl1).delay(120_000).reply(500);
97
- mockSupergraphSdlRequestIfAfter(
98
- 'originalId-1234',
99
- mockCloudConfigUrl2,
100
- ).reply(
101
- 200,
102
- JSON.stringify({
103
- data: {
104
- routerConfig: {
105
- __typename: 'RouterConfigResult',
106
- id: 'originalId-1234',
107
- supergraphSdl: getTestingSupergraphSdl(),
108
- },
109
- },
110
- }),
111
- );
112
-
113
- const result = await loadSupergraphSdlFromUplinks({
114
- graphRef,
115
- apiKey,
116
- endpoints: [mockCloudConfigUrl1, mockCloudConfigUrl2],
117
- errorReportingEndpoint: undefined,
118
- fetcher,
119
- requestTimeoutMs,
120
- compositionId: 'originalId-1234',
121
- maxRetries: 1,
122
- roundRobinSeed: 0,
123
- logger,
124
- });
125
-
126
- expect(result).toMatchObject({
127
- id: 'originalId-1234',
128
- supergraphSdl: getTestingSupergraphSdl(),
129
- });
130
-
131
- // We're intentionally delaying the response above, so we need to make sure
132
- // nock shuts down correctly, and isn't related to the underlying abort
133
- // mechanism.
134
- nock.abortPendingRequests();
135
- });
136
-
137
- it('Throws error if all Uplink URLs fail', async () => {
138
- mockSupergraphSdlRequest('originalId-1234', mockCloudConfigUrl1).reply(500);
139
- mockSupergraphSdlRequestIfAfter(
140
- 'originalId-1234',
141
- mockCloudConfigUrl2,
142
- ).reply(500);
143
-
144
- await expect(
145
- loadSupergraphSdlFromUplinks({
146
- graphRef,
147
- apiKey,
148
- endpoints: [mockCloudConfigUrl1, mockCloudConfigUrl2],
149
- errorReportingEndpoint: undefined,
150
- fetcher,
151
- requestTimeoutMs,
152
- compositionId: 'originalId-1234',
153
- maxRetries: 1,
154
- roundRobinSeed: 0,
155
- logger,
156
- }),
157
- ).rejects.toThrowError(
158
- new UplinkFetcherError(
159
- 'An error occurred while fetching your schema from Apollo: 500 Internal Server Error',
160
- ),
161
- );
162
- });
163
-
164
- describe('errors', () => {
165
- it('throws on a malformed response', async () => {
166
- mockSupergraphSdlRequest().reply(200, 'Invalid JSON');
167
-
168
- await expect(
169
- loadSupergraphSdlFromStorage({
170
- graphRef,
171
- apiKey,
172
- endpoint: mockCloudConfigUrl1,
173
- errorReportingEndpoint: mockOutOfBandReporterUrl,
174
- fetcher,
175
- requestTimeoutMs,
176
- compositionId: null,
177
- logger,
178
- }),
179
- ).rejects.toThrowError(
180
- /An error occurred while fetching your schema from Apollo: 200 invalid json response body at https:\/\/example1.cloud-config-url.com\/cloudconfig\/ reason: Unexpected token/,
181
- );
182
- });
183
-
184
- it('throws errors from JSON on 400', async () => {
185
- const message = 'Query syntax error';
186
- mockSupergraphSdlRequest().reply(
187
- 400,
188
- JSON.stringify({
189
- errors: [{ message }],
190
- }),
191
- );
192
-
193
- await expect(
194
- loadSupergraphSdlFromStorage({
195
- graphRef,
196
- apiKey,
197
- endpoint: mockCloudConfigUrl1,
198
- errorReportingEndpoint: mockOutOfBandReporterUrl,
199
- fetcher,
200
- requestTimeoutMs,
201
- compositionId: null,
202
- logger,
203
- }),
204
- ).rejects.toThrowError(
205
- new UplinkFetcherError(
206
- `An error occurred while fetching your schema from Apollo: \n${message}`,
207
- ),
208
- );
209
- });
210
-
211
- it("throws on non-OK status codes when `errors` isn't present in a JSON response", async () => {
212
- mockSupergraphSdlRequest().reply(500);
213
- mockOutOfBandReportRequestSuccess();
214
-
215
- await expect(
216
- loadSupergraphSdlFromStorage({
217
- graphRef,
218
- apiKey,
219
- endpoint: mockCloudConfigUrl1,
220
- errorReportingEndpoint: mockOutOfBandReporterUrl,
221
- fetcher,
222
- requestTimeoutMs,
223
- compositionId: null,
224
- logger,
225
- }),
226
- ).rejects.toThrowError(
227
- new UplinkFetcherError(
228
- 'An error occurred while fetching your schema from Apollo: 500 Internal Server Error',
229
- ),
230
- );
231
- });
232
-
233
- // if an additional request were made by the out of band reporter, nock would throw since it's unmocked
234
- // and this test would fail
235
- it("Out of band reporting doesn't submit reports when endpoint is not configured", async () => {
236
- mockSupergraphSdlRequest().reply(400);
237
-
238
- await expect(
239
- loadSupergraphSdlFromStorage({
240
- graphRef,
241
- apiKey,
242
- endpoint: mockCloudConfigUrl1,
243
- errorReportingEndpoint: mockOutOfBandReporterUrl,
244
- fetcher,
245
- requestTimeoutMs,
246
- compositionId: null,
247
- logger,
248
- }),
249
- ).rejects.toThrowError(
250
- new UplinkFetcherError(
251
- 'An error occurred while fetching your schema from Apollo: 400 invalid json response body at https://example1.cloud-config-url.com/cloudconfig/ reason: Unexpected end of JSON input',
252
- ),
253
- );
254
- });
255
-
256
- it('throws on 400 status response and does not submit an out of band error', async () => {
257
- mockSupergraphSdlRequest().reply(400);
258
-
259
- await expect(
260
- loadSupergraphSdlFromStorage({
261
- graphRef,
262
- apiKey,
263
- endpoint: mockCloudConfigUrl1,
264
- errorReportingEndpoint: mockOutOfBandReporterUrl,
265
- fetcher,
266
- requestTimeoutMs,
267
- compositionId: null,
268
- logger,
269
- }),
270
- ).rejects.toThrowError(
271
- new UplinkFetcherError(
272
- 'An error occurred while fetching your schema from Apollo: 400 invalid json response body at https://example1.cloud-config-url.com/cloudconfig/ reason: Unexpected end of JSON input',
273
- ),
274
- );
275
- });
276
-
277
- it('throws on 413 status response and successfully submits an out of band error', async () => {
278
- mockSupergraphSdlRequest().reply(413);
279
- mockOutOfBandReportRequestSuccess();
280
-
281
- await expect(
282
- loadSupergraphSdlFromStorage({
283
- graphRef,
284
- apiKey,
285
- endpoint: mockCloudConfigUrl1,
286
- errorReportingEndpoint: mockOutOfBandReporterUrl,
287
- fetcher,
288
- requestTimeoutMs,
289
- compositionId: null,
290
- logger,
291
- }),
292
- ).rejects.toThrowError(
293
- new UplinkFetcherError(
294
- 'An error occurred while fetching your schema from Apollo: 413 Payload Too Large',
295
- ),
296
- );
297
- });
298
-
299
- it('throws on 422 status response and successfully submits an out of band error', async () => {
300
- mockSupergraphSdlRequest().reply(422);
301
- mockOutOfBandReportRequestSuccess();
302
-
303
- await expect(
304
- loadSupergraphSdlFromStorage({
305
- graphRef,
306
- apiKey,
307
- endpoint: mockCloudConfigUrl1,
308
- errorReportingEndpoint: mockOutOfBandReporterUrl,
309
- fetcher,
310
- requestTimeoutMs,
311
- compositionId: null,
312
- logger,
313
- }),
314
- ).rejects.toThrowError(
315
- new UplinkFetcherError(
316
- 'An error occurred while fetching your schema from Apollo: 422 Unprocessable Entity',
317
- ),
318
- );
319
- });
320
-
321
- it('throws on 408 status response and successfully submits an out of band error', async () => {
322
- mockSupergraphSdlRequest().reply(408);
323
- mockOutOfBandReportRequestSuccess();
324
-
325
- await expect(
326
- loadSupergraphSdlFromStorage({
327
- graphRef,
328
- apiKey,
329
- endpoint: mockCloudConfigUrl1,
330
- errorReportingEndpoint: mockOutOfBandReporterUrl,
331
- fetcher,
332
- requestTimeoutMs,
333
- compositionId: null,
334
- logger,
335
- }),
336
- ).rejects.toThrowError(
337
- new UplinkFetcherError(
338
- 'An error occurred while fetching your schema from Apollo: 408 Request Timeout',
339
- ),
340
- );
341
- });
342
- });
343
-
344
- it('throws on 504 status response and successfully submits an out of band error', async () => {
345
- mockSupergraphSdlRequest().reply(504);
346
- mockOutOfBandReportRequestSuccess();
347
-
348
- await expect(
349
- loadSupergraphSdlFromStorage({
350
- graphRef,
351
- apiKey,
352
- endpoint: mockCloudConfigUrl1,
353
- errorReportingEndpoint: mockOutOfBandReporterUrl,
354
- fetcher,
355
- requestTimeoutMs,
356
- compositionId: null,
357
- logger,
358
- }),
359
- ).rejects.toThrowError(
360
- new UplinkFetcherError(
361
- 'An error occurred while fetching your schema from Apollo: 504 Gateway Timeout',
362
- ),
363
- );
364
- });
365
-
366
- it('throws when there is no response and successfully submits an out of band error', async () => {
367
- mockSupergraphSdlRequest().replyWithError('no response');
368
- mockOutOfBandReportRequestSuccess();
369
-
370
- await expect(
371
- loadSupergraphSdlFromStorage({
372
- graphRef,
373
- apiKey,
374
- endpoint: mockCloudConfigUrl1,
375
- errorReportingEndpoint: mockOutOfBandReporterUrl,
376
- fetcher,
377
- requestTimeoutMs,
378
- compositionId: null,
379
- logger,
380
- }),
381
- ).rejects.toThrowError(
382
- new UplinkFetcherError(
383
- 'An error occurred while fetching your schema from Apollo: request to https://example1.cloud-config-url.com/cloudconfig/ failed, reason: no response',
384
- ),
385
- );
386
- });
387
-
388
- it('throws on 502 status response and successfully submits an out of band error', async () => {
389
- mockSupergraphSdlRequest().reply(502);
390
- mockOutOfBandReportRequestSuccess();
391
-
392
- await expect(
393
- loadSupergraphSdlFromStorage({
394
- graphRef,
395
- apiKey,
396
- endpoint: mockCloudConfigUrl1,
397
- errorReportingEndpoint: mockOutOfBandReporterUrl,
398
- fetcher,
399
- requestTimeoutMs,
400
- compositionId: null,
401
- logger,
402
- }),
403
- ).rejects.toThrowError(
404
- new UplinkFetcherError(
405
- 'An error occurred while fetching your schema from Apollo: 502 Bad Gateway',
406
- ),
407
- );
408
- });
409
-
410
- it('throws on 503 status response and successfully submits an out of band error', async () => {
411
- mockSupergraphSdlRequest().reply(503);
412
- mockOutOfBandReportRequestSuccess();
413
-
414
- await expect(
415
- loadSupergraphSdlFromStorage({
416
- graphRef,
417
- apiKey,
418
- endpoint: mockCloudConfigUrl1,
419
- errorReportingEndpoint: mockOutOfBandReporterUrl,
420
- fetcher,
421
- requestTimeoutMs,
422
- compositionId: null,
423
- logger,
424
- }),
425
- ).rejects.toThrowError(
426
- new UplinkFetcherError(
427
- 'An error occurred while fetching your schema from Apollo: 503 Service Unavailable',
428
- ),
429
- );
430
- });
431
-
432
- it('successfully responds to SDL unchanged by returning null', async () => {
433
- mockSupergraphSdlRequestIfAfterUnchanged('id-1234');
434
-
435
- const result = await loadSupergraphSdlFromStorage({
436
- graphRef,
437
- apiKey,
438
- endpoint: mockCloudConfigUrl1,
439
- errorReportingEndpoint: mockOutOfBandReporterUrl,
440
- fetcher,
441
- requestTimeoutMs,
442
- compositionId: 'id-1234',
443
- logger,
444
- });
445
- expect(result).toBeNull();
446
- });
447
- });
448
-
449
- describe('loadSupergraphSdlFromUplinks', () => {
450
- beforeEach(nockBeforeEach);
451
- afterEach(nockAfterEach);
452
-
453
- it("doesn't retry in the unchanged / null case", async () => {
454
- mockSupergraphSdlRequestIfAfterUnchanged('id-1234', mockCloudConfigUrl1);
455
-
456
- let calls = 0;
457
- const result = await loadSupergraphSdlFromUplinks({
458
- graphRef,
459
- apiKey,
460
- endpoints: [mockCloudConfigUrl1, mockCloudConfigUrl2],
461
- errorReportingEndpoint: mockOutOfBandReporterUrl,
462
- fetcher: (url: string, init?: FetcherRequestInit) => {
463
- calls++;
464
- return fetcher(url, init);
465
- },
466
- requestTimeoutMs,
467
- compositionId: 'id-1234',
468
- maxRetries: 5,
469
- roundRobinSeed: 0,
470
- logger,
471
- });
472
-
473
- expect(result).toBeNull();
474
- expect(calls).toBe(1);
475
- });
476
-
477
- it('Retries on error', async () => {
478
- mockSupergraphSdlRequest('originalId-1234', mockCloudConfigUrl1).reply(500);
479
- const supergraphSdl = getTestingSupergraphSdl();
480
- mockSupergraphSdlRequestIfAfter(
481
- 'originalId-1234',
482
- mockCloudConfigUrl2,
483
- ).reply(
484
- 200,
485
- JSON.stringify({
486
- data: {
487
- routerConfig: {
488
- __typename: 'RouterConfigResult',
489
- id: 'originalId-1234',
490
- supergraphSdl,
491
- },
492
- },
493
- }),
494
- );
495
-
496
- const result = await loadSupergraphSdlFromUplinks({
497
- graphRef,
498
- apiKey,
499
- endpoints: [mockCloudConfigUrl1, mockCloudConfigUrl2],
500
- errorReportingEndpoint: undefined,
501
- fetcher,
502
- requestTimeoutMs,
503
- compositionId: 'originalId-1234',
504
- maxRetries: 1,
505
- roundRobinSeed: 0,
506
- logger,
507
- });
508
-
509
- expect(result?.supergraphSdl).toEqual(supergraphSdl);
510
- });
511
- });
@@ -1,77 +0,0 @@
1
- import { deepMerge } from '../deepMerge';
2
-
3
- describe('deepMerge', () => {
4
- it('merges basic', () => {
5
- const target = {
6
- a: 1,
7
- b: 2,
8
- };
9
-
10
- const source = {
11
- b: 3,
12
- c: 4,
13
- };
14
-
15
- expect(deepMerge(target, source)).toEqual({
16
- a: 1,
17
- b: 3,
18
- c: 4,
19
- });
20
- });
21
-
22
- it('merges nested objects', () => {
23
- const target = {
24
- a: 1,
25
- b: {
26
- someProperty: 1,
27
- overwrittenProperty: 'clean',
28
- },
29
- };
30
-
31
- const source = {
32
- b: {
33
- overwrittenProperty: 'dirty',
34
- newProperty: 'new',
35
- },
36
- c: 4,
37
- };
38
-
39
- expect(deepMerge(target, source)).toEqual({
40
- a: 1,
41
- b: {
42
- newProperty: 'new',
43
- overwrittenProperty: 'dirty',
44
- someProperty: 1,
45
- },
46
- c: 4,
47
- });
48
- });
49
-
50
- it('ignores merging __proto__ fields', () => {
51
- const target = {};
52
-
53
- // Bypass setters on __proto__
54
- const source = JSON.parse('{"__proto__": {"pollution": true}}');
55
- deepMerge(target, source);
56
-
57
- expect(Object.prototype.hasOwnProperty('pollution')).toBe(false);
58
- });
59
-
60
- it('merges arrays', () => {
61
- const target = {
62
- a: 1,
63
- b: [{ c: 1, d: 2 }],
64
- };
65
-
66
- const source = {
67
- e: 2,
68
- b: [{ f: 3 }],
69
- };
70
-
71
- expect(deepMerge(target, source)).toEqual({
72
- a: 1,
73
- e: 2,
74
- b: [{ c: 1, d: 2, f: 3 }],
75
- });
76
- });
77
- });