@eturnity/eturnity_reusable_components 7.45.5 → 7.48.1

Sign up to get free protection for your applications and to get access to all the features.
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@eturnity/eturnity_reusable_components",
3
- "version": "7.45.5",
3
+ "version": "7.48.1",
4
4
  "files": [
5
5
  "dist",
6
6
  "src"
@@ -3,73 +3,68 @@ import InputText from './index.vue'
3
3
  export default {
4
4
  title: 'InputText',
5
5
  component: InputText,
6
- // argTypes: {},
6
+ tags: ['autodocs'],
7
7
  }
8
8
 
9
- const Template = (args, { argTypes }) => ({
10
- // Components used in your story `template` are defined in the `components` object
11
- components: { InputText },
12
- // The story's `args` need to be mapped into the template through the `setup()` method
13
- props: Object.keys(argTypes),
14
- template: '<input-text v-bind="$props" />',
9
+ // import InputText from "@eturnity/eturnity_reusable_components/src/components/inputs/inputText"
10
+ // To use:
11
+ // <input-text
12
+ // placeholder="Company name"
13
+ // :value="companyName"
14
+ // @input-change="onInputChange({ value: $event, type: 'companyName' })"
15
+ // :isError="checkErrors()"
16
+ // :errorMessage="This is my error message"
17
+ // infoTextAlign="right" // left by default
18
+ // infoTextMessage="My info message"
19
+ // label="Question 5"
20
+ // alignItems="horizontal" // horizontal, vertical
21
+ // inputWidth="250px"
22
+ // minWidth="100px"
23
+ // />
15
24
 
16
- // import InputText from "@eturnity/eturnity_reusable_components/src/components/inputs/inputText"
17
- // To use:
18
- // <input-text
19
- // placeholder="Company name"
20
- // :value="companyName"
21
- // @input-change="onInputChange({ value: $event, type: 'companyName' })"
22
- // :isError="checkErrors()"
23
- // :errorMessage="This is my error message"
24
- // infoTextAlign="right" // left by default
25
- // infoTextMessage="My info message"
26
- // label="Question 5"
27
- // alignItems="horizontal" // horizontal, vertical
28
- // inputWidth="250px"
29
- // minWidth="100px"
30
- // />
31
- })
32
-
33
- export const Default = Template.bind({})
34
- Default.args = {
35
- placeholder: 'Company name',
36
- disabled: false,
37
- value: '',
38
- inputWidth: '200px',
39
- minWidth: '10ch',
40
- unitName: 'pc',
41
- isError: false,
42
- textAlign: 'left',
25
+ export const Default = {
26
+ args: {
27
+ placeholder: 'Company name',
28
+ disabled: false,
29
+ value: '',
30
+ inputWidth: '200px',
31
+ minWidth: '10ch',
32
+ isError: false,
33
+ label: 'label test',
34
+ labelOptional: true,
35
+ },
43
36
  }
44
37
 
45
- export const hasError = Template.bind({})
46
- hasError.args = {
47
- placeholder: 'Enter Value',
48
- errorMessage: 'This field is required',
49
- isError: true,
50
- disabled: false,
51
- inputWidth: '200px',
38
+ export const HasError = {
39
+ args: {
40
+ placeholder: 'Enter Value',
41
+ errorMessage: 'This field is required',
42
+ isError: true,
43
+ disabled: false,
44
+ inputWidth: '200px',
45
+ },
52
46
  }
53
47
 
54
- export const Disabled = Template.bind({})
55
- Disabled.args = {
56
- placeholder: 'Enter Value',
57
- disabled: true,
58
- value: '',
59
- inputWidth: '200px',
60
- isError: false,
48
+ export const Disabled = {
49
+ args: {
50
+ placeholder: 'Enter Value',
51
+ disabled: true,
52
+ value: '',
53
+ inputWidth: '200px',
54
+ isError: false,
55
+ },
61
56
  }
62
57
 
63
- export const WithLabel = Template.bind({})
64
- WithLabel.args = {
65
- placeholder: 'Company name',
66
- disabled: false,
67
- label: 'What is the best company in Switzerland?',
68
- value: 'Eturnity',
69
- inputWidth: '200px',
70
- unitName: 'pc',
71
- isError: false,
72
- errorMessage: 'Maximum 5 characters',
73
- textAlign: 'left',
74
- alignItems: 'vertical',
58
+ export const WithLabel = {
59
+ args: {
60
+ placeholder: 'Company name',
61
+ disabled: false,
62
+ label: 'What is the best company in Switzerland?',
63
+ value: 'Eturnity',
64
+ inputWidth: '200px',
65
+ unitName: 'pc',
66
+ isError: false,
67
+ errorMessage: 'Maximum 5 characters',
68
+ alignItems: 'vertical',
69
+ },
75
70
  }
@@ -2,22 +2,26 @@
2
2
  <Container>
3
3
  <InputWrapper
4
4
  :align-items="alignItems"
5
+ data-test-id="input_wrapper"
5
6
  :has-label="!!label && label.length > 0"
6
7
  >
7
8
  <LabelWrapper v-if="label">
8
9
  <InputLabel
10
+ ref="label"
9
11
  :data-id="labelDataId"
12
+ data-test-id="label_wrapper"
10
13
  :font-size="fontSize"
11
14
  :label-font-color="labelFontColor"
12
15
  >
13
16
  {{ label }}
14
- <OptionalLabel v-if="labelOptional">
17
+ <OptionalLabel v-if="labelOptional" data-test-id="label_optional">
15
18
  ({{ $gettext('Optional') }})
16
19
  </OptionalLabel>
17
20
  </InputLabel>
18
21
  <InfoText
19
- v-if="infoTextMessage"
22
+ v-if="infoTextMessage != ''"
20
23
  :align-arrow="infoTextAlign"
24
+ data-test-id="info_text_message"
21
25
  :size="fontSize ? fontSize : '16px'"
22
26
  :text="infoTextMessage"
23
27
  />
@@ -28,6 +32,7 @@
28
32
  ref="inputElement"
29
33
  :background-color="backgroundColor"
30
34
  :data-id="inputDataId"
35
+ data-test-id="input"
31
36
  :disabled="disabled"
32
37
  :disabled-background-color="disabledBackgroundColor"
33
38
  :font-color="fontColor"
@@ -50,16 +55,20 @@
50
55
  />
51
56
  <IconWrapper
52
57
  v-if="inputType === 'password' && !isError"
58
+ data-test-id="password_visiblity_change_icon"
53
59
  size="20px"
54
60
  @click="toggleShowPassword()"
55
61
  >
56
62
  <Icon name="current_variant" size="20px" />
57
63
  </IconWrapper>
58
- <IconWrapper v-if="hasError" size="16px">
64
+ <IconWrapper v-if="hasError" data-test-id="error_wrapper" size="16px">
59
65
  <Icon cursor="default" name="warning" size="16px" />
60
66
  </IconWrapper>
61
67
  </IconContainer>
62
- <ErrorMessage v-if="hasError && hasErrorMessage">
68
+ <ErrorMessage
69
+ v-if="hasError && hasErrorMessage"
70
+ data-test-id="error_message_wrapper"
71
+ >
63
72
  {{ dynamicErrorMessage }}
64
73
  </ErrorMessage>
65
74
  </InputErrorWrapper>
@@ -237,93 +246,123 @@
237
246
  placeholder: {
238
247
  required: false,
239
248
  default: '',
249
+ type: String,
240
250
  },
241
251
  alignItems: {
242
252
  required: false,
243
253
  default: 'horizontal',
254
+ type: String,
255
+ validator(value) {
256
+ return ['horizontal', 'vertical'].includes(value)
257
+ },
244
258
  },
245
259
  isError: {
246
260
  required: false,
247
261
  default: false,
262
+ type: Boolean,
248
263
  },
249
264
  inputWidth: {
250
265
  required: false,
251
266
  default: null,
267
+ type: String,
252
268
  },
253
269
  inputHeight: {
254
270
  required: false,
255
271
  default: null,
272
+ type: String,
256
273
  },
257
274
  minWidth: {
258
275
  required: false,
259
276
  default: null,
277
+ type: String,
260
278
  },
261
279
  value: {
262
280
  required: true,
263
281
  default: null,
282
+ type: String,
264
283
  },
265
284
  errorMessage: {
266
285
  required: false,
267
286
  default: '',
287
+ type: String,
268
288
  },
269
289
  infoTextMessage: {
270
290
  required: false,
291
+ default: '',
292
+ type: String,
271
293
  },
272
294
  infoTextAlign: {
273
295
  required: false,
296
+ default: 'left',
297
+ type: String,
274
298
  },
275
299
  label: {
276
300
  required: false,
301
+ default: '',
302
+ type: String,
277
303
  },
278
304
  labelOptional: {
279
305
  required: false,
280
306
  default: false,
307
+ type: Boolean,
281
308
  },
282
309
  noBorder: {
283
310
  required: false,
284
311
  default: false,
312
+ type: Boolean,
285
313
  },
286
314
  disabled: {
287
315
  required: false,
288
316
  default: false,
317
+ type: Boolean,
289
318
  },
290
319
  fontSize: {
291
320
  required: false,
292
321
  default: null,
322
+ type: String,
293
323
  },
294
324
  inputType: {
295
325
  required: false,
296
326
  default: 'text',
327
+ type: String,
297
328
  },
298
329
  labelFontColor: {
299
330
  required: false,
300
331
  default: 'black',
332
+ type: String,
301
333
  },
302
334
  backgroundColor: {
303
335
  required: false,
336
+ type: String,
304
337
  },
305
338
  disabledBackgroundColor: {
306
339
  required: false,
307
340
  default: null,
341
+ type: String,
308
342
  },
309
343
  fontColor: {
310
344
  required: false,
311
345
  default: 'black',
346
+ type: String,
312
347
  },
313
348
  hasFocus: {
314
349
  required: false,
315
350
  default: false,
351
+ type: Boolean,
316
352
  },
317
353
  borderColor: {
318
354
  required: false,
355
+ type: String,
319
356
  },
320
357
  labelDataId: {
321
358
  required: false,
322
359
  default: '',
360
+ type: String,
323
361
  },
324
362
  inputDataId: {
325
363
  required: false,
326
364
  default: '',
365
+ type: String,
327
366
  },
328
367
  },
329
368
  data() {
@@ -336,12 +375,10 @@
336
375
  return this.isError || this.error
337
376
  },
338
377
  hasErrorMessage() {
339
- return (
340
- (this.errorMessage && this.errorMessage.length > 0) || this.errMessage
341
- )
378
+ return this.errorMessage && this.errorMessage.length > 0
342
379
  },
343
380
  dynamicErrorMessage() {
344
- return this.errMessage || this.errorMessage
381
+ return this.errorMessage
345
382
  },
346
383
  },
347
384
  watch: {
@@ -0,0 +1,588 @@
1
+ /* eslint-disable */
2
+ import { mount, Wrapper } from '@vue/test-utils'
3
+ import RCInputText from '@/components/inputs/inputText/index'
4
+ import theme from '@/assets/theme'
5
+
6
+ jest.mock('@/components/icon/iconCache.mjs', () => ({
7
+ // need to mock this due to how jest handles import.meta
8
+ fetchIcon: jest.fn(() => Promise.resolve('mocked-icon-url.svg')),
9
+ }))
10
+
11
+ const wrapper1 = mount(RCInputText, {
12
+ props: {
13
+ placeholder: 'placeholderText',
14
+ value: 'Test value',
15
+ label: 'Test label',
16
+ },
17
+ global: {
18
+ provide: {
19
+ theme,
20
+ },
21
+ },
22
+ })
23
+ const wrapperPassword = mount(RCInputText, {
24
+ props: {
25
+ placeholder: 'placeholderText',
26
+ value: 'Test value',
27
+ label: 'Test label',
28
+ inputType: 'password',
29
+ },
30
+ global: {
31
+ provide: {
32
+ theme,
33
+ },
34
+ },
35
+ })
36
+ describe('RCInputText.vue', () => {
37
+ let consoleWarnSpy
38
+ beforeEach(() => {
39
+ consoleWarnSpy = jest.spyOn(console, 'warn').mockImplementation(() => {})
40
+ })
41
+ afterEach(() => {
42
+ consoleWarnSpy.mockRestore()
43
+ })
44
+ // initial rendering
45
+ it('input is rendered', async () => {
46
+ const inputTextWrapper = wrapper1.find('[data-test-id="input_wrapper"]')
47
+ expect(inputTextWrapper.exists()).toBe(true)
48
+ })
49
+ // event management
50
+ it('input is rendered and emits inputChange when input event is triggered.', async () => {
51
+ const inputElement = wrapper1.find('input')
52
+ await inputElement.setValue('Test Input Value')
53
+ const emittedInputChangeEvent = wrapper1.emitted('input-change')
54
+ expect(emittedInputChangeEvent).toBeTruthy()
55
+ expect(emittedInputChangeEvent).toHaveLength(1) // Check if the event was emitted exactly once
56
+ expect(emittedInputChangeEvent[0]).toEqual(['Test Input Value'])
57
+ })
58
+ it('input emits on-enter-click', async () => {
59
+ const inputElement = wrapper1.find('input')
60
+ await inputElement.trigger('keyup.enter')
61
+ const emittedOnEnterClickEvent = wrapper1.emitted('on-enter-click')
62
+ expect(emittedOnEnterClickEvent).toBeTruthy()
63
+ expect(emittedOnEnterClickEvent).toHaveLength(1) // Check if the event was emitted exactly once
64
+ expect(emittedOnEnterClickEvent[0]).toEqual([]) // Check if the event was emitted exactly once
65
+ })
66
+ it('input emits on-blur', async () => {
67
+ const inputElement = wrapper1.find('input')
68
+ await inputElement.setValue('Test Input Value')
69
+ await inputElement.trigger('blur')
70
+ const emittedOnBlurEvent = wrapper1.emitted('input-blur')
71
+ expect(emittedOnBlurEvent).toBeTruthy()
72
+ expect(emittedOnBlurEvent).toHaveLength(1) // Check if the event was emitted exactly once
73
+ expect(emittedOnBlurEvent[0]).toEqual(['Test Input Value']) // Check if the event was emitted exactly once
74
+ })
75
+ it('input password visibility click trigger input type change', async () => {
76
+ const inputElement = wrapperPassword.find('input')
77
+ const passwordVisibilityIconElement = wrapperPassword.find(
78
+ '[data-test-id="password_visiblity_change_icon"]'
79
+ )
80
+ expect(passwordVisibilityIconElement.exists()).toBe(true)
81
+ await passwordVisibilityIconElement.trigger('click')
82
+ let inputType = inputElement.attributes().type
83
+ expect(inputType).toBe('text')
84
+ await passwordVisibilityIconElement.trigger('click')
85
+ inputType = inputElement.attributes().type
86
+ expect(inputType).toBe('password')
87
+ await passwordVisibilityIconElement.trigger('click')
88
+ inputType = inputElement.attributes().type
89
+ expect(inputType).toBe('text')
90
+ })
91
+ //Test conditional visibility
92
+ it('label visibility check', async () => {
93
+ const wrapper = mount(RCInputText, {
94
+ props: {
95
+ value: 'Test value',
96
+ label: 'Test label',
97
+ },
98
+ global: {
99
+ provide: {
100
+ theme,
101
+ },
102
+ },
103
+ })
104
+ const label = wrapper.find('[data-test-id="label_wrapper"]')
105
+ expect(label.exists()).toBe(true)
106
+ expect(label.text()).toContain('Test label')
107
+ })
108
+ it('label invisibility check', async () => {
109
+ const wrapper = mount(RCInputText, {
110
+ props: {
111
+ value: 'Test value',
112
+ },
113
+ global: {
114
+ provide: {
115
+ theme,
116
+ },
117
+ },
118
+ })
119
+ const label = wrapper.find('[data-test-id="label_wrapper"]')
120
+ expect(label.exists()).toBe(false)
121
+ })
122
+ it('label optional visibility check', async () => {
123
+ const wrapper = mount(RCInputText, {
124
+ props: {
125
+ value: 'Test value',
126
+ label: 'Test label',
127
+ labelOptional: true,
128
+ },
129
+ global: {
130
+ provide: {
131
+ theme,
132
+ },
133
+ },
134
+ })
135
+ const labelOptional = wrapper.find('[data-test-id="label_optional"]')
136
+ expect(labelOptional.exists()).toBe(true)
137
+ })
138
+ it('label optional invisibility check', async () => {
139
+ const wrapper = mount(RCInputText, {
140
+ props: {
141
+ value: 'Test value',
142
+ },
143
+ global: {
144
+ provide: {
145
+ theme,
146
+ },
147
+ },
148
+ })
149
+ const labelOptional = wrapper.find('[data-test-id="label_optional"]')
150
+ expect(labelOptional.exists()).toBe(false)
151
+ })
152
+ it('infoTextMessage visibility check', async () => {
153
+ const wrapper = mount(RCInputText, {
154
+ props: {
155
+ value: 'Test value',
156
+ infoTextMessage: 'infoTextMessage test',
157
+ label: 'Test label',
158
+ },
159
+ global: {
160
+ provide: {
161
+ theme,
162
+ },
163
+ },
164
+ })
165
+ const InfoTextMessage = wrapper.find('[data-test-id="info_text_message"]')
166
+ expect(InfoTextMessage.exists()).toBe(true)
167
+ })
168
+ it('infoTextMessage invibility check', async () => {
169
+ const wrapper = mount(RCInputText, {
170
+ props: {
171
+ value: 'Test value',
172
+ label: 'Test label',
173
+ },
174
+ global: {
175
+ provide: {
176
+ theme,
177
+ },
178
+ },
179
+ })
180
+ const InfoTextMessage = wrapper.find('[data-test-id="info_text_message"]')
181
+ expect(InfoTextMessage.exists()).toBe(false)
182
+ })
183
+ it('error visibility check', async () => {
184
+ const wrapper = mount(RCInputText, {
185
+ props: {
186
+ value: 'Test value',
187
+ isError: true,
188
+ errorMessage: 'Error message test',
189
+ label: 'Test label',
190
+ },
191
+ global: {
192
+ provide: {
193
+ theme,
194
+ },
195
+ },
196
+ })
197
+ const errorWrapper = wrapper.find('[data-test-id="error_wrapper"]')
198
+ const errorMessageWrapper = wrapper.find(
199
+ '[data-test-id="error_message_wrapper"]'
200
+ )
201
+ expect(errorWrapper.exists()).toBe(true)
202
+ expect(errorMessageWrapper.exists()).toBe(true)
203
+ expect(errorMessageWrapper.text()).toContain('Error message test')
204
+ })
205
+ it('error invibility check', async () => {
206
+ const wrapper = mount(RCInputText, {
207
+ props: {
208
+ value: 'Test value',
209
+ label: 'Test label',
210
+ },
211
+ global: {
212
+ provide: {
213
+ theme,
214
+ },
215
+ },
216
+ })
217
+ const errorWrapper = wrapper.find('[data-test-id="error_wrapper"]')
218
+ const errorMessageWrapper = wrapper.find(
219
+ '[data-test-id="error_message_wrapper"]'
220
+ )
221
+ expect(errorWrapper.exists()).toBe(false)
222
+ expect(errorMessageWrapper.exists()).toBe(false)
223
+ })
224
+ //Test that the component handles different prop types correctly and throws appropriate warnings for invalid props.
225
+ it('validation of prop type - placeholder - not String', async () => {
226
+ mount(RCInputText, {
227
+ props: {
228
+ placeholder: 42,
229
+ value: 'value test',
230
+ },
231
+ global: {
232
+ provide: {
233
+ theme,
234
+ },
235
+ },
236
+ })
237
+ expect(consoleWarnSpy).toHaveBeenCalled()
238
+ })
239
+ it('validation of prop type - alignItems - not horizontal or vertical', async () => {
240
+ mount(RCInputText, {
241
+ props: {
242
+ value: 'value test',
243
+ alignItems: 'top',
244
+ },
245
+ global: {
246
+ provide: {
247
+ theme,
248
+ },
249
+ },
250
+ })
251
+ expect(consoleWarnSpy).toHaveBeenCalled()
252
+ })
253
+ it('validation of prop type - isError - not Boolean', async () => {
254
+ mount(RCInputText, {
255
+ props: {
256
+ value: 'value test',
257
+ isError: 'true',
258
+ },
259
+ global: {
260
+ provide: {
261
+ theme,
262
+ },
263
+ },
264
+ })
265
+ expect(consoleWarnSpy).toHaveBeenCalled()
266
+ })
267
+ it('validation of prop type - inputWidth - not String', async () => {
268
+ mount(RCInputText, {
269
+ props: {
270
+ value: 'value test',
271
+ inputWidth: 200,
272
+ },
273
+ global: {
274
+ provide: {
275
+ theme,
276
+ },
277
+ },
278
+ })
279
+ expect(consoleWarnSpy).toHaveBeenCalled()
280
+ })
281
+ it('validation of prop type - inputHeight - not String', async () => {
282
+ mount(RCInputText, {
283
+ props: {
284
+ value: 'value test',
285
+ inputHeight: 200,
286
+ },
287
+ global: {
288
+ provide: {
289
+ theme,
290
+ },
291
+ },
292
+ })
293
+ expect(consoleWarnSpy).toHaveBeenCalled()
294
+ })
295
+ it('validation of prop type - minWidth - not String', async () => {
296
+ mount(RCInputText, {
297
+ props: {
298
+ value: 'value test',
299
+ minWidth: 200,
300
+ },
301
+ global: {
302
+ provide: {
303
+ theme,
304
+ },
305
+ },
306
+ })
307
+ expect(consoleWarnSpy).toHaveBeenCalled()
308
+ })
309
+ it('validation of prop type - value - not String', async () => {
310
+ mount(RCInputText, {
311
+ props: {
312
+ value: 42,
313
+ },
314
+ global: {
315
+ provide: {
316
+ theme,
317
+ },
318
+ },
319
+ })
320
+ expect(consoleWarnSpy).toHaveBeenCalled()
321
+ })
322
+ it('validation of prop type - errorMessage - not String', async () => {
323
+ mount(RCInputText, {
324
+ props: {
325
+ value: 'test value',
326
+ errorMessage: true,
327
+ },
328
+ global: {
329
+ provide: {
330
+ theme,
331
+ },
332
+ },
333
+ })
334
+ expect(consoleWarnSpy).toHaveBeenCalled()
335
+ })
336
+ it('validation of prop type - infoTextMessage - not String', async () => {
337
+ mount(RCInputText, {
338
+ props: {
339
+ value: 'test value',
340
+ infoTextMessage: true,
341
+ },
342
+ global: {
343
+ provide: {
344
+ theme,
345
+ },
346
+ },
347
+ })
348
+ expect(consoleWarnSpy).toHaveBeenCalled()
349
+ })
350
+ it('validation of prop type - infoTextAlign - not String', async () => {
351
+ mount(RCInputText, {
352
+ props: {
353
+ value: 'test value',
354
+ infoTextAlign: true,
355
+ },
356
+ global: {
357
+ provide: {
358
+ theme,
359
+ },
360
+ },
361
+ })
362
+ expect(consoleWarnSpy).toHaveBeenCalled()
363
+ })
364
+ it('validation of prop type - label - not String', async () => {
365
+ mount(RCInputText, {
366
+ props: {
367
+ value: 'test value',
368
+ label: true,
369
+ },
370
+ global: {
371
+ provide: {
372
+ theme,
373
+ },
374
+ },
375
+ })
376
+ expect(consoleWarnSpy).toHaveBeenCalled()
377
+ })
378
+ it('validation of prop type - labelOptional - not Boolean', async () => {
379
+ const wrapper = mount(RCInputText, {
380
+ props: {
381
+ value: 'test value',
382
+ labelOptional: 12,
383
+ label: 'label test',
384
+ },
385
+ global: {
386
+ provide: {
387
+ theme,
388
+ },
389
+ },
390
+ })
391
+ wrapper.vm.$gettext.mockReturnValue('Translated Message')
392
+ expect(consoleWarnSpy).toHaveBeenCalled()
393
+ })
394
+ it('validation of prop type - noBorder - not Boolean', async () => {
395
+ mount(RCInputText, {
396
+ props: {
397
+ value: 'test value',
398
+ noBorder: 1,
399
+ },
400
+ global: {
401
+ provide: {
402
+ theme,
403
+ },
404
+ },
405
+ })
406
+ expect(consoleWarnSpy).toHaveBeenCalled()
407
+ })
408
+ it('validation of prop type - disabled - not Boolean', async () => {
409
+ mount(RCInputText, {
410
+ props: {
411
+ disabled: 'false',
412
+ value: 'value test',
413
+ },
414
+ global: {
415
+ provide: {
416
+ theme,
417
+ },
418
+ },
419
+ })
420
+ expect(consoleWarnSpy).toHaveBeenCalled()
421
+ })
422
+ it('validation of prop type - fontSize - not String', async () => {
423
+ mount(RCInputText, {
424
+ props: {
425
+ fontSize: true,
426
+ value: 'value test',
427
+ },
428
+ global: {
429
+ provide: {
430
+ theme,
431
+ },
432
+ },
433
+ })
434
+ expect(consoleWarnSpy).toHaveBeenCalled()
435
+ })
436
+ it('validation of prop type - inputType - not String', async () => {
437
+ mount(RCInputText, {
438
+ props: {
439
+ inputType: true,
440
+ value: 'value test',
441
+ },
442
+ global: {
443
+ provide: {
444
+ theme,
445
+ },
446
+ },
447
+ })
448
+ expect(consoleWarnSpy).toHaveBeenCalled()
449
+ })
450
+ it('validation of prop type - labelFontColor - not String', async () => {
451
+ mount(RCInputText, {
452
+ props: {
453
+ labelFontColor: true,
454
+ value: 'value test',
455
+ label: 'label text',
456
+ },
457
+ global: {
458
+ provide: {
459
+ theme,
460
+ },
461
+ },
462
+ })
463
+ expect(consoleWarnSpy).toHaveBeenCalled()
464
+ })
465
+ it('validation of prop type - backgroundColor - not String', async () => {
466
+ mount(RCInputText, {
467
+ props: {
468
+ backgroundColor: true,
469
+ value: 'value test',
470
+ },
471
+ global: {
472
+ provide: {
473
+ theme,
474
+ },
475
+ },
476
+ })
477
+ expect(consoleWarnSpy).toHaveBeenCalled()
478
+ })
479
+ it('validation of prop type - disabledBackgroundColor - not String', async () => {
480
+ mount(RCInputText, {
481
+ props: {
482
+ disabledBackgroundColor: true,
483
+ value: 'value test',
484
+ },
485
+ global: {
486
+ provide: {
487
+ theme,
488
+ },
489
+ },
490
+ })
491
+ expect(consoleWarnSpy).toHaveBeenCalled()
492
+ })
493
+ it('validation of prop type - fontColor - not String', async () => {
494
+ mount(RCInputText, {
495
+ props: {
496
+ fontColor: true,
497
+ value: 'value test',
498
+ },
499
+ global: {
500
+ provide: {
501
+ theme,
502
+ },
503
+ },
504
+ })
505
+ expect(consoleWarnSpy).toHaveBeenCalled()
506
+ })
507
+ it('validation of prop type - hasFocus - not Boolean', async () => {
508
+ mount(RCInputText, {
509
+ props: {
510
+ hasFocus: 'true',
511
+ value: 'value test',
512
+ },
513
+ global: {
514
+ provide: {
515
+ theme,
516
+ },
517
+ },
518
+ })
519
+ expect(consoleWarnSpy).toHaveBeenCalled()
520
+ })
521
+ it('validation of prop type - borderColor - not String', async () => {
522
+ mount(RCInputText, {
523
+ props: {
524
+ borderColor: 42,
525
+ value: 'value test',
526
+ },
527
+ global: {
528
+ provide: {
529
+ theme,
530
+ },
531
+ },
532
+ })
533
+ expect(consoleWarnSpy).toHaveBeenCalled()
534
+ })
535
+ it('validation of prop type - labelDataId - not String', async () => {
536
+ mount(RCInputText, {
537
+ props: {
538
+ labelDataId: 42,
539
+ value: 'value test',
540
+ },
541
+ global: {
542
+ provide: {
543
+ theme,
544
+ },
545
+ },
546
+ })
547
+ expect(consoleWarnSpy).toHaveBeenCalled()
548
+ })
549
+ it('validation of prop type - inputDataId - not String', async () => {
550
+ mount(RCInputText, {
551
+ props: {
552
+ inputDataId: 42,
553
+ value: 'value test',
554
+ },
555
+ global: {
556
+ provide: {
557
+ theme,
558
+ },
559
+ },
560
+ })
561
+ expect(consoleWarnSpy).toHaveBeenCalled()
562
+ })
563
+ //Prop Updates: Verify that the component updates correctly when props change, reflecting new values in the rendered output.
564
+ it('update of prop hasFocus', async () => {
565
+ const wrapper = mount(RCInputText, {
566
+ props: {
567
+ value: 'value test',
568
+ hasFocus: false,
569
+ },
570
+ global: {
571
+ provide: {
572
+ theme,
573
+ },
574
+ },
575
+ })
576
+ const inputElement = wrapper.find('input').element
577
+ jest.spyOn(inputElement, 'focus').mockImplementation(() => {
578
+ // Simulate that the input element is now the focused element
579
+ Object.defineProperty(document, 'activeElement', {
580
+ value: inputElement,
581
+ configurable: true,
582
+ })
583
+ })
584
+ await wrapper.setProps({ hasFocus: true })
585
+ await wrapper.vm.$nextTick()
586
+ expect(document.activeElement).toBe(wrapper.find('input').element)
587
+ })
588
+ })
@@ -1,40 +1,67 @@
1
+ import { useArgs } from '@storybook/preview-api'
2
+ import { action } from '@storybook/addon-actions'
3
+ import defaultSearchInputProps from './defaultProps'
1
4
  import SearchInput from './index.vue'
2
5
 
3
6
  export default {
4
7
  title: 'SearchInput',
5
8
  component: SearchInput,
6
- // argTypes: {},
9
+ tags: ['autodocs'],
7
10
  }
8
11
 
9
- const Template = (args, { argTypes }) => ({
10
- // Components used in your story `template` are defined in the `components` object
11
- components: { SearchInput },
12
- // The story's `args` need to be mapped into the template through the `setup()` method
13
- props: Object.keys(argTypes),
14
- template: '<search-input v-bind="$props" />',
15
-
16
- // import SearchInput from "@eturnity/eturnity_reusable_components/src/components/inputs/searchInput"
17
- // To use:
18
- // <search-input
19
- // placeholder="Company name"
20
- // :value="companyName"
21
- // :disabled="true"
22
- // inputWidth="250px"
23
- // />
24
- })
12
+ // To use:
13
+
14
+ const defaultProps = defaultSearchInputProps
15
+
16
+ const Template = (args) => {
17
+ const [currentArgs, updateArgs] = useArgs()
18
+
19
+ const handleInputChange = ($event) => {
20
+ action('on-change')($event)
21
+ updateArgs({ value: $event })
22
+ }
23
+
24
+ return {
25
+ components: { SearchInput },
26
+ setup() {
27
+ return { args: currentArgs, handleInputChange }
28
+ },
29
+ template: `
30
+ <SearchInput
31
+ v-bind="args"
32
+ @on-change="handleInputChange"
33
+ />
34
+ `,
35
+ }
36
+ }
25
37
 
26
38
  export const Default = Template.bind({})
27
39
  Default.args = {
28
- placeholder: 'Search...',
29
- disabled: false,
30
- value: '',
31
- inputWidth: '250px',
40
+ ...defaultProps,
41
+ }
42
+
43
+ export const Placeholder = Template.bind({})
44
+ Placeholder.args = {
45
+ ...defaultProps,
46
+ placeholder: 'Search... ',
32
47
  }
33
48
 
34
49
  export const Disabled = Template.bind({})
35
50
  Disabled.args = {
36
- placeholder: 'Search...',
51
+ ...defaultProps,
37
52
  disabled: true,
38
- value: '',
39
- inputWidth: '250px',
40
53
  }
54
+
55
+ export const StyledIcon = Template.bind({})
56
+ StyledIcon.args = {
57
+ ...defaultProps,
58
+ 'icon-color': 'red',
59
+ 'icon-position': 'left',
60
+ }
61
+
62
+ export const Sizes = Template.bind({})
63
+ Sizes.args = {
64
+ ...defaultProps,
65
+ 'input-width': '250px',
66
+ 'is-filter': true,
67
+ }
@@ -0,0 +1,12 @@
1
+ const defaultSearchInputProps = {
2
+ dataId: 'search_input_id',
3
+ disabled: false, //
4
+ hasFocus: false, //
5
+ iconColor: 'black',
6
+ iconPosition: 'right',
7
+ inputWidth: null, //
8
+ isFilter: false,
9
+ placeholder: '',
10
+ value: '',
11
+ }
12
+ export default defaultSearchInputProps
@@ -22,15 +22,16 @@
22
22
  // import SearchInput from "@eturnity/eturnity_reusable_components/src/components/inputs/searchInput"
23
23
  // To use:
24
24
  // <search-input
25
- // placeholder="Company name"
26
- // :value="companyName"
25
+ // data-id='search_input_id'
27
26
  // :disabled="true"
28
- // inputWidth="250px"
27
+ // :has-focus="true"
28
+ // icon-color="grey2" // colors only from theme
29
+ // icon-position="left"
30
+ // input-width="250px"
31
+ // :is-filter="true" // to set the height at 30px
32
+ // placeholder="Search by company name"
33
+ // :value="companyName"
29
34
  // @on-change="function($event)"
30
- // :isFilter="true" // to set the height at 30px
31
- // data-id="test-data-id"
32
- // iconPosition="left"
33
- // iconColor="grey2"
34
35
  // />
35
36
  import styled from 'vue3-styled-components'
36
37
  import SearchIconSvg from '../../../assets/icons/search_icon_black.svg'
@@ -94,31 +95,38 @@
94
95
  },
95
96
  props: {
96
97
  value: {
98
+ type: [String, Number],
97
99
  required: true,
98
100
  },
99
101
  disabled: {
100
102
  required: false,
101
103
  default: false,
104
+ type: Boolean,
102
105
  },
103
106
  placeholder: {
104
107
  required: false,
105
108
  default: '',
109
+ type: String,
106
110
  },
107
111
  inputWidth: {
108
112
  required: false,
109
113
  default: null,
114
+ type: String,
110
115
  },
111
116
  isFilter: {
112
117
  required: false,
113
118
  default: false,
119
+ type: Boolean,
114
120
  },
115
121
  hasFocus: {
116
122
  required: false,
117
123
  default: false,
124
+ type: Boolean,
118
125
  },
119
126
  dataId: {
120
127
  required: false,
121
128
  default: '',
129
+ type: [String, Number],
122
130
  },
123
131
  iconPosition: {
124
132
  type: String,
@@ -0,0 +1,65 @@
1
+ import { mount } from '@vue/test-utils'
2
+ import SearchInput from '@/components/inputs/searchInput'
3
+ import defaultSearchInputProps from './defaultProps'
4
+ import theme from '@/assets/theme'
5
+
6
+ describe('SearchInput.vue', () => {
7
+ let searchInput
8
+ let searchInputWrapper
9
+
10
+ beforeEach(() => {
11
+ searchInput = mount(SearchInput, {
12
+ props: defaultSearchInputProps,
13
+ global: {
14
+ provide: {
15
+ theme,
16
+ },
17
+ },
18
+ })
19
+
20
+ const defaultDataId = searchInput.props('dataId')
21
+ searchInputWrapper = searchInput.find(`[data-id="${defaultDataId}"]`)
22
+ })
23
+
24
+ it('Search input is rendered and displays the correct placeholder', async () => {
25
+ // Check that Search input has been rendered
26
+ expect(searchInputWrapper.exists()).toBe(true)
27
+
28
+ // Set the placeholder
29
+ const placeholderText = 'Search by company name'
30
+ await searchInput.setProps({ placeholder: placeholderText })
31
+ await searchInput.vm.$nextTick()
32
+
33
+ // Check that the input displays the correct placeholder
34
+ expect(searchInputWrapper.attributes('placeholder')).toBe(placeholderText)
35
+ })
36
+
37
+ it('Search input emits correct payload on change', async () => {
38
+ // Simulate user input
39
+ const inputValue = 'test input'
40
+ await searchInputWrapper.setValue(inputValue)
41
+
42
+ // Check that the component emitted the 'on-change' event with correct payload
43
+ expect(searchInput.emitted('on-change')).toBeTruthy()
44
+ expect(searchInput.emitted('on-change')[0]).toEqual([inputValue])
45
+ })
46
+
47
+ it('test disabled prop', async () => {
48
+ await searchInput.setProps({ disabled: true })
49
+ await searchInput.vm.$nextTick()
50
+
51
+ expect(searchInputWrapper.attributes()).toHaveProperty('disabled')
52
+ expect(searchInputWrapper.element.disabled).toBe(true)
53
+ })
54
+
55
+ it('test hasFocus prop', async () => {
56
+ // Spy on the focus method
57
+ const focusSpy = jest.spyOn(searchInputWrapper.element, 'focus')
58
+
59
+ await searchInput.setProps({ hasFocus: true })
60
+ await searchInput.vm.$nextTick()
61
+
62
+ // Check that the focus method was called
63
+ expect(focusSpy).toHaveBeenCalled()
64
+ })
65
+ })