@rancher/shell 3.0.5-rc.5 → 3.0.5-rc.7
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/data/aws-regions.json +1 -0
- package/assets/images/key.svg +17 -0
- package/assets/styles/base/_spacing.scss +2 -2
- package/assets/styles/base/_variables.scss +17 -11
- package/assets/styles/global/_form.scss +1 -1
- package/assets/styles/global/_labeled-input.scss +1 -1
- package/assets/styles/themes/_dark.scss +5 -0
- package/assets/styles/themes/_light.scss +11 -2
- package/assets/styles/vendor/vue-select.scss +1 -1
- package/assets/translations/en-us.yaml +426 -64
- package/assets/translations/zh-hans.yaml +3 -4
- package/cloud-credential/gcp.vue +9 -1
- package/components/AppModal.vue +2 -0
- package/components/CodeMirror.vue +2 -2
- package/components/ConfigMapSettings/Settings.vue +377 -0
- package/components/ConfigMapSettings/index.vue +354 -0
- package/components/CruResource.vue +1 -2
- package/components/DetailText.vue +61 -11
- package/components/Drawer/Chrome.vue +115 -0
- package/components/Drawer/ResourceDetailDrawer/ConfigTab.vue +61 -0
- package/components/Drawer/ResourceDetailDrawer/YamlTab.vue +48 -0
- package/components/Drawer/ResourceDetailDrawer/__tests__/ConfigTab.test.ts +54 -0
- package/components/Drawer/ResourceDetailDrawer/__tests__/YamlTab.test.ts +80 -0
- package/components/Drawer/ResourceDetailDrawer/__tests__/composables.test.ts +106 -0
- package/components/Drawer/ResourceDetailDrawer/__tests__/helpers.test.ts +42 -0
- package/components/Drawer/ResourceDetailDrawer/composables.ts +53 -0
- package/components/Drawer/ResourceDetailDrawer/helpers.ts +10 -0
- package/components/Drawer/ResourceDetailDrawer/index.vue +111 -0
- package/components/GrowlManager.vue +16 -15
- package/components/IconOrSvg.vue +5 -0
- package/components/KeyValueView.vue +1 -1
- package/components/Loading.vue +1 -1
- package/components/LocaleSelector.vue +9 -1
- package/components/PaginatedResourceTable.vue +46 -1
- package/components/ProgressBarMulti.vue +1 -0
- package/components/PromptModal.vue +6 -1
- package/components/PromptRestore.vue +22 -44
- package/components/RelatedResources.vue +4 -12
- package/components/Resource/Detail/Additional.vue +46 -0
- package/components/Resource/Detail/Metadata/Annotations/__tests__/index.test.ts +1 -1
- package/components/Resource/Detail/Metadata/Annotations/index.vue +5 -0
- package/components/Resource/Detail/Metadata/IdentifyingInformation/__tests__/identifying-fields.test.ts +223 -0
- package/components/Resource/Detail/Metadata/IdentifyingInformation/composable.ts +47 -256
- package/components/Resource/Detail/Metadata/IdentifyingInformation/identifying-fields.ts +317 -0
- package/components/Resource/Detail/Metadata/IdentifyingInformation/index.vue +34 -5
- package/components/Resource/Detail/Metadata/KeyValue.vue +32 -22
- package/components/Resource/Detail/Metadata/Labels/__tests__/index.test.ts +1 -1
- package/components/Resource/Detail/Metadata/Labels/index.vue +4 -0
- package/components/Resource/Detail/Metadata/Rectangle.vue +3 -1
- package/components/Resource/Detail/Metadata/__tests__/KeyValue.test.ts +1 -1
- package/components/Resource/Detail/Metadata/__tests__/Rectangle.test.ts +1 -1
- package/components/Resource/Detail/Metadata/__tests__/composables.test.ts +75 -0
- package/components/Resource/Detail/Metadata/composables.ts +60 -11
- package/components/Resource/Detail/Metadata/index.vue +12 -5
- package/components/Resource/Detail/Page.vue +15 -0
- package/components/Resource/Detail/ResourceRow.vue +37 -18
- package/components/Resource/Detail/ResourceTabs/ConfigMapDataTab/__tests__/composables.test.ts +29 -0
- package/components/Resource/Detail/ResourceTabs/ConfigMapDataTab/__tests__/index.test.ts +48 -0
- package/components/Resource/Detail/ResourceTabs/ConfigMapDataTab/composables.ts +31 -0
- package/components/Resource/Detail/ResourceTabs/ConfigMapDataTab/index.vue +50 -0
- package/components/Resource/Detail/ResourceTabs/KnownHostsTab/__tests__/composables.test.ts +66 -0
- package/components/Resource/Detail/ResourceTabs/KnownHostsTab/composables.ts +21 -0
- package/components/Resource/Detail/ResourceTabs/KnownHostsTab/index.vue +31 -0
- package/components/Resource/Detail/ResourceTabs/SecretDataTab/Basic.vue +45 -0
- package/components/Resource/Detail/ResourceTabs/SecretDataTab/BasicAuth.vue +31 -0
- package/components/Resource/Detail/ResourceTabs/SecretDataTab/Certificate.vue +31 -0
- package/components/Resource/Detail/ResourceTabs/SecretDataTab/Registry.vue +22 -0
- package/components/Resource/Detail/ResourceTabs/SecretDataTab/ServiceAccountToken.vue +31 -0
- package/components/Resource/Detail/ResourceTabs/SecretDataTab/Ssh.vue +32 -0
- package/components/Resource/Detail/ResourceTabs/SecretDataTab/__tests__/Basic.test.ts +40 -0
- package/components/Resource/Detail/ResourceTabs/SecretDataTab/__tests__/BasicAuth.test.ts +33 -0
- package/components/Resource/Detail/ResourceTabs/SecretDataTab/__tests__/Certificate.test.ts +33 -0
- package/components/Resource/Detail/ResourceTabs/SecretDataTab/__tests__/Registry.test.ts +27 -0
- package/components/Resource/Detail/ResourceTabs/SecretDataTab/__tests__/ServiceAccountToken.test.ts +33 -0
- package/components/Resource/Detail/ResourceTabs/SecretDataTab/__tests__/Ssh.test.ts +33 -0
- package/components/Resource/Detail/ResourceTabs/SecretDataTab/__tests__/auth-types.test.ts +186 -0
- package/components/Resource/Detail/ResourceTabs/SecretDataTab/__tests__/composables.test.ts +102 -0
- package/components/Resource/Detail/ResourceTabs/SecretDataTab/auth-types.ts +109 -0
- package/components/Resource/Detail/ResourceTabs/SecretDataTab/composeables.ts +52 -0
- package/components/Resource/Detail/ResourceTabs/SecretDataTab/index.vue +71 -0
- package/components/Resource/Detail/SpacedRow.vue +1 -1
- package/components/Resource/Detail/TitleBar/Title.vue +2 -1
- package/components/Resource/Detail/TitleBar/__tests__/Title.test.ts +1 -1
- package/components/Resource/Detail/TitleBar/__tests__/Top.test.ts +1 -1
- package/components/Resource/Detail/TitleBar/__tests__/composables.test.ts +63 -0
- package/components/Resource/Detail/TitleBar/__tests__/index.test.ts +1 -1
- package/components/Resource/Detail/TitleBar/composables.ts +45 -0
- package/components/Resource/Detail/TitleBar/index.vue +85 -13
- package/components/Resource/Detail/composables.ts +45 -0
- package/components/ResourceDetail/Masthead/__tests__/index.test.ts +70 -0
- package/components/ResourceDetail/{__tests__/Masthead.test.ts → Masthead/__tests__/legacy.test.ts} +3 -3
- package/components/ResourceDetail/Masthead/index.vue +65 -0
- package/components/ResourceDetail/Masthead/latest.vue +44 -0
- package/components/ResourceDetail/{Masthead.vue → Masthead/legacy.vue} +1 -1
- package/components/ResourceDetail/__tests__/index.test.ts +26 -5
- package/components/ResourceDetail/index.vue +33 -17
- package/components/ResourceDetail/legacy.vue +18 -1
- package/components/ResourceList/Masthead.vue +6 -0
- package/components/ResourceList/index.vue +1 -0
- package/components/ResourceTable.vue +6 -1
- package/components/ResourceYaml.vue +15 -2
- package/components/RichTranslation.vue +106 -0
- package/components/SlideInPanelManager.vue +46 -11
- package/components/SortableTable/index.vue +1 -1
- package/components/SortableTable/selection.js +0 -1
- package/components/StateDot/index.vue +28 -0
- package/components/Tabbed/index.vue +17 -16
- package/components/Wizard.vue +4 -2
- package/components/__tests__/ConfigMapSettings.test.ts +376 -0
- package/components/__tests__/GrowlManager.test.ts +0 -25
- package/components/__tests__/PromptRestore.test.ts +1 -65
- package/components/__tests__/RichTranslation.test.ts +115 -0
- package/components/auth/login/ldap.vue +1 -1
- package/components/fleet/FleetApplications.vue +0 -7
- package/components/fleet/FleetClusterTargets/TargetsList.vue +66 -0
- package/components/fleet/FleetClusterTargets/index.vue +455 -0
- package/components/fleet/FleetClusters.vue +25 -6
- package/components/fleet/FleetGitRepoPaths.vue +476 -0
- package/components/fleet/FleetHelmOps.vue +8 -0
- package/components/fleet/FleetRepos.vue +1 -6
- package/components/fleet/FleetResources.vue +4 -5
- package/components/fleet/FleetValuesFrom.vue +295 -0
- package/components/fleet/__tests__/FleetClusterTargets.test.ts +1224 -0
- package/components/fleet/__tests__/FleetGitRepoPaths.test.ts +265 -0
- package/components/fleet/__tests__/FleetOCIStorageSecret.test.ts +13 -13
- package/components/fleet/__tests__/FleetValuesFrom.test.ts +300 -0
- package/components/fleet/dashboard/ResourceCard.vue +1 -0
- package/components/fleet/dashboard/ResourceCardSummary.vue +1 -5
- package/components/fleet/dashboard/ResourceDetails.vue +8 -10
- package/components/fleet/dashboard/ResourcePanel.vue +17 -9
- package/components/form/ArrayList.vue +13 -2
- package/components/form/ChangePassword.vue +3 -1
- package/components/form/FileImageSelector.vue +1 -1
- package/components/form/Footer.vue +10 -4
- package/components/form/KeyValue.vue +81 -43
- package/components/form/LabeledSelect.vue +56 -16
- package/components/form/Labels.vue +90 -17
- package/components/form/MatchExpressions.vue +46 -5
- package/components/form/NameNsDescription.vue +2 -1
- package/components/form/Networking.vue +24 -19
- package/components/form/ResourceLabeledSelect.vue +4 -3
- package/components/form/ResourceSelector.vue +1 -0
- package/components/form/ResourceTabs/index.vue +5 -0
- package/components/form/SecretSelector.vue +9 -2
- package/components/form/Select.vue +57 -19
- package/components/form/SelectOrCreateAuthSecret.vue +6 -3
- package/components/form/SimpleSecretSelector.vue +9 -2
- package/components/form/Taints.vue +21 -2
- package/components/form/UnitInput.vue +8 -0
- package/components/form/ValueFromResource.vue +1 -1
- package/components/form/__tests__/LabeledSelect.test.ts +8 -4
- package/components/form/__tests__/Labels.test.ts +360 -0
- package/components/form/__tests__/MatchExpressions.test.ts +16 -13
- package/components/form/__tests__/Networking.test.ts +116 -0
- package/components/form/__tests__/Select.test.ts +5 -2
- package/components/formatter/FleetApplicationSource.vue +1 -1
- package/components/formatter/PodImages.vue +1 -1
- package/components/formatter/WorkloadHealthScale.vue +1 -1
- package/components/formatter/__tests__/LiveDate.test.ts +10 -2
- package/components/google/AccountAccess.vue +209 -0
- package/components/google/types/gcp.d.ts +136 -0
- package/components/google/types/index.d.ts +101 -0
- package/components/google/util/__mocks__/gcp.ts +465 -0
- package/components/google/util/formatter.ts +82 -0
- package/components/google/util/gcp.ts +134 -0
- package/components/google/util/index.d.ts +11 -0
- package/components/nav/Favorite.vue +1 -1
- package/components/nav/Group.vue +71 -45
- package/components/nav/Header.vue +5 -1
- package/components/nav/NamespaceFilter.vue +13 -1
- package/components/nav/NotificationCenter/Notification.vue +510 -0
- package/components/nav/NotificationCenter/NotificationHeader.vue +112 -0
- package/components/nav/NotificationCenter/index.vue +148 -0
- package/composables/drawer.ts +26 -0
- package/composables/resources.test.ts +63 -0
- package/composables/resources.ts +38 -0
- package/composables/useIsNewDetailPageEnabled.ts +17 -0
- package/config/labels-annotations.js +8 -0
- package/config/pagination-table-headers.js +8 -1
- package/config/product/auth.js +16 -1
- package/config/product/{cis.js → compliance.js} +23 -26
- package/config/product/explorer.js +32 -3
- package/config/product/fleet.js +7 -0
- package/config/product/manager.js +0 -1
- package/config/product/settings.js +22 -11
- package/config/query-params.js +13 -0
- package/config/roles.ts +1 -1
- package/config/router/navigation-guards/authentication.js +51 -2
- package/config/router/routes.js +47 -31
- package/config/settings.ts +21 -3
- package/config/store.js +2 -0
- package/config/system-namespaces.js +1 -1
- package/config/table-headers.js +32 -3
- package/config/types.js +16 -7
- package/config/version.js +1 -1
- package/core/plugin.ts +32 -7
- package/core/types.ts +18 -1
- package/detail/{cis.cattle.io.clusterscan.vue → compliance.cattle.io.clusterscan.vue} +22 -18
- package/detail/management.cattle.io.fleetworkspace.vue +18 -27
- package/detail/management.cattle.io.oidcclient.vue +369 -0
- package/detail/node.vue +2 -2
- package/detail/pod.vue +2 -2
- package/detail/provisioning.cattle.io.cluster.vue +3 -47
- package/detail/service.vue +10 -1
- package/detail/workload/index.vue +8 -2
- package/dialog/ExtensionCatalogUninstallDialog.vue +7 -4
- package/dialog/GenericPrompt.vue +1 -1
- package/dialog/ImportDialog.vue +8 -8
- package/dialog/OidcClientSecretDialog.vue +117 -0
- package/dialog/RotateEncryptionKeyDialog.vue +10 -30
- package/edit/__tests__/cis.cattle.io.clusterscan.test.ts +3 -3
- package/edit/__tests__/fleet.cattle.io.gitrepo.test.ts +5 -2
- package/edit/auth/ldap/__tests__/config.test.ts +14 -0
- package/edit/auth/ldap/config.vue +24 -0
- package/edit/autoscaling.horizontalpodautoscaler/index.vue +4 -1
- package/edit/{cis.cattle.io.clusterscan.vue → compliance.cattle.io.clusterscan.vue} +30 -31
- package/edit/{cis.cattle.io.clusterscanbenchmark.vue → compliance.cattle.io.clusterscanbenchmark.vue} +4 -4
- package/edit/{cis.cattle.io.clusterscanprofile.vue → compliance.cattle.io.clusterscanprofile.vue} +5 -5
- package/edit/configmap.vue +8 -2
- package/edit/constraints.gatekeeper.sh.constraint/index.vue +1 -0
- package/edit/fleet.cattle.io.gitrepo.vue +44 -222
- package/edit/fleet.cattle.io.helmop.vue +44 -269
- package/edit/helm.cattle.io.projecthelmchart.vue +1 -0
- package/edit/k8s.cni.cncf.io.networkattachmentdefinition.vue +1 -0
- package/edit/logging-flow/index.vue +1 -0
- package/edit/logging.banzaicloud.io.output/index.vue +1 -0
- package/edit/management.cattle.io.fleetworkspace.vue +1 -0
- package/edit/management.cattle.io.oidcclient.vue +162 -0
- package/edit/management.cattle.io.project.vue +4 -1
- package/edit/monitoring.coreos.com.alertmanagerconfig/index.vue +1 -1
- package/edit/monitoring.coreos.com.alertmanagerconfig/receiverConfig.vue +5 -0
- package/edit/monitoring.coreos.com.prometheusrule/index.vue +1 -0
- package/edit/monitoring.coreos.com.receiver/auth.vue +30 -30
- package/edit/monitoring.coreos.com.receiver/index.vue +1 -0
- package/edit/monitoring.coreos.com.receiver/types/email.vue +1 -1
- package/edit/monitoring.coreos.com.route.vue +1 -0
- package/edit/namespace.vue +1 -0
- package/edit/networking.istio.io.destinationrule/index.vue +4 -1
- package/edit/networking.k8s.io.ingress/Certificate.vue +12 -12
- package/edit/networking.k8s.io.ingress/__tests__/Certificate.test.ts +165 -0
- package/edit/networking.k8s.io.ingress/index.vue +4 -1
- package/edit/networking.k8s.io.networkpolicy/PolicyRules.vue +7 -2
- package/edit/networking.k8s.io.networkpolicy/index.vue +6 -2
- package/edit/node.vue +1 -0
- package/edit/persistentvolume/index.vue +4 -1
- package/edit/provisioning.cattle.io.cluster/__tests__/rke2.test.ts +3 -2
- package/edit/provisioning.cattle.io.cluster/rke2.vue +516 -426
- package/edit/provisioning.cattle.io.cluster/tabs/Basics.vue +48 -39
- package/edit/provisioning.cattle.io.cluster/tabs/MachinePool.vue +5 -0
- package/edit/provisioning.cattle.io.cluster/tabs/registries/RegistryConfigs.vue +2 -2
- package/edit/resources.cattle.io.restore.vue +1 -1
- package/edit/secret/basic.vue +1 -0
- package/edit/secret/index.vue +127 -15
- package/edit/service.vue +4 -1
- package/edit/serviceaccount.vue +4 -1
- package/edit/storage.k8s.io.storageclass/index.vue +4 -1
- package/edit/workload/index.vue +5 -0
- package/list/{cis.cattle.io.clusterscan.vue → compliance.cattle.io.clusterscan.vue} +2 -2
- package/list/management.cattle.io.oidcclient.vue +108 -0
- package/list/node.vue +2 -0
- package/list/projectsecret.vue +345 -0
- package/list/secret.vue +109 -0
- package/machine-config/amazonec2.vue +3 -24
- package/machine-config/components/GCEImage.vue +374 -0
- package/machine-config/google.vue +617 -0
- package/mixins/__tests__/brand.spec.ts +170 -0
- package/mixins/brand.js +16 -17
- package/mixins/create-edit-view/impl.js +10 -1
- package/mixins/create-edit-view/index.js +5 -0
- package/mixins/resource-fetch-api-pagination.js +24 -8
- package/mixins/resource-fetch.js +3 -1
- package/mixins/vue-select-overrides.js +1 -0
- package/models/cluster.x-k8s.io.machinedeployment.js +11 -2
- package/models/{cis.cattle.io.clusterscan.js → compliance.cattle.io.clusterscan.js} +8 -8
- package/models/{cis.cattle.io.clusterscanbenchmark.js → compliance.cattle.io.clusterscanbenchmark.js} +1 -1
- package/models/{cis.cattle.io.clusterscanprofile.js → compliance.cattle.io.clusterscanprofile.js} +5 -5
- package/models/{cis.cattle.io.clusterscanreport.js → compliance.cattle.io.clusterscanreport.js} +1 -1
- package/models/fleet-application.js +8 -79
- package/models/fleet.cattle.io.cluster.js +13 -2
- package/models/fleet.cattle.io.gitrepo.js +2 -2
- package/models/fleet.cattle.io.helmop.js +9 -39
- package/models/management.cattle.io.fleetworkspace.js +2 -1
- package/models/management.cattle.io.oidcclient.js +18 -0
- package/models/management.cattle.io.registration.js +3 -0
- package/models/provisioning.cattle.io.cluster.js +29 -33
- package/models/secret.js +157 -2
- package/models/service.js +4 -0
- package/models/workload.js +5 -0
- package/package.json +2 -2
- package/pages/about.vue +4 -58
- package/pages/auth/login.vue +1 -1
- package/pages/c/_cluster/apps/charts/AddRepoLink.vue +0 -1
- package/pages/c/_cluster/apps/charts/index.vue +296 -81
- package/pages/c/_cluster/auth/user.retention/index.vue +87 -78
- package/pages/c/_cluster/explorer/index.vue +3 -3
- package/pages/c/_cluster/explorer/projectsecret.vue +34 -0
- package/pages/c/_cluster/explorer/tools/pages/_page.vue +0 -1
- package/pages/c/_cluster/fleet/application/create.vue +3 -2
- package/pages/c/_cluster/fleet/index.vue +94 -57
- package/pages/c/_cluster/fleet/settings/index.vue +229 -0
- package/pages/c/_cluster/longhorn/index.vue +5 -2
- package/pages/c/_cluster/uiplugins/CatalogList/index.vue +16 -1
- package/pages/c/_cluster/uiplugins/PluginInfoPanel.vue +2 -2
- package/pages/explorer/resource/detail/configmap.vue +30 -7
- package/pages/explorer/resource/detail/projectsecret.vue +9 -0
- package/pages/explorer/resource/detail/secret.vue +63 -0
- package/pages/home.vue +9 -55
- package/pages/support/index.vue +4 -6
- package/plugins/dashboard-store/__tests__/normalize.test.ts +223 -0
- package/plugins/dashboard-store/__tests__/resource-class.test.ts +191 -0
- package/plugins/dashboard-store/__tests__/utils/normalize-usecases.ts +1526 -0
- package/plugins/dashboard-store/actions.js +19 -5
- package/plugins/dashboard-store/getters.js +4 -0
- package/plugins/dashboard-store/normalize.js +29 -17
- package/plugins/dashboard-store/resource-class.js +68 -19
- package/plugins/steve/steve-pagination-utils.ts +38 -19
- package/plugins/steve/subscribe.js +6 -1
- package/rancher-components/Banner/Banner.vue +13 -0
- package/rancher-components/Form/Checkbox/Checkbox.vue +9 -4
- package/rancher-components/Form/LabeledInput/LabeledInput.vue +1 -1
- package/rancher-components/LabeledTooltip/LabeledTooltip.vue +1 -0
- package/rancher-components/RcItemCard/RcItemCard.vue +8 -3
- package/store/auth.js +2 -0
- package/store/catalog.js +23 -1
- package/store/growl.js +97 -8
- package/store/index.js +6 -0
- package/store/notifications.ts +426 -0
- package/store/prefs.js +0 -1
- package/store/type-map.js +19 -16
- package/store/uiplugins.ts +15 -1
- package/types/fleet.d.ts +24 -0
- package/types/kube/kube-api.ts +12 -0
- package/types/notifications/index.ts +74 -0
- package/types/shell/index.d.ts +661 -589
- package/types/store/dashboard-store.types.ts +16 -0
- package/types/store/pagination.types.ts +16 -6
- package/utils/__tests__/create-yaml.test.ts +235 -0
- package/utils/__tests__/fleet.test.ts +148 -0
- package/utils/__tests__/object.test.ts +54 -1
- package/utils/__tests__/string.test.ts +273 -1
- package/utils/__tests__/time.test.ts +31 -0
- package/utils/auth.js +9 -2
- package/utils/create-yaml.js +103 -9
- package/utils/crypto/encryption.ts +103 -0
- package/utils/cspAdaptor.ts +51 -0
- package/utils/fleet.ts +54 -65
- package/utils/object.js +36 -0
- package/utils/pagination-utils.ts +19 -1
- package/utils/release-notes.ts +48 -0
- package/utils/selector-typed.ts +7 -2
- package/utils/string.js +24 -0
- package/utils/{time.js → time.ts} +25 -6
- package/utils/uiplugins.ts +22 -0
- package/utils/validators/formRules/index.ts +3 -0
- package/components/Resource/Detail/TitleBar/composable.ts +0 -31
- package/config/product/legacy.js +0 -62
- package/models/etcdbackup.js +0 -45
- package/pages/c/_cluster/legacy/pages/_page.vue +0 -29
- package/pages/c/_cluster/legacy/project/_page.vue +0 -57
- package/pages/c/_cluster/legacy/project/index.vue +0 -32
- package/pages/c/_cluster/legacy/project/pipelines.vue +0 -96
|
@@ -30,7 +30,19 @@ export default {
|
|
|
30
30
|
effectValues: {
|
|
31
31
|
type: Object,
|
|
32
32
|
default: () => DEFAULT_EFFECT_VALUES
|
|
33
|
-
}
|
|
33
|
+
},
|
|
34
|
+
title: {
|
|
35
|
+
type: String,
|
|
36
|
+
default: ''
|
|
37
|
+
},
|
|
38
|
+
addIcon: {
|
|
39
|
+
type: String,
|
|
40
|
+
default: '',
|
|
41
|
+
},
|
|
42
|
+
addClass: {
|
|
43
|
+
type: String,
|
|
44
|
+
default: '',
|
|
45
|
+
},
|
|
34
46
|
},
|
|
35
47
|
|
|
36
48
|
data() {
|
|
@@ -38,6 +50,10 @@ export default {
|
|
|
38
50
|
},
|
|
39
51
|
|
|
40
52
|
computed: {
|
|
53
|
+
_title() {
|
|
54
|
+
return this.title || this.t('tableHeaders.taints');
|
|
55
|
+
},
|
|
56
|
+
|
|
41
57
|
localValue: {
|
|
42
58
|
get() {
|
|
43
59
|
return this.value;
|
|
@@ -60,7 +76,7 @@ export default {
|
|
|
60
76
|
<KeyValue
|
|
61
77
|
:value="value"
|
|
62
78
|
data-testid="taints-keyvalue"
|
|
63
|
-
:title="
|
|
79
|
+
:title="_title"
|
|
64
80
|
:mode="mode"
|
|
65
81
|
:as-map="false"
|
|
66
82
|
:read-allowed="false"
|
|
@@ -70,6 +86,8 @@ export default {
|
|
|
70
86
|
:extra-columns="['effect']"
|
|
71
87
|
:preserve-keys="['effect']"
|
|
72
88
|
:add-label="t('labels.addTaint')"
|
|
89
|
+
:add-icon="addIcon"
|
|
90
|
+
:add-class="addClass"
|
|
73
91
|
:disabled="disabled"
|
|
74
92
|
@update:value="(e) => $emit('update:value', e)"
|
|
75
93
|
>
|
|
@@ -82,6 +100,7 @@ export default {
|
|
|
82
100
|
v-model:value="row.effect"
|
|
83
101
|
:data-testid="`taints-effect-row-${i}`"
|
|
84
102
|
:options="effectOptions"
|
|
103
|
+
:mode="mode"
|
|
85
104
|
:disabled="disabled"
|
|
86
105
|
class="compact-select"
|
|
87
106
|
@update:value="queueUpdate"
|
|
@@ -140,6 +140,13 @@ export default {
|
|
|
140
140
|
type: Boolean,
|
|
141
141
|
default: false,
|
|
142
142
|
},
|
|
143
|
+
/**
|
|
144
|
+
* The sub-label for the Labeled Input.
|
|
145
|
+
*/
|
|
146
|
+
subLabel: {
|
|
147
|
+
type: String,
|
|
148
|
+
default: null
|
|
149
|
+
}
|
|
143
150
|
},
|
|
144
151
|
|
|
145
152
|
data() {
|
|
@@ -247,6 +254,7 @@ export default {
|
|
|
247
254
|
:placeholder="placeholder"
|
|
248
255
|
:hide-arrows="hideArrows"
|
|
249
256
|
:aria-describedby="displayUnit ? describedById : undefined"
|
|
257
|
+
:sub-label="subLabel"
|
|
250
258
|
@update:value="update"
|
|
251
259
|
@blur="update($event.target.value)"
|
|
252
260
|
>
|
|
@@ -32,7 +32,7 @@ export default {
|
|
|
32
32
|
{ value: 'simple', label: 'Key/Value Pair' },
|
|
33
33
|
{ value: 'resourceFieldRef', label: 'Resource' },
|
|
34
34
|
{ value: 'configMapKeyRef', label: 'ConfigMap Key' },
|
|
35
|
-
{ value: 'secretKeyRef', label: 'Secret
|
|
35
|
+
{ value: 'secretKeyRef', label: 'Secret Key' },
|
|
36
36
|
{ value: 'fieldRef', label: 'Pod Field' },
|
|
37
37
|
{ value: 'secretRef', label: 'Secret' },
|
|
38
38
|
{ value: 'configMapRef', label: 'ConfigMap' },
|
|
@@ -168,9 +168,9 @@ describe('component: LabeledSelect', () => {
|
|
|
168
168
|
|
|
169
169
|
await wrapper.trigger('click');
|
|
170
170
|
|
|
171
|
-
const dropdownOpen = wrapper.
|
|
171
|
+
const dropdownOpen = wrapper.vm.isOpen;
|
|
172
172
|
|
|
173
|
-
expect(dropdownOpen
|
|
173
|
+
expect(dropdownOpen).toBe(isOpen);
|
|
174
174
|
});
|
|
175
175
|
});
|
|
176
176
|
|
|
@@ -208,6 +208,7 @@ describe('component: LabeledSelect', () => {
|
|
|
208
208
|
const wrapper = mount(ParentComponent);
|
|
209
209
|
|
|
210
210
|
// https://test-utils.vuejs.org/guide/essentials/event-handling#Asserting-the-arguments-of-the-event
|
|
211
|
+
await wrapper.trigger('click');
|
|
211
212
|
await wrapper.find('input').trigger('focus');
|
|
212
213
|
await wrapper.find('.vs__dropdown-option').trigger('click');
|
|
213
214
|
|
|
@@ -267,7 +268,8 @@ describe('component: LabeledSelect', () => {
|
|
|
267
268
|
value,
|
|
268
269
|
label: 'some-label',
|
|
269
270
|
options,
|
|
270
|
-
searchable: true
|
|
271
|
+
searchable: true,
|
|
272
|
+
loading: false,
|
|
271
273
|
}
|
|
272
274
|
});
|
|
273
275
|
|
|
@@ -281,7 +283,9 @@ describe('component: LabeledSelect', () => {
|
|
|
281
283
|
await input.trigger('keydown.enter');
|
|
282
284
|
|
|
283
285
|
// mimic pressing space on search box inside v-select
|
|
284
|
-
|
|
286
|
+
const search = input.find('input');
|
|
287
|
+
|
|
288
|
+
await search.trigger('keydown.space', mockEvent);
|
|
285
289
|
|
|
286
290
|
// eslint-disable-next-line
|
|
287
291
|
expect(spyFocus).toHaveBeenCalled();
|
|
@@ -0,0 +1,360 @@
|
|
|
1
|
+
import { mount } from '@vue/test-utils';
|
|
2
|
+
import Labels, { Factory } from '@shell/components/form/Labels.vue';
|
|
3
|
+
import KeyValue from '@shell/components/form/KeyValue.vue';
|
|
4
|
+
import { ToggleSwitch } from '@components/Form/ToggleSwitch';
|
|
5
|
+
import { _EDIT, _VIEW } from '@shell/config/query-params';
|
|
6
|
+
|
|
7
|
+
const mockT = jest.fn((key: string) => key);
|
|
8
|
+
|
|
9
|
+
describe('class: Factory', () => {
|
|
10
|
+
const mockProtectedWarning = 'Protected Key';
|
|
11
|
+
|
|
12
|
+
it('should correctly initialize with no protected keys or regexes', () => {
|
|
13
|
+
const factory = new Factory([], [], mockProtectedWarning, { a: '1', b: '2' });
|
|
14
|
+
|
|
15
|
+
expect((factory as any).protectedKeys).toStrictEqual([]);
|
|
16
|
+
expect((factory as any).protectedRegexes).toStrictEqual([]);
|
|
17
|
+
expect((factory as any).protectedWarning).toBe(mockProtectedWarning);
|
|
18
|
+
expect(factory.initValue).toStrictEqual({ a: '1', b: '2' });
|
|
19
|
+
expect(factory.value).toStrictEqual({ a: '1', b: '2' });
|
|
20
|
+
expect(factory.keyErrors).toStrictEqual({});
|
|
21
|
+
expect(factory.hasProtectedKeys).toBe(false);
|
|
22
|
+
});
|
|
23
|
+
|
|
24
|
+
it('should correctly initialize with protected keys', () => {
|
|
25
|
+
const factory = new Factory(['key1'], [], mockProtectedWarning, { key1: 'value1', key2: 'value2' });
|
|
26
|
+
|
|
27
|
+
expect((factory as any).protectedKeys).toStrictEqual(['key1']);
|
|
28
|
+
expect(factory.value).toStrictEqual({ key2: 'value2' });
|
|
29
|
+
expect(factory.hasProtectedKeys).toBe(true);
|
|
30
|
+
});
|
|
31
|
+
|
|
32
|
+
it('should correctly initialize with protected regexes', () => {
|
|
33
|
+
const factory = new Factory([], [/^key/], mockProtectedWarning, { key1: 'value1', other: 'value2' });
|
|
34
|
+
|
|
35
|
+
expect((factory as any).protectedRegexes.map((r: RegExp) => r.source)).toStrictEqual(['^key']);
|
|
36
|
+
expect(factory.value).toStrictEqual({ other: 'value2' });
|
|
37
|
+
expect(factory.hasProtectedKeys).toBe(true);
|
|
38
|
+
});
|
|
39
|
+
|
|
40
|
+
it('should omit protected keys from value but keep them in initValue', () => {
|
|
41
|
+
const factory = new Factory(['protected'], [], mockProtectedWarning, { protected: 'pVal', normal: 'nVal' });
|
|
42
|
+
|
|
43
|
+
expect(factory.initValue).toStrictEqual({ protected: 'pVal', normal: 'nVal' });
|
|
44
|
+
expect(factory.value).toStrictEqual({ normal: 'nVal' });
|
|
45
|
+
});
|
|
46
|
+
|
|
47
|
+
it('should update value and call callbackFn, preserving initial protected keys', () => {
|
|
48
|
+
const initialValue = {
|
|
49
|
+
system: 'sysVal', user: 'userVal', system2: 'sysVal'
|
|
50
|
+
};
|
|
51
|
+
const factory = new Factory(['system', 'system2'], [], mockProtectedWarning, initialValue);
|
|
52
|
+
const callback = jest.fn();
|
|
53
|
+
|
|
54
|
+
const newValue = {
|
|
55
|
+
newUser: 'newUVal', user: 'updatedUserVal', newProtected: 'newPVal', system: 'foo'
|
|
56
|
+
};
|
|
57
|
+
|
|
58
|
+
factory.update(newValue, callback);
|
|
59
|
+
|
|
60
|
+
// The internal factory.value is just the new set
|
|
61
|
+
expect(factory.value).toStrictEqual(newValue);
|
|
62
|
+
|
|
63
|
+
// The callback should receive the mix of new unprotected values and initial protected values
|
|
64
|
+
expect(callback).toHaveBeenCalledWith({
|
|
65
|
+
newProtected: 'newPVal',
|
|
66
|
+
newUser: 'newUVal',
|
|
67
|
+
user: 'updatedUserVal',
|
|
68
|
+
system: 'sysVal', // 'system' is the original protected from initialValue, sysVal is the original value
|
|
69
|
+
system2: 'sysVal' // 'system2' is the original protected from initialValue
|
|
70
|
+
});
|
|
71
|
+
});
|
|
72
|
+
|
|
73
|
+
it('should handle null/undefined update value gracefully', () => {
|
|
74
|
+
const initialValue = { system: 'sysVal', user: 'userVal' };
|
|
75
|
+
const factory = new Factory(['system'], [], mockProtectedWarning, initialValue);
|
|
76
|
+
const callback = jest.fn();
|
|
77
|
+
|
|
78
|
+
factory.update({}, callback);
|
|
79
|
+
|
|
80
|
+
expect(factory.value).toStrictEqual({});
|
|
81
|
+
expect(factory.keyErrors).toStrictEqual({});
|
|
82
|
+
expect(callback).toHaveBeenCalledWith({ system: 'sysVal' }); // Only the original protected values
|
|
83
|
+
});
|
|
84
|
+
|
|
85
|
+
it('should correctly identify protected keys based on both array and regex', () => {
|
|
86
|
+
const factory = new Factory(['staticKey'], [/^dynamic/], mockProtectedWarning, {});
|
|
87
|
+
|
|
88
|
+
expect((factory as any).isProtected('staticKey')).toBe(true);
|
|
89
|
+
expect((factory as any).isProtected('dynamicKey')).toBe(true);
|
|
90
|
+
expect((factory as any).isProtected('otherKey')).toBe(false);
|
|
91
|
+
});
|
|
92
|
+
});
|
|
93
|
+
|
|
94
|
+
describe('component: Labels', () => {
|
|
95
|
+
const mockValue = {
|
|
96
|
+
labels: {
|
|
97
|
+
'kubernetes.io/hostname': 'test-app',
|
|
98
|
+
'my-label': 'my-value'
|
|
99
|
+
},
|
|
100
|
+
systemLabels: ['kubernetes.io/hostname'],
|
|
101
|
+
annotations: {
|
|
102
|
+
'cattle.io/system': 'user',
|
|
103
|
+
'my-annotation': 'my-annotation'
|
|
104
|
+
},
|
|
105
|
+
systemAnnotations: ['cattle.io/system'],
|
|
106
|
+
setLabels: jest.fn(),
|
|
107
|
+
setAnnotations: jest.fn(),
|
|
108
|
+
};
|
|
109
|
+
|
|
110
|
+
it('should initialize with correct data properties', () => {
|
|
111
|
+
const wrapper = mount(Labels, {
|
|
112
|
+
props: {
|
|
113
|
+
value: mockValue,
|
|
114
|
+
mode: 'create',
|
|
115
|
+
},
|
|
116
|
+
global: { mocks: { t: mockT } },
|
|
117
|
+
});
|
|
118
|
+
|
|
119
|
+
const data = (wrapper.vm as any).$data;
|
|
120
|
+
|
|
121
|
+
expect(data.labels).toBeDefined();
|
|
122
|
+
expect(data.labels.initValue).toStrictEqual(mockValue.labels);
|
|
123
|
+
expect(data.labels.protectedKeys).toStrictEqual(mockValue.systemLabels);
|
|
124
|
+
expect(data.labels.value).toStrictEqual({ 'my-label': 'my-value' });
|
|
125
|
+
expect(data.labels.hasProtectedKeys).toBe(true);
|
|
126
|
+
expect(data.labels.keyErrors).toStrictEqual({}); // only when manually update
|
|
127
|
+
|
|
128
|
+
expect(data.annotations).toBeDefined();
|
|
129
|
+
expect(data.annotations.initValue).toStrictEqual(mockValue.annotations);
|
|
130
|
+
expect(data.annotations.protectedKeys).toStrictEqual(mockValue.systemAnnotations);
|
|
131
|
+
expect(data.annotations.value).toStrictEqual({ 'my-annotation': 'my-annotation' });
|
|
132
|
+
expect(data.annotations.hasProtectedKeys).toBe(true);
|
|
133
|
+
expect(data.annotations.keyErrors).toStrictEqual({}); // only when manually update
|
|
134
|
+
|
|
135
|
+
expect(data.toggler).toBe(false);
|
|
136
|
+
});
|
|
137
|
+
|
|
138
|
+
it('should render KeyValue for labels', () => {
|
|
139
|
+
const wrapper = mount(Labels, {
|
|
140
|
+
props: {
|
|
141
|
+
value: mockValue,
|
|
142
|
+
mode: 'create',
|
|
143
|
+
},
|
|
144
|
+
global: { mocks: { t: mockT } },
|
|
145
|
+
});
|
|
146
|
+
|
|
147
|
+
const labelsKeyValue = wrapper.findComponent(KeyValue);
|
|
148
|
+
|
|
149
|
+
expect(labelsKeyValue.exists()).toBe(true);
|
|
150
|
+
expect(labelsKeyValue.props('value')).toStrictEqual({ 'my-label': 'my-value' });
|
|
151
|
+
expect(labelsKeyValue.props('addLabel')).toBe('labels.addLabel');
|
|
152
|
+
expect(labelsKeyValue.props('mode')).toBe('create');
|
|
153
|
+
expect(labelsKeyValue.props('keyErrors')).toStrictEqual({});
|
|
154
|
+
});
|
|
155
|
+
|
|
156
|
+
it('should render KeyValue for annotations if showAnnotations is true', () => {
|
|
157
|
+
const wrapper = mount(Labels, {
|
|
158
|
+
props: {
|
|
159
|
+
value: mockValue,
|
|
160
|
+
mode: 'create',
|
|
161
|
+
showAnnotations: true,
|
|
162
|
+
},
|
|
163
|
+
global: { mocks: { t: mockT } },
|
|
164
|
+
});
|
|
165
|
+
|
|
166
|
+
const keyValueComponents = wrapper.findAllComponents(KeyValue);
|
|
167
|
+
|
|
168
|
+
expect(keyValueComponents).toHaveLength(2);
|
|
169
|
+
const annotationsKeyValue = keyValueComponents[1]; // The second KeyValue is for annotations
|
|
170
|
+
|
|
171
|
+
expect(annotationsKeyValue.exists()).toBe(true);
|
|
172
|
+
expect(annotationsKeyValue.props('value')).toStrictEqual({ 'my-annotation': 'my-annotation' });
|
|
173
|
+
expect(annotationsKeyValue.props('addLabel')).toBe('labels.addAnnotation');
|
|
174
|
+
expect(annotationsKeyValue.props('mode')).toBe('create');
|
|
175
|
+
expect(annotationsKeyValue.props('keyErrors')).toStrictEqual({});
|
|
176
|
+
});
|
|
177
|
+
|
|
178
|
+
it('should not render KeyValue for annotations if showAnnotations is false', () => {
|
|
179
|
+
const wrapper = mount(Labels, {
|
|
180
|
+
props: {
|
|
181
|
+
value: mockValue,
|
|
182
|
+
mode: 'create',
|
|
183
|
+
showAnnotations: false,
|
|
184
|
+
},
|
|
185
|
+
global: { mocks: { t: mockT } },
|
|
186
|
+
});
|
|
187
|
+
|
|
188
|
+
const keyValueComponents = wrapper.findAllComponents(KeyValue);
|
|
189
|
+
|
|
190
|
+
expect(keyValueComponents).toHaveLength(1); // Only the KeyValue for labels
|
|
191
|
+
});
|
|
192
|
+
|
|
193
|
+
it('should show ToggleSwitch in VIEW mode if there are protected keys', async() => {
|
|
194
|
+
const wrapper = mount(Labels, {
|
|
195
|
+
props: {
|
|
196
|
+
value: mockValue,
|
|
197
|
+
mode: _VIEW,
|
|
198
|
+
},
|
|
199
|
+
global: { mocks: { t: mockT } },
|
|
200
|
+
});
|
|
201
|
+
|
|
202
|
+
expect((wrapper.vm as any).showToggler).toBe(true);
|
|
203
|
+
const toggleSwitch = wrapper.findComponent(ToggleSwitch);
|
|
204
|
+
|
|
205
|
+
expect(toggleSwitch.exists()).toBe(true);
|
|
206
|
+
expect(toggleSwitch.props('onLabel')).toBe('labels.labels.show');
|
|
207
|
+
});
|
|
208
|
+
|
|
209
|
+
it('should not show ToggleSwitch in non-VIEW mode', () => {
|
|
210
|
+
const wrapper = mount(Labels, {
|
|
211
|
+
props: {
|
|
212
|
+
value: mockValue,
|
|
213
|
+
mode: _EDIT,
|
|
214
|
+
},
|
|
215
|
+
global: { mocks: { t: mockT } },
|
|
216
|
+
});
|
|
217
|
+
|
|
218
|
+
expect((wrapper.vm as any).showToggler).toBe(false);
|
|
219
|
+
expect(wrapper.findComponent(ToggleSwitch).exists()).toBe(false);
|
|
220
|
+
});
|
|
221
|
+
|
|
222
|
+
it('should not show ToggleSwitch in VIEW mode if no protected keys', () => {
|
|
223
|
+
const mockValueNoProtected = {
|
|
224
|
+
labels: { 'my-label': 'my-value' },
|
|
225
|
+
systemLabels: [],
|
|
226
|
+
annotations: { 'my-annotation': 'my-annotation' },
|
|
227
|
+
systemAnnotations: [],
|
|
228
|
+
setLabels: jest.fn(),
|
|
229
|
+
setAnnotations: jest.fn(),
|
|
230
|
+
};
|
|
231
|
+
|
|
232
|
+
const wrapper = mount(Labels, {
|
|
233
|
+
props: {
|
|
234
|
+
value: mockValueNoProtected,
|
|
235
|
+
mode: _VIEW,
|
|
236
|
+
},
|
|
237
|
+
global: { mocks: { t: mockT } },
|
|
238
|
+
});
|
|
239
|
+
|
|
240
|
+
expect((wrapper.vm as any).showToggler).toBe(false);
|
|
241
|
+
expect(wrapper.findComponent(ToggleSwitch).exists()).toBe(false);
|
|
242
|
+
});
|
|
243
|
+
|
|
244
|
+
it('should toggle label values when ToggleSwitch is activated', async() => {
|
|
245
|
+
const wrapper = mount(Labels, {
|
|
246
|
+
props: {
|
|
247
|
+
value: mockValue,
|
|
248
|
+
mode: _VIEW,
|
|
249
|
+
},
|
|
250
|
+
global: { mocks: { t: mockT } },
|
|
251
|
+
});
|
|
252
|
+
|
|
253
|
+
const labelsKeyValue = wrapper.findComponent(KeyValue);
|
|
254
|
+
|
|
255
|
+
expect(labelsKeyValue.props('value')).toStrictEqual({ 'my-label': 'my-value' }); // Initial: hidden protected
|
|
256
|
+
|
|
257
|
+
// Activate the toggle
|
|
258
|
+
await wrapper.findComponent(ToggleSwitch).vm.$emit('update:value', true);
|
|
259
|
+
await wrapper.vm.$nextTick();
|
|
260
|
+
|
|
261
|
+
expect((wrapper.vm as any).toggler).toBe(true);
|
|
262
|
+
expect(labelsKeyValue.props('value')).toStrictEqual(mockValue.labels); // Should show all labels including protected
|
|
263
|
+
});
|
|
264
|
+
|
|
265
|
+
it('should toggle annotation values when ToggleSwitch is activated', async() => {
|
|
266
|
+
const wrapper = mount(Labels, {
|
|
267
|
+
props: {
|
|
268
|
+
value: mockValue,
|
|
269
|
+
mode: _VIEW,
|
|
270
|
+
},
|
|
271
|
+
global: { mocks: { t: mockT } },
|
|
272
|
+
});
|
|
273
|
+
|
|
274
|
+
const annotationsKeyValue = wrapper.findAllComponents(KeyValue)[1];
|
|
275
|
+
|
|
276
|
+
expect(annotationsKeyValue.props('value')).toStrictEqual({ 'my-annotation': 'my-annotation' }); // Initial: hidden protected
|
|
277
|
+
|
|
278
|
+
// Activate the toggle
|
|
279
|
+
await wrapper.findComponent(ToggleSwitch).vm.$emit('update:value', true);
|
|
280
|
+
await wrapper.vm.$nextTick();
|
|
281
|
+
|
|
282
|
+
expect((wrapper.vm as any).toggler).toBe(true);
|
|
283
|
+
expect(annotationsKeyValue.props('value')).toStrictEqual(mockValue.annotations); // Should show all annotations including protected
|
|
284
|
+
});
|
|
285
|
+
|
|
286
|
+
it('should call setLabels when labels KeyValue emits update:value', async() => {
|
|
287
|
+
const wrapper = mount(Labels, {
|
|
288
|
+
props: {
|
|
289
|
+
value: mockValue,
|
|
290
|
+
mode: 'create',
|
|
291
|
+
},
|
|
292
|
+
global: { mocks: { t: mockT } },
|
|
293
|
+
});
|
|
294
|
+
|
|
295
|
+
const labelsKeyValue = wrapper.findComponent(KeyValue);
|
|
296
|
+
const newLabels = { 'new-label': 'new-value', 'my-label': 'my-value' };
|
|
297
|
+
|
|
298
|
+
await labelsKeyValue.vm.$emit('update:value', newLabels);
|
|
299
|
+
|
|
300
|
+
// We expect setLabels to be called with the new values, preserving initial protected ones
|
|
301
|
+
expect(mockValue.setLabels).toHaveBeenCalledWith({
|
|
302
|
+
'new-label': 'new-value',
|
|
303
|
+
'my-label': 'my-value',
|
|
304
|
+
'kubernetes.io/hostname': 'test-app'
|
|
305
|
+
});
|
|
306
|
+
});
|
|
307
|
+
|
|
308
|
+
it('should call setAnnotations when annotations KeyValue emits update:value', async() => {
|
|
309
|
+
const wrapper = mount(Labels, {
|
|
310
|
+
props: {
|
|
311
|
+
value: mockValue,
|
|
312
|
+
mode: 'create',
|
|
313
|
+
showAnnotations: true,
|
|
314
|
+
},
|
|
315
|
+
global: { mocks: { t: mockT } },
|
|
316
|
+
});
|
|
317
|
+
|
|
318
|
+
const annotationsKeyValue = wrapper.findAllComponents(KeyValue)[1];
|
|
319
|
+
const newAnnotations = { 'new-anno': 'new-value', 'my-annotation': 'my-annotation' };
|
|
320
|
+
|
|
321
|
+
await annotationsKeyValue.vm.$emit('update:value', newAnnotations);
|
|
322
|
+
|
|
323
|
+
// We expect setAnnotations to be called with the new values, preserving initial protected ones
|
|
324
|
+
expect(mockValue.setAnnotations).toHaveBeenCalledWith({
|
|
325
|
+
'new-anno': 'new-value',
|
|
326
|
+
'my-annotation': 'my-annotation',
|
|
327
|
+
'cattle.io/system': 'user'
|
|
328
|
+
});
|
|
329
|
+
});
|
|
330
|
+
|
|
331
|
+
it('should add newly entered protected keys to keyErrors', async() => {
|
|
332
|
+
const wrapper = mount(Labels, {
|
|
333
|
+
props: {
|
|
334
|
+
value: mockValue,
|
|
335
|
+
mode: 'create',
|
|
336
|
+
},
|
|
337
|
+
global: { mocks: { t: mockT } },
|
|
338
|
+
});
|
|
339
|
+
|
|
340
|
+
// Insert new protected key
|
|
341
|
+
const newLabels = {
|
|
342
|
+
'my-label': 'my-value',
|
|
343
|
+
'kubernetes.io/hostname': 'new-protected-value',
|
|
344
|
+
'non-protected': 'value'
|
|
345
|
+
};
|
|
346
|
+
|
|
347
|
+
await wrapper.vm.labels.update(newLabels, () => {});
|
|
348
|
+
await wrapper.vm.$nextTick();
|
|
349
|
+
|
|
350
|
+
// Expect to add protected labels in keyErrors
|
|
351
|
+
expect((wrapper.vm as any).labels.keyErrors).toStrictEqual({ 'kubernetes.io/hostname': 'labels.protectedWarning' });
|
|
352
|
+
|
|
353
|
+
// On edit, should key the protected label in the list
|
|
354
|
+
expect((wrapper.vm as any).labels.value).toStrictEqual({
|
|
355
|
+
'my-label': 'my-value',
|
|
356
|
+
'kubernetes.io/hostname': 'new-protected-value',
|
|
357
|
+
'non-protected': 'value'
|
|
358
|
+
});
|
|
359
|
+
});
|
|
360
|
+
});
|
|
@@ -53,19 +53,22 @@ describe('component: MatchExpressions', () => {
|
|
|
53
53
|
it.each([
|
|
54
54
|
'operator',
|
|
55
55
|
])('should emit an update on %p selection change', async(field) => {
|
|
56
|
-
const wrapper = mount(
|
|
57
|
-
|
|
58
|
-
|
|
59
|
-
|
|
60
|
-
|
|
61
|
-
|
|
62
|
-
|
|
63
|
-
|
|
64
|
-
|
|
65
|
-
|
|
66
|
-
|
|
67
|
-
|
|
68
|
-
|
|
56
|
+
const wrapper = mount(
|
|
57
|
+
MatchExpressions,
|
|
58
|
+
{
|
|
59
|
+
attachTo: document.body,
|
|
60
|
+
props: {
|
|
61
|
+
mode: _CREATE,
|
|
62
|
+
value: [
|
|
63
|
+
{
|
|
64
|
+
id: '123',
|
|
65
|
+
key: '123',
|
|
66
|
+
operator: 'anything',
|
|
67
|
+
values: '123'
|
|
68
|
+
}
|
|
69
|
+
]
|
|
70
|
+
},
|
|
71
|
+
});
|
|
69
72
|
|
|
70
73
|
const select = wrapper.find(`[data-testid="input-match-expression-${ field }-0"]`);
|
|
71
74
|
|
|
@@ -0,0 +1,116 @@
|
|
|
1
|
+
import { mount } from '@vue/test-utils';
|
|
2
|
+
import Networking from '@shell/components/form/Networking.vue';
|
|
3
|
+
import { nextTick } from 'vue';
|
|
4
|
+
|
|
5
|
+
jest.mock('lodash/debounce', () => jest.fn((fn) => fn));
|
|
6
|
+
|
|
7
|
+
describe('component: Networking', () => {
|
|
8
|
+
it.each([
|
|
9
|
+
{
|
|
10
|
+
ip: '10.1.1.1',
|
|
11
|
+
hostnames: ['host1']
|
|
12
|
+
},
|
|
13
|
+
{
|
|
14
|
+
ip: '10.1.1.2',
|
|
15
|
+
hostnames: ['host1', 'host2']
|
|
16
|
+
},
|
|
17
|
+
{
|
|
18
|
+
ip: '10.1.1.3',
|
|
19
|
+
hostnames: []
|
|
20
|
+
}
|
|
21
|
+
])('should render host aliases form if the value contains host aliases config: [%j]', (hostAliasesConfig) => {
|
|
22
|
+
const wrapper = mount(Networking, {
|
|
23
|
+
props: {
|
|
24
|
+
value: { hostAliases: [hostAliasesConfig] },
|
|
25
|
+
mode: 'create',
|
|
26
|
+
},
|
|
27
|
+
global: { mocks: { $store: { getters: { 'i18n/t': jest.fn() } } } }
|
|
28
|
+
});
|
|
29
|
+
|
|
30
|
+
const hostAliases = wrapper.findComponent('[data-test="hostAliases"]');
|
|
31
|
+
const keyInput = hostAliases.find('[data-testid="input-kv-item-key-0"]');
|
|
32
|
+
const valueInput = hostAliases.find('[data-testid="kv-item-value-0"]');
|
|
33
|
+
|
|
34
|
+
expect(keyInput.element.value).toBe(hostAliasesConfig.ip);
|
|
35
|
+
expect(valueInput.find('[data-testid="value-multiline"]').element.value).toBe(hostAliasesConfig.hostnames.join(', '));
|
|
36
|
+
});
|
|
37
|
+
|
|
38
|
+
it('should not render host aliases form, if there is no host aliases configuration', async() => {
|
|
39
|
+
const wrapper = mount(Networking, {
|
|
40
|
+
props: {
|
|
41
|
+
value: {},
|
|
42
|
+
'onUpdate:value': (e) => wrapper.setProps({ value: e }),
|
|
43
|
+
mode: 'create',
|
|
44
|
+
},
|
|
45
|
+
global: { mocks: { $store: { getters: { 'i18n/t': jest.fn() } } } }
|
|
46
|
+
});
|
|
47
|
+
|
|
48
|
+
const hostAliases = wrapper.findComponent('[data-test="hostAliases"]');
|
|
49
|
+
const keyInput = hostAliases.find('[data-testid="input-kv-item-key-0"]');
|
|
50
|
+
const valueInput = hostAliases.find('[data-testid="kv-item-value-0"]');
|
|
51
|
+
|
|
52
|
+
expect(keyInput.exists()).toBe(false);
|
|
53
|
+
expect(valueInput.exists()).toBe(false);
|
|
54
|
+
expect(wrapper.props('value')).toStrictEqual({});
|
|
55
|
+
});
|
|
56
|
+
|
|
57
|
+
it('should render host aliases form correctly if click add host aliases button', async() => {
|
|
58
|
+
const wrapper = mount(Networking, {
|
|
59
|
+
props: {
|
|
60
|
+
value: {},
|
|
61
|
+
'onUpdate:value': (e) => wrapper.setProps({ value: e }),
|
|
62
|
+
mode: 'create',
|
|
63
|
+
},
|
|
64
|
+
global: { mocks: { $store: { getters: { 'i18n/t': jest.fn() } } } }
|
|
65
|
+
});
|
|
66
|
+
|
|
67
|
+
const hostAliases = wrapper.findComponent('[data-test="hostAliases"]');
|
|
68
|
+
const addButton = hostAliases.find('[data-testid="add_row_item_button"]');
|
|
69
|
+
|
|
70
|
+
addButton.trigger('click');
|
|
71
|
+
await nextTick();
|
|
72
|
+
|
|
73
|
+
const keyInput = hostAliases.find('[data-testid="input-kv-item-key-0"]');
|
|
74
|
+
const valueInput = hostAliases.find('[data-testid="kv-item-value-0"]');
|
|
75
|
+
const v = wrapper.props('value');
|
|
76
|
+
|
|
77
|
+
expect(keyInput.exists()).toBe(true);
|
|
78
|
+
expect(valueInput.exists()).toBe(true);
|
|
79
|
+
expect(v.hostAliases).toHaveLength(1);
|
|
80
|
+
expect(v.hostAliases[0].ip).toBe('');
|
|
81
|
+
expect(v.hostAliases[0].hostnames).toStrictEqual([]);
|
|
82
|
+
});
|
|
83
|
+
|
|
84
|
+
it('should render host aliases form correctly if modify the form values', async() => {
|
|
85
|
+
const wrapper = mount(Networking, {
|
|
86
|
+
props: {
|
|
87
|
+
value: {},
|
|
88
|
+
'onUpdate:value': (e) => wrapper.setProps({ value: e }),
|
|
89
|
+
mode: 'create',
|
|
90
|
+
},
|
|
91
|
+
global: { mocks: { $store: { getters: { 'i18n/t': jest.fn() } } } }
|
|
92
|
+
});
|
|
93
|
+
|
|
94
|
+
const hostAliases = wrapper.findComponent('[data-test="hostAliases"]');
|
|
95
|
+
const addButton = hostAliases.find('[data-testid="add_row_item_button"]');
|
|
96
|
+
|
|
97
|
+
addButton.trigger('click');
|
|
98
|
+
await nextTick();
|
|
99
|
+
let v = wrapper.props('value');
|
|
100
|
+
let keyInput = hostAliases.find('[data-testid="input-kv-item-key-0"]');
|
|
101
|
+
let valueInput = hostAliases.find('[data-testid="kv-item-value-0"]');
|
|
102
|
+
|
|
103
|
+
keyInput.setValue('10.1.1.1');
|
|
104
|
+
valueInput.find('[data-testid="value-multiline"]').setValue('test1, test2');
|
|
105
|
+
await nextTick();
|
|
106
|
+
v = wrapper.props('value');
|
|
107
|
+
keyInput = hostAliases.find('[data-testid="input-kv-item-key-0"]');
|
|
108
|
+
valueInput = hostAliases.find('[data-testid="kv-item-value-0"]');
|
|
109
|
+
|
|
110
|
+
expect(v.hostAliases).toHaveLength(1);
|
|
111
|
+
expect(v.hostAliases[0].ip).toBe('10.1.1.1');
|
|
112
|
+
expect(v.hostAliases[0].hostnames).toStrictEqual(['test1', 'test2']);
|
|
113
|
+
expect(keyInput.exists()).toBe(true);
|
|
114
|
+
expect(valueInput.exists()).toBe(true);
|
|
115
|
+
});
|
|
116
|
+
});
|
|
@@ -77,7 +77,8 @@ describe('select.vue', () => {
|
|
|
77
77
|
value,
|
|
78
78
|
label: 'some-label',
|
|
79
79
|
options,
|
|
80
|
-
searchable: true
|
|
80
|
+
searchable: true,
|
|
81
|
+
loading: false,
|
|
81
82
|
}
|
|
82
83
|
});
|
|
83
84
|
|
|
@@ -91,7 +92,9 @@ describe('select.vue', () => {
|
|
|
91
92
|
await input.trigger('keydown.enter');
|
|
92
93
|
|
|
93
94
|
// mimic pressing space on search box inside v-select
|
|
94
|
-
|
|
95
|
+
const search = input.find('input');
|
|
96
|
+
|
|
97
|
+
await search.trigger('keydown.space', mockEvent);
|
|
95
98
|
|
|
96
99
|
// eslint-disable-next-line
|
|
97
100
|
expect(spyFocus).toHaveBeenCalled();
|