@dhis2-ui/organisation-unit-tree 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 +8 -7
- package/src/__e2e__/children_as_child_nodes.js +23 -0
- package/src/__e2e__/common.js +70 -0
- package/src/__e2e__/controlled_expanded.js +89 -0
- package/src/__e2e__/displaying_loading_error.js +45 -0
- package/src/__e2e__/expanded.js +42 -0
- package/src/__e2e__/force_reload.js +66 -0
- package/src/__e2e__/get-organisation-unit-data.js +119 -0
- package/src/__e2e__/highlight.js +23 -0
- package/src/__e2e__/loading_state.js +37 -0
- package/src/__e2e__/multi_selection.js +24 -0
- package/src/__e2e__/namespace.js +1 -0
- package/src/__e2e__/no_selection.js +32 -0
- package/src/__e2e__/path_based_filtering.js +49 -0
- package/src/__e2e__/single_selection.js +46 -0
- package/src/__e2e__/sub_unit_as_root.js +28 -0
- package/src/__e2e__/tree_api.js +55 -0
- package/src/__stories__/collapsed.js +11 -0
- package/src/__stories__/custom-expanded-imperative-open.js +181 -0
- package/src/__stories__/custom-node-label.js +19 -0
- package/src/__stories__/development-stories.js +86 -0
- package/src/__stories__/expanded.js +12 -0
- package/src/__stories__/filtered-root.js +15 -0
- package/src/__stories__/filtered.js +13 -0
- package/src/__stories__/force-reload-all.js +46 -0
- package/src/__stories__/force-reload-one-unit.js +36 -0
- package/src/__stories__/highlighted.js +13 -0
- package/src/__stories__/indeterminate.js +13 -0
- package/src/__stories__/loading-error-grandchild.js +39 -0
- package/src/__stories__/loading.js +27 -0
- package/src/__stories__/multiple-roots.js +20 -0
- package/src/__stories__/no-selection.js +16 -0
- package/src/__stories__/replace-roots.js +28 -0
- package/src/__stories__/root-error.js +36 -0
- package/src/__stories__/root-loading.js +34 -0
- package/src/__stories__/rtl.js +14 -0
- package/src/__stories__/selected-multiple.js +18 -0
- package/src/__stories__/shared.js +192 -0
- package/src/__stories__/single-selection.js +16 -0
- package/src/features/children_as_child_nodes/index.js +29 -0
- package/src/features/children_as_child_nodes.feature +6 -0
- package/src/features/controlled_expanded/index.js +86 -0
- package/src/features/controlled_expanded.feature +11 -0
- package/src/features/displaying_loading_error/index.js +46 -0
- package/src/features/displaying_loading_error.feature +24 -0
- package/src/features/expanded/index.js +87 -0
- package/src/features/expanded.feature +27 -0
- package/src/features/force_reload/index.js +36 -0
- package/src/features/force_reload.feature +7 -0
- package/src/features/highlight/index.js +9 -0
- package/src/features/highlight.feature +5 -0
- package/src/features/loading_state/index.js +26 -0
- package/src/features/loading_state.feature +7 -0
- package/src/features/multi_selection/index.js +94 -0
- package/src/features/multi_selection.feature +31 -0
- package/src/features/no_selection/index.js +41 -0
- package/src/features/no_selection.feature +13 -0
- package/src/features/path_based_filtering/index.js +97 -0
- package/src/features/path_based_filtering.feature +24 -0
- package/src/features/single_selection/index.js +41 -0
- package/src/features/single_selection.feature +20 -0
- package/src/features/sub_unit_as_root/index.js +83 -0
- package/src/features/sub_unit_as_root.feature +34 -0
- package/src/features/tree_api/index.js +121 -0
- package/src/features/tree_api.feature +37 -0
- package/src/get-all-expanded-paths/get-all-expanded-paths.js +32 -0
- package/src/get-all-expanded-paths/get-all-expanded-paths.test.js +22 -0
- package/src/get-all-expanded-paths/index.js +1 -0
- package/src/helpers/index.js +3 -0
- package/src/helpers/is-path-included.js +15 -0
- package/src/helpers/left-trim-to-root-id.js +3 -0
- package/src/helpers/sort-node-children-alphabetically.js +5 -0
- package/src/index.js +6 -0
- package/src/locales/ar/translations.json +5 -0
- package/src/locales/cs/translations.json +5 -0
- package/src/locales/en/translations.json +5 -0
- package/src/locales/es/translations.json +5 -0
- package/src/locales/es_419/translations.json +5 -0
- package/src/locales/fr/translations.json +5 -0
- package/src/locales/index.js +50 -0
- package/src/locales/lo/translations.json +5 -0
- package/src/locales/nb/translations.json +5 -0
- package/src/locales/nl/translations.json +5 -0
- package/src/locales/pt/translations.json +5 -0
- package/src/locales/ru/translations.json +5 -0
- package/src/locales/uk/translations.json +5 -0
- package/src/locales/uz_Latn/translations.json +5 -0
- package/src/locales/uz_UZ_Cyrl/translations.json +5 -0
- package/src/locales/uz_UZ_Latn/translations.json +5 -0
- package/src/locales/vi/translations.json +5 -0
- package/src/locales/zh/translations.json +5 -0
- package/src/locales/zh_CN/translations.json +5 -0
- package/src/organisation-unit-node/compute-child-nodes.js +27 -0
- package/src/organisation-unit-node/compute-child-nodes.test.js +85 -0
- package/src/organisation-unit-node/error-message.js +23 -0
- package/src/organisation-unit-node/has-descendant-selected-paths.js +15 -0
- package/src/organisation-unit-node/has-descendant-selected-paths.test.js +30 -0
- package/src/organisation-unit-node/index.js +1 -0
- package/src/organisation-unit-node/label/disabled-selection-label.js +26 -0
- package/src/organisation-unit-node/label/icon-empty.js +31 -0
- package/src/organisation-unit-node/label/icon-folder-closed.js +38 -0
- package/src/organisation-unit-node/label/icon-folder-open.js +49 -0
- package/src/organisation-unit-node/label/icon-single.js +41 -0
- package/src/organisation-unit-node/label/icon.js +35 -0
- package/src/organisation-unit-node/label/iconized-checkbox.js +67 -0
- package/src/organisation-unit-node/label/index.js +1 -0
- package/src/organisation-unit-node/label/label-container.js +36 -0
- package/src/organisation-unit-node/label/label.js +146 -0
- package/src/organisation-unit-node/label/single-selection-label.js +60 -0
- package/src/organisation-unit-node/loading-spinner.js +22 -0
- package/src/organisation-unit-node/organisation-unit-node-children.js +123 -0
- package/src/organisation-unit-node/organisation-unit-node.js +190 -0
- package/src/organisation-unit-node/use-open-state.js +37 -0
- package/src/organisation-unit-node/use-open-state.test.js +111 -0
- package/src/organisation-unit-node/use-org-children.js +63 -0
- package/src/organisation-unit-node/use-org-children.test.js +314 -0
- package/src/organisation-unit-node/use-org-data/index.js +1 -0
- package/src/organisation-unit-node/use-org-data/use-org-data.js +40 -0
- package/src/organisation-unit-node/use-org-data/use-org-data.test.js +137 -0
- package/src/organisation-unit-tree/default-render-node-label/default-render-node-label.js +1 -0
- package/src/organisation-unit-tree/default-render-node-label/index.js +1 -0
- package/src/organisation-unit-tree/filter-root-ids.js +9 -0
- package/src/organisation-unit-tree/index.js +3 -0
- package/src/organisation-unit-tree/organisation-unit-tree-root-error.js +20 -0
- package/src/organisation-unit-tree/organisation-unit-tree-root-loading.js +22 -0
- package/src/organisation-unit-tree/organisation-unit-tree.js +253 -0
- package/src/organisation-unit-tree/organisation-unit-tree.test.js +77 -0
- package/src/organisation-unit-tree/use-expanded/create-expand-handlers.js +45 -0
- package/src/organisation-unit-tree/use-expanded/create-expand-handlers.test.js +54 -0
- package/src/organisation-unit-tree/use-expanded/index.js +1 -0
- package/src/organisation-unit-tree/use-expanded/use-expanded.js +42 -0
- package/src/organisation-unit-tree/use-expanded/use-expanded.test.js +73 -0
- package/src/organisation-unit-tree/use-force-reload.js +22 -0
- package/src/organisation-unit-tree/use-force-reload.test.js +43 -0
- package/src/organisation-unit-tree/use-root-org-data/index.js +1 -0
- package/src/organisation-unit-tree/use-root-org-data/patch-missing-display-name.js +20 -0
- package/src/organisation-unit-tree/use-root-org-data/patch-missing-display-name.test.js +24 -0
- package/src/organisation-unit-tree/use-root-org-data/use-root-org-data.js +60 -0
- package/src/organisation-unit-tree/use-root-org-data/use-root-org-unit.test.js +184 -0
- package/src/organisation-unit-tree.e2e.stories.js +28 -0
- package/src/organisation-unit-tree.prod.stories.js +70 -0
- package/src/prop-types.js +33 -0
|
@@ -0,0 +1,27 @@
|
|
|
1
|
+
Feature: Nodes can be expanded
|
|
2
|
+
|
|
3
|
+
Scenario: No initially expanded paths are provided
|
|
4
|
+
Given a OrganisationUnitTree with children and no paths in the initiallyExpanded prop is rendered
|
|
5
|
+
Then the root unit is closed
|
|
6
|
+
|
|
7
|
+
# The given step is really long.. but I don't know how to split it while
|
|
8
|
+
# being able to test/prepare that with cypress
|
|
9
|
+
Scenario: The first unit on the second level is provided as initially expanded path
|
|
10
|
+
Given a OrganisationUnitTree with children and the path of the first unit on the second level in the initiallyExpanded prop is rendered
|
|
11
|
+
Then the root unit is opened
|
|
12
|
+
|
|
13
|
+
# For info what a "sub", "main" and "root" unit is, see
|
|
14
|
+
# "sub_unit_as_root.feature"
|
|
15
|
+
Scenario: A sub org unit gets expanded within the main org unit tree
|
|
16
|
+
Given both a sub org unit with children and a main org unit are root org units
|
|
17
|
+
And the root main org unit is expanded
|
|
18
|
+
When the user expands the sub org unit within the main org unit tree
|
|
19
|
+
Then the root sub org unit should not expand
|
|
20
|
+
|
|
21
|
+
# For info what a "sub", "main" and "root" unit is, see
|
|
22
|
+
# "sub_unit_as_root.feature"
|
|
23
|
+
Scenario: A root sub org unit gets expanded which is also in the main org unit tree
|
|
24
|
+
Given both a sub org unit with children and a main org unit are root org units
|
|
25
|
+
And the root main org unit is expanded
|
|
26
|
+
When the user expands the root sub org unit
|
|
27
|
+
Then the sub org unit within the main org unit tree should not expand
|
|
@@ -0,0 +1,36 @@
|
|
|
1
|
+
import { Given, When, Then } from '@badeball/cypress-cucumber-preprocessor'
|
|
2
|
+
|
|
3
|
+
Given('a OrganisationUnitTree with three levels is rendered', () => {
|
|
4
|
+
cy.visitStory('OrganisationUnitTree', 'Force reloading')
|
|
5
|
+
})
|
|
6
|
+
|
|
7
|
+
Given('the two parent levels are opened', () => {
|
|
8
|
+
cy.getOrgUnitByLabel('Org Unit 1').as('rootNode').openOrgUnitNode()
|
|
9
|
+
|
|
10
|
+
cy.getOrgUnitByLabel('Org Unit 2').openOrgUnitNode()
|
|
11
|
+
|
|
12
|
+
cy.get('@rootNode')
|
|
13
|
+
.find(
|
|
14
|
+
'[data-test="dhis2-uiwidgets-orgunittree-node"] [data-test="dhis2-uiwidgets-orgunittree-node"]'
|
|
15
|
+
)
|
|
16
|
+
.should('exist')
|
|
17
|
+
})
|
|
18
|
+
|
|
19
|
+
When(
|
|
20
|
+
'the tree is being force reloaded and the loading process has finished',
|
|
21
|
+
() => {
|
|
22
|
+
cy.get('[data-test="reload-all"]').click()
|
|
23
|
+
}
|
|
24
|
+
)
|
|
25
|
+
|
|
26
|
+
Then('all three levels are visible again', () => {
|
|
27
|
+
cy.get('@rootNode')
|
|
28
|
+
.find('[data-test="dhis2-uiwidgets-orgunittree-node"]')
|
|
29
|
+
.should('exist')
|
|
30
|
+
|
|
31
|
+
cy.get('@rootNode')
|
|
32
|
+
.find(
|
|
33
|
+
'[data-test="dhis2-uiwidgets-orgunittree-node"] [data-test="dhis2-uiwidgets-orgunittree-node"]'
|
|
34
|
+
)
|
|
35
|
+
.should('exist')
|
|
36
|
+
})
|
|
@@ -0,0 +1,7 @@
|
|
|
1
|
+
Feature: The whole organisation unit tree can be reloaded
|
|
2
|
+
|
|
3
|
+
Scenario: The whole tree is reloaded while being opened
|
|
4
|
+
Given a OrganisationUnitTree with three levels is rendered
|
|
5
|
+
And the two parent levels are opened
|
|
6
|
+
When the tree is being force reloaded and the loading process has finished
|
|
7
|
+
Then all three levels are visible again
|
|
@@ -0,0 +1,9 @@
|
|
|
1
|
+
import { Given, Then } from '@badeball/cypress-cucumber-preprocessor'
|
|
2
|
+
|
|
3
|
+
Given('a OrganisationUnitTree with a highlighted root unit is rendered', () => {
|
|
4
|
+
cy.visitStory('OrganisationUnitTree', 'Root highlighted')
|
|
5
|
+
})
|
|
6
|
+
|
|
7
|
+
Then('root unit has the highlighted styles', () => {
|
|
8
|
+
cy.getOrgUnitByLabel('Org Unit 1').find('.highlighted').should('exist')
|
|
9
|
+
})
|
|
@@ -0,0 +1,26 @@
|
|
|
1
|
+
import { Given, When, Then } from '@badeball/cypress-cucumber-preprocessor'
|
|
2
|
+
|
|
3
|
+
Given('a OrganisationUnitTree with two levels is rendered', () => {
|
|
4
|
+
cy.visitStory('OrganisationUnitTree', 'A 0000000001 loading')
|
|
5
|
+
})
|
|
6
|
+
|
|
7
|
+
Given('the root level is closed', () => {
|
|
8
|
+
cy.getOrgUnitByLabel('Org Unit 1').as('rootUnit').shouldBeAClosedNode()
|
|
9
|
+
})
|
|
10
|
+
|
|
11
|
+
When('the root level is opened', () => {
|
|
12
|
+
cy.get('@rootUnit').openOrgUnitNode()
|
|
13
|
+
})
|
|
14
|
+
|
|
15
|
+
Then(
|
|
16
|
+
'there is a loading indicator rendered on the first child of the second level',
|
|
17
|
+
() => {
|
|
18
|
+
cy.getOrgUnitByLabel('Org Unit 2')
|
|
19
|
+
.find('[data-test="dhis2-uicore-circularloader"]')
|
|
20
|
+
.should('exist')
|
|
21
|
+
|
|
22
|
+
cy.getOrgUnitByLabel('Org Unit 2')
|
|
23
|
+
.find('[data-test="dhis2-uiwidgets-orgunittree-node-leaves"]:empty')
|
|
24
|
+
.should('exist')
|
|
25
|
+
}
|
|
26
|
+
)
|
|
@@ -0,0 +1,7 @@
|
|
|
1
|
+
Feature: When a unit is loading its children then there is a loading indicator
|
|
2
|
+
|
|
3
|
+
Scenario: The first second-level unit is loading its children
|
|
4
|
+
Given a OrganisationUnitTree with two levels is rendered
|
|
5
|
+
And the root level is closed
|
|
6
|
+
When the root level is opened
|
|
7
|
+
Then there is a loading indicator rendered on the first child of the second level
|
|
@@ -0,0 +1,94 @@
|
|
|
1
|
+
import { Given, When, Then } from '@badeball/cypress-cucumber-preprocessor'
|
|
2
|
+
|
|
3
|
+
Given('an OrganisationUnitTree with two levels is rendered', () => {
|
|
4
|
+
cy.visitStory('OrganisationUnitTree', 'Multiple selection')
|
|
5
|
+
})
|
|
6
|
+
|
|
7
|
+
Given('no unit is selected', () => {
|
|
8
|
+
cy.window().should((win) => {
|
|
9
|
+
expect(win.selection).to.eql([])
|
|
10
|
+
})
|
|
11
|
+
})
|
|
12
|
+
|
|
13
|
+
Given('the root level unit is opened', () => {
|
|
14
|
+
cy.getOrgUnitByLabel('Org Unit 1').openOrgUnitNode(true)
|
|
15
|
+
})
|
|
16
|
+
|
|
17
|
+
Given('the first unit on the second level is selected', () => {
|
|
18
|
+
cy.getOrgUnitByLabel('Org Unit 2').toggleOrgUnitNodeSelection(true)
|
|
19
|
+
})
|
|
20
|
+
|
|
21
|
+
Given('the first unit on the second level unit is opened', () => {
|
|
22
|
+
cy.getOrgUnitByLabel('Org Unit 2').openOrgUnitNode(true)
|
|
23
|
+
})
|
|
24
|
+
|
|
25
|
+
Given('the second level has two units', () => {
|
|
26
|
+
cy.getOrgUnitByLabel('Org Unit 2')
|
|
27
|
+
.find('[data-test="dhis2-uiwidgets-orgunittree-node-leaves"]')
|
|
28
|
+
.first()
|
|
29
|
+
.children()
|
|
30
|
+
.filter((index, child) =>
|
|
31
|
+
Cypress.$(child).is(
|
|
32
|
+
'[data-test="dhis2-uiwidgets-orgunittree-node"]'
|
|
33
|
+
)
|
|
34
|
+
)
|
|
35
|
+
.should('have.length', 2)
|
|
36
|
+
})
|
|
37
|
+
|
|
38
|
+
When('the user selects a unit', () => {
|
|
39
|
+
cy.getOrgUnitByLabel('Org Unit 1').toggleOrgUnitNodeSelection(true)
|
|
40
|
+
})
|
|
41
|
+
|
|
42
|
+
When('the user selects the first unit on the second level', () => {
|
|
43
|
+
cy.getOrgUnitByLabel('Org Unit 2').toggleOrgUnitNodeSelection(true)
|
|
44
|
+
})
|
|
45
|
+
|
|
46
|
+
When('the user selects the root level', () => {
|
|
47
|
+
cy.getOrgUnitByLabel('Org Unit 1').toggleOrgUnitNodeSelection(true)
|
|
48
|
+
})
|
|
49
|
+
|
|
50
|
+
When('the user selects the second unit on the second level', () => {
|
|
51
|
+
cy.getOrgUnitByLabel('Org Unit 3').toggleOrgUnitNodeSelection(true)
|
|
52
|
+
})
|
|
53
|
+
|
|
54
|
+
Then('a unit is selected', () => {
|
|
55
|
+
cy.window().should((win) => {
|
|
56
|
+
expect(win.selection).to.eql(['/A0000000000'])
|
|
57
|
+
})
|
|
58
|
+
})
|
|
59
|
+
|
|
60
|
+
Then('the unit on the second level is selected', () => {
|
|
61
|
+
cy.window().should((win) => {
|
|
62
|
+
expect(win.selection).to.eql(['/A0000000000/A0000000001'])
|
|
63
|
+
})
|
|
64
|
+
})
|
|
65
|
+
|
|
66
|
+
Then('the unit on the first level is marked as selected intermediately', () => {
|
|
67
|
+
cy.getOrgUnitByLabel('Org Unit 1')
|
|
68
|
+
.find(
|
|
69
|
+
'[data-test="dhis2-uiwidgets-orgunittree-node-label"] [data-test="dhis2-uicore-checkbox"] input'
|
|
70
|
+
)
|
|
71
|
+
.should(($input) => {
|
|
72
|
+
expect($input[0].indeterminate).to.be.true
|
|
73
|
+
})
|
|
74
|
+
})
|
|
75
|
+
|
|
76
|
+
Then('the root unit is marked as selected', () => {
|
|
77
|
+
cy.window().should((win) => {
|
|
78
|
+
expect(win.selection.includes('/A0000000000')).to.be.true
|
|
79
|
+
})
|
|
80
|
+
})
|
|
81
|
+
|
|
82
|
+
Then('the first unit is selected', () => {
|
|
83
|
+
cy.window().should((win) => {
|
|
84
|
+
expect(win.selection.includes('/A0000000000/A0000000001')).to.be.true
|
|
85
|
+
expect(win.selection).to.have.length(2)
|
|
86
|
+
})
|
|
87
|
+
})
|
|
88
|
+
|
|
89
|
+
Then('the second unit is selected', () => {
|
|
90
|
+
cy.window().should((win) => {
|
|
91
|
+
expect(win.selection.includes('/A0000000000/A0000000002')).to.be.true
|
|
92
|
+
expect(win.selection).to.have.length(2)
|
|
93
|
+
})
|
|
94
|
+
})
|
|
@@ -0,0 +1,31 @@
|
|
|
1
|
+
Feature: When not limited any amount of units can be selected
|
|
2
|
+
|
|
3
|
+
Scenario: The user selects a unit when no other unit is selected
|
|
4
|
+
Given an OrganisationUnitTree with two levels is rendered
|
|
5
|
+
And no unit is selected
|
|
6
|
+
When the user selects a unit
|
|
7
|
+
Then a unit is selected
|
|
8
|
+
|
|
9
|
+
Scenario: The user selects a unit when a parent unit is not selected
|
|
10
|
+
Given an OrganisationUnitTree with two levels is rendered
|
|
11
|
+
And the root level unit is opened
|
|
12
|
+
When the user selects the first unit on the second level
|
|
13
|
+
Then the unit on the second level is selected
|
|
14
|
+
Then the unit on the first level is marked as selected intermediately
|
|
15
|
+
|
|
16
|
+
Scenario: The user selects a unit which is selected intermediately
|
|
17
|
+
Given an OrganisationUnitTree with two levels is rendered
|
|
18
|
+
And the root level unit is opened
|
|
19
|
+
And the first unit on the second level is selected
|
|
20
|
+
When the user selects the root level
|
|
21
|
+
Then the root unit is marked as selected
|
|
22
|
+
|
|
23
|
+
Scenario: The user selects a unit when another unit on the same level is selected
|
|
24
|
+
Given an OrganisationUnitTree with two levels is rendered
|
|
25
|
+
And the root level unit is opened
|
|
26
|
+
And the first unit on the second level unit is opened
|
|
27
|
+
And the second level has two units
|
|
28
|
+
And the first unit on the second level is selected
|
|
29
|
+
When the user selects the second unit on the second level
|
|
30
|
+
Then the first unit is selected
|
|
31
|
+
Then the second unit is selected
|
|
@@ -0,0 +1,41 @@
|
|
|
1
|
+
import { Given, When, Then } from '@badeball/cypress-cucumber-preprocessor'
|
|
2
|
+
|
|
3
|
+
Given(
|
|
4
|
+
'a disabled, collapsed OrganisationUnitTree with two levels is rendered',
|
|
5
|
+
() => {
|
|
6
|
+
cy.visitStory('OrganisationUnitTree', 'No selection closed')
|
|
7
|
+
}
|
|
8
|
+
)
|
|
9
|
+
|
|
10
|
+
Given(
|
|
11
|
+
'a disabled OrganisationUnitTree with two levels is rendered with the second level is expanded',
|
|
12
|
+
() => {
|
|
13
|
+
cy.visitStory('OrganisationUnitTree', 'No selection root opened')
|
|
14
|
+
}
|
|
15
|
+
)
|
|
16
|
+
|
|
17
|
+
When('the root node is clicked', () => {
|
|
18
|
+
cy.getOrgUnitByLabel('Org Unit 1')
|
|
19
|
+
.find('[data-test="dhis2-uiwidgets-orgunittree-node-label"]')
|
|
20
|
+
.first()
|
|
21
|
+
.trigger('click')
|
|
22
|
+
})
|
|
23
|
+
|
|
24
|
+
Then('the root node remains unselected', () => {
|
|
25
|
+
cy.getOrgUnitByLabel('Org Unit 1')
|
|
26
|
+
.find('[data-test="dhis2-uiwidgets-orgunittree-node-label"]')
|
|
27
|
+
.first()
|
|
28
|
+
.as('rootLabel')
|
|
29
|
+
.find('.checked')
|
|
30
|
+
.should('not.exist')
|
|
31
|
+
|
|
32
|
+
cy.get('@rootLabel').find('input').should('not.exist')
|
|
33
|
+
})
|
|
34
|
+
|
|
35
|
+
Then('the second level is expanded', () => {
|
|
36
|
+
cy.getOrgUnitByLabel('Org Unit 1').shouldBeAnOpenNode()
|
|
37
|
+
})
|
|
38
|
+
|
|
39
|
+
Then('the second level is collapsed', () => {
|
|
40
|
+
cy.getOrgUnitByLabel('Org Unit 1').shouldBeAClosedNode()
|
|
41
|
+
})
|
|
@@ -0,0 +1,13 @@
|
|
|
1
|
+
Feature: Selection can be disabled entirely in the OrganisationUnitTree
|
|
2
|
+
|
|
3
|
+
Scenario: The user clicks on a level of the disabled OrganisationUnitTree with the second level collapsed
|
|
4
|
+
Given a disabled, collapsed OrganisationUnitTree with two levels is rendered
|
|
5
|
+
When the root node is clicked
|
|
6
|
+
Then the root node remains unselected
|
|
7
|
+
But the second level is expanded
|
|
8
|
+
|
|
9
|
+
Scenario: The user clicks on a level of the disabled OrganisationUnitTree with the second level expanded
|
|
10
|
+
Given a disabled OrganisationUnitTree with two levels is rendered with the second level is expanded
|
|
11
|
+
When the root node is clicked
|
|
12
|
+
Then the root node remains unselected
|
|
13
|
+
But the second level is collapsed
|
|
@@ -0,0 +1,97 @@
|
|
|
1
|
+
import { Before, Given, Then } from '@badeball/cypress-cucumber-preprocessor'
|
|
2
|
+
|
|
3
|
+
Before(() => {
|
|
4
|
+
cy.wrap([]).as('displayedUnits')
|
|
5
|
+
})
|
|
6
|
+
|
|
7
|
+
const addDisplayedUnit = (id) => {
|
|
8
|
+
cy.get('@displayedUnits').then((displayedUnits) => {
|
|
9
|
+
cy.wrap([...displayedUnits, id]).as('displayedUnits')
|
|
10
|
+
})
|
|
11
|
+
}
|
|
12
|
+
|
|
13
|
+
Given(
|
|
14
|
+
'a unfiltered OrganisationUnitTree with a depth of 3 levels is rendered',
|
|
15
|
+
() => {
|
|
16
|
+
cy.visitStory('OrganisationUnitTree', 'Filtered by 3-level-path')
|
|
17
|
+
}
|
|
18
|
+
)
|
|
19
|
+
|
|
20
|
+
Given(
|
|
21
|
+
'a filtered OrganisationUnitTree with a depth of 3 levels is rendered',
|
|
22
|
+
() => {
|
|
23
|
+
cy.visitStory(
|
|
24
|
+
'OrganisationUnitTree',
|
|
25
|
+
'Filtered by 3-level-path and 2-level-path'
|
|
26
|
+
)
|
|
27
|
+
}
|
|
28
|
+
)
|
|
29
|
+
|
|
30
|
+
/**
|
|
31
|
+
* left empty intentionally
|
|
32
|
+
* ========================
|
|
33
|
+
* Step is necessary to make the feature file understandable
|
|
34
|
+
* Required states are prepared by the story.
|
|
35
|
+
* There is no way to check if the given is true by checking the dom
|
|
36
|
+
* as this can only be verified by opening the org unit tree,
|
|
37
|
+
* which triggers the recursive loading strategy.
|
|
38
|
+
*/
|
|
39
|
+
Given('the second level contains two nodes', () => {})
|
|
40
|
+
Given('all parent levels are open', () => {})
|
|
41
|
+
Given(
|
|
42
|
+
'a filter containing the first child of the first second level is provided',
|
|
43
|
+
() => {}
|
|
44
|
+
)
|
|
45
|
+
Given('the second level nodes each have a child node', () => {})
|
|
46
|
+
Given(
|
|
47
|
+
'a filter containing the first child of the second level is provided',
|
|
48
|
+
() => {}
|
|
49
|
+
)
|
|
50
|
+
Given(
|
|
51
|
+
'a filter containing the second child of the first level is provided',
|
|
52
|
+
() => {}
|
|
53
|
+
)
|
|
54
|
+
|
|
55
|
+
Then('the root level is visible', () => {
|
|
56
|
+
cy.getOrgUnitByLabel('Org Unit 1').should('exist')
|
|
57
|
+
|
|
58
|
+
addDisplayedUnit('A0000000000')
|
|
59
|
+
})
|
|
60
|
+
|
|
61
|
+
Then('the first node on the second level is visible', () => {
|
|
62
|
+
cy.getOrgUnitByLabel('Org Unit 2').should('exist')
|
|
63
|
+
|
|
64
|
+
addDisplayedUnit('A0000000001')
|
|
65
|
+
})
|
|
66
|
+
|
|
67
|
+
Then(
|
|
68
|
+
'the first child node of the first node on the second level is visible',
|
|
69
|
+
() => {
|
|
70
|
+
cy.getOrgUnitByLabel('Org Unit 4').should('exist')
|
|
71
|
+
|
|
72
|
+
addDisplayedUnit('A0000000003')
|
|
73
|
+
}
|
|
74
|
+
)
|
|
75
|
+
|
|
76
|
+
Then('the second node on the first level is visible', () => {
|
|
77
|
+
cy.getOrgUnitByLabel('Org Unit 3').should('exist')
|
|
78
|
+
|
|
79
|
+
addDisplayedUnit('A0000000002')
|
|
80
|
+
})
|
|
81
|
+
|
|
82
|
+
Then('all other nodes are not rendered', () => {
|
|
83
|
+
cy.get('@displayedUnits').then((displayedUnits) => {
|
|
84
|
+
cy.window().then((win) => {
|
|
85
|
+
const excludedUnitNumbers = win.allUnits
|
|
86
|
+
.filter((unit) => !displayedUnits.includes(unit))
|
|
87
|
+
.map((id) => parseInt(id.replace(/^.*(\d)$/, '$1'), 10) + 1)
|
|
88
|
+
|
|
89
|
+
excludedUnitNumbers.forEach((number) => {
|
|
90
|
+
const label = `Org Unit ${number}`
|
|
91
|
+
cy.get(
|
|
92
|
+
`[data-test="dhis2-uiwidgets-orgunittree-node-label"]:contains("${label}")`
|
|
93
|
+
).should('not.exist')
|
|
94
|
+
})
|
|
95
|
+
})
|
|
96
|
+
})
|
|
97
|
+
})
|
|
@@ -0,0 +1,24 @@
|
|
|
1
|
+
Feature: The OrganisationUnitTree can be filtered by paths
|
|
2
|
+
|
|
3
|
+
Scenario: The org unit tree is filtered by a three-level-deep path
|
|
4
|
+
Given a unfiltered OrganisationUnitTree with a depth of 3 levels is rendered
|
|
5
|
+
And the second level contains two nodes
|
|
6
|
+
And all parent levels are open
|
|
7
|
+
And a filter containing the first child of the first second level is provided
|
|
8
|
+
Then the root level is visible
|
|
9
|
+
And the first node on the second level is visible
|
|
10
|
+
And the first child node of the first node on the second level is visible
|
|
11
|
+
And all other nodes are not rendered
|
|
12
|
+
|
|
13
|
+
Scenario: The org unit tree is filtered by a three-level- and a two-level-deep path
|
|
14
|
+
Given a filtered OrganisationUnitTree with a depth of 3 levels is rendered
|
|
15
|
+
And the second level contains two nodes
|
|
16
|
+
And the second level nodes each have a child node
|
|
17
|
+
And all parent levels are open
|
|
18
|
+
And a filter containing the first child of the second level is provided
|
|
19
|
+
And a filter containing the second child of the first level is provided
|
|
20
|
+
Then the root level is visible
|
|
21
|
+
And the first node on the second level is visible
|
|
22
|
+
And the first child node of the first node on the second level is visible
|
|
23
|
+
And the second node on the first level is visible
|
|
24
|
+
And all other nodes are not rendered
|
|
@@ -0,0 +1,41 @@
|
|
|
1
|
+
import { Given, When, Then } from '@badeball/cypress-cucumber-preprocessor'
|
|
2
|
+
|
|
3
|
+
Given('an OrganisationUnitTree with two nodes is rendered', () => {
|
|
4
|
+
cy.visitStory('OrganisationUnitTree', 'Single selection')
|
|
5
|
+
})
|
|
6
|
+
|
|
7
|
+
Given('no unit has been selected', () => {
|
|
8
|
+
cy.get('.checked').should('not.exist')
|
|
9
|
+
})
|
|
10
|
+
|
|
11
|
+
Given('the first unit has been selected', () => {
|
|
12
|
+
cy.getOrgUnitByLabel('Org Unit 1').toggleOrgUnitNodeSelection(true, true)
|
|
13
|
+
})
|
|
14
|
+
|
|
15
|
+
When('the user selects the first unit', () => {
|
|
16
|
+
cy.getOrgUnitByLabel('Org Unit 1').toggleOrgUnitNodeSelection(true, true)
|
|
17
|
+
})
|
|
18
|
+
|
|
19
|
+
When('the user selects the second unit', () => {
|
|
20
|
+
cy.getOrgUnitByLabel('Org Unit 2').toggleOrgUnitNodeSelection(true, true)
|
|
21
|
+
})
|
|
22
|
+
|
|
23
|
+
When('the user deselects the first unit', () => {
|
|
24
|
+
cy.getOrgUnitByLabel('Org Unit 1').toggleOrgUnitNodeSelection(false, true)
|
|
25
|
+
})
|
|
26
|
+
|
|
27
|
+
Then('the first unit is selected', () => {
|
|
28
|
+
cy.getOrgUnitByLabel('Org Unit 1').shouldBeASelectedOrgUnitNode(true)
|
|
29
|
+
})
|
|
30
|
+
|
|
31
|
+
Then('the first unit is not selected', () => {
|
|
32
|
+
cy.getOrgUnitByLabel('Org Unit 1').shouldNotBeASelectedOrgUnitNode(true)
|
|
33
|
+
})
|
|
34
|
+
|
|
35
|
+
Then('the second unit is selected', () => {
|
|
36
|
+
cy.getOrgUnitByLabel('Org Unit 2').shouldBeASelectedOrgUnitNode(true)
|
|
37
|
+
})
|
|
38
|
+
|
|
39
|
+
Then('no unit is selected', () => {
|
|
40
|
+
cy.get('.checked').should('not.exist')
|
|
41
|
+
})
|
|
@@ -0,0 +1,20 @@
|
|
|
1
|
+
Feature: When specified only one unit can be selected
|
|
2
|
+
|
|
3
|
+
Scenario: The user selects a unit when no other unit is selected
|
|
4
|
+
Given an OrganisationUnitTree with two nodes is rendered
|
|
5
|
+
And no unit has been selected
|
|
6
|
+
When the user selects the first unit
|
|
7
|
+
Then the first unit is selected
|
|
8
|
+
|
|
9
|
+
Scenario: The user select a unit when another unit is selected
|
|
10
|
+
Given an OrganisationUnitTree with two nodes is rendered
|
|
11
|
+
And the first unit has been selected
|
|
12
|
+
When the user selects the second unit
|
|
13
|
+
Then the first unit is not selected
|
|
14
|
+
Then the second unit is selected
|
|
15
|
+
|
|
16
|
+
Scenario: The user deselects a unit
|
|
17
|
+
Given an OrganisationUnitTree with two nodes is rendered
|
|
18
|
+
And the first unit has been selected
|
|
19
|
+
When the user deselects the first unit
|
|
20
|
+
Then no unit is selected
|
|
@@ -0,0 +1,83 @@
|
|
|
1
|
+
import { Given, When, Then } from '@badeball/cypress-cucumber-preprocessor'
|
|
2
|
+
|
|
3
|
+
const rootOrgUnitLabelSelector = `
|
|
4
|
+
[data-test="dhis2-uiwidgets-orgunittree"]
|
|
5
|
+
> [data-test="dhis2-uiwidgets-orgunittree-node"]
|
|
6
|
+
> [data-test="dhis2-uiwidgets-orgunittree-node-content"]
|
|
7
|
+
> [data-test="dhis2-uiwidgets-orgunittree-node-label"]
|
|
8
|
+
label
|
|
9
|
+
`
|
|
10
|
+
|
|
11
|
+
Given('a sub org unit is a root org unit', () => {
|
|
12
|
+
cy.visitStory(
|
|
13
|
+
'OrganisationUnitTree',
|
|
14
|
+
'multiple root sub and one main org unit'
|
|
15
|
+
)
|
|
16
|
+
})
|
|
17
|
+
|
|
18
|
+
Given('both a sub org unit and a main org unit are root org units', () => {
|
|
19
|
+
cy.visitStory(
|
|
20
|
+
'OrganisationUnitTree',
|
|
21
|
+
'multiple root sub and one main org unit'
|
|
22
|
+
)
|
|
23
|
+
})
|
|
24
|
+
|
|
25
|
+
Given('multiple sub org units is a root org unit', () => {
|
|
26
|
+
cy.visitStory(
|
|
27
|
+
'OrganisationUnitTree',
|
|
28
|
+
'multiple root sub and one main org unit'
|
|
29
|
+
)
|
|
30
|
+
})
|
|
31
|
+
|
|
32
|
+
Given('the root sub org unit is a child of the root main org unit', () => {
|
|
33
|
+
cy.visitStory(
|
|
34
|
+
'OrganisationUnitTree',
|
|
35
|
+
'multiple root sub and one main org unit'
|
|
36
|
+
)
|
|
37
|
+
})
|
|
38
|
+
|
|
39
|
+
Given('the user provided one root sub org unit to the filter', () => {
|
|
40
|
+
cy.get('input[type="input"]').clear().type('/A0000000001')
|
|
41
|
+
})
|
|
42
|
+
|
|
43
|
+
Given('the user provided one non-root sub org unit to the filter', () => {
|
|
44
|
+
cy.get('input[type="input"]').clear().type('/A0000000000/A0000000006')
|
|
45
|
+
})
|
|
46
|
+
|
|
47
|
+
When('the user selects sub org unit in the main org unit tree', () => {
|
|
48
|
+
cy.contains('label', 'Org Unit 1').click()
|
|
49
|
+
cy.get('[data-test="dhis2-uiwidgets-orgunittree-node-content"]')
|
|
50
|
+
.contains('label', 'Org Unit 2')
|
|
51
|
+
.click()
|
|
52
|
+
})
|
|
53
|
+
|
|
54
|
+
When('the user selects the root sub org unit', () => {
|
|
55
|
+
cy.contains(rootOrgUnitLabelSelector, 'Org Unit 2').click()
|
|
56
|
+
})
|
|
57
|
+
|
|
58
|
+
Then(
|
|
59
|
+
'all root sub org units but the filtered sub org unit should be hidden',
|
|
60
|
+
() => {
|
|
61
|
+
cy.contains(rootOrgUnitLabelSelector, 'Org Unit 2').should('exist')
|
|
62
|
+
cy.contains(rootOrgUnitLabelSelector, 'Org Unit 1').should('not.exist')
|
|
63
|
+
cy.contains(rootOrgUnitLabelSelector, 'Org Unit 3').should('not.exist')
|
|
64
|
+
}
|
|
65
|
+
)
|
|
66
|
+
|
|
67
|
+
Then('the root main org unit should be marked as indeterminate', () => {
|
|
68
|
+
cy.contains(rootOrgUnitLabelSelector, 'Org Unit 1')
|
|
69
|
+
.find('> .icon svg')
|
|
70
|
+
.should('have.class', 'indeterminate')
|
|
71
|
+
})
|
|
72
|
+
|
|
73
|
+
Then('the root sub org unit should be selected', () => {
|
|
74
|
+
cy.contains(rootOrgUnitLabelSelector, 'Org Unit 2')
|
|
75
|
+
.find('> .icon svg')
|
|
76
|
+
.should('have.class', 'checked')
|
|
77
|
+
})
|
|
78
|
+
|
|
79
|
+
Then('only the root main org units should be visible', () => {
|
|
80
|
+
cy.contains(rootOrgUnitLabelSelector, 'Org Unit 1').should('exist')
|
|
81
|
+
cy.contains(rootOrgUnitLabelSelector, 'Org Unit 2').should('not.exist')
|
|
82
|
+
cy.contains(rootOrgUnitLabelSelector, 'Org Unit 3').should('not.exist')
|
|
83
|
+
})
|
|
@@ -0,0 +1,34 @@
|
|
|
1
|
+
Feature: Sub-org units can be a root org unit
|
|
2
|
+
|
|
3
|
+
Main org unit : is an actual root org unit in the configured hierarchy
|
|
4
|
+
Sub org unit : is an org unit which is inside the tree of a "main org unit"
|
|
5
|
+
Root org unit : refers to an org unit which is a root node in the component
|
|
6
|
+
---
|
|
7
|
+
Org unit components can have multiple selections in all of the scenarios
|
|
8
|
+
|
|
9
|
+
Scenario: The user selects the root sub org unit
|
|
10
|
+
Given a sub org unit is a root org unit
|
|
11
|
+
When the user selects the root sub org unit
|
|
12
|
+
Then the root sub org unit should be selected
|
|
13
|
+
|
|
14
|
+
Scenario: The user selects the root sub org unit which is included in the tree of a root main org unit
|
|
15
|
+
Given both a sub org unit and a main org unit are root org units
|
|
16
|
+
And the root sub org unit is a child of the root main org unit
|
|
17
|
+
When the user selects the root sub org unit
|
|
18
|
+
Then the root main org unit should be marked as indeterminate
|
|
19
|
+
|
|
20
|
+
Scenario: The user selects the a child in the root main org unit which is also a root sub org unit
|
|
21
|
+
Given both a sub org unit and a main org unit are root org units
|
|
22
|
+
And the root sub org unit is a child of the root main org unit
|
|
23
|
+
When the user selects sub org unit in the main org unit tree
|
|
24
|
+
Then the root sub org unit should be selected
|
|
25
|
+
|
|
26
|
+
Scenario: The user filtered the tree by a root sub unit path
|
|
27
|
+
Given multiple sub org units is a root org unit
|
|
28
|
+
And the user provided one root sub org unit to the filter
|
|
29
|
+
Then all root sub org units but the filtered sub org unit should be hidden
|
|
30
|
+
|
|
31
|
+
Scenario: The user filtered the tree by a non-root sub unit path in the root main org unit
|
|
32
|
+
Given multiple sub org units is a root org unit
|
|
33
|
+
And the user provided one non-root sub org unit to the filter
|
|
34
|
+
Then only the root main org units should be visible
|