@dhis2-ui/transfer 10.16.2 → 10.16.3
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 +10 -9
- package/src/__e2e__/add_remove-highlighted-options.e2e.stories.js +30 -0
- package/src/__e2e__/common/options.js +90 -0
- package/src/__e2e__/common/stateful-decorator.js +33 -0
- package/src/__e2e__/common.js +0 -0
- package/src/__e2e__/disabled-transfer-buttons.e2e.stories.js +49 -0
- package/src/__e2e__/disabled-transfer-options.e2e.stories.js +21 -0
- package/src/__e2e__/display-order.e2e.stories.js +24 -0
- package/src/__e2e__/filter-options-list.e2e.stories.js +87 -0
- package/src/__e2e__/highlight-range-of-options.e2e.stories.js +52 -0
- package/src/__e2e__/loading_lists.e2e.stories.js +26 -0
- package/src/__e2e__/notify_at_end_of_list.e2e.stories.js +116 -0
- package/src/__e2e__/reorder-with-buttons.e2e.stories.js +35 -0
- package/src/__e2e__/set_unset-highlighted-option.e2e.stories.js +30 -0
- package/src/__e2e__/transferring-items.e2e.stories.js +27 -0
- package/src/__tests__/common.test.js +131 -0
- package/src/__tests__/helper/add-all-selectable-source-options.test.js +46 -0
- package/src/__tests__/helper/add-individual-source-options.test.js +80 -0
- package/src/__tests__/helper/default-filter-callback.test.js +45 -0
- package/src/__tests__/helper/is-reorder-down-disabled.test.js +96 -0
- package/src/__tests__/helper/is-reorder-up-disabled.test.js +96 -0
- package/src/__tests__/helper/move-highlighted-picked-option-down.test.js +111 -0
- package/src/__tests__/helper/move-highlighted-picked-option-to-bottom.test.js +101 -0
- package/src/__tests__/helper/move-highlighted-picked-option-to-top.test.js +101 -0
- package/src/__tests__/helper/move-highlighted-picked-option-up.test.js +111 -0
- package/src/__tests__/helper/remove-all-picked-options.test.js +29 -0
- package/src/__tests__/helper/remove-individual-picked-options.test.js +38 -0
- package/src/__tests__/helper/use-highlighted-option/create-toggle-highlighted-option.test.js +104 -0
- package/src/__tests__/helper/use-highlighted-option/toggle-add.test.js +84 -0
- package/src/__tests__/helper/use-highlighted-option/toggle-range.test.js +150 -0
- package/src/__tests__/helper/use-highlighted-option/toggle-replace.test.js +39 -0
- package/src/__tests__/helper/use-highlighted-option.test.js +41 -0
- package/src/__tests__/reordering-actions.test.js +165 -0
- package/src/__tests__/transfer.test.js +137 -0
- package/src/actions.js +33 -0
- package/src/add-all.js +27 -0
- package/src/add-individual.js +27 -0
- package/src/common/find-option-index.js +9 -0
- package/src/common/get-mode-by-modifier-key.js +35 -0
- package/src/common/index.js +5 -0
- package/src/common/is-option.js +7 -0
- package/src/common/modes.js +11 -0
- package/src/common/remove-option.js +19 -0
- package/src/common/toggle-value.js +18 -0
- package/src/container.js +23 -0
- package/src/end-intersection-detector.js +37 -0
- package/src/features/add_remove-highlighted-options/index.js +92 -0
- package/src/features/add_remove-highlighted-options.feature +41 -0
- package/src/features/common/index.js +8 -0
- package/src/features/disabled-transfer-buttons/index.js +118 -0
- package/src/features/disabled-transfer-buttons.feature +46 -0
- package/src/features/disabled-transfer-options/index.js +182 -0
- package/src/features/disabled-transfer-options.feature +42 -0
- package/src/features/display-order/index.js +205 -0
- package/src/features/display-order.feature +30 -0
- package/src/features/filter-options-list/index.js +133 -0
- package/src/features/filter-options-list.feature +40 -0
- package/src/features/highlight-range-of-options/index.js +336 -0
- package/src/features/highlight-range-of-options.feature +70 -0
- package/src/features/loading_lists/index.js +43 -0
- package/src/features/loading_lists.feature +19 -0
- package/src/features/notify_at_end_of_list/index.js +125 -0
- package/src/features/notify_at_end_of_list.feature +64 -0
- package/src/features/reorder-with-buttons/index.js +181 -0
- package/src/features/reorder-with-buttons.feature +138 -0
- package/src/features/set_unset-highlighted-option/index.js +121 -0
- package/src/features/set_unset-highlighted-option.feature +42 -0
- package/src/features/transferring-items/index.js +375 -0
- package/src/features/transferring-items.feature +44 -0
- package/src/filter.js +38 -0
- package/src/icons.js +194 -0
- package/src/index.js +2 -0
- package/src/left-footer.js +22 -0
- package/src/left-header.js +22 -0
- package/src/left-side.js +34 -0
- package/src/locales/en/translations.json +7 -0
- package/src/locales/index.js +16 -0
- package/src/options-container.js +127 -0
- package/src/remove-all.js +27 -0
- package/src/remove-individual.js +27 -0
- package/src/reordering-actions.js +136 -0
- package/src/right-footer.js +22 -0
- package/src/right-header.js +22 -0
- package/src/right-side.js +33 -0
- package/src/transfer/add-all-selectable-source-options.js +37 -0
- package/src/transfer/add-individual-source-options.js +61 -0
- package/src/transfer/create-double-click-handlers.js +36 -0
- package/src/transfer/default-filter-callback.js +17 -0
- package/src/transfer/get-highlighted-picked-indices.js +26 -0
- package/src/transfer/get-option-click-handlers.js +19 -0
- package/src/transfer/index.js +17 -0
- package/src/transfer/is-reorder-down-disabled.js +34 -0
- package/src/transfer/is-reorder-up-disabled.js +30 -0
- package/src/transfer/move-highlighted-picked-option-down.js +54 -0
- package/src/transfer/move-highlighted-picked-option-to-bottom.js +44 -0
- package/src/transfer/move-highlighted-picked-option-to-top.js +38 -0
- package/src/transfer/move-highlighted-picked-option-up.js +47 -0
- package/src/transfer/remove-all-picked-options.js +13 -0
- package/src/transfer/remove-individual-picked-options.js +49 -0
- package/src/transfer/use-filter.js +17 -0
- package/src/transfer/use-highlighted-options/create-toggle-highlighted-option.js +64 -0
- package/src/transfer/use-highlighted-options/toggle-add.js +20 -0
- package/src/transfer/use-highlighted-options/toggle-range.js +61 -0
- package/src/transfer/use-highlighted-options/toggle-replace.js +26 -0
- package/src/transfer/use-highlighted-options.js +34 -0
- package/src/transfer/use-options-key-monitor.js +41 -0
- package/src/transfer-option.js +91 -0
- package/src/transfer.js +539 -0
- package/src/transfer.prod.stories.js +621 -0
|
@@ -0,0 +1,336 @@
|
|
|
1
|
+
import { Given, When, Then } from '@badeball/cypress-cucumber-preprocessor'
|
|
2
|
+
import { extractOptionFromElement } from '../common/index.js'
|
|
3
|
+
|
|
4
|
+
Given('the option list has one or more items', () => {
|
|
5
|
+
cy.visitStory('Transfer highlight range of options', 'Has Options')
|
|
6
|
+
cy.get('{transfer-sourceoptions}')
|
|
7
|
+
.as('list')
|
|
8
|
+
.find('{transferoption}')
|
|
9
|
+
.should('have.length.of.at.least', 1)
|
|
10
|
+
})
|
|
11
|
+
|
|
12
|
+
Given('the selected list has one or more items', () => {
|
|
13
|
+
cy.visitStory('Transfer highlight range of options', 'Has Selected')
|
|
14
|
+
cy.get('{transfer-pickedoptions}')
|
|
15
|
+
.as('list')
|
|
16
|
+
.as('list')
|
|
17
|
+
.find('{transferoption}')
|
|
18
|
+
.should('have.length.of.at.least', 1)
|
|
19
|
+
})
|
|
20
|
+
|
|
21
|
+
Given('the option list has three or more items', () => {
|
|
22
|
+
cy.visitStory('Transfer highlight range of options', 'Has Options')
|
|
23
|
+
cy.get('{transfer-sourceoptions}')
|
|
24
|
+
.as('list')
|
|
25
|
+
.as('list')
|
|
26
|
+
.find('{transferoption}')
|
|
27
|
+
.should('have.length.of.at.least', 3)
|
|
28
|
+
})
|
|
29
|
+
|
|
30
|
+
Given('the selected list has three or more items', () => {
|
|
31
|
+
cy.visitStory('Transfer highlight range of options', 'Has Selected')
|
|
32
|
+
cy.get('{transfer-pickedoptions}')
|
|
33
|
+
.as('list')
|
|
34
|
+
.as('list')
|
|
35
|
+
.find('{transferoption}')
|
|
36
|
+
.should('have.length.of.at.least', 3)
|
|
37
|
+
})
|
|
38
|
+
|
|
39
|
+
Given('the option list has many items', () => {
|
|
40
|
+
cy.visitStory('Transfer highlight range of options', 'Has Options')
|
|
41
|
+
cy.get('{transfer-sourceoptions}')
|
|
42
|
+
.as('list')
|
|
43
|
+
.as('list')
|
|
44
|
+
.find('{transferoption}')
|
|
45
|
+
.should('have.length.of.at.least', 5)
|
|
46
|
+
})
|
|
47
|
+
|
|
48
|
+
Given('the selected list has many items', () => {
|
|
49
|
+
cy.visitStory('Transfer highlight range of options', 'All Selected')
|
|
50
|
+
cy.get('{transfer-pickedoptions}')
|
|
51
|
+
.as('list')
|
|
52
|
+
.as('list')
|
|
53
|
+
.find('{transferoption}')
|
|
54
|
+
.should('have.length.of.at.least', 5)
|
|
55
|
+
})
|
|
56
|
+
|
|
57
|
+
Given('no item is highlighted', () => {
|
|
58
|
+
cy.get('@list').find('.highlighted').should('not.exist')
|
|
59
|
+
})
|
|
60
|
+
|
|
61
|
+
Given('one item is highlighted', () => {
|
|
62
|
+
cy.get('@list')
|
|
63
|
+
.find('{transferoption}')
|
|
64
|
+
.first()
|
|
65
|
+
.as('initiallyHighlighted')
|
|
66
|
+
.click()
|
|
67
|
+
.should('have.class', 'highlighted')
|
|
68
|
+
})
|
|
69
|
+
|
|
70
|
+
Given('there are at least two options following the highlighted option', () => {
|
|
71
|
+
cy.get('@initiallyHighlighted')
|
|
72
|
+
.next()
|
|
73
|
+
.should('exist')
|
|
74
|
+
.as('firstBelowInitiallyHighlighted')
|
|
75
|
+
.next()
|
|
76
|
+
.should('exist')
|
|
77
|
+
.as('secondBelowInitiallyHighlighted')
|
|
78
|
+
})
|
|
79
|
+
|
|
80
|
+
Given('several options are highlighted', () => {
|
|
81
|
+
cy.get('@list')
|
|
82
|
+
.find('{transferoption}')
|
|
83
|
+
.then(($option) => $option.eq(0).add($option.eq(4)).add($option.eq(6)))
|
|
84
|
+
.as('initiallyHighlightedMultiple')
|
|
85
|
+
.each(($option) => cy.wrap($option).clickWith('ctrl'))
|
|
86
|
+
})
|
|
87
|
+
|
|
88
|
+
Given(
|
|
89
|
+
'there are at least two options following the last highlighted option',
|
|
90
|
+
() => {
|
|
91
|
+
cy.get('@initiallyHighlightedMultiple')
|
|
92
|
+
.last('last')
|
|
93
|
+
.next()
|
|
94
|
+
.should('exist')
|
|
95
|
+
.as('firstBelowInitiallyHighlighted')
|
|
96
|
+
.next()
|
|
97
|
+
.should('exist')
|
|
98
|
+
.as('secondBelowInitiallyHighlighted')
|
|
99
|
+
}
|
|
100
|
+
)
|
|
101
|
+
|
|
102
|
+
When('the user clicks an item with the SHIFT modifier key', () => {
|
|
103
|
+
cy.get('@list')
|
|
104
|
+
.find('{transferoption}')
|
|
105
|
+
.first()
|
|
106
|
+
.clickWith('ctrl')
|
|
107
|
+
.as('initiallyHighlighted')
|
|
108
|
+
})
|
|
109
|
+
|
|
110
|
+
When('the user clicks the highlighted item with the SHIFT modifier key', () => {
|
|
111
|
+
cy.get('@initiallyHighlighted').clickWith('shift').as('hiddenHighlighted')
|
|
112
|
+
})
|
|
113
|
+
|
|
114
|
+
When(
|
|
115
|
+
'the user highlightes the second options following the highlighted option with the SHIFT key modifier',
|
|
116
|
+
() => {
|
|
117
|
+
cy.get('@secondBelowInitiallyHighlighted').clickWith('shift')
|
|
118
|
+
}
|
|
119
|
+
)
|
|
120
|
+
|
|
121
|
+
When(
|
|
122
|
+
'the user highlightes the second options following the last highlighted option',
|
|
123
|
+
() => {
|
|
124
|
+
cy.get('@initiallyHighlightedMultiple')
|
|
125
|
+
// last highlighted option
|
|
126
|
+
.last()
|
|
127
|
+
|
|
128
|
+
// next sibling
|
|
129
|
+
.next()
|
|
130
|
+
.as('firstBelowLastHighlighted')
|
|
131
|
+
|
|
132
|
+
// second next sibling
|
|
133
|
+
.next()
|
|
134
|
+
.as('secondBelowLastHighlighted')
|
|
135
|
+
.clickWith('shift')
|
|
136
|
+
}
|
|
137
|
+
)
|
|
138
|
+
|
|
139
|
+
When('the user {string} clicks a highlighted option', (modifierKey) => {
|
|
140
|
+
cy.get('@initiallyHighlightedMultiple')
|
|
141
|
+
.eq(0)
|
|
142
|
+
.clickWith(modifierKey)
|
|
143
|
+
.as('controlClicked')
|
|
144
|
+
})
|
|
145
|
+
|
|
146
|
+
When('the user changed the filter to exclude the last clicked option', () => {
|
|
147
|
+
cy.get('{transfer-filter} input').type('ARI')
|
|
148
|
+
})
|
|
149
|
+
|
|
150
|
+
When('the user SHIFT-clicks a non-highlighted option', () => {
|
|
151
|
+
cy.get('@list')
|
|
152
|
+
.find('{transferoption}')
|
|
153
|
+
.invoke('eq', 4)
|
|
154
|
+
.clickWith('shift')
|
|
155
|
+
.as('firstShiftClicked')
|
|
156
|
+
})
|
|
157
|
+
|
|
158
|
+
When('the user SHIFT-clicks an option', () => {
|
|
159
|
+
cy.get('@list').find('{transferoption}').eq(0).clickWith('shift')
|
|
160
|
+
|
|
161
|
+
cy.wrap(0).as('firstClickedIndexWithShift')
|
|
162
|
+
})
|
|
163
|
+
|
|
164
|
+
When('the user SHIFT-clicks another option', () => {
|
|
165
|
+
cy.get('@list').find('{transferoption}').eq(5).clickWith('shift')
|
|
166
|
+
|
|
167
|
+
cy.wrap(5).as('secondClickedIndexWithShift')
|
|
168
|
+
})
|
|
169
|
+
|
|
170
|
+
Then('the clicked option should be highlighted', () => {
|
|
171
|
+
cy.get('@initiallyHighlighted').should('have.class', 'highlighted')
|
|
172
|
+
})
|
|
173
|
+
|
|
174
|
+
Then('the option is not highlighted', () => {
|
|
175
|
+
cy.all(
|
|
176
|
+
() => cy.get('@hiddenHighlighted'),
|
|
177
|
+
() => cy.get('{transfer-sourceoptions} {transferoption}')
|
|
178
|
+
).should(([hiddenHighlighted, $options]) => {
|
|
179
|
+
const $hiddenHighlighted = $options.filter((index, optionEl) => {
|
|
180
|
+
const option = extractOptionFromElement(optionEl)
|
|
181
|
+
|
|
182
|
+
return (
|
|
183
|
+
option.label === hiddenHighlighted.label &&
|
|
184
|
+
option.value === hiddenHighlighted.value
|
|
185
|
+
)
|
|
186
|
+
})
|
|
187
|
+
|
|
188
|
+
$hiddenHighlighted.each((_index, option) => {
|
|
189
|
+
cy.wrap(option).should('not.have.class', 'highlighted')
|
|
190
|
+
})
|
|
191
|
+
})
|
|
192
|
+
})
|
|
193
|
+
|
|
194
|
+
Then('the clicked options should be highlighted', () => {
|
|
195
|
+
cy.all(
|
|
196
|
+
() => cy.get('@initiallyHighlighted'),
|
|
197
|
+
() => cy.get('@secondBelowInitiallyHighlighted')
|
|
198
|
+
).should(([$initiallyHighlighted, $secondBelowInitiallyHighlighted]) => {
|
|
199
|
+
expect($initiallyHighlighted).to.have.class('highlighted')
|
|
200
|
+
expect($secondBelowInitiallyHighlighted).to.have.class('highlighted')
|
|
201
|
+
})
|
|
202
|
+
})
|
|
203
|
+
|
|
204
|
+
Then(
|
|
205
|
+
'all options between the initially highlighted option and the clicked option are highlighted',
|
|
206
|
+
() => {
|
|
207
|
+
cy.get('@firstBelowInitiallyHighlighted').should(
|
|
208
|
+
'have.class',
|
|
209
|
+
'highlighted'
|
|
210
|
+
)
|
|
211
|
+
}
|
|
212
|
+
)
|
|
213
|
+
|
|
214
|
+
Then(
|
|
215
|
+
'the option highlighted most recently without SHIFT should be highlighted',
|
|
216
|
+
() => {
|
|
217
|
+
cy.get('@initiallyHighlightedMultiple')
|
|
218
|
+
.last()
|
|
219
|
+
.should('have.class', 'highlighted')
|
|
220
|
+
}
|
|
221
|
+
)
|
|
222
|
+
|
|
223
|
+
Then('the option clicked with SHIFT should be highlighted', () => {
|
|
224
|
+
cy.get('@secondBelowInitiallyHighlighted').should(
|
|
225
|
+
'have.class',
|
|
226
|
+
'highlighted'
|
|
227
|
+
)
|
|
228
|
+
})
|
|
229
|
+
|
|
230
|
+
Then(
|
|
231
|
+
'all options between the option highlighted most recently without SHIFT and the clicked option are highlighted',
|
|
232
|
+
() => {
|
|
233
|
+
cy.get('@firstBelowInitiallyHighlighted').should(
|
|
234
|
+
'have.class',
|
|
235
|
+
'highlighted'
|
|
236
|
+
)
|
|
237
|
+
}
|
|
238
|
+
)
|
|
239
|
+
|
|
240
|
+
Then(
|
|
241
|
+
'all other previously highlighted options are not highlighted anymore',
|
|
242
|
+
() => {
|
|
243
|
+
cy.all(
|
|
244
|
+
() =>
|
|
245
|
+
cy.get('@initiallyHighlightedMultiple').last().invoke('index'),
|
|
246
|
+
() => cy.get('@initiallyHighlightedMultiple')
|
|
247
|
+
).should(
|
|
248
|
+
([
|
|
249
|
+
lastInitiallyHighlightedIndex,
|
|
250
|
+
$initiallyHighlightedMultiple,
|
|
251
|
+
]) => {
|
|
252
|
+
$initiallyHighlightedMultiple
|
|
253
|
+
.filter((_, el) => {
|
|
254
|
+
const $el = Cypress.$(el)
|
|
255
|
+
return $el.index() !== lastInitiallyHighlightedIndex
|
|
256
|
+
})
|
|
257
|
+
.each((_, el) => {
|
|
258
|
+
const $el = Cypress.$(el)
|
|
259
|
+
expect($el).to.not.have.class('highlighted')
|
|
260
|
+
})
|
|
261
|
+
}
|
|
262
|
+
)
|
|
263
|
+
}
|
|
264
|
+
)
|
|
265
|
+
|
|
266
|
+
Then(
|
|
267
|
+
'the range from the visually first highlighted option to the SHIFT-clicked option is highlighted',
|
|
268
|
+
() => {
|
|
269
|
+
cy.all(
|
|
270
|
+
() => cy.get('@initiallyHighlightedMultiple'),
|
|
271
|
+
() => cy.get('@firstShiftClicked'),
|
|
272
|
+
() => cy.get('@list').find('{transferoption}')
|
|
273
|
+
).should(
|
|
274
|
+
([$initiallyHighlightedMultiple, $firstShiftClicked, $all]) => {
|
|
275
|
+
const firstVisibleHighlightedIndex =
|
|
276
|
+
$initiallyHighlightedMultiple
|
|
277
|
+
.filter(':visible')
|
|
278
|
+
.eq(0)
|
|
279
|
+
.index()
|
|
280
|
+
const shiftIndex = $firstShiftClicked.index()
|
|
281
|
+
const from = Math.min(firstVisibleHighlightedIndex, shiftIndex)
|
|
282
|
+
const to = Math.max(firstVisibleHighlightedIndex, shiftIndex)
|
|
283
|
+
const $insideRange = $all.slice(from, to + 1)
|
|
284
|
+
const $outsideRange = $all
|
|
285
|
+
.slice(0, from)
|
|
286
|
+
.add($all.slice(to + 1))
|
|
287
|
+
|
|
288
|
+
$insideRange.each((index, option) => {
|
|
289
|
+
expect(Cypress.$(option)).to.have.class('highlighted')
|
|
290
|
+
})
|
|
291
|
+
|
|
292
|
+
$outsideRange.each((index, option) =>
|
|
293
|
+
expect(Cypress.$(option)).to.not.have.class('highlighted')
|
|
294
|
+
)
|
|
295
|
+
}
|
|
296
|
+
)
|
|
297
|
+
}
|
|
298
|
+
)
|
|
299
|
+
|
|
300
|
+
Then(
|
|
301
|
+
'the range from the first clicked option to the second clicked option is highlighted',
|
|
302
|
+
() => {
|
|
303
|
+
cy.all(
|
|
304
|
+
() => cy.get('@firstClickedIndexWithShift'),
|
|
305
|
+
() => cy.get('@secondClickedIndexWithShift'),
|
|
306
|
+
() => cy.get('@list').find('{transferoption}')
|
|
307
|
+
).should(
|
|
308
|
+
([
|
|
309
|
+
firstClickedIndexWithShift,
|
|
310
|
+
secondClickedIndexWithShift,
|
|
311
|
+
$all,
|
|
312
|
+
]) => {
|
|
313
|
+
const from = Math.min(
|
|
314
|
+
firstClickedIndexWithShift,
|
|
315
|
+
secondClickedIndexWithShift
|
|
316
|
+
)
|
|
317
|
+
const to = Math.max(
|
|
318
|
+
firstClickedIndexWithShift,
|
|
319
|
+
secondClickedIndexWithShift
|
|
320
|
+
)
|
|
321
|
+
const $insideRange = $all.slice(from, to + 1)
|
|
322
|
+
const $outsideRange = $all
|
|
323
|
+
.slice(0, from)
|
|
324
|
+
.add($all.slice(to + 1))
|
|
325
|
+
|
|
326
|
+
$insideRange.each((index, option) => {
|
|
327
|
+
expect(Cypress.$(option)).to.have.class('highlighted')
|
|
328
|
+
})
|
|
329
|
+
|
|
330
|
+
$outsideRange.each((index, option) =>
|
|
331
|
+
expect(Cypress.$(option)).to.not.have.class('highlighted')
|
|
332
|
+
)
|
|
333
|
+
}
|
|
334
|
+
)
|
|
335
|
+
}
|
|
336
|
+
)
|
|
@@ -0,0 +1,70 @@
|
|
|
1
|
+
Feature: Highlight a range of options
|
|
2
|
+
|
|
3
|
+
Scenario: The user highlights an option with the SHIFT modifier key
|
|
4
|
+
Given the option list has one or more items
|
|
5
|
+
And no item is highlighted
|
|
6
|
+
When the user clicks an item with the SHIFT modifier key
|
|
7
|
+
Then the clicked option should be highlighted
|
|
8
|
+
|
|
9
|
+
Scenario: The user un-highlights an option with the SHIFT modifier key
|
|
10
|
+
Given the option list has one or more items
|
|
11
|
+
And one item is highlighted
|
|
12
|
+
When the user clicks the highlighted item with the SHIFT modifier key
|
|
13
|
+
Then the option is not highlighted
|
|
14
|
+
|
|
15
|
+
Scenario Outline: The user highlights a range of options with the SHIFT modifier key
|
|
16
|
+
Given the <type> list has three or more items
|
|
17
|
+
And one item is highlighted
|
|
18
|
+
And there are at least two options following the highlighted option
|
|
19
|
+
When the user highlightes the second options following the highlighted option with the SHIFT key modifier
|
|
20
|
+
Then the clicked options should be highlighted
|
|
21
|
+
Then all options between the initially highlighted option and the clicked option are highlighted
|
|
22
|
+
|
|
23
|
+
Examples:
|
|
24
|
+
| type |
|
|
25
|
+
| option |
|
|
26
|
+
| selected |
|
|
27
|
+
|
|
28
|
+
Scenario Outline: The user highlights a range of options with the SHIFT modifier key while multiple are highlighted
|
|
29
|
+
Given the <type> list has three or more items
|
|
30
|
+
And several options are highlighted
|
|
31
|
+
And there are at least two options following the last highlighted option
|
|
32
|
+
When the user highlightes the second options following the last highlighted option
|
|
33
|
+
Then the option highlighted most recently without SHIFT should be highlighted
|
|
34
|
+
And the option clicked with SHIFT should be highlighted
|
|
35
|
+
And all options between the option highlighted most recently without SHIFT and the clicked option are highlighted
|
|
36
|
+
And all other previously highlighted options are not highlighted anymore
|
|
37
|
+
|
|
38
|
+
Examples:
|
|
39
|
+
| type |
|
|
40
|
+
| option |
|
|
41
|
+
| selected |
|
|
42
|
+
|
|
43
|
+
Scenario Outline: The user highlights hides the last-without-SHIFT clicked option and selects a range
|
|
44
|
+
Given the option list has many items
|
|
45
|
+
And several options are highlighted
|
|
46
|
+
When the user "<mod>" clicks a highlighted option
|
|
47
|
+
And the user changed the filter to exclude the last clicked option
|
|
48
|
+
And the user SHIFT-clicks a non-highlighted option
|
|
49
|
+
Then the range from the visually first highlighted option to the SHIFT-clicked option is highlighted
|
|
50
|
+
|
|
51
|
+
Examples:
|
|
52
|
+
| mod |
|
|
53
|
+
| ctrl |
|
|
54
|
+
| cmd |
|
|
55
|
+
| alt |
|
|
56
|
+
|
|
57
|
+
Scenario Outline: The user highlights highlights the first option with SHIFT, then highlights a range with SHIFT
|
|
58
|
+
Given the <type> list has many items
|
|
59
|
+
When the user SHIFT-clicks an option
|
|
60
|
+
And the user SHIFT-clicks another option
|
|
61
|
+
Then the range from the first clicked option to the second clicked option is highlighted
|
|
62
|
+
|
|
63
|
+
Examples:
|
|
64
|
+
| type | mod |
|
|
65
|
+
| option | ctrl |
|
|
66
|
+
| option | cmd |
|
|
67
|
+
| option | alt |
|
|
68
|
+
| selected | ctrl |
|
|
69
|
+
| selected | cmd |
|
|
70
|
+
| selected | alt |
|
|
@@ -0,0 +1,43 @@
|
|
|
1
|
+
import { Given, Then } from '@badeball/cypress-cucumber-preprocessor'
|
|
2
|
+
|
|
3
|
+
Given('the source list is loading', () => {
|
|
4
|
+
cy.visitStory('Transfer Loading Lists', 'Loading Source')
|
|
5
|
+
cy.wrap('source').as('listType')
|
|
6
|
+
})
|
|
7
|
+
|
|
8
|
+
Given('the picked list is loading', () => {
|
|
9
|
+
cy.visitStory('Transfer Loading Lists', 'Loading Picked')
|
|
10
|
+
cy.wrap('picked').as('listType')
|
|
11
|
+
})
|
|
12
|
+
|
|
13
|
+
Given('the source list is not loading', () => {
|
|
14
|
+
cy.visitStory('Transfer Loading Lists', 'Not Loading Source')
|
|
15
|
+
cy.wrap('source').as('listType')
|
|
16
|
+
})
|
|
17
|
+
|
|
18
|
+
Given('the picked list is not loading', () => {
|
|
19
|
+
cy.visitStory('Transfer Loading Lists', 'Not Loading Picked')
|
|
20
|
+
cy.wrap('picked').as('listType')
|
|
21
|
+
})
|
|
22
|
+
|
|
23
|
+
Then('the loading indicator should be shown', () => {
|
|
24
|
+
cy.get('@listType').then((listType) => {
|
|
25
|
+
const listSelector =
|
|
26
|
+
listType === 'source'
|
|
27
|
+
? '{transfer-leftside}'
|
|
28
|
+
: '{transfer-rightside}'
|
|
29
|
+
|
|
30
|
+
cy.get(`${listSelector} .loading`).should('exist')
|
|
31
|
+
})
|
|
32
|
+
})
|
|
33
|
+
|
|
34
|
+
Then('the loading indicator should not be shown', () => {
|
|
35
|
+
cy.get('@listType').then((listType) => {
|
|
36
|
+
const listSelector =
|
|
37
|
+
listType === 'source'
|
|
38
|
+
? '{transfer-leftside}'
|
|
39
|
+
: '{transfer-rightside}'
|
|
40
|
+
|
|
41
|
+
cy.get(`${listSelector} .loading`).should('not.exist')
|
|
42
|
+
})
|
|
43
|
+
})
|
|
@@ -0,0 +1,19 @@
|
|
|
1
|
+
Feature: The source and picked lists can have a loading state
|
|
2
|
+
|
|
3
|
+
Scenario Outline: A list is loading
|
|
4
|
+
Given the <type> list is loading
|
|
5
|
+
Then the loading indicator should be shown
|
|
6
|
+
|
|
7
|
+
Examples:
|
|
8
|
+
| type |
|
|
9
|
+
| source |
|
|
10
|
+
| picked |
|
|
11
|
+
|
|
12
|
+
Scenario Outline: A list is not loading
|
|
13
|
+
Given the <type> list is not loading
|
|
14
|
+
Then the loading indicator should not be shown
|
|
15
|
+
|
|
16
|
+
Examples:
|
|
17
|
+
| type |
|
|
18
|
+
| source |
|
|
19
|
+
| picked |
|
|
@@ -0,0 +1,125 @@
|
|
|
1
|
+
import { Given, When, Then } from '@badeball/cypress-cucumber-preprocessor'
|
|
2
|
+
|
|
3
|
+
Given(
|
|
4
|
+
'the Transfer has enough items to fill the source list completely',
|
|
5
|
+
() => {
|
|
6
|
+
cy.visitStory('Transfer End Of List', 'Full Source List')
|
|
7
|
+
cy.wrap('source').as('listType')
|
|
8
|
+
}
|
|
9
|
+
)
|
|
10
|
+
|
|
11
|
+
Given(
|
|
12
|
+
'the Transfer has enough items to fill the picked list completely',
|
|
13
|
+
() => {
|
|
14
|
+
cy.visitStory('Transfer End Of List', 'Full Picked List')
|
|
15
|
+
cy.wrap('picked').as('listType')
|
|
16
|
+
}
|
|
17
|
+
)
|
|
18
|
+
|
|
19
|
+
Given(
|
|
20
|
+
'the Transfer does not have enough items to fill the source list completely',
|
|
21
|
+
() => {
|
|
22
|
+
cy.visitStory('Transfer End Of List', 'Partial Source List')
|
|
23
|
+
cy.wrap('source').as('listType')
|
|
24
|
+
}
|
|
25
|
+
)
|
|
26
|
+
|
|
27
|
+
Given(
|
|
28
|
+
'the Transfer source options list does not fill the list completely',
|
|
29
|
+
() => {
|
|
30
|
+
cy.visitStory('Transfer End Of List', 'Option Changes For Short List')
|
|
31
|
+
cy.wrap('source').as('listType')
|
|
32
|
+
}
|
|
33
|
+
)
|
|
34
|
+
|
|
35
|
+
Given(
|
|
36
|
+
'the Transfer does not have enough items to fill the picked list completely',
|
|
37
|
+
() => {
|
|
38
|
+
cy.visitStory('Transfer End Of List', 'Partial Picked List')
|
|
39
|
+
cy.wrap('picked').as('listType')
|
|
40
|
+
}
|
|
41
|
+
)
|
|
42
|
+
|
|
43
|
+
When('the user scroll to the end of the list', () => {
|
|
44
|
+
cy.get('@listType').then((listType) => {
|
|
45
|
+
const listSelector =
|
|
46
|
+
listType === 'source'
|
|
47
|
+
? 'transfer-sourceoptions'
|
|
48
|
+
: 'transfer-pickedoptions'
|
|
49
|
+
|
|
50
|
+
cy.get(`{${listSelector}-endintersectiondetector}`).scrollIntoView()
|
|
51
|
+
})
|
|
52
|
+
})
|
|
53
|
+
|
|
54
|
+
When('the user adds an item by clicking the button', () => {
|
|
55
|
+
cy.contains('Increment options lists').click()
|
|
56
|
+
})
|
|
57
|
+
|
|
58
|
+
Then('the last list item should be fully visible', () => {
|
|
59
|
+
cy.contains('ARI treated with antibiotics (pneumonia) new').should(
|
|
60
|
+
'be.visible'
|
|
61
|
+
)
|
|
62
|
+
})
|
|
63
|
+
|
|
64
|
+
Then('the callback for reaching the end should not be called', () => {
|
|
65
|
+
cy.all(
|
|
66
|
+
() => cy.window(),
|
|
67
|
+
() => cy.get('@listType')
|
|
68
|
+
).should(([win, listType]) => {
|
|
69
|
+
const callback =
|
|
70
|
+
listType === 'source' ? win.onEndReached : win.onEndReachedPicked
|
|
71
|
+
|
|
72
|
+
expect(callback).to.not.be.called
|
|
73
|
+
})
|
|
74
|
+
})
|
|
75
|
+
|
|
76
|
+
Then('the callback for reaching the end should be called', () => {
|
|
77
|
+
cy.all(
|
|
78
|
+
() => cy.window(),
|
|
79
|
+
() => cy.get('@listType')
|
|
80
|
+
).should(([win, listType]) => {
|
|
81
|
+
const callback =
|
|
82
|
+
listType === 'source' ? win.onEndReached : win.onEndReachedPicked
|
|
83
|
+
|
|
84
|
+
expect(callback).to.be.calledOnce
|
|
85
|
+
})
|
|
86
|
+
})
|
|
87
|
+
When('the user scrolls down to the source list end', () => {
|
|
88
|
+
cy.get('[data-test="dhis2-uicore-transfer-sourceoptions"]')
|
|
89
|
+
.find('[data-test="dhis2-uicore-intersectiondetector"]')
|
|
90
|
+
.scrollIntoView()
|
|
91
|
+
})
|
|
92
|
+
Then('the list end indicator of the source list should be visible', () => {
|
|
93
|
+
cy.get('[data-test="dhis2-uicore-transfer-sourceoptions"]')
|
|
94
|
+
.find('[data-test="dhis2-uicore-intersectiondetector"]')
|
|
95
|
+
.should('be.visible')
|
|
96
|
+
})
|
|
97
|
+
Then('the list end indicator of the source list should not be visible', () => {
|
|
98
|
+
cy.get('[data-test="dhis2-uicore-transfer-sourceoptions"]')
|
|
99
|
+
.find('[data-test="dhis2-uicore-intersectiondetector"]')
|
|
100
|
+
.should('not.be.visible')
|
|
101
|
+
})
|
|
102
|
+
Then(
|
|
103
|
+
'the callback for reaching the end of the source list should be called {int} times',
|
|
104
|
+
function (int) {
|
|
105
|
+
cy.window().should((win) => {
|
|
106
|
+
expect(win.onEndReached).to.have.callCount(int)
|
|
107
|
+
})
|
|
108
|
+
}
|
|
109
|
+
)
|
|
110
|
+
Then('the selected item is being displayed in the picked list', () => {
|
|
111
|
+
cy.get('[data-test="dhis2-uicore-transfer-pickedoptions"]')
|
|
112
|
+
.contains('Option nr. 9')
|
|
113
|
+
.should('be.visible')
|
|
114
|
+
})
|
|
115
|
+
When('the user selects option nr. {}', function (int) {
|
|
116
|
+
cy.contains(`Option nr. ${int}`).dblclick()
|
|
117
|
+
})
|
|
118
|
+
Then(
|
|
119
|
+
'the callback for reaching the end of the picked list should be called {int} times',
|
|
120
|
+
function (int) {
|
|
121
|
+
cy.window().should((win) => {
|
|
122
|
+
expect(win.onEndReachedPicked).to.have.callCount(int)
|
|
123
|
+
})
|
|
124
|
+
}
|
|
125
|
+
)
|
|
@@ -0,0 +1,64 @@
|
|
|
1
|
+
Feature: The source and picked option lists notify the consumer when the end has been reached
|
|
2
|
+
|
|
3
|
+
Scenario Outline: The list is displayed initially and the end is not visible
|
|
4
|
+
Given the Transfer has enough items to fill the <type> list completely
|
|
5
|
+
Then the callback for reaching the end should not be called
|
|
6
|
+
|
|
7
|
+
Examples:
|
|
8
|
+
| type |
|
|
9
|
+
| source |
|
|
10
|
+
| picked |
|
|
11
|
+
|
|
12
|
+
Scenario Outline: The list is displayed initially and the end is visible
|
|
13
|
+
Given the Transfer does not have enough items to fill the <type> list completely
|
|
14
|
+
Then the callback for reaching the end should be called
|
|
15
|
+
|
|
16
|
+
Examples:
|
|
17
|
+
| type |
|
|
18
|
+
| source |
|
|
19
|
+
| picked |
|
|
20
|
+
|
|
21
|
+
Scenario Outline: The user scrolls down the list to the end
|
|
22
|
+
Given the Transfer has enough items to fill the <type> list completely
|
|
23
|
+
When the user scroll to the end of the list
|
|
24
|
+
Then the callback for reaching the end should be called
|
|
25
|
+
|
|
26
|
+
Examples:
|
|
27
|
+
| type |
|
|
28
|
+
| source |
|
|
29
|
+
| picked |
|
|
30
|
+
|
|
31
|
+
Scenario: The list is short and items are added within the list container
|
|
32
|
+
Given the Transfer source options list does not fill the list completely
|
|
33
|
+
# Initial state: the list has 7 items and the list ends well above the container bottom
|
|
34
|
+
Then the list end indicator of the source list should be visible
|
|
35
|
+
Then the callback for reaching the end of the source list should be called 1 times
|
|
36
|
+
Then the callback for reaching the end of the picked list should be called 1 times
|
|
37
|
+
# Selected item is not in the options array but is present in the `selectedOptionsLookup`
|
|
38
|
+
Then the selected item is being displayed in the picked list
|
|
39
|
+
When the user adds an item by clicking the button
|
|
40
|
+
# The indicator is still just in view
|
|
41
|
+
Then the list end indicator of the source list should be visible
|
|
42
|
+
Then the callback for reaching the end of the source list should be called 2 times
|
|
43
|
+
When the user adds an item by clicking the button
|
|
44
|
+
# This adds val-9, which is a selected item so it gets added to picked options
|
|
45
|
+
# not source options, but the callback is still called
|
|
46
|
+
Then the list end indicator of the source list should be visible
|
|
47
|
+
Then the callback for reaching the end of the source list should be called 3 times
|
|
48
|
+
# The picked list callback does not get called because the picked item was already present
|
|
49
|
+
Then the callback for reaching the end of the picked list should be called 1 times
|
|
50
|
+
When the user adds an item by clicking the button
|
|
51
|
+
# The indicator is still in view but only just
|
|
52
|
+
Then the list end indicator of the source list should be visible
|
|
53
|
+
Then the callback for reaching the end of the source list should be called 4 times
|
|
54
|
+
When the user adds an item by clicking the button
|
|
55
|
+
# The indicator now is out of view, no more calls
|
|
56
|
+
Then the list end indicator of the source list should not be visible
|
|
57
|
+
Then the callback for reaching the end of the source list should be called 4 times
|
|
58
|
+
# But scrolling down does trigger a call
|
|
59
|
+
When the user scrolls down to the source list end
|
|
60
|
+
Then the list end indicator of the source list should be visible
|
|
61
|
+
Then the callback for reaching the end of the source list should be called 5 times
|
|
62
|
+
# And selecting an item triggers a call in the picked list
|
|
63
|
+
When the user selects option nr. 11
|
|
64
|
+
Then the callback for reaching the end of the picked list should be called 2 times
|