@eturnity/eturnity_reusable_components 9.25.17 → 9.28.0
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/package.json +1 -1
- package/src/components/collapsableInfoText/collapsableInfoText.spec.js +57 -0
- package/src/components/collapsableInfoText/collapsableInfoText.stories.js +8 -0
- package/src/components/filter/Filter.stories.js +177 -0
- package/src/components/filter/filter.spec.js +183 -0
- package/src/components/inputs/select/select.spec.js +154 -0
- package/src/components/inputs/select/select.stories.js +230 -56
- package/src/components/inputs/slider/slider.spec.js +59 -0
- package/src/components/inputs/slider/slider.stories.js +4 -2
- package/src/components/inputs/switchField/switchField.spec.js +88 -0
- package/src/components/inputs/textAreaInput/TextAreaInput.stories.js +78 -74
- package/src/components/inputs/textAreaInput/textAreaInput.spec.js +90 -0
|
@@ -1,127 +1,131 @@
|
|
|
1
|
+
import { ref, watch } from 'vue'
|
|
1
2
|
import TextAreaInput from './index.vue'
|
|
2
3
|
|
|
4
|
+
// To use:
|
|
5
|
+
// import TextAreaInput from '@eturnity/eturnity_reusable_components/src/components/inputs/textAreaInput'
|
|
6
|
+
// <text-area-input
|
|
7
|
+
// placeholder="Comments"
|
|
8
|
+
// :value="form.note"
|
|
9
|
+
// label="Question 5"
|
|
10
|
+
// row-height="4"
|
|
11
|
+
// :is-error="false"
|
|
12
|
+
// error-text="This field is required"
|
|
13
|
+
// @input-change="onInputChange($event)"
|
|
14
|
+
// />
|
|
15
|
+
|
|
3
16
|
export default {
|
|
4
17
|
title: 'Components/Inputs/TextAreaInput',
|
|
5
18
|
component: TextAreaInput,
|
|
6
|
-
|
|
19
|
+
tags: ['autodocs'],
|
|
20
|
+
argTypes: {
|
|
21
|
+
value: { control: 'text' },
|
|
22
|
+
placeholder: { control: 'text' },
|
|
23
|
+
label: { control: 'text' },
|
|
24
|
+
rowHeight: { control: 'text' },
|
|
25
|
+
fontSize: { control: 'text' },
|
|
26
|
+
inputWidth: { control: 'text' },
|
|
27
|
+
resize: {
|
|
28
|
+
control: 'inline-radio',
|
|
29
|
+
options: ['none', 'both', 'horizontal', 'vertical'],
|
|
30
|
+
},
|
|
31
|
+
alignItems: {
|
|
32
|
+
control: 'inline-radio',
|
|
33
|
+
options: ['horizontal', 'vertical'],
|
|
34
|
+
},
|
|
35
|
+
appTheme: { control: 'inline-radio', options: ['light', 'dark'] },
|
|
36
|
+
isDisabled: { control: 'boolean' },
|
|
37
|
+
isError: { control: 'boolean' },
|
|
38
|
+
errorText: { control: 'text' },
|
|
39
|
+
infoTextMessage: { control: 'text' },
|
|
40
|
+
isRequiredLabel: { control: 'boolean' },
|
|
41
|
+
},
|
|
7
42
|
}
|
|
8
43
|
|
|
9
|
-
const Template = (args
|
|
10
|
-
// Components used in your story `template` are defined in the `components` object
|
|
44
|
+
const Template = (args) => ({
|
|
11
45
|
components: { TextAreaInput },
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
// alignItems="horizontal" // horizontal, vertical
|
|
28
|
-
// :isDisabled="true"
|
|
29
|
-
// />
|
|
46
|
+
setup() {
|
|
47
|
+
const model = ref(args.value)
|
|
48
|
+
watch(
|
|
49
|
+
() => args.value,
|
|
50
|
+
(v) => {
|
|
51
|
+
model.value = v
|
|
52
|
+
}
|
|
53
|
+
)
|
|
54
|
+
return { args, model }
|
|
55
|
+
},
|
|
56
|
+
template: `
|
|
57
|
+
<div style="padding: 16px;">
|
|
58
|
+
<TextAreaInput v-bind="args" :value="model" @input-change="model = $event" />
|
|
59
|
+
</div>
|
|
60
|
+
`,
|
|
30
61
|
})
|
|
31
62
|
|
|
32
|
-
|
|
33
|
-
Default.args = {
|
|
63
|
+
const baseArgs = {
|
|
34
64
|
placeholder: 'Enter a comment',
|
|
35
|
-
isDisabled: false,
|
|
36
65
|
rowHeight: '2',
|
|
37
|
-
isError: false,
|
|
38
|
-
errorText: 'This field is required',
|
|
39
|
-
infoTextMessage: '',
|
|
40
|
-
label: '',
|
|
41
66
|
value: '',
|
|
42
67
|
alignItems: 'vertical',
|
|
43
68
|
inputWidth: '350px',
|
|
44
69
|
}
|
|
45
70
|
|
|
71
|
+
export const Default = Template.bind({})
|
|
72
|
+
Default.args = {
|
|
73
|
+
...baseArgs,
|
|
74
|
+
}
|
|
75
|
+
|
|
46
76
|
export const Disabled = Template.bind({})
|
|
47
77
|
Disabled.args = {
|
|
48
|
-
|
|
78
|
+
...baseArgs,
|
|
49
79
|
isDisabled: true,
|
|
50
|
-
|
|
51
|
-
isError: false,
|
|
52
|
-
errorText: 'This field is required',
|
|
53
|
-
infoTextMessage: '',
|
|
54
|
-
label: '',
|
|
55
|
-
value: '',
|
|
56
|
-
alignItems: 'vertical',
|
|
57
|
-
inputWidth: '350px',
|
|
80
|
+
value: 'Cannot edit this',
|
|
58
81
|
}
|
|
59
82
|
|
|
60
83
|
export const Error = Template.bind({})
|
|
61
84
|
Error.args = {
|
|
62
|
-
|
|
63
|
-
isDisabled: false,
|
|
64
|
-
rowHeight: '2',
|
|
85
|
+
...baseArgs,
|
|
65
86
|
isError: true,
|
|
66
87
|
errorText: 'This field is required',
|
|
67
|
-
infoTextMessage: '',
|
|
68
|
-
label: '',
|
|
69
|
-
value: '',
|
|
70
|
-
alignItems: 'vertical',
|
|
71
|
-
inputWidth: '350px',
|
|
72
88
|
}
|
|
73
89
|
|
|
74
90
|
export const WithLabel = Template.bind({})
|
|
75
91
|
WithLabel.args = {
|
|
76
|
-
|
|
77
|
-
isDisabled: false,
|
|
78
|
-
rowHeight: '2',
|
|
79
|
-
isError: false,
|
|
80
|
-
errorText: 'This field is required',
|
|
81
|
-
infoTextMessage: 'Here is some information',
|
|
92
|
+
...baseArgs,
|
|
82
93
|
label: 'Description',
|
|
94
|
+
infoTextMessage: 'Here is some information',
|
|
83
95
|
value: 'Here is my description!',
|
|
84
|
-
alignItems: 'vertical',
|
|
85
|
-
inputWidth: '350px',
|
|
86
96
|
}
|
|
87
97
|
|
|
88
98
|
export const HorizontalLabel = Template.bind({})
|
|
89
99
|
HorizontalLabel.args = {
|
|
90
|
-
|
|
91
|
-
isDisabled: false,
|
|
92
|
-
rowHeight: '2',
|
|
93
|
-
isError: false,
|
|
94
|
-
errorText: 'This field is required',
|
|
95
|
-
infoTextMessage: 'Here is some information',
|
|
100
|
+
...baseArgs,
|
|
96
101
|
label: 'Description',
|
|
102
|
+
infoTextMessage: 'Here is some information',
|
|
97
103
|
value: 'Here is my description!',
|
|
98
104
|
alignItems: 'horizontal',
|
|
99
|
-
|
|
105
|
+
}
|
|
106
|
+
|
|
107
|
+
export const RequiredLabel = Template.bind({})
|
|
108
|
+
RequiredLabel.args = {
|
|
109
|
+
...baseArgs,
|
|
110
|
+
label: 'Description',
|
|
111
|
+
isRequiredLabel: true,
|
|
100
112
|
}
|
|
101
113
|
|
|
102
114
|
export const LargerTextArea = Template.bind({})
|
|
103
115
|
LargerTextArea.args = {
|
|
104
|
-
|
|
105
|
-
isDisabled: false,
|
|
106
|
-
rowHeight: '5',
|
|
107
|
-
isError: false,
|
|
108
|
-
errorText: 'This field is required',
|
|
109
|
-
infoTextMessage: 'Here is some information',
|
|
116
|
+
...baseArgs,
|
|
110
117
|
label: 'Description',
|
|
118
|
+
rowHeight: '5',
|
|
111
119
|
value: 'Here is my description!',
|
|
112
|
-
|
|
120
|
+
inputWidth: null,
|
|
113
121
|
}
|
|
114
122
|
|
|
115
123
|
export const LargerFontSize = Template.bind({})
|
|
116
124
|
LargerFontSize.args = {
|
|
117
|
-
|
|
118
|
-
|
|
125
|
+
...baseArgs,
|
|
126
|
+
label: 'Description',
|
|
119
127
|
rowHeight: '5',
|
|
120
128
|
fontSize: '24px',
|
|
121
|
-
isError: false,
|
|
122
|
-
errorText: 'This field is required',
|
|
123
|
-
infoTextMessage: 'Here is some information',
|
|
124
|
-
label: 'Description',
|
|
125
129
|
value: 'Here is my description!',
|
|
126
|
-
|
|
130
|
+
inputWidth: null,
|
|
127
131
|
}
|
|
@@ -0,0 +1,90 @@
|
|
|
1
|
+
/* eslint-disable */
|
|
2
|
+
import { mount } from '@vue/test-utils'
|
|
3
|
+
import TextAreaInput from '@/components/inputs/textAreaInput'
|
|
4
|
+
import InfoText from '@/components/infoText'
|
|
5
|
+
|
|
6
|
+
// InfoText renders an icon; the real iconCache.mjs uses import.meta.
|
|
7
|
+
jest.mock('@/components/icon/iconCache.mjs', () => ({
|
|
8
|
+
fetchIcon: jest.fn(() => Promise.resolve('mocked-icon-url.svg')),
|
|
9
|
+
}))
|
|
10
|
+
|
|
11
|
+
describe('TextAreaInput', () => {
|
|
12
|
+
const mountTextArea = (props = {}) =>
|
|
13
|
+
mount(TextAreaInput, { props: { value: '', ...props } })
|
|
14
|
+
|
|
15
|
+
it('renders a textarea with the value, placeholder and row height', () => {
|
|
16
|
+
const textarea = mountTextArea({
|
|
17
|
+
value: 'Hello',
|
|
18
|
+
placeholder: 'Enter a comment',
|
|
19
|
+
rowHeight: '5',
|
|
20
|
+
}).find('textarea')
|
|
21
|
+
|
|
22
|
+
expect(textarea.element.value).toBe('Hello')
|
|
23
|
+
expect(textarea.attributes('placeholder')).toBe('Enter a comment')
|
|
24
|
+
expect(textarea.attributes('rows')).toBe('5')
|
|
25
|
+
})
|
|
26
|
+
|
|
27
|
+
it('emits input-change with the new value when typing', async () => {
|
|
28
|
+
const wrapper = mountTextArea()
|
|
29
|
+
|
|
30
|
+
await wrapper.find('textarea').setValue('new text')
|
|
31
|
+
|
|
32
|
+
expect(wrapper.emitted('input-change')).toHaveLength(1)
|
|
33
|
+
expect(wrapper.emitted('input-change')[0]).toEqual(['new text'])
|
|
34
|
+
})
|
|
35
|
+
|
|
36
|
+
it('does not emit input-change when disabled', async () => {
|
|
37
|
+
const wrapper = mountTextArea({ isDisabled: true })
|
|
38
|
+
const textarea = wrapper.find('textarea')
|
|
39
|
+
|
|
40
|
+
expect(textarea.attributes('disabled')).toBeDefined()
|
|
41
|
+
await textarea.setValue('blocked')
|
|
42
|
+
|
|
43
|
+
expect(wrapper.emitted('input-change')).toBeUndefined()
|
|
44
|
+
})
|
|
45
|
+
|
|
46
|
+
it('emits input-blur and input-focus with the current value', async () => {
|
|
47
|
+
const wrapper = mountTextArea({ value: 'abc' })
|
|
48
|
+
const textarea = wrapper.find('textarea')
|
|
49
|
+
|
|
50
|
+
await textarea.trigger('focus')
|
|
51
|
+
await textarea.trigger('blur')
|
|
52
|
+
|
|
53
|
+
expect(wrapper.emitted('input-focus')[0]).toEqual(['abc'])
|
|
54
|
+
expect(wrapper.emitted('input-blur')[0]).toEqual(['abc'])
|
|
55
|
+
})
|
|
56
|
+
|
|
57
|
+
it('renders the label with the required star', () => {
|
|
58
|
+
const wrapper = mountTextArea({ label: 'Description', isRequiredLabel: true })
|
|
59
|
+
expect(wrapper.text()).toContain('Description')
|
|
60
|
+
expect(wrapper.text()).toContain('*')
|
|
61
|
+
})
|
|
62
|
+
|
|
63
|
+
it('renders the info text only when a message is provided', () => {
|
|
64
|
+
expect(
|
|
65
|
+
mountTextArea({ label: 'Description' }).findComponent(InfoText).exists()
|
|
66
|
+
).toBe(false)
|
|
67
|
+
expect(
|
|
68
|
+
mountTextArea({ label: 'Description', infoTextMessage: 'Some hint' })
|
|
69
|
+
.findComponent(InfoText)
|
|
70
|
+
.exists()
|
|
71
|
+
).toBe(true)
|
|
72
|
+
})
|
|
73
|
+
|
|
74
|
+
it('shows the error text only when isError is set', () => {
|
|
75
|
+
expect(mountTextArea({ errorText: 'Required' }).text()).not.toContain(
|
|
76
|
+
'Required'
|
|
77
|
+
)
|
|
78
|
+
expect(
|
|
79
|
+
mountTextArea({ isError: true, errorText: 'Required' }).text()
|
|
80
|
+
).toContain('Required')
|
|
81
|
+
})
|
|
82
|
+
|
|
83
|
+
it('prefers inputDataId over dataId for the textarea data-id', () => {
|
|
84
|
+
const textarea = mountTextArea({
|
|
85
|
+
inputDataId: 'note_input',
|
|
86
|
+
dataId: 'fallback',
|
|
87
|
+
}).find('textarea')
|
|
88
|
+
expect(textarea.attributes('data-id')).toBe('note_input')
|
|
89
|
+
})
|
|
90
|
+
})
|