@eturnity/eturnity_reusable_components 7.39.4-EPDM-11716.0 → 7.39.4-EPDM-11717.0

Sign up to get free protection for your applications and to get access to all the features.
@@ -0,0 +1,269 @@
1
+ import { mount, DOMWrapper } from '@vue/test-utils'
2
+ import RadioButton from '@/components/inputs/radioButton'
3
+ import defaultRadioButtonProps from './defaultProps'
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
+ jest.mock('../../../assets/icons/search_icon.png', () => 'search_icon.png')
11
+
12
+ describe('RadioButton.vue', () => {
13
+ const radioButtons = mount(RadioButton, {
14
+ props: defaultRadioButtonProps,
15
+ global: {
16
+ provide: {
17
+ theme,
18
+ },
19
+ },
20
+ })
21
+ function findRadioWrappersByCriteria(criteria) {
22
+ // criteria === ['active', ..., 'hasImage'], can include any number of criteria
23
+ // This function is used for getting a list of
24
+ // RadioWrapper components which matches
25
+ // all the requested criteria (conjunctive filtering).
26
+ // Make sure that criteria don't contradict each other.
27
+ // List of possible criteria =
28
+ // - active || disabled
29
+ // - checked || unchecked
30
+ // - hasInfoIcon
31
+ // - hasImage
32
+
33
+ function getParentRadioWrapper(element) {
34
+ // function is used for getting a parent RadioWrapper component
35
+ const radioWrapper = element.element.closest(
36
+ '[data-test-id^="radioWrapper_"]'
37
+ )
38
+ return radioWrapper ? new DOMWrapper(radioWrapper) : null
39
+ }
40
+
41
+ const elementsWithTestIds = radioButtons.findAll('[data-test-id]')
42
+ let resultsObject = {}
43
+
44
+ criteria.forEach((criterion) => {
45
+ resultsObject[criterion] = []
46
+ if (criterion === 'active' || criterion === 'disabled') {
47
+ const criteriaRelatedElements = elementsWithTestIds.filter((element) =>
48
+ element.attributes('data-test-id').startsWith('radioInput_')
49
+ )
50
+ criteriaRelatedElements.forEach((el) => {
51
+ const element = el.element
52
+ if (criterion === 'active' ? !element.disabled : element.disabled) {
53
+ resultsObject[criterion].push(getParentRadioWrapper(el))
54
+ }
55
+ })
56
+ }
57
+ if (criterion === 'checked' || criterion === 'unchecked') {
58
+ const criteriaRelatedElements = elementsWithTestIds.filter((element) =>
59
+ element.attributes('data-test-id').startsWith('radioInput_')
60
+ )
61
+ criteriaRelatedElements.forEach((el) => {
62
+ const element = el.element
63
+ if (criterion === 'checked' ? element.checked : !element.checked) {
64
+ resultsObject[criterion].push(getParentRadioWrapper(el))
65
+ }
66
+ })
67
+ }
68
+ if (criterion === 'hasInfoIcon') {
69
+ const criteriaRelatedElements = elementsWithTestIds.filter((element) =>
70
+ element.attributes('data-test-id').startsWith('radioInfo_')
71
+ )
72
+ criteriaRelatedElements.forEach((element) => {
73
+ resultsObject[criterion].push(getParentRadioWrapper(element))
74
+ })
75
+ }
76
+ if (criterion === 'hasImage') {
77
+ const criteriaRelatedElements = elementsWithTestIds.filter((element) =>
78
+ element.attributes('data-test-id').startsWith('radioOpenImage_')
79
+ )
80
+ criteriaRelatedElements.forEach((element) => {
81
+ resultsObject[criterion].push(getParentRadioWrapper(element))
82
+ })
83
+ }
84
+ })
85
+
86
+ let resultArray = []
87
+ Object.keys(resultsObject).forEach((criterion, index) => {
88
+ if (index === 0) {
89
+ resultArray = [...resultsObject[criterion]]
90
+ } else {
91
+ resultArray = resultArray.filter((element) =>
92
+ resultsObject[criterion]
93
+ .map((item) => item.attributes('data-test-id'))
94
+ .includes(element.attributes('data-test-id'))
95
+ )
96
+ }
97
+ })
98
+
99
+ return resultArray
100
+ }
101
+
102
+ it('Radio buttons are rendered and emit correct payload on change', async () => {
103
+ //check that all the options have been rendered
104
+ let radioBtnWrappers = radioButtons.findAll('[data-test-id]')
105
+ radioBtnWrappers = radioBtnWrappers.filter((wrapper) =>
106
+ wrapper.attributes('data-test-id').startsWith('radioWrapper_')
107
+ )
108
+ const numberOfOptions = radioButtons.props('options').length
109
+ expect(radioBtnWrappers).toHaveLength(numberOfOptions)
110
+
111
+ // check that the selected element exists and there is only a single copy of it and has correct value
112
+ const checkedWrapperArray = findRadioWrappersByCriteria(['checked'])
113
+ expect(checkedWrapperArray.length).toBe(1)
114
+ const checkedWrapper = checkedWrapperArray[0]
115
+ const checkedRadioInput = checkedWrapper.find('input[type="radio"]')
116
+ const defaultValueFromProps = radioButtons.props('selectedOption')
117
+ expect(checkedRadioInput.attributes('value')).toBe(
118
+ defaultValueFromProps
119
+ )
120
+
121
+ // Log attributes to see what is rendered (commented out just for reference)
122
+ // console.log('checkedRadioInput attributes', checkedRadioInput.attributes())
123
+
124
+ // Test the label
125
+ const labelOfDefaultValue = radioButtons
126
+ .props('options')
127
+ .find((option) => option.value === defaultValueFromProps).label
128
+ expect(checkedWrapper.text()).toContain(labelOfDefaultValue)
129
+
130
+ // Test the click on unselected active element
131
+ const uncheckedWrapperArray = findRadioWrappersByCriteria([
132
+ 'unchecked',
133
+ 'active',
134
+ ])
135
+ const expectedValueOfEmittedEvent = uncheckedWrapperArray[0]
136
+ .attributes('data-test-id')
137
+ .replace('radioWrapper_', '')
138
+ const uncheckedLabelWrapper = uncheckedWrapperArray[0].find('label')
139
+ await uncheckedLabelWrapper.trigger('click')
140
+ expect(radioButtons.emitted('on-radio-change')).toBeTruthy()
141
+ const emittedEvents = radioButtons.emitted('on-radio-change')
142
+ expect(emittedEvents).toHaveLength(1) // Check if the event was emitted exactly once
143
+ // Check the payload of the event
144
+ expect(emittedEvents[emittedEvents.length - 1]).toEqual([
145
+ expectedValueOfEmittedEvent,
146
+ ])
147
+ await radioButtons.setProps({ selectedOption: expectedValueOfEmittedEvent })
148
+ }),
149
+ it('click on disabled element (|| selected element || info icon || image) does not emit anything', async () => {
150
+ // Remember the number of emitted events before triggering clicks
151
+ const initialNumberOfEvents =
152
+ radioButtons.emitted('on-radio-change').length
153
+
154
+ // Test RadioWrapper with disabled element
155
+ const disabledWrapperArray = findRadioWrappersByCriteria(['disabled'])
156
+ const disabledLabelWrapper = disabledWrapperArray[0].find('label')
157
+ await disabledLabelWrapper.trigger('click')
158
+ // Check if we still have the same number of emitted events as at the beginning
159
+ expect(radioButtons.emitted('on-radio-change')).toHaveLength(
160
+ initialNumberOfEvents
161
+ )
162
+
163
+ // Get RadioWrapper with selected element
164
+ const checkedWrapperArray = findRadioWrappersByCriteria(['checked'])
165
+ const checkedLabelWrapper = checkedWrapperArray[0].find('label')
166
+ await checkedLabelWrapper.trigger('click')
167
+ // Check if we still have the same number of emitted events as at the beginning
168
+ expect(radioButtons.emitted('on-radio-change')).toHaveLength(
169
+ initialNumberOfEvents
170
+ )
171
+
172
+ // Get RadioWrapper with info icon
173
+ const arrayOfWrappersWithInfoIcons = findRadioWrappersByCriteria([
174
+ 'active',
175
+ 'unchecked',
176
+ 'hasInfoIcon',
177
+ ])
178
+ const infoIconForClick = arrayOfWrappersWithInfoIcons[0].find(
179
+ '[data-test-id="infoText_trigger"]'
180
+ )
181
+ await infoIconForClick.trigger('click')
182
+ // Check if we still have the same number of emitted events as at the beginning
183
+ expect(radioButtons.emitted('on-radio-change')).toHaveLength(
184
+ initialNumberOfEvents
185
+ )
186
+
187
+ // Get RadioWrapper with image
188
+ const arrayOfWrappersWithImage = findRadioWrappersByCriteria([
189
+ 'active',
190
+ 'unchecked',
191
+ 'hasImage',
192
+ ])
193
+ const testedRadioWrapperWithImage = arrayOfWrappersWithImage[0]
194
+ const openImageWrapperTestId = testedRadioWrapperWithImage
195
+ .attributes('data-test-id')
196
+ .replace('radioWrapper_', 'radioOpenImage_')
197
+ const openImageWrapper = testedRadioWrapperWithImage.find(
198
+ `[data-test-id="${openImageWrapperTestId}"]`
199
+ )
200
+ await openImageWrapper.trigger('click')
201
+ // Check if we still have the same number of emitted events as at the beginning
202
+ expect(radioButtons.emitted('on-radio-change')).toHaveLength(
203
+ initialNumberOfEvents
204
+ )
205
+
206
+ // Since we just clicked on image miniature
207
+ // lets check has the corresponding modal been opened
208
+ // and is the correct image displayed
209
+ const imageModalWrapperTestId = testedRadioWrapperWithImage
210
+ .attributes('data-test-id')
211
+ .replace('radioWrapper_', 'radioModal_')
212
+ const imageModalWrapper = testedRadioWrapperWithImage.find(
213
+ `[data-test-id="${imageModalWrapperTestId}"]`
214
+ )
215
+ expect(imageModalWrapper.attributes('class')).toContain('visible')
216
+ const imageWrapperTestId = testedRadioWrapperWithImage
217
+ .attributes('data-test-id')
218
+ .replace('radioWrapper_', 'radioImage_')
219
+ const imageWrapper = testedRadioWrapperWithImage.find(
220
+ `[data-test-id="${imageWrapperTestId}"]`
221
+ )
222
+ const expectedImageSrc = imageWrapper.attributes('src')
223
+ const modalImageSrc = imageModalWrapper.find('img').attributes('src')
224
+ expect(modalImageSrc).toBe(expectedImageSrc)
225
+ //Close the modal
226
+ radioButtons.find('.visible .close').trigger('click')
227
+ await radioButtons.vm.$nextTick()
228
+ expect(imageModalWrapper.attributes('class')).toContain('hidden')
229
+ }),
230
+ it('test hover on Info Icon', async () => {
231
+ // Get RadioWrapper with Info Icon
232
+ const arrayOfWrappersWithInfoIcon = findRadioWrappersByCriteria([
233
+ 'hasInfoIcon',
234
+ ])
235
+ //Select tested item and get expected text within the info badge
236
+ const testedRadioWrapper =
237
+ arrayOfWrappersWithInfoIcon[arrayOfWrappersWithInfoIcon.length - 1]
238
+ const valueOfTestedRadioWrapper = testedRadioWrapper
239
+ .attributes('data-test-id')
240
+ .replace('radioWrapper_', '')
241
+ const expectedText = defaultRadioButtonProps.options.find((el) => el.value === valueOfTestedRadioWrapper).infoText
242
+ const iconForHover = testedRadioWrapper.find(
243
+ '[data-test-id="infoText_trigger"]'
244
+ )
245
+ await iconForHover.trigger('mouseenter')
246
+ expect(testedRadioWrapper.text()).toContain(expectedText)
247
+ }),
248
+ it('Test the click again after all the manipulations', async () => {
249
+ const uncheckedWrapperArray = findRadioWrappersByCriteria([
250
+ 'unchecked',
251
+ 'active',
252
+ ])
253
+ const expectedValueOfEmittedEvent = uncheckedWrapperArray[0]
254
+ .attributes('data-test-id')
255
+ .replace('radioWrapper_', '')
256
+ const uncheckedLabelWrapper = uncheckedWrapperArray[0].find('label')
257
+ await uncheckedLabelWrapper.trigger('click')
258
+ expect(radioButtons.emitted('on-radio-change')).toBeTruthy()
259
+ const emittedEvents = radioButtons.emitted('on-radio-change')
260
+ expect(emittedEvents).toHaveLength(2) // Check that this is just 2nd emitted event
261
+ // Check the payload of the event
262
+ expect(emittedEvents[emittedEvents.length - 1]).toEqual([
263
+ expectedValueOfEmittedEvent,
264
+ ])
265
+ await radioButtons.setProps({
266
+ selectedOption: expectedValueOfEmittedEvent,
267
+ })
268
+ })
269
+ })