@dhis2-ui/header-bar 10.16.1 → 10.16.3-alpha.1

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (125) hide show
  1. package/package.json +17 -16
  2. package/src/__e2e__/header-bar.e2e.stories.js +26 -0
  3. package/src/__e2e__/stories/common.js +226 -0
  4. package/src/__e2e__/stories/custom-application-title.js +19 -0
  5. package/src/__e2e__/stories/default.js +13 -0
  6. package/src/__e2e__/stories/me-with-avatar.js +27 -0
  7. package/src/__e2e__/stories/modulesWithSpecialCharacters.js +229 -0
  8. package/src/__e2e__/stories/online-status-message.js +49 -0
  9. package/src/__e2e__/stories/pwa-enabled.js +17 -0
  10. package/src/__e2e__/stories/user-has-all-authority.js +20 -0
  11. package/src/__e2e__/stories/user-has-no-authorities.js +20 -0
  12. package/src/__e2e__/stories/user-has-web-interpretation-and-messaging-authority.js +22 -0
  13. package/src/__e2e__/stories/user-has-web-interpretation-authority.js +22 -0
  14. package/src/__e2e__/stories/user-has-web-messaging-authority.js +22 -0
  15. package/src/__e2e__/stories/with-debug-info-edge-cases.js +51 -0
  16. package/src/__e2e__/stories/with-special-app-name-character.js +23 -0
  17. package/src/__e2e__/stories/with-update-available-notification.js +39 -0
  18. package/src/__e2e__/stories/zero-unread-interpretations.js +19 -0
  19. package/src/__e2e__/stories/zero-unread-messages.js +19 -0
  20. package/src/apps.js +276 -0
  21. package/src/debug-info/debug-info-menu-item.js +72 -0
  22. package/src/debug-info/debug-info-modal.js +47 -0
  23. package/src/debug-info/debug-info-table.js +51 -0
  24. package/src/debug-info/use-debug-info.js +15 -0
  25. package/src/features/common/index.js +14 -0
  26. package/src/features/the_headerbar_can_display_online_status/the_headerbar_displays_online_status.js +158 -0
  27. package/src/features/the_headerbar_can_display_online_status.feature +57 -0
  28. package/src/features/the_headerbar_conditionally_renders_notification_icons/the_headerbar_conditionally_renders_notification_icons.js +43 -0
  29. package/src/features/the_headerbar_conditionally_renders_notification_icons.feature +26 -0
  30. package/src/features/the_headerbar_contains_a_menu_to_all_apps/common.js +5 -0
  31. package/src/features/the_headerbar_contains_a_menu_to_all_apps/the_app_menu_closes_when_the_user_clicks_outside.js +9 -0
  32. package/src/features/the_headerbar_contains_a_menu_to_all_apps/the_headerbar_contains_a_menu_icon.js +5 -0
  33. package/src/features/the_headerbar_contains_a_menu_to_all_apps/the_user_will_be_offered_a_menu_with_5_apps.js +16 -0
  34. package/src/features/the_headerbar_contains_a_menu_to_all_apps.feature +21 -0
  35. package/src/features/the_headerbar_contains_a_profile_menu/common.js +14 -0
  36. 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
  37. package/src/features/the_headerbar_contains_a_profile_menu/the_headerbar_shows_an_image_icon_if_the_user_has_an_avatar.js +23 -0
  38. package/src/features/the_headerbar_contains_a_profile_menu/the_menu_is_closed_by_default.js +1 -0
  39. package/src/features/the_headerbar_contains_a_profile_menu/the_menu_opens.js +14 -0
  40. package/src/features/the_headerbar_contains_a_profile_menu/the_profile_menu_closes_when_the_user_clicks_outside.js +5 -0
  41. package/src/features/the_headerbar_contains_a_profile_menu/the_user_can_edit_his_profile.js +7 -0
  42. package/src/features/the_headerbar_contains_a_profile_menu/the_user_can_go_to_his_account.js +7 -0
  43. package/src/features/the_headerbar_contains_a_profile_menu/the_user_can_go_to_the_about_dhis2_page.js +7 -0
  44. package/src/features/the_headerbar_contains_a_profile_menu/the_user_can_go_to_the_help_page.js +7 -0
  45. package/src/features/the_headerbar_contains_a_profile_menu/the_user_can_go_to_the_settings.js +7 -0
  46. package/src/features/the_headerbar_contains_a_profile_menu/the_user_can_log_out.js +53 -0
  47. package/src/features/the_headerbar_contains_a_profile_menu/the_user_name_and_email_are_displayed.js +22 -0
  48. package/src/features/the_headerbar_contains_a_profile_menu.feature +73 -0
  49. 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
  50. package/src/features/the_headerbar_displays_a_link_to_interpretations_and_an_unread_count/there_are_no_unread_interpretations.js +9 -0
  51. package/src/features/the_headerbar_displays_a_link_to_interpretations_and_an_unread_count/there_are_some_unread_interpretations.js +12 -0
  52. package/src/features/the_headerbar_displays_a_link_to_interpretations_and_an_unread_count.feature +13 -0
  53. 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
  54. package/src/features/the_headerbar_displays_a_link_to_messages_and_an_unread_count/there_are_no_unread_messages.js +9 -0
  55. package/src/features/the_headerbar_displays_a_link_to_messages_and_an_unread_count/there_are_some_unread_messages.js +7 -0
  56. package/src/features/the_headerbar_displays_a_link_to_messages_and_an_unread_count.feature +13 -0
  57. package/src/features/the_headerbar_should_contain_a_logo_that_links_to_the_homepage/headerbar_contains_logo.js +12 -0
  58. package/src/features/the_headerbar_should_contain_a_logo_that_links_to_the_homepage.feature +6 -0
  59. package/src/features/the_headerbar_should_display_app_update_notification/index.js +52 -0
  60. package/src/features/the_headerbar_should_display_app_update_notification.feature +22 -0
  61. package/src/features/the_headerbar_should_display_debug_version_infos/index.js +130 -0
  62. package/src/features/the_headerbar_should_display_debug_version_infos.feature +52 -0
  63. 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
  64. package/src/features/the_headerbar_should_display_the_title_provided_by_the_backend_and_the_app.feature +5 -0
  65. package/src/features/the_search_should_escape_regexp_character/common.js +6 -0
  66. package/src/features/the_search_should_escape_regexp_character/the_modules_do_not_contain_items_with_special_chars.js +23 -0
  67. package/src/features/the_search_should_escape_regexp_character/the_user_searches_for_an_app_with_a_regex_character.js +29 -0
  68. package/src/features/the_search_should_escape_regexp_character.feature +48 -0
  69. package/src/header-bar-context.js +28 -0
  70. package/src/header-bar.js +145 -0
  71. package/src/header-bar.prod.stories.js +303 -0
  72. package/src/index.js +1 -0
  73. package/src/join-path.js +4 -0
  74. package/src/locales/ar/translations.json +24 -0
  75. package/src/locales/ar_IQ/translations.json +24 -0
  76. package/src/locales/bn/translations.json +12 -0
  77. package/src/locales/ckb/translations.json +23 -0
  78. package/src/locales/cs/translations.json +24 -0
  79. package/src/locales/da/translations.json +24 -0
  80. package/src/locales/en/translations.json +25 -0
  81. package/src/locales/en_US/translations.json +25 -0
  82. package/src/locales/es/translations.json +25 -0
  83. package/src/locales/es_419/translations.json +24 -0
  84. package/src/locales/fr/translations.json +25 -0
  85. package/src/locales/hi_IN/translations.json +25 -0
  86. package/src/locales/id/translations.json +24 -0
  87. package/src/locales/index.js +88 -0
  88. package/src/locales/km/translations.json +24 -0
  89. package/src/locales/lo/translations.json +24 -0
  90. package/src/locales/my/translations.json +24 -0
  91. package/src/locales/nb/translations.json +24 -0
  92. package/src/locales/nl/translations.json +24 -0
  93. package/src/locales/or/translations.json +12 -0
  94. package/src/locales/prs/translations.json +24 -0
  95. package/src/locales/ps/translations.json +24 -0
  96. package/src/locales/pt/translations.json +25 -0
  97. package/src/locales/pt_BR/translations.json +24 -0
  98. package/src/locales/ro/translations.json +23 -0
  99. package/src/locales/ru/translations.json +24 -0
  100. package/src/locales/si/translations.json +24 -0
  101. package/src/locales/sv/translations.json +24 -0
  102. package/src/locales/tet/translations.json +24 -0
  103. package/src/locales/tg/translations.json +24 -0
  104. package/src/locales/uk/translations.json +24 -0
  105. package/src/locales/ur/translations.json +24 -0
  106. package/src/locales/uz_Latn/translations.json +23 -0
  107. package/src/locales/uz_UZ_Cyrl/translations.json +24 -0
  108. package/src/locales/uz_UZ_Latn/translations.json +24 -0
  109. package/src/locales/vi/translations.json +24 -0
  110. package/src/locales/zh/translations.json +25 -0
  111. package/src/locales/zh_CN/translations.json +24 -0
  112. package/src/logo-image.js +71 -0
  113. package/src/logo.js +45 -0
  114. package/src/notification-icon.js +91 -0
  115. package/src/notifications.js +63 -0
  116. package/src/online-status.js +40 -0
  117. package/src/online-status.styles.js +91 -0
  118. package/src/profile/use-on-doc-click.js +23 -0
  119. package/src/profile/use-on-doc-click.test.js +40 -0
  120. package/src/profile-menu/index.js +1 -0
  121. package/src/profile-menu/profile-header.js +118 -0
  122. package/src/profile-menu/profile-menu.js +176 -0
  123. package/src/profile-menu/update-notification.js +67 -0
  124. package/src/profile.js +101 -0
  125. 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
+ })
@@ -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,5 @@
1
+ import { Then } from '@badeball/cypress-cucumber-preprocessor'
2
+
3
+ Then('the HeaderBar dos not display the app menu', () => {
4
+ cy.get('[data-test="headerbar-apps-menu"]').should('not.exist')
5
+ })
@@ -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,5 @@
1
+ import { Then } from '@badeball/cypress-cucumber-preprocessor'
2
+
3
+ Then('the HeaderBar displays a menu icon', () => {
4
+ cy.get('[data-test="headerbar-apps-icon"]').should('exist')
5
+ })
@@ -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,5 @@
1
+ import { When } from '@badeball/cypress-cucumber-preprocessor'
2
+
3
+ When('the user clicks outside of the menu', () => {
4
+ cy.get('[data-test="headerbar-title"]').click()
5
+ })
@@ -0,0 +1,7 @@
1
+ import { Then } from '@badeball/cypress-cucumber-preprocessor'
2
+
3
+ Then('contains a link to edit the profile', () => {
4
+ cy.get('[data-test="headerbar-profile-edit-profile-link"]').should(
5
+ 'be.visible'
6
+ )
7
+ })
@@ -0,0 +1,7 @@
1
+ import { Then } from '@badeball/cypress-cucumber-preprocessor'
2
+
3
+ Then('contains a link to the user account', () => {
4
+ cy.get('[data-test="headerbar-profile-menu"] > li').should((lis) => {
5
+ expect(lis.eq(1)).to.be.visible
6
+ })
7
+ })
@@ -0,0 +1,7 @@
1
+ import { Then } from '@badeball/cypress-cucumber-preprocessor'
2
+
3
+ Then('contains a link to the About DHIS2 page', () => {
4
+ cy.get('[data-test="headerbar-profile-menu"] > li').should((lis) => {
5
+ expect(lis.eq(3)).to.be.visible
6
+ })
7
+ })
@@ -0,0 +1,7 @@
1
+ import { Then } from '@badeball/cypress-cucumber-preprocessor'
2
+
3
+ Then('contains a link to the help page', () => {
4
+ cy.get('[data-test="headerbar-profile-menu"] > li').should((lis) => {
5
+ expect(lis.eq(2)).to.be.visible
6
+ })
7
+ })
@@ -0,0 +1,7 @@
1
+ import { Then } from '@badeball/cypress-cucumber-preprocessor'
2
+
3
+ Then('contains a link to the settings', () => {
4
+ cy.get('[data-test="headerbar-profile-menu"] > li').should((lis) => {
5
+ expect(lis.eq(0)).to.be.visible
6
+ })
7
+ })
@@ -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
+ })
@@ -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
+ })