@rancher/shell 0.3.23 → 0.3.25
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/assets/styles/base/_variables.scss +1 -0
- package/assets/styles/themes/_dark.scss +1 -0
- package/assets/styles/themes/_light.scss +6 -5
- package/assets/translations/en-us.yaml +44 -17
- package/assets/translations/zh-hans.yaml +2 -2
- package/components/ClusterIconMenu.vue +143 -0
- package/components/CruResource.vue +7 -1
- package/components/ExplorerProjectsNamespaces.vue +11 -1
- package/components/FixedBanner.vue +17 -1
- package/components/Loading.vue +1 -1
- package/components/Markdown.vue +1 -1
- package/components/Questions/__tests__/Yaml.test.ts +3 -2
- package/components/SideNav.vue +1 -1
- package/components/SortableTable/index.vue +3 -2
- package/components/auth/RoleDetailEdit.vue +15 -2
- package/components/auth/login/saml.vue +12 -1
- package/components/form/LabeledSelect.vue +12 -5
- package/components/form/Members/ClusterPermissionsEditor.vue +1 -1
- package/components/form/Members/MembershipEditor.vue +6 -1
- package/components/form/SelectOrCreateAuthSecret.vue +7 -0
- package/components/form/__tests__/KeyValue.test.ts +6 -3
- package/components/form/__tests__/LabeledSelect.test.ts +18 -0
- package/components/formatter/PodsUsage.vue +11 -36
- package/components/formatter/PrincipalGroupBindings.vue +8 -5
- package/components/formatter/__tests__/PodsUsage.test.ts +36 -19
- package/components/nav/Group.vue +62 -34
- package/components/nav/Header.vue +13 -6
- package/components/nav/Pinned.vue +47 -0
- package/components/nav/TopLevelMenu.vue +673 -325
- package/components/nav/Type.vue +88 -8
- package/config/home-links.js +1 -1
- package/config/product/istio.js +15 -5
- package/config/router.js +3 -9
- package/config/table-headers.js +5 -6
- package/config/uiplugins.js +1 -0
- package/core/plugin-helpers.js +3 -0
- package/core/types.ts +6 -1
- package/creators/app/files/.vscode/settings.json +0 -1
- package/creators/pkg/init +2 -2
- package/detail/__tests__/autoscaling.horizontalpodautoscaler.test.ts +118 -0
- package/detail/autoscaling.horizontalpodautoscaler/index.vue +4 -4
- package/detail/provisioning.cattle.io.cluster.vue +7 -5
- package/edit/__tests__/management.cattle.io.clusterroletemplatebinding.test.ts +58 -0
- package/edit/__tests__/namespace.test.ts +5 -3
- package/edit/fleet.cattle.io.gitrepo.vue +43 -15
- package/edit/logging.banzaicloud.io.output/index.vue +7 -0
- package/edit/management.cattle.io.clusterroletemplatebinding.vue +3 -11
- package/edit/namespace.vue +8 -4
- package/edit/provisioning.cattle.io.cluster/Basics.vue +662 -0
- package/edit/provisioning.cattle.io.cluster/CustomCommand.vue +9 -8
- package/edit/provisioning.cattle.io.cluster/DrainOptions.vue +13 -8
- package/edit/provisioning.cattle.io.cluster/MachinePool.vue +11 -2
- package/edit/provisioning.cattle.io.cluster/MemberRoles.vue +40 -0
- package/edit/provisioning.cattle.io.cluster/__tests__/Basics.tests.ts +237 -0
- package/edit/provisioning.cattle.io.cluster/__tests__/CustomCommand.tests.ts +71 -23
- package/edit/provisioning.cattle.io.cluster/__tests__/DrainOptions.test.ts +52 -0
- package/edit/provisioning.cattle.io.cluster/__tests__/rke2.test.ts +65 -142
- package/edit/provisioning.cattle.io.cluster/rke2.vue +253 -582
- package/edit/workload/storage/ContainerMountPaths.vue +7 -5
- package/edit/workload/storage/__tests__/Storage.test.ts +2 -2
- package/edit/workload/storage/persistentVolumeClaim/__tests__/persistentvolumeclaim.test.ts +36 -0
- package/edit/workload/storage/persistentVolumeClaim/persistentvolumeclaim.vue +15 -7
- package/initialize/App.js +2 -0
- package/initialize/client.js +63 -51
- package/initialize/index.js +7 -5
- package/layouts/default.vue +10 -2
- package/layouts/home.vue +6 -2
- package/layouts/plain.vue +9 -2
- package/list/fleet.cattle.io.cluster.vue +2 -2
- package/list/management.cattle.io.feature.vue +1 -1
- package/machine-config/amazonec2.vue +1 -0
- package/machine-config/vmwarevsphere.vue +48 -7
- package/mixins/brand.js +0 -8
- package/mixins/child-hook.js +2 -2
- package/mixins/create-edit-view/impl.js +3 -3
- package/mixins/fetch.client.js +3 -3
- package/models/__tests__/management.cattle.io.node.ts +96 -0
- package/models/__tests__/node.ts +74 -0
- package/models/cluster/node.js +6 -5
- package/models/cluster.x-k8s.io.machinedeployment.js +2 -2
- package/models/management.cattle.io.cluster.js +22 -1
- package/models/management.cattle.io.clusterroletemplatebinding.js +3 -3
- package/models/management.cattle.io.globalrole.js +17 -2
- package/models/management.cattle.io.node.js +6 -4
- package/models/management.cattle.io.projectroletemplatebinding.js +3 -3
- package/models/management.cattle.io.roletemplate.js +17 -2
- package/package.json +2 -6
- package/pages/__tests__/prefs.test.ts +1 -1
- package/pages/about.vue +2 -0
- package/pages/auth/setup.vue +5 -4
- package/pages/c/_cluster/explorer/ConfigBadge.vue +1 -0
- package/pages/c/_cluster/monitoring/index.vue +8 -3
- package/pages/c/_cluster/uiplugins/CatalogList/CatalogLoadDialog.vue +9 -66
- package/pages/c/_cluster/uiplugins/CatalogList/CatalogUninstallDialog.vue +182 -0
- package/pages/c/_cluster/uiplugins/CatalogList/index.vue +15 -32
- package/pages/c/_cluster/uiplugins/UninstallDialog.vue +8 -46
- package/pages/c/_cluster/uiplugins/index.vue +64 -64
- package/pages/diagnostic.vue +0 -39
- package/pages/home.vue +1 -1
- package/pages/prefs.vue +3 -13
- package/plugins/dashboard-store/normalize.js +4 -4
- package/plugins/dashboard-store/resource-class.js +1 -1
- package/plugins/int-number.js +5 -2
- package/plugins/positive-int-number.js +19 -0
- package/plugins/steve/__tests__/getters.spec.ts +15 -0
- package/plugins/steve/getters.js +22 -10
- package/public/index.html +4 -2
- package/rancher-components/BadgeState/BadgeState.vue +5 -1
- package/rancher-components/Banner/Banner.test.ts +51 -1
- package/rancher-components/Banner/Banner.vue +134 -53
- package/rancher-components/Card/Card.test.ts +37 -0
- package/rancher-components/Card/Card.vue +24 -7
- package/rancher-components/Form/Checkbox/Checkbox.test.ts +20 -29
- package/rancher-components/Form/Checkbox/Checkbox.vue +45 -20
- package/rancher-components/Form/LabeledInput/LabeledInput.test.ts +2 -8
- package/rancher-components/Form/LabeledInput/LabeledInput.vue +22 -10
- package/rancher-components/Form/Radio/RadioButton.test.ts +31 -0
- package/rancher-components/Form/Radio/RadioButton.vue +30 -13
- package/rancher-components/Form/Radio/RadioGroup.vue +26 -7
- package/rancher-components/Form/TextArea/TextAreaAutoGrow.vue +7 -6
- package/rancher-components/Form/ToggleSwitch/ToggleSwitch.test.ts +25 -38
- package/rancher-components/Form/ToggleSwitch/ToggleSwitch.vue +23 -11
- package/rancher-components/LabeledTooltip/LabeledTooltip.vue +19 -5
- package/rancher-components/StringList/StringList.test.ts +453 -49
- package/rancher-components/StringList/StringList.vue +92 -58
- package/scripts/extension/parse-tag-name +0 -0
- package/store/index.js +4 -0
- package/store/prefs.js +4 -4
- package/store/type-map.js +2 -16
- package/types/shell/index.d.ts +26 -14
- package/utils/__tests__/cluster.test.ts +55 -0
- package/utils/__tests__/object.test.ts +21 -2
- package/utils/__tests__/sort.test.ts +61 -0
- package/utils/cluster.js +47 -1
- package/utils/object.js +12 -5
- package/utils/string.js +12 -0
- package/utils/validators/formRules/__tests__/index.test.ts +13 -1
- package/utils/validators/formRules/index.ts +4 -0
- package/utils/validators/role-template.js +9 -1
- package/utils/version.js +1 -1
- package/vue.config.js +1 -4
- package/yarn-error.log +200 -0
- package/content/docs/en-us/getting-started.md +0 -224
- package/content/docs/en-us/whats-new.md +0 -29
- package/content/docs/zh-hans/getting-started.md +0 -224
- package/content/docs/zh-hans/whats-new.md +0 -28
- package/pages/docs/_doc.vue +0 -345
- package/pages/docs/toc.js +0 -27
- package/plugins/console.js +0 -34
|
@@ -1,80 +1,484 @@
|
|
|
1
|
-
|
|
1
|
+
/* eslint-disable jest/no-hooks */
|
|
2
|
+
import { mount, Wrapper } from '@vue/test-utils';
|
|
2
3
|
import { StringList } from './index';
|
|
3
4
|
|
|
4
|
-
describe('
|
|
5
|
+
describe('stringList.vue', () => {
|
|
6
|
+
let wrapper: Wrapper<InstanceType<typeof StringList>>;
|
|
5
7
|
|
|
6
|
-
|
|
7
|
-
|
|
8
|
-
|
|
8
|
+
beforeEach(() => {
|
|
9
|
+
wrapper = mount(StringList, { propsData: { items: [] } });
|
|
10
|
+
});
|
|
11
|
+
|
|
12
|
+
describe('list box', () => {
|
|
13
|
+
it('is empty', () => {
|
|
14
|
+
const box = wrapper.find('[data-testid="div-string-list-box"]').element as HTMLElement;
|
|
15
|
+
|
|
16
|
+
expect(box.children).toHaveLength(0);
|
|
9
17
|
});
|
|
10
|
-
const box = wrapper.find('[data-testid="div-string-list-box"]').element as HTMLElement;
|
|
11
18
|
|
|
12
|
-
|
|
13
|
-
|
|
19
|
+
it('show multiple items', async() => {
|
|
20
|
+
const items = ['a', 'b', 'c', 'd', 'e', 'f', 'g', 'h', 'i', 'k'];
|
|
21
|
+
|
|
22
|
+
await wrapper.setProps({ items });
|
|
23
|
+
|
|
24
|
+
const elements = wrapper.findAll('[data-testid^="div-item"]');
|
|
14
25
|
|
|
15
|
-
|
|
16
|
-
const wrapper = mount(StringList, {
|
|
17
|
-
propsData: { items: ['test'] },
|
|
26
|
+
expect(elements).toHaveLength(10);
|
|
18
27
|
});
|
|
19
|
-
const box = wrapper.find('.string-list-box').element as HTMLElement;
|
|
20
28
|
|
|
21
|
-
|
|
22
|
-
|
|
29
|
+
it('double click triggers inline edit mode', async() => {
|
|
30
|
+
const items = ['test'];
|
|
31
|
+
|
|
32
|
+
await wrapper.setProps({ items });
|
|
33
|
+
|
|
34
|
+
const item = wrapper.find('[data-testid="div-item-test"]');
|
|
35
|
+
|
|
36
|
+
await item.trigger('dblclick');
|
|
37
|
+
|
|
38
|
+
const inputField = wrapper.find('[data-testid^="item-edit"]');
|
|
23
39
|
|
|
24
|
-
|
|
25
|
-
const wrapper = mount(StringList, {
|
|
26
|
-
propsData: { items: ['test'] },
|
|
40
|
+
expect(inputField.element).toBeDefined();
|
|
27
41
|
});
|
|
28
|
-
const actionButtons = wrapper.find('[data-testid="div-action-buttons"]').element as HTMLElement;
|
|
29
42
|
|
|
30
|
-
|
|
31
|
-
|
|
43
|
+
it('double click on empty space triggers create mode', async() => {
|
|
44
|
+
await wrapper.setProps({ items: [] });
|
|
45
|
+
|
|
46
|
+
// double click on empty space
|
|
47
|
+
const box = wrapper.find('[data-testid="div-string-list-box"]');
|
|
48
|
+
|
|
49
|
+
await box.trigger('dblclick');
|
|
50
|
+
|
|
51
|
+
const inputField = wrapper.find('[data-testid="item-create"]');
|
|
52
|
+
|
|
53
|
+
expect(inputField.element).toBeDefined();
|
|
54
|
+
});
|
|
55
|
+
|
|
56
|
+
it('select item when click on it', async() => {
|
|
57
|
+
const items = ['test'];
|
|
58
|
+
|
|
59
|
+
await wrapper.setProps({ items });
|
|
60
|
+
|
|
61
|
+
// select item
|
|
62
|
+
const item = wrapper.find('[data-testid^="div-item"]');
|
|
63
|
+
|
|
64
|
+
await item.trigger('mousedown');
|
|
65
|
+
|
|
66
|
+
expect(item.element.className).toContain('selected');
|
|
67
|
+
});
|
|
68
|
+
|
|
69
|
+
it('double click to edit item not allowed when readonly', async() => {
|
|
70
|
+
const items = ['test'];
|
|
32
71
|
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
propsData: {
|
|
36
|
-
items: ['test'],
|
|
72
|
+
await wrapper.setProps({
|
|
73
|
+
items,
|
|
37
74
|
readonly: true,
|
|
38
|
-
}
|
|
75
|
+
});
|
|
76
|
+
|
|
77
|
+
const item = wrapper.find('[data-testid="div-item-test"]');
|
|
78
|
+
|
|
79
|
+
await item.trigger('dblclick');
|
|
80
|
+
|
|
81
|
+
const inputField = wrapper.find('[data-testid^="item-edit"]');
|
|
82
|
+
|
|
83
|
+
expect(inputField.element).toBeUndefined();
|
|
39
84
|
});
|
|
40
|
-
const actionButtons = wrapper.find('[data-testid="div-action-buttons"]').element as HTMLElement;
|
|
41
85
|
|
|
42
|
-
|
|
43
|
-
|
|
86
|
+
it('double click on empty space to create item not allowed when readonly', async() => {
|
|
87
|
+
await wrapper.setProps({
|
|
88
|
+
items: [],
|
|
89
|
+
readonly: true,
|
|
90
|
+
});
|
|
91
|
+
|
|
92
|
+
// double click on empty space
|
|
93
|
+
const box = wrapper.find('[data-testid="div-string-list-box"]');
|
|
94
|
+
|
|
95
|
+
await box.trigger('dblclick');
|
|
44
96
|
|
|
45
|
-
|
|
46
|
-
const items = [ 'a', 'b', 'c', 'd', 'e', 'f', 'g', 'h', 'i', 'k'];
|
|
97
|
+
const inputField = wrapper.find('[data-testid="item-create"]');
|
|
47
98
|
|
|
48
|
-
|
|
49
|
-
|
|
99
|
+
expect(inputField.element).toBeUndefined();
|
|
100
|
+
});
|
|
101
|
+
|
|
102
|
+
it('select item not allowed when readonly', async() => {
|
|
103
|
+
const items = ['test'];
|
|
104
|
+
|
|
105
|
+
await wrapper.setProps({
|
|
50
106
|
items,
|
|
51
|
-
|
|
107
|
+
readonly: true,
|
|
108
|
+
});
|
|
109
|
+
|
|
110
|
+
// select item
|
|
111
|
+
const item = wrapper.find('[data-testid^="div-item"]');
|
|
112
|
+
|
|
113
|
+
await item.trigger('mousedown');
|
|
114
|
+
|
|
115
|
+
expect(item.element.className).not.toContain('selected');
|
|
52
116
|
});
|
|
53
|
-
const elements = wrapper.findAll('[data-testid^="div-item"]');
|
|
54
117
|
|
|
55
|
-
|
|
118
|
+
it('emit type:item event', async() => {
|
|
119
|
+
// activate create mode
|
|
120
|
+
await wrapper.setData({ isCreateItem: true });
|
|
121
|
+
|
|
122
|
+
const inputField = wrapper.find('[data-testid="item-create"]');
|
|
123
|
+
|
|
124
|
+
// set input value to 'F'
|
|
125
|
+
await inputField.setValue('F');
|
|
126
|
+
await wrapper.vm.$nextTick();
|
|
56
127
|
|
|
57
|
-
|
|
128
|
+
const emitted = (wrapper.emitted('type:item') || [])[0][0][0];
|
|
58
129
|
|
|
59
|
-
|
|
60
|
-
|
|
130
|
+
expect(emitted).toBe('F');
|
|
131
|
+
});
|
|
61
132
|
});
|
|
62
133
|
|
|
63
|
-
|
|
64
|
-
|
|
134
|
+
describe('buttons', () => {
|
|
135
|
+
it('are visible by default', () => {
|
|
136
|
+
const actionButtons = wrapper.find('[data-testid="div-action-buttons"]');
|
|
65
137
|
|
|
66
|
-
|
|
67
|
-
|
|
68
|
-
|
|
69
|
-
|
|
138
|
+
expect(actionButtons.element).toBeDefined();
|
|
139
|
+
});
|
|
140
|
+
|
|
141
|
+
it('are hidden when is view-only mode', async() => {
|
|
142
|
+
await wrapper.setProps({ readonly: true });
|
|
143
|
+
const actionButtons = wrapper.find('[data-testid="div-action-buttons"]');
|
|
144
|
+
|
|
145
|
+
expect(actionButtons.element).toBeUndefined();
|
|
146
|
+
});
|
|
147
|
+
|
|
148
|
+
describe('add button', () => {
|
|
149
|
+
it('is enabled by default', () => {
|
|
150
|
+
const addButton = wrapper.find('[data-testid="button-add"]')?.element as HTMLButtonElement;
|
|
151
|
+
|
|
152
|
+
expect(addButton.disabled).toBe(false);
|
|
153
|
+
});
|
|
154
|
+
|
|
155
|
+
it('show the input field when is clicked', async() => {
|
|
156
|
+
// click add button
|
|
157
|
+
const addButton = wrapper.find('[data-testid="button-add"]');
|
|
158
|
+
|
|
159
|
+
await addButton.trigger('click');
|
|
160
|
+
|
|
161
|
+
const inputField = wrapper.find('[data-testid="item-create"]');
|
|
162
|
+
|
|
163
|
+
expect(inputField.element).toBeDefined();
|
|
164
|
+
});
|
|
165
|
+
|
|
166
|
+
it('is disabled when create mode is active', async() => {
|
|
167
|
+
// click add button
|
|
168
|
+
const addButton = wrapper.find('[data-testid="button-add"]');
|
|
169
|
+
|
|
170
|
+
await addButton.trigger('click');
|
|
171
|
+
|
|
172
|
+
wrapper.find('[data-testid="item-create"]');
|
|
173
|
+
|
|
174
|
+
const buttonElem = addButton.element as HTMLButtonElement;
|
|
175
|
+
|
|
176
|
+
expect(buttonElem.disabled).toBe(true);
|
|
177
|
+
});
|
|
178
|
+
});
|
|
179
|
+
|
|
180
|
+
describe('remove button', () => {
|
|
181
|
+
it('is disabled by default', () => {
|
|
182
|
+
const removeButton = wrapper.find('[data-testid="button-remove"]');
|
|
183
|
+
const buttonElem = removeButton.element as HTMLButtonElement;
|
|
184
|
+
|
|
185
|
+
expect(buttonElem.disabled).toBe(true);
|
|
186
|
+
});
|
|
187
|
+
|
|
188
|
+
it('is enabled when create mode is active', async() => {
|
|
189
|
+
// click add button
|
|
190
|
+
const addButton = wrapper.find('[data-testid="button-add"]');
|
|
191
|
+
|
|
192
|
+
await addButton.trigger('click');
|
|
193
|
+
|
|
194
|
+
const removeButton = wrapper.find('[data-testid="button-remove"]');
|
|
195
|
+
const buttonElem = removeButton.element as HTMLButtonElement;
|
|
196
|
+
|
|
197
|
+
expect(buttonElem.disabled).toBe(false);
|
|
198
|
+
});
|
|
199
|
+
|
|
200
|
+
it('is enabled when edit mode is active', async() => {
|
|
201
|
+
const items = ['test'];
|
|
202
|
+
|
|
203
|
+
await wrapper.setProps({ items });
|
|
204
|
+
|
|
205
|
+
// activate edit mode
|
|
206
|
+
await wrapper.setData({ editedItem: 'test' });
|
|
207
|
+
|
|
208
|
+
const removeButton = wrapper.find('[data-testid="button-remove"]');
|
|
209
|
+
const buttonElem = removeButton.element as HTMLButtonElement;
|
|
210
|
+
|
|
211
|
+
expect(buttonElem.disabled).toBe(false);
|
|
212
|
+
});
|
|
213
|
+
|
|
214
|
+
it('is enabled when an item is selected', async() => {
|
|
215
|
+
const items = ['test'];
|
|
216
|
+
|
|
217
|
+
await wrapper.setProps({ items });
|
|
218
|
+
|
|
219
|
+
// select item
|
|
220
|
+
await wrapper.setData({ selected: 'test' });
|
|
221
|
+
|
|
222
|
+
// click remove button
|
|
223
|
+
const removeButton = wrapper.find('[data-testid="button-remove"]');
|
|
224
|
+
const buttonElem = removeButton.element as HTMLButtonElement;
|
|
225
|
+
|
|
226
|
+
expect(buttonElem.disabled).toBe(false);
|
|
227
|
+
});
|
|
228
|
+
|
|
229
|
+
it('removes items when an item is selected', async() => {
|
|
230
|
+
const items = ['a'];
|
|
231
|
+
|
|
232
|
+
await wrapper.setProps({ items });
|
|
233
|
+
|
|
234
|
+
// select item
|
|
235
|
+
await wrapper.setData({ selected: 'a' });
|
|
236
|
+
|
|
237
|
+
// click remove button
|
|
238
|
+
const removeButton = wrapper.find('[data-testid="button-remove"]');
|
|
239
|
+
|
|
240
|
+
await removeButton.trigger('mousedown');
|
|
241
|
+
|
|
242
|
+
await wrapper.vm.$nextTick();
|
|
243
|
+
|
|
244
|
+
const itemsCount = (wrapper.emitted('change') || [])[0][0].length;
|
|
245
|
+
|
|
246
|
+
expect(itemsCount).toBe(0);
|
|
247
|
+
});
|
|
248
|
+
|
|
249
|
+
it('deactivates create mode', async() => {
|
|
250
|
+
// activate create mode
|
|
251
|
+
await wrapper.setData({ isCreateItem: true });
|
|
252
|
+
|
|
253
|
+
// click remove button
|
|
254
|
+
const removeButton = wrapper.find('[data-testid="button-remove"]');
|
|
255
|
+
|
|
256
|
+
await removeButton.trigger('mousedown');
|
|
257
|
+
|
|
258
|
+
const inputField = await wrapper.find('[data-testid="item-create"]');
|
|
259
|
+
|
|
260
|
+
expect(inputField.element).toBeUndefined();
|
|
261
|
+
});
|
|
262
|
+
|
|
263
|
+
it('deactivates edit mode', async() => {
|
|
264
|
+
const items = ['test'];
|
|
265
|
+
|
|
266
|
+
await wrapper.setProps({ items });
|
|
267
|
+
|
|
268
|
+
// activate edit mode
|
|
269
|
+
await wrapper.setData({ editedItem: 'test' });
|
|
270
|
+
|
|
271
|
+
// click remove button
|
|
272
|
+
const removeButton = wrapper.find('[data-testid="button-remove"]');
|
|
273
|
+
|
|
274
|
+
await removeButton.trigger('mousedown');
|
|
275
|
+
|
|
276
|
+
const inputField = wrapper.find('[data-testid^="item-edit"]');
|
|
277
|
+
|
|
278
|
+
expect(inputField.element).toBeUndefined();
|
|
279
|
+
});
|
|
280
|
+
});
|
|
281
|
+
});
|
|
282
|
+
|
|
283
|
+
describe('list edit', () => {
|
|
284
|
+
const validItem = ' item name ';
|
|
285
|
+
const emptyItem = ' ';
|
|
286
|
+
|
|
287
|
+
it('save a new item in create mode by pressing Enter key', async() => {
|
|
288
|
+
// activate create mode
|
|
289
|
+
await wrapper.setData({ isCreateItem: true });
|
|
290
|
+
|
|
291
|
+
// type item name
|
|
292
|
+
const inputField = wrapper.find('[data-testid="item-create"]');
|
|
293
|
+
|
|
294
|
+
await inputField.setValue(validItem);
|
|
295
|
+
|
|
296
|
+
// press enter
|
|
297
|
+
await inputField.trigger('keydown.enter');
|
|
298
|
+
await wrapper.vm.$nextTick();
|
|
299
|
+
|
|
300
|
+
const emitted = (wrapper.emitted('change') || [])[0][0][0];
|
|
301
|
+
|
|
302
|
+
expect(emitted).toBe(validItem.trim());
|
|
303
|
+
});
|
|
304
|
+
|
|
305
|
+
it('save item in edit mode by pressing Enter key', async() => {
|
|
306
|
+
const items = ['test'];
|
|
307
|
+
|
|
308
|
+
await wrapper.setProps({ items });
|
|
309
|
+
|
|
310
|
+
// activate edit mode
|
|
311
|
+
await wrapper.setData({ editedItem: 'test' });
|
|
312
|
+
const inputField = wrapper.find('[data-testid^="item-edit"]');
|
|
313
|
+
|
|
314
|
+
// edit item name
|
|
315
|
+
await inputField.setValue(validItem);
|
|
316
|
+
|
|
317
|
+
// press enter
|
|
318
|
+
await inputField.trigger('keydown.enter');
|
|
319
|
+
await wrapper.vm.$nextTick();
|
|
320
|
+
|
|
321
|
+
const emitted = (wrapper.emitted('change') || [])[0][0][0];
|
|
322
|
+
|
|
323
|
+
expect(emitted).toBe(validItem.trim());
|
|
324
|
+
});
|
|
325
|
+
|
|
326
|
+
it('reject a new item in create mode when item name is empty', async() => {
|
|
327
|
+
// activate create mode
|
|
328
|
+
await wrapper.setData({ isCreateItem: true });
|
|
329
|
+
|
|
330
|
+
// type item name
|
|
331
|
+
const inputField = wrapper.find('[data-testid="item-create"]');
|
|
332
|
+
|
|
333
|
+
await inputField.setValue(emptyItem);
|
|
334
|
+
|
|
335
|
+
// press enter
|
|
336
|
+
await inputField.trigger('keydown.enter');
|
|
337
|
+
await wrapper.vm.$nextTick();
|
|
338
|
+
|
|
339
|
+
expect(wrapper.emitted('change')).toBeFalsy();
|
|
340
|
+
});
|
|
341
|
+
|
|
342
|
+
it('reject a new item in create mode when item name is duplicate', async() => {
|
|
343
|
+
const items = ['test'];
|
|
344
|
+
|
|
345
|
+
await wrapper.setProps({ items });
|
|
346
|
+
|
|
347
|
+
// activate create mode
|
|
348
|
+
await wrapper.setData({ isCreateItem: true });
|
|
349
|
+
|
|
350
|
+
// type item name
|
|
351
|
+
const inputField = wrapper.find('[data-testid="item-create"]');
|
|
352
|
+
|
|
353
|
+
await inputField.setValue('test');
|
|
354
|
+
|
|
355
|
+
// press enter
|
|
356
|
+
await inputField.trigger('keydown.enter');
|
|
357
|
+
await wrapper.vm.$nextTick();
|
|
358
|
+
|
|
359
|
+
expect(wrapper.emitted('change')).toBeFalsy();
|
|
70
360
|
});
|
|
71
|
-
const elements = wrapper.findAll('[data-testid^="div-item"]');
|
|
72
|
-
expect(elements.length).toBe(10);
|
|
73
361
|
|
|
74
|
-
|
|
362
|
+
it('reject an item in edit mode when item name is empty', async() => {
|
|
363
|
+
const items = ['test'];
|
|
364
|
+
|
|
365
|
+
await wrapper.setProps({ items });
|
|
366
|
+
|
|
367
|
+
// activate edit mode
|
|
368
|
+
await wrapper.setData({ editedItem: 'test' });
|
|
369
|
+
const inputField = wrapper.find('[data-testid^="item-edit"]');
|
|
370
|
+
|
|
371
|
+
// edit item name
|
|
372
|
+
await inputField.setValue(emptyItem);
|
|
373
|
+
|
|
374
|
+
// press enter
|
|
375
|
+
await inputField.trigger('keydown.enter');
|
|
376
|
+
await wrapper.vm.$nextTick();
|
|
75
377
|
|
|
76
|
-
|
|
77
|
-
|
|
378
|
+
expect(wrapper.emitted('change')).toBeFalsy();
|
|
379
|
+
});
|
|
380
|
+
|
|
381
|
+
it('reject an item in edit mode when item name is duplicate', async() => {
|
|
382
|
+
const items = ['test', 'test-1'];
|
|
383
|
+
|
|
384
|
+
await wrapper.setProps({ items });
|
|
385
|
+
|
|
386
|
+
// activate edit mode
|
|
387
|
+
await wrapper.setData({ editedItem: 'test' });
|
|
388
|
+
const inputField = wrapper.find('[data-testid^="item-edit"]');
|
|
389
|
+
|
|
390
|
+
// edit item name
|
|
391
|
+
await inputField.setValue('test-1');
|
|
392
|
+
|
|
393
|
+
// press enter
|
|
394
|
+
await inputField.trigger('keydown.enter');
|
|
395
|
+
await wrapper.vm.$nextTick();
|
|
396
|
+
|
|
397
|
+
expect(wrapper.emitted('change')).toBeFalsy();
|
|
398
|
+
});
|
|
78
399
|
});
|
|
79
400
|
|
|
401
|
+
describe('errors handling', () => {
|
|
402
|
+
it('show duplicate warning icon when errorMessages is defined', async() => {
|
|
403
|
+
const items = ['test'];
|
|
404
|
+
|
|
405
|
+
await wrapper.setProps({
|
|
406
|
+
items,
|
|
407
|
+
errorMessages: { duplicate: 'error, item is duplicate.' },
|
|
408
|
+
});
|
|
409
|
+
|
|
410
|
+
// activate edit mode
|
|
411
|
+
await wrapper.setData({ isCreateItem: true });
|
|
412
|
+
|
|
413
|
+
// type item name
|
|
414
|
+
const inputField = wrapper.find('[data-testid="item-create"]');
|
|
415
|
+
|
|
416
|
+
await inputField.setValue('test');
|
|
417
|
+
|
|
418
|
+
const icon = wrapper.find('[data-testid="i-warning-icon"]');
|
|
419
|
+
|
|
420
|
+
expect(icon.element).toBeDefined();
|
|
421
|
+
});
|
|
422
|
+
|
|
423
|
+
it('show duplicate warning message when errorMessages is defined', async() => {
|
|
424
|
+
const items = ['test'];
|
|
425
|
+
|
|
426
|
+
await wrapper.setProps({
|
|
427
|
+
items,
|
|
428
|
+
errorMessages: { duplicate: 'error, item is duplicate.' },
|
|
429
|
+
});
|
|
430
|
+
|
|
431
|
+
// activate edit mode
|
|
432
|
+
await wrapper.setData({ isCreateItem: true });
|
|
433
|
+
|
|
434
|
+
// type item name
|
|
435
|
+
const inputField = wrapper.find('[data-testid="item-create"]');
|
|
436
|
+
|
|
437
|
+
await inputField.setValue('test');
|
|
438
|
+
|
|
439
|
+
const message = wrapper.find('[data-testid^="span-error-message"]');
|
|
440
|
+
|
|
441
|
+
expect(message.element).toBeDefined();
|
|
442
|
+
});
|
|
443
|
+
|
|
444
|
+
it('emit duplicate errors', async() => {
|
|
445
|
+
const items = ['test'];
|
|
446
|
+
|
|
447
|
+
await wrapper.setProps({ items });
|
|
448
|
+
|
|
449
|
+
// activate edit mode
|
|
450
|
+
await wrapper.setData({ isCreateItem: true });
|
|
451
|
+
|
|
452
|
+
// type item name
|
|
453
|
+
const inputField = wrapper.find('[data-testid="item-create"]');
|
|
454
|
+
|
|
455
|
+
await inputField.setValue('test');
|
|
456
|
+
|
|
457
|
+
const isDuplicate = (wrapper.emitted('errors') || [])[0][0].duplicate;
|
|
458
|
+
|
|
459
|
+
expect(isDuplicate).toBe(true);
|
|
460
|
+
});
|
|
461
|
+
|
|
462
|
+
it('emit duplicate errors, reset error', async() => {
|
|
463
|
+
const items = ['test'];
|
|
464
|
+
|
|
465
|
+
await wrapper.setProps({ items });
|
|
466
|
+
|
|
467
|
+
// activate edit mode
|
|
468
|
+
await wrapper.setData({ isCreateItem: true });
|
|
469
|
+
|
|
470
|
+
// type item name
|
|
471
|
+
const inputField = wrapper.find('[data-testid="item-create"]');
|
|
472
|
+
|
|
473
|
+
// emit duplicate errors
|
|
474
|
+
await inputField.setValue('test');
|
|
475
|
+
|
|
476
|
+
// it is not duplicate, reset duplicate error -> emit false
|
|
477
|
+
await inputField.setValue('test-1');
|
|
478
|
+
|
|
479
|
+
const isDuplicate = (wrapper.emitted('errors') || [])[0][0].duplicate;
|
|
480
|
+
|
|
481
|
+
expect(isDuplicate).toBe(false);
|
|
482
|
+
});
|
|
483
|
+
});
|
|
80
484
|
});
|