@rancher/shell 3.0.5-rc.7 → 3.0.5-rc.9
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/brand/classic/metadata.json +3 -0
- package/assets/styles/app.scss +1 -0
- package/assets/styles/base/_color.scss +19 -0
- package/assets/styles/base/_helpers.scss +10 -0
- package/assets/styles/base/_variables.scss +1 -1
- package/assets/styles/fonts/_icons.scss +1 -32
- package/assets/styles/global/_layout.scss +1 -1
- package/assets/styles/global/_tooltip.scss +7 -4
- package/assets/styles/themes/_dark.scss +272 -259
- package/assets/styles/themes/_light.scss +551 -516
- package/assets/styles/themes/_modern.scss +936 -0
- package/assets/translations/en-us.yaml +219 -38
- package/assets/translations/zh-hans.yaml +0 -1
- package/chart/__tests__/S3.test.ts +2 -1
- package/chart/monitoring/grafana/index.vue +8 -2
- package/cloud-credential/generic.vue +18 -10
- package/cloud-credential/harvester.vue +1 -9
- package/components/ActionMenuShell.vue +3 -1
- package/components/AdvancedSection.vue +8 -0
- package/components/ChartReadme.vue +17 -7
- package/components/Cron/CronExpressionEditor.vue +299 -0
- package/components/Cron/CronExpressionEditorModal.vue +247 -0
- package/components/Cron/CronTooltip.vue +87 -0
- package/components/Cron/types.ts +13 -0
- package/components/Drawer/ResourceDetailDrawer/__tests__/composables.test.ts +1 -26
- package/components/Drawer/ResourceDetailDrawer/composables.ts +0 -23
- package/components/Drawer/ResourceDetailDrawer/index.vue +17 -4
- package/components/ForceDirectedTreeChart/composable.ts +11 -0
- package/components/InstallHelmCharts.vue +656 -0
- package/components/LazyImage.vue +60 -4
- package/components/LocaleSelector.vue +7 -2
- package/components/Markdown.vue +4 -0
- package/components/PromptModal.vue +1 -1
- package/components/Resource/Detail/Card/__tests__/StateCard.test.ts +1 -0
- package/components/Resource/Detail/CopyToClipboard.vue +78 -0
- package/components/Resource/Detail/FetchLoader/__tests__/composables.test.ts +69 -0
- package/components/Resource/Detail/FetchLoader/composables.ts +27 -0
- package/components/Resource/Detail/Masthead/composable.ts +16 -0
- package/components/Resource/Detail/Masthead/index.vue +37 -0
- package/components/Resource/Detail/Metadata/Annotations/__tests__/index.test.ts +1 -1
- package/components/Resource/Detail/Metadata/Annotations/index.vue +1 -1
- package/components/Resource/Detail/Metadata/IdentifyingInformation/__tests__/identifying-fields.test.ts +13 -61
- package/components/Resource/Detail/Metadata/IdentifyingInformation/__tests__/index.test.ts +33 -6
- package/components/Resource/Detail/Metadata/IdentifyingInformation/identifying-fields.ts +29 -43
- package/components/Resource/Detail/Metadata/IdentifyingInformation/index.vue +25 -5
- package/components/Resource/Detail/Metadata/KeyValue.vue +12 -23
- package/components/Resource/Detail/Metadata/KeyValueRow.vue +144 -0
- package/components/Resource/Detail/Metadata/Labels/__tests__/index.test.ts +1 -0
- package/components/Resource/Detail/Metadata/Labels/index.vue +1 -0
- package/components/Resource/Detail/Metadata/__tests__/KeyValue.test.ts +30 -32
- package/components/Resource/Detail/Metadata/__tests__/KeyValueRow.test.ts +108 -0
- package/components/Resource/Detail/Metadata/__tests__/composables.test.ts +10 -20
- package/components/Resource/Detail/Metadata/__tests__/index.test.ts +12 -5
- package/components/Resource/Detail/Metadata/composables.ts +9 -10
- package/components/Resource/Detail/Metadata/index.vue +18 -2
- package/components/Resource/Detail/Page.vue +35 -21
- package/components/Resource/Detail/Preview/Content.vue +63 -0
- package/components/Resource/Detail/Preview/Preview.vue +128 -0
- package/components/Resource/Detail/Preview/__tests__/Content.spec.ts +71 -0
- package/components/Resource/Detail/Preview/__tests__/Preview.spec.ts +121 -0
- package/components/Resource/Detail/ResourcePopover/ResourcePopoverCard.vue +141 -0
- package/components/Resource/Detail/ResourcePopover/__tests__/ResourcePopoverCard.test.ts +136 -0
- package/components/Resource/Detail/ResourcePopover/__tests__/index.test.ts +245 -0
- package/components/Resource/Detail/ResourcePopover/index.vue +226 -0
- package/components/Resource/Detail/SpacedRow.vue +1 -0
- package/components/Resource/Detail/TitleBar/__tests__/composables.test.ts +8 -14
- package/components/Resource/Detail/TitleBar/__tests__/index.test.ts +1 -1
- package/components/Resource/Detail/TitleBar/composables.ts +3 -6
- package/components/Resource/Detail/TitleBar/index.vue +11 -29
- package/components/Resource/Detail/ViewOptions/composable.ts +9 -0
- package/components/Resource/Detail/ViewOptions/index.vue +41 -0
- package/components/Resource/Detail/__tests__/CopyToClipboard.spec.ts +82 -0
- package/components/ResourceDetail/Masthead/legacy.vue +0 -19
- package/components/ResourceDetail/index.vue +544 -74
- package/components/ResourceTable.vue +24 -0
- package/components/SlideInPanelManager.vue +10 -3
- package/components/SortableTable/index.vue +11 -5
- package/components/SortableTable/paging.js +3 -0
- package/components/Tabbed/Tab.vue +43 -1
- package/components/Tabbed/index.vue +32 -4
- package/components/__tests__/Cron/CronExpressionEditor.test.ts +151 -0
- package/components/__tests__/Cron/CronExpressionEditorModal.test.ts +81 -0
- package/components/__tests__/LazyImage.spec.ts +121 -0
- package/components/auth/login/saml.vue +86 -0
- package/components/fleet/FleetStatus.vue +4 -0
- package/components/form/ClusterAppearance.vue +5 -0
- package/components/form/LabeledSelect.vue +8 -8
- package/components/form/Members/ClusterPermissionsEditor.vue +1 -1
- package/components/form/ProjectMemberEditor.vue +1 -1
- package/components/form/ResourceLabeledSelect.vue +19 -6
- package/components/form/ResourceTabs/composable.ts +54 -0
- package/components/form/ResourceTabs/index.vue +30 -7
- package/components/form/SecretSelector.vue +9 -0
- package/components/form/Select.vue +13 -10
- package/components/form/__tests__/LabeledSelect.test.ts +133 -0
- package/components/form/__tests__/Select.test.ts +134 -0
- package/components/form/labeled-select-utils/labeled-select-pagination.ts +3 -38
- package/components/formatter/FleetApplicationSource.vue +25 -17
- package/components/nav/Favorite.vue +4 -0
- package/components/nav/NotificationCenter/Notification.vue +1 -27
- package/components/nav/WindowManager/index.vue +3 -3
- package/composables/useExtensionManager.ts +17 -0
- package/config/home-links.js +12 -0
- package/config/labels-annotations.js +1 -3
- package/config/page-actions.js +0 -1
- package/config/product/explorer.js +3 -1
- package/config/product/fleet.js +2 -7
- package/config/product/manager.js +0 -5
- package/config/query-params.js +1 -0
- package/config/router/navigation-guards/clusters.js +2 -1
- package/config/router/navigation-guards/products.js +1 -1
- package/core/extension-manager-impl.js +518 -0
- package/core/plugins.js +35 -468
- package/core/types.ts +8 -2
- package/detail/__tests__/autoscaling.horizontalpodautoscaler.test.ts +1 -0
- package/detail/__tests__/provisioning.cattle.io.cluster.test.ts +11 -0
- package/detail/__tests__/workload.test.ts +164 -0
- package/detail/catalog.cattle.io.app.vue +7 -4
- package/detail/configmap.vue +33 -75
- package/detail/fleet.cattle.io.bundle.vue +1 -5
- package/detail/fleet.cattle.io.cluster.vue +3 -2
- package/detail/fleet.cattle.io.gitrepo.vue +76 -49
- package/detail/fleet.cattle.io.helmop.vue +78 -49
- package/detail/projectsecret.vue +11 -0
- package/detail/provisioning.cattle.io.cluster.vue +350 -324
- package/detail/secret.vue +49 -308
- package/detail/workload/index.vue +38 -21
- package/dialog/AddonConfigConfirmationDialog.vue +1 -1
- package/dialog/GenericPrompt.vue +1 -1
- package/dialog/ImportDialog.vue +9 -2
- package/dialog/InstallExtensionDialog.vue +26 -15
- package/edit/__tests__/fleet.cattle.io.gitrepo.test.ts +2 -1
- package/edit/__tests__/fleet.cattle.io.helmop.test.ts +224 -0
- package/edit/__tests__/resources.cattle.io.restore.test.ts +106 -0
- package/edit/cloudcredential.vue +31 -17
- package/edit/constraints.gatekeeper.sh.constraint/index.vue +10 -2
- package/edit/fleet.cattle.io.cluster.vue +19 -0
- package/edit/fleet.cattle.io.gitrepo.vue +28 -22
- package/edit/fleet.cattle.io.helmop.vue +78 -56
- package/edit/logging.banzaicloud.io.output/index.vue +1 -1
- package/edit/logging.banzaicloud.io.output/providers/awsElasticsearch.vue +5 -6
- package/edit/monitoring.coreos.com.alertmanagerconfig/index.vue +12 -11
- package/edit/monitoring.coreos.com.alertmanagerconfig/receiverConfig.vue +11 -1
- package/edit/networking.k8s.io.ingress/Certificate.vue +9 -11
- package/edit/networking.k8s.io.ingress/DefaultBackend.vue +8 -3
- package/edit/networking.k8s.io.ingress/Rule.vue +2 -5
- package/edit/networking.k8s.io.ingress/RulePath.vue +17 -11
- package/edit/networking.k8s.io.networkpolicy/PolicyRuleTarget.vue +11 -10
- package/edit/networking.k8s.io.networkpolicy/PolicyRules.vue +1 -3
- package/edit/networking.k8s.io.networkpolicy/index.vue +17 -17
- package/edit/provisioning.cattle.io.cluster/index.vue +14 -19
- package/edit/provisioning.cattle.io.cluster/rke2.vue +31 -15
- package/edit/provisioning.cattle.io.cluster/tabs/AgentConfiguration.vue +9 -7
- package/edit/provisioning.cattle.io.cluster/tabs/DirectoryConfig.vue +10 -12
- package/edit/provisioning.cattle.io.cluster/tabs/MachinePool.vue +39 -38
- package/edit/provisioning.cattle.io.cluster/tabs/etcd/S3Config.vue +41 -19
- package/edit/provisioning.cattle.io.cluster/tabs/etcd/index.vue +16 -3
- package/edit/provisioning.cattle.io.cluster/tabs/registries/RegistryConfigs.vue +30 -31
- package/edit/provisioning.cattle.io.cluster/tabs/registries/RegistryMirrors.vue +9 -10
- package/edit/provisioning.cattle.io.cluster/tabs/registries/index.vue +1 -3
- package/edit/provisioning.cattle.io.cluster/tabs/upgrade/DrainOptions.vue +16 -9
- package/edit/resources.cattle.io.restore.vue +5 -8
- package/edit/workload/index.vue +5 -14
- package/list/__tests__/workload.test.ts +1 -0
- package/list/provisioning.cattle.io.cluster.vue +1 -69
- package/list/workload.vue +8 -1
- package/machine-config/__tests__/vmwarevsphere.test.ts +5 -7
- package/machine-config/components/GCEImage.vue +6 -5
- package/machine-config/google.vue +20 -7
- package/machine-config/vmwarevsphere.vue +7 -17
- package/mixins/__tests__/chart.test.ts +139 -1
- package/mixins/chart.js +58 -20
- package/mixins/resource-fetch-api-pagination.js +3 -4
- package/models/__tests__/chart.test.ts +111 -80
- package/models/__tests__/fleet.cattle.io.helmop.test.ts +224 -0
- package/models/__tests__/namespace.test.ts +69 -0
- package/models/__tests__/node.test.ts +7 -63
- package/models/apps.statefulset.js +8 -10
- package/models/catalog.cattle.io.app.js +1 -1
- package/models/catalog.cattle.io.operation.js +1 -1
- package/models/chart.js +41 -21
- package/models/cloudcredential.js +2 -163
- package/models/cluster/node.js +7 -7
- package/models/cluster.x-k8s.io.machine.js +3 -3
- package/models/compliance.cattle.io.clusterscan.js +2 -2
- package/models/configmap.js +4 -0
- package/models/constraints.gatekeeper.sh.constraint.js +1 -1
- package/models/fleet-application.js +16 -63
- package/models/fleet.cattle.io.bundle.js +1 -38
- package/models/fleet.cattle.io.gitrepo.js +19 -1
- package/models/fleet.cattle.io.helmop.js +30 -22
- package/models/management.cattle.io.project.js +12 -0
- package/models/management.cattle.io.setting.js +4 -0
- package/models/namespace.js +30 -0
- package/models/persistentvolumeclaim.js +1 -1
- package/models/pod.js +2 -2
- package/models/provisioning.cattle.io.cluster.js +16 -40
- package/models/rke.cattle.io.etcdsnapshot.js +1 -1
- package/models/secret.js +4 -0
- package/models/storage.k8s.io.storageclass.js +2 -2
- package/models/workload.js +6 -3
- package/package.json +19 -18
- package/pages/c/_cluster/apps/charts/AppChartCardFooter.vue +26 -10
- package/pages/c/_cluster/apps/charts/AppChartCardSubHeader.vue +4 -1
- package/pages/c/_cluster/apps/charts/__tests__/AppChartCardFooter.spec.js +41 -0
- package/pages/c/_cluster/apps/charts/chart.vue +440 -183
- package/pages/c/_cluster/apps/charts/index.vue +1 -0
- package/pages/c/_cluster/apps/charts/install.vue +7 -6
- package/pages/c/_cluster/explorer/projectsecret.vue +3 -13
- package/pages/c/_cluster/explorer/tools/__tests__/index.test.ts +102 -12
- package/pages/c/_cluster/explorer/tools/index.vue +145 -254
- package/pages/c/_cluster/fleet/__tests__/index.test.ts +608 -314
- package/pages/c/_cluster/fleet/index.vue +103 -44
- package/pages/c/_cluster/manager/cloudCredential/index.vue +20 -60
- package/pages/c/_cluster/manager/drivers/kontainerDriver/index.vue +12 -2
- package/pages/c/_cluster/uiplugins/PluginInfoPanel.vue +11 -4
- package/pages/c/_cluster/uiplugins/__tests__/index.spec.ts +318 -0
- package/pages/c/_cluster/uiplugins/index.vue +256 -387
- package/pages/home.vue +1 -9
- package/plugins/dashboard-store/actions.js +42 -22
- package/plugins/dashboard-store/resource-class.js +80 -0
- package/plugins/steve/__tests__/getters.test.ts +1 -1
- package/plugins/steve/__tests__/subscribe.spec.ts +259 -1
- package/plugins/steve/getters.js +8 -2
- package/plugins/steve/resourceWatcher.js +10 -3
- package/plugins/steve/subscribe.js +192 -19
- package/plugins/steve/worker/web-worker.advanced.js +2 -0
- package/public/index.html +2 -1
- package/rancher-components/Card/Card.vue +1 -19
- package/rancher-components/Form/Checkbox/Checkbox.vue +1 -1
- package/rancher-components/Form/Radio/RadioButton.vue +1 -1
- package/rancher-components/Form/Radio/RadioGroup.vue +1 -1
- package/rancher-components/LabeledTooltip/LabeledTooltip.vue +1 -11
- package/rancher-components/Pill/RcCounterBadge/RcCounterBadge.test.ts +53 -0
- package/rancher-components/Pill/RcCounterBadge/RcCounterBadge.vue +65 -0
- package/rancher-components/Pill/RcCounterBadge/index.ts +1 -0
- package/rancher-components/Pill/RcCounterBadge/types.ts +7 -0
- package/rancher-components/Pill/RcStatusBadge/RcStatusBadge.test.ts +15 -0
- package/rancher-components/Pill/RcStatusBadge/RcStatusBadge.vue +65 -0
- package/rancher-components/Pill/RcStatusBadge/index.ts +2 -0
- package/rancher-components/Pill/RcStatusBadge/types.ts +5 -0
- package/rancher-components/Pill/RcStatusIndicator/RcStatusIndicator.test.ts +33 -0
- package/rancher-components/Pill/RcStatusIndicator/RcStatusIndicator.vue +75 -0
- package/rancher-components/Pill/RcStatusIndicator/index.ts +2 -0
- package/rancher-components/Pill/RcStatusIndicator/types.ts +7 -0
- package/rancher-components/Pill/RcTag/RcTag.test.ts +64 -0
- package/rancher-components/Pill/RcTag/RcTag.vue +94 -0
- package/rancher-components/Pill/RcTag/index.ts +1 -0
- package/rancher-components/Pill/RcTag/types.ts +9 -0
- package/rancher-components/Pill/types.ts +3 -0
- package/rancher-components/RcButton/RcButton.vue +1 -1
- package/rancher-components/RcDropdown/RcDropdown.test.ts +98 -0
- package/rancher-components/RcDropdown/RcDropdown.vue +5 -0
- package/rancher-components/RcDropdown/RcDropdownItem.vue +7 -1
- package/rancher-components/RcDropdown/RcDropdownItemCheckbox.vue +2 -1
- package/rancher-components/RcDropdown/RcDropdownItemSelect.vue +2 -1
- package/rancher-components/RcDropdown/useDropdownContext.ts +21 -0
- package/rancher-components/RcDropdown/useDropdownItem.ts +30 -1
- package/rancher-components/RcItemCard/RcItemCard.test.ts +20 -0
- package/rancher-components/RcItemCard/RcItemCard.vue +41 -6
- package/rancher-components/RcItemCard/RcItemCardAction.vue +12 -0
- package/store/__tests__/catalog.test.ts +156 -1
- package/store/aws.js +19 -8
- package/store/catalog.js +10 -5
- package/store/type-map.js +3 -15
- package/types/extension-manager.ts +26 -0
- package/types/resources/settings.d.ts +1 -1
- package/types/shell/index.d.ts +149 -44
- package/types/uiplugins.ts +73 -0
- package/utils/__tests__/back-off.test.ts +354 -0
- package/utils/__tests__/kontainer.test.ts +19 -0
- package/utils/__tests__/product.test.ts +129 -0
- package/utils/__tests__/resource.test.ts +87 -0
- package/utils/__tests__/uiplugins.test.ts +84 -0
- package/utils/alertmanagerconfig.js +2 -2
- package/utils/auth.js +3 -76
- package/utils/back-off.ts +176 -0
- package/utils/dynamic-importer.js +8 -0
- package/utils/kontainer.ts +3 -5
- package/utils/product.ts +39 -0
- package/utils/resource.ts +35 -0
- package/utils/select.js +0 -24
- package/utils/style.ts +3 -0
- package/utils/uiplugins.ts +29 -2
- package/utils/validators/__tests__/setting.test.js +92 -0
- package/utils/validators/formRules/__tests__/index.test.ts +91 -7
- package/utils/validators/formRules/index.ts +84 -8
- package/utils/validators/setting.js +17 -0
- package/vue.config.js +1 -1
- package/cloud-credential/__tests__/harvester.test.ts +0 -18
- package/components/Resource/Detail/Metadata/Rectangle.vue +0 -34
- package/components/Resource/Detail/Metadata/__tests__/Rectangle.test.ts +0 -24
- package/components/ResourceDetail/Masthead/__tests__/legacy.test.ts +0 -65
- package/components/ResourceDetail/__tests__/index.test.ts +0 -135
- package/components/ResourceDetail/legacy.vue +0 -562
- package/components/formatter/CloudCredExpired.vue +0 -69
- package/pages/explorer/resource/detail/configmap.vue +0 -42
- package/pages/explorer/resource/detail/projectsecret.vue +0 -9
- package/pages/explorer/resource/detail/secret.vue +0 -63
- package/utils/aws.js +0 -0
- /package/components/{ForceDirectedTreeChart.vue → ForceDirectedTreeChart/index.vue} +0 -0
|
@@ -97,32 +97,57 @@ describe('formRules', () => {
|
|
|
97
97
|
});
|
|
98
98
|
|
|
99
99
|
describe('urlRepository', () => {
|
|
100
|
-
const message = JSON.stringify({ message: 'validation.
|
|
100
|
+
const message = JSON.stringify({ message: 'validation.repository.url' });
|
|
101
101
|
const testCases = [
|
|
102
102
|
// Valid HTTP(s)
|
|
103
103
|
['https://github.com/rancher/dashboard.git', undefined],
|
|
104
104
|
['http://github.com/rancher/dashboard.git', undefined],
|
|
105
105
|
['https://github.com/rancher/dashboard', undefined],
|
|
106
106
|
['https://github.com/rancher/dashboard/', undefined],
|
|
107
|
+
['https://github.com/rancher/%20dashboard/', undefined],
|
|
108
|
+
['https://github.com/rancher/dashboard/%20', undefined],
|
|
109
|
+
['https://localhost:8005', undefined],
|
|
107
110
|
|
|
108
111
|
// Valid SSH
|
|
109
112
|
['git@github.com:rancher/dashboard.git', undefined],
|
|
110
113
|
['git@github.com:rancher/dashboard', undefined],
|
|
111
114
|
['git@github.com:rancher/dashboard/', undefined],
|
|
115
|
+
['git@github.com:rancher/%20dashboard/', undefined],
|
|
116
|
+
['git@github.com:rancher/dashboard/%20', undefined],
|
|
117
|
+
['git@git.apps.local:fleet/fleet-local.git', undefined],
|
|
118
|
+
['git@git.apps.local:33333/fleet/fleet-local.git', undefined],
|
|
112
119
|
|
|
113
120
|
// Not valid HTTP(s)
|
|
114
121
|
['https://github.com/rancher/ dashboard.git', message],
|
|
115
122
|
['http://github.com/rancher/ dashboard.git', message],
|
|
123
|
+
['http://github.com/ rancher/dashboard.git', message],
|
|
124
|
+
['http://github.com /rancher/dashboard.git', message],
|
|
116
125
|
['https://github.com/rancher/dashboard ', message],
|
|
126
|
+
['https%20://github.com/rancher/dashboard ', message],
|
|
127
|
+
['ht%20tps://github.com/rancher/dashboard ', message],
|
|
128
|
+
['https://git%20hub.com/rancher/dashboard/%20', message],
|
|
129
|
+
['https://https://', message],
|
|
130
|
+
['http:/ww.abc.com', message],
|
|
131
|
+
['http:ww.abc.com', message],
|
|
117
132
|
['foo://github.com/rancher/dashboard/', message],
|
|
118
133
|
['github.com/rancher/dashboard/', message],
|
|
119
134
|
|
|
120
135
|
// Not valid SSH
|
|
121
136
|
['git@github.com:rancher/ dashboard.git', message],
|
|
122
137
|
['git@github.com:rancher/dashboard ', message],
|
|
138
|
+
['git@github.com:rancher/ dashboard', message],
|
|
139
|
+
['git @github.com:rancher/dashboard', message],
|
|
140
|
+
['git@github.com: rancher/dashboard', message],
|
|
123
141
|
['git@github.comrancher/dashboard', message],
|
|
142
|
+
['git@githubcomrancher/dashboard', message],
|
|
143
|
+
['%20git@github.comrancher/dashboard', message],
|
|
144
|
+
['git@git%20hub.comrancher/dashboard', message],
|
|
145
|
+
['git@git.apps.local:/fleet/fleet-local.git', message],
|
|
146
|
+
['git@.git', message],
|
|
147
|
+
['git@', message],
|
|
124
148
|
|
|
125
|
-
[undefined,
|
|
149
|
+
[undefined, message],
|
|
150
|
+
['', message]
|
|
126
151
|
];
|
|
127
152
|
|
|
128
153
|
it.each(testCases)(
|
|
@@ -139,20 +164,26 @@ describe('formRules', () => {
|
|
|
139
164
|
const message = JSON.stringify({ message: 'validation.oci.url' });
|
|
140
165
|
const testCases = [
|
|
141
166
|
// Valid
|
|
142
|
-
['oci://
|
|
167
|
+
['oci://registry.example.com', undefined],
|
|
168
|
+
['oci://myregistry.dev:5000', undefined],
|
|
169
|
+
['oci://192.168.1.100', undefined],
|
|
170
|
+
['oci://my.domain.com/my/image:tag', undefined],
|
|
171
|
+
['oci://localhost:5000', undefined],
|
|
143
172
|
['oci://region.objectstorage.example.com/n', undefined],
|
|
144
|
-
['oci://a', undefined],
|
|
145
|
-
['oci://UPPERCASE/path', undefined],
|
|
146
173
|
|
|
147
174
|
// Invalid
|
|
148
175
|
['http://example.com/oci', message],
|
|
149
176
|
['https://oci.cloud.com', message],
|
|
150
177
|
['ftp://oci.server.net', message],
|
|
151
|
-
['
|
|
178
|
+
['path/to/oci', message],
|
|
179
|
+
['oci://a', message],
|
|
152
180
|
['oci:/missing/slash', message],
|
|
153
181
|
['oci:', message],
|
|
154
182
|
['oci://', message],
|
|
155
|
-
['oci://
|
|
183
|
+
['oci://oci://duplicate/protocol', message],
|
|
184
|
+
['oci ://registry.example.com/foo/bar', message],
|
|
185
|
+
['oci://registry.example. com/foo/bar', message],
|
|
186
|
+
['oci://registry.example.com/ foo/bar', message],
|
|
156
187
|
['oci://resource multiple spaces', message],
|
|
157
188
|
['', message],
|
|
158
189
|
[undefined, message],
|
|
@@ -168,6 +199,59 @@ describe('formRules', () => {
|
|
|
168
199
|
);
|
|
169
200
|
});
|
|
170
201
|
|
|
202
|
+
describe('version', () => {
|
|
203
|
+
const message = JSON.stringify({ message: 'validation.version' });
|
|
204
|
+
const testCases: (null | string | undefined)[][] = [
|
|
205
|
+
// Valid
|
|
206
|
+
['1.2.3', undefined],
|
|
207
|
+
['', undefined],
|
|
208
|
+
[null, undefined],
|
|
209
|
+
|
|
210
|
+
// Invalid
|
|
211
|
+
['1.2.x', message],
|
|
212
|
+
['foo', message],
|
|
213
|
+
['1.2', message],
|
|
214
|
+
['1.2.', message],
|
|
215
|
+
['.', message],
|
|
216
|
+
];
|
|
217
|
+
|
|
218
|
+
it.each(testCases)(
|
|
219
|
+
'should return undefined or correct message based on the provided Version: %p',
|
|
220
|
+
(version, expected) => {
|
|
221
|
+
const formRuleResult = formRules.version(version);
|
|
222
|
+
|
|
223
|
+
expect(formRuleResult).toStrictEqual(expected);
|
|
224
|
+
}
|
|
225
|
+
);
|
|
226
|
+
});
|
|
227
|
+
|
|
228
|
+
describe('semanticVersion', () => {
|
|
229
|
+
const message = JSON.stringify({ message: 'validation.semanticVersion' });
|
|
230
|
+
const testCases: (null | string | undefined)[][] = [
|
|
231
|
+
// Valid
|
|
232
|
+
['1.2.x', undefined],
|
|
233
|
+
['1.2.3', undefined],
|
|
234
|
+
['1.2', undefined],
|
|
235
|
+
['> 1', undefined],
|
|
236
|
+
['', undefined],
|
|
237
|
+
[null, undefined],
|
|
238
|
+
|
|
239
|
+
// Invalid
|
|
240
|
+
['foo', message],
|
|
241
|
+
['1.2.', message],
|
|
242
|
+
['.', message],
|
|
243
|
+
];
|
|
244
|
+
|
|
245
|
+
it.each(testCases)(
|
|
246
|
+
'should return undefined or correct message based on the provided Semantic Version: %p',
|
|
247
|
+
(version, expected) => {
|
|
248
|
+
const formRuleResult = formRules.semanticVersion(version);
|
|
249
|
+
|
|
250
|
+
expect(formRuleResult).toStrictEqual(expected);
|
|
251
|
+
}
|
|
252
|
+
);
|
|
253
|
+
});
|
|
254
|
+
|
|
171
255
|
describe('alphanumeric', () => {
|
|
172
256
|
const message = JSON.stringify({ message: 'validation.alphanumeric', key: 'testDisplayKey' });
|
|
173
257
|
const testCases = [
|
|
@@ -1,3 +1,5 @@
|
|
|
1
|
+
import semver from 'semver';
|
|
2
|
+
import { parse } from '@shell/utils/url';
|
|
1
3
|
import { RBAC } from '@shell/config/types';
|
|
2
4
|
import { HCI } from '@shell/config/labels-annotations';
|
|
3
5
|
import isEmpty from 'lodash/isEmpty';
|
|
@@ -5,7 +7,7 @@ import has from 'lodash/has';
|
|
|
5
7
|
import isUrl from 'is-url';
|
|
6
8
|
// import uniq from 'lodash/uniq';
|
|
7
9
|
import { Translation } from '@shell/types/t';
|
|
8
|
-
import { isHttps, isLocalhost, hasTrailingForwardSlash } from '@shell/utils/validators/setting';
|
|
10
|
+
import { isHttps, isLocalhost, hasTrailingForwardSlash, isDomainWithoutProtocol } from '@shell/utils/validators/setting';
|
|
9
11
|
import { cronScheduleRule } from '@shell/utils/validators/cron-schedule';
|
|
10
12
|
|
|
11
13
|
// import uniq from 'lodash/uniq';
|
|
@@ -164,6 +166,8 @@ export default function(
|
|
|
164
166
|
|
|
165
167
|
const https: Validator = (val: string) => val && !isHttps(val) ? t('validation.setting.serverUrl.https') : undefined;
|
|
166
168
|
|
|
169
|
+
const awsStyleEndpoint: Validator = (val: string) => val && !isDomainWithoutProtocol(val) ? t('validation.setting.serverUrl.awsStyleEndpoint') : undefined;
|
|
170
|
+
|
|
167
171
|
const localhost: Validator = (val: string) => isLocalhost(val) ? t('validation.setting.serverUrl.localhost') : undefined;
|
|
168
172
|
|
|
169
173
|
const trailingForwardSlash: Validator = (val: string) => hasTrailingForwardSlash(val) ? t('validation.setting.serverUrl.trailingForwardSlash') : undefined;
|
|
@@ -173,22 +177,91 @@ export default function(
|
|
|
173
177
|
const genericUrl: Validator = (val: string) => val && !isUrl(val) ? t('validation.genericUrl') : undefined;
|
|
174
178
|
|
|
175
179
|
const urlRepository: Validator = (url: string) => {
|
|
176
|
-
const
|
|
177
|
-
|
|
180
|
+
const message = t('validation.repository.url');
|
|
181
|
+
|
|
182
|
+
if (!url) {
|
|
183
|
+
return message;
|
|
184
|
+
}
|
|
185
|
+
|
|
186
|
+
if (url.includes(' ')) {
|
|
187
|
+
return message;
|
|
188
|
+
}
|
|
189
|
+
|
|
190
|
+
const {
|
|
191
|
+
protocol,
|
|
192
|
+
authority,
|
|
193
|
+
host,
|
|
194
|
+
port,
|
|
195
|
+
path
|
|
196
|
+
} = parse(url);
|
|
197
|
+
|
|
198
|
+
// Test duplicate protocol
|
|
199
|
+
if (!host || protocol === host) {
|
|
200
|
+
return message;
|
|
201
|
+
}
|
|
202
|
+
|
|
203
|
+
// Test http(s) protocol
|
|
204
|
+
if (protocol && (!/^(http|http(s))/gm.test(protocol) || (!url.startsWith('https://') && !url.startsWith('http://')))) {
|
|
205
|
+
return message;
|
|
206
|
+
}
|
|
207
|
+
|
|
208
|
+
// Test ssh, authority must be valid (SSH user + host)
|
|
209
|
+
if (!protocol && !port && (!authority.endsWith(':') || path.startsWith('/'))) {
|
|
210
|
+
return message;
|
|
211
|
+
}
|
|
178
212
|
|
|
179
|
-
|
|
180
|
-
|
|
213
|
+
// Encoded space characters (%20) are allowed only in the path
|
|
214
|
+
const hostAndPath = `${ host }${ path.replaceAll('%20', '') }`;
|
|
181
215
|
|
|
182
|
-
|
|
216
|
+
// Test host/path
|
|
217
|
+
if (!/^([\w\.@\:\/\-]+)([\d\/\w.-]+?)(.git){0,1}(\/)?$/gm.test(hostAndPath)) {
|
|
218
|
+
return message;
|
|
183
219
|
}
|
|
184
220
|
|
|
185
221
|
return undefined;
|
|
186
222
|
};
|
|
187
223
|
|
|
188
224
|
const ociRegistry: Validator = (url: string) => {
|
|
189
|
-
const
|
|
225
|
+
const message = t('validation.oci.url');
|
|
226
|
+
|
|
227
|
+
if (!url) {
|
|
228
|
+
return message;
|
|
229
|
+
}
|
|
230
|
+
|
|
231
|
+
if (url.includes(' ')) {
|
|
232
|
+
return message;
|
|
233
|
+
}
|
|
234
|
+
|
|
235
|
+
const {
|
|
236
|
+
protocol,
|
|
237
|
+
host,
|
|
238
|
+
path
|
|
239
|
+
} = parse(url);
|
|
240
|
+
|
|
241
|
+
// Test duplicate protocol
|
|
242
|
+
if (!host || protocol === host) {
|
|
243
|
+
return message;
|
|
244
|
+
}
|
|
245
|
+
|
|
246
|
+
// Test oci protocol
|
|
247
|
+
if (!url.startsWith('oci://')) {
|
|
248
|
+
return message;
|
|
249
|
+
}
|
|
250
|
+
|
|
251
|
+
// Test host/path
|
|
252
|
+
if (!/^([\w\.@\:\/\-]+)([\d\/\w.-]+?)(\/)?$/gm.test(`${ host }${ path }`)) {
|
|
253
|
+
return message;
|
|
254
|
+
}
|
|
255
|
+
|
|
256
|
+
return undefined;
|
|
257
|
+
};
|
|
258
|
+
|
|
259
|
+
const version: Validator = (value: string) => {
|
|
260
|
+
return value && !semver.valid(value) ? t('validation.version') : undefined;
|
|
261
|
+
};
|
|
190
262
|
|
|
191
|
-
|
|
263
|
+
const semanticVersion: Validator = (value: string) => {
|
|
264
|
+
return value && !semver.validRange(value) ? t('validation.semanticVersion') : undefined;
|
|
192
265
|
};
|
|
193
266
|
|
|
194
267
|
const alphanumeric: Validator = (val: string) => val && !/^[a-zA-Z0-9]+$/.test(val) ? t('validation.alphanumeric', { key }) : undefined;
|
|
@@ -541,6 +614,7 @@ export default function(
|
|
|
541
614
|
imageUrl,
|
|
542
615
|
interval,
|
|
543
616
|
https,
|
|
617
|
+
awsStyleEndpoint,
|
|
544
618
|
localhost,
|
|
545
619
|
trailingForwardSlash,
|
|
546
620
|
url,
|
|
@@ -561,9 +635,11 @@ export default function(
|
|
|
561
635
|
isOctal,
|
|
562
636
|
roleTemplateRules,
|
|
563
637
|
ruleGroups,
|
|
638
|
+
semanticVersion,
|
|
564
639
|
servicePort,
|
|
565
640
|
subDomain,
|
|
566
641
|
testRule,
|
|
642
|
+
version,
|
|
567
643
|
wildcardHostname
|
|
568
644
|
};
|
|
569
645
|
}
|
|
@@ -1,9 +1,26 @@
|
|
|
1
1
|
import isUrl from 'is-url';
|
|
2
2
|
|
|
3
|
+
// Note that these function cover specific use cases and you need to make sure it works for your use case before using them.
|
|
4
|
+
// ie they would consider empty values as valid, not all endpoint formatting is enforced
|
|
5
|
+
|
|
3
6
|
export const isServerUrl = (value) => value === 'server-url';
|
|
4
7
|
|
|
5
8
|
export const isHttps = (value) => value.toLowerCase().startsWith('https://');
|
|
6
9
|
|
|
10
|
+
/**
|
|
11
|
+
* Checks that provided string is a domain without protocol (case insensitive):
|
|
12
|
+
* - Cannot start with any protocol, such as http://, https://, ftp://, ftps://, udp://
|
|
13
|
+
* - Must only use the letters a to z, the numbers 0 to 9, and the dot (.) and hyphen (-) characters.
|
|
14
|
+
* - if the hyphen character is used in a domain name, it cannot be the first or the last character in the name.
|
|
15
|
+
* - The length of each label can be 2-63 characters
|
|
16
|
+
* - TLD is at least 2 characters
|
|
17
|
+
* - The total length of a domain name, including the dot at the end, cannot exceed 254 characters.
|
|
18
|
+
* - Allows for optional port and path
|
|
19
|
+
* @param {*} value
|
|
20
|
+
* @returns boolean indicating if the value is a domain without protocol
|
|
21
|
+
*/
|
|
22
|
+
export const isDomainWithoutProtocol = (value) => (/^(?=.{1,254}$)(?![a-z][a-z0-9+.-]*:\/\/)(?:[a-z0-9](?:[a-z0-9-]{0,61}[a-z0-9])?\.)+[a-z]{2,}(?::\d{1,5})?(?:\/\S*)?$/i).test(value);
|
|
23
|
+
|
|
7
24
|
export const isLocalhost = (value) => (/^(?:https?:\/\/)?(?:localhost|127\.0\.0\.1)/i).test(value);
|
|
8
25
|
|
|
9
26
|
export const hasTrailingForwardSlash = (value) => isUrl(value) && value?.toLowerCase().endsWith('/');
|
package/vue.config.js
CHANGED
|
@@ -546,7 +546,7 @@ module.exports = function(dir, appConfig = {}) {
|
|
|
546
546
|
config.plugins.push(getVirtualModulesAutoImport(dir));
|
|
547
547
|
config.plugins.push(getPackageImport(dir));
|
|
548
548
|
config.plugins.push(createEnvVariablesPlugin(routerBasePath, rancherEnv));
|
|
549
|
-
config.plugins.push(new NodePolyfillPlugin()); // required from Webpack 5 to polyfill node modules
|
|
549
|
+
config.plugins.push(new NodePolyfillPlugin({ additionalAliases: ['process'] })); // required from Webpack 5 to polyfill node modules
|
|
550
550
|
|
|
551
551
|
// The static assets need to be in the built assets directory in order to get served (primarily the favicon)
|
|
552
552
|
config.plugins.push(new CopyWebpackPlugin({ patterns: [{ from: path.join(SHELL_ABS, 'static'), to: '.' }] }));
|
|
@@ -1,18 +0,0 @@
|
|
|
1
|
-
import { mount } from '@vue/test-utils';
|
|
2
|
-
import HarvesterCloudCreds from '@shell/cloud-credential/harvester.vue';
|
|
3
|
-
|
|
4
|
-
const mockStore = { getters: { 'i18n/t': jest.fn() } };
|
|
5
|
-
|
|
6
|
-
describe('cloud credentials: Harvester', () => {
|
|
7
|
-
const wrapper = mount(HarvesterCloudCreds, {
|
|
8
|
-
props: { value: {} },
|
|
9
|
-
global: { mocks: { $store: mockStore } }
|
|
10
|
-
});
|
|
11
|
-
|
|
12
|
-
it('should display the warning banner for token expiration', async() => {
|
|
13
|
-
const warningBanner = wrapper.find('[data-testid="harvester-token-expiration-warning-banner"]');
|
|
14
|
-
|
|
15
|
-
expect(warningBanner.exists()).toBe(true);
|
|
16
|
-
expect(warningBanner.isVisible()).toBe(true);
|
|
17
|
-
});
|
|
18
|
-
});
|
|
@@ -1,34 +0,0 @@
|
|
|
1
|
-
<script setup lang="ts">
|
|
2
|
-
export interface RectangleProps {
|
|
3
|
-
outline?: boolean;
|
|
4
|
-
}
|
|
5
|
-
|
|
6
|
-
const props = withDefaults(
|
|
7
|
-
defineProps<RectangleProps>(),
|
|
8
|
-
{ outline: false }
|
|
9
|
-
);
|
|
10
|
-
|
|
11
|
-
</script>
|
|
12
|
-
|
|
13
|
-
<template>
|
|
14
|
-
<div
|
|
15
|
-
class="rectangle"
|
|
16
|
-
:class="{outline: props.outline}"
|
|
17
|
-
>
|
|
18
|
-
<slot />
|
|
19
|
-
</div>
|
|
20
|
-
</template>
|
|
21
|
-
|
|
22
|
-
<style lang="scss" scoped>
|
|
23
|
-
.rectangle {
|
|
24
|
-
border: 1px solid var(--tag-bg);
|
|
25
|
-
border-radius: 4px;
|
|
26
|
-
padding: 0 8px;
|
|
27
|
-
height: 23px;
|
|
28
|
-
line-height: 23px;
|
|
29
|
-
|
|
30
|
-
&:not(.outline) {
|
|
31
|
-
background-color: var(--tag-bg);
|
|
32
|
-
}
|
|
33
|
-
}
|
|
34
|
-
</style>
|
|
@@ -1,24 +0,0 @@
|
|
|
1
|
-
import { mount } from '@vue/test-utils';
|
|
2
|
-
import Rectangle from '@shell/components/Resource/Detail/Metadata/Rectangle.vue';
|
|
3
|
-
|
|
4
|
-
describe('component: Rectangle', () => {
|
|
5
|
-
it('should render container with class title and missing outline when passed outline:false', async() => {
|
|
6
|
-
const wrapper = mount(Rectangle, { props: { outline: false } });
|
|
7
|
-
|
|
8
|
-
expect(wrapper.find('.rectangle').exists()).toBeTruthy();
|
|
9
|
-
expect(wrapper.find('.rectangle.outline').exists()).toBeFalsy();
|
|
10
|
-
});
|
|
11
|
-
|
|
12
|
-
it('should render outline class when passed outline:true', async() => {
|
|
13
|
-
const wrapper = mount(Rectangle, { props: { outline: true } });
|
|
14
|
-
|
|
15
|
-
expect(wrapper.find('.rectangle.outline').exists()).toBeTruthy();
|
|
16
|
-
});
|
|
17
|
-
|
|
18
|
-
it('should render default slot', async() => {
|
|
19
|
-
const content = 'CONTENT';
|
|
20
|
-
const wrapper = mount(Rectangle, { slots: { default: content } });
|
|
21
|
-
|
|
22
|
-
expect(wrapper.find('.rectangle').element.innerHTML).toStrictEqual(content);
|
|
23
|
-
});
|
|
24
|
-
});
|
|
@@ -1,65 +0,0 @@
|
|
|
1
|
-
import { mount, RouterLinkStub } from '@vue/test-utils';
|
|
2
|
-
import { _VIEW } from '@shell/config/query-params';
|
|
3
|
-
import Legacy from '@shell/components/ResourceDetail/Masthead/legacy.vue';
|
|
4
|
-
import { createStore } from 'vuex';
|
|
5
|
-
|
|
6
|
-
const mockedStore = () => {
|
|
7
|
-
return {
|
|
8
|
-
getters: {
|
|
9
|
-
currentStore: () => 'current_store',
|
|
10
|
-
currentProduct: { inStore: 'cluster' },
|
|
11
|
-
isExplorer: false,
|
|
12
|
-
currentCluster: {},
|
|
13
|
-
'type-map/labelFor': jest.fn(),
|
|
14
|
-
'type-map/optionsFor': jest.fn(),
|
|
15
|
-
'current_store/schemaFor': jest.fn(),
|
|
16
|
-
},
|
|
17
|
-
};
|
|
18
|
-
};
|
|
19
|
-
|
|
20
|
-
const requiredSetup = () => {
|
|
21
|
-
const store = createStore({ getters: { 'management/byId': () => jest.fn() } });
|
|
22
|
-
|
|
23
|
-
return {
|
|
24
|
-
stubs: {
|
|
25
|
-
'router-link': RouterLinkStub,
|
|
26
|
-
LiveDate: true
|
|
27
|
-
},
|
|
28
|
-
provide: { store },
|
|
29
|
-
mocks: { $store: mockedStore() }
|
|
30
|
-
};
|
|
31
|
-
};
|
|
32
|
-
|
|
33
|
-
describe('component: Masthead/legacy', () => {
|
|
34
|
-
it.each([
|
|
35
|
-
['hidden', '', false, { displayName: 'admin', location: { id: 'resource-id' } }, false, false],
|
|
36
|
-
['plain-text', 'admin', true, { displayName: 'admin', location: null }, false, true],
|
|
37
|
-
['link', 'foo', true, { displayName: 'foo', location: { id: 'resource-id' } }, true, false],
|
|
38
|
-
])('"Created By" should be %p, with text: %p', (
|
|
39
|
-
_,
|
|
40
|
-
text,
|
|
41
|
-
showCreatedBy,
|
|
42
|
-
createdBy,
|
|
43
|
-
showLink,
|
|
44
|
-
showPlainText,
|
|
45
|
-
) => {
|
|
46
|
-
const wrapper = mount(Legacy, {
|
|
47
|
-
props: {
|
|
48
|
-
mode: _VIEW,
|
|
49
|
-
value: {
|
|
50
|
-
showCreatedBy,
|
|
51
|
-
createdBy,
|
|
52
|
-
},
|
|
53
|
-
},
|
|
54
|
-
global: { ...requiredSetup() }
|
|
55
|
-
});
|
|
56
|
-
|
|
57
|
-
const container = wrapper.find('[data-testid="masthead-subheader-createdBy"]');
|
|
58
|
-
const link = wrapper.find('[data-testid="masthead-subheader-createdBy-link"]');
|
|
59
|
-
const plainText = wrapper.find('[data-testid="masthead-subheader-createdBy_plain-text"]');
|
|
60
|
-
|
|
61
|
-
expect(link.exists()).toBe(showLink);
|
|
62
|
-
expect(plainText.exists()).toBe(showPlainText);
|
|
63
|
-
expect(showLink || showPlainText ? container.element.textContent : '').toContain(text);
|
|
64
|
-
});
|
|
65
|
-
});
|
|
@@ -1,135 +0,0 @@
|
|
|
1
|
-
import { mount } from '@vue/test-utils';
|
|
2
|
-
import ResourceDetail from '@shell/components/ResourceDetail/index.vue';
|
|
3
|
-
import { _EDIT, _VIEW, LEGACY, MODE } from '@shell/config/query-params';
|
|
4
|
-
import * as pageEnabled from '@shell/composables/useIsNewDetailPageEnabled';
|
|
5
|
-
import flushPromises from 'flush-promises';
|
|
6
|
-
import { computed } from 'vue';
|
|
7
|
-
|
|
8
|
-
const mockQuery: any = {};
|
|
9
|
-
const mockParams: any = {};
|
|
10
|
-
|
|
11
|
-
jest.mock('@shell/components/ResourceDetail/legacy.vue', () => ({
|
|
12
|
-
template: '<div class="legacy">Legacy</div>',
|
|
13
|
-
name: 'Legacy',
|
|
14
|
-
props: ['flexContent', 'componentTestId', 'storeOverride', 'resourceOverride', 'parentRouteOverride', 'errorsMap']
|
|
15
|
-
}));
|
|
16
|
-
|
|
17
|
-
jest.mock('@shell/components/Loading.vue', () => ({
|
|
18
|
-
template: '<div class="loading">Loading</div>',
|
|
19
|
-
name: 'Loading'
|
|
20
|
-
}));
|
|
21
|
-
|
|
22
|
-
jest.mock('@shell/pages/explorer/resource/detail/configmap.vue', () => ({
|
|
23
|
-
template: '<div class="configmap">configmap</div>',
|
|
24
|
-
name: 'configmap',
|
|
25
|
-
}));
|
|
26
|
-
|
|
27
|
-
jest.mock('vue-router', () => ({
|
|
28
|
-
useRoute: () => ({
|
|
29
|
-
query: mockQuery,
|
|
30
|
-
params: mockParams
|
|
31
|
-
})
|
|
32
|
-
}));
|
|
33
|
-
|
|
34
|
-
jest.mock('@shell/composables/useIsNewDetailPageEnabled');
|
|
35
|
-
|
|
36
|
-
describe('component: ResourceDetail/index', () => {
|
|
37
|
-
const resourceName = 'configmap';
|
|
38
|
-
const useIsNewDetailPageEnabledSpy = jest.spyOn(pageEnabled, 'useIsNewDetailPageEnabled');
|
|
39
|
-
|
|
40
|
-
beforeEach(() => {
|
|
41
|
-
jest.clearAllMocks();
|
|
42
|
-
});
|
|
43
|
-
|
|
44
|
-
it('should render legacy component with default props if useIsNewDetailPageEnabledSpy is false', async() => {
|
|
45
|
-
mockParams.resource = resourceName;
|
|
46
|
-
mockQuery[MODE] = _VIEW;
|
|
47
|
-
|
|
48
|
-
useIsNewDetailPageEnabledSpy.mockReturnValue(computed(() => false));
|
|
49
|
-
|
|
50
|
-
const wrapper = mount(ResourceDetail, { });
|
|
51
|
-
const legacyComponent = wrapper.findComponent<any>({ name: 'Legacy' });
|
|
52
|
-
|
|
53
|
-
expect(legacyComponent.props('flexContent')).toStrictEqual(false);
|
|
54
|
-
expect(legacyComponent.props('componentTestId')).toStrictEqual('resource-details');
|
|
55
|
-
expect(legacyComponent.props('storeOverride')).toBeUndefined();
|
|
56
|
-
expect(legacyComponent.props('resourceOverride')).toBeUndefined();
|
|
57
|
-
expect(legacyComponent.props('parentRouteOverride')).toBeUndefined();
|
|
58
|
-
expect(legacyComponent.props('errorsMap')).toBeUndefined();
|
|
59
|
-
expect(useIsNewDetailPageEnabledSpy).toHaveBeenCalledTimes(1);
|
|
60
|
-
});
|
|
61
|
-
|
|
62
|
-
it('should render legacy component with default props if useIsNewDetailPageEnabledSpy is false but resourceName has not been added to our mapping', async() => {
|
|
63
|
-
mockParams.resource = 'notMapped';
|
|
64
|
-
mockQuery[MODE] = _VIEW;
|
|
65
|
-
|
|
66
|
-
useIsNewDetailPageEnabledSpy.mockReturnValue(computed(() => false));
|
|
67
|
-
|
|
68
|
-
const wrapper = mount(ResourceDetail, {});
|
|
69
|
-
const legacyComponent = wrapper.findComponent<any>({ name: 'Legacy' });
|
|
70
|
-
|
|
71
|
-
expect(legacyComponent.exists()).toBeTruthy();
|
|
72
|
-
expect(useIsNewDetailPageEnabledSpy).toHaveBeenCalledTimes(1);
|
|
73
|
-
});
|
|
74
|
-
|
|
75
|
-
it('should render legacy component with default props if useIsNewDetailPageEnabledSpy is false but mode is not VIEW', async() => {
|
|
76
|
-
mockParams.resource = resourceName;
|
|
77
|
-
mockQuery[MODE] = _EDIT;
|
|
78
|
-
|
|
79
|
-
useIsNewDetailPageEnabledSpy.mockReturnValue(computed(() => false));
|
|
80
|
-
|
|
81
|
-
const wrapper = mount(ResourceDetail, {});
|
|
82
|
-
const legacyComponent = wrapper.findComponent<any>({ name: 'Legacy' });
|
|
83
|
-
|
|
84
|
-
expect(legacyComponent.exists()).toBeTruthy();
|
|
85
|
-
expect(useIsNewDetailPageEnabledSpy).toHaveBeenCalledTimes(1);
|
|
86
|
-
});
|
|
87
|
-
|
|
88
|
-
it('should render legacy component while forwarding props', async() => {
|
|
89
|
-
mockParams.resource = resourceName;
|
|
90
|
-
mockQuery[MODE] = _VIEW;
|
|
91
|
-
|
|
92
|
-
const flexContent = true;
|
|
93
|
-
const componentTestId = 'componentTestId';
|
|
94
|
-
const storeOverride = 'storeOverride';
|
|
95
|
-
const resourceOverride = 'resourceOverride';
|
|
96
|
-
const parentRouteOverride = 'parentRouteOverride';
|
|
97
|
-
const errorsMap = { error: 'test' };
|
|
98
|
-
|
|
99
|
-
const wrapper = mount(ResourceDetail, {
|
|
100
|
-
props: {
|
|
101
|
-
flexContent,
|
|
102
|
-
componentTestId,
|
|
103
|
-
storeOverride,
|
|
104
|
-
resourceOverride,
|
|
105
|
-
parentRouteOverride,
|
|
106
|
-
errorsMap,
|
|
107
|
-
}
|
|
108
|
-
});
|
|
109
|
-
const legacyComponent = wrapper.findComponent<any>({ name: 'Legacy' });
|
|
110
|
-
|
|
111
|
-
expect(legacyComponent.props('flexContent')).toStrictEqual(flexContent);
|
|
112
|
-
expect(legacyComponent.props('componentTestId')).toStrictEqual(componentTestId);
|
|
113
|
-
expect(legacyComponent.props('storeOverride')).toStrictEqual(storeOverride);
|
|
114
|
-
expect(legacyComponent.props('resourceOverride')).toStrictEqual(resourceOverride);
|
|
115
|
-
expect(legacyComponent.props('parentRouteOverride')).toStrictEqual(parentRouteOverride);
|
|
116
|
-
expect(legacyComponent.props('errorsMap')).toStrictEqual(errorsMap);
|
|
117
|
-
});
|
|
118
|
-
|
|
119
|
-
it('should render new component if useIsNewDetailPageEnabledSpy is true', async() => {
|
|
120
|
-
mockParams.resource = resourceName;
|
|
121
|
-
mockParams.id = 'ID';
|
|
122
|
-
mockQuery[MODE] = _VIEW;
|
|
123
|
-
mockQuery[LEGACY] = 'false';
|
|
124
|
-
|
|
125
|
-
useIsNewDetailPageEnabledSpy.mockReturnValue(computed(() => true));
|
|
126
|
-
|
|
127
|
-
const wrapper = mount(ResourceDetail);
|
|
128
|
-
|
|
129
|
-
await flushPromises();
|
|
130
|
-
const configmapComponent = wrapper.findComponent<any>({ name: 'configmap' });
|
|
131
|
-
|
|
132
|
-
expect(configmapComponent.exists()).toBeTruthy();
|
|
133
|
-
expect(useIsNewDetailPageEnabledSpy).toHaveBeenCalledTimes(1);
|
|
134
|
-
});
|
|
135
|
-
});
|