@rancher/shell 0.5.1 → 0.5.3

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (70) hide show
  1. package/assets/translations/en-us.yaml +8 -4
  2. package/components/ClusterIconMenu.vue +24 -9
  3. package/components/CodeMirror.vue +79 -18
  4. package/components/FixedBanner.vue +1 -0
  5. package/components/ResourceDetail/index.vue +1 -4
  6. package/components/ResourceYaml.vue +29 -5
  7. package/components/SideNav.vue +42 -64
  8. package/components/SortableTable/index.vue +1 -1
  9. package/components/YamlEditor.vue +1 -0
  10. package/components/__tests__/CodeMirror.spec.ts +99 -0
  11. package/components/form/BannerSettings.vue +3 -0
  12. package/components/form/FileSelector.vue +1 -0
  13. package/components/form/KeyValue.vue +1 -0
  14. package/components/formatter/WorkloadDetailEndpoints.vue +12 -22
  15. package/components/formatter/__tests__/WorkloadDetailEndpoints.test.ts +81 -0
  16. package/components/nav/Header.vue +1 -0
  17. package/components/nav/Jump.vue +19 -9
  18. package/components/nav/TopLevelMenu.vue +37 -15
  19. package/components/nav/Type.vue +15 -4
  20. package/components/nav/__tests__/TopLevelMenu.test.ts +1 -1
  21. package/components/nav/__tests__/Type.test.ts +30 -0
  22. package/core/types-provisioning.ts +7 -0
  23. package/detail/__tests__/provisioning.cattle.io.cluster.test.ts +77 -0
  24. package/detail/fleet.cattle.io.bundle.vue +1 -1
  25. package/detail/provisioning.cattle.io.cluster.vue +19 -4
  26. package/edit/management.cattle.io.setting.vue +1 -0
  27. package/edit/monitoring.coreos.com.alertmanagerconfig/types/opsgenie.vue +1 -1
  28. package/edit/monitoring.coreos.com.alertmanagerconfig/types/pagerduty.vue +1 -2
  29. package/edit/monitoring.coreos.com.alertmanagerconfig/types/slack.vue +1 -1
  30. package/edit/provisioning.cattle.io.cluster/index.vue +23 -10
  31. package/edit/provisioning.cattle.io.cluster/rke2.vue +22 -50
  32. package/edit/provisioning.cattle.io.cluster/tabs/Basics.vue +9 -11
  33. package/edit/provisioning.cattle.io.cluster/tabs/registries/RegistryConfigs.vue +3 -1
  34. package/edit/provisioning.cattle.io.cluster/tabs/registries/index.vue +3 -0
  35. package/edit/token.vue +1 -0
  36. package/list/catalog.cattle.io.app.vue +1 -0
  37. package/list/management.cattle.io.setting.vue +1 -0
  38. package/machine-config/amazonec2.vue +1 -0
  39. package/models/__tests__/provisioning.cattle.io.cluster.test.ts +151 -0
  40. package/models/__tests__/secret.test.ts +37 -0
  41. package/models/__tests__/storage.k8s.io.storageclass.test.ts +22 -0
  42. package/models/management.cattle.io.kontainerdriver.js +2 -1
  43. package/models/provisioning.cattle.io.cluster.js +36 -1
  44. package/models/secret.js +9 -0
  45. package/models/storage.k8s.io.storageclass.js +1 -1
  46. package/package.json +1 -1
  47. package/pages/c/_cluster/settings/DefaultLinksEditor.vue +1 -0
  48. package/pages/c/_cluster/settings/brand.vue +3 -0
  49. package/pages/c/_cluster/uiplugins/AddExtensionRepos.vue +4 -4
  50. package/pages/c/_cluster/uiplugins/SetupUIPlugins.vue +5 -2
  51. package/pages/c/_cluster/uiplugins/__tests__/AddExtensionRepos.test.ts +96 -0
  52. package/pages/c/_cluster/uiplugins/__tests__/SetupUIPlugins.test.ts +128 -0
  53. package/plugins/dashboard-store/__tests__/actions.test.ts +196 -111
  54. package/plugins/dashboard-store/actions.js +4 -6
  55. package/plugins/dashboard-store/getters.js +60 -2
  56. package/plugins/dashboard-store/resource-class.js +6 -2
  57. package/plugins/steve/__tests__/getters.spec.ts +10 -0
  58. package/plugins/steve/__tests__/resource-utils.test.ts +159 -0
  59. package/plugins/steve/actions.js +3 -37
  60. package/plugins/steve/getters.js +6 -0
  61. package/plugins/steve/resource-utils.ts +38 -0
  62. package/scripts/extension/parse-tag-name +3 -3
  63. package/store/__tests__/type-map.test.ts +1122 -0
  64. package/store/index.js +3 -2
  65. package/store/plugins.js +7 -6
  66. package/store/type-map.js +145 -75
  67. package/types/shell/index.d.ts +2 -0
  68. package/utils/__tests__/create-yaml.test.ts +10 -0
  69. package/utils/create-yaml.js +5 -1
  70. package/utils/object.js +10 -0
@@ -0,0 +1,1122 @@
1
+ /* eslint-disable jest/max-nested-describe */
2
+
3
+ import { TYPE_MODES, getters } from '../type-map';
4
+ import { NAME as EXPLORER } from '@shell/config/product/explorer';
5
+ import {
6
+ COUNT,
7
+ SCHEMA,
8
+ } from '@shell/config/types';
9
+
10
+ /**
11
+ * types in the store
12
+ */
13
+ const types = {
14
+ virtual: { name: 'virt' },
15
+ spoof: { name: 'spoof' }
16
+ };
17
+
18
+ const schemas = {
19
+ pod: {
20
+ id: 'pod',
21
+ type: SCHEMA,
22
+ attributes: { kind: 'pod' },
23
+ },
24
+ /**
25
+ * Represents a group
26
+ */
27
+ podNoAttributes: {
28
+ id: 'pod',
29
+ type: SCHEMA,
30
+ },
31
+ secret: {
32
+ id: 'secret',
33
+ type: SCHEMA,
34
+ attributes: { kind: 'secret' },
35
+ },
36
+ topLevel: {
37
+ id: 'toplevel',
38
+ type: SCHEMA,
39
+ }
40
+ };
41
+
42
+ /**
43
+ * counts in the store
44
+ */
45
+ const counts = {
46
+ pod: {
47
+ summary: { count: 1 },
48
+ revision: 'abc',
49
+ namespaces: { a: true }
50
+ },
51
+ toplevel: {
52
+ summary: { count: 1 },
53
+ revision: 'abc',
54
+ namespaces: { a: true }
55
+ },
56
+ secret: {
57
+ summary: { count: 1 },
58
+ revision: 'abc',
59
+ namespaces: { a: true }
60
+ }
61
+ };
62
+
63
+ /**
64
+ * Some of the objects that we expect to be returned by allTypes
65
+ */
66
+ const expectedMenuItems = {
67
+ podWithoutAttribute: {
68
+ label: 'Pod',
69
+ name: 'pod',
70
+ namespaced: true,
71
+ route: 'cde',
72
+ schema: schemas.podNoAttributes,
73
+ weight: 1,
74
+ },
75
+ podWithAttribute: {
76
+ label: 'Pod',
77
+ name: 'pod',
78
+ namespaced: true,
79
+ route: 'cde',
80
+ schema: schemas.pod,
81
+ weight: 1,
82
+ },
83
+ secretWithAttribute: {
84
+ label: 'Secret',
85
+ name: 'secret',
86
+ namespaced: true,
87
+ route: 'cde',
88
+ schema: schemas.secret,
89
+ weight: 1,
90
+ },
91
+ virtual: {
92
+ label: 'virt',
93
+ name: 'virt',
94
+ weight: 1,
95
+ },
96
+ spoof: {
97
+ label: 'spoof',
98
+ name: 'spoof',
99
+ weight: 1,
100
+ },
101
+ topLevel: {
102
+ label: 'Pod',
103
+ mode: 'basic',
104
+ name: 'toplevel',
105
+ namespaced: true,
106
+ route: 'cde',
107
+ schema: schemas.topLevel,
108
+ weight: 1,
109
+ }
110
+ };
111
+
112
+ describe('type-map', () => {
113
+ describe('getters', () => {
114
+ describe('allTypes', () => {
115
+ /**
116
+ * Stick in the required mode param to the expected menu items
117
+ */
118
+ const setTypeMode = (modes, resourcesById) => {
119
+ return modes.reduce((res, mode) => {
120
+ const newResource = { };
121
+
122
+ Object.entries(resourcesById).forEach(([id, resource]: [string, any]) => {
123
+ newResource[id] = {
124
+ ...resource,
125
+ mode,
126
+ };
127
+ });
128
+ res[mode] = newResource;
129
+
130
+ return res;
131
+ }, {});
132
+ };
133
+
134
+ /** All basic ctx properties and helpers */
135
+ const generateDefaults = (productName = EXPLORER, productStore = 'cluster', modes = [TYPE_MODES.BASIC]) => {
136
+ return {
137
+ productName,
138
+ productStore,
139
+
140
+ state: {
141
+ products: [{
142
+ name: EXPLORER,
143
+ inStore: productStore,
144
+ }],
145
+ virtualTypes: { [productName]: [] },
146
+ spoofedTypes: { [productName]: [] }
147
+ },
148
+ typeMapGetters: {
149
+ labelFor: (schema, count) => '',
150
+ optionsFor: (schema) => {},
151
+ groupForBasicType: () => {},
152
+ typeWeightFor: (label, isBasic) => 1
153
+ },
154
+ rootState: {},
155
+ rootGetters: {
156
+ [`${ productStore }/all`]: (schema: string) => {
157
+ return [];
158
+ },
159
+ 'prefs/get': (pref) => {},
160
+
161
+ },
162
+
163
+ modes
164
+ };
165
+ };
166
+
167
+ /**
168
+ * When there are no schema, spoofed or virtual types there's no menu types
169
+ */
170
+ it('empty', () => {
171
+ const {
172
+ state, typeMapGetters, rootState, rootGetters, productName, modes
173
+ } = generateDefaults();
174
+
175
+ const groups = getters.allTypes(state, typeMapGetters, rootState, rootGetters)(productName, modes);
176
+
177
+ expect(groups).toStrictEqual({});
178
+ });
179
+
180
+ describe('product: Explorer', () => {
181
+ /**
182
+ * Extend generateDefaults with env to return a pod type
183
+ */
184
+ const createEnvBasicPod = (modes = [TYPE_MODES.BASIC], expected = true) => {
185
+ const defaults = generateDefaults(EXPLORER, `cluster`, [TYPE_MODES.BASIC]);
186
+ const { typeMapGetters, rootGetters, productStore } = defaults;
187
+
188
+ const testRootGetters = {
189
+ ...rootGetters,
190
+ [`${ productStore }/all`]: (resource: string) => {
191
+ switch (resource) {
192
+ case SCHEMA:
193
+ return [schemas.pod];
194
+ case COUNT:
195
+ return [{ counts: { pod: counts.pod } }];
196
+ }
197
+
198
+ return [];
199
+ },
200
+ };
201
+
202
+ const testTypeMapGetters = {
203
+ ...typeMapGetters,
204
+ labelFor: (schema, count) => 'Pod',
205
+ groupForBasicType: () => true,
206
+ optionsFor: (schema) => ({
207
+ namespaced: true,
208
+ customRoute: 'cde'
209
+ }),
210
+ isFavorite: () => false,
211
+ };
212
+
213
+ return {
214
+ ...defaults,
215
+ typeMapGetters: testTypeMapGetters,
216
+ rootGetters: testRootGetters,
217
+
218
+ modes,
219
+
220
+ expectedTypes: expected ? setTypeMode(modes, { pod: expectedMenuItems.podWithAttribute }) : {}
221
+ };
222
+ };
223
+
224
+ /**
225
+ * Extend generateDefaults with env to return a virtual type
226
+ */
227
+ const createEnvBasicVirtual = (modes = [TYPE_MODES.BASIC], expected = true) => {
228
+ const defaults = generateDefaults();
229
+ const { state, typeMapGetters, productName } = defaults;
230
+
231
+ const testState = {
232
+ ...state,
233
+ virtualTypes: { [productName]: [types.virtual] }
234
+ };
235
+
236
+ const testTypeMapGetters = {
237
+ ...typeMapGetters,
238
+ groupForBasicType: () => true,
239
+ };
240
+
241
+ return {
242
+ ...defaults,
243
+ state: testState,
244
+ typeMapGetters: testTypeMapGetters,
245
+
246
+ modes,
247
+
248
+ expectedTypes: expected ? setTypeMode(modes, { virt: expectedMenuItems.virtual }) : {}
249
+ };
250
+ };
251
+
252
+ /**
253
+ * Extend generateDefaults with env to return a spoof type
254
+ */
255
+ const createEnvBasicSpoof = (modes = [TYPE_MODES.BASIC], expected = true) => {
256
+ const defaults = generateDefaults();
257
+ const { state, typeMapGetters, productName } = defaults;
258
+
259
+ const testState = {
260
+ ...state,
261
+ spoofedTypes: { [productName]: [types.spoof] }
262
+ };
263
+
264
+ const testTypeMapGetters = {
265
+ ...typeMapGetters,
266
+ groupForBasicType: () => true,
267
+ };
268
+
269
+ return {
270
+ ...defaults,
271
+ state: testState,
272
+ typeMapGetters: testTypeMapGetters,
273
+
274
+ modes,
275
+
276
+ expectedTypes: expected ? setTypeMode(modes, { spoof: expectedMenuItems.spoof }) : {}
277
+ };
278
+ };
279
+
280
+ describe('mode: BASIC', () => {
281
+ it('one entry', () => {
282
+ const {
283
+ state, typeMapGetters, rootState, rootGetters, productName, modes, expectedTypes
284
+ } = createEnvBasicPod();
285
+
286
+ const groups = getters.allTypes(state, typeMapGetters, rootState, rootGetters)(productName, modes);
287
+
288
+ expect(groups).toStrictEqual(expectedTypes);
289
+ });
290
+
291
+ it('one entry (explicitly test basic mode with a schema without `kind`)', () => {
292
+ // This is odd, but it should be clear that in basic mode schemas without a kind are ok)
293
+ const {
294
+ state, typeMapGetters, rootState, rootGetters, productName, modes, productStore
295
+ } = createEnvBasicPod();
296
+
297
+ const testRootGetters = {
298
+ ...rootGetters,
299
+ [`${ productStore }/all`]: (resource: string) => {
300
+ switch (resource) {
301
+ case SCHEMA:
302
+ return [schemas.podNoAttributes];
303
+ case COUNT:
304
+ return [{ counts: { pod: counts.pod } }];
305
+ }
306
+
307
+ return [];
308
+ },
309
+ };
310
+
311
+ const groups = getters.allTypes(state, typeMapGetters, rootState, testRootGetters)(productName, modes);
312
+
313
+ expect(groups).toStrictEqual(setTypeMode([TYPE_MODES.BASIC], { pod: expectedMenuItems.podWithoutAttribute }));
314
+ });
315
+
316
+ it('no entry (basic but no group)', () => {
317
+ const {
318
+ state, typeMapGetters, rootState, rootGetters, productName, modes, expectedTypes
319
+ } = createEnvBasicPod([TYPE_MODES.BASIC], false);
320
+
321
+ const testTypeMapGetters = {
322
+ ...typeMapGetters,
323
+ groupForBasicType: (product, id) => false
324
+ };
325
+
326
+ const groups = getters.allTypes(state, testTypeMapGetters, rootState, rootGetters)(productName, modes);
327
+
328
+ expect(groups).toStrictEqual(expectedTypes);
329
+ });
330
+
331
+ describe('virtual types', () => {
332
+ it('one entry', () => {
333
+ const {
334
+ state, typeMapGetters, rootState, rootGetters, productName, modes, expectedTypes
335
+ } = createEnvBasicVirtual();
336
+
337
+ const groups = getters.allTypes(state, typeMapGetters, rootState, rootGetters)(productName, modes);
338
+
339
+ expect(groups).toStrictEqual(expectedTypes);
340
+ });
341
+
342
+ it('no entry (group not basic)', () => {
343
+ const {
344
+ state, typeMapGetters, rootState, rootGetters, productName, modes, expectedTypes
345
+ } = createEnvBasicVirtual([TYPE_MODES.BASIC], false);
346
+
347
+ const testTypeMapGetters = {
348
+ ...typeMapGetters,
349
+ groupForBasicType: () => false,
350
+ };
351
+
352
+ const groups = getters.allTypes(state, testTypeMapGetters, rootState, rootGetters)(productName, modes);
353
+
354
+ expect(groups).toStrictEqual(expectedTypes);
355
+ });
356
+ });
357
+
358
+ describe('spoof types', () => {
359
+ it('one entry', () => {
360
+ const {
361
+ state, typeMapGetters, rootState, rootGetters, productName, modes, expectedTypes
362
+ } = createEnvBasicSpoof();
363
+
364
+ const groups = getters.allTypes(state, typeMapGetters, rootState, rootGetters)(productName, modes);
365
+
366
+ expect(groups).toStrictEqual(expectedTypes);
367
+ });
368
+
369
+ it('no entry (group not basic)', () => {
370
+ const {
371
+ state, typeMapGetters, rootState, rootGetters, productName, modes, expectedTypes
372
+ } = createEnvBasicSpoof([TYPE_MODES.BASIC], false);
373
+
374
+ const testTypeMapGetters = {
375
+ ...typeMapGetters,
376
+ groupForBasicType: () => false,
377
+ };
378
+
379
+ const groups = getters.allTypes(state, testTypeMapGetters, rootState, rootGetters)(productName, modes);
380
+
381
+ expect(groups).toStrictEqual(expectedTypes);
382
+ });
383
+ });
384
+ });
385
+
386
+ describe('mode: ALL', () => {
387
+ /**
388
+ * Extend createEnvBasicPod with env to return a pod type for mode TYPE_MODES.ALL
389
+ */
390
+ const createEnvAllPod = (expected = true) => {
391
+ const defaults = createEnvBasicPod([TYPE_MODES.ALL]);
392
+ const { rootGetters, productStore } = defaults;
393
+
394
+ const testRootGetters = {
395
+ ...rootGetters,
396
+ [`${ productStore }/all`]: (resource: string) => {
397
+ switch (resource) {
398
+ case SCHEMA:
399
+ return [schemas.pod];
400
+ case COUNT:
401
+ return [{ counts: { pod: counts.pod } }];
402
+ }
403
+
404
+ return [];
405
+ },
406
+ };
407
+
408
+ return {
409
+ ...defaults,
410
+ rootGetters: testRootGetters,
411
+
412
+ expectedTypes: expected ? setTypeMode([TYPE_MODES.ALL], { pod: expectedMenuItems.podWithAttribute }) : { }
413
+ };
414
+ };
415
+
416
+ /**
417
+ * Extend createEnvBasicVirtual with env to return a virtual type for mode TYPE_MODES.ALL
418
+ */
419
+ const createAllVirtualType = () => {
420
+ return createEnvBasicVirtual([TYPE_MODES.ALL]);
421
+ };
422
+
423
+ /**
424
+ * Extend createEnvBasicSpoof with env to return a spoof type for mode TYPE_MODES.ALL
425
+ */
426
+ const createAllSpoofedType = () => {
427
+ return createEnvBasicSpoof([TYPE_MODES.ALL]);
428
+ };
429
+
430
+ it('one entry', () => {
431
+ const {
432
+ state, typeMapGetters, rootState, rootGetters, productName, modes, expectedTypes
433
+ } = createEnvAllPod();
434
+
435
+ const groups = getters.allTypes(state, typeMapGetters, rootState, rootGetters)(productName, modes);
436
+
437
+ expect(groups).toStrictEqual(expectedTypes);
438
+ });
439
+
440
+ it('no entry (schema without a kind)', () => {
441
+ const {
442
+ state, typeMapGetters, productStore, rootGetters, productName, modes, rootState, expectedTypes
443
+ } = createEnvAllPod(false);
444
+
445
+ const testRootGetters = {
446
+ ...rootGetters,
447
+ [`${ productStore }/all`]: (resource: string) => {
448
+ switch (resource) {
449
+ case SCHEMA:
450
+ return [schemas.podNoAttributes];
451
+ case COUNT:
452
+ return [{ counts: { pod: counts.pod } }];
453
+ }
454
+
455
+ return [];
456
+ },
457
+ };
458
+
459
+ const groups = getters.allTypes(state, typeMapGetters, rootState, testRootGetters)(productName, modes);
460
+
461
+ expect(groups).toStrictEqual(expectedTypes);
462
+ });
463
+
464
+ it('no entry (needs rancher cluster)', () => {
465
+ const {
466
+ state, typeMapGetters, rootGetters, productName, modes, rootState, expectedTypes
467
+ } = createEnvAllPod(false);
468
+
469
+ const testRootGetters = {
470
+ ...rootGetters,
471
+ isRancher: false
472
+ };
473
+
474
+ const testTypeMapGetters = {
475
+ ...typeMapGetters,
476
+ optionsFor: (schema) => ({
477
+ namespaced: true,
478
+ customRoute: 'cde',
479
+ ifRancherCluster: true
480
+ }),
481
+ };
482
+
483
+ const groups = getters.allTypes(state, testTypeMapGetters, rootState, testRootGetters)(productName, modes);
484
+
485
+ expect(groups).toStrictEqual(expectedTypes);
486
+ });
487
+
488
+ it('no entry (shouldn\'t be rancher cluster)', () => {
489
+ const {
490
+ state, typeMapGetters, rootGetters, productName, modes, rootState, expectedTypes
491
+ } = createEnvAllPod(false);
492
+
493
+ const testRootGetters = {
494
+ ...rootGetters,
495
+ isRancher: true
496
+ };
497
+
498
+ const testTypeMapGetters = {
499
+ ...typeMapGetters,
500
+ optionsFor: (schema) => ({
501
+ namespaced: true,
502
+ customRoute: 'cde',
503
+ ifRancherCluster: false
504
+ }),
505
+ };
506
+
507
+ const groups = getters.allTypes(state, testTypeMapGetters, rootState, testRootGetters)(productName, modes);
508
+
509
+ expect(groups).toStrictEqual(expectedTypes);
510
+ });
511
+
512
+ it('one entry (needs rancher cluster)', () => {
513
+ const {
514
+ state, typeMapGetters, rootGetters, productName, modes, rootState, expectedTypes
515
+ } = createEnvAllPod();
516
+
517
+ const testRootGetters = {
518
+ ...rootGetters,
519
+ isRancher: true
520
+ };
521
+
522
+ const testTypeMapGetters = {
523
+ ...typeMapGetters,
524
+ optionsFor: (schema) => ({
525
+ namespaced: true,
526
+ customRoute: 'cde',
527
+ ifRancherCluster: true
528
+ }),
529
+ };
530
+
531
+ const groups = getters.allTypes(state, testTypeMapGetters, rootState, testRootGetters)(productName, modes);
532
+
533
+ expect(groups).toStrictEqual(expectedTypes);
534
+ });
535
+
536
+ it('no entry (local only)', () => {
537
+ const {
538
+ state, typeMapGetters, rootGetters, productName, modes, rootState, expectedTypes
539
+ } = createEnvAllPod(false);
540
+
541
+ const testRootGetters = {
542
+ ...rootGetters,
543
+ currentCluster: { isLocal: false }
544
+ };
545
+
546
+ const testTypeMapGetters = {
547
+ ...typeMapGetters,
548
+ optionsFor: (schema) => ({
549
+ namespaced: true,
550
+ customRoute: 'cde',
551
+ localOnly: true
552
+ }),
553
+ };
554
+
555
+ const groups = getters.allTypes(state, testTypeMapGetters, rootState, testRootGetters)(productName, modes);
556
+
557
+ expect(groups).toStrictEqual(expectedTypes);
558
+ });
559
+
560
+ it('one entry (local only)', () => {
561
+ const {
562
+ state, typeMapGetters, rootGetters, productName, modes, rootState, expectedTypes
563
+ } = createEnvAllPod();
564
+
565
+ const testRootGetters = {
566
+ ...rootGetters,
567
+ currentCluster: { isLocal: true }
568
+ };
569
+
570
+ const testTypeMapGetters = {
571
+ ...typeMapGetters,
572
+ optionsFor: (schema) => ({
573
+ namespaced: true,
574
+ customRoute: 'cde',
575
+ localOnly: true
576
+ }),
577
+ };
578
+
579
+ const groups = getters.allTypes(state, testTypeMapGetters, rootState, testRootGetters)(productName, modes);
580
+
581
+ expect(groups).toStrictEqual(expectedTypes);
582
+ });
583
+
584
+ describe('virtual types', () => {
585
+ it('one entry', () => {
586
+ const {
587
+ state, typeMapGetters, rootState, rootGetters, productName, modes, expectedTypes
588
+ } = createAllVirtualType();
589
+
590
+ const groups = getters.allTypes(state, typeMapGetters, rootState, rootGetters)(productName, modes);
591
+
592
+ expect(groups).toStrictEqual(expectedTypes);
593
+ });
594
+ });
595
+
596
+ describe('spoof types', () => {
597
+ it('one entry', () => {
598
+ const {
599
+ state, typeMapGetters, rootState, rootGetters, productName, modes, expectedTypes
600
+ } = createAllSpoofedType();
601
+
602
+ const groups = getters.allTypes(state, typeMapGetters, rootState, rootGetters)(productName, modes);
603
+
604
+ expect(groups).toStrictEqual(expectedTypes);
605
+ });
606
+ });
607
+ });
608
+
609
+ describe('mode: FAVORITE', () => {
610
+ /**
611
+ * Extend generateDefaults with env to return a pod type for mode TYPE_MODES.FAVORITE
612
+ */
613
+ const generateDefaultsForFavourite = (expected = true) => {
614
+ const defaults = generateDefaults();
615
+ const { typeMapGetters, rootGetters, productStore } = defaults;
616
+
617
+ const testRootGetters = {
618
+ ...rootGetters,
619
+ [`${ productStore }/all`]: (resource: string) => {
620
+ switch (resource) {
621
+ case SCHEMA:
622
+ return [schemas.secret];
623
+ case COUNT:
624
+ return [{ counts: { secret: counts.secret } }];
625
+ }
626
+
627
+ return [];
628
+ },
629
+ };
630
+
631
+ const testTypeMapGetters = {
632
+ ...typeMapGetters,
633
+ labelFor: (schema, count) => 'Secret',
634
+ groupForBasicType: () => true,
635
+ optionsFor: (schema) => ({
636
+ namespaced: true,
637
+ customRoute: 'cde'
638
+ }),
639
+ isFavorite: () => true,
640
+ };
641
+
642
+ return {
643
+ ...defaults,
644
+ modes: [TYPE_MODES.FAVORITE],
645
+ typeMapGetters: testTypeMapGetters,
646
+ rootGetters: testRootGetters,
647
+
648
+ expectedTypes: expected ? setTypeMode([TYPE_MODES.FAVORITE], { secret: expectedMenuItems.secretWithAttribute }) : {}
649
+ };
650
+ };
651
+
652
+ /**
653
+ * Extend generateDefaultsForFavourite with env to return a virtual type for mode TYPE_MODES.FAVORITE
654
+ */
655
+ const createDefaultsForFavouriteVirtualType = (expected = true) => {
656
+ const defaults = generateDefaults();
657
+ const defaultsFavourites = generateDefaultsForFavourite();
658
+ const { state, productName } = defaultsFavourites;
659
+
660
+ const testState = {
661
+ ...state,
662
+ virtualTypes: { [productName]: [types.virtual] }
663
+ };
664
+
665
+ return {
666
+ ...defaultsFavourites,
667
+ state: testState,
668
+ rootGetters: defaults.rootGetters,
669
+
670
+ expectedTypes: expected ? setTypeMode([TYPE_MODES.FAVORITE], { virt: expectedMenuItems.virtual }) : {}
671
+ };
672
+ };
673
+
674
+ /**
675
+ * Extend generateDefaultsForFavourite with env to return a spoof type for mode TYPE_MODES.FAVORITE
676
+ */
677
+ const createDefaultsForFavouriteSpoofType = (expected = true) => {
678
+ const defaults = generateDefaults();
679
+ const defaultsFavourites = generateDefaultsForFavourite();
680
+ const { state, productName } = defaultsFavourites;
681
+
682
+ const testState = {
683
+ ...state,
684
+ spoofedTypes: { [productName]: [types.spoof] }
685
+ };
686
+
687
+ return {
688
+ ...defaultsFavourites,
689
+ state: testState,
690
+ rootGetters: defaults.rootGetters,
691
+
692
+ expectedTypes: expected ? setTypeMode([TYPE_MODES.FAVORITE], { spoof: expectedMenuItems.spoof }) : {}
693
+ };
694
+ };
695
+
696
+ it('one entry', () => {
697
+ const {
698
+ state, typeMapGetters, rootState, rootGetters, productName, modes, expectedTypes
699
+ } = generateDefaultsForFavourite();
700
+
701
+ const groups = getters.allTypes(state, typeMapGetters, rootState, rootGetters)(productName, modes);
702
+
703
+ expect(groups).toStrictEqual(expectedTypes);
704
+ });
705
+
706
+ it('no entry (not favourite)', () => {
707
+ const {
708
+ state, typeMapGetters, rootState, rootGetters, productName, modes, expectedTypes
709
+ } = generateDefaultsForFavourite(false);
710
+
711
+ const testTypeMapGetters = {
712
+ ...typeMapGetters,
713
+ isFavorite: () => false,
714
+ };
715
+
716
+ const groups = getters.allTypes(state, testTypeMapGetters, rootState, rootGetters)(productName, modes);
717
+
718
+ expect(groups).toStrictEqual(expectedTypes);
719
+ });
720
+
721
+ describe('virtual types', () => {
722
+ it('one entry', () => {
723
+ const {
724
+ state, typeMapGetters, rootState, rootGetters, productName, modes, expectedTypes
725
+ } = createDefaultsForFavouriteVirtualType();
726
+
727
+ const groups = getters.allTypes(state, typeMapGetters, rootState, rootGetters)(productName, modes);
728
+
729
+ expect(groups).toStrictEqual(expectedTypes);
730
+ });
731
+
732
+ it('no entry (not favourite)', () => {
733
+ const expectedGroups = { };
734
+
735
+ const {
736
+ state, typeMapGetters, rootState, rootGetters, productName, modes
737
+ } = createDefaultsForFavouriteVirtualType();
738
+
739
+ const testTypeMapGetters = {
740
+ ...typeMapGetters,
741
+ isFavorite: () => false,
742
+ };
743
+
744
+ const groups = getters.allTypes(state, testTypeMapGetters, rootState, rootGetters)(productName, modes);
745
+
746
+ expect(groups).toStrictEqual(expectedGroups);
747
+ });
748
+ });
749
+
750
+ describe('spoof types', () => {
751
+ it('one entry', () => {
752
+ const {
753
+ state, typeMapGetters, rootState, rootGetters, productName, modes, expectedTypes
754
+ } = createDefaultsForFavouriteSpoofType();
755
+
756
+ const groups = getters.allTypes(state, typeMapGetters, rootState, rootGetters)(productName, modes);
757
+
758
+ expect(groups).toStrictEqual(expectedTypes);
759
+ });
760
+
761
+ it('no entry (not favourite)', () => {
762
+ const {
763
+ state, typeMapGetters, rootState, rootGetters, productName, modes, expectedTypes
764
+ } = createDefaultsForFavouriteSpoofType(false);
765
+
766
+ const testTypeMapGetters = {
767
+ ...typeMapGetters,
768
+ isFavorite: () => false,
769
+ };
770
+
771
+ const groups = getters.allTypes(state, testTypeMapGetters, rootState, rootGetters)(productName, modes);
772
+
773
+ expect(groups).toStrictEqual(expectedTypes);
774
+ });
775
+ });
776
+ });
777
+
778
+ describe('mode: USED', () => {
779
+ /**
780
+ * Extend createEnvBasicPod with env to return a pod for mode TYPE_MODES.USED
781
+ */
782
+ const createUsedPod = () => {
783
+ const defaults = createEnvBasicPod([TYPE_MODES.USED]);
784
+ const { rootGetters, productStore } = defaults;
785
+
786
+ const testRootGetters = {
787
+ ...rootGetters,
788
+ [`${ productStore }/all`]: (resource: string) => {
789
+ switch (resource) {
790
+ case SCHEMA:
791
+ return [schemas.pod];
792
+ case COUNT:
793
+ return [{ counts: { pod: counts.pod } }];
794
+ }
795
+
796
+ return [];
797
+ },
798
+ };
799
+
800
+ return {
801
+ ...defaults,
802
+ rootGetters: testRootGetters
803
+ };
804
+ };
805
+
806
+ it('one entry', () => {
807
+ const expectedGroups = setTypeMode([TYPE_MODES.USED], { pod: expectedMenuItems.podWithAttribute });
808
+
809
+ const {
810
+ state, typeMapGetters, rootState, rootGetters, productName, modes
811
+ } = createUsedPod();
812
+
813
+ const groups = getters.allTypes(state, typeMapGetters, rootState, rootGetters)(productName, modes);
814
+
815
+ expect(groups).toStrictEqual(expectedGroups);
816
+ });
817
+
818
+ describe('virtual types', () => {
819
+ it('no entry (used not included)', () => {
820
+ const expectedGroups = { };
821
+
822
+ const {
823
+ state, typeMapGetters, rootState, rootGetters, productName
824
+ } = createEnvBasicVirtual();
825
+
826
+ const groups = getters.allTypes(state, typeMapGetters, rootState, rootGetters)(productName, [TYPE_MODES.USED]);
827
+
828
+ expect(groups).toStrictEqual(expectedGroups);
829
+ });
830
+ });
831
+
832
+ describe('spoof types', () => {
833
+ it('no entry (used not included)', () => {
834
+ const expectedGroups = { };
835
+
836
+ const {
837
+ state, typeMapGetters, rootState, rootGetters, productName
838
+ } = createEnvBasicSpoof();
839
+
840
+ const groups = getters.allTypes(state, typeMapGetters, rootState, rootGetters)(productName, [TYPE_MODES.USED]);
841
+
842
+ expect(groups).toStrictEqual(expectedGroups);
843
+ });
844
+ });
845
+ });
846
+
847
+ describe('mode: multiple', () => {
848
+ // Covers getProductsGroups use cases
849
+ const modes = [TYPE_MODES.BASIC, TYPE_MODES.FAVORITE, TYPE_MODES.USED];
850
+
851
+ const createAllOfTheThings = () => {
852
+ const defaults = generateDefaults(EXPLORER, 'cluster', modes);
853
+ const {
854
+ state, typeMapGetters, rootGetters, productName, productStore
855
+ } = defaults;
856
+
857
+ const testState = {
858
+ ...state,
859
+ virtualTypes: { [productName]: [types.virtual] },
860
+ spoofedTypes: { [productName]: [types.spoof] }
861
+ };
862
+
863
+ const testRootGetters = {
864
+ ...rootGetters,
865
+ [`${ productStore }/all`]: (resource: string) => {
866
+ switch (resource) {
867
+ case SCHEMA:
868
+ return [schemas.topLevel, schemas.pod, schemas.secret];
869
+ case COUNT:
870
+ return [{
871
+ counts: {
872
+ toplevel: counts.toplevel,
873
+ pod: counts.pod,
874
+ secret: counts.secret
875
+ }
876
+ }];
877
+ }
878
+
879
+ return [];
880
+ },
881
+ };
882
+
883
+ const testTypeMapGetters = {
884
+ ...typeMapGetters,
885
+ labelFor: (schema, count) => {
886
+ switch (schema.id) {
887
+ case 'secret':
888
+ return 'Secret';
889
+ default:
890
+ return 'Pod';
891
+ }
892
+ },
893
+ groupForBasicType: () => true,
894
+ optionsFor: (schema) => ({
895
+ namespaced: true,
896
+ customRoute: 'cde'
897
+ }),
898
+ isFavorite: (id) => id === 'secret',
899
+ };
900
+
901
+ return {
902
+ ...defaults,
903
+ typeMapGetters: testTypeMapGetters,
904
+ rootGetters: testRootGetters,
905
+ state: testState,
906
+
907
+ modes,
908
+ expectedTypes: {
909
+ ...setTypeMode([TYPE_MODES.BASIC], {
910
+ // A resource that's favourite should still appear in the basic side nav
911
+ // fav: {
912
+ secret: expectedMenuItems.secretWithAttribute,
913
+
914
+ // A basic resource
915
+ pod: expectedMenuItems.podWithAttribute,
916
+
917
+ // A top level resource with an invalid schema (no kind)
918
+ toplevel: expectedMenuItems.topLevel,
919
+
920
+ virt: expectedMenuItems.virtual,
921
+
922
+ spoof: expectedMenuItems.spoof
923
+ }),
924
+ ...setTypeMode([TYPE_MODES.FAVORITE], { secret: expectedMenuItems.secretWithAttribute }),
925
+ ...setTypeMode([TYPE_MODES.USED], {
926
+ // A resource that's favourite should still appear in the basic side nav
927
+ secret: expectedMenuItems.secretWithAttribute,
928
+ // A basic resource
929
+ pod: expectedMenuItems.podWithAttribute,
930
+ }),
931
+ }
932
+ };
933
+ };
934
+
935
+ it('no entries', () => {
936
+ const {
937
+ state, typeMapGetters, rootState, rootGetters, productName
938
+ } = generateDefaults(EXPLORER, 'cluster', modes);
939
+
940
+ const groups = getters.allTypes(state, typeMapGetters, rootState, rootGetters)(productName, modes);
941
+
942
+ expect(groups).toStrictEqual({});
943
+ });
944
+
945
+ it('one entry each', () => {
946
+ const {
947
+ state, typeMapGetters, rootState, rootGetters, productName, expectedTypes
948
+ } = createAllOfTheThings();
949
+
950
+ const groups = getters.allTypes(state, typeMapGetters, rootState, rootGetters)(productName, modes);
951
+
952
+ expect(groups).toStrictEqual(expectedTypes);
953
+ });
954
+
955
+ it('limited basic type', () => {
956
+ const {
957
+ state, typeMapGetters, rootState, rootGetters, productName, productStore
958
+ } = createAllOfTheThings();
959
+
960
+ const testState = {
961
+ ...state,
962
+ virtualTypes: { },
963
+ spoofedTypes: { }
964
+ };
965
+
966
+ const testRootGetters = {
967
+ ...rootGetters,
968
+ [`${ productStore }/all`]: (resource: string) => {
969
+ switch (resource) {
970
+ case SCHEMA:
971
+ return [schemas.secret];
972
+ case COUNT:
973
+ return [{ counts: { secret: counts.secret } }];
974
+ }
975
+
976
+ return [];
977
+ },
978
+ };
979
+
980
+ const testExpectedTypes = {
981
+ ...setTypeMode([TYPE_MODES.BASIC], { secret: expectedMenuItems.secretWithAttribute }),
982
+ ...setTypeMode([TYPE_MODES.FAVORITE], { secret: expectedMenuItems.secretWithAttribute }),
983
+ ...setTypeMode([TYPE_MODES.USED], { secret: expectedMenuItems.secretWithAttribute }),
984
+ };
985
+
986
+ const groups = getters.allTypes(testState, typeMapGetters, rootState, testRootGetters)(productName, modes);
987
+
988
+ expect(groups).toStrictEqual(testExpectedTypes);
989
+ });
990
+
991
+ it('no favourite type', () => {
992
+ const {
993
+ state, typeMapGetters, rootState, rootGetters, productName, productStore
994
+ } = createAllOfTheThings();
995
+
996
+ const testRootGetters = {
997
+ ...rootGetters,
998
+ [`${ productStore }/all`]: (resource: string) => {
999
+ switch (resource) {
1000
+ case SCHEMA:
1001
+ return [schemas.topLevel, schemas.pod];
1002
+ case COUNT:
1003
+ return [{
1004
+ counts: {
1005
+ toplevel: counts.toplevel,
1006
+ pod: counts.pod,
1007
+ }
1008
+ }];
1009
+ }
1010
+
1011
+ return [];
1012
+ },
1013
+ };
1014
+
1015
+ const testExpectedTypes = {
1016
+ ...setTypeMode([TYPE_MODES.BASIC], {
1017
+ // A basic resource
1018
+ pod: expectedMenuItems.podWithAttribute,
1019
+
1020
+ // A top level resource with an invalid schema (no kind)
1021
+ toplevel: expectedMenuItems.topLevel,
1022
+
1023
+ virt: expectedMenuItems.virtual,
1024
+
1025
+ spoof: expectedMenuItems.spoof
1026
+ }),
1027
+ ...setTypeMode([TYPE_MODES.USED], {
1028
+ // A basic resource
1029
+ pod: expectedMenuItems.podWithAttribute,
1030
+ }),
1031
+ };
1032
+
1033
+ const groups = getters.allTypes(state, typeMapGetters, rootState, testRootGetters)(productName, modes);
1034
+
1035
+ expect(groups).toStrictEqual(testExpectedTypes);
1036
+ });
1037
+
1038
+ it('no used type / no virtual type', () => {
1039
+ const {
1040
+ state, typeMapGetters, rootState, rootGetters, productName
1041
+ } = createAllOfTheThings();
1042
+
1043
+ const testState = {
1044
+ ...state,
1045
+ spoofedTypes: { [productName]: [types.spoof] },
1046
+ virtualTypes: { [productName]: [] },
1047
+ };
1048
+
1049
+ const testExpectedTypes = {
1050
+ ...setTypeMode([TYPE_MODES.BASIC], {
1051
+ // A resource that's favourite should still appear in the basic side nav
1052
+ // fav: {
1053
+ secret: expectedMenuItems.secretWithAttribute,
1054
+
1055
+ // A basic resource
1056
+ pod: expectedMenuItems.podWithAttribute,
1057
+
1058
+ // A top level resource with an invalid schema (no kind)
1059
+ toplevel: expectedMenuItems.topLevel,
1060
+
1061
+ spoof: expectedMenuItems.spoof
1062
+ }),
1063
+ ...setTypeMode([TYPE_MODES.FAVORITE], { secret: expectedMenuItems.secretWithAttribute }),
1064
+ ...setTypeMode([TYPE_MODES.USED], {
1065
+ // A resource that's favourite should still appear in the basic side nav
1066
+ secret: expectedMenuItems.secretWithAttribute,
1067
+ // A basic resource
1068
+ pod: expectedMenuItems.podWithAttribute,
1069
+ }),
1070
+ };
1071
+
1072
+ const groups = getters.allTypes(testState, typeMapGetters, rootState, rootGetters)(productName, modes);
1073
+
1074
+ expect(groups).toStrictEqual(testExpectedTypes);
1075
+ });
1076
+
1077
+ it('no used type / no spoofed type', () => {
1078
+ const {
1079
+ state, typeMapGetters, rootState, rootGetters, productName
1080
+ } = createAllOfTheThings();
1081
+
1082
+ const testState = {
1083
+ ...state,
1084
+ spoofedTypes: { [productName]: [] },
1085
+ virtualTypes: { [productName]: [types.virtual] },
1086
+ };
1087
+
1088
+ const testExpectedTypes = {
1089
+ ...setTypeMode([TYPE_MODES.BASIC], {
1090
+ // A resource that's favourite should still appear in the basic side nav
1091
+ // fav: {
1092
+ secret: expectedMenuItems.secretWithAttribute,
1093
+
1094
+ // A basic resource
1095
+ pod: expectedMenuItems.podWithAttribute,
1096
+
1097
+ // A top level resource with an invalid schema (no kind)
1098
+ toplevel: expectedMenuItems.topLevel,
1099
+
1100
+ virt: expectedMenuItems.virtual,
1101
+
1102
+ }),
1103
+ ...setTypeMode([TYPE_MODES.FAVORITE], { secret: expectedMenuItems.secretWithAttribute }),
1104
+ ...setTypeMode([TYPE_MODES.USED], {
1105
+ // A resource that's favourite should still appear in the basic side nav
1106
+ secret: expectedMenuItems.secretWithAttribute,
1107
+ // A basic resource
1108
+ pod: expectedMenuItems.podWithAttribute,
1109
+ }),
1110
+ };
1111
+
1112
+ const groups = getters.allTypes(testState, typeMapGetters, rootState, rootGetters)(productName, modes);
1113
+
1114
+ expect(groups).toStrictEqual(testExpectedTypes);
1115
+ });
1116
+ });
1117
+ });
1118
+ });
1119
+ });
1120
+ });
1121
+
1122
+ // getTree - Remove ignored schemas, not-applicable to ns filter