@stoplight/elements 9.0.11 → 9.0.12-beta-0.2

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 (68) hide show
  1. package/.DS_Store +0 -0
  2. package/.storybook/main.js +6 -0
  3. package/.storybook/manager.js +1 -0
  4. package/.storybook/preview.jsx +3 -0
  5. package/dist/LICENSE +190 -0
  6. package/dist/README.md +19 -0
  7. package/dist/package.json +52 -0
  8. package/jest.config.js +7 -0
  9. package/package.json +76 -16
  10. package/src/__fixtures__/api-descriptions/Instagram.ts +1859 -0
  11. package/src/__fixtures__/api-descriptions/badgesForSchema.ts +36 -0
  12. package/src/__fixtures__/api-descriptions/simpleApiWithInternalOperations.ts +253 -0
  13. package/src/__fixtures__/api-descriptions/simpleApiWithoutDescription.ts +243 -0
  14. package/src/__fixtures__/api-descriptions/todosApiBundled.ts +430 -0
  15. package/src/__fixtures__/api-descriptions/zoomApiYaml.ts +6083 -0
  16. package/src/components/API/APIWithResponsiveSidebarLayout.tsx +125 -0
  17. package/src/components/API/APIWithSidebarLayout.tsx +158 -0
  18. package/src/components/API/APIWithStackedLayout.tsx +286 -0
  19. package/src/components/API/__tests__/utils.test.ts +1323 -0
  20. package/src/components/API/utils.ts +206 -0
  21. package/src/containers/API.spec.tsx +122 -0
  22. package/src/containers/API.stories.tsx +117 -0
  23. package/src/containers/API.tsx +277 -0
  24. package/src/containers/story-helper.tsx +53 -0
  25. package/src/hooks/useExportDocumentProps.spec.tsx +68 -0
  26. package/src/hooks/useExportDocumentProps.tsx +48 -0
  27. package/src/index.ts +6 -0
  28. package/src/styles.css +1 -0
  29. package/src/utils/oas/__tests__/oas.spec.ts +411 -0
  30. package/src/utils/oas/index.ts +192 -0
  31. package/src/utils/oas/oas2.ts +31 -0
  32. package/src/utils/oas/oas3.ts +54 -0
  33. package/src/utils/oas/types.ts +34 -0
  34. package/src/web-components/__stories__/Api.stories.tsx +63 -0
  35. package/src/web-components/components.ts +26 -0
  36. package/src/web-components/index.ts +3 -0
  37. package/tsconfig.build.json +18 -0
  38. package/tsconfig.json +7 -0
  39. package/web-components.config.js +1 -0
  40. package/styles.min.css +0 -1
  41. package/web-components.min.js +0 -2
  42. package/web-components.min.js.LICENSE.txt +0 -176
  43. /package/{__fixtures__ → dist/__fixtures__}/api-descriptions/Instagram.d.ts +0 -0
  44. /package/{__fixtures__ → dist/__fixtures__}/api-descriptions/badgesForSchema.d.ts +0 -0
  45. /package/{__fixtures__ → dist/__fixtures__}/api-descriptions/simpleApiWithInternalOperations.d.ts +0 -0
  46. /package/{__fixtures__ → dist/__fixtures__}/api-descriptions/simpleApiWithoutDescription.d.ts +0 -0
  47. /package/{__fixtures__ → dist/__fixtures__}/api-descriptions/todosApiBundled.d.ts +0 -0
  48. /package/{__fixtures__ → dist/__fixtures__}/api-descriptions/zoomApiYaml.d.ts +0 -0
  49. /package/{components → dist/components}/API/APIWithResponsiveSidebarLayout.d.ts +0 -0
  50. /package/{components → dist/components}/API/APIWithSidebarLayout.d.ts +0 -0
  51. /package/{components → dist/components}/API/APIWithStackedLayout.d.ts +0 -0
  52. /package/{components → dist/components}/API/utils.d.ts +0 -0
  53. /package/{containers → dist/containers}/API.d.ts +0 -0
  54. /package/{containers → dist/containers}/API.spec.d.ts +0 -0
  55. /package/{containers → dist/containers}/API.stories.d.ts +0 -0
  56. /package/{containers → dist/containers}/story-helper.d.ts +0 -0
  57. /package/{hooks → dist/hooks}/useExportDocumentProps.d.ts +0 -0
  58. /package/{hooks → dist/hooks}/useExportDocumentProps.spec.d.ts +0 -0
  59. /package/{index.d.ts → dist/index.d.ts} +0 -0
  60. /package/{index.esm.js → dist/index.esm.js} +0 -0
  61. /package/{index.js → dist/index.js} +0 -0
  62. /package/{index.mjs → dist/index.mjs} +0 -0
  63. /package/{utils → dist/utils}/oas/index.d.ts +0 -0
  64. /package/{utils → dist/utils}/oas/oas2.d.ts +0 -0
  65. /package/{utils → dist/utils}/oas/oas3.d.ts +0 -0
  66. /package/{utils → dist/utils}/oas/types.d.ts +0 -0
  67. /package/{web-components → dist/web-components}/components.d.ts +0 -0
  68. /package/{web-components → dist/web-components}/index.d.ts +0 -0
@@ -0,0 +1,1323 @@
1
+ import { NodeType } from '@stoplight/types';
2
+ import { OpenAPIObject as _OpenAPIObject, PathObject } from 'openapi3-ts';
3
+
4
+ import { transformOasToServiceNode } from '../../../utils/oas';
5
+ import { OperationNode, SchemaNode, WebhookNode } from '../../../utils/oas/types';
6
+ import { computeAPITree, computeTagGroups } from '../utils';
7
+
8
+ type OpenAPIObject = Partial<_OpenAPIObject> & {
9
+ webhooks?: PathObject;
10
+ };
11
+ describe.each([
12
+ ['paths', NodeType.HttpOperation, 'Endpoints', 'path'],
13
+ ['webhooks', NodeType.HttpWebhook, 'Webhooks', 'name'],
14
+ ] as const)('when grouping from "%s" as %s', (pathProp, nodeType, title, parentKeyProp) => {
15
+ describe('computeTagGroups', () => {
16
+ it('orders endpoints according to specified tags', () => {
17
+ const apiDocument: OpenAPIObject = {
18
+ openapi: '3.0.0',
19
+ info: {
20
+ title: 'some api',
21
+ version: '1.0.0',
22
+ description: 'some description',
23
+ },
24
+ tags: [
25
+ {
26
+ name: 'beta',
27
+ },
28
+ {
29
+ name: 'alpha',
30
+ },
31
+ ],
32
+ [pathProp]: {
33
+ '/a': {
34
+ get: {
35
+ tags: ['alpha'],
36
+ },
37
+ },
38
+ '/b': {
39
+ get: {
40
+ tags: ['beta'],
41
+ },
42
+ },
43
+ },
44
+ };
45
+
46
+ const serviceNode = transformOasToServiceNode(apiDocument);
47
+ expect(serviceNode ? computeTagGroups<OperationNode | WebhookNode>(serviceNode, nodeType) : null).toEqual({
48
+ groups: [
49
+ {
50
+ title: 'beta',
51
+ items: [
52
+ {
53
+ type: nodeType,
54
+ uri: `/${pathProp}/b/get`,
55
+ data: {
56
+ id: expect.any(String),
57
+ method: 'get',
58
+ [parentKeyProp]: '/b',
59
+ responses: [],
60
+ servers: [],
61
+ request: {
62
+ headers: [],
63
+ query: [],
64
+ cookie: [],
65
+ path: [],
66
+ },
67
+ tags: [
68
+ {
69
+ id: '9695eccd3aa64',
70
+ name: 'beta',
71
+ },
72
+ ],
73
+ security: [],
74
+ securityDeclarationType: 'inheritedFromService',
75
+ extensions: {},
76
+ },
77
+ name: '/b',
78
+ tags: ['beta'],
79
+ },
80
+ ],
81
+ },
82
+ {
83
+ title: 'alpha',
84
+ items: [
85
+ {
86
+ type: nodeType,
87
+ uri: `/${pathProp}/a/get`,
88
+ data: {
89
+ id: expect.any(String),
90
+ method: 'get',
91
+ [parentKeyProp]: '/a',
92
+ responses: [],
93
+ servers: [],
94
+ request: {
95
+ headers: [],
96
+ query: [],
97
+ cookie: [],
98
+ path: [],
99
+ },
100
+ tags: [
101
+ {
102
+ id: 'df0b92b61db3a',
103
+ name: 'alpha',
104
+ },
105
+ ],
106
+ security: [],
107
+ securityDeclarationType: 'inheritedFromService',
108
+ extensions: {},
109
+ },
110
+ name: '/a',
111
+ tags: ['alpha'],
112
+ },
113
+ ],
114
+ },
115
+ ],
116
+ ungrouped: [],
117
+ });
118
+ });
119
+
120
+ it('should support multiple tags by operations', () => {
121
+ const apiDocument: OpenAPIObject = {
122
+ openapi: '3.0.0',
123
+ info: {
124
+ title: 'some api',
125
+ version: '1.0.0',
126
+ description: 'some description',
127
+ },
128
+ tags: [
129
+ {
130
+ name: 'beta',
131
+ },
132
+ {
133
+ name: 'alpha',
134
+ },
135
+ ],
136
+ [pathProp]: {
137
+ '/a': {
138
+ get: {
139
+ tags: ['alpha', 'beta'],
140
+ },
141
+ },
142
+ '/b': {
143
+ get: {
144
+ tags: ['beta'],
145
+ },
146
+ },
147
+ },
148
+ };
149
+
150
+ const serviceNode = transformOasToServiceNode(apiDocument);
151
+ expect(serviceNode ? computeTagGroups<OperationNode | WebhookNode>(serviceNode, nodeType) : null).toEqual({
152
+ groups: [
153
+ {
154
+ title: 'beta',
155
+ items: [
156
+ {
157
+ type: nodeType,
158
+ uri: `/${pathProp}/a/get`,
159
+ data: {
160
+ id: expect.any(String),
161
+ method: 'get',
162
+ [parentKeyProp]: '/a',
163
+ responses: [],
164
+ servers: [],
165
+ request: {
166
+ headers: [],
167
+ query: [],
168
+ cookie: [],
169
+ path: [],
170
+ },
171
+ tags: [
172
+ {
173
+ id: 'df0b92b61db3a',
174
+ name: 'alpha',
175
+ },
176
+ {
177
+ id: '9695eccd3aa64',
178
+ name: 'beta',
179
+ },
180
+ ],
181
+ security: [],
182
+ securityDeclarationType: 'inheritedFromService',
183
+ extensions: {},
184
+ },
185
+ name: '/a',
186
+ tags: ['alpha', 'beta'],
187
+ },
188
+ {
189
+ type: nodeType,
190
+ uri: `/${pathProp}/b/get`,
191
+ data: {
192
+ id: expect.any(String),
193
+ method: 'get',
194
+ [parentKeyProp]: '/b',
195
+ responses: [],
196
+ servers: [],
197
+ request: {
198
+ headers: [],
199
+ query: [],
200
+ cookie: [],
201
+ path: [],
202
+ },
203
+ tags: [
204
+ {
205
+ id: '9695eccd3aa64',
206
+ name: 'beta',
207
+ },
208
+ ],
209
+ security: [],
210
+ securityDeclarationType: 'inheritedFromService',
211
+ extensions: {},
212
+ },
213
+ name: '/b',
214
+ tags: ['beta'],
215
+ },
216
+ ],
217
+ },
218
+ {
219
+ title: 'alpha',
220
+ items: [
221
+ {
222
+ type: nodeType,
223
+ uri: `/${pathProp}/a/get`,
224
+ data: {
225
+ id: expect.any(String),
226
+ method: 'get',
227
+ [parentKeyProp]: '/a',
228
+ responses: [],
229
+ servers: [],
230
+ request: {
231
+ headers: [],
232
+ query: [],
233
+ cookie: [],
234
+ path: [],
235
+ },
236
+ tags: [
237
+ {
238
+ id: 'df0b92b61db3a',
239
+ name: 'alpha',
240
+ },
241
+ {
242
+ id: '9695eccd3aa64',
243
+ name: 'beta',
244
+ },
245
+ ],
246
+ security: [],
247
+ securityDeclarationType: 'inheritedFromService',
248
+ extensions: {},
249
+ },
250
+ name: '/a',
251
+ tags: ['alpha', 'beta'],
252
+ },
253
+ ],
254
+ },
255
+ ],
256
+ ungrouped: [],
257
+ });
258
+ });
259
+
260
+ it("within the tags it doesn't reorder the endpoints", () => {
261
+ const apiDocument: OpenAPIObject = {
262
+ openapi: '3.0.0',
263
+ info: {
264
+ title: 'some api',
265
+ version: '1.0.0',
266
+ description: 'some description',
267
+ },
268
+ tags: [
269
+ {
270
+ name: 'beta',
271
+ },
272
+ {
273
+ name: 'alpha',
274
+ },
275
+ ],
276
+ [pathProp]: {
277
+ '/a': {
278
+ get: {
279
+ tags: ['alpha'],
280
+ },
281
+ },
282
+ '/c': {
283
+ get: {
284
+ tags: ['beta'],
285
+ },
286
+ },
287
+ '/b': {
288
+ get: {
289
+ tags: ['beta'],
290
+ },
291
+ },
292
+ },
293
+ };
294
+
295
+ const serviceNode = transformOasToServiceNode(apiDocument);
296
+ expect(serviceNode ? computeTagGroups<OperationNode | WebhookNode>(serviceNode, nodeType) : null).toEqual({
297
+ groups: [
298
+ {
299
+ title: 'beta',
300
+ items: [
301
+ {
302
+ type: nodeType,
303
+ uri: `/${pathProp}/c/get`,
304
+ data: {
305
+ id: expect.any(String),
306
+ method: 'get',
307
+ [parentKeyProp]: '/c',
308
+ responses: [],
309
+ servers: [],
310
+ request: { headers: [], query: [], cookie: [], path: [] },
311
+ tags: [{ id: '9695eccd3aa64', name: 'beta' }],
312
+ security: [],
313
+ securityDeclarationType: 'inheritedFromService',
314
+ extensions: {},
315
+ },
316
+ name: '/c',
317
+ tags: ['beta'],
318
+ },
319
+ {
320
+ type: nodeType,
321
+ uri: `/${pathProp}/b/get`,
322
+ data: {
323
+ id: expect.any(String),
324
+ method: 'get',
325
+ [parentKeyProp]: '/b',
326
+ responses: [],
327
+ servers: [],
328
+ request: { headers: [], query: [], cookie: [], path: [] },
329
+ tags: [{ id: '9695eccd3aa64', name: 'beta' }],
330
+ security: [],
331
+ securityDeclarationType: 'inheritedFromService',
332
+ extensions: {},
333
+ },
334
+ name: '/b',
335
+ tags: ['beta'],
336
+ },
337
+ ],
338
+ },
339
+ {
340
+ title: 'alpha',
341
+ items: [
342
+ {
343
+ type: nodeType,
344
+ uri: `/${pathProp}/a/get`,
345
+ data: {
346
+ id: expect.any(String),
347
+ method: 'get',
348
+ [parentKeyProp]: '/a',
349
+ responses: [],
350
+ servers: [],
351
+ request: { headers: [], query: [], cookie: [], path: [] },
352
+ tags: [{ id: 'df0b92b61db3a', name: 'alpha' }],
353
+ security: [],
354
+ securityDeclarationType: 'inheritedFromService',
355
+ extensions: {},
356
+ },
357
+ name: '/a',
358
+ tags: ['alpha'],
359
+ },
360
+ ],
361
+ },
362
+ ],
363
+ ungrouped: [],
364
+ });
365
+ });
366
+
367
+ it("within the tags it doesn't reorder the methods", () => {
368
+ const apiDocument: OpenAPIObject = {
369
+ openapi: '3.0.0',
370
+ info: {
371
+ title: 'some api',
372
+ version: '1.0.0',
373
+ description: 'some description',
374
+ },
375
+ tags: [
376
+ {
377
+ name: 'beta',
378
+ },
379
+ {
380
+ name: 'alpha',
381
+ },
382
+ ],
383
+ [pathProp]: {
384
+ '/a': {
385
+ get: {
386
+ tags: ['alpha'],
387
+ },
388
+ },
389
+ '/b': {
390
+ get: {
391
+ tags: ['beta'],
392
+ },
393
+ delete: {
394
+ tags: ['beta'],
395
+ },
396
+ },
397
+ },
398
+ };
399
+
400
+ const serviceNode = transformOasToServiceNode(apiDocument);
401
+ expect(serviceNode ? computeTagGroups<OperationNode | WebhookNode>(serviceNode, nodeType) : null).toEqual({
402
+ groups: [
403
+ {
404
+ title: 'beta',
405
+ items: [
406
+ {
407
+ type: nodeType,
408
+ uri: `/${pathProp}/b/get`,
409
+ data: {
410
+ id: expect.any(String),
411
+ method: 'get',
412
+ [parentKeyProp]: '/b',
413
+ responses: [],
414
+ servers: [],
415
+ request: { headers: [], query: [], cookie: [], path: [] },
416
+ tags: [{ id: '9695eccd3aa64', name: 'beta' }],
417
+ security: [],
418
+ securityDeclarationType: 'inheritedFromService',
419
+ extensions: {},
420
+ },
421
+ name: '/b',
422
+ tags: ['beta'],
423
+ },
424
+ {
425
+ type: nodeType,
426
+ uri: `/${pathProp}/b/delete`,
427
+ data: {
428
+ id: expect.any(String),
429
+ method: 'delete',
430
+ [parentKeyProp]: '/b',
431
+ responses: [],
432
+ servers: [],
433
+ request: { headers: [], query: [], cookie: [], path: [] },
434
+ tags: [{ id: '9695eccd3aa64', name: 'beta' }],
435
+ security: [],
436
+ securityDeclarationType: 'inheritedFromService',
437
+ extensions: {},
438
+ },
439
+ name: '/b',
440
+ tags: ['beta'],
441
+ },
442
+ ],
443
+ },
444
+ {
445
+ title: 'alpha',
446
+ items: [
447
+ {
448
+ type: nodeType,
449
+ uri: `/${pathProp}/a/get`,
450
+ data: {
451
+ id: expect.any(String),
452
+ method: 'get',
453
+ [parentKeyProp]: '/a',
454
+ responses: [],
455
+ servers: [],
456
+ request: { headers: [], query: [], cookie: [], path: [] },
457
+ tags: [{ id: 'df0b92b61db3a', name: 'alpha' }],
458
+ security: [],
459
+ securityDeclarationType: 'inheritedFromService',
460
+ extensions: {},
461
+ },
462
+ name: '/a',
463
+ tags: ['alpha'],
464
+ },
465
+ ],
466
+ },
467
+ ],
468
+ ungrouped: [],
469
+ });
470
+ });
471
+
472
+ it("doesn't throw with incorrect tags value", () => {
473
+ const apiDocument = {
474
+ openapi: '3.0.0',
475
+ info: {
476
+ title: 'some api',
477
+ version: '1.0.0',
478
+ description: 'some description',
479
+ },
480
+ [pathProp]: {},
481
+ tags: {
482
+ $ref: './tags',
483
+ },
484
+ };
485
+
486
+ const serviceNode = transformOasToServiceNode(apiDocument);
487
+ expect(serviceNode ? computeTagGroups<OperationNode | WebhookNode>(serviceNode, nodeType) : null).toEqual({
488
+ groups: [],
489
+ ungrouped: [],
490
+ });
491
+ });
492
+
493
+ it('leaves tag casing unchanged', () => {
494
+ const apiDocument: OpenAPIObject = {
495
+ openapi: '3.0.0',
496
+ info: {
497
+ title: 'some api',
498
+ version: '1.0.0',
499
+ description: 'some description',
500
+ },
501
+ tags: [
502
+ {
503
+ name: 'Beta',
504
+ },
505
+ {
506
+ name: 'alpha',
507
+ },
508
+ ],
509
+ [pathProp]: {
510
+ '/a': {
511
+ get: {
512
+ tags: ['alpha'],
513
+ },
514
+ },
515
+ '/b': {
516
+ get: {
517
+ tags: ['Beta'],
518
+ },
519
+ },
520
+ },
521
+ };
522
+
523
+ const serviceNode = transformOasToServiceNode(apiDocument);
524
+ expect(serviceNode ? computeTagGroups<OperationNode | WebhookNode>(serviceNode, nodeType) : null).toEqual({
525
+ groups: [
526
+ {
527
+ title: 'Beta',
528
+ items: [
529
+ {
530
+ type: nodeType,
531
+ uri: `/${pathProp}/b/get`,
532
+ data: {
533
+ id: expect.any(String),
534
+ method: 'get',
535
+ [parentKeyProp]: '/b',
536
+ responses: [],
537
+ servers: [],
538
+ request: {
539
+ headers: [],
540
+ query: [],
541
+ cookie: [],
542
+ path: [],
543
+ },
544
+ tags: [
545
+ {
546
+ name: 'Beta',
547
+ id: 'c6a65e6457b55',
548
+ },
549
+ ],
550
+ security: [],
551
+ securityDeclarationType: 'inheritedFromService',
552
+ extensions: {},
553
+ },
554
+ name: '/b',
555
+ tags: ['Beta'],
556
+ },
557
+ ],
558
+ },
559
+ {
560
+ title: 'alpha',
561
+ items: [
562
+ {
563
+ type: nodeType,
564
+ uri: `/${pathProp}/a/get`,
565
+ data: {
566
+ id: expect.any(String),
567
+ method: 'get',
568
+ [parentKeyProp]: '/a',
569
+ responses: [],
570
+ servers: [],
571
+ request: {
572
+ headers: [],
573
+ query: [],
574
+ cookie: [],
575
+ path: [],
576
+ },
577
+ tags: [
578
+ {
579
+ id: 'df0b92b61db3a',
580
+ name: 'alpha',
581
+ },
582
+ ],
583
+ security: [],
584
+ securityDeclarationType: 'inheritedFromService',
585
+ extensions: {},
586
+ },
587
+ name: '/a',
588
+ tags: ['alpha'],
589
+ },
590
+ ],
591
+ },
592
+ ],
593
+ ungrouped: [],
594
+ });
595
+ });
596
+
597
+ it('matches mixed tag casing', () => {
598
+ const apiDocument: OpenAPIObject = {
599
+ openapi: '3.0.0',
600
+ info: {
601
+ title: 'some api',
602
+ version: '1.0.0',
603
+ description: 'some description',
604
+ },
605
+ tags: [
606
+ {
607
+ name: 'Beta',
608
+ },
609
+ {
610
+ name: 'alpha',
611
+ },
612
+ ],
613
+ [pathProp]: {
614
+ '/a': {
615
+ get: {
616
+ tags: ['alpha'],
617
+ },
618
+ },
619
+ '/b': {
620
+ get: {
621
+ tags: ['beta'],
622
+ },
623
+ },
624
+ },
625
+ };
626
+
627
+ const serviceNode = transformOasToServiceNode(apiDocument);
628
+ expect(serviceNode ? computeTagGroups<OperationNode | WebhookNode>(serviceNode, nodeType) : null).toEqual({
629
+ groups: [
630
+ {
631
+ title: 'Beta',
632
+ items: [
633
+ {
634
+ type: nodeType,
635
+ uri: `/${pathProp}/b/get`,
636
+ data: {
637
+ id: expect.any(String),
638
+ method: 'get',
639
+ [parentKeyProp]: '/b',
640
+ responses: [],
641
+ servers: [],
642
+ request: {
643
+ headers: [],
644
+ query: [],
645
+ cookie: [],
646
+ path: [],
647
+ },
648
+ tags: [
649
+ {
650
+ id: '9695eccd3aa64',
651
+ name: 'beta',
652
+ },
653
+ ],
654
+ security: [],
655
+ securityDeclarationType: 'inheritedFromService',
656
+ extensions: {},
657
+ },
658
+ name: '/b',
659
+ tags: ['beta'],
660
+ },
661
+ ],
662
+ },
663
+ {
664
+ title: 'alpha',
665
+ items: [
666
+ {
667
+ type: nodeType,
668
+ uri: `/${pathProp}/a/get`,
669
+ data: {
670
+ id: expect.any(String),
671
+ method: 'get',
672
+ [parentKeyProp]: '/a',
673
+ responses: [],
674
+ servers: [],
675
+ request: {
676
+ headers: [],
677
+ query: [],
678
+ cookie: [],
679
+ path: [],
680
+ },
681
+ tags: [
682
+ {
683
+ id: 'df0b92b61db3a',
684
+ name: 'alpha',
685
+ },
686
+ ],
687
+ security: [],
688
+ securityDeclarationType: 'inheritedFromService',
689
+ extensions: {},
690
+ },
691
+ name: '/a',
692
+ tags: ['alpha'],
693
+ },
694
+ ],
695
+ },
696
+ ],
697
+ ungrouped: [],
698
+ });
699
+ });
700
+ });
701
+
702
+ describe('computeAPITree', () => {
703
+ it('generates API ToC tree', () => {
704
+ const apiDocument: OpenAPIObject = {
705
+ openapi: '3.0.0',
706
+ info: {
707
+ title: 'some api',
708
+ version: '1.0.0',
709
+ description: 'some description',
710
+ },
711
+ [pathProp]: {
712
+ '/something': {
713
+ get: {
714
+ responses: {
715
+ 200: {
716
+ schema: { $ref: '#/definitions/schemas/ImportantSchema' },
717
+ },
718
+ },
719
+ },
720
+ },
721
+ },
722
+ components: {
723
+ schemas: {
724
+ ImportantSchema: {
725
+ type: 'object',
726
+ properties: {
727
+ a: { type: 'string' },
728
+ },
729
+ },
730
+ },
731
+ },
732
+ };
733
+
734
+ expect(computeAPITree(transformOasToServiceNode(apiDocument)!)).toEqual([
735
+ {
736
+ id: '/',
737
+ meta: '',
738
+ slug: '/',
739
+ title: 'Overview',
740
+ type: 'overview',
741
+ },
742
+ {
743
+ title,
744
+ },
745
+ {
746
+ id: `/${pathProp}/something/get`,
747
+ meta: 'get',
748
+ slug: `/${pathProp}/something/get`,
749
+ title: '/something',
750
+ type: nodeType,
751
+ },
752
+ { title: 'Schemas' },
753
+ {
754
+ id: '/schemas/ImportantSchema',
755
+ slug: '/schemas/ImportantSchema',
756
+ title: 'ImportantSchema',
757
+ type: 'model',
758
+ meta: '',
759
+ },
760
+ ]);
761
+ });
762
+
763
+ it('allows to hide schemas from ToC', () => {
764
+ const apiDocument: OpenAPIObject = {
765
+ openapi: '3.0.0',
766
+ info: {
767
+ title: 'some api',
768
+ version: '1.0.0',
769
+ description: 'some description',
770
+ },
771
+ [pathProp]: {
772
+ '/something': {
773
+ get: {
774
+ responses: {
775
+ 200: {
776
+ schema: { $ref: '#/definitions/schemas/ImportantSchema' },
777
+ },
778
+ },
779
+ },
780
+ },
781
+ },
782
+ components: {
783
+ schemas: {
784
+ ImportantSchema: {
785
+ type: 'object',
786
+ properties: {
787
+ a: { type: 'string' },
788
+ },
789
+ },
790
+ },
791
+ },
792
+ };
793
+
794
+ expect(computeAPITree(transformOasToServiceNode(apiDocument)!, { hideSchemas: true })).toEqual([
795
+ {
796
+ id: '/',
797
+ meta: '',
798
+ slug: '/',
799
+ title: 'Overview',
800
+ type: 'overview',
801
+ },
802
+ {
803
+ title,
804
+ },
805
+ {
806
+ id: `/${pathProp}/something/get`,
807
+ meta: 'get',
808
+ slug: `/${pathProp}/something/get`,
809
+ title: '/something',
810
+ type: nodeType,
811
+ },
812
+ ]);
813
+ });
814
+
815
+ it('allows to hide internal operations from ToC', () => {
816
+ const apiDocument: OpenAPIObject = {
817
+ openapi: '3.0.0',
818
+ info: {
819
+ title: 'some api',
820
+ version: '1.0.0',
821
+ description: 'some description',
822
+ },
823
+ [pathProp]: {
824
+ '/something': {
825
+ get: {},
826
+ post: {
827
+ 'x-internal': true,
828
+ },
829
+ },
830
+ },
831
+ };
832
+
833
+ expect(computeAPITree(transformOasToServiceNode(apiDocument)!, { hideInternal: true })).toEqual([
834
+ {
835
+ id: '/',
836
+ meta: '',
837
+ slug: '/',
838
+ title: 'Overview',
839
+ type: 'overview',
840
+ },
841
+ {
842
+ title,
843
+ },
844
+ {
845
+ id: `/${pathProp}/something/get`,
846
+ meta: 'get',
847
+ slug: `/${pathProp}/something/get`,
848
+ title: '/something',
849
+ type: nodeType,
850
+ },
851
+ ]);
852
+ });
853
+
854
+ it('allows to hide nested internal operations from ToC', () => {
855
+ const apiDocument: OpenAPIObject = {
856
+ openapi: '3.0.0',
857
+ info: {
858
+ title: 'some api',
859
+ version: '1.0.0',
860
+ description: 'some description',
861
+ },
862
+ tags: [
863
+ {
864
+ name: 'a',
865
+ },
866
+ ],
867
+ [pathProp]: {
868
+ '/something': {
869
+ get: {
870
+ tags: ['a'],
871
+ },
872
+ post: {
873
+ 'x-internal': true,
874
+ tags: ['a'],
875
+ },
876
+ },
877
+ },
878
+ };
879
+
880
+ expect(computeAPITree(transformOasToServiceNode(apiDocument)!, { hideInternal: true })).toEqual([
881
+ {
882
+ id: '/',
883
+ meta: '',
884
+ slug: '/',
885
+ title: 'Overview',
886
+ type: 'overview',
887
+ },
888
+ {
889
+ title,
890
+ },
891
+ {
892
+ title: 'a',
893
+ itemsType: nodeType,
894
+ items: [
895
+ {
896
+ id: `/${pathProp}/something/get`,
897
+ meta: 'get',
898
+ slug: `/${pathProp}/something/get`,
899
+ title: '/something',
900
+ type: nodeType,
901
+ },
902
+ ],
903
+ },
904
+ ]);
905
+ });
906
+
907
+ it('allows to hide internal models from ToC', () => {
908
+ const apiDocument: OpenAPIObject = {
909
+ openapi: '3.0.0',
910
+ info: {
911
+ title: 'some api',
912
+ version: '1.0.0',
913
+ description: 'some description',
914
+ },
915
+ [pathProp]: {},
916
+ components: {
917
+ schemas: {
918
+ SomeInternalSchema: {
919
+ 'x-internal': true,
920
+ },
921
+ },
922
+ },
923
+ };
924
+
925
+ expect(computeAPITree(transformOasToServiceNode(apiDocument)!, { hideInternal: true })).toEqual([
926
+ {
927
+ id: '/',
928
+ meta: '',
929
+ slug: '/',
930
+ title: 'Overview',
931
+ type: 'overview',
932
+ },
933
+ ]);
934
+ });
935
+
936
+ it('allows to hide nested internal models from ToC', () => {
937
+ const apiDocument: OpenAPIObject = {
938
+ openapi: '3.0.0',
939
+ info: {
940
+ title: 'some api',
941
+ version: '1.0.0',
942
+ description: 'some description',
943
+ },
944
+ tags: [
945
+ {
946
+ name: 'a',
947
+ },
948
+ ],
949
+ [pathProp]: {},
950
+ components: {
951
+ schemas: {
952
+ a: {
953
+ 'x-tags': ['a'],
954
+ },
955
+ b: {
956
+ 'x-tags': ['a'],
957
+ 'x-internal': true,
958
+ },
959
+ },
960
+ },
961
+ };
962
+
963
+ expect(computeAPITree(transformOasToServiceNode(apiDocument)!, { hideInternal: true })).toEqual([
964
+ {
965
+ id: '/',
966
+ meta: '',
967
+ slug: '/',
968
+ title: 'Overview',
969
+ type: 'overview',
970
+ },
971
+ { title: 'Schemas' },
972
+ {
973
+ title: 'a',
974
+ itemsType: NodeType.Model,
975
+ items: [
976
+ {
977
+ id: '/schemas/a',
978
+ slug: '/schemas/a',
979
+ title: 'a',
980
+ type: 'model',
981
+ meta: '',
982
+ },
983
+ ],
984
+ },
985
+ ]);
986
+ });
987
+
988
+ it('excludes groups with no items', () => {
989
+ const apiDocument: OpenAPIObject = {
990
+ openapi: '3.0.0',
991
+ info: {
992
+ title: 'some api',
993
+ version: '1.0.0',
994
+ description: 'some description',
995
+ },
996
+ tags: [
997
+ {
998
+ name: 'a',
999
+ },
1000
+ ],
1001
+ [pathProp]: {
1002
+ '/something': {
1003
+ post: {
1004
+ 'x-internal': true,
1005
+ tags: ['a'],
1006
+ },
1007
+ },
1008
+ '/something-else': {
1009
+ post: {
1010
+ tags: ['b'],
1011
+ },
1012
+ },
1013
+ },
1014
+ components: {
1015
+ schemas: {
1016
+ a: {
1017
+ 'x-tags': ['a'],
1018
+ 'x-internal': true,
1019
+ },
1020
+ },
1021
+ },
1022
+ };
1023
+
1024
+ expect(computeAPITree(transformOasToServiceNode(apiDocument)!, { hideInternal: true })).toEqual([
1025
+ {
1026
+ id: '/',
1027
+ meta: '',
1028
+ slug: '/',
1029
+ title: 'Overview',
1030
+ type: 'overview',
1031
+ },
1032
+ {
1033
+ title,
1034
+ },
1035
+ {
1036
+ title: 'b',
1037
+ itemsType: nodeType,
1038
+ items: [
1039
+ {
1040
+ id: `/${pathProp}/something-else/post`,
1041
+ meta: 'post',
1042
+ slug: `/${pathProp}/something-else/post`,
1043
+ title: '/something-else',
1044
+ type: nodeType,
1045
+ },
1046
+ ],
1047
+ },
1048
+ ]);
1049
+ });
1050
+ });
1051
+ });
1052
+
1053
+ describe('when grouping models', () => {
1054
+ describe('computeTagGroups', () => {
1055
+ it('orders models according to specified tags', () => {
1056
+ const apiDocument: OpenAPIObject = {
1057
+ openapi: '3.0.0',
1058
+ info: {
1059
+ title: 'some api',
1060
+ version: '1.0.0',
1061
+ description: 'some description',
1062
+ },
1063
+ tags: [
1064
+ {
1065
+ name: 'beta',
1066
+ },
1067
+ {
1068
+ name: 'alpha',
1069
+ },
1070
+ ],
1071
+ components: {
1072
+ schemas: {
1073
+ a: {
1074
+ 'x-tags': ['alpha'],
1075
+ },
1076
+ b: {
1077
+ 'x-tags': ['beta'],
1078
+ },
1079
+ },
1080
+ },
1081
+ };
1082
+
1083
+ const serviceNode = transformOasToServiceNode(apiDocument);
1084
+ expect(serviceNode ? computeTagGroups<SchemaNode>(serviceNode, NodeType.Model) : null).toEqual({
1085
+ groups: [
1086
+ {
1087
+ title: 'beta',
1088
+ items: [
1089
+ {
1090
+ type: NodeType.Model,
1091
+ uri: '/schemas/b',
1092
+ data: {
1093
+ 'x-tags': ['beta'],
1094
+ },
1095
+ name: 'b',
1096
+ tags: ['beta'],
1097
+ },
1098
+ ],
1099
+ },
1100
+ {
1101
+ title: 'alpha',
1102
+ items: [
1103
+ {
1104
+ type: NodeType.Model,
1105
+ uri: '/schemas/a',
1106
+ data: {
1107
+ 'x-tags': ['alpha'],
1108
+ },
1109
+ name: 'a',
1110
+ tags: ['alpha'],
1111
+ },
1112
+ ],
1113
+ },
1114
+ ],
1115
+ ungrouped: [],
1116
+ });
1117
+ });
1118
+
1119
+ it("within the tags it doesn't reorder the schemas", () => {
1120
+ const apiDocument: OpenAPIObject = {
1121
+ openapi: '3.0.0',
1122
+ info: {
1123
+ title: 'some api',
1124
+ version: '1.0.0',
1125
+ description: 'some description',
1126
+ },
1127
+ tags: [
1128
+ {
1129
+ name: 'beta',
1130
+ },
1131
+ {
1132
+ name: 'alpha',
1133
+ },
1134
+ ],
1135
+ components: {
1136
+ schemas: {
1137
+ a: {
1138
+ 'x-tags': ['alpha'],
1139
+ },
1140
+ c: {
1141
+ 'x-tags': ['beta'],
1142
+ },
1143
+ b: {
1144
+ 'x-tags': ['beta'],
1145
+ },
1146
+ },
1147
+ },
1148
+ };
1149
+
1150
+ const serviceNode = transformOasToServiceNode(apiDocument);
1151
+ expect(serviceNode ? computeTagGroups<SchemaNode>(serviceNode, NodeType.Model) : null).toEqual({
1152
+ groups: [
1153
+ {
1154
+ title: 'beta',
1155
+ items: [
1156
+ {
1157
+ type: NodeType.Model,
1158
+ uri: '/schemas/c',
1159
+ data: {
1160
+ 'x-tags': ['beta'],
1161
+ },
1162
+ name: 'c',
1163
+ tags: ['beta'],
1164
+ },
1165
+ {
1166
+ type: NodeType.Model,
1167
+ uri: '/schemas/b',
1168
+ data: {
1169
+ 'x-tags': ['beta'],
1170
+ },
1171
+ name: 'b',
1172
+ tags: ['beta'],
1173
+ },
1174
+ ],
1175
+ },
1176
+ {
1177
+ title: 'alpha',
1178
+ items: [
1179
+ {
1180
+ type: NodeType.Model,
1181
+ uri: '/schemas/a',
1182
+ data: {
1183
+ 'x-tags': ['alpha'],
1184
+ },
1185
+ name: 'a',
1186
+ tags: ['alpha'],
1187
+ },
1188
+ ],
1189
+ },
1190
+ ],
1191
+ ungrouped: [],
1192
+ });
1193
+ });
1194
+
1195
+ it('leaves tag casing unchanged', () => {
1196
+ const apiDocument: OpenAPIObject = {
1197
+ openapi: '3.0.0',
1198
+ info: {
1199
+ title: 'some api',
1200
+ version: '1.0.0',
1201
+ description: 'some description',
1202
+ },
1203
+ tags: [
1204
+ {
1205
+ name: 'Beta',
1206
+ },
1207
+ {
1208
+ name: 'alpha',
1209
+ },
1210
+ ],
1211
+ components: {
1212
+ schemas: {
1213
+ a: {
1214
+ 'x-tags': ['alpha'],
1215
+ },
1216
+ b: {
1217
+ 'x-tags': ['Beta'],
1218
+ },
1219
+ },
1220
+ },
1221
+ };
1222
+
1223
+ const serviceNode = transformOasToServiceNode(apiDocument);
1224
+ expect(serviceNode ? computeTagGroups<SchemaNode>(serviceNode, NodeType.Model) : null).toEqual({
1225
+ groups: [
1226
+ {
1227
+ title: 'Beta',
1228
+ items: [
1229
+ {
1230
+ type: NodeType.Model,
1231
+ uri: '/schemas/b',
1232
+ data: {
1233
+ 'x-tags': ['Beta'],
1234
+ },
1235
+ name: 'b',
1236
+ tags: ['Beta'],
1237
+ },
1238
+ ],
1239
+ },
1240
+ {
1241
+ title: 'alpha',
1242
+ items: [
1243
+ {
1244
+ type: NodeType.Model,
1245
+ uri: '/schemas/a',
1246
+ data: {
1247
+ 'x-tags': ['alpha'],
1248
+ },
1249
+ name: 'a',
1250
+ tags: ['alpha'],
1251
+ },
1252
+ ],
1253
+ },
1254
+ ],
1255
+ ungrouped: [],
1256
+ });
1257
+ });
1258
+
1259
+ it('matches mixed tag casing', () => {
1260
+ const apiDocument: OpenAPIObject = {
1261
+ openapi: '3.0.0',
1262
+ info: {
1263
+ title: 'some api',
1264
+ version: '1.0.0',
1265
+ description: 'some description',
1266
+ },
1267
+ tags: [
1268
+ {
1269
+ name: 'Beta',
1270
+ },
1271
+ {
1272
+ name: 'alpha',
1273
+ },
1274
+ ],
1275
+ components: {
1276
+ schemas: {
1277
+ a: {
1278
+ 'x-tags': ['alpha'],
1279
+ },
1280
+ b: {
1281
+ 'x-tags': ['beta'],
1282
+ },
1283
+ },
1284
+ },
1285
+ };
1286
+
1287
+ const serviceNode = transformOasToServiceNode(apiDocument);
1288
+ expect(serviceNode ? computeTagGroups<SchemaNode>(serviceNode, NodeType.Model) : null).toEqual({
1289
+ groups: [
1290
+ {
1291
+ title: 'Beta',
1292
+ items: [
1293
+ {
1294
+ type: NodeType.Model,
1295
+ uri: '/schemas/b',
1296
+ data: {
1297
+ 'x-tags': ['beta'],
1298
+ },
1299
+ name: 'b',
1300
+ tags: ['beta'],
1301
+ },
1302
+ ],
1303
+ },
1304
+ {
1305
+ title: 'alpha',
1306
+ items: [
1307
+ {
1308
+ type: NodeType.Model,
1309
+ uri: '/schemas/a',
1310
+ data: {
1311
+ 'x-tags': ['alpha'],
1312
+ },
1313
+ name: 'a',
1314
+ tags: ['alpha'],
1315
+ },
1316
+ ],
1317
+ },
1318
+ ],
1319
+ ungrouped: [],
1320
+ });
1321
+ });
1322
+ });
1323
+ });