@dhis2-ui/header-bar 10.16.2 → 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.
- package/package.json +17 -16
- package/src/__e2e__/header-bar.e2e.stories.js +26 -0
- package/src/__e2e__/stories/common.js +226 -0
- package/src/__e2e__/stories/custom-application-title.js +19 -0
- package/src/__e2e__/stories/default.js +13 -0
- package/src/__e2e__/stories/me-with-avatar.js +27 -0
- package/src/__e2e__/stories/modulesWithSpecialCharacters.js +229 -0
- package/src/__e2e__/stories/online-status-message.js +49 -0
- package/src/__e2e__/stories/pwa-enabled.js +17 -0
- package/src/__e2e__/stories/user-has-all-authority.js +20 -0
- package/src/__e2e__/stories/user-has-no-authorities.js +20 -0
- package/src/__e2e__/stories/user-has-web-interpretation-and-messaging-authority.js +22 -0
- package/src/__e2e__/stories/user-has-web-interpretation-authority.js +22 -0
- package/src/__e2e__/stories/user-has-web-messaging-authority.js +22 -0
- package/src/__e2e__/stories/with-debug-info-edge-cases.js +51 -0
- package/src/__e2e__/stories/with-special-app-name-character.js +23 -0
- package/src/__e2e__/stories/with-update-available-notification.js +39 -0
- package/src/__e2e__/stories/zero-unread-interpretations.js +19 -0
- package/src/__e2e__/stories/zero-unread-messages.js +19 -0
- package/src/apps.js +276 -0
- package/src/debug-info/debug-info-menu-item.js +72 -0
- package/src/debug-info/debug-info-modal.js +47 -0
- package/src/debug-info/debug-info-table.js +51 -0
- package/src/debug-info/use-debug-info.js +15 -0
- package/src/features/common/index.js +14 -0
- package/src/features/the_headerbar_can_display_online_status/the_headerbar_displays_online_status.js +158 -0
- package/src/features/the_headerbar_can_display_online_status.feature +57 -0
- package/src/features/the_headerbar_conditionally_renders_notification_icons/the_headerbar_conditionally_renders_notification_icons.js +43 -0
- package/src/features/the_headerbar_conditionally_renders_notification_icons.feature +26 -0
- package/src/features/the_headerbar_contains_a_menu_to_all_apps/common.js +5 -0
- package/src/features/the_headerbar_contains_a_menu_to_all_apps/the_app_menu_closes_when_the_user_clicks_outside.js +9 -0
- package/src/features/the_headerbar_contains_a_menu_to_all_apps/the_headerbar_contains_a_menu_icon.js +5 -0
- package/src/features/the_headerbar_contains_a_menu_to_all_apps/the_user_will_be_offered_a_menu_with_5_apps.js +16 -0
- package/src/features/the_headerbar_contains_a_menu_to_all_apps.feature +21 -0
- package/src/features/the_headerbar_contains_a_profile_menu/common.js +14 -0
- package/src/features/the_headerbar_contains_a_profile_menu/the_headerbar_shows_a_text_icon_if_the_user_does_not_have_an_avatar.js +30 -0
- package/src/features/the_headerbar_contains_a_profile_menu/the_headerbar_shows_an_image_icon_if_the_user_has_an_avatar.js +23 -0
- package/src/features/the_headerbar_contains_a_profile_menu/the_menu_is_closed_by_default.js +1 -0
- package/src/features/the_headerbar_contains_a_profile_menu/the_menu_opens.js +14 -0
- package/src/features/the_headerbar_contains_a_profile_menu/the_profile_menu_closes_when_the_user_clicks_outside.js +5 -0
- package/src/features/the_headerbar_contains_a_profile_menu/the_user_can_edit_his_profile.js +7 -0
- package/src/features/the_headerbar_contains_a_profile_menu/the_user_can_go_to_his_account.js +7 -0
- package/src/features/the_headerbar_contains_a_profile_menu/the_user_can_go_to_the_about_dhis2_page.js +7 -0
- package/src/features/the_headerbar_contains_a_profile_menu/the_user_can_go_to_the_help_page.js +7 -0
- package/src/features/the_headerbar_contains_a_profile_menu/the_user_can_go_to_the_settings.js +7 -0
- package/src/features/the_headerbar_contains_a_profile_menu/the_user_can_log_out.js +53 -0
- package/src/features/the_headerbar_contains_a_profile_menu/the_user_name_and_email_are_displayed.js +22 -0
- package/src/features/the_headerbar_contains_a_profile_menu.feature +73 -0
- package/src/features/the_headerbar_displays_a_link_to_interpretations_and_an_unread_count/the_headerbar_displays_a_link_to_the_interpretations.js +5 -0
- package/src/features/the_headerbar_displays_a_link_to_interpretations_and_an_unread_count/there_are_no_unread_interpretations.js +9 -0
- package/src/features/the_headerbar_displays_a_link_to_interpretations_and_an_unread_count/there_are_some_unread_interpretations.js +12 -0
- package/src/features/the_headerbar_displays_a_link_to_interpretations_and_an_unread_count.feature +13 -0
- package/src/features/the_headerbar_displays_a_link_to_messages_and_an_unread_count/the_headerbar_displays_a_link_to_the_messages.js +5 -0
- package/src/features/the_headerbar_displays_a_link_to_messages_and_an_unread_count/there_are_no_unread_messages.js +9 -0
- package/src/features/the_headerbar_displays_a_link_to_messages_and_an_unread_count/there_are_some_unread_messages.js +7 -0
- package/src/features/the_headerbar_displays_a_link_to_messages_and_an_unread_count.feature +13 -0
- package/src/features/the_headerbar_should_contain_a_logo_that_links_to_the_homepage/headerbar_contains_logo.js +12 -0
- package/src/features/the_headerbar_should_contain_a_logo_that_links_to_the_homepage.feature +6 -0
- package/src/features/the_headerbar_should_display_app_update_notification/index.js +52 -0
- package/src/features/the_headerbar_should_display_app_update_notification.feature +22 -0
- package/src/features/the_headerbar_should_display_debug_version_infos/index.js +130 -0
- package/src/features/the_headerbar_should_display_debug_version_infos.feature +52 -0
- package/src/features/the_headerbar_should_display_the_title_provided_by_the_backend_and_the_app/the_headerbar_displays_the_custom_title.js +11 -0
- package/src/features/the_headerbar_should_display_the_title_provided_by_the_backend_and_the_app.feature +5 -0
- package/src/features/the_search_should_escape_regexp_character/common.js +6 -0
- package/src/features/the_search_should_escape_regexp_character/the_modules_do_not_contain_items_with_special_chars.js +23 -0
- package/src/features/the_search_should_escape_regexp_character/the_user_searches_for_an_app_with_a_regex_character.js +29 -0
- package/src/features/the_search_should_escape_regexp_character.feature +48 -0
- package/src/header-bar-context.js +28 -0
- package/src/header-bar.js +145 -0
- package/src/header-bar.prod.stories.js +303 -0
- package/src/index.js +1 -0
- package/src/join-path.js +4 -0
- package/src/locales/ar/translations.json +24 -0
- package/src/locales/ar_IQ/translations.json +24 -0
- package/src/locales/bn/translations.json +12 -0
- package/src/locales/ckb/translations.json +23 -0
- package/src/locales/cs/translations.json +24 -0
- package/src/locales/da/translations.json +24 -0
- package/src/locales/en/translations.json +25 -0
- package/src/locales/en_US/translations.json +25 -0
- package/src/locales/es/translations.json +25 -0
- package/src/locales/es_419/translations.json +24 -0
- package/src/locales/fr/translations.json +25 -0
- package/src/locales/hi_IN/translations.json +25 -0
- package/src/locales/id/translations.json +24 -0
- package/src/locales/index.js +88 -0
- package/src/locales/km/translations.json +24 -0
- package/src/locales/lo/translations.json +24 -0
- package/src/locales/my/translations.json +24 -0
- package/src/locales/nb/translations.json +24 -0
- package/src/locales/nl/translations.json +24 -0
- package/src/locales/or/translations.json +12 -0
- package/src/locales/prs/translations.json +24 -0
- package/src/locales/ps/translations.json +24 -0
- package/src/locales/pt/translations.json +25 -0
- package/src/locales/pt_BR/translations.json +24 -0
- package/src/locales/ro/translations.json +23 -0
- package/src/locales/ru/translations.json +24 -0
- package/src/locales/si/translations.json +24 -0
- package/src/locales/sv/translations.json +24 -0
- package/src/locales/tet/translations.json +24 -0
- package/src/locales/tg/translations.json +24 -0
- package/src/locales/uk/translations.json +24 -0
- package/src/locales/ur/translations.json +24 -0
- package/src/locales/uz_Latn/translations.json +23 -0
- package/src/locales/uz_UZ_Cyrl/translations.json +24 -0
- package/src/locales/uz_UZ_Latn/translations.json +24 -0
- package/src/locales/vi/translations.json +24 -0
- package/src/locales/zh/translations.json +25 -0
- package/src/locales/zh_CN/translations.json +24 -0
- package/src/logo-image.js +71 -0
- package/src/logo.js +45 -0
- package/src/notification-icon.js +91 -0
- package/src/notifications.js +63 -0
- package/src/online-status.js +40 -0
- package/src/online-status.styles.js +91 -0
- package/src/profile/use-on-doc-click.js +23 -0
- package/src/profile/use-on-doc-click.test.js +40 -0
- package/src/profile-menu/index.js +1 -0
- package/src/profile-menu/profile-header.js +118 -0
- package/src/profile-menu/profile-menu.js +176 -0
- package/src/profile-menu/update-notification.js +67 -0
- package/src/profile.js +101 -0
- package/src/title.js +23 -0
|
@@ -0,0 +1,15 @@
|
|
|
1
|
+
import { useConfig } from '@dhis2/app-runtime'
|
|
2
|
+
|
|
3
|
+
export const useDebugInfo = () => {
|
|
4
|
+
const { appName, appVersion, systemInfo } = useConfig()
|
|
5
|
+
|
|
6
|
+
return {
|
|
7
|
+
app_name: appName || null,
|
|
8
|
+
app_version: appVersion?.full || null,
|
|
9
|
+
dhis2_version: systemInfo?.version || null,
|
|
10
|
+
dhis2_revision: systemInfo?.revision || null,
|
|
11
|
+
}
|
|
12
|
+
}
|
|
13
|
+
|
|
14
|
+
export const useFormattedDebugInfo = () =>
|
|
15
|
+
JSON.stringify(useDebugInfo(), undefined, 2)
|
|
@@ -0,0 +1,14 @@
|
|
|
1
|
+
import { Before, Given } from '@badeball/cypress-cucumber-preprocessor'
|
|
2
|
+
|
|
3
|
+
export const baseUrl = 'https://domain.tld/'
|
|
4
|
+
export const webCommons = 'https://domain.tld/dhis-web-commons/'
|
|
5
|
+
|
|
6
|
+
Before(() => {
|
|
7
|
+
cy.intercept('GET', `${baseUrl}api/fileResources/avatarId/data`, {
|
|
8
|
+
fixture: 'HeaderBar/avatar.png',
|
|
9
|
+
}).as('avatar')
|
|
10
|
+
})
|
|
11
|
+
|
|
12
|
+
Given('the HeaderBar loads without an error', () => {
|
|
13
|
+
cy.visitStory('HeaderBarTesting', 'Default')
|
|
14
|
+
})
|
package/src/features/the_headerbar_can_display_online_status/the_headerbar_displays_online_status.js
ADDED
|
@@ -0,0 +1,158 @@
|
|
|
1
|
+
import {
|
|
2
|
+
Before,
|
|
3
|
+
After,
|
|
4
|
+
Given,
|
|
5
|
+
Then,
|
|
6
|
+
When,
|
|
7
|
+
} from '@badeball/cypress-cucumber-preprocessor'
|
|
8
|
+
|
|
9
|
+
// see https://github.com/cypress-io/cypress/issues/17723#issuecomment-1457064322
|
|
10
|
+
const goOffline = () => {
|
|
11
|
+
cy.log('**go offline**')
|
|
12
|
+
// stub every request with a StaticResponse to simulate network error
|
|
13
|
+
.then(() => cy.intercept('*', { forceNetworkError: true }))
|
|
14
|
+
.then(() =>
|
|
15
|
+
cy.window().then((win) => win.dispatchEvent(new Event('offline')))
|
|
16
|
+
)
|
|
17
|
+
}
|
|
18
|
+
const goOnline = () => {
|
|
19
|
+
// disable offline mode, otherwise we will break our tests :)
|
|
20
|
+
cy.log('**go online**')
|
|
21
|
+
// go back to normal network behavior
|
|
22
|
+
.then(() => cy.intercept('*'))
|
|
23
|
+
.then(() =>
|
|
24
|
+
cy.window().then((win) => win.dispatchEvent(new Event('online')))
|
|
25
|
+
)
|
|
26
|
+
}
|
|
27
|
+
|
|
28
|
+
Before(() => {
|
|
29
|
+
goOnline()
|
|
30
|
+
})
|
|
31
|
+
After(() => goOnline())
|
|
32
|
+
|
|
33
|
+
Given(
|
|
34
|
+
'the HeaderBar loads without error with showOnlineStatus configured',
|
|
35
|
+
() => {
|
|
36
|
+
cy.visitStory('HeaderBarTesting', 'Show Online Status')
|
|
37
|
+
}
|
|
38
|
+
)
|
|
39
|
+
|
|
40
|
+
Given('the HeaderBar loads without error when PWA is enabled', () => {
|
|
41
|
+
cy.visitStory('HeaderBarTesting', 'PWA Enabled')
|
|
42
|
+
cy.get(':contains("Online")').should('exist')
|
|
43
|
+
})
|
|
44
|
+
|
|
45
|
+
Given(
|
|
46
|
+
'the HeaderBar loads and is PWA enabled so online status messages will be visible',
|
|
47
|
+
() => {
|
|
48
|
+
cy.visitStory(
|
|
49
|
+
'HeaderBarTesting',
|
|
50
|
+
'Online Status Messaging With PWA Enabled'
|
|
51
|
+
)
|
|
52
|
+
}
|
|
53
|
+
)
|
|
54
|
+
|
|
55
|
+
Given('the viewport is narrower than 480px', () => {
|
|
56
|
+
cy.viewport(460, 660)
|
|
57
|
+
})
|
|
58
|
+
|
|
59
|
+
Then('the HeaderBar does not render online status', () => {
|
|
60
|
+
cy.get('[data-test="headerbar-online-status"]').should('not.exist')
|
|
61
|
+
})
|
|
62
|
+
|
|
63
|
+
Then('the HeaderBar renders online status', () => {
|
|
64
|
+
cy.get('[data-test="headerbar-online-status"]').should('exist')
|
|
65
|
+
})
|
|
66
|
+
|
|
67
|
+
Then('the HeaderBar displays only the desktop status badge', () => {
|
|
68
|
+
// This assumes default viewport size: 1000x660
|
|
69
|
+
cy.get('[data-test="headerbar-online-status"].badge').should('be.visible')
|
|
70
|
+
cy.get('[data-test="headerbar-online-status"].bar').should('not.be.visible')
|
|
71
|
+
})
|
|
72
|
+
|
|
73
|
+
Then('the status badge shows online', () => {
|
|
74
|
+
cy.get('[data-test="headerbar-online-status"].badge .label').should(
|
|
75
|
+
($label) => {
|
|
76
|
+
expect($label.text()).to.equal('Online')
|
|
77
|
+
}
|
|
78
|
+
)
|
|
79
|
+
cy.get('[data-test="headerbar-online-status"].badge .icon').should(
|
|
80
|
+
($icon) => {
|
|
81
|
+
expect($icon).to.have.class('online')
|
|
82
|
+
}
|
|
83
|
+
)
|
|
84
|
+
})
|
|
85
|
+
|
|
86
|
+
Then('the HeaderBar displays only the mobile status bar', () => {
|
|
87
|
+
cy.get('[data-test="headerbar-online-status"].bar').should('be.visible')
|
|
88
|
+
cy.get('[data-test="headerbar-online-status"].badge').should(
|
|
89
|
+
'not.be.visible'
|
|
90
|
+
)
|
|
91
|
+
})
|
|
92
|
+
|
|
93
|
+
Given('the browser goes offline', () => {
|
|
94
|
+
goOffline()
|
|
95
|
+
})
|
|
96
|
+
|
|
97
|
+
Then('the status badge shows offline', () => {
|
|
98
|
+
// cy.get('[data-test="headerbar-online-status"].badge .label')
|
|
99
|
+
// .invoke('text')
|
|
100
|
+
// .should('equal', 'Offline')
|
|
101
|
+
|
|
102
|
+
cy.get('[data-test="headerbar-online-status"].badge .label').should(
|
|
103
|
+
($label) => {
|
|
104
|
+
expect($label.text()).to.equal('Offline')
|
|
105
|
+
}
|
|
106
|
+
)
|
|
107
|
+
cy.get('[data-test="headerbar-online-status"].badge .icon').should(
|
|
108
|
+
($icon) => {
|
|
109
|
+
expect($icon).to.have.class('offline')
|
|
110
|
+
}
|
|
111
|
+
)
|
|
112
|
+
})
|
|
113
|
+
|
|
114
|
+
Then('no online status message text is displayed', () => {
|
|
115
|
+
cy.get('[data-test="headerbar-online-status"] .info').should('not.exist')
|
|
116
|
+
cy.get('[data-test="headerbar-online-status"] .info-dense').should(
|
|
117
|
+
'not.exist'
|
|
118
|
+
)
|
|
119
|
+
})
|
|
120
|
+
|
|
121
|
+
When('an online status message is sent', () => {
|
|
122
|
+
cy.get('button').contains('display online status message').click()
|
|
123
|
+
})
|
|
124
|
+
|
|
125
|
+
When('an online status message is removed', () => {
|
|
126
|
+
cy.get('button').contains('remove online status message').click()
|
|
127
|
+
})
|
|
128
|
+
|
|
129
|
+
Then('an online status message is displayed', () => {
|
|
130
|
+
cy.get('[data-test="headerbar-online-status"] .info').should(
|
|
131
|
+
'include.text',
|
|
132
|
+
'8 offline events'
|
|
133
|
+
)
|
|
134
|
+
})
|
|
135
|
+
|
|
136
|
+
Then(
|
|
137
|
+
'an online status message is displayed with formatting for small screens',
|
|
138
|
+
() => {
|
|
139
|
+
cy.get('[data-test="headerbar-online-status"] .info-dense').should(
|
|
140
|
+
'include.text',
|
|
141
|
+
'8 offline events'
|
|
142
|
+
)
|
|
143
|
+
}
|
|
144
|
+
)
|
|
145
|
+
|
|
146
|
+
Then('last online text is displayed in the status badge', () => {
|
|
147
|
+
cy.get('[data-test="headerbar-online-status"].badge .info').should(
|
|
148
|
+
'include.text',
|
|
149
|
+
'Last online'
|
|
150
|
+
)
|
|
151
|
+
})
|
|
152
|
+
|
|
153
|
+
Then('last online text is displayed in the mobile status bar', () => {
|
|
154
|
+
cy.get('[data-test="headerbar-online-status"].bar .info-dense').should(
|
|
155
|
+
'include.text',
|
|
156
|
+
'Last online'
|
|
157
|
+
)
|
|
158
|
+
})
|
|
@@ -0,0 +1,57 @@
|
|
|
1
|
+
Feature: The HeaderBar can display online status
|
|
2
|
+
|
|
3
|
+
# Configuring to show
|
|
4
|
+
|
|
5
|
+
Scenario: The HeaderBar doesn't display online status when not configured
|
|
6
|
+
Given the HeaderBar loads without an error
|
|
7
|
+
Then the HeaderBar does not render online status
|
|
8
|
+
|
|
9
|
+
Scenario: The HeaderBar displays online status when PWA is enabled
|
|
10
|
+
Given the HeaderBar loads without error when PWA is enabled
|
|
11
|
+
Then the HeaderBar renders online status
|
|
12
|
+
|
|
13
|
+
# Large / small screens & Online / Offline status
|
|
14
|
+
|
|
15
|
+
Scenario: The HeaderBar displays a badge on large screens
|
|
16
|
+
Given the HeaderBar loads without error when PWA is enabled
|
|
17
|
+
Then the HeaderBar displays only the desktop status badge
|
|
18
|
+
And the status badge shows online
|
|
19
|
+
|
|
20
|
+
Scenario: The HeaderBar displays a sub-bar on smaller screens
|
|
21
|
+
Given the HeaderBar loads without error when PWA is enabled
|
|
22
|
+
And the viewport is narrower than 480px
|
|
23
|
+
Then the HeaderBar displays only the mobile status bar
|
|
24
|
+
|
|
25
|
+
# This is not a complete test of the connection status functionality --
|
|
26
|
+
# see the app-runtime for detailed tests
|
|
27
|
+
Scenario: The HeaderBar displays an offline status when offline
|
|
28
|
+
Given the HeaderBar loads without error when PWA is enabled
|
|
29
|
+
And the browser goes offline
|
|
30
|
+
Then the status badge shows offline
|
|
31
|
+
|
|
32
|
+
# Online status message
|
|
33
|
+
|
|
34
|
+
Scenario: In the HeaderBar no online status message text is displayed by default
|
|
35
|
+
Given the HeaderBar loads and is PWA enabled so online status messages will be visible
|
|
36
|
+
Then no online status message text is displayed
|
|
37
|
+
|
|
38
|
+
Scenario: In the HeaderBar the online status message text is displayed
|
|
39
|
+
Given the HeaderBar loads and is PWA enabled so online status messages will be visible
|
|
40
|
+
When an online status message is sent
|
|
41
|
+
Then an online status message is displayed
|
|
42
|
+
|
|
43
|
+
Scenario: In the HeaderBar the online status message text can be removed
|
|
44
|
+
Given the HeaderBar loads and is PWA enabled so online status messages will be visible
|
|
45
|
+
When an online status message is sent
|
|
46
|
+
Then an online status message is displayed
|
|
47
|
+
When an online status message is removed
|
|
48
|
+
Then no online status message text is displayed
|
|
49
|
+
|
|
50
|
+
# Online status message - small screens
|
|
51
|
+
|
|
52
|
+
Scenario: In the HeaderBar the online status message text can be set on small screens
|
|
53
|
+
Given the HeaderBar loads and is PWA enabled so online status messages will be visible
|
|
54
|
+
And the viewport is narrower than 480px
|
|
55
|
+
Then no online status message text is displayed
|
|
56
|
+
When an online status message is sent
|
|
57
|
+
Then an online status message is displayed with formatting for small screens
|
|
@@ -0,0 +1,43 @@
|
|
|
1
|
+
import { Given, Then } from '@badeball/cypress-cucumber-preprocessor'
|
|
2
|
+
|
|
3
|
+
Given('the user has the ALL authority', () => {
|
|
4
|
+
cy.visitStory('HeaderBarTesting', 'User Has All Authority')
|
|
5
|
+
})
|
|
6
|
+
|
|
7
|
+
Given(
|
|
8
|
+
'the user has the M_dhis-web-interpretation and M_dhis-web-messaging authority',
|
|
9
|
+
() => {
|
|
10
|
+
cy.visitStory(
|
|
11
|
+
'HeaderBarTesting',
|
|
12
|
+
'User Has Web Interpretation And Messaging Authority'
|
|
13
|
+
)
|
|
14
|
+
}
|
|
15
|
+
)
|
|
16
|
+
|
|
17
|
+
Given('the user has the M_dhis-web-interpretation authority', () => {
|
|
18
|
+
cy.visitStory('HeaderBarTesting', 'User Has Web Interpretation Authority')
|
|
19
|
+
})
|
|
20
|
+
|
|
21
|
+
Given('the user has the M_dhis-web-messaging authority', () => {
|
|
22
|
+
cy.visitStory('HeaderBarTesting', 'User Has Web Messaging Authority')
|
|
23
|
+
})
|
|
24
|
+
|
|
25
|
+
Given('the user has authority for none of the apps', () => {
|
|
26
|
+
cy.visitStory('HeaderBarTesting', 'User Has No Authorities')
|
|
27
|
+
})
|
|
28
|
+
|
|
29
|
+
Then('the messaging app icon is not rendered', () => {
|
|
30
|
+
cy.get('[data-test="headerbar-messages"]').should('not.exist')
|
|
31
|
+
})
|
|
32
|
+
|
|
33
|
+
Then('the messaging app icon is rendered', () => {
|
|
34
|
+
cy.get('[data-test="headerbar-messages"]').should('exist')
|
|
35
|
+
})
|
|
36
|
+
|
|
37
|
+
Then('the interpretations app icon is not rendered', () => {
|
|
38
|
+
cy.get('[data-test="headerbar-interpretations"]').should('not.exist')
|
|
39
|
+
})
|
|
40
|
+
|
|
41
|
+
Then('the interpretations app icon is rendered', () => {
|
|
42
|
+
cy.get('[data-test="headerbar-interpretations"]').should('exist')
|
|
43
|
+
})
|
|
@@ -0,0 +1,26 @@
|
|
|
1
|
+
Feature: The HeaderBar conditionally renders notification icons
|
|
2
|
+
|
|
3
|
+
Scenario: The user has the All authority
|
|
4
|
+
Given the user has the ALL authority
|
|
5
|
+
Then the interpretations app icon is rendered
|
|
6
|
+
And the messaging app icon is rendered
|
|
7
|
+
|
|
8
|
+
Scenario: The user has authority for both apps
|
|
9
|
+
Given the user has the M_dhis-web-interpretation and M_dhis-web-messaging authority
|
|
10
|
+
Then the interpretations app icon is rendered
|
|
11
|
+
And the messaging app icon is rendered
|
|
12
|
+
|
|
13
|
+
Scenario: The user has authority for the interpretations app only
|
|
14
|
+
Given the user has the M_dhis-web-interpretation authority
|
|
15
|
+
Then the interpretations app icon is rendered
|
|
16
|
+
But the messaging app icon is not rendered
|
|
17
|
+
|
|
18
|
+
Scenario: The user has authority for the messaging app only
|
|
19
|
+
Given the user has the M_dhis-web-messaging authority
|
|
20
|
+
Then the messaging app icon is rendered
|
|
21
|
+
But the interpretations app icon is not rendered
|
|
22
|
+
|
|
23
|
+
Scenario: The user has authority for none of the apps
|
|
24
|
+
Given the user has authority for none of the apps
|
|
25
|
+
Then the messaging app icon is not rendered
|
|
26
|
+
And the interpretations app icon is not rendered
|
|
@@ -0,0 +1,9 @@
|
|
|
1
|
+
import { When } from '@badeball/cypress-cucumber-preprocessor'
|
|
2
|
+
|
|
3
|
+
When('the user opens the menu', () => {
|
|
4
|
+
cy.get('[data-test="headerbar-apps-icon"]').click()
|
|
5
|
+
})
|
|
6
|
+
|
|
7
|
+
When('the user clicks outside of the menu', () => {
|
|
8
|
+
cy.get('[data-test="headerbar-title"]').click()
|
|
9
|
+
})
|
|
@@ -0,0 +1,16 @@
|
|
|
1
|
+
import { When, Then } from '@badeball/cypress-cucumber-preprocessor'
|
|
2
|
+
|
|
3
|
+
When('the user clicks on the menu icons', () => {
|
|
4
|
+
cy.get('[data-test="headerbar-apps-icon"]').click()
|
|
5
|
+
})
|
|
6
|
+
|
|
7
|
+
Then('the menu opens', () => {
|
|
8
|
+
cy.get('[data-test="headerbar-apps-menu"]').should('be.visible')
|
|
9
|
+
})
|
|
10
|
+
|
|
11
|
+
Then('contains items with links', () => {
|
|
12
|
+
cy.get('[data-test="headerbar-apps-menu-list"]')
|
|
13
|
+
.find('a')
|
|
14
|
+
.its('length')
|
|
15
|
+
.should('be.greaterThan', 0)
|
|
16
|
+
})
|
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
Feature: The HeaderBar contains a menu to all apps
|
|
2
|
+
|
|
3
|
+
Scenario: The HeaderBar contains a menu icon
|
|
4
|
+
Given the HeaderBar loads without an error
|
|
5
|
+
Then the HeaderBar displays a menu icon
|
|
6
|
+
|
|
7
|
+
Scenario: The menu is closed by default
|
|
8
|
+
Given the HeaderBar loads without an error
|
|
9
|
+
Then the HeaderBar dos not display the app menu
|
|
10
|
+
|
|
11
|
+
Scenario: The user will be offered a menu with apps
|
|
12
|
+
Given the HeaderBar loads without an error
|
|
13
|
+
When the user clicks on the menu icons
|
|
14
|
+
Then the menu opens
|
|
15
|
+
And contains items with links
|
|
16
|
+
|
|
17
|
+
Scenario: The app menu closes when the user clicks outside
|
|
18
|
+
Given the HeaderBar loads without an error
|
|
19
|
+
When the user opens the menu
|
|
20
|
+
And the user clicks outside of the menu
|
|
21
|
+
Then the HeaderBar dos not display the app menu
|
|
@@ -0,0 +1,14 @@
|
|
|
1
|
+
import { Then, When } from '@badeball/cypress-cucumber-preprocessor'
|
|
2
|
+
|
|
3
|
+
Then('the HeaderBar does not display the profile menu', () => {
|
|
4
|
+
cy.get('[data-test="headerbar-profile-menu"]').should('not.exist')
|
|
5
|
+
})
|
|
6
|
+
|
|
7
|
+
When('the user opens the menu', () => {
|
|
8
|
+
cy.get(
|
|
9
|
+
`
|
|
10
|
+
[data-test="headerbar-profile-icon-text"],
|
|
11
|
+
[data-test="headerbar-profile-icon-image"]
|
|
12
|
+
`
|
|
13
|
+
).click()
|
|
14
|
+
})
|
|
@@ -0,0 +1,30 @@
|
|
|
1
|
+
import { Given, Then, When } from '@badeball/cypress-cucumber-preprocessor'
|
|
2
|
+
|
|
3
|
+
Given(
|
|
4
|
+
'the HeaderBar loads without an error and the user does not have an avatar',
|
|
5
|
+
() => {
|
|
6
|
+
cy.visitStory('HeaderBarTesting', 'Default')
|
|
7
|
+
}
|
|
8
|
+
)
|
|
9
|
+
|
|
10
|
+
Then(`the headerbar contains a text icon of size 36px`, () => {
|
|
11
|
+
cy.fixture('HeaderBar/me').then(() => {
|
|
12
|
+
cy.get('[data-test="headerbar-profile-icon-text"]')
|
|
13
|
+
.should('be.visible')
|
|
14
|
+
.and('have.css', 'height', '36px')
|
|
15
|
+
.and('have.css', 'width', '36px')
|
|
16
|
+
})
|
|
17
|
+
})
|
|
18
|
+
|
|
19
|
+
When('the user clicks on the text icon', () => {
|
|
20
|
+
cy.get('[data-test="headerbar-profile-icon-text"]').click()
|
|
21
|
+
})
|
|
22
|
+
|
|
23
|
+
Then(`the profile menu contains a text icon of size 48px`, () => {
|
|
24
|
+
cy.fixture('HeaderBar/me').then(() => {
|
|
25
|
+
cy.get('[data-test="headerbar-profile-menu-icon-text"]')
|
|
26
|
+
.should('be.visible')
|
|
27
|
+
.and('have.css', 'height', '48px')
|
|
28
|
+
.and('have.css', 'width', '48px')
|
|
29
|
+
})
|
|
30
|
+
})
|
|
@@ -0,0 +1,23 @@
|
|
|
1
|
+
import { Given, Then, When } from '@badeball/cypress-cucumber-preprocessor'
|
|
2
|
+
|
|
3
|
+
Given('the HeaderBar loads without an error and the user has an avatar', () => {
|
|
4
|
+
cy.visitStory('HeaderBarTesting', 'Me With Avatar')
|
|
5
|
+
})
|
|
6
|
+
|
|
7
|
+
Then('the headerbar contains an image icon of size 36px', () => {
|
|
8
|
+
cy.get('[data-test="headerbar-profile-icon-image"]')
|
|
9
|
+
.should('be.visible')
|
|
10
|
+
.and('have.css', 'height', '36px')
|
|
11
|
+
.and('have.css', 'width', '36px')
|
|
12
|
+
})
|
|
13
|
+
|
|
14
|
+
When('the user clicks on the image icon', () => {
|
|
15
|
+
cy.get('[data-test="headerbar-profile-icon-image"]').click()
|
|
16
|
+
})
|
|
17
|
+
|
|
18
|
+
Then('the profile menu contains an image icon of size 48px', () => {
|
|
19
|
+
cy.get('[data-test="headerbar-profile-menu-icon-image"]')
|
|
20
|
+
.should('be.visible')
|
|
21
|
+
.and('have.css', 'height', '48px')
|
|
22
|
+
.and('have.css', 'width', '48px')
|
|
23
|
+
})
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
// all step definitions are shared with other scenarios
|
|
@@ -0,0 +1,14 @@
|
|
|
1
|
+
import { When, Then } from '@badeball/cypress-cucumber-preprocessor'
|
|
2
|
+
|
|
3
|
+
When('the user clicks on the profile icons', () => {
|
|
4
|
+
cy.get(
|
|
5
|
+
`
|
|
6
|
+
[data-test="headerbar-profile-icon-text"],
|
|
7
|
+
[data-test="headerbar-profile-icon-image"]
|
|
8
|
+
`
|
|
9
|
+
).click()
|
|
10
|
+
})
|
|
11
|
+
|
|
12
|
+
Then('the menu opens', () => {
|
|
13
|
+
cy.get('[data-test="headerbar-profile-menu"]').should('be.visible')
|
|
14
|
+
})
|
|
@@ -0,0 +1,53 @@
|
|
|
1
|
+
import { When, Then } from '@badeball/cypress-cucumber-preprocessor'
|
|
2
|
+
import { baseUrl } from '../common/index.js'
|
|
3
|
+
|
|
4
|
+
const logoutUrl = `${baseUrl}dhis-web-commons-security/logout.action`
|
|
5
|
+
|
|
6
|
+
Then('contains a link to log out the user', () => {
|
|
7
|
+
cy.get('[data-test="headerbar-profile-menu"] > li').should((lis) => {
|
|
8
|
+
const menuItem = lis.eq(4)
|
|
9
|
+
expect(menuItem).to.be.visible
|
|
10
|
+
expect(menuItem.find('a')).to.have.attr('href', logoutUrl)
|
|
11
|
+
})
|
|
12
|
+
})
|
|
13
|
+
|
|
14
|
+
When('there is no loading mask', () => {
|
|
15
|
+
cy.get('[data-test="headerbar-profile-menu-loading-mask"]').should(
|
|
16
|
+
'not.exist'
|
|
17
|
+
)
|
|
18
|
+
})
|
|
19
|
+
|
|
20
|
+
Then('the user clicks the link to log out', () => {
|
|
21
|
+
cy.get('[data-test="headerbar-profile-menu"] > li:nth-child(5)').trigger(
|
|
22
|
+
'click'
|
|
23
|
+
)
|
|
24
|
+
})
|
|
25
|
+
|
|
26
|
+
Then('a loading mask covers the screen', () => {
|
|
27
|
+
cy.get('[data-test="headerbar-profile-menu-loading-mask"]').should(
|
|
28
|
+
'be.visible'
|
|
29
|
+
)
|
|
30
|
+
})
|
|
31
|
+
|
|
32
|
+
// Currently not working
|
|
33
|
+
When('clearSensitiveCaches is called', async () => {
|
|
34
|
+
// Open caches to test 'clearSensitiveCaches':
|
|
35
|
+
// A keepable cache
|
|
36
|
+
await caches.open('workbox-precache-v2-asdf')
|
|
37
|
+
// Other, potentially-sensitive cache
|
|
38
|
+
await caches.open('test-cache')
|
|
39
|
+
|
|
40
|
+
// Todo: wait for function to resolve (loading mask goes away?)
|
|
41
|
+
const keys = await caches.keys()
|
|
42
|
+
// Static asset caches are kept
|
|
43
|
+
expect(keys).to.include('workbox-precache-v2-asdf')
|
|
44
|
+
// Others are removed
|
|
45
|
+
expect(keys).not.to.include('test-cache')
|
|
46
|
+
})
|
|
47
|
+
|
|
48
|
+
// Currently not working
|
|
49
|
+
Then('the window navigates to the logout URL', () => {
|
|
50
|
+
// (Currently unable to stub window.location.assign;
|
|
51
|
+
// would be done in 'Then the user clicks link to log out')
|
|
52
|
+
// cy.get('@locationAssign').should('be.calledWith', logoutUrl)
|
|
53
|
+
})
|
package/src/features/the_headerbar_contains_a_profile_menu/the_user_name_and_email_are_displayed.js
ADDED
|
@@ -0,0 +1,22 @@
|
|
|
1
|
+
import { Then } from '@badeball/cypress-cucumber-preprocessor'
|
|
2
|
+
|
|
3
|
+
Then('contains the user name', () => {
|
|
4
|
+
cy.all(
|
|
5
|
+
() => cy.window(),
|
|
6
|
+
() => cy.get('[data-test="headerbar-profile-username"]')
|
|
7
|
+
).then(([win, $name]) => {
|
|
8
|
+
console.log('win.dataProviderData', win.dataProviderData)
|
|
9
|
+
const { name } = win.dataProviderData.me
|
|
10
|
+
expect($name.text()).to.equal(name)
|
|
11
|
+
})
|
|
12
|
+
})
|
|
13
|
+
|
|
14
|
+
Then('contains the user email', () => {
|
|
15
|
+
cy.all(
|
|
16
|
+
() => cy.window(),
|
|
17
|
+
() => cy.get('[data-test="headerbar-profile-user-email"]')
|
|
18
|
+
).then(([win, $email]) => {
|
|
19
|
+
const { email } = win.dataProviderData.me
|
|
20
|
+
expect($email.text()).to.equal(email)
|
|
21
|
+
})
|
|
22
|
+
})
|