@rancher/shell 0.3.28 → 0.3.29

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (33) hide show
  1. package/.DS_Store +0 -0
  2. package/assets/translations/en-us.yaml +15 -1
  3. package/chart/monitoring/grafana/index.vue +2 -2
  4. package/components/AsyncButton.vue +9 -0
  5. package/components/SortableTable/THead.vue +7 -9
  6. package/components/SortableTable/index.vue +1 -2
  7. package/components/fleet/FleetStatus.vue +3 -3
  8. package/components/fleet/FleetSummary.vue +32 -27
  9. package/detail/provisioning.cattle.io.cluster.vue +2 -1
  10. package/edit/workload/index.vue +2 -1
  11. package/machine-config/__tests__/vmwarevsphere.test.ts +72 -0
  12. package/machine-config/vmwarevsphere.vue +68 -13
  13. package/package.json +2 -1
  14. package/rancher-components/BadgeState/BadgeState.vue +5 -1
  15. package/rancher-components/Banner/Banner.test.ts +51 -1
  16. package/rancher-components/Banner/Banner.vue +134 -53
  17. package/rancher-components/Card/Card.test.ts +37 -0
  18. package/rancher-components/Card/Card.vue +24 -7
  19. package/rancher-components/Form/Checkbox/Checkbox.test.ts +20 -29
  20. package/rancher-components/Form/Checkbox/Checkbox.vue +45 -20
  21. package/rancher-components/Form/LabeledInput/LabeledInput.test.ts +2 -8
  22. package/rancher-components/Form/LabeledInput/LabeledInput.vue +22 -10
  23. package/rancher-components/Form/Radio/RadioButton.test.ts +31 -0
  24. package/rancher-components/Form/Radio/RadioButton.vue +30 -13
  25. package/rancher-components/Form/Radio/RadioGroup.vue +26 -7
  26. package/rancher-components/Form/TextArea/TextAreaAutoGrow.vue +7 -6
  27. package/rancher-components/Form/ToggleSwitch/ToggleSwitch.test.ts +25 -38
  28. package/rancher-components/Form/ToggleSwitch/ToggleSwitch.vue +23 -11
  29. package/rancher-components/LabeledTooltip/LabeledTooltip.vue +19 -5
  30. package/rancher-components/StringList/StringList.test.ts +453 -49
  31. package/rancher-components/StringList/StringList.vue +92 -58
  32. package/types/shell/index.d.ts +9 -9
  33. package/yarn-error.log +200 -0
package/.DS_Store ADDED
Binary file
@@ -691,6 +691,15 @@ asyncButton:
691
691
  successIcon: checkmark
692
692
  waiting: ''
693
693
  waitingIcon: refresh
694
+ manual-refresh:
695
+ action: ''
696
+ actionIcon: refresh
697
+ error: ''
698
+ errorIcon: error
699
+ success: ''
700
+ successIcon: checkmark
701
+ waiting: ''
702
+ waitingIcon: refresh
694
703
  remove:
695
704
  action: Remove
696
705
  success: Removed
@@ -1525,6 +1534,9 @@ cluster:
1525
1534
  host:
1526
1535
  label: Host
1527
1536
  note: Specific host to create VM on (leave blank for standalone ESXi or for cluster with DRS)
1537
+ gracefulShutdownTimeout:
1538
+ label: Graceful Shutdown Timeout
1539
+ note: The time in seconds to wait before forcing deleting VMs in the infrastructure. Zero means disable graceful shutdown.
1528
1540
  instanceOptions:
1529
1541
  label: Instance Options
1530
1542
  description: Choose the size and OS of the virtual machine
@@ -5858,7 +5870,9 @@ workload:
5858
5870
  exec: Command run inside the container exits with status 0
5859
5871
  image: Container Image
5860
5872
  imagePullPolicy: Pull Policy
5861
- imagePullSecrets: Pull Secrets
5873
+ imagePullSecrets:
5874
+ label: Pull Secrets
5875
+ tooltip: Must be of Type `kubernetes.io/dockercfg` or `kubernetes.io/dockerconfigjson`
5862
5876
  init: Init Container
5863
5877
  lifecycleHook:
5864
5878
  postStart:
@@ -136,7 +136,7 @@ export default {
136
136
  newValsOut = {
137
137
  accessModes: null,
138
138
  storageClassName: null,
139
- size: null,
139
+ size: '10Gi',
140
140
  subPath: null,
141
141
  type: 'pvc',
142
142
  annotations: null,
@@ -148,7 +148,7 @@ export default {
148
148
  newValsOut = {
149
149
  accessModes: null,
150
150
  storageClassName: null,
151
- size: null,
151
+ size: '10Gi',
152
152
  subPath: null,
153
153
  type: 'statefulset',
154
154
  enabled: true,
@@ -273,6 +273,7 @@ export default Vue.extend<{ phase: string}, any, any, any>({
273
273
  :data-testid="componentTestid + '-async-button'"
274
274
  @click="clicked"
275
275
  >
276
+ <span v-if="mode === 'manual-refresh'">{{ t('action.refresh') }}</span>
276
277
  <i
277
278
  v-if="displayIcon"
278
279
  v-clean-tooltip="tooltip"
@@ -285,3 +286,11 @@ export default Vue.extend<{ phase: string}, any, any, any>({
285
286
  />
286
287
  </button>
287
288
  </template>
289
+
290
+ <style lang="scss" scoped>
291
+ // refresh mode has icon + text. We need to fix the positioning of the icon and sizing
292
+ .manual-refresh i {
293
+ margin: 0 0 0 8px !important;
294
+ font-size: 1rem !important;
295
+ }
296
+ </style>
@@ -162,15 +162,13 @@ export default {
162
162
  const menu = document.querySelector('.table-options-container');
163
163
  const elem = document.querySelector('.table-options-btn');
164
164
 
165
- if (!this.tableColsMenuPosition) {
166
- this.tableColsMenuPosition = fitOnScreen(menu, ev || elem, {
167
- overlapX: true,
168
- fudgeX: 26,
169
- fudgeY: -22,
170
- positionX: CENTER,
171
- positionY: AUTO,
172
- });
173
- }
165
+ this.tableColsMenuPosition = fitOnScreen(menu, ev || elem, {
166
+ overlapX: true,
167
+ fudgeX: 326,
168
+ fudgeY: -22,
169
+ positionX: CENTER,
170
+ positionY: AUTO,
171
+ });
174
172
 
175
173
  // toggle visibility
176
174
  this.tableColsOptionsVisibility = !this.tableColsOptionsVisibility;
@@ -1026,9 +1026,8 @@ export default {
1026
1026
  <slot name="header-right" />
1027
1027
  <AsyncButton
1028
1028
  v-if="isTooManyItemsToAutoUpdate"
1029
- v-clean-tooltip="t('performance.manualRefresh.buttonTooltip')"
1030
1029
  class="manual-refresh"
1031
- mode="refresh"
1030
+ mode="manual-refresh"
1032
1031
  :current-phase="currentPhase"
1033
1032
  @click="debouncedRefreshTableData"
1034
1033
  />
@@ -1,7 +1,7 @@
1
1
  <script>
2
2
  import { sortBy } from '@shell/utils/sort';
3
3
  import { get } from '@shell/utils/object';
4
- import { stateSort } from '@shell/plugins/dashboard-store/resource-class';
4
+ import { stateSort, STATES_ENUM } from '@shell/plugins/dashboard-store/resource-class';
5
5
 
6
6
  export default {
7
7
 
@@ -50,8 +50,8 @@ export default {
50
50
  computed: {
51
51
  meta() {
52
52
  return {
53
- total: this.values.map((x) => x.value).reduce((a, b) => a + b),
54
- readyCount: this.values.filter((x) => x.label === 'Success' || x.label === 'Ready').map((x) => x.value).reduce((a, b) => a + b)
53
+ total: this.values.map((x) => x.value).reduce((a, b) => a + b, 0),
54
+ readyCount: this.values.filter((x) => x.status === STATES_ENUM.SUCCESS || x.status === STATES_ENUM.READY).map((x) => x.value).reduce((a, b) => a + b, 0)
55
55
  };
56
56
  },
57
57
 
@@ -6,47 +6,52 @@ import FleetStatus from '@shell/components/fleet/FleetStatus';
6
6
  const getResourceDefaultState = (labelGetter, stateKey) => {
7
7
  return {
8
8
  ready: {
9
- count: 0,
10
- color: STATES[STATES_ENUM.READY].color,
11
- label: labelGetter(`${ stateKey }.${ STATES_ENUM.READY }`, null, STATES[STATES_ENUM.READY].label )
9
+ count: 0,
10
+ color: STATES[STATES_ENUM.READY].color,
11
+ label: labelGetter(`${ stateKey }.${ STATES_ENUM.READY }`, null, STATES[STATES_ENUM.READY].label ),
12
+ status: STATES_ENUM.READY
12
13
  },
13
14
  info: {
14
- count: 0,
15
- color: STATES[STATES_ENUM.INFO].color,
16
- label: labelGetter(`${ stateKey }.${ STATES_ENUM.INFO }`, null, STATES[STATES_ENUM.INFO].label )
15
+ count: 0,
16
+ color: STATES[STATES_ENUM.INFO].color,
17
+ label: labelGetter(`${ stateKey }.${ STATES_ENUM.INFO }`, null, STATES[STATES_ENUM.INFO].label ),
18
+ status: STATES_ENUM.INFO
17
19
  },
18
20
  warning: {
19
- count: 0,
20
- color: STATES[STATES_ENUM.WARNING].color,
21
- label: labelGetter(`${ stateKey }.${ STATES_ENUM.WARNING }`, null, STATES[STATES_ENUM.WARNING].label )
21
+ count: 0,
22
+ color: STATES[STATES_ENUM.WARNING].color,
23
+ label: labelGetter(`${ stateKey }.${ STATES_ENUM.WARNING }`, null, STATES[STATES_ENUM.WARNING].label ),
24
+ status: STATES_ENUM.WARNING
22
25
  },
23
26
  notready: {
24
- count: 0,
25
- color: STATES[STATES_ENUM.NOT_READY].color,
26
- label: labelGetter(`${ stateKey }.${ STATES_ENUM.NOT_READY }`, null, STATES[STATES_ENUM.NOT_READY].label )
27
+ count: 0,
28
+ color: STATES[STATES_ENUM.NOT_READY].color,
29
+ label: labelGetter(`${ stateKey }.${ STATES_ENUM.NOT_READY }`, null, STATES[STATES_ENUM.NOT_READY].label ),
30
+ status: STATES_ENUM.NOT_READY
27
31
  },
28
32
  error: {
29
- count: 0,
30
- color: STATES[STATES_ENUM.ERROR].color,
31
- label: labelGetter(`${ stateKey }.${ STATES_ENUM.ERROR }`, null, STATES[STATES_ENUM.ERROR].label )
32
-
33
+ count: 0,
34
+ color: STATES[STATES_ENUM.ERROR].color,
35
+ label: labelGetter(`${ stateKey }.${ STATES_ENUM.ERROR }`, null, STATES[STATES_ENUM.ERROR].label ),
36
+ status: STATES_ENUM.ERROR
33
37
  },
34
38
  errapplied: {
35
- count: 0,
36
- color: STATES[STATES_ENUM.ERR_APPLIED].color,
37
- label: labelGetter(`${ stateKey }.${ STATES_ENUM.ERR_APPLIED }`, null, STATES[STATES_ENUM.ERR_APPLIED].label )
38
-
39
+ count: 0,
40
+ color: STATES[STATES_ENUM.ERR_APPLIED].color,
41
+ label: labelGetter(`${ stateKey }.${ STATES_ENUM.ERR_APPLIED }`, null, STATES[STATES_ENUM.ERR_APPLIED].label ),
42
+ status: STATES_ENUM.ERR_APPLIED,
39
43
  },
40
44
  waitapplied: {
41
- count: 0,
42
- color: STATES[STATES_ENUM.WAIT_APPLIED].color,
43
- label: labelGetter(`${ stateKey }.${ STATES_ENUM.WAIT_APPLIED }`, null, STATES[STATES_ENUM.WAIT_APPLIED].label )
44
-
45
+ count: 0,
46
+ color: STATES[STATES_ENUM.WAIT_APPLIED].color,
47
+ label: labelGetter(`${ stateKey }.${ STATES_ENUM.WAIT_APPLIED }`, null, STATES[STATES_ENUM.WAIT_APPLIED].label ),
48
+ status: STATES_ENUM.WAIT_APPLIED
45
49
  },
46
50
  unknown: {
47
- count: 0,
48
- color: STATES[STATES_ENUM.UNKNOWN].color,
49
- label: labelGetter(`${ stateKey }.${ STATES_ENUM.UNKNOWN }`, null, STATES[STATES_ENUM.UNKNOWN].label )
51
+ count: 0,
52
+ color: STATES[STATES_ENUM.UNKNOWN].color,
53
+ label: labelGetter(`${ stateKey }.${ STATES_ENUM.UNKNOWN }`, null, STATES[STATES_ENUM.UNKNOWN].label ),
54
+ status: STATES_ENUM.UNKNOWN
50
55
  }
51
56
  };
52
57
  };
@@ -782,10 +782,11 @@ export default {
782
782
  </div>
783
783
  </div>
784
784
  <div
785
- v-if="group.ref && poolSummaryInfo[group.ref]"
785
+ v-if="group.ref"
786
786
  class="right group-header-buttons mr-20"
787
787
  >
788
788
  <MachineSummaryGraph
789
+ v-if="poolSummaryInfo[group.ref]"
789
790
  :row="poolSummaryInfo[group.ref]"
790
791
  :horizontal="true"
791
792
  class="mr-20"
@@ -235,7 +235,7 @@ export default {
235
235
  <div class="col span-6">
236
236
  <LabeledSelect
237
237
  v-model="imagePullSecrets"
238
- :label="t('workload.container.imagePullSecrets')"
238
+ :label="t('workload.container.imagePullSecrets.label')"
239
239
  :multiple="true"
240
240
  :taggable="true"
241
241
  :options="imagePullNamespacedSecrets"
@@ -243,6 +243,7 @@ export default {
243
243
  option-label="metadata.name"
244
244
  :reduce="service=>service.metadata.name"
245
245
  :create-option="createOption"
246
+ :tooltip="t('workload.container.imagePullSecrets.tooltip')"
246
247
  />
247
248
  </div>
248
249
  </div>
@@ -0,0 +1,72 @@
1
+ import { mount } from '@vue/test-utils';
2
+ import vmwarevsphere, { DEFAULT_VALUES } from '@shell/machine-config/vmwarevsphere.vue';
3
+
4
+ describe('component: vmwarevsphere', () => {
5
+ it('should mount successfully with correct default values', () => {
6
+ const defaultGetters = { 'i18n/t': jest.fn() };
7
+ const wrapper = mount(vmwarevsphere, {
8
+ propsData: {
9
+ poolId: 'poolId',
10
+ credentialId: 'credentialId',
11
+ disabled: false,
12
+ mode: 'create',
13
+ value: {
14
+ initted: false,
15
+ network: [],
16
+ tag: []
17
+ },
18
+ provider: 'vmwarevsphere'
19
+ },
20
+ mocks: {
21
+ $fetchState: { pending: false },
22
+ $store: { getters: defaultGetters },
23
+ },
24
+ stubs: { CodeMirror: true }
25
+ });
26
+
27
+ const dataCenterElement = wrapper.find(`[data-testid="datacenter"]`).element;
28
+ const resourcePoolElement = wrapper.find(`[data-testid="resourcePool"]`).element;
29
+ const dataStoreElement = wrapper.find(`[data-testid="dataStore"]`).element;
30
+ const folderElement = wrapper.find(`[data-testid="folder"]`).element;
31
+ const hostElement = wrapper.find(`[data-testid="host"]`).element;
32
+ const gracefulShutdownTimeoutElement = wrapper.find(`[data-testid="gracefulShutdownTimeout"]`).element;
33
+
34
+ expect(dataCenterElement).toBeDefined();
35
+ expect(resourcePoolElement).toBeDefined();
36
+ expect(dataStoreElement).toBeDefined();
37
+ expect(folderElement).toBeDefined();
38
+ expect(hostElement).toBeDefined();
39
+ expect(gracefulShutdownTimeoutElement).toBeDefined();
40
+
41
+ const {
42
+ cpuCount: defaultCpuCount,
43
+ diskSize: defaultDiskSize,
44
+ memorySize: defaultMemorySize,
45
+ hostsystem: defaultHostsystem,
46
+ cloudConfig: defaultCloudConfig,
47
+ gracefulShutdownTimeout: defaultGracefulShutdownTimeout,
48
+ cfgparam: defaultCfgparam,
49
+ os: defaultOs
50
+ } = DEFAULT_VALUES;
51
+
52
+ const {
53
+ cpuCount,
54
+ diskSize,
55
+ memorySize,
56
+ hostsystem,
57
+ cloudConfig,
58
+ gracefulShutdownTimeout,
59
+ cfgparam,
60
+ os
61
+ } = wrapper.vm.$options.propsData.value;
62
+
63
+ expect(cpuCount).toStrictEqual(defaultCpuCount);
64
+ expect(diskSize).toStrictEqual(defaultDiskSize);
65
+ expect(memorySize).toStrictEqual(defaultMemorySize);
66
+ expect(hostsystem).toStrictEqual(defaultHostsystem);
67
+ expect(cloudConfig).toStrictEqual(defaultCloudConfig);
68
+ expect(gracefulShutdownTimeout).toStrictEqual(defaultGracefulShutdownTimeout);
69
+ expect(cfgparam).toStrictEqual(defaultCfgparam);
70
+ expect(os).toStrictEqual(defaultOs);
71
+ });
72
+ });
@@ -39,7 +39,17 @@ const OS_OPTIONS = [
39
39
  'linux',
40
40
  'windows'
41
41
  ];
42
- const DEFAULT_CFGPARAM = ['disk.enableUUID=TRUE'];
42
+
43
+ export const DEFAULT_VALUES = {
44
+ cpuCount: '2',
45
+ diskSize: '20000',
46
+ memorySize: '4096',
47
+ hostsystem: '',
48
+ cloudConfig: '#cloud-config\n\n',
49
+ gracefulShutdownTimeout: '0',
50
+ cfgparam: ['disk.enableUUID=TRUE'],
51
+ os: OS_OPTIONS[0]
52
+ };
43
53
 
44
54
  const getDefaultVappOptions = (networks) => {
45
55
  return {
@@ -217,15 +227,27 @@ export default {
217
227
  if (this.mode === _CREATE && !this.value.initted) {
218
228
  Object.defineProperty(this.value, 'initted', { value: true, enumerable: false });
219
229
 
230
+ const {
231
+ cpuCount,
232
+ diskSize,
233
+ memorySize,
234
+ hostsystem,
235
+ cloudConfig,
236
+ gracefulShutdownTimeout,
237
+ cfgparam,
238
+ os
239
+ } = DEFAULT_VALUES;
240
+
220
241
  set(this.value, 'creationType', creationMethods[0].value);
221
- set(this.value, 'cpuCount', '2');
222
- set(this.value, 'diskSize', '20000');
223
- set(this.value, 'memorySize', '4096');
224
- set(this.value, 'hostsystem', '');
225
- set(this.value, 'cloudConfig', '#cloud-config\n\n');
226
- set(this.value, 'cfgparam', DEFAULT_CFGPARAM);
242
+ set(this.value, 'cpuCount', cpuCount);
243
+ set(this.value, 'diskSize', diskSize);
244
+ set(this.value, 'memorySize', memorySize);
245
+ set(this.value, 'hostsystem', hostsystem);
246
+ set(this.value, 'gracefulShutdownTimeout', gracefulShutdownTimeout);
247
+ set(this.value, 'cloudConfig', cloudConfig);
248
+ set(this.value, 'cfgparam', cfgparam);
227
249
  set(this.value, 'vappProperty', this.value.vappProperty);
228
- set(this.value, 'os', OS_OPTIONS[0]);
250
+ set(this.value, 'os', os);
229
251
  Object.entries(INITIAL_VAPP_OPTIONS).forEach(([key, value]) => {
230
252
  set(this.value, key, value);
231
253
  });
@@ -326,6 +348,8 @@ export default {
326
348
  memorySize: integerString('value.memorySize'),
327
349
  diskSize: integerString('value.diskSize'),
328
350
 
351
+ gracefulShutdownTimeout: integerString('value.gracefulShutdownTimeout'),
352
+
329
353
  showCloudConfigYaml() {
330
354
  return this.value.creationType !== 'legacy';
331
355
  },
@@ -731,7 +755,10 @@ export default {
731
755
  </p>
732
756
  </h4>
733
757
  <div slot="body">
734
- <div class="row">
758
+ <div
759
+ class="row"
760
+ data-testid="datacenter"
761
+ >
735
762
  <div class="col span-6">
736
763
  <LabeledSelect
737
764
  v-model="value.datacenter"
@@ -742,7 +769,10 @@ export default {
742
769
  :disabled="disabled"
743
770
  />
744
771
  </div>
745
- <div class="col span-6">
772
+ <div
773
+ class="col span-6"
774
+ data-testid="resourcePool"
775
+ >
746
776
  <LabeledSelect
747
777
  v-model="value.pool"
748
778
  :loading="resourcePoolsLoading"
@@ -754,7 +784,10 @@ export default {
754
784
  </div>
755
785
  </div>
756
786
  <div class="row mt-10">
757
- <div class="col span-6">
787
+ <div
788
+ class="col span-6"
789
+ data-testid="dataStore"
790
+ >
758
791
  <LabeledSelect
759
792
  v-model="value.datastore"
760
793
  :loading="dataStoresLoading"
@@ -764,7 +797,10 @@ export default {
764
797
  :disabled="disabled"
765
798
  />
766
799
  </div>
767
- <div class="col span-6">
800
+ <div
801
+ class="col span-6"
802
+ data-testid="folder"
803
+ >
768
804
  <LabeledSelect
769
805
  v-model="value.folder"
770
806
  :loading="foldersLoading"
@@ -776,7 +812,10 @@ export default {
776
812
  </div>
777
813
  </div>
778
814
  <div class="row mt-10">
779
- <div class="col span-12">
815
+ <div
816
+ class="col span-6"
817
+ data-testid="host"
818
+ >
780
819
  <LabeledSelect
781
820
  v-model="host"
782
821
  :loading="hostsLoading"
@@ -789,6 +828,22 @@ export default {
789
828
  {{ t('cluster.machineConfig.vsphere.scheduling.host.note') }}
790
829
  </p>
791
830
  </div>
831
+ <div
832
+ class="col span-6"
833
+ data-testid="gracefulShutdownTimeout"
834
+ >
835
+ <UnitInput
836
+ v-model="gracefulShutdownTimeout"
837
+ :mode="mode"
838
+ :label="t('cluster.machineConfig.vsphere.scheduling.gracefulShutdownTimeout.label')"
839
+ :suffix="t('suffix.seconds', { count: gracefulShutdownTimeout})"
840
+ :disabled="disabled"
841
+ min="0"
842
+ />
843
+ <p class="text-muted mt-5">
844
+ {{ t('cluster.machineConfig.vsphere.scheduling.gracefulShutdownTimeout.note') }}
845
+ </p>
846
+ </div>
792
847
  </div>
793
848
  </div>
794
849
  </Card>
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@rancher/shell",
3
- "version": "0.3.28",
3
+ "version": "0.3.29",
4
4
  "description": "Rancher Dashboard Shell",
5
5
  "repository": "https://github.com/rancherlabs/dashboard",
6
6
  "license": "Apache-2.0",
@@ -41,6 +41,7 @@
41
41
  "@nuxtjs/eslint-config-typescript": "6.0.1",
42
42
  "@nuxtjs/webpack-profile": "0.1.0",
43
43
  "@popperjs/core": "2.4.4",
44
+ "@types/is-url": "1.2.30",
44
45
  "@types/node": "16.4.3",
45
46
  "@typescript-eslint/eslint-plugin": "4.33.0",
46
47
  "@typescript-eslint/parser": "4.33.0",
@@ -60,7 +60,11 @@ export default Vue.extend({
60
60
 
61
61
  <template>
62
62
  <span :class="{'badge-state': true, [bg]: true}">
63
- <i v-if="icon" class="icon" :class="{[icon]: true, 'mr-5': !!msg}" />{{ msg }}
63
+ <i
64
+ v-if="icon"
65
+ class="icon"
66
+ :class="{[icon]: true, 'mr-5': !!msg}"
67
+ />{{ msg }}
64
68
  </span>
65
69
  </template>
66
70
 
@@ -1,13 +1,63 @@
1
1
  import { mount } from '@vue/test-utils';
2
2
  import { Banner } from './index';
3
+ import { cleanHtmlDirective } from '@shell/plugins/clean-html-directive';
3
4
 
4
5
  describe('component: Banner', () => {
5
6
  it('should display text based on label', () => {
6
7
  const label = 'test';
7
- const wrapper = mount(Banner, { propsData: { label } });
8
+ const wrapper = mount(
9
+ Banner,
10
+ {
11
+ directives: { cleanHtmlDirective },
12
+ propsData: { label }
13
+ });
8
14
 
9
15
  const element = wrapper.find('span').element;
10
16
 
11
17
  expect(element.textContent).toBe(label);
12
18
  });
19
+
20
+ it('should display an icon', () => {
21
+ const icon = 'my-icon';
22
+ const wrapper = mount(Banner, { propsData: { icon } });
23
+
24
+ const element = wrapper.find(`.${ icon }`).element;
25
+
26
+ expect(element.classList).toContain(icon);
27
+ });
28
+
29
+ it('should not display an icon', () => {
30
+ const wrapper = mount(Banner);
31
+
32
+ const element = wrapper.find(`[data-testid="banner-icon"]`).element;
33
+
34
+ expect(element).not.toBeDefined();
35
+ });
36
+
37
+ it('should emit close event', () => {
38
+ const wrapper = mount(Banner, { propsData: { closable: true } });
39
+ const element = wrapper.find(`[data-testid="banner-close"]`).element;
40
+
41
+ element.click();
42
+
43
+ expect(wrapper.emitted('close')).toHaveLength(1);
44
+ });
45
+
46
+ it('should add the right color', () => {
47
+ const color = 'red';
48
+ const wrapper = mount(Banner, { propsData: { color } });
49
+
50
+ const element = wrapper.element;
51
+
52
+ expect(element.classList).toContain(color);
53
+ });
54
+
55
+ it('should stack the banner messages', () => {
56
+ const stacked = true;
57
+ const wrapper = mount(Banner, { propsData: { stacked } });
58
+
59
+ const element = wrapper.find(`[data-testid="banner-content"]`).element;
60
+
61
+ expect(element.classList).toContain('stacked');
62
+ });
13
63
  });