@rancher/shell 3.0.8-rc.9 → 3.0.8

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 (146) hide show
  1. package/apis/impl/apis.ts +61 -0
  2. package/apis/index.ts +40 -0
  3. package/apis/intf/modal.ts +90 -0
  4. package/apis/intf/shell.ts +36 -0
  5. package/apis/intf/slide-in.ts +98 -0
  6. package/apis/intf/system.ts +41 -0
  7. package/apis/shell/__tests__/modal.test.ts +80 -0
  8. package/apis/shell/__tests__/notifications.test.ts +71 -0
  9. package/apis/shell/__tests__/slide-in.test.ts +54 -0
  10. package/apis/shell/__tests__/system.test.ts +129 -0
  11. package/apis/shell/index.ts +38 -0
  12. package/apis/shell/modal.ts +41 -0
  13. package/apis/shell/notifications.ts +65 -0
  14. package/apis/shell/slide-in.ts +33 -0
  15. package/apis/shell/system.ts +65 -0
  16. package/apis/vue-shim.d.ts +11 -0
  17. package/assets/styles/global/_tooltip.scss +6 -1
  18. package/assets/translations/en-us.yaml +5 -0
  19. package/components/ActionMenuShell.vue +3 -1
  20. package/components/CruResource.vue +8 -1
  21. package/components/Drawer/ResourceDetailDrawer/__tests__/composables.test.ts +50 -1
  22. package/components/Drawer/ResourceDetailDrawer/composables.ts +19 -0
  23. package/components/Drawer/ResourceDetailDrawer/index.vue +3 -1
  24. package/components/LocaleSelector.vue +2 -2
  25. package/components/ModalManager.vue +11 -1
  26. package/components/Questions/__tests__/Yaml.test.ts +1 -1
  27. package/components/RelatedResources.vue +5 -0
  28. package/components/Resource/Detail/ResourcePopover/index.vue +5 -1
  29. package/components/ResourceDetail/Masthead/latest.vue +23 -21
  30. package/components/ResourceDetail/index.vue +3 -0
  31. package/components/ResourceTable.vue +54 -21
  32. package/components/SlideInPanelManager.vue +16 -11
  33. package/components/SortableTable/THead.vue +2 -1
  34. package/components/SortableTable/index.vue +20 -2
  35. package/components/Tabbed/index.vue +37 -2
  36. package/components/__tests__/NamespaceFilter.test.ts +49 -0
  37. package/components/auth/SelectPrincipal.vue +4 -0
  38. package/components/auth/login/ldap.vue +3 -3
  39. package/components/fleet/FleetSecretSelector.vue +1 -1
  40. package/components/form/KeyValue.vue +1 -1
  41. package/components/form/NameNsDescription.vue +1 -1
  42. package/components/form/NodeScheduling.vue +2 -2
  43. package/components/form/ResourceTabs/composable.ts +2 -2
  44. package/components/form/ResourceTabs/index.vue +0 -2
  45. package/components/form/__tests__/NameNsDescription.test.ts +42 -0
  46. package/components/formatter/LinkName.vue +5 -0
  47. package/components/nav/Group.vue +25 -7
  48. package/components/nav/Header.vue +1 -1
  49. package/components/nav/NamespaceFilter.vue +1 -0
  50. package/components/nav/Type.vue +17 -6
  51. package/components/nav/WindowManager/panels/TabBodyContainer.vue +1 -1
  52. package/components/nav/__tests__/Type.test.ts +59 -0
  53. package/composables/cruResource.ts +27 -0
  54. package/composables/focusTrap.ts +3 -1
  55. package/composables/resourceDetail.ts +15 -0
  56. package/composables/useLabeledFormElement.ts +3 -4
  57. package/config/product/fleet.js +1 -1
  58. package/config/router/navigation-guards/clusters.js +3 -3
  59. package/config/router/navigation-guards/products.js +1 -1
  60. package/config/router/routes.js +1 -5
  61. package/core/__tests__/extension-manager-impl.test.js +437 -0
  62. package/core/extension-manager-impl.js +6 -27
  63. package/core/plugin-helpers.ts +2 -2
  64. package/core/plugin.ts +9 -1
  65. package/core/plugins-loader.js +2 -2
  66. package/core/types-provisioning.ts +4 -0
  67. package/core/types.ts +35 -0
  68. package/detail/provisioning.cattle.io.cluster.vue +8 -6
  69. package/dialog/DeveloperLoadExtensionDialog.vue +1 -1
  70. package/dialog/MoveNamespaceDialog.vue +20 -4
  71. package/dialog/SearchDialog.vue +1 -0
  72. package/dialog/__tests__/MoveNamespaceDialog.test.ts +249 -0
  73. package/directives/__tests__/clean-tooltip.test.ts +298 -0
  74. package/directives/clean-tooltip.ts +234 -0
  75. package/edit/__tests__/fleet.cattle.io.gitrepo.test.ts +2 -2
  76. package/edit/__tests__/fleet.cattle.io.helmop.test.ts +98 -1
  77. package/edit/fleet.cattle.io.helmop.vue +5 -0
  78. package/edit/provisioning.cattle.io.cluster/__tests__/rke2.test.ts +21 -21
  79. package/edit/provisioning.cattle.io.cluster/index.vue +5 -5
  80. package/edit/provisioning.cattle.io.cluster/rke2.vue +8 -8
  81. package/edit/resources.cattle.io.restore.vue +1 -1
  82. package/edit/workload/Job.vue +2 -2
  83. package/edit/workload/index.vue +1 -1
  84. package/initialize/install-plugins.js +4 -5
  85. package/machine-config/azure.vue +1 -1
  86. package/machine-config/components/GCEImage.vue +1 -1
  87. package/models/__tests__/provisioning.cattle.io.cluster.test.ts +16 -0
  88. package/models/chart.js +70 -74
  89. package/models/management.cattle.io.cluster.js +1 -1
  90. package/models/provisioning.cattle.io.cluster.js +11 -3
  91. package/package.json +7 -7
  92. package/pages/auth/login.vue +3 -3
  93. package/pages/auth/setup.vue +1 -1
  94. package/pages/auth/verify.vue +3 -3
  95. package/pages/c/_cluster/apps/charts/index.vue +122 -24
  96. package/pages/c/_cluster/apps/charts/install.vue +33 -0
  97. package/pages/c/_cluster/explorer/__tests__/index.test.ts +1 -1
  98. package/pages/c/_cluster/fleet/index.vue +4 -7
  99. package/pages/c/_cluster/settings/index.vue +5 -0
  100. package/pkg/auto-import.js +3 -3
  101. package/pkg/dynamic-importer.lib.js +1 -1
  102. package/pkg/import.js +1 -1
  103. package/plugins/__tests__/mutations.tests.ts +179 -0
  104. package/plugins/dashboard-store/getters.js +1 -1
  105. package/plugins/dashboard-store/model-loader.js +1 -1
  106. package/plugins/dashboard-store/mutations.js +23 -2
  107. package/plugins/dashboard-store/resource-class.js +8 -3
  108. package/plugins/plugin.js +2 -2
  109. package/plugins/steve/__tests__/steve-pagination-utils.test.ts +301 -128
  110. package/plugins/steve/steve-class.js +1 -1
  111. package/plugins/steve/steve-pagination-utils.ts +108 -43
  112. package/rancher-components/Form/Checkbox/Checkbox.vue +1 -1
  113. package/rancher-components/Form/LabeledInput/LabeledInput.vue +1 -1
  114. package/rancher-components/RcDropdown/useDropdownContext.ts +2 -4
  115. package/rancher-components/RcItemCard/RcItemCard.vue +1 -1
  116. package/scripts/publish-shell.sh +25 -0
  117. package/store/__tests__/catalog.test.ts +1 -1
  118. package/store/__tests__/type-map.test.ts +164 -2
  119. package/store/auth.js +23 -11
  120. package/store/i18n.js +3 -3
  121. package/store/index.js +5 -3
  122. package/store/notifications.ts +2 -0
  123. package/store/prefs.js +2 -2
  124. package/store/type-map.js +17 -7
  125. package/types/internal-api/shell/modal.d.ts +6 -6
  126. package/types/notifications/index.ts +126 -15
  127. package/types/rancher/index.d.ts +9 -0
  128. package/types/shell/index.d.ts +16 -1
  129. package/types/vue-shim.d.ts +5 -4
  130. package/utils/__tests__/router.test.js +238 -0
  131. package/utils/cluster.js +4 -1
  132. package/utils/fleet.ts +8 -1
  133. package/utils/pagination-utils.ts +2 -2
  134. package/utils/pagination-wrapper.ts +1 -1
  135. package/utils/router.js +50 -0
  136. package/utils/unit-tests/pagination-utils.spec.ts +8 -8
  137. package/vue.config.js +3 -3
  138. package/composables/useExtensionManager.ts +0 -17
  139. package/core/__test__/extension-manager-impl.test.js +0 -236
  140. package/core/plugins.js +0 -38
  141. package/directives/clean-tooltip.js +0 -32
  142. package/plugins/internal-api/index.ts +0 -37
  143. package/plugins/internal-api/shared/base-api.ts +0 -13
  144. package/plugins/internal-api/shell/shell.api.ts +0 -108
  145. package/types/internal-api/shell/growl.d.ts +0 -25
  146. package/types/internal-api/shell/slideIn.d.ts +0 -15
@@ -1,6 +1,6 @@
1
1
 
2
2
  import { PaginationFilterEquality, PaginationFilterField, PaginationParamFilter, PaginationParamProjectOrNamespace } from '@shell/types/store/pagination.types';
3
- import { NAMESPACE_FILTER_P_FULL_PREFIX } from '@shell/utils/namespace-filter';
3
+ import { NAMESPACE_FILTER_ALL_SYSTEM, NAMESPACE_FILTER_ALL_USER, NAMESPACE_FILTER_P_FULL_PREFIX } from '@shell/utils/namespace-filter';
4
4
  import stevePaginationUtils from '../steve-pagination-utils';
5
5
  import Schema from '@shell/models/schema';
6
6
 
@@ -20,6 +20,14 @@ class TestNamespaceProjectFilters {
20
20
  public handleSelectionFilter(neu: string[], isLocalCluster: boolean) {
21
21
  return stevePaginationUtils.handleSelectionFilter(neu, isLocalCluster);
22
22
  }
23
+
24
+ public combineNsProjectFilterResults(a: any, b: any) {
25
+ return stevePaginationUtils.combineNsProjectFilterResults(a, b);
26
+ }
27
+
28
+ public createFiltersFromNamespaceProjectFilterResult(filterResult: any) {
29
+ return stevePaginationUtils.createFiltersFromNamespaceProjectFilterResult(filterResult);
30
+ }
23
31
  }
24
32
 
25
33
  describe('class: NamespaceProjectFilters', () => {
@@ -48,7 +56,7 @@ describe('class: NamespaceProjectFilters', () => {
48
56
  productHidesSystemNamespaces: false,
49
57
  });
50
58
 
51
- expect(result).toStrictEqual([]);
59
+ expect(result).toStrictEqual({});
52
60
  });
53
61
 
54
62
  it('should filter obscure namespaces if showReservedRancherNamespaces is false', () => {
@@ -58,12 +66,10 @@ describe('class: NamespaceProjectFilters', () => {
58
66
  productHidesSystemNamespaces: false,
59
67
  });
60
68
 
61
- expect(result).toHaveLength(1);
62
- expect(result).toContainEqual(expect.objectContaining({
63
- fields: [expect.objectContaining({
64
- value: 'obscure,obscure-system', equality: ' NOTIN ', field: `metadata.namespace`
65
- })]
66
- }));
69
+ expect(result).toStrictEqual({
70
+ obscure: false,
71
+ 'obscure-system': false
72
+ });
67
73
  });
68
74
 
69
75
  it('should filter system namespaces if productHidesSystemNamespaces is true', () => {
@@ -73,12 +79,10 @@ describe('class: NamespaceProjectFilters', () => {
73
79
  productHidesSystemNamespaces: true,
74
80
  });
75
81
 
76
- expect(result).toHaveLength(1);
77
- expect(result).toContainEqual(expect.objectContaining({
78
- fields: [expect.objectContaining({
79
- value: 'system,obscure-system', equality: ' NOTIN ', field: `metadata.namespace`
80
- })]
81
- }));
82
+ expect(result).toStrictEqual({
83
+ system: false,
84
+ 'obscure-system': false
85
+ });
82
86
  });
83
87
 
84
88
  it('should filter both obscure and system namespaces when both settings are active', () => {
@@ -88,12 +92,11 @@ describe('class: NamespaceProjectFilters', () => {
88
92
  productHidesSystemNamespaces: true,
89
93
  });
90
94
 
91
- expect(result).toHaveLength(1);
92
- expect(result).toContainEqual(expect.objectContaining({
93
- fields: [expect.objectContaining({
94
- value: 'obscure,system,obscure-system', equality: ' NOTIN ', field: `metadata.namespace`
95
- })]
96
- }));
95
+ expect(result).toStrictEqual({
96
+ obscure: false,
97
+ system: false,
98
+ 'obscure-system': false
99
+ });
97
100
  });
98
101
  });
99
102
 
@@ -105,16 +108,10 @@ describe('class: NamespaceProjectFilters', () => {
105
108
  isAllUser: false,
106
109
  });
107
110
 
108
- expect(result).toHaveLength(1);
109
- const filter = result[0] as PaginationParamFilter;
110
-
111
- expect(filter.fields).toHaveLength(2);
112
- expect(filter.fields).toContainEqual(expect.objectContaining({
113
- value: 'system', equality: '=', field: 'metadata.namespace'
114
- }));
115
- expect(filter.fields).toContainEqual(expect.objectContaining({
116
- value: 'obscure-system', equality: '=', field: 'metadata.namespace'
117
- }));
111
+ expect(result).toStrictEqual({
112
+ system: true,
113
+ 'obscure-system': true
114
+ });
118
115
  });
119
116
 
120
117
  it('should create AND filters to exclude system namespaces when isAllUser is true', () => {
@@ -124,17 +121,59 @@ describe('class: NamespaceProjectFilters', () => {
124
121
  isAllUser: true,
125
122
  });
126
123
 
127
- expect(result).toHaveLength(2);
128
- expect(result).toContainEqual(expect.objectContaining({
129
- fields: [expect.objectContaining({
130
- value: 'system', equality: '!=', field: 'metadata.namespace'
131
- })]
132
- }));
133
- expect(result).toContainEqual(expect.objectContaining({
134
- fields: [expect.objectContaining({
135
- value: 'obscure-system', equality: '!=', field: 'metadata.namespace'
136
- })]
137
- }));
124
+ expect(result).toStrictEqual({
125
+ system: false,
126
+ 'obscure-system': false
127
+ });
128
+ });
129
+ });
130
+
131
+ describe('method: combineNsProjectFilterResults', () => {
132
+ it('should merge two results, prioritizing the first', () => {
133
+ const a = { ns1: true, ns2: false };
134
+ const b = { ns2: true, ns3: true };
135
+ const result = testNamespaceProjectFilters.combineNsProjectFilterResults(a, b);
136
+
137
+ expect(result).toStrictEqual({
138
+ ns1: true,
139
+ ns2: false, // kept from a
140
+ ns3: true // added from b
141
+ });
142
+ });
143
+ });
144
+
145
+ describe('method: createFiltersFromNamespaceProjectFilterResult', () => {
146
+ it('should create IN filter if there are included namespaces', () => {
147
+ const input = {
148
+ ns1: true, ns2: true, ns3: false
149
+ };
150
+ const result = testNamespaceProjectFilters.createFiltersFromNamespaceProjectFilterResult(input);
151
+
152
+ expect(result).toHaveLength(1);
153
+ expect(result[0].fields[0]).toMatchObject({
154
+ field: 'metadata.namespace',
155
+ equality: PaginationFilterEquality.IN,
156
+ value: 'ns1,ns2'
157
+ });
158
+ });
159
+
160
+ it('should create NOT_IN filter if there are only excluded namespaces', () => {
161
+ const input = { ns1: false, ns2: false };
162
+ const result = testNamespaceProjectFilters.createFiltersFromNamespaceProjectFilterResult(input);
163
+
164
+ expect(result).toHaveLength(1);
165
+ expect(result[0].fields[0]).toMatchObject({
166
+ field: 'metadata.namespace',
167
+ equality: PaginationFilterEquality.NOT_IN,
168
+ value: 'ns1,ns2'
169
+ });
170
+ });
171
+
172
+ it('should return empty array if input is empty', () => {
173
+ const input = {};
174
+ const result = testNamespaceProjectFilters.createFiltersFromNamespaceProjectFilterResult(input);
175
+
176
+ expect(result).toHaveLength(0);
138
177
  });
139
178
  });
140
179
 
@@ -231,103 +270,237 @@ describe('class StevePaginationUtils', () => {
231
270
  const testStevePaginationUtils = new TestStevePaginationUtils();
232
271
  const schema = { id: 'pod' } as unknown as Schema;
233
272
 
234
- it('should return an empty string for no filters', () => {
235
- const result = testStevePaginationUtils.convertPaginationParams({ schema, filters: [] });
273
+ describe('method: createParamsFromNsFilter', () => {
274
+ const normalNs = {
275
+ id: 'normal', name: 'normal', isObscure: false, isSystem: false
276
+ } as any;
277
+ const obscureNs = {
278
+ id: 'obscure', name: 'obscure', isObscure: true, isSystem: false
279
+ } as any;
280
+ const systemNs = {
281
+ id: 'system', name: 'system', isObscure: false, isSystem: true
282
+ } as any;
283
+ const allNamespaces = [normalNs, obscureNs, systemNs];
284
+
285
+ it('should return empty filters if all namespaces requested and settings allow all', () => {
286
+ const result = stevePaginationUtils.createParamsFromNsFilter({
287
+ allNamespaces,
288
+ selection: [],
289
+ isAllNamespaces: true,
290
+ isLocalCluster: false,
291
+ showReservedRancherNamespaces: true,
292
+ productHidesSystemNamespaces: false,
293
+ });
236
294
 
237
- expect(result).toBe('');
238
- });
295
+ expect(result.projectsOrNamespaces).toHaveLength(0);
296
+ expect(result.filters).toHaveLength(0);
297
+ });
239
298
 
240
- it('should handle a single filter with a single field', () => {
241
- const filters = [
242
- new PaginationParamFilter({ fields: [new PaginationFilterField({ field: 'metadata.name', value: 'test' })] }),
243
- ];
244
- const result = testStevePaginationUtils.convertPaginationParams({ schema, filters });
299
+ it('should filter obscure namespaces if showReservedRancherNamespaces is false', () => {
300
+ const result = stevePaginationUtils.createParamsFromNsFilter({
301
+ allNamespaces,
302
+ selection: [],
303
+ isAllNamespaces: true,
304
+ isLocalCluster: false,
305
+ showReservedRancherNamespaces: false,
306
+ productHidesSystemNamespaces: false,
307
+ });
245
308
 
246
- expect(result).toBe('filter=metadata.name=test');
247
- });
309
+ expect(result.filters).toHaveLength(1);
310
+ expect(result.filters[0].fields[0]).toMatchObject({
311
+ field: 'metadata.namespace',
312
+ equality: PaginationFilterEquality.NOT_IN,
313
+ value: 'obscure'
314
+ });
315
+ });
248
316
 
249
- it('should handle a single filter with a single field with encoded char', () => {
250
- const filters = [
251
- new PaginationParamFilter({ fields: [new PaginationFilterField({ field: 'metadata.name', value: 'te/st' })] }),
252
- ];
253
- const result = testStevePaginationUtils.convertPaginationParams({ schema, filters });
317
+ it('should filter system namespaces if productHidesSystemNamespaces is true', () => {
318
+ const result = stevePaginationUtils.createParamsFromNsFilter({
319
+ allNamespaces,
320
+ selection: [],
321
+ isAllNamespaces: true,
322
+ isLocalCluster: false,
323
+ showReservedRancherNamespaces: true,
324
+ productHidesSystemNamespaces: true,
325
+ });
254
326
 
255
- expect(result).toBe('filter=metadata.name="te%2Fst"');
256
- });
327
+ expect(result.filters).toHaveLength(1);
328
+ expect(result.filters[0].fields[0]).toMatchObject({
329
+ field: 'metadata.namespace',
330
+ equality: PaginationFilterEquality.NOT_IN,
331
+ value: 'system'
332
+ });
333
+ });
257
334
 
258
- it('should handle a single filter with multiple fields (OR)', () => {
259
- const filters = [
260
- new PaginationParamFilter({
261
- fields: [
262
- new PaginationFilterField({ field: 'metadata.name', value: 'test1' }),
263
- new PaginationFilterField({ field: 'metadata.namespace', value: 'ns1' }),
264
- ],
265
- }),
266
- ];
267
- const result = testStevePaginationUtils.convertPaginationParams({ schema, filters });
268
-
269
- expect(result).toBe('filter=metadata.name=test1,metadata.namespace=ns1');
270
- });
335
+ it('should filter both obscure and system namespaces when both settings are active', () => {
336
+ const result = stevePaginationUtils.createParamsFromNsFilter({
337
+ allNamespaces,
338
+ selection: [],
339
+ isAllNamespaces: true,
340
+ isLocalCluster: false,
341
+ showReservedRancherNamespaces: false,
342
+ productHidesSystemNamespaces: true,
343
+ });
271
344
 
272
- it('should handle multiple filters (AND)', () => {
273
- const filters = [
274
- new PaginationParamFilter({ fields: [new PaginationFilterField({ field: 'metadata.name', value: 'test1' })] }),
275
- new PaginationParamFilter({ fields: [new PaginationFilterField({ field: 'metadata.namespace', value: 'ns1' })] }),
276
- ];
277
- const result = testStevePaginationUtils.convertPaginationParams({ schema, filters });
345
+ expect(result.filters).toHaveLength(1);
346
+ expect(result.filters[0].fields[0]).toMatchObject({
347
+ field: 'metadata.namespace',
348
+ equality: PaginationFilterEquality.NOT_IN,
349
+ value: 'obscure,system'
350
+ });
351
+ });
278
352
 
279
- expect(result).toBe('filter=metadata.name=test1&filter=metadata.namespace=ns1');
280
- });
353
+ it('should handle ALL_SYSTEM selection', () => {
354
+ const result = stevePaginationUtils.createParamsFromNsFilter({
355
+ allNamespaces,
356
+ selection: [NAMESPACE_FILTER_ALL_SYSTEM],
357
+ isAllNamespaces: false,
358
+ isLocalCluster: false,
359
+ showReservedRancherNamespaces: true,
360
+ productHidesSystemNamespaces: false,
361
+ });
362
+
363
+ expect(result.filters).toHaveLength(1);
364
+ expect(result.filters[0].fields[0]).toMatchObject({
365
+ field: 'metadata.namespace',
366
+ equality: PaginationFilterEquality.IN,
367
+ value: 'system'
368
+ });
369
+ });
370
+
371
+ it('should handle ALL_USER selection', () => {
372
+ const result = stevePaginationUtils.createParamsFromNsFilter({
373
+ allNamespaces,
374
+ selection: [NAMESPACE_FILTER_ALL_USER],
375
+ isAllNamespaces: false,
376
+ isLocalCluster: false,
377
+ showReservedRancherNamespaces: true,
378
+ productHidesSystemNamespaces: false,
379
+ });
380
+
381
+ expect(result.filters).toHaveLength(1);
382
+ expect(result.filters[0].fields[0]).toMatchObject({
383
+ field: 'metadata.namespace',
384
+ equality: PaginationFilterEquality.NOT_IN,
385
+ value: 'system'
386
+ });
387
+ });
281
388
 
282
- it('should handle different equality operators', () => {
283
- const filters = [
284
- new PaginationParamFilter({
285
- fields: [
286
- new PaginationFilterField({
287
- field: 'spec.containers.image',
288
- value: 'nginx',
289
- equality: PaginationFilterEquality.CONTAINS,
290
- }),
291
- ],
292
- }),
293
- new PaginationParamFilter({
294
- fields: [
295
- new PaginationFilterField({
296
- field: 'metadata.name',
297
- value: 'test',
298
- equality: PaginationFilterEquality.NOT_EQUALS,
299
- }),
300
- ],
301
- }),
302
- ];
303
- const result = testStevePaginationUtils.convertPaginationParams({ schema, filters });
304
-
305
- expect(result).toBe('filter=spec.containers.image~nginx&filter=metadata.name!=test');
389
+ it('should handle specific project/namespace selection', () => {
390
+ const selection = ['ns-1'];
391
+ const result = stevePaginationUtils.createParamsFromNsFilter({
392
+ allNamespaces,
393
+ selection,
394
+ isAllNamespaces: false,
395
+ isLocalCluster: false,
396
+ showReservedRancherNamespaces: true,
397
+ productHidesSystemNamespaces: false,
398
+ });
399
+
400
+ expect(result.projectsOrNamespaces).toHaveLength(1);
401
+ expect(result.projectsOrNamespaces[0].fields[0].value).toBe('ns-1');
402
+ });
306
403
  });
307
404
 
308
- it('should handle IN and NOT_IN operators', () => {
309
- const filters = [
310
- new PaginationParamFilter({
311
- fields: [
312
- new PaginationFilterField({
313
- field: 'metadata.name',
314
- value: 'test1,test2',
315
- equality: PaginationFilterEquality.IN,
316
- }),
317
- ],
318
- }),
319
- new PaginationParamFilter({
320
- fields: [
321
- new PaginationFilterField({
322
- field: 'metadata.namespace',
323
- value: 'ns1,ns2',
324
- equality: PaginationFilterEquality.NOT_IN,
325
- }),
326
- ],
327
- }),
328
- ];
329
- const result = testStevePaginationUtils.convertPaginationParams({ schema, filters });
330
-
331
- expect(result).toBe('filter=metadata.name IN (test1,test2)&filter=metadata.namespace NOTIN (ns1,ns2)');
405
+ describe('method: convertPaginationParams', () => {
406
+ it('should return an empty string for no filters', () => {
407
+ const result = testStevePaginationUtils.convertPaginationParams({ schema, filters: [] });
408
+
409
+ expect(result).toBe('');
410
+ });
411
+
412
+ it('should handle a single filter with a single field', () => {
413
+ const filters = [
414
+ new PaginationParamFilter({ fields: [new PaginationFilterField({ field: 'metadata.name', value: 'test' })] }),
415
+ ];
416
+ const result = testStevePaginationUtils.convertPaginationParams({ schema, filters });
417
+
418
+ expect(result).toBe('filter=metadata.name=test');
419
+ });
420
+
421
+ it('should handle a single filter with a single field with encoded char', () => {
422
+ const filters = [
423
+ new PaginationParamFilter({ fields: [new PaginationFilterField({ field: 'metadata.name', value: 'te/st' })] }),
424
+ ];
425
+ const result = testStevePaginationUtils.convertPaginationParams({ schema, filters });
426
+
427
+ expect(result).toBe('filter=metadata.name="te%2Fst"');
428
+ });
429
+
430
+ it('should handle a single filter with multiple fields (OR)', () => {
431
+ const filters = [
432
+ new PaginationParamFilter({
433
+ fields: [
434
+ new PaginationFilterField({ field: 'metadata.name', value: 'test1' }),
435
+ new PaginationFilterField({ field: 'metadata.namespace', value: 'ns1' }),
436
+ ],
437
+ }),
438
+ ];
439
+ const result = testStevePaginationUtils.convertPaginationParams({ schema, filters });
440
+
441
+ expect(result).toBe('filter=metadata.name=test1,metadata.namespace=ns1');
442
+ });
443
+
444
+ it('should handle multiple filters (AND)', () => {
445
+ const filters = [
446
+ new PaginationParamFilter({ fields: [new PaginationFilterField({ field: 'metadata.name', value: 'test1' })] }),
447
+ new PaginationParamFilter({ fields: [new PaginationFilterField({ field: 'metadata.namespace', value: 'ns1' })] }),
448
+ ];
449
+ const result = testStevePaginationUtils.convertPaginationParams({ schema, filters });
450
+
451
+ expect(result).toBe('filter=metadata.name=test1&filter=metadata.namespace=ns1');
452
+ });
453
+
454
+ it('should handle different equality operators', () => {
455
+ const filters = [
456
+ new PaginationParamFilter({
457
+ fields: [
458
+ new PaginationFilterField({
459
+ field: 'spec.containers.image',
460
+ value: 'nginx',
461
+ equality: PaginationFilterEquality.CONTAINS,
462
+ }),
463
+ ],
464
+ }),
465
+ new PaginationParamFilter({
466
+ fields: [
467
+ new PaginationFilterField({
468
+ field: 'metadata.name',
469
+ value: 'test',
470
+ equality: PaginationFilterEquality.NOT_EQUALS,
471
+ }),
472
+ ],
473
+ }),
474
+ ];
475
+ const result = testStevePaginationUtils.convertPaginationParams({ schema, filters });
476
+
477
+ expect(result).toBe('filter=spec.containers.image~nginx&filter=metadata.name!=test');
478
+ });
479
+
480
+ it('should handle IN and NOT_IN operators', () => {
481
+ const filters = [
482
+ new PaginationParamFilter({
483
+ fields: [
484
+ new PaginationFilterField({
485
+ field: 'metadata.name',
486
+ value: 'test1,test2',
487
+ equality: PaginationFilterEquality.IN,
488
+ }),
489
+ ],
490
+ }),
491
+ new PaginationParamFilter({
492
+ fields: [
493
+ new PaginationFilterField({
494
+ field: 'metadata.namespace',
495
+ value: 'ns1,ns2',
496
+ equality: PaginationFilterEquality.NOT_IN,
497
+ }),
498
+ ],
499
+ }),
500
+ ];
501
+ const result = testStevePaginationUtils.convertPaginationParams({ schema, filters });
502
+
503
+ expect(result).toBe('filter=metadata.name IN (test1,test2)&filter=metadata.namespace NOTIN (ns1,ns2)');
504
+ });
332
505
  });
333
506
  });
@@ -47,7 +47,7 @@ export default class SteveModel extends HybridModel {
47
47
  * Get all model extensions for this model
48
48
  */
49
49
  get modelExtensions() {
50
- return this.$plugin.getDynamic(EXT_IDS.MODEL_EXTENSION, this.type) || [];
50
+ return this.$extension.getDynamic(EXT_IDS.MODEL_EXTENSION, this.type) || [];
51
51
  }
52
52
 
53
53
  cleanForSave(data, forNew) {