@dhis2-ui/transfer 10.13.1 → 10.14.0
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/build/cjs/__e2e__/reorder-with-buttons.e2e.stories.js +15 -4
- package/build/cjs/__tests__/helper/default-filter-callback.test.js +6 -0
- package/build/cjs/__tests__/helper/is-reorder-down-disabled.test.js +50 -11
- package/build/cjs/__tests__/helper/is-reorder-up-disabled.test.js +50 -11
- package/build/cjs/__tests__/helper/move-highlighted-picked-option-down.test.js +65 -11
- package/build/cjs/__tests__/helper/move-highlighted-picked-option-to-bottom.test.js +85 -0
- package/build/cjs/__tests__/helper/move-highlighted-picked-option-to-top.test.js +85 -0
- package/build/cjs/__tests__/helper/move-highlighted-picked-option-up.test.js +65 -11
- package/build/cjs/__tests__/reordering-actions.test.js +104 -0
- package/build/cjs/features/reorder-with-buttons/index.js +70 -2
- package/build/cjs/features/reorder-with-buttons.feature +97 -5
- package/build/cjs/icons.js +53 -13
- package/build/cjs/locales/en/translations.json +7 -0
- package/build/cjs/locales/index.js +21 -0
- package/build/cjs/reordering-actions.js +93 -27
- package/build/cjs/transfer/default-filter-callback.js +17 -6
- package/build/cjs/transfer/get-highlighted-picked-indices.js +34 -0
- package/build/cjs/transfer/index.js +33 -0
- package/build/cjs/transfer/is-reorder-down-disabled.js +19 -8
- package/build/cjs/transfer/is-reorder-up-disabled.js +18 -8
- package/build/cjs/transfer/move-highlighted-picked-option-down.js +23 -6
- package/build/cjs/transfer/move-highlighted-picked-option-to-bottom.js +45 -0
- package/build/cjs/transfer/move-highlighted-picked-option-to-top.js +44 -0
- package/build/cjs/transfer/move-highlighted-picked-option-up.js +21 -6
- package/build/cjs/transfer.js +58 -6
- package/build/cjs/transfer.prod.stories.js +89 -19
- package/build/es/__e2e__/reorder-with-buttons.e2e.stories.js +14 -2
- package/build/es/__tests__/helper/default-filter-callback.test.js +6 -0
- package/build/es/__tests__/helper/is-reorder-down-disabled.test.js +50 -11
- package/build/es/__tests__/helper/is-reorder-up-disabled.test.js +50 -11
- package/build/es/__tests__/helper/move-highlighted-picked-option-down.test.js +65 -11
- package/build/es/__tests__/helper/move-highlighted-picked-option-to-bottom.test.js +83 -0
- package/build/es/__tests__/helper/move-highlighted-picked-option-to-top.test.js +83 -0
- package/build/es/__tests__/helper/move-highlighted-picked-option-up.test.js +65 -11
- package/build/es/__tests__/reordering-actions.test.js +101 -0
- package/build/es/features/reorder-with-buttons/index.js +70 -2
- package/build/es/features/reorder-with-buttons.feature +97 -5
- package/build/es/icons.js +51 -13
- package/build/es/locales/en/translations.json +7 -0
- package/build/es/locales/index.js +13 -0
- package/build/es/reordering-actions.js +94 -28
- package/build/es/transfer/default-filter-callback.js +17 -6
- package/build/es/transfer/get-highlighted-picked-indices.js +27 -0
- package/build/es/transfer/index.js +3 -0
- package/build/es/transfer/is-reorder-down-disabled.js +20 -8
- package/build/es/transfer/is-reorder-up-disabled.js +19 -8
- package/build/es/transfer/move-highlighted-picked-option-down.js +24 -6
- package/build/es/transfer/move-highlighted-picked-option-to-bottom.js +39 -0
- package/build/es/transfer/move-highlighted-picked-option-to-top.js +38 -0
- package/build/es/transfer/move-highlighted-picked-option-up.js +22 -6
- package/build/es/transfer.js +60 -8
- package/build/es/transfer.prod.stories.js +88 -18
- package/package.json +9 -7
|
@@ -37,4 +37,10 @@ describe('Transfer - defaultFilterCallback', () => {
|
|
|
37
37
|
const actual = defaultFilterCallback(options, filter);
|
|
38
38
|
expect(actual).toEqual(expected);
|
|
39
39
|
});
|
|
40
|
+
it('should return all options when the filter is invalid regexp', () => {
|
|
41
|
+
const filter = '(';
|
|
42
|
+
const expected = options;
|
|
43
|
+
const actual = defaultFilterCallback(options, filter);
|
|
44
|
+
expect(actual).toEqual(expected);
|
|
45
|
+
});
|
|
40
46
|
});
|
|
@@ -2,35 +2,74 @@ import { isReorderDownDisabled } from '../../transfer/is-reorder-down-disabled.j
|
|
|
2
2
|
describe('Transfer - isReorderDownDisabled', () => {
|
|
3
3
|
const selected = ['foo', 'bar', 'baz'];
|
|
4
4
|
it('should return true when there are no highlighted picked options', () => {
|
|
5
|
-
const highlightedPickedOptions = [];
|
|
6
5
|
const actual = isReorderDownDisabled({
|
|
7
|
-
highlightedPickedOptions,
|
|
6
|
+
highlightedPickedOptions: [],
|
|
8
7
|
selected
|
|
9
8
|
});
|
|
10
9
|
expect(actual).toBe(true);
|
|
11
10
|
});
|
|
12
|
-
it('should return true
|
|
13
|
-
const highlightedPickedOptions = ['bar', 'foo'];
|
|
11
|
+
it('should return true if the last picked option is the only highlighted one', () => {
|
|
14
12
|
const actual = isReorderDownDisabled({
|
|
15
|
-
highlightedPickedOptions,
|
|
13
|
+
highlightedPickedOptions: ['baz'],
|
|
16
14
|
selected
|
|
17
15
|
});
|
|
18
16
|
expect(actual).toBe(true);
|
|
19
17
|
});
|
|
20
|
-
it('should return
|
|
21
|
-
const
|
|
18
|
+
it('should return false when one picked option is highlighted which is not the last one', () => {
|
|
19
|
+
const actual = isReorderDownDisabled({
|
|
20
|
+
highlightedPickedOptions: ['bar'],
|
|
21
|
+
selected
|
|
22
|
+
});
|
|
23
|
+
expect(actual).toBe(false);
|
|
24
|
+
});
|
|
25
|
+
it('should return false for a contiguous multi-select not flush to the bottom', () => {
|
|
26
|
+
const actual = isReorderDownDisabled({
|
|
27
|
+
highlightedPickedOptions: ['foo', 'bar'],
|
|
28
|
+
selected
|
|
29
|
+
});
|
|
30
|
+
expect(actual).toBe(false);
|
|
31
|
+
});
|
|
32
|
+
it('should return true for a contiguous multi-select flush to the bottom', () => {
|
|
22
33
|
const actual = isReorderDownDisabled({
|
|
23
|
-
highlightedPickedOptions,
|
|
34
|
+
highlightedPickedOptions: ['bar', 'baz'],
|
|
24
35
|
selected
|
|
25
36
|
});
|
|
26
37
|
expect(actual).toBe(true);
|
|
27
38
|
});
|
|
28
|
-
it('should return
|
|
29
|
-
const highlightedPickedOptions = ['bar'];
|
|
39
|
+
it('should return true when all items are highlighted', () => {
|
|
30
40
|
const actual = isReorderDownDisabled({
|
|
31
|
-
highlightedPickedOptions,
|
|
41
|
+
highlightedPickedOptions: ['foo', 'bar', 'baz'],
|
|
42
|
+
selected
|
|
43
|
+
});
|
|
44
|
+
expect(actual).toBe(true);
|
|
45
|
+
});
|
|
46
|
+
it('should return false for a non-contiguous selection containing the last item', () => {
|
|
47
|
+
const actual = isReorderDownDisabled({
|
|
48
|
+
highlightedPickedOptions: ['foo', 'baz'],
|
|
49
|
+
selected
|
|
50
|
+
});
|
|
51
|
+
expect(actual).toBe(false);
|
|
52
|
+
});
|
|
53
|
+
it('should ignore highlighted values that do not exist in selected', () => {
|
|
54
|
+
const actual = isReorderDownDisabled({
|
|
55
|
+
highlightedPickedOptions: ['ghost', 'foo'],
|
|
32
56
|
selected
|
|
33
57
|
});
|
|
34
58
|
expect(actual).toBe(false);
|
|
35
59
|
});
|
|
60
|
+
it('should return true when all highlighted values are missing from selected', () => {
|
|
61
|
+
const actual = isReorderDownDisabled({
|
|
62
|
+
highlightedPickedOptions: ['ghost'],
|
|
63
|
+
selected
|
|
64
|
+
});
|
|
65
|
+
expect(actual).toBe(true);
|
|
66
|
+
});
|
|
67
|
+
it('should return true when a filter is active on the picked side', () => {
|
|
68
|
+
const actual = isReorderDownDisabled({
|
|
69
|
+
highlightedPickedOptions: ['foo'],
|
|
70
|
+
selected,
|
|
71
|
+
filterActivePicked: true
|
|
72
|
+
});
|
|
73
|
+
expect(actual).toBe(true);
|
|
74
|
+
});
|
|
36
75
|
});
|
|
@@ -2,35 +2,74 @@ import { isReorderUpDisabled } from '../../transfer/is-reorder-up-disabled.js';
|
|
|
2
2
|
describe('Transfer - isReorderUpDisabled', () => {
|
|
3
3
|
const selected = ['foo', 'bar', 'baz'];
|
|
4
4
|
it('should return true when there are no highlighted picked options', () => {
|
|
5
|
-
const highlightedPickedOptions = [];
|
|
6
5
|
const actual = isReorderUpDisabled({
|
|
7
|
-
highlightedPickedOptions,
|
|
6
|
+
highlightedPickedOptions: [],
|
|
8
7
|
selected
|
|
9
8
|
});
|
|
10
9
|
expect(actual).toBe(true);
|
|
11
10
|
});
|
|
12
|
-
it('should return true
|
|
13
|
-
const highlightedPickedOptions = ['bar', 'baz'];
|
|
11
|
+
it('should return true if the first picked option is the only highlighted one', () => {
|
|
14
12
|
const actual = isReorderUpDisabled({
|
|
15
|
-
highlightedPickedOptions,
|
|
13
|
+
highlightedPickedOptions: ['foo'],
|
|
16
14
|
selected
|
|
17
15
|
});
|
|
18
16
|
expect(actual).toBe(true);
|
|
19
17
|
});
|
|
20
|
-
it('should return
|
|
21
|
-
const highlightedPickedOptions = ['foo'];
|
|
18
|
+
it('should return false when one picked option is highlighted which is not the first one', () => {
|
|
22
19
|
const actual = isReorderUpDisabled({
|
|
23
|
-
highlightedPickedOptions,
|
|
20
|
+
highlightedPickedOptions: ['baz'],
|
|
21
|
+
selected
|
|
22
|
+
});
|
|
23
|
+
expect(actual).toBe(false);
|
|
24
|
+
});
|
|
25
|
+
it('should return false for a contiguous multi-select not flush to the top', () => {
|
|
26
|
+
const actual = isReorderUpDisabled({
|
|
27
|
+
highlightedPickedOptions: ['bar', 'baz'],
|
|
28
|
+
selected
|
|
29
|
+
});
|
|
30
|
+
expect(actual).toBe(false);
|
|
31
|
+
});
|
|
32
|
+
it('should return true for a contiguous multi-select flush to the top', () => {
|
|
33
|
+
const actual = isReorderUpDisabled({
|
|
34
|
+
highlightedPickedOptions: ['foo', 'bar'],
|
|
35
|
+
selected
|
|
36
|
+
});
|
|
37
|
+
expect(actual).toBe(true);
|
|
38
|
+
});
|
|
39
|
+
it('should return true when all items are highlighted', () => {
|
|
40
|
+
const actual = isReorderUpDisabled({
|
|
41
|
+
highlightedPickedOptions: ['foo', 'bar', 'baz'],
|
|
24
42
|
selected
|
|
25
43
|
});
|
|
26
44
|
expect(actual).toBe(true);
|
|
27
45
|
});
|
|
28
|
-
it('should return false
|
|
29
|
-
const highlightedPickedOptions = ['baz'];
|
|
46
|
+
it('should return false for a non-contiguous selection containing the first item', () => {
|
|
30
47
|
const actual = isReorderUpDisabled({
|
|
31
|
-
highlightedPickedOptions,
|
|
48
|
+
highlightedPickedOptions: ['foo', 'baz'],
|
|
32
49
|
selected
|
|
33
50
|
});
|
|
34
51
|
expect(actual).toBe(false);
|
|
35
52
|
});
|
|
53
|
+
it('should ignore highlighted values that do not exist in selected', () => {
|
|
54
|
+
const actual = isReorderUpDisabled({
|
|
55
|
+
highlightedPickedOptions: ['ghost', 'baz'],
|
|
56
|
+
selected
|
|
57
|
+
});
|
|
58
|
+
expect(actual).toBe(false);
|
|
59
|
+
});
|
|
60
|
+
it('should return true when all highlighted values are missing from selected', () => {
|
|
61
|
+
const actual = isReorderUpDisabled({
|
|
62
|
+
highlightedPickedOptions: ['ghost'],
|
|
63
|
+
selected
|
|
64
|
+
});
|
|
65
|
+
expect(actual).toBe(true);
|
|
66
|
+
});
|
|
67
|
+
it('should return true when a filter is active on the picked side', () => {
|
|
68
|
+
const actual = isReorderUpDisabled({
|
|
69
|
+
highlightedPickedOptions: ['baz'],
|
|
70
|
+
selected,
|
|
71
|
+
filterActivePicked: true
|
|
72
|
+
});
|
|
73
|
+
expect(actual).toBe(true);
|
|
74
|
+
});
|
|
36
75
|
});
|
|
@@ -1,15 +1,13 @@
|
|
|
1
1
|
import { moveHighlightedPickedOptionDown } from '../../transfer/move-highlighted-picked-option-down.js';
|
|
2
2
|
describe('Transfer - moveHighlightedPickedOptionDown', () => {
|
|
3
3
|
const onChange = jest.fn();
|
|
4
|
-
const selected = ['foo', 'bar', 'baz'];
|
|
5
4
|
afterEach(() => {
|
|
6
5
|
onChange.mockClear();
|
|
7
6
|
});
|
|
8
|
-
it('should move
|
|
9
|
-
const highlighted = ['bar'];
|
|
7
|
+
it('should move a single highlighted option down', () => {
|
|
10
8
|
moveHighlightedPickedOptionDown({
|
|
11
|
-
selected,
|
|
12
|
-
highlightedPickedOptions:
|
|
9
|
+
selected: ['foo', 'bar', 'baz'],
|
|
10
|
+
highlightedPickedOptions: ['bar'],
|
|
13
11
|
onChange
|
|
14
12
|
});
|
|
15
13
|
expect(onChange).toHaveBeenCalledWith({
|
|
@@ -17,21 +15,77 @@ describe('Transfer - moveHighlightedPickedOptionDown', () => {
|
|
|
17
15
|
});
|
|
18
16
|
});
|
|
19
17
|
it('should do nothing when trying to move down the last option', () => {
|
|
20
|
-
const highlighted = ['baz'];
|
|
21
18
|
moveHighlightedPickedOptionDown({
|
|
22
|
-
selected,
|
|
23
|
-
highlightedPickedOptions:
|
|
19
|
+
selected: ['foo', 'bar', 'baz'],
|
|
20
|
+
highlightedPickedOptions: ['baz'],
|
|
24
21
|
onChange
|
|
25
22
|
});
|
|
26
23
|
expect(onChange).toHaveBeenCalledTimes(0);
|
|
27
24
|
});
|
|
28
25
|
it('should do nothing when trying to move down a non-existing option', () => {
|
|
29
|
-
const highlighted = ['foobar'];
|
|
30
26
|
moveHighlightedPickedOptionDown({
|
|
31
|
-
selected,
|
|
32
|
-
highlightedPickedOptions:
|
|
27
|
+
selected: ['foo', 'bar', 'baz'],
|
|
28
|
+
highlightedPickedOptions: ['ghost'],
|
|
33
29
|
onChange
|
|
34
30
|
});
|
|
35
31
|
expect(onChange).toHaveBeenCalledTimes(0);
|
|
36
32
|
});
|
|
33
|
+
it('should shift a contiguous block of highlighted options down as a group', () => {
|
|
34
|
+
moveHighlightedPickedOptionDown({
|
|
35
|
+
selected: ['a', 'b', 'c', 'd', 'e'],
|
|
36
|
+
highlightedPickedOptions: ['b', 'c'],
|
|
37
|
+
onChange
|
|
38
|
+
});
|
|
39
|
+
expect(onChange).toHaveBeenCalledWith({
|
|
40
|
+
selected: ['a', 'd', 'b', 'c', 'e']
|
|
41
|
+
});
|
|
42
|
+
});
|
|
43
|
+
it('should collapse and shift a non-contiguous selection down in one call', () => {
|
|
44
|
+
moveHighlightedPickedOptionDown({
|
|
45
|
+
selected: ['a', 'b', 'c', 'd', 'e'],
|
|
46
|
+
highlightedPickedOptions: ['b', 'd'],
|
|
47
|
+
onChange
|
|
48
|
+
});
|
|
49
|
+
expect(onChange).toHaveBeenCalledWith({
|
|
50
|
+
selected: ['a', 'c', 'e', 'b', 'd']
|
|
51
|
+
});
|
|
52
|
+
});
|
|
53
|
+
it('should preserve the relative order of highlighted items regardless of input order', () => {
|
|
54
|
+
moveHighlightedPickedOptionDown({
|
|
55
|
+
selected: ['a', 'b', 'c', 'd', 'e'],
|
|
56
|
+
highlightedPickedOptions: ['d', 'b'],
|
|
57
|
+
onChange
|
|
58
|
+
});
|
|
59
|
+
expect(onChange).toHaveBeenCalledWith({
|
|
60
|
+
selected: ['a', 'c', 'e', 'b', 'd']
|
|
61
|
+
});
|
|
62
|
+
});
|
|
63
|
+
it('should collapse a non-contiguous selection containing the last item without shifting past the end', () => {
|
|
64
|
+
moveHighlightedPickedOptionDown({
|
|
65
|
+
selected: ['a', 'b', 'c'],
|
|
66
|
+
highlightedPickedOptions: ['a', 'c'],
|
|
67
|
+
onChange
|
|
68
|
+
});
|
|
69
|
+
expect(onChange).toHaveBeenCalledWith({
|
|
70
|
+
selected: ['b', 'a', 'c']
|
|
71
|
+
});
|
|
72
|
+
});
|
|
73
|
+
it('should do nothing when the highlighted block is already flush to the bottom', () => {
|
|
74
|
+
moveHighlightedPickedOptionDown({
|
|
75
|
+
selected: ['a', 'b', 'c', 'd'],
|
|
76
|
+
highlightedPickedOptions: ['c', 'd'],
|
|
77
|
+
onChange
|
|
78
|
+
});
|
|
79
|
+
expect(onChange).toHaveBeenCalledTimes(0);
|
|
80
|
+
});
|
|
81
|
+
it('should ignore highlighted values that do not exist in selected', () => {
|
|
82
|
+
moveHighlightedPickedOptionDown({
|
|
83
|
+
selected: ['a', 'b', 'c'],
|
|
84
|
+
highlightedPickedOptions: ['ghost', 'a'],
|
|
85
|
+
onChange
|
|
86
|
+
});
|
|
87
|
+
expect(onChange).toHaveBeenCalledWith({
|
|
88
|
+
selected: ['b', 'a', 'c']
|
|
89
|
+
});
|
|
90
|
+
});
|
|
37
91
|
});
|
|
@@ -0,0 +1,83 @@
|
|
|
1
|
+
import { moveHighlightedPickedOptionToBottom } from '../../transfer/move-highlighted-picked-option-to-bottom.js';
|
|
2
|
+
describe('Transfer - moveHighlightedPickedOptionToBottom', () => {
|
|
3
|
+
const onChange = jest.fn();
|
|
4
|
+
afterEach(() => {
|
|
5
|
+
onChange.mockClear();
|
|
6
|
+
});
|
|
7
|
+
it('should move a single highlighted option to the bottom', () => {
|
|
8
|
+
moveHighlightedPickedOptionToBottom({
|
|
9
|
+
selected: ['a', 'b', 'c', 'd'],
|
|
10
|
+
highlightedPickedOptions: ['b'],
|
|
11
|
+
onChange
|
|
12
|
+
});
|
|
13
|
+
expect(onChange).toHaveBeenCalledWith({
|
|
14
|
+
selected: ['a', 'c', 'd', 'b']
|
|
15
|
+
});
|
|
16
|
+
});
|
|
17
|
+
it('should move a contiguous block to the bottom as a group', () => {
|
|
18
|
+
moveHighlightedPickedOptionToBottom({
|
|
19
|
+
selected: ['a', 'b', 'c', 'd', 'e'],
|
|
20
|
+
highlightedPickedOptions: ['b', 'c'],
|
|
21
|
+
onChange
|
|
22
|
+
});
|
|
23
|
+
expect(onChange).toHaveBeenCalledWith({
|
|
24
|
+
selected: ['a', 'd', 'e', 'b', 'c']
|
|
25
|
+
});
|
|
26
|
+
});
|
|
27
|
+
it('should collapse a non-contiguous selection to the bottom preserving relative order', () => {
|
|
28
|
+
moveHighlightedPickedOptionToBottom({
|
|
29
|
+
selected: ['a', 'b', 'c', 'd', 'e'],
|
|
30
|
+
highlightedPickedOptions: ['b', 'd'],
|
|
31
|
+
onChange
|
|
32
|
+
});
|
|
33
|
+
expect(onChange).toHaveBeenCalledWith({
|
|
34
|
+
selected: ['a', 'c', 'e', 'b', 'd']
|
|
35
|
+
});
|
|
36
|
+
});
|
|
37
|
+
it('should preserve relative order regardless of highlight input order', () => {
|
|
38
|
+
moveHighlightedPickedOptionToBottom({
|
|
39
|
+
selected: ['a', 'b', 'c', 'd', 'e'],
|
|
40
|
+
highlightedPickedOptions: ['d', 'b'],
|
|
41
|
+
onChange
|
|
42
|
+
});
|
|
43
|
+
expect(onChange).toHaveBeenCalledWith({
|
|
44
|
+
selected: ['a', 'c', 'e', 'b', 'd']
|
|
45
|
+
});
|
|
46
|
+
});
|
|
47
|
+
it('should do nothing when the highlighted block is already flush to the bottom', () => {
|
|
48
|
+
moveHighlightedPickedOptionToBottom({
|
|
49
|
+
selected: ['a', 'b', 'c', 'd'],
|
|
50
|
+
highlightedPickedOptions: ['c', 'd'],
|
|
51
|
+
onChange
|
|
52
|
+
});
|
|
53
|
+
expect(onChange).toHaveBeenCalledTimes(0);
|
|
54
|
+
});
|
|
55
|
+
it('should still run when the selection includes the bottom item but has a gap', () => {
|
|
56
|
+
moveHighlightedPickedOptionToBottom({
|
|
57
|
+
selected: ['a', 'b', 'c', 'd'],
|
|
58
|
+
highlightedPickedOptions: ['b', 'd'],
|
|
59
|
+
onChange
|
|
60
|
+
});
|
|
61
|
+
expect(onChange).toHaveBeenCalledWith({
|
|
62
|
+
selected: ['a', 'c', 'b', 'd']
|
|
63
|
+
});
|
|
64
|
+
});
|
|
65
|
+
it('should do nothing when no highlighted options exist in selected', () => {
|
|
66
|
+
moveHighlightedPickedOptionToBottom({
|
|
67
|
+
selected: ['a', 'b', 'c'],
|
|
68
|
+
highlightedPickedOptions: ['ghost'],
|
|
69
|
+
onChange
|
|
70
|
+
});
|
|
71
|
+
expect(onChange).toHaveBeenCalledTimes(0);
|
|
72
|
+
});
|
|
73
|
+
it('should ignore highlighted values that do not exist in selected', () => {
|
|
74
|
+
moveHighlightedPickedOptionToBottom({
|
|
75
|
+
selected: ['a', 'b', 'c'],
|
|
76
|
+
highlightedPickedOptions: ['ghost', 'a'],
|
|
77
|
+
onChange
|
|
78
|
+
});
|
|
79
|
+
expect(onChange).toHaveBeenCalledWith({
|
|
80
|
+
selected: ['b', 'c', 'a']
|
|
81
|
+
});
|
|
82
|
+
});
|
|
83
|
+
});
|
|
@@ -0,0 +1,83 @@
|
|
|
1
|
+
import { moveHighlightedPickedOptionToTop } from '../../transfer/move-highlighted-picked-option-to-top.js';
|
|
2
|
+
describe('Transfer - moveHighlightedPickedOptionToTop', () => {
|
|
3
|
+
const onChange = jest.fn();
|
|
4
|
+
afterEach(() => {
|
|
5
|
+
onChange.mockClear();
|
|
6
|
+
});
|
|
7
|
+
it('should move a single highlighted option to the top', () => {
|
|
8
|
+
moveHighlightedPickedOptionToTop({
|
|
9
|
+
selected: ['a', 'b', 'c', 'd'],
|
|
10
|
+
highlightedPickedOptions: ['c'],
|
|
11
|
+
onChange
|
|
12
|
+
});
|
|
13
|
+
expect(onChange).toHaveBeenCalledWith({
|
|
14
|
+
selected: ['c', 'a', 'b', 'd']
|
|
15
|
+
});
|
|
16
|
+
});
|
|
17
|
+
it('should move a contiguous block to the top as a group', () => {
|
|
18
|
+
moveHighlightedPickedOptionToTop({
|
|
19
|
+
selected: ['a', 'b', 'c', 'd', 'e'],
|
|
20
|
+
highlightedPickedOptions: ['c', 'd'],
|
|
21
|
+
onChange
|
|
22
|
+
});
|
|
23
|
+
expect(onChange).toHaveBeenCalledWith({
|
|
24
|
+
selected: ['c', 'd', 'a', 'b', 'e']
|
|
25
|
+
});
|
|
26
|
+
});
|
|
27
|
+
it('should collapse a non-contiguous selection to the top preserving relative order', () => {
|
|
28
|
+
moveHighlightedPickedOptionToTop({
|
|
29
|
+
selected: ['a', 'b', 'c', 'd', 'e'],
|
|
30
|
+
highlightedPickedOptions: ['b', 'd'],
|
|
31
|
+
onChange
|
|
32
|
+
});
|
|
33
|
+
expect(onChange).toHaveBeenCalledWith({
|
|
34
|
+
selected: ['b', 'd', 'a', 'c', 'e']
|
|
35
|
+
});
|
|
36
|
+
});
|
|
37
|
+
it('should preserve relative order regardless of highlight input order', () => {
|
|
38
|
+
moveHighlightedPickedOptionToTop({
|
|
39
|
+
selected: ['a', 'b', 'c', 'd', 'e'],
|
|
40
|
+
highlightedPickedOptions: ['d', 'b'],
|
|
41
|
+
onChange
|
|
42
|
+
});
|
|
43
|
+
expect(onChange).toHaveBeenCalledWith({
|
|
44
|
+
selected: ['b', 'd', 'a', 'c', 'e']
|
|
45
|
+
});
|
|
46
|
+
});
|
|
47
|
+
it('should do nothing when the highlighted block is already flush to the top', () => {
|
|
48
|
+
moveHighlightedPickedOptionToTop({
|
|
49
|
+
selected: ['a', 'b', 'c', 'd'],
|
|
50
|
+
highlightedPickedOptions: ['a', 'b'],
|
|
51
|
+
onChange
|
|
52
|
+
});
|
|
53
|
+
expect(onChange).toHaveBeenCalledTimes(0);
|
|
54
|
+
});
|
|
55
|
+
it('should still run when the selection includes the top item but has a gap', () => {
|
|
56
|
+
moveHighlightedPickedOptionToTop({
|
|
57
|
+
selected: ['a', 'b', 'c', 'd'],
|
|
58
|
+
highlightedPickedOptions: ['a', 'c'],
|
|
59
|
+
onChange
|
|
60
|
+
});
|
|
61
|
+
expect(onChange).toHaveBeenCalledWith({
|
|
62
|
+
selected: ['a', 'c', 'b', 'd']
|
|
63
|
+
});
|
|
64
|
+
});
|
|
65
|
+
it('should do nothing when no highlighted options exist in selected', () => {
|
|
66
|
+
moveHighlightedPickedOptionToTop({
|
|
67
|
+
selected: ['a', 'b', 'c'],
|
|
68
|
+
highlightedPickedOptions: ['ghost'],
|
|
69
|
+
onChange
|
|
70
|
+
});
|
|
71
|
+
expect(onChange).toHaveBeenCalledTimes(0);
|
|
72
|
+
});
|
|
73
|
+
it('should ignore highlighted values that do not exist in selected', () => {
|
|
74
|
+
moveHighlightedPickedOptionToTop({
|
|
75
|
+
selected: ['a', 'b', 'c'],
|
|
76
|
+
highlightedPickedOptions: ['ghost', 'c'],
|
|
77
|
+
onChange
|
|
78
|
+
});
|
|
79
|
+
expect(onChange).toHaveBeenCalledWith({
|
|
80
|
+
selected: ['c', 'a', 'b']
|
|
81
|
+
});
|
|
82
|
+
});
|
|
83
|
+
});
|
|
@@ -1,15 +1,13 @@
|
|
|
1
1
|
import { moveHighlightedPickedOptionUp } from '../../transfer/move-highlighted-picked-option-up.js';
|
|
2
2
|
describe('Transfer - moveHighlightedPickedOptionUp', () => {
|
|
3
3
|
const onChange = jest.fn();
|
|
4
|
-
const selected = ['foo', 'bar', 'baz'];
|
|
5
4
|
afterEach(() => {
|
|
6
5
|
onChange.mockClear();
|
|
7
6
|
});
|
|
8
|
-
it('should move
|
|
9
|
-
const highlighted = ['bar'];
|
|
7
|
+
it('should move a single highlighted option up', () => {
|
|
10
8
|
moveHighlightedPickedOptionUp({
|
|
11
|
-
selected,
|
|
12
|
-
highlightedPickedOptions:
|
|
9
|
+
selected: ['foo', 'bar', 'baz'],
|
|
10
|
+
highlightedPickedOptions: ['bar'],
|
|
13
11
|
onChange
|
|
14
12
|
});
|
|
15
13
|
expect(onChange).toHaveBeenCalledWith({
|
|
@@ -17,21 +15,77 @@ describe('Transfer - moveHighlightedPickedOptionUp', () => {
|
|
|
17
15
|
});
|
|
18
16
|
});
|
|
19
17
|
it('should do nothing when trying to move up the first option', () => {
|
|
20
|
-
const highlighted = ['foo'];
|
|
21
18
|
moveHighlightedPickedOptionUp({
|
|
22
|
-
selected,
|
|
23
|
-
highlightedPickedOptions:
|
|
19
|
+
selected: ['foo', 'bar', 'baz'],
|
|
20
|
+
highlightedPickedOptions: ['foo'],
|
|
24
21
|
onChange
|
|
25
22
|
});
|
|
26
23
|
expect(onChange).toHaveBeenCalledTimes(0);
|
|
27
24
|
});
|
|
28
25
|
it('should do nothing when trying to move up a non-existing option', () => {
|
|
29
|
-
const highlighted = ['foobar'];
|
|
30
26
|
moveHighlightedPickedOptionUp({
|
|
31
|
-
selected,
|
|
32
|
-
highlightedPickedOptions:
|
|
27
|
+
selected: ['foo', 'bar', 'baz'],
|
|
28
|
+
highlightedPickedOptions: ['ghost'],
|
|
33
29
|
onChange
|
|
34
30
|
});
|
|
35
31
|
expect(onChange).toHaveBeenCalledTimes(0);
|
|
36
32
|
});
|
|
33
|
+
it('should shift a contiguous block of highlighted options up as a group', () => {
|
|
34
|
+
moveHighlightedPickedOptionUp({
|
|
35
|
+
selected: ['a', 'b', 'c', 'd', 'e'],
|
|
36
|
+
highlightedPickedOptions: ['c', 'd'],
|
|
37
|
+
onChange
|
|
38
|
+
});
|
|
39
|
+
expect(onChange).toHaveBeenCalledWith({
|
|
40
|
+
selected: ['a', 'c', 'd', 'b', 'e']
|
|
41
|
+
});
|
|
42
|
+
});
|
|
43
|
+
it('should collapse and shift a non-contiguous selection up in one call', () => {
|
|
44
|
+
moveHighlightedPickedOptionUp({
|
|
45
|
+
selected: ['a', 'b', 'c', 'd', 'e'],
|
|
46
|
+
highlightedPickedOptions: ['b', 'd'],
|
|
47
|
+
onChange
|
|
48
|
+
});
|
|
49
|
+
expect(onChange).toHaveBeenCalledWith({
|
|
50
|
+
selected: ['b', 'd', 'a', 'c', 'e']
|
|
51
|
+
});
|
|
52
|
+
});
|
|
53
|
+
it('should preserve the relative order of highlighted items regardless of input order', () => {
|
|
54
|
+
moveHighlightedPickedOptionUp({
|
|
55
|
+
selected: ['a', 'b', 'c', 'd', 'e'],
|
|
56
|
+
highlightedPickedOptions: ['d', 'b'],
|
|
57
|
+
onChange
|
|
58
|
+
});
|
|
59
|
+
expect(onChange).toHaveBeenCalledWith({
|
|
60
|
+
selected: ['b', 'd', 'a', 'c', 'e']
|
|
61
|
+
});
|
|
62
|
+
});
|
|
63
|
+
it('should collapse a non-contiguous selection containing the first item without shifting past index 0', () => {
|
|
64
|
+
moveHighlightedPickedOptionUp({
|
|
65
|
+
selected: ['a', 'b', 'c'],
|
|
66
|
+
highlightedPickedOptions: ['a', 'c'],
|
|
67
|
+
onChange
|
|
68
|
+
});
|
|
69
|
+
expect(onChange).toHaveBeenCalledWith({
|
|
70
|
+
selected: ['a', 'c', 'b']
|
|
71
|
+
});
|
|
72
|
+
});
|
|
73
|
+
it('should do nothing when the highlighted block is already flush to the top', () => {
|
|
74
|
+
moveHighlightedPickedOptionUp({
|
|
75
|
+
selected: ['a', 'b', 'c', 'd'],
|
|
76
|
+
highlightedPickedOptions: ['a', 'b'],
|
|
77
|
+
onChange
|
|
78
|
+
});
|
|
79
|
+
expect(onChange).toHaveBeenCalledTimes(0);
|
|
80
|
+
});
|
|
81
|
+
it('should ignore highlighted values that do not exist in selected', () => {
|
|
82
|
+
moveHighlightedPickedOptionUp({
|
|
83
|
+
selected: ['a', 'b', 'c'],
|
|
84
|
+
highlightedPickedOptions: ['ghost', 'c'],
|
|
85
|
+
onChange
|
|
86
|
+
});
|
|
87
|
+
expect(onChange).toHaveBeenCalledWith({
|
|
88
|
+
selected: ['a', 'c', 'b']
|
|
89
|
+
});
|
|
90
|
+
});
|
|
37
91
|
});
|
|
@@ -0,0 +1,101 @@
|
|
|
1
|
+
function _extends() { return _extends = Object.assign ? Object.assign.bind() : function (n) { for (var e = 1; e < arguments.length; e++) { var t = arguments[e]; for (var r in t) ({}).hasOwnProperty.call(t, r) && (n[r] = t[r]); } return n; }, _extends.apply(null, arguments); }
|
|
2
|
+
import { mount } from 'enzyme';
|
|
3
|
+
import React from 'react';
|
|
4
|
+
import { ReorderingActions } from '../reordering-actions.js';
|
|
5
|
+
const findButton = (wrapper, dataTest) => wrapper.find(`button[data-test="${dataTest}"]`);
|
|
6
|
+
const allButtonHooks = dataTest => [`${dataTest}-buttonmovetotop`, `${dataTest}-buttonmoveup`, `${dataTest}-buttonmovedown`, `${dataTest}-buttonmovetobottom`];
|
|
7
|
+
describe('Transfer - ReorderingActions', () => {
|
|
8
|
+
const dataTest = 'test-reorderingactions';
|
|
9
|
+
const baseProps = {
|
|
10
|
+
dataTest,
|
|
11
|
+
onChangeUp: jest.fn(),
|
|
12
|
+
onChangeDown: jest.fn(),
|
|
13
|
+
onChangeToTop: jest.fn(),
|
|
14
|
+
onChangeToBottom: jest.fn()
|
|
15
|
+
};
|
|
16
|
+
afterEach(() => {
|
|
17
|
+
Object.values(baseProps).forEach(value => {
|
|
18
|
+
if (jest.isMockFunction(value)) {
|
|
19
|
+
value.mockClear();
|
|
20
|
+
}
|
|
21
|
+
});
|
|
22
|
+
});
|
|
23
|
+
it('renders all four reorder buttons', () => {
|
|
24
|
+
const wrapper = mount(/*#__PURE__*/React.createElement(ReorderingActions, baseProps));
|
|
25
|
+
expect(findButton(wrapper, `${dataTest}-buttonmovetotop`)).toHaveLength(1);
|
|
26
|
+
expect(findButton(wrapper, `${dataTest}-buttonmoveup`)).toHaveLength(1);
|
|
27
|
+
expect(findButton(wrapper, `${dataTest}-buttonmovedown`)).toHaveLength(1);
|
|
28
|
+
expect(findButton(wrapper, `${dataTest}-buttonmovetobottom`)).toHaveLength(1);
|
|
29
|
+
});
|
|
30
|
+
it('invokes the corresponding handler for each button', () => {
|
|
31
|
+
const wrapper = mount(/*#__PURE__*/React.createElement(ReorderingActions, baseProps));
|
|
32
|
+
findButton(wrapper, `${dataTest}-buttonmovetotop`).simulate('click');
|
|
33
|
+
expect(baseProps.onChangeToTop).toHaveBeenCalledTimes(1);
|
|
34
|
+
findButton(wrapper, `${dataTest}-buttonmoveup`).simulate('click');
|
|
35
|
+
expect(baseProps.onChangeUp).toHaveBeenCalledTimes(1);
|
|
36
|
+
findButton(wrapper, `${dataTest}-buttonmovedown`).simulate('click');
|
|
37
|
+
expect(baseProps.onChangeDown).toHaveBeenCalledTimes(1);
|
|
38
|
+
findButton(wrapper, `${dataTest}-buttonmovetobottom`).simulate('click');
|
|
39
|
+
expect(baseProps.onChangeToBottom).toHaveBeenCalledTimes(1);
|
|
40
|
+
});
|
|
41
|
+
it('does not cross-fire handlers when a single button is clicked', () => {
|
|
42
|
+
const wrapper = mount(/*#__PURE__*/React.createElement(ReorderingActions, baseProps));
|
|
43
|
+
findButton(wrapper, `${dataTest}-buttonmoveup`).simulate('click');
|
|
44
|
+
expect(baseProps.onChangeUp).toHaveBeenCalledTimes(1);
|
|
45
|
+
expect(baseProps.onChangeDown).not.toHaveBeenCalled();
|
|
46
|
+
expect(baseProps.onChangeToTop).not.toHaveBeenCalled();
|
|
47
|
+
expect(baseProps.onChangeToBottom).not.toHaveBeenCalled();
|
|
48
|
+
});
|
|
49
|
+
it('disables both up-side buttons when disabledUp is true', () => {
|
|
50
|
+
const wrapper = mount(/*#__PURE__*/React.createElement(ReorderingActions, _extends({}, baseProps, {
|
|
51
|
+
disabledUp: true
|
|
52
|
+
})));
|
|
53
|
+
expect(findButton(wrapper, `${dataTest}-buttonmovetotop`).prop('disabled')).toBe(true);
|
|
54
|
+
expect(findButton(wrapper, `${dataTest}-buttonmoveup`).prop('disabled')).toBe(true);
|
|
55
|
+
expect(findButton(wrapper, `${dataTest}-buttonmovedown`).prop('disabled')).toBeFalsy();
|
|
56
|
+
expect(findButton(wrapper, `${dataTest}-buttonmovetobottom`).prop('disabled')).toBeFalsy();
|
|
57
|
+
});
|
|
58
|
+
it('disables both down-side buttons when disabledDown is true', () => {
|
|
59
|
+
const wrapper = mount(/*#__PURE__*/React.createElement(ReorderingActions, _extends({}, baseProps, {
|
|
60
|
+
disabledDown: true
|
|
61
|
+
})));
|
|
62
|
+
expect(findButton(wrapper, `${dataTest}-buttonmovedown`).prop('disabled')).toBe(true);
|
|
63
|
+
expect(findButton(wrapper, `${dataTest}-buttonmovetobottom`).prop('disabled')).toBe(true);
|
|
64
|
+
expect(findButton(wrapper, `${dataTest}-buttonmoveup`).prop('disabled')).toBeFalsy();
|
|
65
|
+
expect(findButton(wrapper, `${dataTest}-buttonmovetotop`).prop('disabled')).toBeFalsy();
|
|
66
|
+
});
|
|
67
|
+
it('does not invoke handlers for disabled buttons', () => {
|
|
68
|
+
const wrapper = mount(/*#__PURE__*/React.createElement(ReorderingActions, _extends({}, baseProps, {
|
|
69
|
+
disabledUp: true,
|
|
70
|
+
disabledDown: true
|
|
71
|
+
})));
|
|
72
|
+
findButton(wrapper, `${dataTest}-buttonmovetotop`).simulate('click');
|
|
73
|
+
findButton(wrapper, `${dataTest}-buttonmoveup`).simulate('click');
|
|
74
|
+
findButton(wrapper, `${dataTest}-buttonmovedown`).simulate('click');
|
|
75
|
+
findButton(wrapper, `${dataTest}-buttonmovetobottom`).simulate('click');
|
|
76
|
+
expect(baseProps.onChangeToTop).not.toHaveBeenCalled();
|
|
77
|
+
expect(baseProps.onChangeUp).not.toHaveBeenCalled();
|
|
78
|
+
expect(baseProps.onChangeDown).not.toHaveBeenCalled();
|
|
79
|
+
expect(baseProps.onChangeToBottom).not.toHaveBeenCalled();
|
|
80
|
+
});
|
|
81
|
+
it('sets aria-label on every button', () => {
|
|
82
|
+
const wrapper = mount(/*#__PURE__*/React.createElement(ReorderingActions, baseProps));
|
|
83
|
+
const assertLabel = (hook, label) => {
|
|
84
|
+
expect(findButton(wrapper, hook).prop('aria-label')).toBe(label);
|
|
85
|
+
};
|
|
86
|
+
assertLabel(`${dataTest}-buttonmovetotop`, 'Move selected items to top');
|
|
87
|
+
assertLabel(`${dataTest}-buttonmoveup`, 'Move selected items up');
|
|
88
|
+
assertLabel(`${dataTest}-buttonmovedown`, 'Move selected items down');
|
|
89
|
+
assertLabel(`${dataTest}-buttonmovetobottom`, 'Move selected items to bottom');
|
|
90
|
+
});
|
|
91
|
+
it('still renders and wires up all four buttons when filterActive is true', () => {
|
|
92
|
+
const wrapper = mount(/*#__PURE__*/React.createElement(ReorderingActions, _extends({}, baseProps, {
|
|
93
|
+
filterActive: true
|
|
94
|
+
})));
|
|
95
|
+
allButtonHooks(dataTest).forEach(hook => {
|
|
96
|
+
expect(findButton(wrapper, hook)).toHaveLength(1);
|
|
97
|
+
});
|
|
98
|
+
findButton(wrapper, `${dataTest}-buttonmoveup`).simulate('click');
|
|
99
|
+
expect(baseProps.onChangeUp).toHaveBeenCalledTimes(1);
|
|
100
|
+
});
|
|
101
|
+
});
|