@rancher/shell 3.0.4 → 3.0.5-rc.2
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/images/providers/sks.svg +1 -0
- package/assets/styles/base/_basic.scss +6 -0
- package/assets/styles/base/_helpers.scss +4 -0
- package/assets/styles/base/_variables.scss +1 -0
- package/assets/styles/global/_button.scss +1 -0
- package/assets/translations/en-us.yaml +65 -15
- package/assets/translations/zh-hans.yaml +4 -3
- package/chart/monitoring/index.vue +3 -1
- package/cloud-credential/aws.vue +2 -0
- package/components/ActionDropdownShell.vue +71 -0
- package/components/AppModal.vue +18 -4
- package/components/AsyncButton.vue +24 -7
- package/components/BannerGraphic.vue +1 -0
- package/components/CommunityLinks.vue +4 -59
- package/components/CopyToClipboardText.vue +2 -1
- package/components/CruResource.vue +6 -1
- package/components/DetailText.vue +5 -0
- package/components/ExplorerMembers.vue +1 -1
- package/components/ExplorerProjectsNamespaces.vue +68 -18
- package/components/GlobalRoleBindings.vue +5 -1
- package/components/GrowlManager.vue +1 -0
- package/components/LandingPagePreference.vue +7 -3
- package/components/LocaleSelector.vue +39 -95
- package/components/ModalManager.vue +55 -0
- package/components/ModalWithCard.vue +1 -0
- package/components/PromptModal.vue +47 -8
- package/components/PromptRemove.vue +1 -0
- package/components/PromptRestore.vue +1 -0
- package/components/ResourceCancelModal.vue +1 -0
- package/components/ResourceDetail/Masthead.vue +38 -12
- package/components/ResourceDetail/__tests__/Masthead.test.ts +5 -1
- package/components/ResourceDetail/index.vue +47 -12
- package/components/ResourceTable.vue +54 -19
- package/components/SideNav.vue +5 -1
- package/components/SlideInPanelManager.vue +126 -0
- package/components/SortableTable/THead.vue +5 -2
- package/components/SortableTable/actions.js +1 -1
- package/components/SortableTable/index.vue +64 -51
- package/components/SortableTable/paging.js +16 -19
- package/components/SortableTable/selection.js +0 -11
- package/components/Wizard.vue +2 -2
- package/components/__tests__/AsyncButton.test.ts +2 -2
- package/components/__tests__/ModalManager.spec.ts +176 -0
- package/components/__tests__/PromptModal.test.ts +148 -0
- package/components/__tests__/SlideInPanelManager.spec.ts +166 -0
- package/components/auth/AuthBanner.vue +13 -11
- package/components/auth/Principal.vue +1 -0
- package/components/auth/__tests__/RoleDetailEdit.test.ts +3 -2
- package/components/auth/login/ldap.vue +1 -1
- package/components/fleet/FleetResources.vue +21 -6
- package/components/form/ArrayList.vue +76 -60
- package/components/form/BannerSettings.vue +17 -2
- package/components/form/ColorInput.vue +35 -6
- package/components/form/Command.vue +6 -15
- package/components/form/EnvVars.vue +16 -8
- package/components/form/HealthCheck.vue +3 -3
- package/components/form/HookOption.vue +11 -16
- package/components/form/LabeledSelect.vue +18 -22
- package/components/form/LifecycleHooks.vue +3 -3
- package/components/form/MatchExpressions.vue +14 -8
- package/components/form/NameNsDescription.vue +128 -104
- package/components/form/Networking.vue +20 -12
- package/components/form/NodeAffinity.vue +31 -23
- package/components/form/NodeScheduling.vue +13 -3
- package/components/form/NotificationSettings.vue +15 -1
- package/components/form/Password.vue +1 -0
- package/components/form/PodAffinity.vue +43 -43
- package/components/form/Probe.vue +68 -66
- package/components/form/ResourceQuota/Project.vue +5 -1
- package/components/form/ResourceSelector.vue +7 -9
- package/components/form/SSHKnownHosts/__tests__/KnownHostsEditDialog.test.ts +16 -24
- package/components/form/SSHKnownHosts/index.vue +30 -13
- package/components/form/Security.vue +54 -56
- package/components/form/Select.vue +32 -21
- package/components/form/ShellInput.vue +5 -1
- package/components/form/Tolerations.vue +5 -1
- package/components/form/ValueFromResource.vue +134 -121
- package/components/form/WorkloadPorts.vue +18 -18
- package/components/form/__tests__/ArrayList.test.ts +5 -2
- package/components/form/__tests__/ColorInput.test.ts +35 -0
- package/components/form/__tests__/LabeledSelect.test.ts +40 -0
- package/components/form/__tests__/MatchExpressions.test.ts +12 -12
- package/components/form/__tests__/NameNsDescription.test.ts +115 -14
- package/components/form/__tests__/Probe.test.ts +12 -8
- package/components/form/__tests__/SSHKnownHosts.test.ts +22 -2
- package/components/form/__tests__/Select.test.ts +37 -0
- package/components/formatter/InternalExternalIP.vue +2 -0
- package/components/formatter/SecretData.vue +20 -7
- package/components/nav/Group.vue +27 -5
- package/components/nav/Header.vue +17 -43
- package/components/nav/NamespaceFilter.vue +134 -86
- package/components/nav/TopLevelMenu.vue +4 -5
- package/components/nav/Type.vue +12 -1
- package/components/nav/WindowManager/ContainerLogs.vue +87 -61
- package/components/nav/WindowManager/ContainerLogsActions.vue +76 -0
- package/components/templates/blank.vue +4 -1
- package/components/templates/default.vue +8 -3
- package/components/templates/home.vue +10 -1
- package/components/templates/plain.vue +10 -4
- package/composables/focusTrap.ts +12 -4
- package/composables/useRuntimeFlag.ts +29 -0
- package/config/router/routes.js +20 -13
- package/config/store.js +4 -0
- package/config/uiplugins.js +5 -1
- package/core/types.ts +12 -6
- package/detail/catalog.cattle.io.app.vue +6 -1
- package/detail/fleet.cattle.io.bundle.vue +70 -6
- package/detail/fleet.cattle.io.gitrepo.vue +1 -1
- package/detail/namespace.vue +0 -3
- package/detail/node.vue +17 -13
- package/detail/provisioning.cattle.io.cluster.vue +72 -6
- package/dialog/AddCustomBadgeDialog.vue +1 -1
- package/{pages/c/_cluster/uiplugins/AddExtensionRepos.vue → dialog/AddExtensionReposDialog.vue} +72 -42
- package/{components/AssignTo.vue → dialog/AssignToDialog.vue} +71 -80
- package/dialog/ChangePasswordDialog.vue +106 -0
- package/dialog/DeactivateDriverDialog.vue +1 -0
- package/{pages/c/_cluster/uiplugins/DeveloperInstallDialog.vue → dialog/DeveloperLoadExtensionDialog.vue} +74 -71
- package/dialog/DisableAuthProviderDialog.vue +101 -0
- package/dialog/DrainNode.vue +1 -1
- package/{pages/c/_cluster/uiplugins/CatalogList/CatalogLoadDialog.vue → dialog/ExtensionCatalogInstallDialog.vue} +100 -88
- package/{pages/c/_cluster/uiplugins/CatalogList/CatalogUninstallDialog.vue → dialog/ExtensionCatalogUninstallDialog.vue} +69 -57
- package/dialog/FeatureFlagListDialog.vue +288 -0
- package/dialog/ForceMachineRemoveDialog.vue +5 -2
- package/{components/Import.vue → dialog/ImportDialog.vue} +0 -5
- package/{pages/c/_cluster/uiplugins/InstallDialog.vue → dialog/InstallExtensionDialog.vue} +124 -106
- package/{components/form/SSHKnownHosts → dialog}/KnownHostsEditDialog.vue +52 -59
- package/dialog/MoveNamespaceDialog.vue +157 -0
- package/dialog/ScalePoolDownDialog.vue +1 -1
- package/{components/nav/Jump.vue → dialog/SearchDialog.vue} +34 -14
- package/{pages/c/_cluster/uiplugins/UninstallDialog.vue → dialog/UninstallExtensionDialog.vue} +67 -58
- package/dialog/WechatDialog.vue +57 -0
- package/edit/__tests__/monitoring.coreos.com.prometheusrule.test.ts +16 -3
- package/edit/auth/__tests__/oidc.test.ts +152 -109
- package/edit/auth/azuread.vue +2 -1
- package/edit/auth/github.vue +1 -1
- package/edit/auth/googleoauth.vue +5 -1
- package/edit/auth/ldap/index.vue +1 -1
- package/edit/auth/oidc.vue +38 -5
- package/edit/auth/saml.vue +1 -1
- package/edit/cloudcredential.vue +24 -9
- package/edit/logging.banzaicloud.io.output/__tests__/logging.banzaicloud.io.output.test.ts +40 -9
- package/edit/management.cattle.io.user.vue +28 -3
- package/edit/namespace.vue +1 -4
- package/edit/networking.k8s.io.ingress/IngressClass.vue +7 -3
- package/edit/networking.k8s.io.ingress/__tests__/IngressClass.test.ts +58 -0
- package/edit/persistentvolume/__tests__/persistentvolume.test.ts +14 -2
- package/edit/provisioning.cattle.io.cluster/CustomCommand.vue +4 -1
- package/edit/provisioning.cattle.io.cluster/SelectCredential.vue +26 -9
- package/edit/provisioning.cattle.io.cluster/__tests__/Advanced.test.ts +8 -8
- package/edit/provisioning.cattle.io.cluster/__tests__/DirectoryConfig.test.ts +26 -12
- package/edit/provisioning.cattle.io.cluster/__tests__/rke2.test.ts +66 -0
- package/edit/provisioning.cattle.io.cluster/__tests__/utils/rke2-test-data.ts +58 -0
- package/edit/provisioning.cattle.io.cluster/rke2.vue +49 -41
- package/edit/provisioning.cattle.io.cluster/tabs/AgentConfiguration.vue +6 -1
- package/edit/provisioning.cattle.io.cluster/tabs/DirectoryConfig.vue +5 -3
- package/edit/provisioning.cattle.io.cluster/tabs/MachinePool.vue +33 -2
- package/edit/provisioning.cattle.io.cluster/tabs/etcd/index.vue +2 -2
- package/edit/token.vue +2 -0
- package/edit/workload/index.vue +1 -0
- package/edit/workload/mixins/workload.js +0 -2
- package/initialize/install-plugins.js +2 -1
- package/list/harvesterhci.io.management.cluster.vue +4 -1
- package/list/management.cattle.io.feature.vue +4 -287
- package/list/provisioning.cattle.io.cluster.vue +20 -12
- package/machine-config/azure.vue +16 -4
- package/mixins/vue-select-overrides.js +0 -4
- package/models/__tests__/namespace.test.ts +25 -1
- package/models/cloudcredential.js +5 -0
- package/models/fleet.cattle.io.cluster.js +8 -2
- package/models/fleet.cattle.io.gitrepo.js +8 -34
- package/models/kontainerdriver.js +6 -3
- package/models/management.cattle.io.feature.js +7 -1
- package/models/management.cattle.io.node.js +3 -3
- package/models/namespace.js +11 -6
- package/models/nodedriver.js +6 -3
- package/models/workload.js +4 -1
- package/package.json +3 -3
- package/pages/about.vue +13 -3
- package/pages/account/index.vue +16 -6
- package/pages/auth/login.vue +18 -7
- package/pages/auth/logout.vue +4 -1
- package/pages/auth/setup.vue +2 -0
- package/pages/auth/verify.vue +13 -8
- package/pages/c/_cluster/apps/charts/chart.vue +1 -1
- package/pages/c/_cluster/apps/charts/install.vue +26 -26
- package/pages/c/_cluster/auth/config/index.vue +10 -12
- package/pages/c/_cluster/explorer/EventsTable.vue +38 -33
- package/pages/c/_cluster/explorer/index.vue +17 -15
- package/pages/c/_cluster/istio/index.vue +2 -2
- package/pages/c/_cluster/longhorn/index.vue +1 -1
- package/pages/c/_cluster/monitoring/index.vue +1 -1
- package/pages/c/_cluster/monitoring/monitor/_namespace/_id.vue +4 -2
- package/pages/c/_cluster/monitoring/monitor/create.vue +4 -2
- package/pages/c/_cluster/monitoring/route-receiver/_id.vue +4 -2
- package/pages/c/_cluster/monitoring/route-receiver/create.vue +5 -2
- package/pages/c/_cluster/neuvector/index.vue +1 -1
- package/pages/c/_cluster/settings/banners.vue +4 -3
- package/pages/c/_cluster/uiplugins/CatalogList/index.vue +8 -10
- package/pages/c/_cluster/uiplugins/__tests__/AddExtensionRepos.test.ts +4 -7
- package/pages/c/_cluster/uiplugins/index.vue +98 -55
- package/pages/diagnostic.vue +59 -11
- package/pages/fail-whale.vue +14 -8
- package/pages/home.vue +24 -18
- package/pages/prefs.vue +7 -6
- package/pages/support/index.vue +4 -1
- package/plugins/internal-api/index.ts +37 -0
- package/plugins/internal-api/shared/base-api.ts +13 -0
- package/plugins/internal-api/shell/shell.api.ts +108 -0
- package/plugins/steve/actions.js +0 -12
- package/public/index.html +1 -0
- package/rancher-components/Card/Card.vue +1 -1
- package/rancher-components/Form/Checkbox/Checkbox.test.ts +59 -1
- package/rancher-components/Form/Checkbox/Checkbox.vue +27 -3
- package/rancher-components/Form/LabeledInput/LabeledInput.test.ts +47 -0
- package/rancher-components/Form/LabeledInput/LabeledInput.vue +20 -2
- package/rancher-components/Form/Radio/RadioButton.test.ts +36 -1
- package/rancher-components/Form/Radio/RadioButton.vue +20 -4
- package/rancher-components/Form/Radio/RadioGroup.test.ts +60 -0
- package/rancher-components/Form/Radio/RadioGroup.vue +52 -10
- package/rancher-components/Form/ToggleSwitch/ToggleSwitch.test.ts +17 -0
- package/rancher-components/Form/ToggleSwitch/ToggleSwitch.vue +5 -0
- package/rancher-components/LabeledTooltip/LabeledTooltip.vue +10 -1
- package/rancher-components/RcButton/RcButton.vue +2 -1
- package/rancher-components/RcButton/types.ts +1 -0
- package/rancher-components/RcDropdown/RcDropdown.vue +18 -6
- package/rancher-components/RcDropdown/RcDropdownItem.vue +3 -56
- package/rancher-components/RcDropdown/RcDropdownItemCheckbox.vue +68 -0
- package/rancher-components/RcDropdown/RcDropdownItemSelect.vue +92 -0
- package/rancher-components/RcDropdown/RcDropdownTrigger.vue +10 -0
- package/rancher-components/RcDropdown/index.ts +2 -0
- package/rancher-components/RcDropdown/useDropdownCollection.ts +8 -0
- package/rancher-components/RcDropdown/useDropdownContext.ts +9 -3
- package/rancher-components/RcDropdown/useDropdownItem.ts +63 -0
- package/scripts/extension/bundle +20 -0
- package/scripts/extension/helm/charts/ui-plugin-server/templates/cr.yaml +2 -1
- package/scripts/extension/helm/charts/ui-plugin-server/values.yaml +2 -0
- package/scripts/extension/helmpatch +44 -31
- package/scripts/extension/publish +12 -12
- package/scripts/typegen.sh +2 -4
- package/server/har-file.js +25 -3
- package/store/action-menu.js +26 -56
- package/store/features.js +2 -1
- package/store/index.js +5 -0
- package/store/modal.ts +71 -0
- package/store/slideInPanel.ts +47 -0
- package/store/type-map.js +12 -1
- package/store/type-map.utils.ts +4 -4
- package/types/global-vue.d.ts +5 -0
- package/types/internal-api/shell/growl.d.ts +25 -0
- package/types/internal-api/shell/modal.d.ts +77 -0
- package/types/internal-api/shell/slideIn.d.ts +15 -0
- package/types/resources/fleet.d.ts +0 -14
- package/types/shell/index.d.ts +43 -24
- package/types/vue-shim.d.ts +4 -1
- package/utils/__mocks__/tabbable.js +13 -0
- package/utils/__tests__/object.test.ts +38 -4
- package/utils/cluster.js +35 -0
- package/utils/fleet.ts +15 -73
- package/utils/object.js +48 -5
- package/utils/validators/formRules/__tests__/index.test.ts +10 -1
- package/utils/validators/formRules/index.ts +27 -3
- package/utils/validators/machine-pool.ts +20 -0
- package/components/DisableAuthProviderModal.vue +0 -114
- package/components/MoveModal.vue +0 -166
- package/components/PromptChangePassword.vue +0 -123
- package/components/fleet/FleetBundleResources.vue +0 -86
- package/components/formatter/ExtensionCache.vue +0 -74
- package/components/formatter/Port.vue +0 -24
- package/components/formatter/SecretType.vue +0 -41
- package/types/vue-shim.d +0 -20
|
@@ -1,8 +1,7 @@
|
|
|
1
1
|
<script>
|
|
2
|
-
import { mapGetters } from 'vuex';
|
|
2
|
+
import { mapGetters, useStore } from 'vuex';
|
|
3
3
|
import { defineAsyncComponent, ref, onMounted, onBeforeUnmount } from 'vue';
|
|
4
4
|
import day from 'dayjs';
|
|
5
|
-
import semver from 'semver';
|
|
6
5
|
import isEmpty from 'lodash/isEmpty';
|
|
7
6
|
import { dasherize, ucFirst } from '@shell/utils/string';
|
|
8
7
|
import { get, clone } from '@shell/utils/object';
|
|
@@ -25,7 +24,8 @@ import { getParent } from '@shell/utils/dom';
|
|
|
25
24
|
import { FORMATTERS } from '@shell/components/SortableTable/sortable-config';
|
|
26
25
|
import ButtonMultiAction from '@shell/components/ButtonMultiAction.vue';
|
|
27
26
|
import ActionMenu from '@shell/components/ActionMenuShell.vue';
|
|
28
|
-
import {
|
|
27
|
+
import { useRuntimeFlag } from '@shell/composables/useRuntimeFlag';
|
|
28
|
+
import ActionDropdownShell from '@shell/components/ActionDropdownShell.vue';
|
|
29
29
|
|
|
30
30
|
// Uncomment for table performance debugging
|
|
31
31
|
// import tableDebug from './debug';
|
|
@@ -62,6 +62,7 @@ export default {
|
|
|
62
62
|
LabeledSelect,
|
|
63
63
|
ButtonMultiAction,
|
|
64
64
|
ActionMenu,
|
|
65
|
+
ActionDropdownShell,
|
|
65
66
|
},
|
|
66
67
|
mixins: [
|
|
67
68
|
filtering,
|
|
@@ -546,7 +547,13 @@ export default {
|
|
|
546
547
|
table.value.removeEventListener('keyup', handleEnterKey);
|
|
547
548
|
});
|
|
548
549
|
|
|
549
|
-
|
|
550
|
+
const store = useStore();
|
|
551
|
+
const { featureDropdownMenu } = useRuntimeFlag(store);
|
|
552
|
+
|
|
553
|
+
return {
|
|
554
|
+
table,
|
|
555
|
+
featureDropdownMenu,
|
|
556
|
+
};
|
|
550
557
|
},
|
|
551
558
|
|
|
552
559
|
created() {
|
|
@@ -768,12 +775,6 @@ export default {
|
|
|
768
775
|
|
|
769
776
|
return rows;
|
|
770
777
|
},
|
|
771
|
-
|
|
772
|
-
featureDropdownMenu() {
|
|
773
|
-
const { fullVersion } = getVersionInfo(this.$store);
|
|
774
|
-
|
|
775
|
-
return semver.gte(semver.coerce(fullVersion).version, '2.11.0');
|
|
776
|
-
}
|
|
777
778
|
},
|
|
778
779
|
|
|
779
780
|
methods: {
|
|
@@ -1104,47 +1105,59 @@ export default {
|
|
|
1104
1105
|
/>
|
|
1105
1106
|
<span v-clean-html="act.label" />
|
|
1106
1107
|
</button>
|
|
1107
|
-
<
|
|
1108
|
-
|
|
1109
|
-
|
|
1110
|
-
|
|
1111
|
-
|
|
1112
|
-
|
|
1113
|
-
|
|
1114
|
-
|
|
1115
|
-
|
|
1116
|
-
|
|
1117
|
-
|
|
1118
|
-
|
|
1119
|
-
|
|
1120
|
-
|
|
1121
|
-
|
|
1122
|
-
|
|
1123
|
-
|
|
1124
|
-
|
|
1125
|
-
|
|
1126
|
-
|
|
1127
|
-
|
|
1128
|
-
:
|
|
1129
|
-
v-close-popper
|
|
1130
|
-
v-clean-tooltip="{
|
|
1131
|
-
content: actionTooltip,
|
|
1132
|
-
placement: 'right'
|
|
1133
|
-
}"
|
|
1134
|
-
:class="{ disabled: !act.enabled }"
|
|
1135
|
-
@click="applyTableAction(act, null, $event)"
|
|
1136
|
-
@mouseover="setBulkActionOfInterest(act)"
|
|
1137
|
-
@mouseleave="setBulkActionOfInterest(null)"
|
|
1108
|
+
<template v-if="featureDropdownMenu">
|
|
1109
|
+
<ActionDropdownShell
|
|
1110
|
+
:disabled="!selectedRows.length"
|
|
1111
|
+
:hidden-actions="hiddenActions"
|
|
1112
|
+
:action-tooltip="actionTooltip"
|
|
1113
|
+
@click="applyTableAction"
|
|
1114
|
+
@mouseover="setBulkActionOfInterest"
|
|
1115
|
+
@mouseleave="setBulkActionOfInterest"
|
|
1116
|
+
/>
|
|
1117
|
+
</template>
|
|
1118
|
+
<template v-else>
|
|
1119
|
+
<ActionDropdown
|
|
1120
|
+
:class="bulkActionsDropdownClass"
|
|
1121
|
+
class="bulk-actions-dropdown"
|
|
1122
|
+
:disable-button="!selectedRows.length"
|
|
1123
|
+
size="sm"
|
|
1124
|
+
>
|
|
1125
|
+
<template #button-content>
|
|
1126
|
+
<button
|
|
1127
|
+
ref="actionDropDown"
|
|
1128
|
+
class="btn bg-primary mr-0"
|
|
1129
|
+
:disabled="!selectedRows.length"
|
|
1138
1130
|
>
|
|
1139
|
-
<i
|
|
1140
|
-
|
|
1141
|
-
|
|
1142
|
-
|
|
1143
|
-
|
|
1144
|
-
|
|
1145
|
-
|
|
1146
|
-
|
|
1147
|
-
|
|
1131
|
+
<i class="icon icon-gear" />
|
|
1132
|
+
<span>{{ t('sortableTable.bulkActions.collapsed.label') }}</span>
|
|
1133
|
+
<i class="ml-10 icon icon-chevron-down" />
|
|
1134
|
+
</button>
|
|
1135
|
+
</template>
|
|
1136
|
+
<template #popover-content>
|
|
1137
|
+
<ul class="list-unstyled menu">
|
|
1138
|
+
<li
|
|
1139
|
+
v-for="(act, i) in hiddenActions"
|
|
1140
|
+
:key="i"
|
|
1141
|
+
v-close-popper
|
|
1142
|
+
v-clean-tooltip="{
|
|
1143
|
+
content: actionTooltip,
|
|
1144
|
+
placement: 'right'
|
|
1145
|
+
}"
|
|
1146
|
+
:class="{ disabled: !act.enabled }"
|
|
1147
|
+
@click="applyTableAction(act, null, $event)"
|
|
1148
|
+
@mouseover="setBulkActionOfInterest(act)"
|
|
1149
|
+
@mouseleave="setBulkActionOfInterest(null)"
|
|
1150
|
+
>
|
|
1151
|
+
<i
|
|
1152
|
+
v-if="act.icon"
|
|
1153
|
+
:class="act.icon"
|
|
1154
|
+
/>
|
|
1155
|
+
<span v-clean-html="act.label" />
|
|
1156
|
+
</li>
|
|
1157
|
+
</ul>
|
|
1158
|
+
</template>
|
|
1159
|
+
</ActionDropdown>
|
|
1160
|
+
</template>
|
|
1148
1161
|
<label
|
|
1149
1162
|
v-if="selectedRowsText"
|
|
1150
1163
|
:class="bulkActionAvailabilityClass"
|
|
@@ -1457,9 +1470,9 @@ export default {
|
|
|
1457
1470
|
:value="col.value"
|
|
1458
1471
|
:row="row.row"
|
|
1459
1472
|
:col="col.col"
|
|
1473
|
+
:get-custom-detail-link="getCustomDetailLink"
|
|
1460
1474
|
v-bind="col.col.formatterOpts"
|
|
1461
1475
|
:row-key="row.key"
|
|
1462
|
-
:get-custom-detail-link="getCustomDetailLink"
|
|
1463
1476
|
/>
|
|
1464
1477
|
<component
|
|
1465
1478
|
:is="col.component"
|
|
@@ -49,6 +49,21 @@ export default {
|
|
|
49
49
|
return this.$store.getters['i18n/t'](this.pagingLabel, opt);
|
|
50
50
|
},
|
|
51
51
|
|
|
52
|
+
perPage() {
|
|
53
|
+
let out = this.rowsPerPage || 0;
|
|
54
|
+
|
|
55
|
+
if ( out <= 0 ) {
|
|
56
|
+
out = parseInt(this.$store.getters['prefs/get'](ROWS_PER_PAGE), 10) || 0;
|
|
57
|
+
}
|
|
58
|
+
|
|
59
|
+
// This should ideally never happen, but the preference value could be invalid, so return something...
|
|
60
|
+
if ( out <= 0 ) {
|
|
61
|
+
out = 10;
|
|
62
|
+
}
|
|
63
|
+
|
|
64
|
+
return out;
|
|
65
|
+
},
|
|
66
|
+
|
|
52
67
|
pagedRows() {
|
|
53
68
|
if (this.externalPaginationEnabled) {
|
|
54
69
|
return this.rows;
|
|
@@ -61,9 +76,7 @@ export default {
|
|
|
61
76
|
},
|
|
62
77
|
|
|
63
78
|
data() {
|
|
64
|
-
|
|
65
|
-
|
|
66
|
-
return { page: 1, perPage };
|
|
79
|
+
return { page: 1 };
|
|
67
80
|
},
|
|
68
81
|
|
|
69
82
|
watch: {
|
|
@@ -89,22 +102,6 @@ export default {
|
|
|
89
102
|
},
|
|
90
103
|
|
|
91
104
|
methods: {
|
|
92
|
-
getPerPage() {
|
|
93
|
-
// perPage can not change while the list is displayed
|
|
94
|
-
let out = this.rowsPerPage || 0;
|
|
95
|
-
|
|
96
|
-
if ( out <= 0 ) {
|
|
97
|
-
out = parseInt(this.$store.getters['prefs/get'](ROWS_PER_PAGE), 10) || 0;
|
|
98
|
-
}
|
|
99
|
-
|
|
100
|
-
// This should ideally never happen, but the preference value could be invalid, so return something...
|
|
101
|
-
if ( out <= 0 ) {
|
|
102
|
-
out = 10;
|
|
103
|
-
}
|
|
104
|
-
|
|
105
|
-
return out;
|
|
106
|
-
},
|
|
107
|
-
|
|
108
105
|
setPage(num) {
|
|
109
106
|
if (this.page === num) {
|
|
110
107
|
return;
|
|
@@ -340,17 +340,6 @@ export default {
|
|
|
340
340
|
if ( !isSelected ) {
|
|
341
341
|
this.update([node], this.selectedRows.slice());
|
|
342
342
|
}
|
|
343
|
-
|
|
344
|
-
let resources = this.selectedRows;
|
|
345
|
-
|
|
346
|
-
if ( this.mangleActionResources ) {
|
|
347
|
-
resources = await this.mangleActionResources(resources);
|
|
348
|
-
}
|
|
349
|
-
|
|
350
|
-
this.$store.commit(`action-menu/show`, {
|
|
351
|
-
resources,
|
|
352
|
-
event: e,
|
|
353
|
-
});
|
|
354
343
|
},
|
|
355
344
|
|
|
356
345
|
keySelectRow(row, more = false) {
|
package/components/Wizard.vue
CHANGED
|
@@ -426,7 +426,7 @@ export default {
|
|
|
426
426
|
</div>
|
|
427
427
|
<div
|
|
428
428
|
id="wizard-footer-controls"
|
|
429
|
-
class="controls-row
|
|
429
|
+
class="controls-row"
|
|
430
430
|
>
|
|
431
431
|
<slot
|
|
432
432
|
name="cancel"
|
|
@@ -674,7 +674,7 @@ $spacer: 10px;
|
|
|
674
674
|
// We have to account for the absolute position of the .controls-row
|
|
675
675
|
.footer-error {
|
|
676
676
|
margin-top: -40px;
|
|
677
|
-
margin-bottom:
|
|
677
|
+
margin-bottom: calc($footer-height + 10px);
|
|
678
678
|
}
|
|
679
679
|
|
|
680
680
|
.controls-row {
|
|
@@ -42,7 +42,7 @@ describe('component: AsyncButton', () => {
|
|
|
42
42
|
expect(span.text()).toBe('some-string');
|
|
43
43
|
});
|
|
44
44
|
|
|
45
|
-
it('click on async button should emit click with a proper state of waiting, disabled and spinning ::: CB true', () => {
|
|
45
|
+
it('click on async button should emit click with a proper state of waiting, appear disabled and spinning ::: CB true', () => {
|
|
46
46
|
jest.useFakeTimers();
|
|
47
47
|
|
|
48
48
|
const wrapper: VueWrapper<InstanceType<typeof AsyncButton>> = mount(AsyncButton, {
|
|
@@ -65,7 +65,7 @@ describe('component: AsyncButton', () => {
|
|
|
65
65
|
expect(wrapper.emitted('click')).toHaveLength(1);
|
|
66
66
|
expect(wrapper.vm.phase).toBe(ASYNC_BUTTON_STATES.WAITING);
|
|
67
67
|
expect(wrapper.vm.isSpinning).toBe(true);
|
|
68
|
-
expect(wrapper.vm.
|
|
68
|
+
expect(wrapper.vm.appearsDisabled).toBe(true);
|
|
69
69
|
// testing cb function has been emitted
|
|
70
70
|
expect(typeof wrapper.emitted('click')![0][0]).toBe('function');
|
|
71
71
|
|
|
@@ -0,0 +1,176 @@
|
|
|
1
|
+
import { mount } from '@vue/test-utils';
|
|
2
|
+
import { createStore, Store } from 'vuex';
|
|
3
|
+
import { nextTick } from 'vue';
|
|
4
|
+
|
|
5
|
+
import ModalManager from '@shell/components/ModalManager.vue';
|
|
6
|
+
|
|
7
|
+
interface ModalManagerMethods {
|
|
8
|
+
registerBackgroundClosing(fn: Function): void;
|
|
9
|
+
close(): void;
|
|
10
|
+
}
|
|
11
|
+
|
|
12
|
+
const MockComponent = {
|
|
13
|
+
template: '<div data-testid="modal-manager-component">Mock Content</div>',
|
|
14
|
+
props: ['someProp', 'resources', 'registerBackgroundClosing']
|
|
15
|
+
};
|
|
16
|
+
|
|
17
|
+
describe('modalManager.vue with Teleport', () => {
|
|
18
|
+
let store: Store<any>;
|
|
19
|
+
let getters: Record<string, () => any>;
|
|
20
|
+
let modalsDiv: HTMLDivElement;
|
|
21
|
+
|
|
22
|
+
beforeEach(() => {
|
|
23
|
+
// Create the teleport target container
|
|
24
|
+
modalsDiv = document.createElement('div');
|
|
25
|
+
modalsDiv.setAttribute('id', 'modals');
|
|
26
|
+
document.body.appendChild(modalsDiv);
|
|
27
|
+
|
|
28
|
+
getters = {
|
|
29
|
+
'modal/isOpen': () => true,
|
|
30
|
+
'modal/component': () => MockComponent,
|
|
31
|
+
'modal/componentProps': () => ({ someProp: 'testValue' }),
|
|
32
|
+
'modal/resources': () => ({ data: 'mockData' }),
|
|
33
|
+
'modal/closeOnClickOutside': () => true,
|
|
34
|
+
'modal/modalWidth': () => '500px'
|
|
35
|
+
};
|
|
36
|
+
|
|
37
|
+
store = createStore({
|
|
38
|
+
getters,
|
|
39
|
+
mutations: { 'modal/closeModal': jest.fn() }
|
|
40
|
+
});
|
|
41
|
+
});
|
|
42
|
+
|
|
43
|
+
afterEach(() => {
|
|
44
|
+
// Clean up the teleport container after each test
|
|
45
|
+
document.body.removeChild(modalsDiv);
|
|
46
|
+
});
|
|
47
|
+
|
|
48
|
+
const factory = () => {
|
|
49
|
+
return mount(ModalManager, {
|
|
50
|
+
attachTo: document.body, // attach so Teleport can work properly
|
|
51
|
+
global: {
|
|
52
|
+
plugins: [store],
|
|
53
|
+
stubs: {
|
|
54
|
+
AppModal: {
|
|
55
|
+
name: 'AppModal',
|
|
56
|
+
template: `<div data-testid="app-modal" @close="$emit('close')" :style="{ '--prompt-modal-width': width }"><slot /></div>`,
|
|
57
|
+
props: ['clickToClose', 'width']
|
|
58
|
+
}
|
|
59
|
+
}
|
|
60
|
+
}
|
|
61
|
+
});
|
|
62
|
+
};
|
|
63
|
+
|
|
64
|
+
it('renders the AppModal and dynamic component when modal is open', async() => {
|
|
65
|
+
factory();
|
|
66
|
+
|
|
67
|
+
await nextTick();
|
|
68
|
+
|
|
69
|
+
// Because Teleport moves content out of the normal wrapper,
|
|
70
|
+
// we query the document for the teleported elements.
|
|
71
|
+
const appModal = document.querySelector('[data-testid="app-modal"]');
|
|
72
|
+
const dynamicComponent = document.querySelector('[data-testid="modal-manager-component"]');
|
|
73
|
+
|
|
74
|
+
expect(appModal).toBeTruthy();
|
|
75
|
+
expect(dynamicComponent).toBeTruthy();
|
|
76
|
+
expect(appModal?.getAttribute('style')).toContain('--prompt-modal-width: 500px');
|
|
77
|
+
|
|
78
|
+
// We assume the mock component is rendered correctly if its markup is found.
|
|
79
|
+
});
|
|
80
|
+
|
|
81
|
+
it('does not render the AppModal when modal is closed', async() => {
|
|
82
|
+
getters['modal/isOpen'] = () => false;
|
|
83
|
+
store = createStore({
|
|
84
|
+
getters,
|
|
85
|
+
mutations: { 'modal/closeModal': jest.fn() }
|
|
86
|
+
});
|
|
87
|
+
factory();
|
|
88
|
+
await nextTick();
|
|
89
|
+
|
|
90
|
+
const appModal = document.querySelector('[data-testid="app-modal"]');
|
|
91
|
+
|
|
92
|
+
expect(appModal).toBeNull();
|
|
93
|
+
});
|
|
94
|
+
|
|
95
|
+
it('does not render the AppModal when dynamic component is null', async() => {
|
|
96
|
+
getters['modal/component'] = () => null;
|
|
97
|
+
store = createStore({
|
|
98
|
+
getters,
|
|
99
|
+
mutations: { 'modal/closeModal': jest.fn() }
|
|
100
|
+
});
|
|
101
|
+
factory();
|
|
102
|
+
await nextTick();
|
|
103
|
+
|
|
104
|
+
const appModal = document.querySelector('[data-testid="app-modal"]');
|
|
105
|
+
|
|
106
|
+
expect(appModal).toBeNull();
|
|
107
|
+
});
|
|
108
|
+
|
|
109
|
+
it('calls store commit when close is triggered', async() => {
|
|
110
|
+
const closeModalMutation = jest.fn();
|
|
111
|
+
|
|
112
|
+
getters['modal/isOpen'] = () => true;
|
|
113
|
+
store = createStore({
|
|
114
|
+
getters,
|
|
115
|
+
mutations: { 'modal/closeModal': closeModalMutation }
|
|
116
|
+
});
|
|
117
|
+
const wrapper = factory();
|
|
118
|
+
|
|
119
|
+
await nextTick();
|
|
120
|
+
|
|
121
|
+
const appModalWrapper = wrapper.findComponent({ name: 'AppModal' });
|
|
122
|
+
|
|
123
|
+
appModalWrapper.vm.$emit('close');
|
|
124
|
+
await nextTick();
|
|
125
|
+
|
|
126
|
+
expect(closeModalMutation).toHaveBeenCalledWith({}, undefined);
|
|
127
|
+
});
|
|
128
|
+
|
|
129
|
+
it('calls registered background closing function on close', async() => {
|
|
130
|
+
const closeModalMutation = jest.fn();
|
|
131
|
+
|
|
132
|
+
getters['modal/isOpen'] = () => true;
|
|
133
|
+
store = createStore({
|
|
134
|
+
getters,
|
|
135
|
+
mutations: { 'modal/closeModal': closeModalMutation }
|
|
136
|
+
});
|
|
137
|
+
const wrapper = factory();
|
|
138
|
+
|
|
139
|
+
await nextTick();
|
|
140
|
+
|
|
141
|
+
const backgroundFn = jest.fn();
|
|
142
|
+
|
|
143
|
+
(wrapper.vm as unknown as ModalManagerMethods).registerBackgroundClosing(backgroundFn);
|
|
144
|
+
await nextTick();
|
|
145
|
+
|
|
146
|
+
const appModalWrapper = wrapper.findComponent({ name: 'AppModal' });
|
|
147
|
+
|
|
148
|
+
appModalWrapper.vm.$emit('close');
|
|
149
|
+
await nextTick();
|
|
150
|
+
|
|
151
|
+
expect(backgroundFn).toHaveBeenCalledWith();
|
|
152
|
+
expect(closeModalMutation).toHaveBeenCalledWith({}, undefined);
|
|
153
|
+
});
|
|
154
|
+
|
|
155
|
+
it('does nothing if modal is already closed when close is triggered', async() => {
|
|
156
|
+
const closeModalMutation = jest.fn();
|
|
157
|
+
|
|
158
|
+
getters['modal/isOpen'] = () => false;
|
|
159
|
+
store = createStore({
|
|
160
|
+
getters,
|
|
161
|
+
mutations: { 'modal/closeModal': closeModalMutation }
|
|
162
|
+
});
|
|
163
|
+
const wrapper = factory();
|
|
164
|
+
|
|
165
|
+
await nextTick();
|
|
166
|
+
|
|
167
|
+
const modalManager = wrapper.vm as unknown as ModalManagerMethods;
|
|
168
|
+
const spy = jest.spyOn(modalManager, 'close');
|
|
169
|
+
|
|
170
|
+
modalManager.close();
|
|
171
|
+
await nextTick();
|
|
172
|
+
|
|
173
|
+
expect(spy).toHaveBeenCalledWith();
|
|
174
|
+
expect(closeModalMutation).not.toHaveBeenCalled();
|
|
175
|
+
});
|
|
176
|
+
});
|
|
@@ -0,0 +1,148 @@
|
|
|
1
|
+
import { mount } from '@vue/test-utils';
|
|
2
|
+
import PromptModal from '@shell/components/PromptModal.vue';
|
|
3
|
+
|
|
4
|
+
import GenericPrompt from '@shell/dialog/GenericPrompt.vue';
|
|
5
|
+
import AddClusterMemberDialog from '@shell/dialog/AddClusterMemberDialog.vue';
|
|
6
|
+
import AddCustomBadgeDialog from '@shell/dialog/AddCustomBadgeDialog.vue';
|
|
7
|
+
import AddonConfigConfirmationDialog from '@shell/dialog/AddonConfigConfirmationDialog.vue';
|
|
8
|
+
import AddProjectMemberDialog from '@shell/dialog/AddProjectMemberDialog.vue';
|
|
9
|
+
import DeactivateDriverDialog from '@shell/dialog/DeactivateDriverDialog.vue';
|
|
10
|
+
import DiagnosticTimingsDialog from '@shell/dialog/DiagnosticTimingsDialog.vue';
|
|
11
|
+
import DrainNode from '@shell/dialog/DrainNode.vue';
|
|
12
|
+
import ForceMachineRemoveDialog from '@shell/dialog/ForceMachineRemoveDialog.vue';
|
|
13
|
+
import GitRepoForceUpdateDialog from '@shell/dialog/GitRepoForceUpdateDialog.vue';
|
|
14
|
+
import RollbackWorkloadDialog from '@shell/dialog/RollbackWorkloadDialog.vue';
|
|
15
|
+
import RotateCertificatesDialog from '@shell/dialog/RotateCertificatesDialog.vue';
|
|
16
|
+
import RotateEncryptionKeyDialog from '@shell/dialog/RotateEncryptionKeyDialog.vue';
|
|
17
|
+
import SaveAsRKETemplateDialog from '@shell/dialog/SaveAsRKETemplateDialog.vue';
|
|
18
|
+
import ScaleMachineDownDialog from '@shell/dialog/ScaleMachineDownDialog.vue';
|
|
19
|
+
import ScalePoolDownDialog from '@shell/dialog/ScalePoolDownDialog.vue';
|
|
20
|
+
import SloDialog from '@shell/dialog/SloDialog.vue';
|
|
21
|
+
|
|
22
|
+
import DisableAuthProviderDialog from '@shell/dialog/DisableAuthProviderDialog.vue';
|
|
23
|
+
import WechatDialog from '@shell/dialog/WechatDialog.vue';
|
|
24
|
+
import DeveloperLoadExtensionDialog from '@shell/dialog/DeveloperLoadExtensionDialog.vue';
|
|
25
|
+
import AddExtensionReposDialog from '@shell/dialog/AddExtensionReposDialog.vue';
|
|
26
|
+
import InstallExtensionDialog from '@shell/dialog/InstallExtensionDialog.vue';
|
|
27
|
+
import UninstallExtensionDialog from '@shell/dialog/UninstallExtensionDialog.vue';
|
|
28
|
+
import KnownHostsEditDialog from '@shell/dialog/KnownHostsEditDialog.vue';
|
|
29
|
+
import ImportDialog from '@shell/dialog/ImportDialog.vue';
|
|
30
|
+
import SearchDialog from '@shell/dialog/SearchDialog.vue';
|
|
31
|
+
import ChangePasswordDialog from '@shell/dialog/ChangePasswordDialog.vue';
|
|
32
|
+
import AssignToDialog from '@shell/dialog/AssignToDialog.vue';
|
|
33
|
+
import FeatureFlagListDialog from '@shell/dialog/FeatureFlagListDialog.vue';
|
|
34
|
+
import MoveNamespaceDialog from '@shell/dialog/MoveNamespaceDialog.vue';
|
|
35
|
+
import ExtensionCatalogInstallDialog from '@shell/dialog/ExtensionCatalogInstallDialog.vue';
|
|
36
|
+
import ExtensionCatalogUninstallDialog from '@shell/dialog/ExtensionCatalogUninstallDialog.vue';
|
|
37
|
+
|
|
38
|
+
import { createStore } from 'vuex';
|
|
39
|
+
|
|
40
|
+
jest.mock('@shell/utils/clipboard', () => {
|
|
41
|
+
return { copyTextToClipboard: jest.fn(() => Promise.resolve({})) };
|
|
42
|
+
});
|
|
43
|
+
|
|
44
|
+
function generateStore(component: any):any {
|
|
45
|
+
return createStore({
|
|
46
|
+
modules: { // promptModal
|
|
47
|
+
'action-menu': {
|
|
48
|
+
namespaced: true,
|
|
49
|
+
state: {
|
|
50
|
+
modalData: {
|
|
51
|
+
closeOnClickOutside: true,
|
|
52
|
+
resources: [{ cluster: { isRke2: true, machines: [] } }], // ScaleMachineDownDialog
|
|
53
|
+
componentProps: {
|
|
54
|
+
drivers: [], // DeactivateDriverDialog
|
|
55
|
+
driverType: 'kontainerDrivers', // DeactivateDriverDialog
|
|
56
|
+
downloadData: () => jest.fn(), // DiagnosticTimingsDialog
|
|
57
|
+
gatherResponseTimes: () => jest.fn(), // DiagnosticTimingsDialog
|
|
58
|
+
kubeNodes: [{}], // DrainNode
|
|
59
|
+
repositories: [], // GitRepoForceUpdateDialog
|
|
60
|
+
workload: { metadata: {}, kind: '' }, // RollbackWorkloadDialog
|
|
61
|
+
catalog: {}
|
|
62
|
+
},
|
|
63
|
+
},
|
|
64
|
+
|
|
65
|
+
},
|
|
66
|
+
},
|
|
67
|
+
},
|
|
68
|
+
getters: {
|
|
69
|
+
'type-map/importDialog': () => () => component, // promptModal
|
|
70
|
+
'i18n/exists': () => jest.fn(), // promptModal
|
|
71
|
+
'i18n/t': () => jest.fn(), // general usage
|
|
72
|
+
'rancher/schemaFor': () => jest.fn(), // general usage
|
|
73
|
+
'prefs/get': () => jest.fn(), // ScalePoolDownDialog
|
|
74
|
+
'type-map/allTypes': () => jest.fn(), // SearchDialog
|
|
75
|
+
'type-map/labelFor': () => jest.fn(), // ScaleMachineDownDialog
|
|
76
|
+
'type-map/getTree': () => jest.fn().mockReturnValue([]), // SearchDialog
|
|
77
|
+
'cluster/all': () => jest.fn(), // SearchDialog
|
|
78
|
+
currentProduct: () => { // SearchDialog
|
|
79
|
+
return { inStore: 'cluster' };
|
|
80
|
+
},
|
|
81
|
+
currentCluster: () => { // general usage
|
|
82
|
+
'local';
|
|
83
|
+
},
|
|
84
|
+
}
|
|
85
|
+
});
|
|
86
|
+
}
|
|
87
|
+
|
|
88
|
+
describe('component: PromptModal', () => {
|
|
89
|
+
it.each([
|
|
90
|
+
// current prompt modals at time of coding
|
|
91
|
+
['GenericPrompt', GenericPrompt],
|
|
92
|
+
['AddClusterMemberDialog', AddClusterMemberDialog],
|
|
93
|
+
['AddonConfigConfirmationDialog', AddonConfigConfirmationDialog],
|
|
94
|
+
['AddProjectMemberDialog', AddProjectMemberDialog],
|
|
95
|
+
['DeactivateDriverDialog', DeactivateDriverDialog],
|
|
96
|
+
['DiagnosticTimingsDialog', DiagnosticTimingsDialog],
|
|
97
|
+
['DrainNode', DrainNode],
|
|
98
|
+
['ForceMachineRemoveDialog', ForceMachineRemoveDialog],
|
|
99
|
+
['GitRepoForceUpdateDialog', GitRepoForceUpdateDialog],
|
|
100
|
+
['RollbackWorkloadDialog', RollbackWorkloadDialog],
|
|
101
|
+
['RotateCertificatesDialog', RotateCertificatesDialog],
|
|
102
|
+
['RotateEncryptionKeyDialog', RotateEncryptionKeyDialog],
|
|
103
|
+
['SaveAsRKETemplateDialog', SaveAsRKETemplateDialog],
|
|
104
|
+
['SloDialog', SloDialog],
|
|
105
|
+
['AddCustomBadgeDialog', AddCustomBadgeDialog],
|
|
106
|
+
['ScaleMachineDownDialog', ScaleMachineDownDialog],
|
|
107
|
+
['ScalePoolDownDialog', ScalePoolDownDialog],
|
|
108
|
+
// new modals created/moved
|
|
109
|
+
['DisableAuthProviderDialog', DisableAuthProviderDialog],
|
|
110
|
+
['WechatDialog', WechatDialog],
|
|
111
|
+
['DeveloperLoadExtensionDialog', DeveloperLoadExtensionDialog],
|
|
112
|
+
['AddExtensionReposDialog', AddExtensionReposDialog],
|
|
113
|
+
['InstallExtensionDialog', InstallExtensionDialog],
|
|
114
|
+
['UninstallExtensionDialog', UninstallExtensionDialog],
|
|
115
|
+
['KnownHostsEditDialog', KnownHostsEditDialog],
|
|
116
|
+
['ImportDialog', ImportDialog],
|
|
117
|
+
['SearchDialog', SearchDialog],
|
|
118
|
+
['ChangePasswordDialog', ChangePasswordDialog],
|
|
119
|
+
['AssignToDialog', AssignToDialog],
|
|
120
|
+
['FeatureFlagListDialog', FeatureFlagListDialog],
|
|
121
|
+
['MoveNamespaceDialog', MoveNamespaceDialog],
|
|
122
|
+
['ExtensionCatalogInstallDialog', ExtensionCatalogInstallDialog],
|
|
123
|
+
['ExtensionCatalogUninstallDialog', ExtensionCatalogUninstallDialog],
|
|
124
|
+
])('prompt Modal should render modal %p', (modalName, component) => {
|
|
125
|
+
// mock structuredClone
|
|
126
|
+
window.structuredClone = (arg) => JSON.parse(JSON.stringify(arg));
|
|
127
|
+
|
|
128
|
+
document.body.innerHTML = '<div id="modals"></div>';
|
|
129
|
+
const wrapper = mount(PromptModal,
|
|
130
|
+
{
|
|
131
|
+
attachTo: document.body,
|
|
132
|
+
data() {
|
|
133
|
+
return { opened: true }; // this controls modal content visibility
|
|
134
|
+
},
|
|
135
|
+
global: {
|
|
136
|
+
mocks: {
|
|
137
|
+
$store: generateStore(component),
|
|
138
|
+
$fetchState: {}
|
|
139
|
+
},
|
|
140
|
+
stubs: { transition: false }
|
|
141
|
+
}
|
|
142
|
+
}
|
|
143
|
+
);
|
|
144
|
+
|
|
145
|
+
expect(wrapper.vm.opened).toBe(true);
|
|
146
|
+
expect(wrapper.findComponent(component as any).exists()).toBe(true);
|
|
147
|
+
});
|
|
148
|
+
});
|