@dhis2-ui/transfer 10.16.1 → 10.16.3-alpha.1

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.
Files changed (109) hide show
  1. package/package.json +10 -9
  2. package/src/__e2e__/add_remove-highlighted-options.e2e.stories.js +30 -0
  3. package/src/__e2e__/common/options.js +90 -0
  4. package/src/__e2e__/common/stateful-decorator.js +33 -0
  5. package/src/__e2e__/common.js +0 -0
  6. package/src/__e2e__/disabled-transfer-buttons.e2e.stories.js +49 -0
  7. package/src/__e2e__/disabled-transfer-options.e2e.stories.js +21 -0
  8. package/src/__e2e__/display-order.e2e.stories.js +24 -0
  9. package/src/__e2e__/filter-options-list.e2e.stories.js +87 -0
  10. package/src/__e2e__/highlight-range-of-options.e2e.stories.js +52 -0
  11. package/src/__e2e__/loading_lists.e2e.stories.js +26 -0
  12. package/src/__e2e__/notify_at_end_of_list.e2e.stories.js +116 -0
  13. package/src/__e2e__/reorder-with-buttons.e2e.stories.js +35 -0
  14. package/src/__e2e__/set_unset-highlighted-option.e2e.stories.js +30 -0
  15. package/src/__e2e__/transferring-items.e2e.stories.js +27 -0
  16. package/src/__tests__/common.test.js +131 -0
  17. package/src/__tests__/helper/add-all-selectable-source-options.test.js +46 -0
  18. package/src/__tests__/helper/add-individual-source-options.test.js +80 -0
  19. package/src/__tests__/helper/default-filter-callback.test.js +45 -0
  20. package/src/__tests__/helper/is-reorder-down-disabled.test.js +96 -0
  21. package/src/__tests__/helper/is-reorder-up-disabled.test.js +96 -0
  22. package/src/__tests__/helper/move-highlighted-picked-option-down.test.js +111 -0
  23. package/src/__tests__/helper/move-highlighted-picked-option-to-bottom.test.js +101 -0
  24. package/src/__tests__/helper/move-highlighted-picked-option-to-top.test.js +101 -0
  25. package/src/__tests__/helper/move-highlighted-picked-option-up.test.js +111 -0
  26. package/src/__tests__/helper/remove-all-picked-options.test.js +29 -0
  27. package/src/__tests__/helper/remove-individual-picked-options.test.js +38 -0
  28. package/src/__tests__/helper/use-highlighted-option/create-toggle-highlighted-option.test.js +104 -0
  29. package/src/__tests__/helper/use-highlighted-option/toggle-add.test.js +84 -0
  30. package/src/__tests__/helper/use-highlighted-option/toggle-range.test.js +150 -0
  31. package/src/__tests__/helper/use-highlighted-option/toggle-replace.test.js +39 -0
  32. package/src/__tests__/helper/use-highlighted-option.test.js +41 -0
  33. package/src/__tests__/reordering-actions.test.js +165 -0
  34. package/src/__tests__/transfer.test.js +137 -0
  35. package/src/actions.js +33 -0
  36. package/src/add-all.js +27 -0
  37. package/src/add-individual.js +27 -0
  38. package/src/common/find-option-index.js +9 -0
  39. package/src/common/get-mode-by-modifier-key.js +35 -0
  40. package/src/common/index.js +5 -0
  41. package/src/common/is-option.js +7 -0
  42. package/src/common/modes.js +11 -0
  43. package/src/common/remove-option.js +19 -0
  44. package/src/common/toggle-value.js +18 -0
  45. package/src/container.js +23 -0
  46. package/src/end-intersection-detector.js +37 -0
  47. package/src/features/add_remove-highlighted-options/index.js +92 -0
  48. package/src/features/add_remove-highlighted-options.feature +41 -0
  49. package/src/features/common/index.js +8 -0
  50. package/src/features/disabled-transfer-buttons/index.js +118 -0
  51. package/src/features/disabled-transfer-buttons.feature +46 -0
  52. package/src/features/disabled-transfer-options/index.js +182 -0
  53. package/src/features/disabled-transfer-options.feature +42 -0
  54. package/src/features/display-order/index.js +205 -0
  55. package/src/features/display-order.feature +30 -0
  56. package/src/features/filter-options-list/index.js +133 -0
  57. package/src/features/filter-options-list.feature +40 -0
  58. package/src/features/highlight-range-of-options/index.js +336 -0
  59. package/src/features/highlight-range-of-options.feature +70 -0
  60. package/src/features/loading_lists/index.js +43 -0
  61. package/src/features/loading_lists.feature +19 -0
  62. package/src/features/notify_at_end_of_list/index.js +125 -0
  63. package/src/features/notify_at_end_of_list.feature +64 -0
  64. package/src/features/reorder-with-buttons/index.js +181 -0
  65. package/src/features/reorder-with-buttons.feature +138 -0
  66. package/src/features/set_unset-highlighted-option/index.js +121 -0
  67. package/src/features/set_unset-highlighted-option.feature +42 -0
  68. package/src/features/transferring-items/index.js +375 -0
  69. package/src/features/transferring-items.feature +44 -0
  70. package/src/filter.js +38 -0
  71. package/src/icons.js +194 -0
  72. package/src/index.js +2 -0
  73. package/src/left-footer.js +22 -0
  74. package/src/left-header.js +22 -0
  75. package/src/left-side.js +34 -0
  76. package/src/locales/en/translations.json +7 -0
  77. package/src/locales/index.js +16 -0
  78. package/src/options-container.js +127 -0
  79. package/src/remove-all.js +27 -0
  80. package/src/remove-individual.js +27 -0
  81. package/src/reordering-actions.js +136 -0
  82. package/src/right-footer.js +22 -0
  83. package/src/right-header.js +22 -0
  84. package/src/right-side.js +33 -0
  85. package/src/transfer/add-all-selectable-source-options.js +37 -0
  86. package/src/transfer/add-individual-source-options.js +61 -0
  87. package/src/transfer/create-double-click-handlers.js +36 -0
  88. package/src/transfer/default-filter-callback.js +17 -0
  89. package/src/transfer/get-highlighted-picked-indices.js +26 -0
  90. package/src/transfer/get-option-click-handlers.js +19 -0
  91. package/src/transfer/index.js +17 -0
  92. package/src/transfer/is-reorder-down-disabled.js +34 -0
  93. package/src/transfer/is-reorder-up-disabled.js +30 -0
  94. package/src/transfer/move-highlighted-picked-option-down.js +54 -0
  95. package/src/transfer/move-highlighted-picked-option-to-bottom.js +44 -0
  96. package/src/transfer/move-highlighted-picked-option-to-top.js +38 -0
  97. package/src/transfer/move-highlighted-picked-option-up.js +47 -0
  98. package/src/transfer/remove-all-picked-options.js +13 -0
  99. package/src/transfer/remove-individual-picked-options.js +49 -0
  100. package/src/transfer/use-filter.js +17 -0
  101. package/src/transfer/use-highlighted-options/create-toggle-highlighted-option.js +64 -0
  102. package/src/transfer/use-highlighted-options/toggle-add.js +20 -0
  103. package/src/transfer/use-highlighted-options/toggle-range.js +61 -0
  104. package/src/transfer/use-highlighted-options/toggle-replace.js +26 -0
  105. package/src/transfer/use-highlighted-options.js +34 -0
  106. package/src/transfer/use-options-key-monitor.js +41 -0
  107. package/src/transfer-option.js +91 -0
  108. package/src/transfer.js +539 -0
  109. 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