@eturnity/eturnity_reusable_components 9.28.0 → 9.28.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/package.json +1 -1
- package/src/components/dropdown/Dropdown.stories.js +9 -0
- package/src/components/dropdown/dropdown.spec.js +99 -26
- package/src/components/dropdown/index.vue +2 -0
- package/src/components/inputs/inputNumber/InputNumber.stories.js +87 -103
- package/src/components/inputs/inputNumber/inputNumber.spec.js +133 -0
- package/src/components/inputs/inputNumberQuestion/inputNumberQuestion.spec.js +103 -0
- package/src/components/inputs/inputNumberQuestion/inputNumberQuestion.stories.js +31 -10
- package/src/components/inputs/toggle/Toggle.stories.js +73 -34
- package/src/components/inputs/toggle/toggle.spec.js +121 -82
- package/src/components/label/label.spec.js +55 -0
- package/src/components/label/label.stories.js +36 -0
- package/src/components/markerItem/markerItem.spec.js +46 -0
- package/src/components/markerItem/markerItem.stories.js +7 -0
- package/src/components/modals/modal/modal.stories.js +17 -7
- package/src/components/navigationTabs/navigationTabs.spec.js +95 -0
- package/src/components/sideMenu/sideMenu.spec.js +109 -0
- package/src/components/sideMenu/sideMenu.stories.js +43 -0
|
@@ -1,6 +1,18 @@
|
|
|
1
1
|
import { ref } from 'vue'
|
|
2
2
|
import InputNumberQuestion from './index.vue'
|
|
3
|
-
|
|
3
|
+
|
|
4
|
+
// import InputNumberQuestion from "@eturnity/eturnity_reusable_components/src/components/inputs/inputNumberQuestion"
|
|
5
|
+
// How to use:
|
|
6
|
+
// <input-number-question
|
|
7
|
+
// :question="question" // required — { number_format_precision, number_min_allowed, number_max_allowed, unit_short_name }
|
|
8
|
+
// :value="inputValue" // required
|
|
9
|
+
// placeholder="Enter distance"
|
|
10
|
+
// inputWidth="150px" // default 100%
|
|
11
|
+
// :isError="false"
|
|
12
|
+
// errorMessage="Enter a number between 1 and 10"
|
|
13
|
+
// @input-change="onInputChange($event)"
|
|
14
|
+
// @on-enter-click="onInputSubmit()"
|
|
15
|
+
// />
|
|
4
16
|
|
|
5
17
|
const questionWithUnit = {
|
|
6
18
|
number_format_precision: 2,
|
|
@@ -23,6 +35,22 @@ export default {
|
|
|
23
35
|
parameters: {
|
|
24
36
|
layout: 'centered',
|
|
25
37
|
},
|
|
38
|
+
argTypes: {
|
|
39
|
+
question: {
|
|
40
|
+
description:
|
|
41
|
+
'Required. Drives formatting: number_format_precision, ' +
|
|
42
|
+
'number_min_allowed, number_max_allowed, unit_short_name.',
|
|
43
|
+
},
|
|
44
|
+
value: { description: 'Current value (required). String or number.' },
|
|
45
|
+
placeholder: { description: 'Placeholder shown when empty' },
|
|
46
|
+
inputWidth: { description: 'Width of the input, defaults to 100%' },
|
|
47
|
+
isError: { description: 'Error state styling', control: 'boolean' },
|
|
48
|
+
errorMessage: { description: 'Message shown while isError is true' },
|
|
49
|
+
clearInput: {
|
|
50
|
+
description: 'When flipped to true, clears the displayed text',
|
|
51
|
+
control: 'boolean',
|
|
52
|
+
},
|
|
53
|
+
},
|
|
26
54
|
}
|
|
27
55
|
|
|
28
56
|
const Template = (args) => ({
|
|
@@ -32,21 +60,14 @@ const Template = (args) => ({
|
|
|
32
60
|
return { args, val }
|
|
33
61
|
},
|
|
34
62
|
template: `
|
|
35
|
-
<div
|
|
63
|
+
<div style="min-width: 280px; padding: 16px;">
|
|
36
64
|
<InputNumberQuestion
|
|
37
|
-
|
|
65
|
+
v-bind="args"
|
|
38
66
|
:value="val"
|
|
39
|
-
:placeholder="args.placeholder"
|
|
40
|
-
:is-error="args.isError"
|
|
41
|
-
:input-width="args.inputWidth"
|
|
42
|
-
:error-message="args.errorMessage"
|
|
43
67
|
@input-change="val = $event"
|
|
44
68
|
/>
|
|
45
69
|
</div>
|
|
46
70
|
`,
|
|
47
|
-
provide: {
|
|
48
|
-
theme,
|
|
49
|
-
},
|
|
50
71
|
})
|
|
51
72
|
|
|
52
73
|
export const WithUnit = Template.bind({})
|
|
@@ -1,77 +1,116 @@
|
|
|
1
|
+
import { ref } from 'vue'
|
|
1
2
|
import Toggle from './index.vue'
|
|
3
|
+
import theme from '@/assets/theme'
|
|
4
|
+
|
|
5
|
+
// import Toggle from "@eturnity/eturnity_reusable_components/src/components/inputs/toggle"
|
|
6
|
+
// To use:
|
|
7
|
+
// <toggle
|
|
8
|
+
// @on-toggle-change="onInputChange($event)"
|
|
9
|
+
// :isChecked="toggleValue" // Boolean
|
|
10
|
+
// label="My Label Text"
|
|
11
|
+
// toggleColor="red"
|
|
12
|
+
// size="small" // small, medium
|
|
13
|
+
// backgroundColor="blue"
|
|
14
|
+
// labelAlign="right"
|
|
15
|
+
// fontColor="black"
|
|
16
|
+
// :disabled="true"
|
|
17
|
+
// infoTextMessage="My info message"
|
|
18
|
+
// />
|
|
2
19
|
|
|
3
20
|
export default {
|
|
4
21
|
title: 'Components/Inputs/Toggle',
|
|
5
22
|
component: Toggle,
|
|
6
|
-
|
|
23
|
+
tags: ['autodocs'],
|
|
24
|
+
parameters: {
|
|
25
|
+
layout: 'centered',
|
|
26
|
+
},
|
|
27
|
+
argTypes: {
|
|
28
|
+
isChecked: { control: 'boolean' },
|
|
29
|
+
label: { control: 'text' },
|
|
30
|
+
size: { control: 'select', options: ['small', 'medium'] },
|
|
31
|
+
labelAlign: { control: 'select', options: ['left', 'right'] },
|
|
32
|
+
toggleColor: { control: 'color' },
|
|
33
|
+
backgroundColor: { control: 'color' },
|
|
34
|
+
fontColor: { control: 'color' },
|
|
35
|
+
disabled: { control: 'boolean' },
|
|
36
|
+
isRequiredLabel: { control: 'boolean' },
|
|
37
|
+
infoTextMessage: { control: 'text' },
|
|
38
|
+
},
|
|
7
39
|
}
|
|
8
40
|
|
|
9
|
-
const Template = (args
|
|
10
|
-
// Components used in your story `template` are defined in the `components` object
|
|
41
|
+
const Template = (args) => ({
|
|
11
42
|
components: { Toggle },
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
|
|
43
|
+
setup() {
|
|
44
|
+
const isChecked = ref(args.isChecked)
|
|
45
|
+
return { args, isChecked }
|
|
46
|
+
},
|
|
47
|
+
template: `
|
|
48
|
+
<div data-test-id="toggle-story" style="padding: 16px; min-width: 240px;">
|
|
49
|
+
<Toggle
|
|
50
|
+
v-bind="args"
|
|
51
|
+
:isChecked="isChecked"
|
|
52
|
+
@on-toggle-change="isChecked = $event"
|
|
53
|
+
/>
|
|
54
|
+
<p style="margin-top: 12px; font-size: 12px; color: #666;">isChecked: {{ isChecked }}</p>
|
|
55
|
+
</div>
|
|
56
|
+
`,
|
|
57
|
+
provide: {
|
|
58
|
+
theme,
|
|
59
|
+
},
|
|
29
60
|
})
|
|
30
61
|
|
|
31
62
|
export const Default = Template.bind({})
|
|
32
63
|
Default.args = {
|
|
33
64
|
isChecked: true,
|
|
34
|
-
size: 'small',
|
|
65
|
+
size: 'small',
|
|
35
66
|
disabled: false,
|
|
36
67
|
}
|
|
37
68
|
|
|
38
69
|
export const Medium = Template.bind({})
|
|
39
70
|
Medium.args = {
|
|
40
|
-
|
|
41
|
-
size: 'medium',
|
|
42
|
-
disabled: false,
|
|
71
|
+
...Default.args,
|
|
72
|
+
size: 'medium',
|
|
43
73
|
}
|
|
44
74
|
|
|
45
75
|
export const CustomColor = Template.bind({})
|
|
46
76
|
CustomColor.args = {
|
|
47
|
-
|
|
48
|
-
size: 'small', // "small" or "medium"
|
|
49
|
-
disabled: false,
|
|
77
|
+
...Default.args,
|
|
50
78
|
toggleColor: 'red',
|
|
51
79
|
backgroundColor: 'blue',
|
|
52
80
|
}
|
|
53
81
|
|
|
54
82
|
export const LabelLeft = Template.bind({})
|
|
55
83
|
LabelLeft.args = {
|
|
56
|
-
|
|
57
|
-
size: 'small', // "small" or "medium"
|
|
84
|
+
...Default.args,
|
|
58
85
|
label: 'My Label Text',
|
|
59
|
-
disabled: false,
|
|
60
86
|
labelAlign: 'left',
|
|
61
87
|
}
|
|
62
88
|
|
|
63
89
|
export const LabelRight = Template.bind({})
|
|
64
90
|
LabelRight.args = {
|
|
65
|
-
|
|
66
|
-
size: 'small', // "small" or "medium"
|
|
91
|
+
...Default.args,
|
|
67
92
|
label: 'My Label Text',
|
|
68
|
-
disabled: false,
|
|
69
93
|
labelAlign: 'right',
|
|
70
94
|
}
|
|
71
95
|
|
|
96
|
+
export const WithInfoText = Template.bind({})
|
|
97
|
+
WithInfoText.args = {
|
|
98
|
+
...Default.args,
|
|
99
|
+
label: 'My Label Text',
|
|
100
|
+
infoTextMessage: 'Applies to this location only.',
|
|
101
|
+
}
|
|
102
|
+
|
|
103
|
+
export const Required = Template.bind({})
|
|
104
|
+
Required.args = {
|
|
105
|
+
...Default.args,
|
|
106
|
+
label: 'My Label Text',
|
|
107
|
+
labelAlign: 'left',
|
|
108
|
+
isRequiredLabel: true,
|
|
109
|
+
}
|
|
110
|
+
|
|
72
111
|
export const Disabled = Template.bind({})
|
|
73
112
|
Disabled.args = {
|
|
113
|
+
...Default.args,
|
|
74
114
|
isChecked: false,
|
|
75
|
-
size: 'small', // "small" or "medium"
|
|
76
115
|
disabled: true,
|
|
77
116
|
}
|
|
@@ -1,102 +1,141 @@
|
|
|
1
1
|
/* eslint-disable */
|
|
2
2
|
import { mount } from '@vue/test-utils'
|
|
3
3
|
import RCToggle from '@/components/inputs/toggle'
|
|
4
|
-
|
|
4
|
+
|
|
5
|
+
// `theme` and `$gettext` are provided globally by jest.setup.js, so specs do
|
|
6
|
+
// not need to re-provide them. See the canonical example at
|
|
7
|
+
// src/components/buttons/closeButton/closeButton.spec.js.
|
|
5
8
|
|
|
6
9
|
jest.mock('@/components/icon/iconCache.mjs', () => ({
|
|
7
10
|
// need to mock this due to how jest handles import.meta
|
|
8
11
|
fetchIcon: jest.fn(() => Promise.resolve('mocked-icon-url.svg')),
|
|
9
12
|
}))
|
|
10
13
|
|
|
11
|
-
describe('RCToggle
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
props: { isChecked: true, label: 'Test label', disabled: false },
|
|
15
|
-
global: {
|
|
16
|
-
provide: {
|
|
17
|
-
theme,
|
|
18
|
-
},
|
|
19
|
-
},
|
|
20
|
-
})
|
|
21
|
-
const toggleWrapper = wrapper.find('[data-test-id="toggle_wrapper"]')
|
|
14
|
+
describe('RCToggle', () => {
|
|
15
|
+
const mountToggle = (props = {}) =>
|
|
16
|
+
mount(RCToggle, { props: { isChecked: false, ...props } })
|
|
22
17
|
|
|
23
|
-
|
|
18
|
+
it('renders the toggle and reflects the checked state', () => {
|
|
19
|
+
const wrapper = mountToggle({ isChecked: true })
|
|
20
|
+
const toggleWrapper = wrapper.find('[data-test-id="toggle_wrapper"]')
|
|
24
21
|
expect(toggleWrapper.exists()).toBe(true)
|
|
25
22
|
expect(toggleWrapper.attributes('checked')).toBe('true')
|
|
23
|
+
})
|
|
24
|
+
|
|
25
|
+
it('reflects the unchecked state', () => {
|
|
26
|
+
const wrapper = mountToggle({ isChecked: false })
|
|
27
|
+
const toggleWrapper = wrapper.find('[data-test-id="toggle_wrapper"]')
|
|
28
|
+
expect(toggleWrapper.attributes('checked')).toBe('false')
|
|
29
|
+
})
|
|
26
30
|
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
|
|
31
|
+
it('emits on-toggle-change with the negated value when clicked', async () => {
|
|
32
|
+
const wrapper = mountToggle({ isChecked: true })
|
|
33
|
+
await wrapper.find('[data-test-id="page_wrapper"]').trigger('click')
|
|
30
34
|
|
|
31
|
-
|
|
32
|
-
expect(
|
|
35
|
+
const emitted = wrapper.emitted('on-toggle-change')
|
|
36
|
+
expect(emitted).toHaveLength(1)
|
|
37
|
+
expect(emitted[0]).toEqual([false])
|
|
38
|
+
})
|
|
33
39
|
|
|
34
|
-
|
|
40
|
+
it('emits on-toggle-change when the space key is pressed', async () => {
|
|
41
|
+
const wrapper = mountToggle({ isChecked: false })
|
|
42
|
+
await wrapper
|
|
43
|
+
.find('[data-test-id="toggle_wrapper"]')
|
|
44
|
+
.trigger('keydown.space')
|
|
45
|
+
|
|
46
|
+
const emitted = wrapper.emitted('on-toggle-change')
|
|
47
|
+
expect(emitted).toHaveLength(1)
|
|
48
|
+
expect(emitted[0]).toEqual([true])
|
|
49
|
+
})
|
|
50
|
+
|
|
51
|
+
it('does not emit when disabled and clicked', async () => {
|
|
52
|
+
const wrapper = mountToggle({ isChecked: false, disabled: true })
|
|
53
|
+
await wrapper.find('[data-test-id="page_wrapper"]').trigger('click')
|
|
54
|
+
|
|
55
|
+
expect(wrapper.emitted('on-toggle-change')).toBeUndefined()
|
|
56
|
+
})
|
|
57
|
+
|
|
58
|
+
it('toggles back and forth across successive clicks', async () => {
|
|
59
|
+
const wrapper = mountToggle({ isChecked: false })
|
|
35
60
|
const pageWrapper = wrapper.find('[data-test-id="page_wrapper"]')
|
|
61
|
+
|
|
36
62
|
await pageWrapper.trigger('click')
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
|
|
40
|
-
|
|
41
|
-
|
|
42
|
-
|
|
43
|
-
expect(
|
|
44
|
-
|
|
45
|
-
|
|
46
|
-
|
|
47
|
-
|
|
48
|
-
|
|
49
|
-
|
|
50
|
-
|
|
51
|
-
|
|
52
|
-
|
|
53
|
-
|
|
54
|
-
|
|
55
|
-
|
|
56
|
-
|
|
57
|
-
|
|
58
|
-
|
|
59
|
-
|
|
60
|
-
|
|
61
|
-
|
|
62
|
-
|
|
63
|
-
|
|
64
|
-
|
|
65
|
-
|
|
66
|
-
|
|
67
|
-
|
|
68
|
-
|
|
69
|
-
|
|
70
|
-
|
|
71
|
-
|
|
72
|
-
|
|
73
|
-
|
|
74
|
-
|
|
63
|
+
await wrapper.setProps({ isChecked: true })
|
|
64
|
+
await pageWrapper.trigger('click')
|
|
65
|
+
await wrapper.setProps({ isChecked: false })
|
|
66
|
+
await pageWrapper.trigger('click')
|
|
67
|
+
|
|
68
|
+
const emitted = wrapper.emitted('on-toggle-change')
|
|
69
|
+
expect(emitted).toHaveLength(3)
|
|
70
|
+
expect(emitted[0]).toEqual([true])
|
|
71
|
+
expect(emitted[1]).toEqual([false])
|
|
72
|
+
expect(emitted[2]).toEqual([true])
|
|
73
|
+
})
|
|
74
|
+
|
|
75
|
+
it('renders no label container when no label is provided', () => {
|
|
76
|
+
const wrapper = mountToggle()
|
|
77
|
+
expect(wrapper.find('[data-test-id="label_left_container"]').exists()).toBe(
|
|
78
|
+
false
|
|
79
|
+
)
|
|
80
|
+
expect(wrapper.find('[data-test-id="label_right_container"]').exists()).toBe(
|
|
81
|
+
false
|
|
82
|
+
)
|
|
83
|
+
})
|
|
84
|
+
|
|
85
|
+
it('renders the label on the right by default', () => {
|
|
86
|
+
const wrapper = mountToggle({ label: 'My Label' })
|
|
87
|
+
expect(wrapper.find('[data-test-id="label_right_container"]').exists()).toBe(
|
|
88
|
+
true
|
|
89
|
+
)
|
|
90
|
+
expect(wrapper.find('[data-test-id="label_left_container"]').exists()).toBe(
|
|
91
|
+
false
|
|
92
|
+
)
|
|
93
|
+
expect(wrapper.text()).toContain('My Label')
|
|
94
|
+
})
|
|
95
|
+
|
|
96
|
+
it('renders the label on the left when labelAlign is "left"', () => {
|
|
97
|
+
const wrapper = mountToggle({ label: 'My Label', labelAlign: 'left' })
|
|
98
|
+
expect(wrapper.find('[data-test-id="label_left_container"]').exists()).toBe(
|
|
99
|
+
true
|
|
100
|
+
)
|
|
101
|
+
expect(wrapper.find('[data-test-id="label_right_container"]').exists()).toBe(
|
|
102
|
+
false
|
|
103
|
+
)
|
|
104
|
+
})
|
|
105
|
+
|
|
106
|
+
it('renders the info text only when infoTextMessage is provided', () => {
|
|
107
|
+
expect(
|
|
108
|
+
mountToggle({ label: 'My Label', labelAlign: 'left' })
|
|
109
|
+
.find('[data-test-id="infoText_container"]')
|
|
110
|
+
.exists()
|
|
111
|
+
).toBe(false)
|
|
112
|
+
|
|
113
|
+
expect(
|
|
114
|
+
mountToggle({
|
|
115
|
+
label: 'My Label',
|
|
116
|
+
labelAlign: 'left',
|
|
117
|
+
infoTextMessage: 'Some info',
|
|
75
118
|
})
|
|
76
|
-
|
|
77
|
-
|
|
78
|
-
|
|
79
|
-
|
|
80
|
-
|
|
81
|
-
|
|
82
|
-
|
|
83
|
-
|
|
84
|
-
|
|
85
|
-
|
|
86
|
-
expect(emittedEvent[0]).toEqual([true]) // Check the payload of the first click
|
|
87
|
-
await wrapper.setProps({ isChecked: true }) // manually update the props
|
|
88
|
-
|
|
89
|
-
// Trigger click again and check events
|
|
90
|
-
await pageWrapper.trigger('click')
|
|
91
|
-
emittedEvent = wrapper.emitted('on-toggle-change')
|
|
92
|
-
expect(emittedEvent).toHaveLength(2) // Ensure that the event count has increased
|
|
93
|
-
expect(emittedEvent[1]).toEqual([false]) // Check the payload of the second click
|
|
94
|
-
await wrapper.setProps({ isChecked: false }) // manually update the props
|
|
95
|
-
|
|
96
|
-
// Trigger click again and check events
|
|
97
|
-
await pageWrapper.trigger('click')
|
|
98
|
-
emittedEvent = wrapper.emitted('on-toggle-change')
|
|
99
|
-
expect(emittedEvent).toHaveLength(3) // Ensure that the event count has increased
|
|
100
|
-
expect(emittedEvent[2]).toEqual([true]) // Check the payload of the third click
|
|
119
|
+
.find('[data-test-id="infoText_container"]')
|
|
120
|
+
.exists()
|
|
121
|
+
).toBe(true)
|
|
122
|
+
})
|
|
123
|
+
|
|
124
|
+
it('renders the required star only when isRequiredLabel is true', () => {
|
|
125
|
+
const withStar = mountToggle({
|
|
126
|
+
label: 'My Label',
|
|
127
|
+
labelAlign: 'left',
|
|
128
|
+
isRequiredLabel: true,
|
|
101
129
|
})
|
|
130
|
+
expect(withStar.text()).toContain('*')
|
|
131
|
+
|
|
132
|
+
const withoutStar = mountToggle({ label: 'My Label', labelAlign: 'left' })
|
|
133
|
+
expect(withoutStar.text()).not.toContain('*')
|
|
134
|
+
})
|
|
135
|
+
|
|
136
|
+
it('exposes dataId and dataQaId as data attributes', () => {
|
|
137
|
+
const wrapper = mountToggle({ dataId: 'my_toggle', dataQaId: 'qa_toggle' })
|
|
138
|
+
expect(wrapper.find('[data-id="my_toggle"]').exists()).toBe(true)
|
|
139
|
+
expect(wrapper.find('[data-qa-id="qa_toggle"]').exists()).toBe(true)
|
|
140
|
+
})
|
|
102
141
|
})
|
|
@@ -0,0 +1,55 @@
|
|
|
1
|
+
/* eslint-disable */
|
|
2
|
+
import { mount } from '@vue/test-utils'
|
|
3
|
+
import Label from '@/components/label'
|
|
4
|
+
|
|
5
|
+
// `theme` and `$gettext` are provided globally by jest.setup.js, so specs do
|
|
6
|
+
// not need to re-provide them. See the canonical example at
|
|
7
|
+
// src/components/buttons/closeButton/closeButton.spec.js.
|
|
8
|
+
|
|
9
|
+
jest.mock('@/components/icon/iconCache.mjs', () => ({
|
|
10
|
+
// need to mock this due to how jest handles import.meta
|
|
11
|
+
fetchIcon: jest.fn(() => Promise.resolve('mocked-icon-url.svg')),
|
|
12
|
+
}))
|
|
13
|
+
|
|
14
|
+
describe('Label', () => {
|
|
15
|
+
const mountLabel = (props = {}, slot = 'My label') =>
|
|
16
|
+
mount(Label, { props, slots: { default: slot } })
|
|
17
|
+
|
|
18
|
+
it('renders the default slot content', () => {
|
|
19
|
+
const wrapper = mountLabel({}, 'Project name')
|
|
20
|
+
expect(wrapper.text()).toContain('Project name')
|
|
21
|
+
})
|
|
22
|
+
|
|
23
|
+
it('renders the required star only when isRequiredLabel is true', () => {
|
|
24
|
+
expect(mountLabel({ isRequiredLabel: true }).text()).toContain('*')
|
|
25
|
+
expect(mountLabel({ isRequiredLabel: false }).text()).not.toContain('*')
|
|
26
|
+
})
|
|
27
|
+
|
|
28
|
+
it('renders the optional label only when labelOptional is true', () => {
|
|
29
|
+
expect(mountLabel({ labelOptional: true }).text()).toContain('(optional)')
|
|
30
|
+
expect(mountLabel({ labelOptional: false }).text()).not.toContain(
|
|
31
|
+
'(optional)'
|
|
32
|
+
)
|
|
33
|
+
})
|
|
34
|
+
|
|
35
|
+
it('renders the info text only when infoTextMessage is provided', () => {
|
|
36
|
+
expect(
|
|
37
|
+
mountLabel().find('[data-test-id="infoText_container"]').exists()
|
|
38
|
+
).toBe(false)
|
|
39
|
+
|
|
40
|
+
expect(
|
|
41
|
+
mountLabel({ infoTextMessage: 'Some info' })
|
|
42
|
+
.find('[data-test-id="infoText_container"]')
|
|
43
|
+
.exists()
|
|
44
|
+
).toBe(true)
|
|
45
|
+
})
|
|
46
|
+
|
|
47
|
+
it('renders both the required star and the optional label together', () => {
|
|
48
|
+
const text = mountLabel({
|
|
49
|
+
isRequiredLabel: true,
|
|
50
|
+
labelOptional: true,
|
|
51
|
+
}).text()
|
|
52
|
+
expect(text).toContain('*')
|
|
53
|
+
expect(text).toContain('(optional)')
|
|
54
|
+
})
|
|
55
|
+
})
|
|
@@ -16,6 +16,7 @@ export default {
|
|
|
16
16
|
labelOptional: { control: 'boolean' },
|
|
17
17
|
infoTextMessage: { control: 'text' },
|
|
18
18
|
infoTextAlign: { control: 'select', options: ['left', 'right'] },
|
|
19
|
+
appTheme: { control: 'select', options: ['light', 'dark'] },
|
|
19
20
|
},
|
|
20
21
|
}
|
|
21
22
|
|
|
@@ -67,3 +68,38 @@ HorizontalLayout.args = {
|
|
|
67
68
|
slotLabel: 'Budget (CHF)',
|
|
68
69
|
labelAlign: 'horizontal',
|
|
69
70
|
}
|
|
71
|
+
|
|
72
|
+
export const CustomFontStyle = Template.bind({})
|
|
73
|
+
CustomFontStyle.args = {
|
|
74
|
+
...Default.args,
|
|
75
|
+
slotLabel: 'Section heading',
|
|
76
|
+
fontSize: '20px',
|
|
77
|
+
labelFontColor: 'green',
|
|
78
|
+
}
|
|
79
|
+
|
|
80
|
+
const DarkTemplate = (args) => ({
|
|
81
|
+
components: { LabelText },
|
|
82
|
+
setup() {
|
|
83
|
+
return { args }
|
|
84
|
+
},
|
|
85
|
+
template: `
|
|
86
|
+
<div
|
|
87
|
+
data-test-id="label-story"
|
|
88
|
+
style="padding: 16px; max-width: 420px; background: #1f1f1f;"
|
|
89
|
+
>
|
|
90
|
+
<LabelText v-bind="args">
|
|
91
|
+
{{ args.slotLabel }}
|
|
92
|
+
</LabelText>
|
|
93
|
+
</div>
|
|
94
|
+
`,
|
|
95
|
+
provide: {
|
|
96
|
+
theme,
|
|
97
|
+
},
|
|
98
|
+
})
|
|
99
|
+
|
|
100
|
+
export const DarkTheme = DarkTemplate.bind({})
|
|
101
|
+
DarkTheme.args = {
|
|
102
|
+
...Default.args,
|
|
103
|
+
slotLabel: 'Project name',
|
|
104
|
+
appTheme: 'dark',
|
|
105
|
+
}
|
|
@@ -0,0 +1,46 @@
|
|
|
1
|
+
/* eslint-disable */
|
|
2
|
+
import { mount } from '@vue/test-utils'
|
|
3
|
+
import MarkerItem from '@/components/markerItem'
|
|
4
|
+
|
|
5
|
+
// `theme` and `$gettext` are provided globally by jest.setup.js, so specs do
|
|
6
|
+
// not need to re-provide them. See the canonical example at
|
|
7
|
+
// src/components/buttons/closeButton/closeButton.spec.js.
|
|
8
|
+
|
|
9
|
+
jest.mock('@/components/icon/iconCache.mjs', () => ({
|
|
10
|
+
// need to mock this due to how jest handles import.meta
|
|
11
|
+
fetchIcon: jest.fn(() => Promise.resolve('mocked-icon-url.svg')),
|
|
12
|
+
}))
|
|
13
|
+
|
|
14
|
+
describe('MarkerItem', () => {
|
|
15
|
+
const mountMarker = (props = {}) =>
|
|
16
|
+
mount(MarkerItem, { props: { label: 'Marker', ...props } })
|
|
17
|
+
|
|
18
|
+
it('renders the label text', () => {
|
|
19
|
+
const wrapper = mountMarker({ label: 'Highlights' })
|
|
20
|
+
expect(wrapper.text()).toContain('Highlights')
|
|
21
|
+
})
|
|
22
|
+
|
|
23
|
+
it('exposes the label as the span title attribute', () => {
|
|
24
|
+
const wrapper = mountMarker({ label: 'Highlights' })
|
|
25
|
+
expect(wrapper.find('span').attributes('title')).toBe('Highlights')
|
|
26
|
+
})
|
|
27
|
+
|
|
28
|
+
it('renders an icon only when iconName is provided', () => {
|
|
29
|
+
expect(
|
|
30
|
+
mountMarker({ iconName: 'House' })
|
|
31
|
+
.find('[data-test-id="icon_wrapper"]')
|
|
32
|
+
.exists()
|
|
33
|
+
).toBe(true)
|
|
34
|
+
|
|
35
|
+
expect(
|
|
36
|
+
mountMarker().find('[data-test-id="icon_wrapper"]').exists()
|
|
37
|
+
).toBe(false)
|
|
38
|
+
})
|
|
39
|
+
|
|
40
|
+
it('passes the iconName through to the Icon component', () => {
|
|
41
|
+
const wrapper = mountMarker({ iconName: 'House' })
|
|
42
|
+
expect(wrapper.findComponent({ name: 'EturnityIcon' }).exists()).toBe(true)
|
|
43
|
+
// EturnityIcon forwards `name` to the inner Icon, which declares it as a prop
|
|
44
|
+
expect(wrapper.findComponent({ name: 'Icon' }).props('name')).toBe('House')
|
|
45
|
+
})
|
|
46
|
+
})
|