@adobe/aio-cli-plugin-api-mesh 2.0.0 → 2.2.0-beta.1

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 (32) hide show
  1. package/oclif.manifest.json +1 -1
  2. package/package.json +5 -3
  3. package/src/commands/__fixtures__/env_invalid +8 -0
  4. package/src/commands/__fixtures__/env_valid +3 -0
  5. package/src/commands/__fixtures__/files/requestParams.json +3 -0
  6. package/src/commands/__fixtures__/openapi-schema.json +4 -0
  7. package/src/commands/__fixtures__/requestParams.json +3 -0
  8. package/src/commands/__fixtures__/sample_fully_qualified_mesh.json +29 -0
  9. package/src/commands/__fixtures__/sample_invalid_mesh.txt +17 -0
  10. package/src/commands/__fixtures__/sample_mesh_files.json +23 -0
  11. package/src/commands/__fixtures__/sample_mesh_invalid_file_content.json +14 -0
  12. package/src/commands/__fixtures__/sample_mesh_invalid_file_name.json +27 -0
  13. package/src/commands/__fixtures__/sample_mesh_invalid_paths.json +23 -0
  14. package/src/commands/__fixtures__/sample_mesh_invalid_type.json +27 -0
  15. package/src/commands/__fixtures__/sample_mesh_mismatching_path.json +29 -0
  16. package/src/commands/__fixtures__/sample_mesh_outside_workspace_dir.json +23 -0
  17. package/src/commands/__fixtures__/sample_mesh_path_from_home.json +14 -0
  18. package/src/commands/__fixtures__/sample_mesh_subdirectory.json +23 -0
  19. package/src/commands/__fixtures__/sample_mesh_with_files_array.json +29 -0
  20. package/src/commands/__fixtures__/sample_mesh_with_placeholder +17 -0
  21. package/src/commands/api-mesh/__tests__/create.test.js +1334 -140
  22. package/src/commands/api-mesh/__tests__/delete.test.js +3 -3
  23. package/src/commands/api-mesh/__tests__/init.test.js +390 -0
  24. package/src/commands/api-mesh/__tests__/update.test.js +524 -109
  25. package/src/commands/api-mesh/create.js +47 -14
  26. package/src/commands/api-mesh/init.js +168 -0
  27. package/src/commands/api-mesh/update.js +49 -17
  28. package/src/helpers.js +254 -3
  29. package/src/lib/devConsole.js +1 -2
  30. package/src/templates/gitignore +1 -0
  31. package/src/templates/package.json +38 -0
  32. package/src/utils.js +337 -33
@@ -14,7 +14,13 @@ const mockConsoleCLIInstance = {};
14
14
 
15
15
  const CreateCommand = require('../create');
16
16
  const sampleCreateMeshConfig = require('../../__fixtures__/sample_mesh.json');
17
- const { initSdk, initRequestId, promptConfirm } = require('../../../helpers');
17
+ const {
18
+ initSdk,
19
+ initRequestId,
20
+ promptConfirm,
21
+ interpolateMesh,
22
+ importFiles,
23
+ } = require('../../../helpers');
18
24
  const {
19
25
  createMesh,
20
26
  createAPIMeshCredentials,
@@ -40,6 +46,8 @@ jest.mock('../../../helpers', () => ({
40
46
  initSdk: jest.fn().mockResolvedValue({}),
41
47
  initRequestId: jest.fn().mockResolvedValue({}),
42
48
  promptConfirm: jest.fn().mockResolvedValue(true),
49
+ interpolateMesh: jest.fn().mockResolvedValue({}),
50
+ importFiles: jest.fn().mockResolvedValue(),
43
51
  }));
44
52
  jest.mock('../../../lib/devConsole');
45
53
 
@@ -84,8 +92,20 @@ describe('create command tests', () => {
84
92
  });
85
93
  });
86
94
 
87
- afterEach(() => {
88
- jest.restoreAllMocks();
95
+ test('must return proper object structure used by adobe/generator-app-api-mesh', async () => {
96
+ parseSpy.mockResolvedValueOnce({
97
+ args: { file: 'src/commands/__fixtures__/sample_mesh.json' },
98
+ flags: {
99
+ json: Promise.resolve(true),
100
+ },
101
+ });
102
+ const output = await CreateCommand.run();
103
+ expect(output).toHaveProperty('mesh');
104
+ expect(output).toHaveProperty('adobeIdIntegrationsForWorkspace');
105
+ expect(output.mesh).toEqual(expect.objectContaining({ meshId: 'dummy_mesh_id' }));
106
+ expect(output.adobeIdIntegrationsForWorkspace).toEqual(
107
+ expect.objectContaining({ apiKey: 'dummy_api_key' }),
108
+ );
89
109
  });
90
110
 
91
111
  test('snapshot create command description', () => {
@@ -99,6 +119,7 @@ describe('create command tests', () => {
99
119
  },
100
120
  ]
101
121
  `);
122
+
102
123
  expect(CreateCommand.flags).toMatchInlineSnapshot(`
103
124
  {
104
125
  "autoConfirmAction": {
@@ -109,6 +130,15 @@ describe('create command tests', () => {
109
130
  "parse": [Function],
110
131
  "type": "boolean",
111
132
  },
133
+ "env": {
134
+ "char": "e",
135
+ "default": ".env",
136
+ "description": "Path to env file",
137
+ "input": [],
138
+ "multiple": false,
139
+ "parse": [Function],
140
+ "type": "option",
141
+ },
112
142
  "ignoreCache": {
113
143
  "allowNo": false,
114
144
  "char": "i",
@@ -128,6 +158,131 @@ describe('create command tests', () => {
128
158
  `);
129
159
  expect(CreateCommand.aliases).toMatchInlineSnapshot(`[]`);
130
160
  });
161
+ test('should fail if create mesh api has failed', async () => {
162
+ createMesh.mockRejectedValueOnce(new Error('create mesh api failed'));
163
+
164
+ const runResult = CreateCommand.run();
165
+ await expect(runResult).rejects.toEqual(
166
+ new Error(
167
+ 'Unable to create a mesh. Please check the mesh configuration file and try again. If the error persists please contact support. RequestId: dummy_request_id',
168
+ ),
169
+ );
170
+ expect(logSpy.mock.calls).toMatchInlineSnapshot(`
171
+ [
172
+ [
173
+ "create mesh api failed",
174
+ ],
175
+ ]
176
+ `);
177
+ expect(errorLogSpy.mock.calls).toMatchInlineSnapshot(`
178
+ [
179
+ [
180
+ "Unable to create a mesh. Please check the mesh configuration file and try again. If the error persists please contact support. RequestId: dummy_request_id",
181
+ ],
182
+ ]
183
+ `);
184
+ });
185
+ test('should create if a valid mesh config file is provided', async () => {
186
+ const runResult = await CreateCommand.run();
187
+
188
+ expect(initRequestId).toHaveBeenCalled();
189
+ expect(createMesh.mock.calls[0]).toMatchInlineSnapshot(`
190
+ [
191
+ "1234",
192
+ "5678",
193
+ "123456789",
194
+ {
195
+ "meshConfig": {
196
+ "sources": [
197
+ {
198
+ "handler": {
199
+ "graphql": {
200
+ "endpoint": "<gql_endpoint>",
201
+ },
202
+ },
203
+ "name": "<api_name>",
204
+ },
205
+ ],
206
+ },
207
+ },
208
+ ]
209
+ `);
210
+ expect(createAPIMeshCredentials.mock.calls[0]).toMatchInlineSnapshot(`
211
+ [
212
+ "1234",
213
+ "5678",
214
+ "123456789",
215
+ ]
216
+ `);
217
+ expect(subscribeCredentialToMeshService.mock.calls[0]).toMatchInlineSnapshot(`
218
+ [
219
+ "1234",
220
+ "5678",
221
+ "123456789",
222
+ "dummy_id",
223
+ ]
224
+ `);
225
+ expect(runResult).toMatchInlineSnapshot(`
226
+ {
227
+ "adobeIdIntegrationsForWorkspace": {
228
+ "apiKey": "dummy_api_key",
229
+ "id": "dummy_id",
230
+ },
231
+ "mesh": {
232
+ "meshConfig": {
233
+ "sources": [
234
+ {
235
+ "handler": {
236
+ "graphql": {
237
+ "endpoint": "<gql_endpoint>",
238
+ },
239
+ },
240
+ "name": "<api_name>",
241
+ },
242
+ ],
243
+ },
244
+ "meshId": "dummy_mesh_id",
245
+ },
246
+ "sdkList": [
247
+ "dummy_service",
248
+ ],
249
+ }
250
+ `);
251
+ expect(logSpy.mock.calls).toMatchInlineSnapshot(`
252
+ [
253
+ [
254
+ "******************************************************************************************************",
255
+ ],
256
+ [
257
+ "Your mesh is being provisioned. Wait a few minutes before checking the status of your mesh %s",
258
+ "dummy_mesh_id",
259
+ ],
260
+ [
261
+ "To check the status of your mesh, run:",
262
+ ],
263
+ [
264
+ "aio api-mesh:status",
265
+ ],
266
+ [
267
+ "******************************************************************************************************",
268
+ ],
269
+ [
270
+ "Successfully created API Key %s",
271
+ "dummy_api_key",
272
+ ],
273
+ [
274
+ "Successfully subscribed API Key %s to API Mesh service",
275
+ "dummy_api_key",
276
+ ],
277
+ [
278
+ "Mesh Endpoint: %s
279
+ ",
280
+ "https://graph.adobe.io/api/dummy_mesh_id/graphql?api_key=dummy_api_key",
281
+ ],
282
+ ]
283
+ `);
284
+ expect(errorLogSpy.mock.calls).toMatchInlineSnapshot(`[]`);
285
+ });
131
286
 
132
287
  test('should fail if mesh config file arg is missing', async () => {
133
288
  parseSpy.mockResolvedValueOnce({
@@ -183,34 +338,8 @@ describe('create command tests', () => {
183
338
  `);
184
339
  });
185
340
 
186
- test('should fail if create mesh api has failed', async () => {
187
- createMesh.mockRejectedValueOnce(new Error('create mesh api failed'));
188
-
189
- const runResult = CreateCommand.run();
190
-
191
- await expect(runResult).rejects.toEqual(
192
- new Error(
193
- 'Unable to create a mesh. Please check the mesh configuration file and try again. If the error persists please contact support. RequestId: dummy_request_id',
194
- ),
195
- );
196
- expect(logSpy.mock.calls).toMatchInlineSnapshot(`
197
- [
198
- [
199
- "create mesh api failed",
200
- ],
201
- ]
202
- `);
203
- expect(errorLogSpy.mock.calls).toMatchInlineSnapshot(`
204
- [
205
- [
206
- "Unable to create a mesh. Please check the mesh configuration file and try again. If the error persists please contact support. RequestId: dummy_request_id",
207
- ],
208
- ]
209
- `);
210
- });
211
-
212
341
  test('should fail if create api credential api has failed', async () => {
213
- createAPIMeshCredentials.mockRejectedValueOnce(new Error('create api credential api failed'));
342
+ createAPIMeshCredentials.mockRejectedValue(new Error('create api credential api failed'));
214
343
 
215
344
  const runResult = CreateCommand.run();
216
345
 
@@ -299,72 +428,22 @@ describe('create command tests', () => {
299
428
  `);
300
429
  });
301
430
 
302
- test('should create if a valid mesh config file is provided', async () => {
303
- const runResult = await CreateCommand.run();
431
+ test('should not ask for confirmation if autoConfirmAction is provided', async () => {
432
+ parseSpy.mockResolvedValueOnce({
433
+ args: { file: 'src/commands/__fixtures__/sample_mesh.json' },
434
+ flags: {
435
+ ignoreCache: mockIgnoreCacheFlag,
436
+ autoConfirmAction: Promise.resolve(true),
437
+ },
438
+ });
439
+
440
+ await CreateCommand.run();
304
441
 
305
442
  expect(initRequestId).toHaveBeenCalled();
306
- expect(createMesh.mock.calls[0]).toMatchInlineSnapshot(`
307
- [
308
- "1234",
309
- "5678",
310
- "123456789",
311
- {
312
- "meshConfig": {
313
- "sources": [
314
- {
315
- "handler": {
316
- "graphql": {
317
- "endpoint": "<gql_endpoint>",
318
- },
319
- },
320
- "name": "<api_name>",
321
- },
322
- ],
323
- },
324
- },
325
- ]
326
- `);
327
- expect(createAPIMeshCredentials.mock.calls[0]).toMatchInlineSnapshot(`
328
- [
329
- "1234",
330
- "5678",
331
- "123456789",
332
- ]
333
- `);
334
- expect(subscribeCredentialToMeshService.mock.calls[0]).toMatchInlineSnapshot(`
335
- [
336
- "1234",
337
- "5678",
338
- "123456789",
339
- "dummy_id",
340
- ]
341
- `);
342
- expect(runResult).toMatchInlineSnapshot(`
343
- {
344
- "adobeIdIntegrationsForWorkspace": {
345
- "apiKey": "dummy_api_key",
346
- "id": "dummy_id",
347
- },
348
- "mesh": {
349
- "meshConfig": {
350
- "sources": [
351
- {
352
- "handler": {
353
- "graphql": {
354
- "endpoint": "<gql_endpoint>",
355
- },
356
- },
357
- "name": "<api_name>",
358
- },
359
- ],
360
- },
361
- "meshId": "dummy_mesh_id",
362
- },
363
- "sdkList": [
364
- "dummy_service",
365
- ],
366
- }
367
- `);
443
+ expect(promptConfirm).not.toHaveBeenCalled();
444
+ expect(initSdk).toHaveBeenCalledWith({
445
+ ignoreCache: true,
446
+ });
368
447
  expect(logSpy.mock.calls).toMatchInlineSnapshot(`
369
448
  [
370
449
  [
@@ -401,91 +480,1206 @@ describe('create command tests', () => {
401
480
  expect(errorLogSpy.mock.calls).toMatchInlineSnapshot(`[]`);
402
481
  });
403
482
 
404
- test('should not ask for confirmation if autoConfirmAction is provided', async () => {
405
- parseSpy.mockResolvedValueOnce({
406
- args: { file: 'src/commands/__fixtures__/sample_mesh.json' },
407
- flags: {
408
- ignoreCache: mockIgnoreCacheFlag,
409
- autoConfirmAction: Promise.resolve(true),
410
- },
411
- });
412
-
483
+ test('should stop creation if user declines confirmation', async () => {
484
+ promptConfirm.mockResolvedValueOnce(false);
485
+
413
486
  await CreateCommand.run();
414
487
 
415
488
  expect(initRequestId).toHaveBeenCalled();
416
- expect(promptConfirm).not.toHaveBeenCalled();
489
+ expect(promptConfirm).toHaveBeenCalled();
417
490
  expect(initSdk).toHaveBeenCalledWith({
418
491
  ignoreCache: true,
419
492
  });
420
493
  expect(logSpy.mock.calls).toMatchInlineSnapshot(`
421
494
  [
422
495
  [
423
- "******************************************************************************************************",
424
- ],
425
- [
426
- "Your mesh is being provisioned. Wait a few minutes before checking the status of your mesh %s",
427
- "dummy_mesh_id",
496
+ "Create cancelled",
428
497
  ],
498
+ ]
499
+ `);
500
+ expect(errorLogSpy.mock.calls).toMatchInlineSnapshot(`[]`);
501
+ });
502
+
503
+ test('must return proper object structure used by adobe/generator-app-api-mesh', async () => {
504
+ parseSpy.mockResolvedValueOnce({
505
+ args: { file: 'src/commands/__fixtures__/sample_mesh.json' },
506
+ flags: {
507
+ json: Promise.resolve(true),
508
+ },
509
+ });
510
+ const output = await CreateCommand.run();
511
+ expect(output).toHaveProperty('mesh');
512
+ expect(output).toHaveProperty('adobeIdIntegrationsForWorkspace');
513
+ expect(output.mesh).toEqual(expect.objectContaining({ meshId: 'dummy_mesh_id' }));
514
+ expect(output.adobeIdIntegrationsForWorkspace).toEqual(
515
+ expect.objectContaining({ apiKey: 'dummy_api_key' }),
516
+ );
517
+ });
518
+
519
+ test('should return error if the mesh has placeholders and env file provided using --env flag is not found', async () => {
520
+ parseSpy.mockResolvedValueOnce({
521
+ args: { file: 'src/commands/__fixtures__/sample_mesh_with_placeholder' },
522
+ flags: {
523
+ ignoreCache: mockIgnoreCacheFlag,
524
+ autoConfirmAction: Promise.resolve(true),
525
+ env: 'src/commands/__fixtures__/.env_nonExisting',
526
+ },
527
+ });
528
+ const runResult = CreateCommand.run();
529
+
530
+ await expect(runResult).rejects.toEqual(
531
+ new Error(
532
+ 'Unable to read the file src/commands/__fixtures__/.env_nonExisting. Please check the file and try again.',
533
+ ),
534
+ );
535
+
536
+ expect(logSpy.mock.calls).toMatchInlineSnapshot(`
537
+ [
429
538
  [
430
- "To check the status of your mesh, run:",
539
+ "The provided mesh contains placeholders. Starting mesh interpolation process.",
431
540
  ],
432
541
  [
433
- "aio api-mesh:status",
542
+ "ENOENT: no such file or directory, open 'src/commands/__fixtures__/.env_nonExisting'",
434
543
  ],
544
+ ]
545
+ `);
546
+ expect(errorLogSpy.mock.calls).toMatchInlineSnapshot(`
547
+ [
435
548
  [
436
- "******************************************************************************************************",
549
+ "Unable to read the file src/commands/__fixtures__/.env_nonExisting. Please check the file and try again.",
437
550
  ],
551
+ ]
552
+ `);
553
+ });
554
+
555
+ test('should return error if mesh has placeholders and the provided env file is invalid', async () => {
556
+ parseSpy.mockResolvedValueOnce({
557
+ args: { file: 'src/commands/__fixtures__/sample_mesh_with_placeholder' },
558
+ flags: {
559
+ ignoreCache: mockIgnoreCacheFlag,
560
+ autoConfirmAction: Promise.resolve(true),
561
+ env: 'src/commands/__fixtures__/env_invalid',
562
+ },
563
+ });
564
+
565
+ const runResult = CreateCommand.run();
566
+
567
+ await expect(runResult).rejects.toEqual(
568
+ new Error(
569
+ "Issue in src/commands/__fixtures__/env_invalid file - Duplicate key << key1 >> on line 3,Invalid format for key/value << key2=='value3' >> on line 5,Invalid format << key3 >> on line 6,Invalid format for key/value << key4='value4 >> on line 7",
570
+ ),
571
+ );
572
+
573
+ expect(errorLogSpy.mock.calls).toMatchInlineSnapshot(`
574
+ [
438
575
  [
439
- "Successfully created API Key %s",
440
- "dummy_api_key",
576
+ "Issue in src/commands/__fixtures__/env_invalid file - Duplicate key << key1 >> on line 3,Invalid format for key/value << key2=='value3' >> on line 5,Invalid format << key3 >> on line 6,Invalid format for key/value << key4='value4 >> on line 7",
441
577
  ],
578
+ ]
579
+ `);
580
+ });
581
+
582
+ test('should return error if the mesh has placeholders and the provided env file is valid but there are missing keys found in mesh interpolation', async () => {
583
+ parseSpy.mockResolvedValueOnce({
584
+ args: { file: 'src/commands/__fixtures__/sample_mesh_with_placeholder' },
585
+ flags: {
586
+ ignoreCache: mockIgnoreCacheFlag,
587
+ autoConfirmAction: Promise.resolve(true),
588
+ env: 'src/commands/__fixtures__/env_valid',
589
+ },
590
+ });
591
+
592
+ interpolateMesh.mockResolvedValueOnce({
593
+ interpolationStatus: 'failed',
594
+ missingKeys: ['newKey1', 'newKey2'],
595
+ interpolatedMesh: '',
596
+ });
597
+
598
+ const runResult = CreateCommand.run();
599
+ await expect(runResult).rejects.toEqual(
600
+ new Error('The mesh file cannot be interpolated due to missing keys : newKey1 , newKey2'),
601
+ );
602
+
603
+ await expect(errorLogSpy.mock.calls).toMatchInlineSnapshot(`
604
+ [
442
605
  [
443
- "Successfully subscribed API Key %s to API Mesh service",
444
- "dummy_api_key",
606
+ "The mesh file cannot be interpolated due to missing keys : newKey1 , newKey2",
445
607
  ],
608
+ ]
609
+ `);
610
+ });
611
+
612
+ test('should return error if the provided env file is valid and mesh interpolation is successful but interpolated mesh is not a valid JSON', async () => {
613
+ parseSpy.mockResolvedValueOnce({
614
+ args: { file: 'src/commands/__fixtures__/sample_mesh_with_placeholder' },
615
+ flags: {
616
+ ignoreCache: mockIgnoreCacheFlag,
617
+ autoConfirmAction: Promise.resolve(true),
618
+ env: 'src/commands/__fixtures__/env_valid',
619
+ },
620
+ });
621
+
622
+ //sampleInterpolated mesh where value of responseConfig.includeHTTPDetails is invalid i.e. non-boolean
623
+ const sampleInterpolatedMesh =
624
+ '{"meshConfig":{"sources":[{"name":"<api-name>","handler":{"graphql":{"endpoint":"<api-url>"}}}],"responseConfig":{"includeHTTPDetails":sample}}}';
625
+
626
+ interpolateMesh.mockResolvedValueOnce({
627
+ interpolationStatus: 'success',
628
+ missingKeys: [],
629
+ interpolatedMeshData: sampleInterpolatedMesh,
630
+ });
631
+
632
+ const runResult = CreateCommand.run();
633
+ await expect(runResult).rejects.toEqual(
634
+ new Error('Interpolated mesh is not a valid JSON. Please check the generated json file.'),
635
+ );
636
+
637
+ await expect(errorLogSpy.mock.calls).toMatchInlineSnapshot(`
638
+ [
446
639
  [
447
- "Mesh Endpoint: %s
448
- ",
449
- "https://graph.adobe.io/api/dummy_mesh_id/graphql?api_key=dummy_api_key",
640
+ "Interpolated mesh is not a valid JSON. Please check the generated json file.",
450
641
  ],
451
642
  ]
452
643
  `);
453
- expect(errorLogSpy.mock.calls).toMatchInlineSnapshot(`[]`);
454
644
  });
455
645
 
456
- test('should stop creation if user declines confirmation', async () => {
457
- promptConfirm.mockResolvedValueOnce(false);
646
+ test('should successfully create a mesh if provided env file is valid, mesh interpolation is successful and interpolated mesh is a valid JSON', async () => {
647
+ parseSpy.mockResolvedValue({
648
+ args: { file: 'src/commands/__fixtures__/sample_mesh_with_placeholder' },
649
+ flags: {
650
+ ignoreCache: mockIgnoreCacheFlag,
651
+ autoConfirmAction: mockAutoApproveAction,
652
+ env: 'src/commands/__fixtures__/env_valid',
653
+ },
654
+ });
458
655
 
459
- await CreateCommand.run();
656
+ //sampleInterpolated mesh where the mesh string is a valid JSON
657
+ const sampleInterpolatedMesh =
658
+ '{"meshConfig":{"sources":[{"name":"<api-name>","handler":{"graphql":{"endpoint":"<api-url>"}}}],"responseConfig":{"includeHTTPDetails":true}}}';
460
659
 
461
- expect(initRequestId).toHaveBeenCalled();
462
- expect(promptConfirm).toHaveBeenCalled();
463
- expect(initSdk).toHaveBeenCalledWith({
464
- ignoreCache: true,
660
+ interpolateMesh.mockResolvedValueOnce({
661
+ interpolationStatus: 'success',
662
+ missingKeys: [],
663
+ interpolatedMeshData: sampleInterpolatedMesh,
465
664
  });
466
- expect(logSpy.mock.calls).toMatchInlineSnapshot(`
665
+
666
+ const runResult = await CreateCommand.run();
667
+
668
+ expect(promptConfirm).toHaveBeenCalledWith('Are you sure you want to create a mesh?');
669
+ expect(runResult).toMatchInlineSnapshot(`
670
+ {
671
+ "adobeIdIntegrationsForWorkspace": {
672
+ "apiKey": "dummy_api_key",
673
+ "id": "dummy_id",
674
+ },
675
+ "mesh": {
676
+ "meshConfig": {
677
+ "sources": [
678
+ {
679
+ "handler": {
680
+ "graphql": {
681
+ "endpoint": "<gql_endpoint>",
682
+ },
683
+ },
684
+ "name": "<api_name>",
685
+ },
686
+ ],
687
+ },
688
+ "meshId": "dummy_mesh_id",
689
+ },
690
+ "sdkList": [
691
+ "dummy_service",
692
+ ],
693
+ }
694
+ `);
695
+ });
696
+
697
+ test('should return error if inputMesh is not a valid JSON', async () => {
698
+ parseSpy.mockResolvedValue({
699
+ args: { file: 'src/commands/__fixtures__/sample_invalid_mesh.txt' },
700
+ flags: {
701
+ ignoreCache: mockIgnoreCacheFlag,
702
+ autoConfirmAction: mockAutoApproveAction,
703
+ },
704
+ });
705
+
706
+ const runResult = CreateCommand.run();
707
+ await expect(runResult).rejects.toEqual(
708
+ new Error('Input mesh file is not a valid JSON. Please check the file provided.'),
709
+ );
710
+
711
+ await expect(errorLogSpy.mock.calls).toMatchInlineSnapshot(`
467
712
  [
468
713
  [
469
- "Create cancelled",
714
+ "Input mesh file is not a valid JSON. Please check the file provided.",
470
715
  ],
471
716
  ]
472
717
  `);
473
- expect(errorLogSpy.mock.calls).toMatchInlineSnapshot(`[]`);
474
718
  });
475
719
 
476
- test('must return proper object structure used by adobe/generator-app-api-mesh', async () => {
477
- parseSpy.mockResolvedValueOnce({
478
- args: { file: 'src/commands/__fixtures__/sample_mesh.json' },
720
+ test('should pass if there are local files in meshConfig i.e., the file is appended in files array', async () => {
721
+ let meshConfig = {
722
+ sources: [
723
+ {
724
+ name: '<json_source_name>',
725
+ handler: {
726
+ JsonSchema: {
727
+ baseUrl: '<json_source__baseurl>',
728
+ operations: [
729
+ {
730
+ type: 'Query',
731
+ field: '<query>',
732
+ path: '<query_path>',
733
+ method: 'POST',
734
+ requestSchema: './requestParams.json',
735
+ },
736
+ ],
737
+ },
738
+ },
739
+ },
740
+ ],
741
+ files: [
742
+ {
743
+ path: './requestParams.json',
744
+ content: '{"type":"updatedContent"}',
745
+ },
746
+ ],
747
+ };
748
+
749
+ createMesh.mockResolvedValue({
750
+ meshId: 'dummy_mesh_id',
751
+ meshConfig: meshConfig,
752
+ });
753
+
754
+ parseSpy.mockResolvedValue({
755
+ args: { file: 'src/commands/__fixtures__/sample_mesh_files.json' },
479
756
  flags: {
480
- json: Promise.resolve(true),
757
+ autoConfirmAction: Promise.resolve(false),
481
758
  },
482
759
  });
760
+
761
+ importFiles.mockResolvedValueOnce({
762
+ meshConfig,
763
+ });
764
+
483
765
  const output = await CreateCommand.run();
484
- expect(output).toHaveProperty('mesh');
485
- expect(output).toHaveProperty('adobeIdIntegrationsForWorkspace');
486
- expect(output.mesh).toEqual(expect.objectContaining({ meshId: 'dummy_mesh_id' }));
487
- expect(output.adobeIdIntegrationsForWorkspace).toEqual(
488
- expect.objectContaining({ apiKey: 'dummy_api_key' }),
489
- );
766
+
767
+ expect(initRequestId).toHaveBeenCalled();
768
+ expect(createMesh.mock.calls[0]).toMatchInlineSnapshot(`
769
+ [
770
+ "1234",
771
+ "5678",
772
+ "123456789",
773
+ {
774
+ "meshConfig": {
775
+ "files": [
776
+ {
777
+ "content": "{"type":"updatedContent"}",
778
+ "path": "./requestParams.json",
779
+ },
780
+ ],
781
+ "sources": [
782
+ {
783
+ "handler": {
784
+ "JsonSchema": {
785
+ "baseUrl": "<json_source__baseurl>",
786
+ "operations": [
787
+ {
788
+ "field": "<query>",
789
+ "method": "POST",
790
+ "path": "<query_path>",
791
+ "requestSchema": "./requestParams.json",
792
+ "type": "Query",
793
+ },
794
+ ],
795
+ },
796
+ },
797
+ "name": "<json_source_name>",
798
+ },
799
+ ],
800
+ },
801
+ },
802
+ ]
803
+ `);
804
+ expect(createAPIMeshCredentials.mock.calls[0]).toMatchInlineSnapshot(`
805
+ [
806
+ "1234",
807
+ "5678",
808
+ "123456789",
809
+ ]
810
+ `);
811
+
812
+ expect(subscribeCredentialToMeshService.mock.calls[0]).toMatchInlineSnapshot(`
813
+ [
814
+ "1234",
815
+ "5678",
816
+ "123456789",
817
+ "dummy_id",
818
+ ]
819
+ `);
820
+ expect(output).toMatchInlineSnapshot(`
821
+ {
822
+ "adobeIdIntegrationsForWorkspace": {
823
+ "apiKey": "dummy_api_key",
824
+ "id": "dummy_id",
825
+ },
826
+ "mesh": {
827
+ "meshConfig": {
828
+ "files": [
829
+ {
830
+ "content": "{"type":"updatedContent"}",
831
+ "path": "./requestParams.json",
832
+ },
833
+ ],
834
+ "sources": [
835
+ {
836
+ "handler": {
837
+ "JsonSchema": {
838
+ "baseUrl": "<json_source__baseurl>",
839
+ "operations": [
840
+ {
841
+ "field": "<query>",
842
+ "method": "POST",
843
+ "path": "<query_path>",
844
+ "requestSchema": "./requestParams.json",
845
+ "type": "Query",
846
+ },
847
+ ],
848
+ },
849
+ },
850
+ "name": "<json_source_name>",
851
+ },
852
+ ],
853
+ },
854
+ "meshId": "dummy_mesh_id",
855
+ },
856
+ "sdkList": [
857
+ "dummy_service",
858
+ ],
859
+ }
860
+ `);
861
+ });
862
+
863
+ test('should fail if the file name is more than 25 characters', async () => {
864
+ parseSpy.mockResolvedValue({
865
+ args: { file: 'src/commands/__fixtures__/sample_mesh_invalid_file_name.json' },
866
+ flags: {
867
+ autoConfirmAction: Promise.resolve(false),
868
+ },
869
+ });
870
+
871
+ const output = CreateCommand.run();
872
+
873
+ await expect(output).rejects.toEqual(new Error('Input mesh config is not valid.'));
874
+
875
+ expect(logSpy.mock.calls).toMatchInlineSnapshot(`
876
+ [
877
+ [
878
+ "Mesh file names must be less than 25 characters. The following file(s) are invalid: requestJSONParameters.json.",
879
+ ],
880
+ ]
881
+ `);
882
+
883
+ expect(errorLogSpy.mock.calls).toMatchInlineSnapshot(`
884
+ [
885
+ [
886
+ "Input mesh config is not valid.",
887
+ ],
888
+ ]
889
+ `);
890
+ });
891
+
892
+ test('should fail if the file paths in files array and filenames in sources, transforms, additionalResolvers do not match in mesh config', async () => {
893
+ parseSpy.mockResolvedValue({
894
+ args: { file: 'src/commands/__fixtures__/sample_mesh_mismatching_path.json' },
895
+ flags: {
896
+ autoConfirmAction: Promise.resolve(false),
897
+ },
898
+ });
899
+
900
+ const output = CreateCommand.run();
901
+
902
+ await expect(output).rejects.toEqual(new Error('Input mesh config is not valid.'));
903
+
904
+ expect(logSpy.mock.calls).toMatchInlineSnapshot(`
905
+ [
906
+ [
907
+ "Please make sure the file names are matching in meshConfig.",
908
+ ],
909
+ ]
910
+ `);
911
+ expect(errorLogSpy.mock.calls).toMatchInlineSnapshot(`
912
+ [
913
+ [
914
+ "Input mesh config is not valid.",
915
+ ],
916
+ ]
917
+ `);
918
+ });
919
+
920
+ test('should fail if the file is of type other than js, json extension', async () => {
921
+ parseSpy.mockResolvedValue({
922
+ args: { file: 'src/commands/__fixtures__/sample_mesh_invalid_type.json' },
923
+ flags: {
924
+ autoConfirmAction: Promise.resolve(false),
925
+ },
926
+ });
927
+
928
+ const output = CreateCommand.run();
929
+
930
+ await expect(output).rejects.toEqual(new Error('Input mesh config is not valid.'));
931
+
932
+ expect(logSpy.mock.calls).toMatchInlineSnapshot(`
933
+ [
934
+ [
935
+ "Mesh files must be JavaScript or JSON. Other file types are not supported. The following file(s) are invalid: requestParams.txt.",
936
+ ],
937
+ ]
938
+ `);
939
+ expect(errorLogSpy.mock.calls).toMatchInlineSnapshot(`
940
+ [
941
+ [
942
+ "Input mesh config is not valid.",
943
+ ],
944
+ ]
945
+ `);
946
+ });
947
+
948
+ test('should fail if the files do not exist in the mesh directory or subdirectory', async () => {
949
+ parseSpy.mockResolvedValue({
950
+ args: { file: 'src/commands/__fixtures__/sample_mesh_invalid_paths.json' },
951
+ flags: {
952
+ autoConfirmAction: Promise.resolve(false),
953
+ },
954
+ });
955
+
956
+ importFiles.mockImplementation(() => {
957
+ throw new Error(
958
+ 'Please make sure the files: schemaBody.json and sample_mesh_invalid_paths.json are in the same directory/subdirectory.',
959
+ );
960
+ });
961
+
962
+ const output = CreateCommand.run();
963
+ await expect(output).rejects.toEqual(
964
+ new Error(
965
+ 'Unable to import the files in the mesh config. Please check the file and try again.',
966
+ ),
967
+ );
968
+
969
+ expect(logSpy.mock.calls).toMatchInlineSnapshot(`
970
+ [
971
+ [
972
+ "Please make sure the files: schemaBody.json and sample_mesh_invalid_paths.json are in the same directory/subdirectory.",
973
+ ],
974
+ ]
975
+ `);
976
+
977
+ expect(errorLogSpy.mock.calls).toMatchInlineSnapshot(`
978
+ [
979
+ [
980
+ "Unable to import the files in the mesh config. Please check the file and try again.",
981
+ ],
982
+ ]
983
+ `);
984
+ });
985
+
986
+ test('should fail if import files function fails', async () => {
987
+ parseSpy.mockResolvedValue({
988
+ args: { file: 'src/commands/__fixtures__/sample_mesh_files.json' },
989
+ flags: {
990
+ autoConfirmAction: Promise.resolve(false),
991
+ },
992
+ });
993
+
994
+ importFiles.mockImplementation(() => {
995
+ throw new Error('Error reading the file');
996
+ });
997
+
998
+ const output = CreateCommand.run();
999
+
1000
+ await expect(output).rejects.toEqual(
1001
+ new Error(
1002
+ 'Unable to import the files in the mesh config. Please check the file and try again.',
1003
+ ),
1004
+ );
1005
+
1006
+ expect(logSpy.mock.calls).toMatchInlineSnapshot(`
1007
+ [
1008
+ [
1009
+ "Error reading the file",
1010
+ ],
1011
+ ]
1012
+ `);
1013
+
1014
+ expect(errorLogSpy.mock.calls).toMatchInlineSnapshot(`
1015
+ [
1016
+ [
1017
+ "Unable to import the files in the mesh config. Please check the file and try again.",
1018
+ ],
1019
+ ]
1020
+ `);
1021
+ });
1022
+
1023
+ test('should not override if prompt returns No, if there is files array', async () => {
1024
+ let meshConfig = {
1025
+ sources: [
1026
+ {
1027
+ name: '<json_source_name>',
1028
+ handler: {
1029
+ JsonSchema: {
1030
+ baseUrl: '<json_source__baseurl>',
1031
+ operations: [
1032
+ {
1033
+ type: 'Query',
1034
+ field: '<query>',
1035
+ path: '<query_path>',
1036
+ method: 'POST',
1037
+ requestSchema: './requestParams.json',
1038
+ },
1039
+ ],
1040
+ },
1041
+ },
1042
+ },
1043
+ ],
1044
+ files: [
1045
+ {
1046
+ path: './requestParams.json',
1047
+ content: '{"type":"dummyContent"}',
1048
+ },
1049
+ ],
1050
+ };
1051
+
1052
+ promptConfirm.mockResolvedValue(false).mockResolvedValue(true);
1053
+
1054
+ importFiles.mockResolvedValue(meshConfig);
1055
+
1056
+ createMesh.mockResolvedValue({
1057
+ meshId: 'dummy_mesh_id',
1058
+ meshConfig: meshConfig,
1059
+ });
1060
+
1061
+ parseSpy.mockResolvedValue({
1062
+ args: { file: 'src/commands/__fixtures__/sample_mesh_with_files_array.json' },
1063
+ flags: {
1064
+ autoConfirmAction: Promise.resolve(false),
1065
+ },
1066
+ });
1067
+
1068
+ const output = await CreateCommand.run();
1069
+
1070
+ expect(initRequestId).toHaveBeenCalled();
1071
+ expect(createMesh.mock.calls[0]).toMatchInlineSnapshot(`
1072
+ [
1073
+ "1234",
1074
+ "5678",
1075
+ "123456789",
1076
+ {
1077
+ "files": [
1078
+ {
1079
+ "content": "{"type":"dummyContent"}",
1080
+ "path": "./requestParams.json",
1081
+ },
1082
+ ],
1083
+ "sources": [
1084
+ {
1085
+ "handler": {
1086
+ "JsonSchema": {
1087
+ "baseUrl": "<json_source__baseurl>",
1088
+ "operations": [
1089
+ {
1090
+ "field": "<query>",
1091
+ "method": "POST",
1092
+ "path": "<query_path>",
1093
+ "requestSchema": "./requestParams.json",
1094
+ "type": "Query",
1095
+ },
1096
+ ],
1097
+ },
1098
+ },
1099
+ "name": "<json_source_name>",
1100
+ },
1101
+ ],
1102
+ },
1103
+ ]
1104
+ `);
1105
+ expect(createAPIMeshCredentials.mock.calls[0]).toMatchInlineSnapshot(`
1106
+ [
1107
+ "1234",
1108
+ "5678",
1109
+ "123456789",
1110
+ ]
1111
+ `);
1112
+ expect(subscribeCredentialToMeshService.mock.calls[0]).toMatchInlineSnapshot(`
1113
+ [
1114
+ "1234",
1115
+ "5678",
1116
+ "123456789",
1117
+ "dummy_id",
1118
+ ]
1119
+ `);
1120
+ expect(output).toMatchInlineSnapshot(`
1121
+ {
1122
+ "adobeIdIntegrationsForWorkspace": {
1123
+ "apiKey": "dummy_api_key",
1124
+ "id": "dummy_id",
1125
+ },
1126
+ "mesh": {
1127
+ "meshConfig": {
1128
+ "files": [
1129
+ {
1130
+ "content": "{"type":"dummyContent"}",
1131
+ "path": "./requestParams.json",
1132
+ },
1133
+ ],
1134
+ "sources": [
1135
+ {
1136
+ "handler": {
1137
+ "JsonSchema": {
1138
+ "baseUrl": "<json_source__baseurl>",
1139
+ "operations": [
1140
+ {
1141
+ "field": "<query>",
1142
+ "method": "POST",
1143
+ "path": "<query_path>",
1144
+ "requestSchema": "./requestParams.json",
1145
+ "type": "Query",
1146
+ },
1147
+ ],
1148
+ },
1149
+ },
1150
+ "name": "<json_source_name>",
1151
+ },
1152
+ ],
1153
+ },
1154
+ "meshId": "dummy_mesh_id",
1155
+ },
1156
+ "sdkList": [
1157
+ "dummy_service",
1158
+ ],
1159
+ }
1160
+ `);
1161
+ });
1162
+
1163
+ test('should override if prompt returns Yes, if there is files array', async () => {
1164
+ let meshConfig = {
1165
+ sources: [
1166
+ {
1167
+ name: '<json_source_name>',
1168
+ handler: {
1169
+ JsonSchema: {
1170
+ baseUrl: '<json_source__baseurl>',
1171
+ operations: [
1172
+ {
1173
+ type: 'Query',
1174
+ field: '<query>',
1175
+ path: '<query_path>',
1176
+ method: 'POST',
1177
+ requestSchema: './requestParams.json',
1178
+ },
1179
+ ],
1180
+ },
1181
+ },
1182
+ },
1183
+ ],
1184
+ files: [
1185
+ {
1186
+ path: './requestParams.json',
1187
+ content: '{"type":"updatedContent"}',
1188
+ },
1189
+ ],
1190
+ };
1191
+
1192
+ promptConfirm.mockResolvedValue(true).mockResolvedValue(true);
1193
+
1194
+ parseSpy.mockResolvedValue({
1195
+ args: { file: 'src/commands/__fixtures__/sample_mesh_with_files_array.json' },
1196
+ flags: {
1197
+ autoConfirmAction: Promise.resolve(false),
1198
+ },
1199
+ });
1200
+
1201
+ importFiles.mockResolvedValueOnce({
1202
+ meshConfig,
1203
+ });
1204
+
1205
+ createMesh.mockResolvedValue({
1206
+ meshId: 'dummy_mesh_id',
1207
+ meshConfig: meshConfig,
1208
+ });
1209
+
1210
+ const output = await CreateCommand.run();
1211
+
1212
+ expect(initRequestId).toHaveBeenCalled();
1213
+ expect(createMesh.mock.calls[0]).toMatchInlineSnapshot(`
1214
+ [
1215
+ "1234",
1216
+ "5678",
1217
+ "123456789",
1218
+ {
1219
+ "meshConfig": {
1220
+ "files": [
1221
+ {
1222
+ "content": "{"type":"updatedContent"}",
1223
+ "path": "./requestParams.json",
1224
+ },
1225
+ ],
1226
+ "sources": [
1227
+ {
1228
+ "handler": {
1229
+ "JsonSchema": {
1230
+ "baseUrl": "<json_source__baseurl>",
1231
+ "operations": [
1232
+ {
1233
+ "field": "<query>",
1234
+ "method": "POST",
1235
+ "path": "<query_path>",
1236
+ "requestSchema": "./requestParams.json",
1237
+ "type": "Query",
1238
+ },
1239
+ ],
1240
+ },
1241
+ },
1242
+ "name": "<json_source_name>",
1243
+ },
1244
+ ],
1245
+ },
1246
+ },
1247
+ ]
1248
+ `);
1249
+ expect(createAPIMeshCredentials.mock.calls[0]).toMatchInlineSnapshot(`
1250
+ [
1251
+ "1234",
1252
+ "5678",
1253
+ "123456789",
1254
+ ]
1255
+ `);
1256
+
1257
+ expect(subscribeCredentialToMeshService.mock.calls[0]).toMatchInlineSnapshot(`
1258
+ [
1259
+ "1234",
1260
+ "5678",
1261
+ "123456789",
1262
+ "dummy_id",
1263
+ ]
1264
+ `);
1265
+ expect(output).toMatchInlineSnapshot(`
1266
+ {
1267
+ "adobeIdIntegrationsForWorkspace": {
1268
+ "apiKey": "dummy_api_key",
1269
+ "id": "dummy_id",
1270
+ },
1271
+ "mesh": {
1272
+ "meshConfig": {
1273
+ "files": [
1274
+ {
1275
+ "content": "{"type":"updatedContent"}",
1276
+ "path": "./requestParams.json",
1277
+ },
1278
+ ],
1279
+ "sources": [
1280
+ {
1281
+ "handler": {
1282
+ "JsonSchema": {
1283
+ "baseUrl": "<json_source__baseurl>",
1284
+ "operations": [
1285
+ {
1286
+ "field": "<query>",
1287
+ "method": "POST",
1288
+ "path": "<query_path>",
1289
+ "requestSchema": "./requestParams.json",
1290
+ "type": "Query",
1291
+ },
1292
+ ],
1293
+ },
1294
+ },
1295
+ "name": "<json_source_name>",
1296
+ },
1297
+ ],
1298
+ },
1299
+ "meshId": "dummy_mesh_id",
1300
+ },
1301
+ "sdkList": [
1302
+ "dummy_service",
1303
+ ],
1304
+ }
1305
+ `);
1306
+ });
1307
+
1308
+ test('should pass for a fully-qualified meshConfig even if the file does not exist in fileSystem', async () => {
1309
+ let meshConfig = {
1310
+ sources: [
1311
+ {
1312
+ name: '<json_source_name>',
1313
+ handler: {
1314
+ JsonSchema: {
1315
+ baseUrl: '<json_source__baseurl>',
1316
+ operations: [
1317
+ {
1318
+ type: 'Query',
1319
+ field: '<query>',
1320
+ path: '<query_path>',
1321
+ method: 'POST',
1322
+ requestSchema: './schemaBody.json',
1323
+ },
1324
+ ],
1325
+ },
1326
+ },
1327
+ },
1328
+ ],
1329
+ files: [
1330
+ {
1331
+ path: './schemaBody.json',
1332
+ content: '{"type":"dummyContent"}',
1333
+ },
1334
+ ],
1335
+ };
1336
+
1337
+ parseSpy.mockResolvedValue({
1338
+ args: { file: 'src/commands/__fixtures__/sample_fully_qualified_mesh.json' },
1339
+ flags: {
1340
+ autoConfirmAction: Promise.resolve(false),
1341
+ },
1342
+ });
1343
+
1344
+ promptConfirm.mockResolvedValue(true);
1345
+
1346
+ importFiles.mockResolvedValueOnce({
1347
+ meshConfig,
1348
+ });
1349
+
1350
+ createMesh.mockResolvedValue({
1351
+ meshId: 'dummy_mesh_id',
1352
+ meshConfig: meshConfig,
1353
+ });
1354
+
1355
+ const output = await CreateCommand.run();
1356
+
1357
+ expect(initRequestId).toHaveBeenCalled();
1358
+ expect(createMesh.mock.calls[0]).toMatchInlineSnapshot(`
1359
+ [
1360
+ "1234",
1361
+ "5678",
1362
+ "123456789",
1363
+ {
1364
+ "meshConfig": {
1365
+ "files": [
1366
+ {
1367
+ "content": "{"type":"dummyContent"}",
1368
+ "path": "./schemaBody.json",
1369
+ },
1370
+ ],
1371
+ "sources": [
1372
+ {
1373
+ "handler": {
1374
+ "JsonSchema": {
1375
+ "baseUrl": "<json_source__baseurl>",
1376
+ "operations": [
1377
+ {
1378
+ "field": "<query>",
1379
+ "method": "POST",
1380
+ "path": "<query_path>",
1381
+ "requestSchema": "./schemaBody.json",
1382
+ "type": "Query",
1383
+ },
1384
+ ],
1385
+ },
1386
+ },
1387
+ "name": "<json_source_name>",
1388
+ },
1389
+ ],
1390
+ },
1391
+ },
1392
+ ]
1393
+ `);
1394
+ expect(createAPIMeshCredentials.mock.calls[0]).toMatchInlineSnapshot(`
1395
+ [
1396
+ "1234",
1397
+ "5678",
1398
+ "123456789",
1399
+ ]
1400
+ `);
1401
+ expect(subscribeCredentialToMeshService.mock.calls[0]).toMatchInlineSnapshot(`
1402
+ [
1403
+ "1234",
1404
+ "5678",
1405
+ "123456789",
1406
+ "dummy_id",
1407
+ ]
1408
+ `);
1409
+ expect(output).toMatchInlineSnapshot(`
1410
+ {
1411
+ "adobeIdIntegrationsForWorkspace": {
1412
+ "apiKey": "dummy_api_key",
1413
+ "id": "dummy_id",
1414
+ },
1415
+ "mesh": {
1416
+ "meshConfig": {
1417
+ "files": [
1418
+ {
1419
+ "content": "{"type":"dummyContent"}",
1420
+ "path": "./schemaBody.json",
1421
+ },
1422
+ ],
1423
+ "sources": [
1424
+ {
1425
+ "handler": {
1426
+ "JsonSchema": {
1427
+ "baseUrl": "<json_source__baseurl>",
1428
+ "operations": [
1429
+ {
1430
+ "field": "<query>",
1431
+ "method": "POST",
1432
+ "path": "<query_path>",
1433
+ "requestSchema": "./schemaBody.json",
1434
+ "type": "Query",
1435
+ },
1436
+ ],
1437
+ },
1438
+ },
1439
+ "name": "<json_source_name>",
1440
+ },
1441
+ ],
1442
+ },
1443
+ "meshId": "dummy_mesh_id",
1444
+ },
1445
+ "sdkList": [
1446
+ "dummy_service",
1447
+ ],
1448
+ }
1449
+ `);
1450
+ });
1451
+
1452
+ test('should pass if the file is located in subdirectory of mesh directory', async () => {
1453
+ let meshConfig = {
1454
+ sources: [
1455
+ {
1456
+ name: '<json_source_name>',
1457
+ handler: {
1458
+ JsonSchema: {
1459
+ baseUrl: '<json_source__baseurl>',
1460
+ operations: [
1461
+ {
1462
+ type: 'Query',
1463
+ field: '<query>',
1464
+ path: '<query_path>',
1465
+ method: 'POST',
1466
+ requestSchema: './files/requestParams.json',
1467
+ },
1468
+ ],
1469
+ },
1470
+ },
1471
+ },
1472
+ ],
1473
+ files: [
1474
+ {
1475
+ path: './files/requestParams.json',
1476
+ content: '{"type":"updatedContent"}',
1477
+ },
1478
+ ],
1479
+ };
1480
+
1481
+ createMesh.mockResolvedValue({
1482
+ meshId: 'dummy_mesh_id',
1483
+ meshConfig: meshConfig,
1484
+ });
1485
+
1486
+ parseSpy.mockResolvedValue({
1487
+ args: { file: 'src/commands/__fixtures__/sample_mesh_subdirectory.json' },
1488
+ flags: {
1489
+ autoConfirmAction: Promise.resolve(false),
1490
+ },
1491
+ });
1492
+
1493
+ importFiles.mockResolvedValueOnce({
1494
+ meshConfig,
1495
+ });
1496
+
1497
+ const output = await CreateCommand.run();
1498
+
1499
+ expect(initRequestId).toHaveBeenCalled();
1500
+ expect(createMesh.mock.calls[0]).toMatchInlineSnapshot(`
1501
+ [
1502
+ "1234",
1503
+ "5678",
1504
+ "123456789",
1505
+ {
1506
+ "meshConfig": {
1507
+ "files": [
1508
+ {
1509
+ "content": "{"type":"updatedContent"}",
1510
+ "path": "./files/requestParams.json",
1511
+ },
1512
+ ],
1513
+ "sources": [
1514
+ {
1515
+ "handler": {
1516
+ "JsonSchema": {
1517
+ "baseUrl": "<json_source__baseurl>",
1518
+ "operations": [
1519
+ {
1520
+ "field": "<query>",
1521
+ "method": "POST",
1522
+ "path": "<query_path>",
1523
+ "requestSchema": "./files/requestParams.json",
1524
+ "type": "Query",
1525
+ },
1526
+ ],
1527
+ },
1528
+ },
1529
+ "name": "<json_source_name>",
1530
+ },
1531
+ ],
1532
+ },
1533
+ },
1534
+ ]
1535
+ `);
1536
+ expect(createAPIMeshCredentials.mock.calls[0]).toMatchInlineSnapshot(`
1537
+ [
1538
+ "1234",
1539
+ "5678",
1540
+ "123456789",
1541
+ ]
1542
+ `);
1543
+
1544
+ expect(subscribeCredentialToMeshService.mock.calls[0]).toMatchInlineSnapshot(`
1545
+ [
1546
+ "1234",
1547
+ "5678",
1548
+ "123456789",
1549
+ "dummy_id",
1550
+ ]
1551
+ `);
1552
+ expect(output).toMatchInlineSnapshot(`
1553
+ {
1554
+ "adobeIdIntegrationsForWorkspace": {
1555
+ "apiKey": "dummy_api_key",
1556
+ "id": "dummy_id",
1557
+ },
1558
+ "mesh": {
1559
+ "meshConfig": {
1560
+ "files": [
1561
+ {
1562
+ "content": "{"type":"updatedContent"}",
1563
+ "path": "./files/requestParams.json",
1564
+ },
1565
+ ],
1566
+ "sources": [
1567
+ {
1568
+ "handler": {
1569
+ "JsonSchema": {
1570
+ "baseUrl": "<json_source__baseurl>",
1571
+ "operations": [
1572
+ {
1573
+ "field": "<query>",
1574
+ "method": "POST",
1575
+ "path": "<query_path>",
1576
+ "requestSchema": "./files/requestParams.json",
1577
+ "type": "Query",
1578
+ },
1579
+ ],
1580
+ },
1581
+ },
1582
+ "name": "<json_source_name>",
1583
+ },
1584
+ ],
1585
+ },
1586
+ "meshId": "dummy_mesh_id",
1587
+ },
1588
+ "sdkList": [
1589
+ "dummy_service",
1590
+ ],
1591
+ }
1592
+ `);
1593
+ });
1594
+
1595
+ test('should fail if the file is outside the workspace directory', async () => {
1596
+ parseSpy.mockResolvedValue({
1597
+ args: { file: 'src/commands/__fixtures__/sample_mesh_outside_workspace_dir.json' },
1598
+ flags: {
1599
+ autoConfirmAction: Promise.resolve(false),
1600
+ },
1601
+ });
1602
+
1603
+ const output = CreateCommand.run();
1604
+
1605
+ await expect(output).rejects.toEqual(new Error('Input mesh config is not valid.'));
1606
+ expect(logSpy.mock.calls).toMatchInlineSnapshot(`
1607
+ [
1608
+ [
1609
+ "File(s): requestParams.json is outside the mesh directory.",
1610
+ ],
1611
+ ]
1612
+ `);
1613
+ expect(errorLogSpy.mock.calls).toMatchInlineSnapshot(`
1614
+ [
1615
+ [
1616
+ "Input mesh config is not valid.",
1617
+ ],
1618
+ ]
1619
+ `);
1620
+ });
1621
+
1622
+ test('should fail if the file has invalid JSON content', async () => {
1623
+ parseSpy.mockResolvedValue({
1624
+ args: { file: 'src/commands/__fixtures__/sample_mesh_invalid_file_content.json' },
1625
+ flags: {
1626
+ autoConfirmAction: Promise.resolve(false),
1627
+ },
1628
+ });
1629
+
1630
+ importFiles.mockImplementation(() => {
1631
+ throw new Error('Invalid JSON content in openapi-schema.json');
1632
+ });
1633
+
1634
+ const output = CreateCommand.run();
1635
+
1636
+ await expect(output).rejects.toEqual(
1637
+ new Error(
1638
+ 'Unable to import the files in the mesh config. Please check the file and try again.',
1639
+ ),
1640
+ );
1641
+
1642
+ expect(logSpy.mock.calls).toMatchInlineSnapshot(`
1643
+ [
1644
+ [
1645
+ "Invalid JSON content in openapi-schema.json",
1646
+ ],
1647
+ ]
1648
+ `);
1649
+
1650
+ expect(errorLogSpy.mock.calls).toMatchInlineSnapshot(`
1651
+ [
1652
+ [
1653
+ "Unable to import the files in the mesh config. Please check the file and try again.",
1654
+ ],
1655
+ ]
1656
+ `);
1657
+ });
1658
+
1659
+ test('should fail if the file path starts from home directory i.e., path starts with ~/', async () => {
1660
+ parseSpy.mockResolvedValue({
1661
+ args: { file: 'src/commands/__fixtures__/sample_mesh_path_from_home.json' },
1662
+ flags: {
1663
+ autoConfirmAction: Promise.resolve(false),
1664
+ },
1665
+ });
1666
+
1667
+ const output = CreateCommand.run();
1668
+
1669
+ await expect(output).rejects.toEqual(new Error('Input mesh config is not valid.'));
1670
+ expect(logSpy.mock.calls).toMatchInlineSnapshot(`
1671
+ [
1672
+ [
1673
+ "File(s): venia-openapi-schema.json is outside the mesh directory.",
1674
+ ],
1675
+ ]
1676
+ `);
1677
+ expect(errorLogSpy.mock.calls).toMatchInlineSnapshot(`
1678
+ [
1679
+ [
1680
+ "Input mesh config is not valid.",
1681
+ ],
1682
+ ]
1683
+ `);
490
1684
  });
491
1685
  });