@rancher/shell 3.0.9-rc.1 → 3.0.9-rc.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.
- package/assets/styles/base/_color.scss +1 -0
- package/assets/styles/base/_typography.scss +14 -5
- package/assets/styles/themes/_light.scss +1 -1
- package/assets/styles/themes/_modern.scss +1 -1
- package/assets/translations/en-us.yaml +104 -33
- package/assets/translations/zh-hans.yaml +13 -2
- package/components/ActionMenu.vue +7 -8
- package/components/ActionMenuShell.vue +23 -24
- package/components/CodeMirror.vue +4 -3
- package/components/DetailText.vue +54 -7
- package/components/Drawer/Chrome.vue +11 -4
- package/components/Drawer/DrawerCard.vue +19 -0
- package/components/Drawer/ResourceDetailDrawer/ConfigTab.vue +3 -11
- package/components/Drawer/ResourceDetailDrawer/__tests__/ConfigTab.test.ts +2 -2
- package/components/Drawer/ResourceDetailDrawer/index.vue +3 -20
- package/components/Drawer/types.ts +1 -0
- package/components/DynamicContent/DynamicContentCloseButton.vue +2 -2
- package/components/LocaleSelector.vue +1 -1
- package/components/Markdown.vue +1 -1
- package/components/PopoverCard.vue +3 -3
- package/components/Resource/Detail/Card/ExtrasCard.vue +39 -0
- package/components/Resource/Detail/Card/Scaler.vue +10 -2
- package/components/Resource/Detail/Card/StateCard/__tests__/composables.test.ts +142 -0
- package/components/Resource/Detail/Card/StateCard/composables.ts +41 -11
- package/components/Resource/Detail/Card/StateCard/index.vue +3 -9
- package/components/Resource/Detail/Card/StateCard/types.ts +6 -0
- package/components/Resource/Detail/Card/{PodsCard → StatusCard}/index.vue +14 -10
- package/components/Resource/Detail/Card/__tests__/PodsCard.test.ts +24 -25
- package/components/Resource/Detail/Cards.vue +27 -0
- package/components/Resource/Detail/Masthead/__tests__/index.test.ts +70 -0
- package/components/Resource/Detail/Masthead/index.vue +5 -0
- package/components/Resource/Detail/Metadata/KeyValueRow.vue +4 -2
- package/components/Resource/Detail/ResourcePopover/ResourcePopoverCard.vue +2 -2
- package/components/Resource/Detail/ResourceRow.types.ts +14 -0
- package/components/Resource/Detail/ResourceRow.vue +23 -35
- package/components/Resource/Detail/StatusRow.vue +5 -2
- package/components/Resource/Detail/TitleBar/__tests__/composables.test.ts +38 -7
- package/components/Resource/Detail/TitleBar/__tests__/index.test.ts +106 -2
- package/components/Resource/Detail/TitleBar/composables.ts +2 -1
- package/components/Resource/Detail/TitleBar/index.vue +41 -6
- package/components/ResourceDetail/Masthead/__tests__/index.test.ts +49 -1
- package/components/ResourceDetail/Masthead/__tests__/latest.test.ts +85 -0
- package/components/ResourceDetail/Masthead/index.vue +1 -0
- package/components/ResourceDetail/Masthead/latest.vue +8 -1
- package/components/ResourceDetail/Masthead/legacy.vue +1 -1
- package/components/ResourceTable.vue +1 -1
- package/components/Setting.vue +1 -1
- package/components/SortableTable/index.vue +25 -0
- package/components/SortableTable/selection.js +25 -12
- package/components/SortableTable/sorting.js +1 -1
- package/components/Tabbed/Tab.vue +5 -0
- package/components/Tabbed/index.vue +40 -9
- package/components/Window/ContainerShell.vue +10 -13
- package/components/__tests__/ProjectRow.test.ts +102 -15
- package/components/fleet/FleetClusterTargets/TargetsList.vue +47 -29
- package/components/fleet/FleetClusterTargets/index.vue +82 -29
- package/components/fleet/FleetClusters.vue +26 -12
- package/components/fleet/FleetGitRepoPaths.vue +2 -2
- package/components/fleet/FleetResources.vue +14 -0
- package/components/fleet/FleetValuesFrom.vue +2 -2
- package/components/fleet/__tests__/FleetClusterTargets.test.ts +531 -0
- package/components/fleet/__tests__/FleetClusters.test.ts +576 -0
- package/components/fleet/dashboard/ResourceDetails.vue +96 -123
- package/components/form/Conditions.vue +1 -15
- package/components/form/HookOption.vue +5 -0
- package/components/form/LabeledSelect.vue +1 -1
- package/components/form/LifecycleHooks.vue +2 -6
- package/components/form/ResourceLabeledSelect.vue +12 -1
- package/components/form/ResourceQuota/Project.vue +59 -8
- package/components/form/ResourceQuota/ProjectRow.vue +116 -21
- package/components/form/ResourceQuota/shared.js +42 -18
- package/components/form/SeccompProfile.vue +113 -0
- package/components/form/Security.vue +244 -133
- package/components/form/__tests__/LabeledSelect.test.ts +1 -1
- package/components/form/__tests__/SeccompProfile.test.js +124 -0
- package/components/form/__tests__/Security.test.ts +125 -37
- package/components/formatter/Autoscaler.vue +2 -2
- package/components/formatter/FleetSummaryGraph.vue +4 -1
- package/components/formatter/LinkName.vue +3 -2
- package/components/nav/Group.vue +5 -0
- package/components/nav/Header.vue +3 -3
- package/components/nav/HeaderPageActionMenu.vue +1 -1
- package/components/nav/NamespaceFilter.vue +6 -6
- package/components/nav/NotificationCenter/index.vue +1 -1
- package/components/nav/TopLevelMenu.helper.ts +41 -16
- package/components/nav/TopLevelMenu.vue +45 -25
- package/components/nav/WorkspaceSwitcher.vue +1 -1
- package/components/nav/__tests__/TopLevelMenu.helper.test.ts +277 -0
- package/components/nav/__tests__/TopLevelMenu.test.ts +160 -4
- package/components/templates/default.vue +0 -3
- package/components/templates/home.vue +0 -3
- package/components/templates/plain.vue +0 -3
- package/composables/useClickOutside.ts +1 -1
- package/config/product/explorer.js +2 -3
- package/config/table-headers.js +9 -7
- package/config/types.js +45 -9
- package/detail/__tests__/workload.test.ts +8 -16
- package/detail/catalog.cattle.io.app.vue +5 -0
- package/detail/fleet.cattle.io.cluster.vue +6 -0
- package/detail/management.cattle.io.oidcclient.vue +15 -4
- package/detail/workload/index.vue +7 -109
- package/edit/__tests__/management.cattle.io.project.test.js +137 -0
- package/edit/__tests__/projectsecret.test.ts +42 -0
- package/edit/auth/__tests__/oidc.test.ts +50 -0
- package/edit/auth/oidc.vue +68 -44
- package/edit/autoscaling.horizontalpodautoscaler/index.vue +140 -59
- package/edit/autoscaling.horizontalpodautoscaler/metrics-row.vue +41 -5
- package/edit/management.cattle.io.project.vue +36 -6
- package/edit/monitoring.coreos.com.alertmanagerconfig/index.vue +16 -3
- package/edit/projectsecret.vue +29 -0
- package/edit/provisioning.cattle.io.cluster/__tests__/Basics.test.ts +89 -200
- package/edit/provisioning.cattle.io.cluster/__tests__/Networking.test.ts +58 -17
- package/edit/provisioning.cattle.io.cluster/rke2.vue +11 -0
- package/edit/provisioning.cattle.io.cluster/tabs/Basics.vue +3 -63
- package/edit/provisioning.cattle.io.cluster/tabs/networking/index.vue +82 -14
- package/edit/workload/__tests__/index.test.ts +3 -4
- package/edit/workload/index.vue +47 -28
- package/edit/workload/mixins/workload.js +66 -31
- package/initialize/install-plugins.js +0 -2
- package/list/catalog.cattle.io.clusterrepo.vue +1 -1
- package/list/projectsecret.vue +2 -2
- package/machine-config/__tests__/vmwarevsphere.test.ts +64 -0
- package/machine-config/amazonec2.vue +2 -2
- package/machine-config/vmwarevsphere.vue +58 -4
- package/mixins/__tests__/chart.test.ts +63 -0
- package/mixins/chart.js +56 -51
- package/models/__tests__/catalog.cattle.io.app.test.ts +33 -0
- package/models/__tests__/workload.test.ts +333 -0
- package/models/catalog.cattle.io.app.js +8 -0
- package/models/management.cattle.io.cluster.js +22 -30
- package/models/pod.js +14 -0
- package/models/provisioning.cattle.io.cluster.js +2 -2
- package/models/secret.js +1 -1
- package/models/workload.js +93 -27
- package/package.json +4 -4
- package/pages/__tests__/diagnostic.test.ts +71 -0
- package/pages/c/_cluster/apps/charts/__tests__/install.test.ts +91 -0
- package/pages/c/_cluster/apps/charts/install.vue +4 -4
- package/pages/c/_cluster/explorer/EventsTable.vue +2 -2
- package/pages/c/_cluster/explorer/tools/index.vue +23 -5
- package/pages/c/_cluster/fleet/index.vue +14 -8
- package/pages/c/_cluster/manager/hostedprovider/index.vue +1 -19
- package/pages/c/_cluster/monitoring/alertmanagerconfig/_alertmanagerconfigid/receiver.vue +18 -5
- package/pages/c/_cluster/uiplugins/PluginInfoPanel.vue +1 -1
- package/pages/c/_cluster/uiplugins/index.vue +41 -9
- package/pages/diagnostic.vue +17 -3
- package/plugins/dashboard-store/__tests__/resource-class.test.ts +234 -0
- package/plugins/dashboard-store/actions.js +9 -8
- package/plugins/dashboard-store/resource-class.js +97 -1
- package/plugins/steve/__tests__/revision.test.ts +84 -0
- package/plugins/steve/__tests__/steve-pagination-utils.test.ts +30 -0
- package/plugins/steve/__tests__/subscribe.spec.ts +134 -0
- package/plugins/steve/revision.ts +26 -0
- package/plugins/steve/steve-pagination-utils.ts +6 -5
- package/plugins/steve/subscribe.js +188 -49
- package/plugins/subscribe-events.ts +2 -2
- package/rancher-components/Form/Checkbox/Checkbox.vue +13 -0
- package/rancher-components/LabeledTooltip/LabeledTooltip.vue +1 -1
- package/rancher-components/Pill/RcCounterBadge/RcCounterBadge.vue +2 -1
- package/rancher-components/Pill/RcStatusBadge/RcStatusBadge.vue +3 -1
- package/rancher-components/Pill/RcStatusIndicator/RcStatusIndicator.vue +3 -1
- package/rancher-components/Pill/RcTag/RcTag.vue +1 -1
- package/rancher-components/Pill/index.ts +4 -0
- package/rancher-components/RcButton/RcButton.test.ts +53 -9
- package/rancher-components/RcButton/RcButton.vue +217 -25
- package/rancher-components/RcButton/types.ts +27 -1
- package/rancher-components/RcDropdown/RcDropdownMenu.vue +4 -4
- package/rancher-components/RcDropdown/types.ts +3 -3
- package/rancher-components/RcIcon/RcIcon.test.ts +42 -0
- package/rancher-components/RcIcon/RcIcon.vue +9 -6
- package/rancher-components/RcIcon/types.ts +13 -9
- package/rancher-components/RcItemCard/RcItemCard.test.ts +16 -6
- package/rancher-components/RcItemCard/RcItemCard.vue +13 -23
- package/rancher-components/utils/status.test.ts +10 -15
- package/rancher-components/utils/status.ts +5 -6
- package/store/__tests__/auth.test.ts +21 -5
- package/store/auth.js +6 -3
- package/store/aws.js +18 -12
- package/store/index.js +4 -8
- package/store/type-map.utils.ts +1 -1
- package/types/kube/kube-api.ts +29 -3
- package/types/rancher/steve.api.ts +40 -0
- package/types/shell/index.d.ts +262 -156
- package/types/store/pagination.types.ts +1 -0
- package/types/store/subscribe-events.types.ts +1 -0
- package/utils/__tests__/azure.test.ts +56 -0
- package/utils/__tests__/back-off.test.ts +364 -245
- package/utils/__tests__/error.test.ts +44 -0
- package/utils/__tests__/fleet.test.ts +8 -1
- package/utils/__tests__/pagination-wrapper.test.ts +167 -0
- package/utils/__tests__/version.test.ts +55 -1
- package/utils/azure.js +12 -0
- package/utils/back-off.ts +302 -69
- package/utils/dynamic-content/__tests__/index.test.ts +1 -1
- package/utils/dynamic-content/__tests__/new-release.test.ts +48 -7
- package/utils/dynamic-content/__tests__/support-notice.test.ts +1 -4
- package/utils/dynamic-content/index.ts +1 -6
- package/utils/dynamic-content/new-release.ts +5 -3
- package/utils/dynamic-content/types.d.ts +0 -1
- package/utils/error.js +9 -0
- package/utils/fleet.ts +2 -2
- package/utils/inactivity.ts +2 -3
- package/utils/pagination-wrapper.ts +99 -15
- package/utils/validators/formRules/index.ts +3 -0
- package/utils/version.js +38 -0
- package/components/auth/AzureWarning.vue +0 -77
- /package/components/Resource/Detail/{Card/PodsCard/Bubble.vue → Bubble.vue} +0 -0
- /package/components/Resource/Detail/Card/{PodsCard → StatusCard}/composable.ts +0 -0
|
@@ -1221,4 +1221,535 @@ describe('component: FleetClusterTargets', () => {
|
|
|
1221
1221
|
});
|
|
1222
1222
|
});
|
|
1223
1223
|
});
|
|
1224
|
+
|
|
1225
|
+
describe('clusterGroup Functionality Tests', () => {
|
|
1226
|
+
describe('clusterGroup Data Management', () => {
|
|
1227
|
+
it('should initialize with empty selectedClusterGroups', () => {
|
|
1228
|
+
const wrapper = mount(FleetClusterTargets, {
|
|
1229
|
+
props: {
|
|
1230
|
+
targets: [],
|
|
1231
|
+
namespace: 'fleet-default',
|
|
1232
|
+
mode: _EDIT
|
|
1233
|
+
}
|
|
1234
|
+
});
|
|
1235
|
+
|
|
1236
|
+
expect(wrapper.vm.selectedClusterGroups).toStrictEqual([]);
|
|
1237
|
+
});
|
|
1238
|
+
|
|
1239
|
+
it('should populate allClusterGroups from store data', async() => {
|
|
1240
|
+
const mockClusterGroups = [
|
|
1241
|
+
{
|
|
1242
|
+
metadata: { namespace: 'fleet-default', name: 'production-group' },
|
|
1243
|
+
nameDisplay: 'Production Group'
|
|
1244
|
+
},
|
|
1245
|
+
{
|
|
1246
|
+
metadata: { namespace: 'fleet-default', name: 'staging-group' },
|
|
1247
|
+
nameDisplay: 'Staging Group'
|
|
1248
|
+
}
|
|
1249
|
+
];
|
|
1250
|
+
|
|
1251
|
+
const wrapper = mount(FleetClusterTargets, {
|
|
1252
|
+
props: {
|
|
1253
|
+
targets: [],
|
|
1254
|
+
namespace: 'fleet-default',
|
|
1255
|
+
mode: _EDIT
|
|
1256
|
+
}
|
|
1257
|
+
});
|
|
1258
|
+
|
|
1259
|
+
wrapper.setData({ allClusterGroups: mockClusterGroups });
|
|
1260
|
+
await flushPromises();
|
|
1261
|
+
|
|
1262
|
+
expect(wrapper.vm.allClusterGroups).toStrictEqual(mockClusterGroups);
|
|
1263
|
+
});
|
|
1264
|
+
|
|
1265
|
+
it('should filter clusterGroupsOptions by namespace', () => {
|
|
1266
|
+
const mockClusterGroups = [
|
|
1267
|
+
{
|
|
1268
|
+
metadata: { namespace: 'fleet-default', name: 'group-1' },
|
|
1269
|
+
nameDisplay: 'Group 1'
|
|
1270
|
+
},
|
|
1271
|
+
{
|
|
1272
|
+
metadata: { namespace: 'other-namespace', name: 'group-2' },
|
|
1273
|
+
nameDisplay: 'Group 2'
|
|
1274
|
+
},
|
|
1275
|
+
{
|
|
1276
|
+
metadata: { namespace: 'fleet-default', name: 'group-3' },
|
|
1277
|
+
nameDisplay: 'Group 3'
|
|
1278
|
+
}
|
|
1279
|
+
];
|
|
1280
|
+
|
|
1281
|
+
const wrapper = mount(FleetClusterTargets, {
|
|
1282
|
+
props: {
|
|
1283
|
+
targets: [],
|
|
1284
|
+
namespace: 'fleet-default',
|
|
1285
|
+
mode: _EDIT
|
|
1286
|
+
}
|
|
1287
|
+
});
|
|
1288
|
+
|
|
1289
|
+
wrapper.setData({ allClusterGroups: mockClusterGroups });
|
|
1290
|
+
|
|
1291
|
+
const filteredOptions = wrapper.vm.clusterGroupsOptions;
|
|
1292
|
+
|
|
1293
|
+
expect(filteredOptions).toHaveLength(2);
|
|
1294
|
+
expect(filteredOptions).toStrictEqual([
|
|
1295
|
+
{ label: 'Group 1', value: 'group-1' },
|
|
1296
|
+
{ label: 'Group 3', value: 'group-3' }
|
|
1297
|
+
]);
|
|
1298
|
+
});
|
|
1299
|
+
});
|
|
1300
|
+
|
|
1301
|
+
describe('clusterGroup Selection Methods', () => {
|
|
1302
|
+
it('should update selectedClusterGroups when selectClusterGroups is called', async() => {
|
|
1303
|
+
const wrapper = mount(FleetClusterTargets, {
|
|
1304
|
+
props: {
|
|
1305
|
+
targets: [],
|
|
1306
|
+
namespace: 'fleet-default',
|
|
1307
|
+
mode: _EDIT
|
|
1308
|
+
}
|
|
1309
|
+
});
|
|
1310
|
+
|
|
1311
|
+
const updateSpy = jest.spyOn(wrapper.vm, 'update');
|
|
1312
|
+
|
|
1313
|
+
wrapper.vm.selectClusterGroups(['group-1', 'group-2']);
|
|
1314
|
+
await flushPromises();
|
|
1315
|
+
|
|
1316
|
+
expect(wrapper.vm.selectedClusterGroups).toStrictEqual(['group-1', 'group-2']);
|
|
1317
|
+
expect(updateSpy).toHaveBeenCalledWith();
|
|
1318
|
+
});
|
|
1319
|
+
|
|
1320
|
+
it('should emit update:value when selectClusterGroups is called', async() => {
|
|
1321
|
+
const wrapper = mount(FleetClusterTargets, {
|
|
1322
|
+
props: {
|
|
1323
|
+
targets: [],
|
|
1324
|
+
namespace: 'fleet-default',
|
|
1325
|
+
mode: _EDIT
|
|
1326
|
+
}
|
|
1327
|
+
});
|
|
1328
|
+
|
|
1329
|
+
wrapper.vm.selectClusterGroups(['test-group']);
|
|
1330
|
+
await flushPromises();
|
|
1331
|
+
|
|
1332
|
+
expect(wrapper.emitted('update:value')).toBeDefined();
|
|
1333
|
+
});
|
|
1334
|
+
|
|
1335
|
+
it('should handle empty array in selectClusterGroups', async() => {
|
|
1336
|
+
const wrapper = mount(FleetClusterTargets, {
|
|
1337
|
+
props: {
|
|
1338
|
+
targets: [],
|
|
1339
|
+
namespace: 'fleet-default',
|
|
1340
|
+
mode: _EDIT
|
|
1341
|
+
}
|
|
1342
|
+
});
|
|
1343
|
+
|
|
1344
|
+
// First set some groups
|
|
1345
|
+
wrapper.vm.selectClusterGroups(['group-1', 'group-2']);
|
|
1346
|
+
await flushPromises();
|
|
1347
|
+
|
|
1348
|
+
// Then clear them
|
|
1349
|
+
wrapper.vm.selectClusterGroups([]);
|
|
1350
|
+
await flushPromises();
|
|
1351
|
+
|
|
1352
|
+
expect(wrapper.vm.selectedClusterGroups).toStrictEqual([]);
|
|
1353
|
+
});
|
|
1354
|
+
|
|
1355
|
+
it('should replace existing selectedClusterGroups on new selection', async() => {
|
|
1356
|
+
const wrapper = mount(FleetClusterTargets, {
|
|
1357
|
+
props: {
|
|
1358
|
+
targets: [],
|
|
1359
|
+
namespace: 'fleet-default',
|
|
1360
|
+
mode: _EDIT
|
|
1361
|
+
}
|
|
1362
|
+
});
|
|
1363
|
+
|
|
1364
|
+
// Initial selection
|
|
1365
|
+
wrapper.vm.selectClusterGroups(['group-1', 'group-2']);
|
|
1366
|
+
await flushPromises();
|
|
1367
|
+
|
|
1368
|
+
// Replace with new selection
|
|
1369
|
+
wrapper.vm.selectClusterGroups(['group-3', 'group-4', 'group-5']);
|
|
1370
|
+
await flushPromises();
|
|
1371
|
+
|
|
1372
|
+
expect(wrapper.vm.selectedClusterGroups).toStrictEqual(['group-3', 'group-4', 'group-5']);
|
|
1373
|
+
});
|
|
1374
|
+
});
|
|
1375
|
+
|
|
1376
|
+
describe('clusterGroup Target Processing', () => {
|
|
1377
|
+
it('should parse existing targets with clusterGroup in fromTargets', () => {
|
|
1378
|
+
const targets = [
|
|
1379
|
+
{ clusterGroup: 'production-group' },
|
|
1380
|
+
{ clusterGroup: 'staging-group' },
|
|
1381
|
+
{ clusterName: 'specific-cluster' }
|
|
1382
|
+
];
|
|
1383
|
+
|
|
1384
|
+
const wrapper = mount(FleetClusterTargets, {
|
|
1385
|
+
props: {
|
|
1386
|
+
targets,
|
|
1387
|
+
namespace: 'fleet-default',
|
|
1388
|
+
mode: _EDIT
|
|
1389
|
+
}
|
|
1390
|
+
});
|
|
1391
|
+
|
|
1392
|
+
expect(wrapper.vm.selectedClusterGroups).toStrictEqual(['production-group', 'staging-group']);
|
|
1393
|
+
expect(wrapper.vm.selectedClusters).toStrictEqual(['specific-cluster']);
|
|
1394
|
+
});
|
|
1395
|
+
|
|
1396
|
+
it('should include clusterGroups in normalizeTargets output', () => {
|
|
1397
|
+
const wrapper = mount(FleetClusterTargets, {
|
|
1398
|
+
props: {
|
|
1399
|
+
targets: [],
|
|
1400
|
+
namespace: 'fleet-default',
|
|
1401
|
+
mode: _EDIT
|
|
1402
|
+
}
|
|
1403
|
+
});
|
|
1404
|
+
|
|
1405
|
+
const result = wrapper.vm.normalizeTargets(
|
|
1406
|
+
['cluster-1'],
|
|
1407
|
+
[{ matchLabels: { env: 'prod' } }],
|
|
1408
|
+
['group-1', 'group-2']
|
|
1409
|
+
);
|
|
1410
|
+
|
|
1411
|
+
expect(result).toStrictEqual([
|
|
1412
|
+
{ clusterName: 'cluster-1' },
|
|
1413
|
+
{ clusterSelector: { matchLabels: { env: 'prod' } } },
|
|
1414
|
+
{ clusterGroup: 'group-1' },
|
|
1415
|
+
{ clusterGroup: 'group-2' }
|
|
1416
|
+
]);
|
|
1417
|
+
});
|
|
1418
|
+
|
|
1419
|
+
it('should handle only clusterGroups in normalizeTargets', () => {
|
|
1420
|
+
const wrapper = mount(FleetClusterTargets, {
|
|
1421
|
+
props: {
|
|
1422
|
+
targets: [],
|
|
1423
|
+
namespace: 'fleet-default',
|
|
1424
|
+
mode: _EDIT
|
|
1425
|
+
}
|
|
1426
|
+
});
|
|
1427
|
+
|
|
1428
|
+
const result = wrapper.vm.normalizeTargets([], [], ['group-1', 'group-2']);
|
|
1429
|
+
|
|
1430
|
+
expect(result).toStrictEqual([
|
|
1431
|
+
{ clusterGroup: 'group-1' },
|
|
1432
|
+
{ clusterGroup: 'group-2' }
|
|
1433
|
+
]);
|
|
1434
|
+
});
|
|
1435
|
+
|
|
1436
|
+
it('should return undefined when normalizeTargets has no inputs', () => {
|
|
1437
|
+
const wrapper = mount(FleetClusterTargets, {
|
|
1438
|
+
props: {
|
|
1439
|
+
targets: [],
|
|
1440
|
+
namespace: 'fleet-default',
|
|
1441
|
+
mode: _EDIT
|
|
1442
|
+
}
|
|
1443
|
+
});
|
|
1444
|
+
|
|
1445
|
+
const result = wrapper.vm.normalizeTargets([], [], []);
|
|
1446
|
+
|
|
1447
|
+
expect(result).toBeUndefined();
|
|
1448
|
+
});
|
|
1449
|
+
|
|
1450
|
+
it('should include clusterGroups in toTargets when targetMode is clusters', () => {
|
|
1451
|
+
const wrapper = mount(FleetClusterTargets, {
|
|
1452
|
+
props: {
|
|
1453
|
+
targets: [],
|
|
1454
|
+
namespace: 'fleet-default',
|
|
1455
|
+
mode: _EDIT
|
|
1456
|
+
}
|
|
1457
|
+
});
|
|
1458
|
+
|
|
1459
|
+
wrapper.setData({
|
|
1460
|
+
targetMode: 'clusters',
|
|
1461
|
+
selectedClusters: ['cluster-1'],
|
|
1462
|
+
clusterSelectors: [],
|
|
1463
|
+
selectedClusterGroups: ['group-1', 'group-2']
|
|
1464
|
+
});
|
|
1465
|
+
|
|
1466
|
+
const result = wrapper.vm.toTargets();
|
|
1467
|
+
|
|
1468
|
+
expect(result).toStrictEqual([
|
|
1469
|
+
{ clusterName: 'cluster-1' },
|
|
1470
|
+
{ clusterGroup: 'group-1' },
|
|
1471
|
+
{ clusterGroup: 'group-2' }
|
|
1472
|
+
]);
|
|
1473
|
+
});
|
|
1474
|
+
});
|
|
1475
|
+
|
|
1476
|
+
describe('clusterGroup Integration with Target Modes', () => {
|
|
1477
|
+
it('should handle clusterGroup targets and set appropriate targetMode', () => {
|
|
1478
|
+
const targets = [
|
|
1479
|
+
{ clusterGroup: 'test-group' }
|
|
1480
|
+
];
|
|
1481
|
+
|
|
1482
|
+
const wrapper = mount(FleetClusterTargets, {
|
|
1483
|
+
props: {
|
|
1484
|
+
targets,
|
|
1485
|
+
namespace: 'fleet-default',
|
|
1486
|
+
mode: _EDIT
|
|
1487
|
+
}
|
|
1488
|
+
});
|
|
1489
|
+
|
|
1490
|
+
// ClusterGroup targets should be parsed correctly
|
|
1491
|
+
expect(wrapper.vm.selectedClusterGroups).toStrictEqual(['test-group']);
|
|
1492
|
+
});
|
|
1493
|
+
});
|
|
1494
|
+
|
|
1495
|
+
it('should handle mixed targets with clusterGroup, clusterName, and clusterSelector', () => {
|
|
1496
|
+
const targets = [
|
|
1497
|
+
{ clusterName: 'specific-cluster' },
|
|
1498
|
+
{ clusterGroup: 'production-group' },
|
|
1499
|
+
{ clusterSelector: { matchLabels: { env: 'staging' } } },
|
|
1500
|
+
{ clusterGroup: 'development-group' }
|
|
1501
|
+
];
|
|
1502
|
+
|
|
1503
|
+
const wrapper = mount(FleetClusterTargets, {
|
|
1504
|
+
props: {
|
|
1505
|
+
targets,
|
|
1506
|
+
namespace: 'fleet-default',
|
|
1507
|
+
mode: _EDIT
|
|
1508
|
+
}
|
|
1509
|
+
});
|
|
1510
|
+
|
|
1511
|
+
expect(wrapper.vm.selectedClusters).toStrictEqual(['specific-cluster']);
|
|
1512
|
+
expect(wrapper.vm.selectedClusterGroups).toStrictEqual(['production-group', 'development-group']);
|
|
1513
|
+
expect(wrapper.vm.clusterSelectors).toHaveLength(1);
|
|
1514
|
+
expect(wrapper.vm.clusterSelectors[0].matchLabels).toStrictEqual({ env: 'staging' });
|
|
1515
|
+
});
|
|
1516
|
+
|
|
1517
|
+
it('should reset selectedClusterGroups when reset method is called', () => {
|
|
1518
|
+
const wrapper = mount(FleetClusterTargets, {
|
|
1519
|
+
props: {
|
|
1520
|
+
targets: [],
|
|
1521
|
+
namespace: 'fleet-default',
|
|
1522
|
+
mode: _EDIT
|
|
1523
|
+
}
|
|
1524
|
+
});
|
|
1525
|
+
|
|
1526
|
+
// Set some cluster groups
|
|
1527
|
+
wrapper.setData({
|
|
1528
|
+
targetMode: 'clusters',
|
|
1529
|
+
selectedClusterGroups: ['group-1', 'group-2'],
|
|
1530
|
+
selectedClusters: ['cluster-1'],
|
|
1531
|
+
clusterSelectors: [{ key: 1 }]
|
|
1532
|
+
});
|
|
1533
|
+
|
|
1534
|
+
// Call reset
|
|
1535
|
+
wrapper.vm.reset();
|
|
1536
|
+
|
|
1537
|
+
expect(wrapper.vm.selectedClusterGroups).toStrictEqual([]);
|
|
1538
|
+
expect(wrapper.vm.targetMode).toBe('all');
|
|
1539
|
+
expect(wrapper.vm.selectedClusters).toStrictEqual([]);
|
|
1540
|
+
expect(wrapper.vm.clusterSelectors).toStrictEqual([]);
|
|
1541
|
+
});
|
|
1542
|
+
});
|
|
1543
|
+
|
|
1544
|
+
describe('clusterGroup Event Handling and Updates', () => {
|
|
1545
|
+
it('should emit correct targets when both clusters and clusterGroups are selected', async() => {
|
|
1546
|
+
const wrapper = mount(FleetClusterTargets, {
|
|
1547
|
+
props: {
|
|
1548
|
+
targets: [],
|
|
1549
|
+
namespace: 'fleet-default',
|
|
1550
|
+
mode: _CREATE
|
|
1551
|
+
}
|
|
1552
|
+
});
|
|
1553
|
+
|
|
1554
|
+
// Set target mode and selections
|
|
1555
|
+
wrapper.setData({ targetMode: 'clusters' });
|
|
1556
|
+
wrapper.vm.selectClusters(['cluster-1', 'cluster-2']);
|
|
1557
|
+
await flushPromises();
|
|
1558
|
+
|
|
1559
|
+
wrapper.vm.selectClusterGroups(['group-1']);
|
|
1560
|
+
await flushPromises();
|
|
1561
|
+
|
|
1562
|
+
const emittedValues = wrapper.emitted('update:value');
|
|
1563
|
+
const lastEmitted = emittedValues?.[emittedValues.length - 1][0];
|
|
1564
|
+
|
|
1565
|
+
expect(lastEmitted).toStrictEqual([
|
|
1566
|
+
{ clusterName: 'cluster-1' },
|
|
1567
|
+
{ clusterName: 'cluster-2' },
|
|
1568
|
+
{ clusterGroup: 'group-1' }
|
|
1569
|
+
]);
|
|
1570
|
+
});
|
|
1571
|
+
|
|
1572
|
+
it('should handle clusterGroup selection in CREATE mode with proper event emission', async() => {
|
|
1573
|
+
const wrapper = mount(FleetClusterTargets, {
|
|
1574
|
+
props: {
|
|
1575
|
+
targets: [],
|
|
1576
|
+
namespace: 'fleet-default',
|
|
1577
|
+
mode: _CREATE
|
|
1578
|
+
}
|
|
1579
|
+
});
|
|
1580
|
+
|
|
1581
|
+
wrapper.setData({ targetMode: 'clusters' });
|
|
1582
|
+
wrapper.vm.selectClusterGroups(['create-group-1', 'create-group-2']);
|
|
1583
|
+
await flushPromises();
|
|
1584
|
+
|
|
1585
|
+
const emittedValues = wrapper.emitted('update:value');
|
|
1586
|
+
|
|
1587
|
+
expect(emittedValues).toBeDefined();
|
|
1588
|
+
|
|
1589
|
+
const lastEmitted = emittedValues?.[emittedValues.length - 1][0];
|
|
1590
|
+
|
|
1591
|
+
expect(lastEmitted).toStrictEqual([
|
|
1592
|
+
{ clusterGroup: 'create-group-1' },
|
|
1593
|
+
{ clusterGroup: 'create-group-2' }
|
|
1594
|
+
]);
|
|
1595
|
+
});
|
|
1596
|
+
|
|
1597
|
+
it('should update component state correctly when clusterGroups prop changes', async() => {
|
|
1598
|
+
const initialTargets = [{ clusterGroup: 'initial-group' }];
|
|
1599
|
+
|
|
1600
|
+
const wrapper = mount(FleetClusterTargets, {
|
|
1601
|
+
props: {
|
|
1602
|
+
targets: initialTargets,
|
|
1603
|
+
namespace: 'fleet-default',
|
|
1604
|
+
mode: _EDIT
|
|
1605
|
+
}
|
|
1606
|
+
});
|
|
1607
|
+
|
|
1608
|
+
expect(wrapper.vm.selectedClusterGroups).toStrictEqual(['initial-group']);
|
|
1609
|
+
|
|
1610
|
+
// Update props
|
|
1611
|
+
const newTargets = [
|
|
1612
|
+
{ clusterGroup: 'new-group-1' },
|
|
1613
|
+
{ clusterGroup: 'new-group-2' }
|
|
1614
|
+
];
|
|
1615
|
+
|
|
1616
|
+
await wrapper.setProps({ targets: newTargets });
|
|
1617
|
+
|
|
1618
|
+
// Reset and then parse new targets to simulate component update
|
|
1619
|
+
wrapper.vm.reset();
|
|
1620
|
+
wrapper.vm.fromTargets();
|
|
1621
|
+
|
|
1622
|
+
expect(wrapper.vm.selectedClusterGroups).toStrictEqual(['new-group-1', 'new-group-2']);
|
|
1623
|
+
});
|
|
1624
|
+
});
|
|
1625
|
+
|
|
1626
|
+
describe('clusterGroup Edge Cases and Error Handling', () => {
|
|
1627
|
+
it('should handle undefined clusterGroup in targets gracefully', () => {
|
|
1628
|
+
const targets = [
|
|
1629
|
+
{ clusterGroup: undefined },
|
|
1630
|
+
{ clusterGroup: 'valid-group' },
|
|
1631
|
+
{ clusterName: 'cluster-1' }
|
|
1632
|
+
];
|
|
1633
|
+
|
|
1634
|
+
const wrapper = mount(FleetClusterTargets, {
|
|
1635
|
+
props: {
|
|
1636
|
+
targets: targets as any,
|
|
1637
|
+
namespace: 'fleet-default',
|
|
1638
|
+
mode: _EDIT
|
|
1639
|
+
}
|
|
1640
|
+
});
|
|
1641
|
+
|
|
1642
|
+
expect(wrapper.vm.selectedClusterGroups).toStrictEqual(['valid-group']);
|
|
1643
|
+
});
|
|
1644
|
+
|
|
1645
|
+
it('should handle empty string clusterGroup in targets', () => {
|
|
1646
|
+
const targets = [
|
|
1647
|
+
{ clusterGroup: '' },
|
|
1648
|
+
{ clusterGroup: 'valid-group' }
|
|
1649
|
+
];
|
|
1650
|
+
|
|
1651
|
+
const wrapper = mount(FleetClusterTargets, {
|
|
1652
|
+
props: {
|
|
1653
|
+
targets: targets as any,
|
|
1654
|
+
namespace: 'fleet-default',
|
|
1655
|
+
mode: _EDIT
|
|
1656
|
+
}
|
|
1657
|
+
});
|
|
1658
|
+
|
|
1659
|
+
expect(wrapper.vm.selectedClusterGroups).toStrictEqual(['valid-group']);
|
|
1660
|
+
});
|
|
1661
|
+
|
|
1662
|
+
it('should handle empty allClusterGroups data', () => {
|
|
1663
|
+
const wrapper = mount(FleetClusterTargets, {
|
|
1664
|
+
props: {
|
|
1665
|
+
targets: [],
|
|
1666
|
+
namespace: 'fleet-default',
|
|
1667
|
+
mode: _EDIT
|
|
1668
|
+
}
|
|
1669
|
+
});
|
|
1670
|
+
|
|
1671
|
+
wrapper.setData({ allClusterGroups: [] });
|
|
1672
|
+
|
|
1673
|
+
expect(() => wrapper.vm.clusterGroupsOptions).not.toThrow();
|
|
1674
|
+
expect(wrapper.vm.clusterGroupsOptions).toStrictEqual([]);
|
|
1675
|
+
});
|
|
1676
|
+
|
|
1677
|
+
it('should handle clusterGroups with missing nameDisplay', () => {
|
|
1678
|
+
const mockClusterGroups = [
|
|
1679
|
+
{
|
|
1680
|
+
metadata: { namespace: 'fleet-default', name: 'group-1' }
|
|
1681
|
+
// Missing nameDisplay
|
|
1682
|
+
},
|
|
1683
|
+
{
|
|
1684
|
+
metadata: { namespace: 'fleet-default', name: 'group-2' },
|
|
1685
|
+
nameDisplay: 'Group 2'
|
|
1686
|
+
}
|
|
1687
|
+
];
|
|
1688
|
+
|
|
1689
|
+
const wrapper = mount(FleetClusterTargets, {
|
|
1690
|
+
props: {
|
|
1691
|
+
targets: [],
|
|
1692
|
+
namespace: 'fleet-default',
|
|
1693
|
+
mode: _EDIT
|
|
1694
|
+
}
|
|
1695
|
+
});
|
|
1696
|
+
|
|
1697
|
+
wrapper.setData({ allClusterGroups: mockClusterGroups });
|
|
1698
|
+
|
|
1699
|
+
const options = wrapper.vm.clusterGroupsOptions;
|
|
1700
|
+
|
|
1701
|
+
expect(options).toStrictEqual([
|
|
1702
|
+
{ label: undefined, value: 'group-1' },
|
|
1703
|
+
{ label: 'Group 2', value: 'group-2' }
|
|
1704
|
+
]);
|
|
1705
|
+
});
|
|
1706
|
+
});
|
|
1707
|
+
|
|
1708
|
+
describe('clusterGroup Component Lifecycle', () => {
|
|
1709
|
+
it('should preserve clusterGroup selections during component updates', async() => {
|
|
1710
|
+
const wrapper = mount(FleetClusterTargets, {
|
|
1711
|
+
props: {
|
|
1712
|
+
targets: [],
|
|
1713
|
+
namespace: 'fleet-default',
|
|
1714
|
+
mode: _EDIT
|
|
1715
|
+
}
|
|
1716
|
+
});
|
|
1717
|
+
|
|
1718
|
+
// Set initial selection
|
|
1719
|
+
wrapper.vm.selectClusterGroups(['persistent-group']);
|
|
1720
|
+
await flushPromises();
|
|
1721
|
+
|
|
1722
|
+
// Trigger component update by changing namespace
|
|
1723
|
+
await wrapper.setProps({ namespace: 'different-namespace' });
|
|
1724
|
+
await flushPromises();
|
|
1725
|
+
|
|
1726
|
+
// In EDIT mode, selections should be preserved unless explicitly reset
|
|
1727
|
+
expect(wrapper.vm.selectedClusterGroups).toStrictEqual(['persistent-group']);
|
|
1728
|
+
});
|
|
1729
|
+
|
|
1730
|
+
it('should clear clusterGroup selections on namespace change in CREATE mode', async() => {
|
|
1731
|
+
const wrapper = mount(FleetClusterTargets, {
|
|
1732
|
+
props: {
|
|
1733
|
+
targets: [],
|
|
1734
|
+
namespace: 'fleet-default',
|
|
1735
|
+
mode: _CREATE
|
|
1736
|
+
}
|
|
1737
|
+
});
|
|
1738
|
+
|
|
1739
|
+
// Set initial selection
|
|
1740
|
+
wrapper.vm.selectClusterGroups(['temp-group']);
|
|
1741
|
+
await flushPromises();
|
|
1742
|
+
|
|
1743
|
+
// Mock the reset method call that happens on namespace change in CREATE mode
|
|
1744
|
+
const resetSpy = jest.spyOn(wrapper.vm, 'reset');
|
|
1745
|
+
|
|
1746
|
+
await wrapper.setProps({ namespace: 'different-namespace' });
|
|
1747
|
+
|
|
1748
|
+
// Manually trigger reset to simulate the watcher behavior
|
|
1749
|
+
wrapper.vm.reset();
|
|
1750
|
+
|
|
1751
|
+
expect(resetSpy).toHaveBeenCalledWith();
|
|
1752
|
+
expect(wrapper.vm.selectedClusterGroups).toStrictEqual([]);
|
|
1753
|
+
});
|
|
1754
|
+
});
|
|
1224
1755
|
});
|