From e0806e0a63b09dfb5d168d71e91eb1d1040f6fb7 Mon Sep 17 00:00:00 2001 From: Ben Kiarie Date: Mon, 18 Nov 2024 06:42:08 +0300 Subject: [PATCH] update e2e --- .github/workflows/build.yml | 2 +- api/Dockerfile | 4 +- api/package.json | 4 +- api/server.js | 12 +- api/src/auth.js | 10 +- api/src/controllers/login.js | 43 +- .../mocha/services/async-storage.spec.js | 5 - package.json | 4 +- scripts/deploy/package-lock.json | 4 +- scripts/deploy/package.json | 4 +- sentinel/Dockerfile | 4 +- sentinel/package-lock.json | 4 +- sentinel/package.json | 4 +- .../navigation/more-options-menu.wdio-spec.js | 32 +- .../old-navigation.wdio-spec.js | 5 +- .../reports/send-message.wdio-spec.js | 8 +- tests/e2e/default-mobile/wdio.conf.js | 1 + .../default/admin/admin-access.wdio-spec.js | 8 +- .../default/analytics/analytics.wdio-spec.js | 2 +- .../delete-assigned-place.wdio-spec.js | 2 +- .../e2e/default/contacts/export.wdio-spec.js | 9 +- tests/e2e/default/db/db-sync.wdio-spec.js | 4 +- .../default/enketo/add-family.wdio-spec.js | 2 +- .../default/enketo/death-report.wdio-spec.js | 2 +- .../edit-report-with-attachment.wdio-spec.js | 8 +- .../default/enketo/phone-widget.wdio-spec.js | 3 +- ...pregnancy-complete-a-delivery.wdio-spec.js | 6 +- ...egnancy-danger-sign-follow-up.wdio-spec.js | 4 +- .../submit-photo-upload-form.wdio-spec.js | 4 +- .../enketo/submit-z-score-form.wdio-spec.js | 2 +- .../e2e/default/logging/logging.wdio-spec.js | 2 +- .../default/login/login-logout.wdio-spec.js | 18 +- .../offline-user/all-permissions.wdio-spec.js | 50 +- .../delete-permission-disabled.wdio-spec.js | 16 +- .../edit-permission-disabled.wdio-spec.js | 6 +- .../permissions-disabled.wdio-spec.js | 46 +- .../permissions-enabled.wdio-spec.js | 44 +- .../privacy-policy.wdio-spec.js | 25 +- tests/e2e/default/reports/delete.wdio-spec.js | 2 +- tests/e2e/default/reports/export.wdio-spec.js | 8 +- .../service-worker.wdio-spec.js | 4 +- .../tasks/config/tasks-breadcrumbs-config.js | 33 +- .../e2e/default/tasks/due-dates.wdio-spec.js | 2 +- tests/e2e/default/tasks/tasks.wdio-spec.js | 18 + .../incorrect-locale.wdio-spec.js | 5 +- .../translations/message-format.wdio-spec.js | 7 +- .../nepali-dates-and-numbers.wdio-spec.js | 2 +- .../translations/new-language.wdio-spec.js | 2 +- tests/integration/api/server.spec.js | 24 + .../haproxy/keep-alive-script/Dockerfile | 2 +- .../default/about/about.wdio.page.js | 2 - .../default/admin/admin.wdio.page.js | 2 +- .../default/analytics/analytics.wdio.page.js | 14 - .../default/common/common.wdio.page.js | 545 +++++++++--------- .../default/contacts/contacts.wdio.page.js | 29 +- .../default/enketo/custom-doc.wdio.page.js | 3 - .../default/login/login.wdio.page.js | 1 + .../old-navigation.wdio.page.js | 8 + .../privacy-policy.wdio.page.js | 2 +- .../default/reports/reports.wdio.page.js | 33 +- .../default/users/user-settings.wdio.page.js | 4 +- .../default/users/user.wdio.page.js | 3 +- 62 files changed, 588 insertions(+), 580 deletions(-) diff --git a/.github/workflows/build.yml b/.github/workflows/build.yml index 334d51143ea..2b983ac1a35 100644 --- a/.github/workflows/build.yml +++ b/.github/workflows/build.yml @@ -16,7 +16,7 @@ env: TAG: ${{ (github.ref_type == 'tag' && github.ref_name) || '' }} BRANCH: ${{ github.head_ref || github.ref_name }} BUILD_NUMBER: ${{ github.run_id }} - NODE_VERSION: '20.11' + NODE_VERSION: '22.11' jobs: diff --git a/api/Dockerfile b/api/Dockerfile index fd35f5b327a..46f417dfb59 100644 --- a/api/Dockerfile +++ b/api/Dockerfile @@ -1,10 +1,8 @@ -FROM alpine:3.19 AS base_build +FROM node:22-alpine AS base_build RUN apk add --update --no-cache \ build-base \ curl \ - nodejs~=20 \ - npm~=10 \ tzdata \ libxslt \ bash \ diff --git a/api/package.json b/api/package.json index 1c9ff46e6f3..9b6e5e2a949 100644 --- a/api/package.json +++ b/api/package.json @@ -8,8 +8,8 @@ "url": "git://github.com/medic/cht-core.git" }, "engines": { - "node": ">=20.11.0", - "npm": ">=10.2.4" + "node": ">=22.11.0", + "npm": ">=10.9.0" }, "scripts": { "toc": "doctoc --github --maxlevel 2 README.md", diff --git a/api/server.js b/api/server.js index fb8d799d8ef..6364630fda2 100644 --- a/api/server.js +++ b/api/server.js @@ -82,7 +82,6 @@ process await migrations.run(); logger.info('Database migrations completed successfully'); - startupLog.start('forms'); logger.info('Generating manifest'); await manifest.generate(); logger.info('Manifest generated successfully'); @@ -90,15 +89,20 @@ process logger.info('Generating service worker'); await generateServiceWorker.run(true); logger.info('Service worker generated successfully'); + } catch (err) { + logger.error('Fatal error initialising API'); + logger.error('%o', err); + process.exit(1); + } + try { + startupLog.start('forms'); logger.info('Updating xforms…'); await generateXform.updateAll(); logger.info('xforms updated successfully'); - } catch (err) { - logger.error('Fatal error initialising API'); + logger.error('Error initialising API'); logger.error('%o', err); - process.exit(1); } startupLog.complete(); diff --git a/api/src/auth.js b/api/src/auth.js index 59ab14a5f5d..9c539341e23 100644 --- a/api/src/auth.js +++ b/api/src/auth.js @@ -78,7 +78,10 @@ module.exports = { checkPasswordChange: async (req) => { if (!req.userCtx || !req.userCtx.name) { - throw { code: 401, message: 'Not logged in' }; + const error = new Error('Not logged in'); + error.code = 401; + error.error = 'Not logged in'; + throw error; } if (req.url.includes('/password-reset')) { @@ -91,7 +94,10 @@ module.exports = { const user = await users.getUserDoc((req.userCtx.name)); if (user.password_change_required) { - throw { code: 403, message: 'Password change required' }; + const error = new Error('Password change required'); + error.code = 403; + error.error = 'Password change required'; + throw error; } return true; }, diff --git a/api/src/controllers/login.js b/api/src/controllers/login.js index 5b64a7ca164..53ccc5f12b7 100644 --- a/api/src/controllers/login.js +++ b/api/src/controllers/login.js @@ -450,6 +450,30 @@ const validateCurrentPassword = async (username, currentPassword, newPassword) = } }; +const passwordResetValidation = async (username, currentPassword, password) => { + const validation = validatePasswordReset(password); + if (!validation.isValid) { + return { + isValid: false, + status: 400, + error: validation.error, + params: validation.params + }; + } + + const currentPasswordValidation = await validateCurrentPassword(username, currentPassword, password); + if (!currentPasswordValidation.isValid) { + return { + isValid: false, + status: 400, + error: currentPasswordValidation.error + }; + } + + return { isValid: true }; +}; + + module.exports = { renderLogin, renderPasswordReset, @@ -510,26 +534,19 @@ module.exports = { try { const { username, currentPassword, password } = req.body; - const validation = validatePasswordReset(password); - if (!validation.isValid) { - return res.status(400).json({ - error: validation.error, - params: validation.params, - }); - } - const currentPasswordValidation = await validateCurrentPassword(username, currentPassword, password); - if (!currentPasswordValidation.isValid) { - return res.status(400).json({ - error: currentPasswordValidation.error + const validationResult = await passwordResetValidation(username, currentPassword, password); + if (!validationResult.isValid) { + return res.status(validationResult.status).json({ + error: validationResult.error, + params: validationResult.params }); } + const userDoc = await db.users.get(`org.couchdb.user:${username}`); await updatePassword(userDoc, password); const { sessionCookie, userCtx } = await createNewSession(username, password); - const redirectUrl = await redirectToApp({ req, res, sessionCookie, userCtx }); - return res.status(302).send(redirectUrl); } catch (err) { logger.error('Error updating password: %o', err); diff --git a/api/tests/mocha/services/async-storage.spec.js b/api/tests/mocha/services/async-storage.spec.js index cc77549ed17..e7b7e17b55a 100644 --- a/api/tests/mocha/services/async-storage.spec.js +++ b/api/tests/mocha/services/async-storage.spec.js @@ -1,16 +1,13 @@ const sinon = require('sinon'); const rewire = require('rewire'); const { expect } = require('chai'); -const asyncHooks = require('node:async_hooks'); const request = require('@medic/couch-request'); const serverUtils = require('../../../src/server-utils'); describe('async-storage', () => { let service; - let asyncLocalStorage; beforeEach(() => { - asyncLocalStorage = sinon.spy(asyncHooks, 'AsyncLocalStorage'); sinon.stub(request, 'initialize'); }); @@ -20,8 +17,6 @@ describe('async-storage', () => { it('should initialize async storage and initialize couch-request', async () => { service = rewire('../../../src/services/async-storage'); - - expect(asyncLocalStorage.callCount).to.equal(1); expect(request.initialize.args).to.deep.equal([[ service, serverUtils.REQUEST_ID_HEADER diff --git a/package.json b/package.json index 2064e3b99c2..43e9019ccce 100644 --- a/package.json +++ b/package.json @@ -8,8 +8,8 @@ "url": "git://github.com/medic/cht-core.git" }, "engines": { - "node": ">=20.11.0", - "npm": ">=10.2.4" + "node": ">=22.11.0", + "npm": ">=10.9.0" }, "workspaces": [ "./shared-libs/*" diff --git a/scripts/deploy/package-lock.json b/scripts/deploy/package-lock.json index 8d80e83826c..89d84f2d027 100644 --- a/scripts/deploy/package-lock.json +++ b/scripts/deploy/package-lock.json @@ -32,8 +32,8 @@ "sinon": "^17.0.1" }, "engines": { - "node": ">=20.11.0", - "npm": ">=10.2.4" + "node": ">=22.11.0", + "npm": ">=10.9.0" } }, "node_modules/@isaacs/cliui": { diff --git a/scripts/deploy/package.json b/scripts/deploy/package.json index 02fb47b32bf..9776cbcb8e0 100644 --- a/scripts/deploy/package.json +++ b/scripts/deploy/package.json @@ -7,8 +7,8 @@ "test": "tests" }, "engines": { - "node": ">=20.11.0", - "npm": ">=10.2.4" + "node": ">=22.11.0", + "npm": ">=10.9.0" }, "bin": { "cht-deploy": "./cht-deploy", diff --git a/sentinel/Dockerfile b/sentinel/Dockerfile index 834828ac503..7c7cb950cfc 100644 --- a/sentinel/Dockerfile +++ b/sentinel/Dockerfile @@ -1,10 +1,8 @@ -FROM alpine:3.19 AS base_build +FROM node:22-alpine AS base_build RUN apk add --update --no-cache \ build-base \ curl \ - nodejs~=20 \ - npm~=10 \ tzdata \ bash \ jq diff --git a/sentinel/package-lock.json b/sentinel/package-lock.json index 674251a9427..52c73db440e 100644 --- a/sentinel/package-lock.json +++ b/sentinel/package-lock.json @@ -8,8 +8,8 @@ "name": "medic-sentinel", "version": "0.1.0", "engines": { - "node": ">=20.11.0", - "npm": ">=10.2.4" + "node": ">=22.11.0", + "npm": ">=10.9.0" } }, "../shared-libs/cht-datasource": { diff --git a/sentinel/package.json b/sentinel/package.json index cbeb28a96e2..1365be2601d 100644 --- a/sentinel/package.json +++ b/sentinel/package.json @@ -4,8 +4,8 @@ "private": true, "version": "0.1.0", "engines": { - "node": ">=20.11.0", - "npm": ">=10.2.4" + "node": ">=22.11.0", + "npm": ">=10.9.0" }, "scripts": { "run-watch": "TZ=UTC nodemon --inspect=0.0.0.0:9228 --watch server.js --watch 'src/**' --watch '../shared-libs/**/src/**' --watch '../shared-libs/**/dist/**' server.js" diff --git a/tests/e2e/default-mobile/navigation/more-options-menu.wdio-spec.js b/tests/e2e/default-mobile/navigation/more-options-menu.wdio-spec.js index 72214a2272d..a13bd85876d 100644 --- a/tests/e2e/default-mobile/navigation/more-options-menu.wdio-spec.js +++ b/tests/e2e/default-mobile/navigation/more-options-menu.wdio-spec.js @@ -58,7 +58,7 @@ describe('More Options Menu - Offline User', () => { describe('Message tab', () => { it('should hide the kebab menu.', async () => { await sms.sendSms('testing', contact.phone); - expect(await (await commonPage.moreOptionsMenu()).isExisting()).to.be.false; + expect(await commonPage.isMoreOptionsMenuPresent()).to.be.false; }); }); @@ -73,9 +73,9 @@ describe('More Options Menu - Offline User', () => { await commonPage.goToPeople(); await contactsPage.selectLHSRowByText(patient.name); await commonPage.openMoreOptionsMenu(); - expect(await commonPage.isMenuOptionVisible('export', 'contacts')).to.be.false; - expect(await commonPage.isMenuOptionEnabled('edit', 'contacts')).to.be.true; - expect(await commonPage.isMenuOptionEnabled('delete', 'contacts')).to.be.true; + expect(await commonPage.isMenuOptionVisible('export')).to.be.false; + expect(await commonPage.isMenuOptionEnabled('edit')).to.be.true; + expect(await commonPage.isMenuOptionEnabled('delete')).to.be.true; }); it('should hide the \'export\' and \'edit\' options and ' + @@ -83,9 +83,9 @@ describe('More Options Menu - Offline User', () => { await commonPage.goToPeople(); await contactsPage.selectLHSRowByText(health_center.name); await commonPage.openMoreOptionsMenu(); - expect(await commonPage.isMenuOptionVisible('export', 'contacts')).to.be.false; - expect(await commonPage.isMenuOptionVisible('edit', 'contacts')).to.be.false; - expect(await commonPage.isMenuOptionEnabled('delete', 'contacts')).to.be.false; + expect(await commonPage.isMenuOptionVisible('export')).to.be.false; + expect(await commonPage.isMenuOptionVisible('edit')).to.be.false; + expect(await commonPage.isMenuOptionEnabled('delete')).to.be.false; }); }); @@ -93,24 +93,24 @@ describe('More Options Menu - Offline User', () => { it('should hide the \'export\' and \'edit\' options and ' + 'enable the \'delete\' and \'review\' options when the sms report is opened', async () => { await commonPage.goToReports(); - expect(await (await commonPage.moreOptionsMenu()).isExisting()).to.be.false; + expect(await commonPage.isMoreOptionsMenuPresent()).to.be.false; await reportPage.goToReportById(smsReportId); await commonPage.openMoreOptionsMenu(); - expect(await commonPage.isMenuOptionVisible('export', 'reports')).to.be.false; - expect(await commonPage.isMenuOptionVisible('edit', 'reports')).to.be.false; - expect(await commonPage.isMenuOptionEnabled('delete', 'reports')).to.be.true; - expect(await commonPage.isMenuOptionEnabled('review', 'report')).to.be.true; + expect(await commonPage.isMenuOptionVisible('export')).to.be.false; + expect(await commonPage.isMenuOptionVisible('edit',)).to.be.false; + expect(await commonPage.isMenuOptionEnabled('delete')).to.be.true; + expect(await commonPage.isMenuOptionEnabled('review')).to.be.true; }); it('should hide the \'export\' option and ' + 'enable the \'edit\', \'delete\' and \'review\' options when the xml report is opened', async () => { await reportPage.goToReportById(xmlReportId); await commonPage.openMoreOptionsMenu(); - expect(await commonPage.isMenuOptionVisible('export', 'reports')).to.be.false; - expect(await commonPage.isMenuOptionEnabled('edit', 'reports')).to.be.true; - expect(await commonPage.isMenuOptionEnabled('delete', 'reports')).to.be.true; - expect(await commonPage.isMenuOptionEnabled('review', 'report')).to.be.true; + expect(await commonPage.isMenuOptionVisible('export')).to.be.false; + expect(await commonPage.isMenuOptionEnabled('edit')).to.be.true; + expect(await commonPage.isMenuOptionEnabled('delete')).to.be.true; + expect(await commonPage.isMenuOptionEnabled('review')).to.be.true; }); }); }); diff --git a/tests/e2e/default-mobile/old-navigation/old-navigation.wdio-spec.js b/tests/e2e/default-mobile/old-navigation/old-navigation.wdio-spec.js index ffb4f25a667..fa637bb23e8 100644 --- a/tests/e2e/default-mobile/old-navigation/old-navigation.wdio-spec.js +++ b/tests/e2e/default-mobile/old-navigation/old-navigation.wdio-spec.js @@ -6,7 +6,6 @@ const pregnancyFactory = require('@factories/cht/reports/pregnancy'); const loginPage = require('@page-objects/default/login/login.wdio.page'); const oldNavigationPage = require('@page-objects/default/old-navigation/old-navigation.wdio.page'); const messagesPage = require('@page-objects/default/sms/messages.wdio.page'); -const commonPage = require('@page-objects/default/common/common.wdio.page'); const taskPage = require('@page-objects/default/tasks/tasks.wdio.page'); const reportsPage = require('@page-objects/default/reports/reports.wdio.page'); const contactPage = require('@page-objects/default/contacts/contacts.wdio.page'); @@ -56,7 +55,7 @@ describe('Old Navigation', () => { await messagesPage.sendMessageOnMobile(message, person.name, person.phone ); await messagesPage.openMessage(person._id); - const { name } = await commonPage.getHeaderTitleOnMobile(); + const { name } = await oldNavigationPage.getHeaderTitleOnMobile(); expect(name).to.equal(person.name); const messages = await messagesPage.getAmountOfMessagesByPhone(); @@ -71,7 +70,7 @@ describe('Old Navigation', () => { pregnancyReport._id, '~pregnancy-danger-sign-follow-up~anc.pregnancy_danger_sign_followup' ); - const { name } = await commonPage.getHeaderTitleOnMobile(); + const { name } = await oldNavigationPage.getHeaderTitleOnMobile(); expect(name).to.equal('Pregnancy danger sign follow-up'); }); diff --git a/tests/e2e/default-mobile/reports/send-message.wdio-spec.js b/tests/e2e/default-mobile/reports/send-message.wdio-spec.js index a973be680fd..11acd90734f 100644 --- a/tests/e2e/default-mobile/reports/send-message.wdio-spec.js +++ b/tests/e2e/default-mobile/reports/send-message.wdio-spec.js @@ -3,7 +3,7 @@ const placeFactory = require('@factories/cht/contacts/place'); const userFactory = require('@factories/cht/users/users'); const personFactory = require('@factories/cht/contacts/person'); const loginPage = require('@page-objects/default/login/login.wdio.page'); -const commonElements = require('@page-objects/default/common/common.wdio.page'); +const commonPage = require('@page-objects/default/common/common.wdio.page'); const reportsPage = require('@page-objects/default/reports/reports.wdio.page'); const pregnancyFactory = require('@factories/cht/reports/pregnancy'); @@ -39,12 +39,12 @@ describe('Report - Send message action', () => { }); it('should display option to send message', async () => { - await commonElements.goToReports(); + await commonPage.goToReports(); const firstReport = await reportsPage.leftPanelSelectors.firstReport(); await reportsPage.openSelectedReport(firstReport); - expect(await commonElements.isReportActionDisplayed()).to.equal(true); - expect(await commonElements.reportsFastActionFAB().getAttribute('class')) + expect(await commonPage.isReportActionDisplayed()).to.equal(true); + expect(await commonPage.fabSelectors.reportsFastActionFAB().getAttribute('class')) .to.include('fa-envelope'); }); }); diff --git a/tests/e2e/default-mobile/wdio.conf.js b/tests/e2e/default-mobile/wdio.conf.js index e05b097ed5f..6b1fd0e8282 100644 --- a/tests/e2e/default-mobile/wdio.conf.js +++ b/tests/e2e/default-mobile/wdio.conf.js @@ -12,6 +12,7 @@ exports.config = Object.assign(wdioBaseConfig.config, { '../default/navigation/navigation.wdio-spec.js', '../default/reports/delete.wdio-spec.js', '../default/enketo/training-cards.wdio-spec.js', + './**/more-options-menu.wdio-spec.js', ] }, beforeSuite: async () => { diff --git a/tests/e2e/default/admin/admin-access.wdio-spec.js b/tests/e2e/default/admin/admin-access.wdio-spec.js index f2d237731be..388d4f10a1d 100644 --- a/tests/e2e/default/admin/admin-access.wdio-spec.js +++ b/tests/e2e/default/admin/admin-access.wdio-spec.js @@ -38,19 +38,19 @@ describe('Accessing the admin app', () => { await common.waitForLoaders(); await browser.url('/admin/#/forms'); expect(await (await adminPage.adminNavbarLogo()).isDisplayed()).to.equal(false); - expect(await common.jsonError()).to.equal(error); + expect(await common.getJsonErrorText()).to.equal(error); await browser.url('/admin'); expect(await (await adminPage.adminNavbarLogo()).isDisplayed()).to.equal(false); - expect(await common.jsonError()).to.equal(error); + expect(await common.getJsonErrorText()).to.equal(error); await browser.url('/medic/_design/medic-admin/_rewrite/'); expect(await (await adminPage.adminNavbarLogo()).isDisplayed()).to.equal(false); - expect(await common.jsonError()).to.equal(error); + expect(await common.getJsonErrorText()).to.equal(error); await browser.url('/medic/_design/medic-admin/_rewrite/#/authorization/permissions'); expect(await (await adminPage.adminNavbarLogo()).isDisplayed()).to.equal(false); - expect(await common.jsonError()).to.equal(error); + expect(await common.getJsonErrorText()).to.equal(error); }); it('should allow admins to access the page', async () => { diff --git a/tests/e2e/default/analytics/analytics.wdio-spec.js b/tests/e2e/default/analytics/analytics.wdio-spec.js index 19542236fbc..80d94c18a68 100644 --- a/tests/e2e/default/analytics/analytics.wdio-spec.js +++ b/tests/e2e/default/analytics/analytics.wdio-spec.js @@ -43,7 +43,7 @@ describe('Targets', () => { await sentinelUtils.waitForSentinel(); await loginPage.login(chw); - await (await commonPage.analyticsTab()).waitForDisplayed(); + await (await commonPage.tabsSelector.analyticsTab()).waitForDisplayed(); }); afterEach(async () => { diff --git a/tests/e2e/default/contacts/delete-assigned-place.wdio-spec.js b/tests/e2e/default/contacts/delete-assigned-place.wdio-spec.js index 2f6fedb6c83..d6f00e7df47 100644 --- a/tests/e2e/default/contacts/delete-assigned-place.wdio-spec.js +++ b/tests/e2e/default/contacts/delete-assigned-place.wdio-spec.js @@ -65,6 +65,6 @@ describe('User Test Cases -> Creating Users ->', () => { await contactPage.selectLHSRowByText(districtHospital2.name); await commonPage.openMoreOptionsMenu(); - expect(await commonPage.isMenuOptionEnabled('delete', 'contacts')).to.be.false; + expect(await commonPage.isMenuOptionEnabled('delete')).to.be.false; }); }); diff --git a/tests/e2e/default/contacts/export.wdio-spec.js b/tests/e2e/default/contacts/export.wdio-spec.js index 32d0e50a87a..648587076d1 100644 --- a/tests/e2e/default/contacts/export.wdio-spec.js +++ b/tests/e2e/default/contacts/export.wdio-spec.js @@ -1,9 +1,8 @@ const moment = require('moment'); -const contactPage = require('@page-objects/default/contacts/contacts.wdio.page'); const userFactory = require('@factories/cht/users/users'); const placeFactory = require('@factories/cht/contacts/place'); const personFactory = require('@factories/cht/contacts/person'); -const commonElements = require('@page-objects/default/common/common.wdio.page'); +const commonPage = require('@page-objects/default/common/common.wdio.page'); const loginPage = require('@page-objects/default/login/login.wdio.page'); const fileDownloadUtils = require('@utils/file-download'); const utils = require('@utils'); @@ -23,12 +22,12 @@ describe('Export Contacts ', () => { contactDocs.forEach(savedContact => savedContactIds.push(savedContact.id)); await utils.createUsers([ onlineUser ]); await loginPage.login(onlineUser); - await commonElements.waitForPageLoaded(); - await commonElements.goToPeople(); + await commonPage.waitForPageLoaded(); + await commonPage.goToPeople(); }); it('should download export file', async () => { - await contactPage.exportContacts(); + await commonPage.accessExportOption(); const files = await fileDownloadUtils.waitForDownload(`contacts-${today.format('YYYYMMDD')}`); expect(files).to.not.be.undefined; diff --git a/tests/e2e/default/db/db-sync.wdio-spec.js b/tests/e2e/default/db/db-sync.wdio-spec.js index 24c327738c7..ffc7b4a3a2d 100644 --- a/tests/e2e/default/db/db-sync.wdio-spec.js +++ b/tests/e2e/default/db/db-sync.wdio-spec.js @@ -98,8 +98,8 @@ describe('db-sync', () => { body: restrictedUser }); await sentinelUtils.waitForSentinel(); - await loginPage.login({ username: restrictedUserName, password: restrictedPass }); - await (await commonElements.analyticsTab()).waitForDisplayed(); + await loginPage.login({ username: restrictedUserName, password: restrictedPass, resetPassword: false }); + await (await commonElements.tabsSelector.analyticsTab()).waitForDisplayed(); }); after(async () => { diff --git a/tests/e2e/default/enketo/add-family.wdio-spec.js b/tests/e2e/default/enketo/add-family.wdio-spec.js index 5d03750c5a1..1cdc770359b 100644 --- a/tests/e2e/default/enketo/add-family.wdio-spec.js +++ b/tests/e2e/default/enketo/add-family.wdio-spec.js @@ -18,7 +18,7 @@ describe('Family form', () => { await commonPage.openFastActionReport('add-family-multiple-repeats', false); await familyForm.submitFamilyForm(); await familyForm.reportCheck('test Family', 'boreholes', 'true', 'true', 'ucid'); - await reportsPage.editReport(); + await commonPage.accessEditOption(); await commonEnketoPage.setInputValue('Names', 'modified'); await genericForm.nextPage(7); await commonEnketoPage.selectCheckBox('What is the family\'s source of drinking water?', 'Spring'); diff --git a/tests/e2e/default/enketo/death-report.wdio-spec.js b/tests/e2e/default/enketo/death-report.wdio-spec.js index b4829321ce6..49ba3f2c1a4 100644 --- a/tests/e2e/default/enketo/death-report.wdio-spec.js +++ b/tests/e2e/default/enketo/death-report.wdio-spec.js @@ -65,7 +65,7 @@ describe('Submit a death report', () => { expect((await reportsPage.getDetailReportRowContent('place_of_death')).rowValues[0]).to.equal('health_facility'); // Edit the report created - await reportsPage.editReport(); + await commonPage.accessEditOption(); await commonEnketoPage.selectRadioButton('Place of death', 'Home'); await genericForm.nextPage(); await genericForm.submitForm(); diff --git a/tests/e2e/default/enketo/edit-report-with-attachment.wdio-spec.js b/tests/e2e/default/enketo/edit-report-with-attachment.wdio-spec.js index b92f4949313..13df92e8112 100644 --- a/tests/e2e/default/enketo/edit-report-with-attachment.wdio-spec.js +++ b/tests/e2e/default/enketo/edit-report-with-attachment.wdio-spec.js @@ -27,7 +27,7 @@ describe('Edit report with attachment', () => { await commonPage.goToReports(); await reportsPage.openReport(editReportWithAttachmentDoc._id); - await reportsPage.editReport(); + await commonPage.accessEditOption(); await genericForm.submitForm(); const editedReport = await utils.getDoc(editReportWithAttachmentDoc._id); @@ -35,7 +35,7 @@ describe('Edit report with attachment', () => { expect(editedReport.fields).excludingEvery('meta').to.deep.equal({ intro: 'initial text' }); await reportsPage.openReport(editReportWithAttachmentDoc._id); - await reportsPage.editReport(); + await commonPage.accessEditOption(); await genericForm.submitForm(); const twiceEditedReport = await utils.getDoc(editReportWithAttachmentDoc._id); @@ -50,7 +50,7 @@ describe('Edit report with attachment', () => { await commonPage.goToReports(); await reportsPage.openReport(editReportWithAttachmentDoc._id); - await reportsPage.editReport(); + await commonPage.accessEditOption(); await commonEnketoPage.setInputValue('Enter text', 'initial text updated'); await genericForm.submitForm(); @@ -59,7 +59,7 @@ describe('Edit report with attachment', () => { expect(editedReport.fields).excludingEvery('meta').to.deep.equal({ intro: 'initial text updated' }); await reportsPage.openReport(editReportWithAttachmentDoc._id); - await reportsPage.editReport(); + await commonPage.accessEditOption(); await commonEnketoPage.setInputValue('Enter text', 'initial text updated twice'); await genericForm.submitForm(); diff --git a/tests/e2e/default/enketo/phone-widget.wdio-spec.js b/tests/e2e/default/enketo/phone-widget.wdio-spec.js index c7bbdba53fd..0c5056d8af1 100644 --- a/tests/e2e/default/enketo/phone-widget.wdio-spec.js +++ b/tests/e2e/default/enketo/phone-widget.wdio-spec.js @@ -3,7 +3,6 @@ const reportsPage = require('@page-objects/default/reports/reports.wdio.page'); const utils = require('@utils'); const loginPage = require('@page-objects/default/login/login.wdio.page'); const genericForm = require('@page-objects/default/enketo/generic-form.wdio.page'); -const contactsPage = require('@page-objects/default/contacts/contacts.wdio.page'); const commonEnketoPage = require('@page-objects/default/enketo/common-enketo.wdio.page'); const personFactory = require('@factories/cht/contacts/person'); const { expect } = require('chai'); @@ -57,7 +56,7 @@ describe('Phone widget', () => { it('can use duplicate phone number when editing contact with same number', async () => { await commonPage.goToPeople(person1._id); - await contactsPage.openEditContactForm(); + await commonPage.accessEditOption(); await (await genericForm.nextPage()); // Try setting phone to number of the other person diff --git a/tests/e2e/default/enketo/pregnancy-complete-a-delivery.wdio-spec.js b/tests/e2e/default/enketo/pregnancy-complete-a-delivery.wdio-spec.js index f09bb6a4fbe..b3884a729ff 100644 --- a/tests/e2e/default/enketo/pregnancy-complete-a-delivery.wdio-spec.js +++ b/tests/e2e/default/enketo/pregnancy-complete-a-delivery.wdio-spec.js @@ -213,7 +213,7 @@ describe('Contact Delivery Form', () => { expect(_.uniq(aliveBabyUUIds).length).to.deep.equal(noOfAliveBabies); await reportsPage.openReport(reportId); - await reportsPage.editReport(); + await commonPage.accessEditOption(); await genericForm.nextPage(); await genericForm.nextPage(); await genericForm.nextPage(); @@ -321,7 +321,7 @@ describe('Contact Delivery Form', () => { // edit one field await reportsPage.openReport(reportId); - await reportsPage.editReport(); + await commonPage.accessEditOption(); await genericForm.nextPage(); await genericForm.nextPage(); await commonEnketoPage.selectRadioButton('How did she deliver?', 'Cesarean'); @@ -392,7 +392,7 @@ describe('Contact Delivery Form', () => { expect(initialReport._attachments).to.equal(undefined); await browser.refresh(); - await reportsPage.editReport(); + await commonPage.accessEditOption(); await genericForm.nextPage(); await dangerSignPage.selectAllDangerSignsDelivery(); await genericForm.nextPage(); diff --git a/tests/e2e/default/enketo/pregnancy-danger-sign-follow-up.wdio-spec.js b/tests/e2e/default/enketo/pregnancy-danger-sign-follow-up.wdio-spec.js index 8009c06c66e..bc85774a410 100644 --- a/tests/e2e/default/enketo/pregnancy-danger-sign-follow-up.wdio-spec.js +++ b/tests/e2e/default/enketo/pregnancy-danger-sign-follow-up.wdio-spec.js @@ -44,7 +44,7 @@ describe('Pregnancy danger sign follow-up form', () => { expect(initialReport._attachments).to.equal(undefined); await reportsPage.openReport(reportId); - await reportsPage.editReport(); + await commonPage.accessEditOption(); await genericForm.nextPage(); await genericForm.submitForm(); @@ -63,7 +63,7 @@ describe('Pregnancy danger sign follow-up form', () => { expect(initialReport._attachments).to.equal(undefined); await reportsPage.openReport(reportId); - await reportsPage.editReport(); + await commonPage.accessEditOption(); await fillPregnancyDangerSignFollowUpForm('No', 'Yes'); await dangerSignPage.selectAllDangerSignsPregnancy(); await genericForm.submitForm(); diff --git a/tests/e2e/default/enketo/submit-photo-upload-form.wdio-spec.js b/tests/e2e/default/enketo/submit-photo-upload-form.wdio-spec.js index 548aacee22d..5b3a83909f9 100644 --- a/tests/e2e/default/enketo/submit-photo-upload-form.wdio-spec.js +++ b/tests/e2e/default/enketo/submit-photo-upload-form.wdio-spec.js @@ -31,7 +31,7 @@ describe('Submit Photo Upload form', () => { expect(attachmentNames[0]).to.match(/^user-file-photo-for-upload-form-\d\d?_\d\d?_\d\d?\.png$/); await reportsPage.openReport(reportId); - await reportsPage.editReport(); + await commonPage.accessEditOption(); await (enketoWidgetsPage.imagePreview('photo-upload')).waitForDisplayed(); await genericForm.submitForm(); @@ -50,7 +50,7 @@ describe('Submit Photo Upload form', () => { expect(attachmentNames[0]).to.match(/^user-file-photo-for-upload-form-\d\d?_\d\d?_\d\d?\.png$/); await reportsPage.openReport(reportId); - await reportsPage.editReport(); + await commonPage.accessEditOption(); await (enketoWidgetsPage.imagePreview('photo-upload')).waitForDisplayed(); await enketoWidgetsPage.selectImage('photo-upload', path.join(__dirname, '../../../../webapp/src/img/layers.png')); await (enketoWidgetsPage.imagePreview('photo-upload')).waitForDisplayed(); diff --git a/tests/e2e/default/enketo/submit-z-score-form.wdio-spec.js b/tests/e2e/default/enketo/submit-z-score-form.wdio-spec.js index 44addd0b249..83d9c925fb9 100644 --- a/tests/e2e/default/enketo/submit-z-score-form.wdio-spec.js +++ b/tests/e2e/default/enketo/submit-z-score-form.wdio-spec.js @@ -119,7 +119,7 @@ describe('Submit Z-Score form', () => { const reportId = await reportsPage.getCurrentReportId(); const initialReport = await utils.getDoc(reportId); - await reportsPage.editReport(); + await commonPage.accessEditOption(); await genericForm.submitForm(); const updatedReport = await utils.getDoc(reportId); diff --git a/tests/e2e/default/logging/logging.wdio-spec.js b/tests/e2e/default/logging/logging.wdio-spec.js index 6c0374200cf..e4acdae730f 100644 --- a/tests/e2e/default/logging/logging.wdio-spec.js +++ b/tests/e2e/default/logging/logging.wdio-spec.js @@ -10,7 +10,7 @@ describe('audit log', () => { it('should mask password on login', async () => { const collectAuditLogs = await utils.collectHaproxyLogs(/POST,\/_session/); - await loginPage.login({ auth, resetPassword: false }); + await loginPage.login({ username: auth.username, password: auth.password, resetPassword: false }); const auditLogs = (await collectAuditLogs()).filter(log => log.length); expect(auditLogs.length).to.equal(1); expect(auditLogs[0]).to.contain(`{"name":"${constants.USERNAME}","password":"***"}`); diff --git a/tests/e2e/default/login/login-logout.wdio-spec.js b/tests/e2e/default/login/login-logout.wdio-spec.js index 1472148167f..c02977c9a51 100644 --- a/tests/e2e/default/login/login-logout.wdio-spec.js +++ b/tests/e2e/default/login/login-logout.wdio-spec.js @@ -72,14 +72,14 @@ describe('Login page functionality tests', () => { }); it('should log in using username and password fields', async () => { - await loginPage.login(auth); - await (await commonPage.analyticsTab()).waitForDisplayed(); - await (await commonPage.messagesTab()).waitForDisplayed(); + await loginPage.login({ username: auth.username, password: auth.password, resetPassword: false }); + await (await commonPage.tabsSelector.analyticsTab()).waitForDisplayed(); + await (await commonPage.tabsSelector.messagesTab()).waitForDisplayed(); }); it('should set correct cookies', async () => { - await loginPage.login(auth); - await (await commonPage.analyticsTab()).waitForDisplayed(); + await loginPage.login({ username: auth.username, password: auth.password, resetPassword: false }); + await (await commonPage.tabsSelector.analyticsTab()).waitForDisplayed(); const cookies = await browser.getCookies(); expect(cookies.length).to.equal(3); @@ -117,8 +117,8 @@ describe('Login page functionality tests', () => { it('should display the "session expired" modal and redirect to login page', async () => { // Login and ensure it's redirected to webapp - await loginPage.login(auth); - await (await commonPage.messagesTab()).waitForDisplayed(); + await loginPage.login({ username: auth.username, password: auth.password, resetPassword: false }); + await (await commonPage.tabsSelector.messagesTab()).waitForDisplayed(); // Delete cookies and trigger a request to the server await browser.deleteCookies('AuthSession'); await commonPage.goToReports(); @@ -170,7 +170,7 @@ describe('Login page functionality tests', () => { expect(revealedPassword.value).to.equal('pass-456'); await loginPage.login({ username: auth.username, password: auth.password, resetPassword: false }); - await (await commonPage.messagesTab()).waitForDisplayed(); + await (await commonPage.tabsSelector.messagesTab()).waitForDisplayed(); }); }); @@ -267,7 +267,7 @@ describe('Login page functionality tests', () => { await loginPage.passwordReset(user.password, NEW_PASSWORD, NEW_PASSWORD); await (await loginPage.updatePasswordButton()).click(); await commonPage.waitForPageLoaded(); - await (await commonPage.messagesTab()).waitForDisplayed(); + await (await commonPage.tabsSelector.messagesTab()).waitForDisplayed(); }); }); }); diff --git a/tests/e2e/default/more-options-menu/offline-user/all-permissions.wdio-spec.js b/tests/e2e/default/more-options-menu/offline-user/all-permissions.wdio-spec.js index 79519bfb9c4..cf843f1306c 100644 --- a/tests/e2e/default/more-options-menu/offline-user/all-permissions.wdio-spec.js +++ b/tests/e2e/default/more-options-menu/offline-user/all-permissions.wdio-spec.js @@ -63,7 +63,7 @@ describe('More Options Menu - Offline User', () => { it('should hide the kebab menu.', async () => { await commonPage.goToMessages(); await sms.sendSms('testing', contact.phone); - expect(await (await commonPage.moreOptionsMenu()).isExisting()).to.be.false; + expect(await commonPage.isMoreOptionsMenuPresent()).to.be.false; }); }); @@ -72,27 +72,27 @@ describe('More Options Menu - Offline User', () => { 'disable the \'delete\' option when no contact is opened', async () => { await commonPage.goToPeople(); await commonPage.openMoreOptionsMenu(); - expect(await commonPage.isMenuOptionVisible('export', 'contacts')).to.be.false; - expect(await commonPage.isMenuOptionVisible('edit', 'contacts')).to.be.false; - expect(await commonPage.isMenuOptionEnabled('delete', 'contacts')).to.be.false; + expect(await commonPage.isMenuOptionVisible('export')).to.be.false; + expect(await commonPage.isMenuOptionVisible('edit')).to.be.false; + expect(await commonPage.isMenuOptionEnabled('delete')).to.be.false; }); it('should hide the \'export\' option and ' + 'enable the \'edit\' and \'delete\' options when a contact is opened', async () => { await commonPage.goToPeople(patient._id); await commonPage.openMoreOptionsMenu(); - expect(await commonPage.isMenuOptionVisible('export', 'contacts')).to.be.false; - expect(await commonPage.isMenuOptionEnabled('edit', 'contacts')).to.be.true; - expect(await commonPage.isMenuOptionEnabled('delete', 'contacts')).to.be.true; + expect(await commonPage.isMenuOptionVisible('export')).to.be.false; + expect(await commonPage.isMenuOptionEnabled('edit')).to.be.true; + expect(await commonPage.isMenuOptionEnabled('delete')).to.be.true; }); it('should hide the \'export\' and \'edit\' options and ' + 'disable the \'delete\' option when the offline user\'s place is selected', async () => { await commonPage.goToPeople(offlineUser.place); await commonPage.openMoreOptionsMenu(); - expect(await commonPage.isMenuOptionVisible('export', 'contacts')).to.be.false; - expect(await commonPage.isMenuOptionVisible('edit', 'contacts')).to.be.false; - expect(await commonPage.isMenuOptionEnabled('delete', 'contacts')).to.be.false; + expect(await commonPage.isMenuOptionVisible('export')).to.be.false; + expect(await commonPage.isMenuOptionVisible('edit')).to.be.false; + expect(await commonPage.isMenuOptionEnabled('delete')).to.be.false; }); }); @@ -100,24 +100,24 @@ describe('More Options Menu - Offline User', () => { it('should hide the \'export\' and \'edit\' options and ' + 'enable the \'delete\' and \'review\' options when the sms report is opened', async () => { await commonPage.goToReports(); - expect(await (await commonPage.moreOptionsMenu()).isExisting()).to.be.false; + expect(await commonPage.isMoreOptionsMenuPresent()).to.be.false; await reportPage.goToReportById(smsReportId); await commonPage.openMoreOptionsMenu(); - expect(await commonPage.isMenuOptionVisible('export', 'reports')).to.be.false; - expect(await commonPage.isMenuOptionVisible('edit', 'reports')).to.be.false; - expect(await commonPage.isMenuOptionEnabled('delete', 'reports')).to.be.true; - expect(await commonPage.isMenuOptionEnabled('review', 'report')).to.be.true; + expect(await commonPage.isMenuOptionVisible('export')).to.be.false; + expect(await commonPage.isMenuOptionVisible('edit')).to.be.false; + expect(await commonPage.isMenuOptionEnabled('delete')).to.be.true; + expect(await commonPage.isMenuOptionEnabled('review')).to.be.true; }); it('should hide the \'export\' option and ' + 'enable the \'edit\', \'delete\' and \'review\' options when the xml report is opened', async () => { await reportPage.goToReportById(xmlReportId); await commonPage.openMoreOptionsMenu(); - expect(await commonPage.isMenuOptionVisible('export', 'reports')).to.be.false; - expect(await commonPage.isMenuOptionEnabled('edit', 'reports')).to.be.true; - expect(await commonPage.isMenuOptionEnabled('delete', 'reports')).to.be.true; - expect(await commonPage.isMenuOptionEnabled('review', 'report')).to.be.true; + expect(await commonPage.isMenuOptionVisible('export')).to.be.false; + expect(await commonPage.isMenuOptionEnabled('edit')).to.be.true; + expect(await commonPage.isMenuOptionEnabled('delete')).to.be.true; + expect(await commonPage.isMenuOptionEnabled('review')).to.be.true; }); }); }); @@ -136,20 +136,20 @@ describe('More Options Menu - Offline User', () => { it('should hide the kebab menu in Messages, People and Reports tabs', async () => { await commonPage.goToMessages(); await sms.sendSms('testing', contact.phone); - expect(await (await commonPage.moreOptionsMenu()).isExisting()).to.be.false; + expect(await commonPage.isMoreOptionsMenuPresent()).to.be.false; await commonPage.goToPeople(); - expect(await (await commonPage.moreOptionsMenu()).isExisting()).to.be.false; + expect(await commonPage.isMoreOptionsMenuPresent()).to.be.false; await contactPage.selectLHSRowByText(contact.name); - expect(await (await commonPage.moreOptionsMenu()).isExisting()).to.be.false; + expect(await commonPage.isMoreOptionsMenuPresent()).to.be.false; await commonPage.goToReports(); - expect(await (await commonPage.moreOptionsMenu()).isExisting()).to.be.false; + expect(await commonPage.isMoreOptionsMenuPresent()).to.be.false; await reportPage.goToReportById(smsReportId); - expect(await (await commonPage.moreOptionsMenu()).isExisting()).to.be.false; + expect(await commonPage.isMoreOptionsMenuPresent()).to.be.false; await reportPage.goToReportById(xmlReportId); - expect(await (await commonPage.moreOptionsMenu()).isExisting()).to.be.false; + expect(await commonPage.isMoreOptionsMenuPresent()).to.be.false; }); }); }); diff --git a/tests/e2e/default/more-options-menu/offline-user/delete-permission-disabled.wdio-spec.js b/tests/e2e/default/more-options-menu/offline-user/delete-permission-disabled.wdio-spec.js index 445b55363bf..0cffc5de941 100644 --- a/tests/e2e/default/more-options-menu/offline-user/delete-permission-disabled.wdio-spec.js +++ b/tests/e2e/default/more-options-menu/offline-user/delete-permission-disabled.wdio-spec.js @@ -63,26 +63,26 @@ describe('More Options Menu - Offline User - Delete permissions disabled', () => await commonPage.goToPeople(contact._id); await commonPage.closeReloadModal(); await commonPage.openMoreOptionsMenu(); - expect(await commonPage.isMenuOptionEnabled('edit', 'contacts')).to.be.true; - expect(await commonPage.isMenuOptionVisible('export', 'contacts')).to.be.false; - expect(await commonPage.isMenuOptionVisible('delete', 'contacts')).to.be.false; + expect(await commonPage.isMenuOptionEnabled('edit')).to.be.true; + expect(await commonPage.isMenuOptionVisible('export')).to.be.false; + expect(await commonPage.isMenuOptionVisible('delete')).to.be.false; }); }); describe('Report tab', () => { it('should hide the kebab menu when the sms report is opened', async () => { await reportPage.goToReportById(smsReportId); - expect(await (await commonPage.moreOptionsMenu()).isExisting()).to.be.false; + expect(await commonPage.isMoreOptionsMenuPresent()).to.be.false; }); it('should enable the \'edit\' and \'review\' option and ' + 'hide the \'export\' and \'delete\' options when the xml report is opened', async () => { await reportPage.goToReportById(xmlReportId); await commonPage.openMoreOptionsMenu(); - expect(await commonPage.isMenuOptionEnabled('edit', 'reports')).to.be.true; - expect(await commonPage.isMenuOptionEnabled('review', 'report')).to.be.true; - expect(await commonPage.isMenuOptionVisible('export', 'reports')).to.be.false; - expect(await commonPage.isMenuOptionVisible('delete', 'reports')).to.be.false; + expect(await commonPage.isMenuOptionEnabled('edit')).to.be.true; + expect(await commonPage.isMenuOptionEnabled('review')).to.be.true; + expect(await commonPage.isMenuOptionVisible('export')).to.be.false; + expect(await commonPage.isMenuOptionVisible('delete')).to.be.false; }); }); }); diff --git a/tests/e2e/default/more-options-menu/offline-user/edit-permission-disabled.wdio-spec.js b/tests/e2e/default/more-options-menu/offline-user/edit-permission-disabled.wdio-spec.js index 9b4716e27f8..5ce3ef9bdb8 100644 --- a/tests/e2e/default/more-options-menu/offline-user/edit-permission-disabled.wdio-spec.js +++ b/tests/e2e/default/more-options-menu/offline-user/edit-permission-disabled.wdio-spec.js @@ -62,19 +62,19 @@ describe('More Options Menu - Offline User - Edit permissions disabled', () => { it('should hide the kebab menu.', async () => { await commonPage.goToPeople(patient._id); await commonPage.closeReloadModal(); - expect(await (await commonPage.moreOptionsMenu()).isExisting()).to.be.false; + expect(await commonPage.isMoreOptionsMenuPresent()).to.be.false; }); }); describe('Report tab', () => { it('should hide the kebab menu when the sms report is opened.', async () => { await reportPage.goToReportById(smsReportId); - expect(await (await commonPage.moreOptionsMenu()).isExisting()).to.be.false; + expect(await commonPage.isMoreOptionsMenuPresent()).to.be.false; }); it('should hide the kebab menu when the xml report is opened.', async () => { await reportPage.goToReportById(xmlReportId); - expect(await (await commonPage.moreOptionsMenu()).isExisting()).to.be.false; + expect(await commonPage.isMoreOptionsMenuPresent()).to.be.false; }); }); }); diff --git a/tests/e2e/default/more-options-menu/online-user/permissions-disabled.wdio-spec.js b/tests/e2e/default/more-options-menu/online-user/permissions-disabled.wdio-spec.js index d950f98be94..7461ce309fa 100644 --- a/tests/e2e/default/more-options-menu/online-user/permissions-disabled.wdio-spec.js +++ b/tests/e2e/default/more-options-menu/online-user/permissions-disabled.wdio-spec.js @@ -58,28 +58,28 @@ describe('More Options Menu - Online User - Permissions disabled', () => { 'enable the \'edit\' and \'delete\' options when a contact is opened', async () => { await commonPage.goToPeople(contact._id); await commonPage.openMoreOptionsMenu(); - expect(await commonPage.isMenuOptionVisible('export', 'contacts')).to.be.false; - expect(await commonPage.isMenuOptionEnabled('edit', 'contacts')).to.be.true; - expect(await commonPage.isMenuOptionEnabled('delete', 'contacts')).to.be.true; + expect(await commonPage.isMenuOptionVisible('export')).to.be.false; + expect(await commonPage.isMenuOptionEnabled('edit')).to.be.true; + expect(await commonPage.isMenuOptionEnabled('delete')).to.be.true; }); it('should hide the \'export\' option and ' + 'enable the \'edit\', \'delete\' and \'review\' options when a report is opened', async () => { await commonPage.goToReports(); - expect(await (await commonPage.moreOptionsMenu()).isExisting()).to.be.false; + expect(await commonPage.isMoreOptionsMenuPresent()).to.be.false; (await reportPage.leftPanelSelectors.firstReport()).click(); await commonPage.openMoreOptionsMenu(); - expect(await commonPage.isMenuOptionVisible('export', 'reports')).to.be.false; - expect(await commonPage.isMenuOptionEnabled('edit', 'reports')).to.be.true; - expect(await commonPage.isMenuOptionEnabled('delete', 'reports')).to.be.true; - expect(await commonPage.isMenuOptionEnabled('review', 'report')).to.be.true; + expect(await commonPage.isMenuOptionVisible('export')).to.be.false; + expect(await commonPage.isMenuOptionEnabled('edit')).to.be.true; + expect(await commonPage.isMenuOptionEnabled('delete')).to.be.true; + expect(await commonPage.isMenuOptionEnabled('review')).to.be.true; }); it('should hide the kebab menu on the Message tab', async () => { await commonPage.goToMessages(); await commonPage.waitForLoaderToDisappear(); expect(await commonPage.isMessagesListPresent()).to.be.true; - expect(await (await commonPage.moreOptionsMenu()).isExisting()).to.be.false; + expect(await commonPage.isMoreOptionsMenuPresent()).to.be.false; }); }); @@ -95,9 +95,9 @@ describe('More Options Menu - Online User - Permissions disabled', () => { 'enable the \'edit\' and \'export\' options when a contact is opened', async () => { await commonPage.goToPeople(contact._id); await commonPage.openMoreOptionsMenu(); - expect(await commonPage.isMenuOptionVisible('delete', 'contacts')).to.be.false; - expect(await commonPage.isMenuOptionEnabled('edit', 'contacts')).to.be.true; - expect(await commonPage.isMenuOptionEnabled('export', 'contacts')).to.be.true; + expect(await commonPage.isMenuOptionVisible('delete')).to.be.false; + expect(await commonPage.isMenuOptionEnabled('edit')).to.be.true; + expect(await commonPage.isMenuOptionEnabled('export')).to.be.true; }); it('should hide the \'delete\' option and ' + @@ -105,10 +105,10 @@ describe('More Options Menu - Online User - Permissions disabled', () => { await commonPage.goToReports(); (await reportPage.leftPanelSelectors.firstReport()).click(); await commonPage.openMoreOptionsMenu(); - expect(await commonPage.isMenuOptionVisible('delete', 'reports')).to.be.false; - expect(await commonPage.isMenuOptionEnabled('export', 'reports')).to.be.true; - expect(await commonPage.isMenuOptionEnabled('edit', 'reports')).to.be.true; - expect(await commonPage.isMenuOptionEnabled('review', 'report')).to.be.true; + expect(await commonPage.isMenuOptionVisible('delete')).to.be.false; + expect(await commonPage.isMenuOptionEnabled('export')).to.be.true; + expect(await commonPage.isMenuOptionEnabled('edit')).to.be.true; + expect(await commonPage.isMenuOptionEnabled('review')).to.be.true; }); }); @@ -124,9 +124,9 @@ describe('More Options Menu - Online User - Permissions disabled', () => { 'enable the \'export\' option when a contact is opened', async () => { await commonPage.goToPeople(contact._id); await commonPage.openMoreOptionsMenu(); - expect(await commonPage.isMenuOptionVisible('edit', 'contacts')).to.be.false; - expect(await commonPage.isMenuOptionVisible('delete', 'contacts')).to.be.false; - expect(await commonPage.isMenuOptionEnabled('export', 'contacts')).to.be.true; + expect(await commonPage.isMenuOptionVisible('edit')).to.be.false; + expect(await commonPage.isMenuOptionVisible('delete')).to.be.false; + expect(await commonPage.isMenuOptionEnabled('export')).to.be.true; }); it('should hide the \'edit\', \'delete\' and \'review\' options and ' + @@ -134,10 +134,10 @@ describe('More Options Menu - Online User - Permissions disabled', () => { await commonPage.goToReports(); (await reportPage.leftPanelSelectors.firstReport()).click(); await commonPage.openMoreOptionsMenu(); - expect(await commonPage.isMenuOptionVisible('edit', 'reports')).to.be.false; - expect(await commonPage.isMenuOptionVisible('delete', 'reports')).to.be.false; - expect(await commonPage.isMenuOptionVisible('review', 'report')).to.be.false; - expect(await commonPage.isMenuOptionEnabled('export', 'reports')).to.be.true; + expect(await commonPage.isMenuOptionVisible('edit')).to.be.false; + expect(await commonPage.isMenuOptionVisible('delete')).to.be.false; + expect(await commonPage.isMenuOptionVisible('review')).to.be.false; + expect(await commonPage.isMenuOptionEnabled('export')).to.be.true; }); }); }); diff --git a/tests/e2e/default/more-options-menu/online-user/permissions-enabled.wdio-spec.js b/tests/e2e/default/more-options-menu/online-user/permissions-enabled.wdio-spec.js index 3655eb80ece..bc2c4c23b9a 100644 --- a/tests/e2e/default/more-options-menu/online-user/permissions-enabled.wdio-spec.js +++ b/tests/e2e/default/more-options-menu/online-user/permissions-enabled.wdio-spec.js @@ -25,23 +25,23 @@ describe('More Options Menu - Online User - Permissions enabled', () => { async () => { await commonPage.goToMessages(); await commonPage.openMoreOptionsMenu(); - expect(await commonPage.isMenuOptionEnabled('export', 'messages')).to.be.false; + expect(await commonPage.isMenuOptionEnabled('export')).to.be.false; }); it('should disable the \'export\' option and hide the \'edit\' and \'delete\' options in Contact tab', async () => { await commonPage.goToPeople(); await commonPage.openMoreOptionsMenu(); - expect(await commonPage.isMenuOptionEnabled('export', 'contacts')).to.be.false; - expect(await commonPage.isMenuOptionVisible('edit', 'contacts')).to.be.false; - expect(await commonPage.isMenuOptionVisible('delete', 'contacts')).to.be.false; + expect(await commonPage.isMenuOptionEnabled('export')).to.be.false; + expect(await commonPage.isMenuOptionVisible('edit')).to.be.false; + expect(await commonPage.isMenuOptionVisible('delete')).to.be.false; }); it('should disable the \'export\' option and hide the \'edit\' and \'delete\' options in Report tab', async () => { await commonPage.goToReports(); await commonPage.openMoreOptionsMenu(); - expect(await commonPage.isMenuOptionEnabled('export', 'reports')).to.be.false; - expect(await commonPage.isMenuOptionVisible('edit', 'reports')).to.be.false; - expect(await commonPage.isMenuOptionVisible('delete', 'reports')).to.be.false; + expect(await commonPage.isMenuOptionEnabled('export')).to.be.false; + expect(await commonPage.isMenuOptionVisible('edit')).to.be.false; + expect(await commonPage.isMenuOptionVisible('delete')).to.be.false; }); }); @@ -103,7 +103,7 @@ describe('More Options Menu - Online User - Permissions enabled', () => { await commonPage.waitForLoaderToDisappear(); await commonPage.waitForPageLoaded(); await commonPage.openMoreOptionsMenu(); - expect(await commonPage.isMenuOptionEnabled('export', 'messages')).to.be.true; + expect(await commonPage.isMenuOptionEnabled('export')).to.be.true; }); it('should enable the \'export\', \'review\' and \'delete\' options and hide the \'edit\' option in Report tab ' + @@ -111,10 +111,10 @@ describe('More Options Menu - Online User - Permissions enabled', () => { await reportPage.goToReportById(smsReportId); await (await reportPage.rightPanelSelectors.reportBodyDetails()).waitForDisplayed(); await commonPage.openMoreOptionsMenu(); - expect(await commonPage.isMenuOptionEnabled('export', 'reports')).to.be.true; - expect(await commonPage.isMenuOptionEnabled('review', 'report')).to.be.true; - expect(await commonPage.isMenuOptionEnabled('delete', 'reports')).to.be.true; - expect(await commonPage.isMenuOptionVisible('edit', 'reports')).to.be.false; + expect(await commonPage.isMenuOptionEnabled('export')).to.be.true; + expect(await commonPage.isMenuOptionEnabled('review')).to.be.true; + expect(await commonPage.isMenuOptionEnabled('delete')).to.be.true; + expect(await commonPage.isMenuOptionVisible('edit')).to.be.false; }); it('should enable the \'export\', \'review\', \'edit\' and \'delete\' options in Report tab ' + @@ -122,19 +122,19 @@ describe('More Options Menu - Online User - Permissions enabled', () => { await reportPage.goToReportById(xmlReportId); await reportPage.rightPanelSelectors.reportBodyDetails().waitForDisplayed(); await commonPage.openMoreOptionsMenu(); - expect(await commonPage.isMenuOptionEnabled('export', 'reports')).to.be.true; - expect(await commonPage.isMenuOptionEnabled('review', 'report')).to.be.true; - expect(await commonPage.isMenuOptionEnabled('edit', 'reports')).to.be.true; - expect(await commonPage.isMenuOptionEnabled('delete', 'reports')).to.be.true; + expect(await commonPage.isMenuOptionEnabled('export')).to.be.true; + expect(await commonPage.isMenuOptionEnabled('review')).to.be.true; + expect(await commonPage.isMenuOptionEnabled('edit')).to.be.true; + expect(await commonPage.isMenuOptionEnabled('delete')).to.be.true; }); it('should enable the \'export\', \'edit\' and \'delete\' options in Contact tab ' + 'when a contact is opened.', async () => { await commonPage.goToPeople(contact._id); await commonPage.openMoreOptionsMenu(); - expect(await commonPage.isMenuOptionEnabled('export', 'contacts')).to.be.true; - expect(await commonPage.isMenuOptionEnabled('edit', 'contacts')).to.be.true; - expect(await commonPage.isMenuOptionEnabled('delete', 'contacts')).to.be.true; + expect(await commonPage.isMenuOptionEnabled('export')).to.be.true; + expect(await commonPage.isMenuOptionEnabled('edit')).to.be.true; + expect(await commonPage.isMenuOptionEnabled('delete')).to.be.true; }); it('should enable the \'export\' option and hide the \'edit\' and \'delete\' options in Contact tab ' + @@ -144,9 +144,9 @@ describe('More Options Menu - Online User - Permissions enabled', () => { await commonPage.waitForPageLoaded(); await commonPage.goToPeople(); await commonPage.openMoreOptionsMenu(); - expect(await commonPage.isMenuOptionEnabled('export', 'contacts')).to.be.true; - expect(await commonPage.isMenuOptionVisible('edit', 'contacts')).to.be.false; - expect(await commonPage.isMenuOptionVisible('delete', 'contacts')).to.be.false; + expect(await commonPage.isMenuOptionEnabled('export')).to.be.true; + expect(await commonPage.isMenuOptionVisible('edit')).to.be.false; + expect(await commonPage.isMenuOptionVisible('delete')).to.be.false; }); }); }); diff --git a/tests/e2e/default/privacy-policy/privacy-policy.wdio-spec.js b/tests/e2e/default/privacy-policy/privacy-policy.wdio-spec.js index e3a5de48fde..0c0b42c9153 100644 --- a/tests/e2e/default/privacy-policy/privacy-policy.wdio-spec.js +++ b/tests/e2e/default/privacy-policy/privacy-policy.wdio-spec.js @@ -1,4 +1,4 @@ -const commonElements = require('@page-objects/default/common/common.wdio.page.js'); +const commonPage = require('@page-objects/default/common/common.wdio.page.js'); const utils = require('@utils'); const loginPage = require('@page-objects/default/login/login.wdio.page'); const privacyPage = require('@page-objects/default/privacy-policy/privacy-policy.wdio.page'); @@ -11,6 +11,7 @@ describe('Privacy policy', () => { const englishTexts = privacyPolicyFactory.english; const frenchTexts = privacyPolicyFactory.french; const spanishTexts = privacyPolicyFactory.spanish; + const newPassword = loginPage.NEW_PASSWORD; const users = [ userFactory.build({ username: 'offlineuser', isOffline: true }), @@ -36,12 +37,12 @@ describe('Privacy policy', () => { it('should show the correct privacy policy on login', async () => { await privacyPage.waitAndAcceptPolicy(await privacyPage.privacyWrapper(), englishTexts, user.isOffline); - expect(await (await commonElements.messagesTab()).isDisplayed()).to.be.true; + expect(await (await commonPage.tabsSelector.messagesTab()).isDisplayed()).to.be.true; }); it('should not show on refresh', async () => { await browser.url('/'); - await (await commonElements.messagesTab()).waitForDisplayed(); + await (await commonPage.tabsSelector.messagesTab()).waitForDisplayed(); expect(await (await privacyPage.privacyWrapper()).isDisplayed()).to.not.be.true; }); @@ -53,8 +54,8 @@ describe('Privacy policy', () => { it('should not show on subsequent login', async () => { await browser.reloadSession(); await browser.url('/'); - await loginPage.login({ username: user.username, password: user.password, resetPassword: false }); - await (await commonElements.messagesTab()).waitForDisplayed(); + await loginPage.login({ username: user.username, password: newPassword, resetPassword: false }); + await (await commonPage.tabsSelector.messagesTab()).waitForDisplayed(); expect(await (await privacyPage.privacyWrapper()).isDisplayed()).to.not.be.true; }); @@ -63,20 +64,20 @@ describe('Privacy policy', () => { await browser.url('/'); await loginPage.login({ username: user.username, - password: user.password, + password: newPassword, locale: 'fr', privacyPolicy: true, resetPassword: false }); await privacyPage.waitAndAcceptPolicy(await privacyPage.privacyWrapper(), frenchTexts); - expect(await (await commonElements.messagesTab()).isDisplayed()).to.be.true; + expect(await (await commonPage.tabsSelector.messagesTab()).isDisplayed()).to.be.true; }); it('should show if the user changes their language', async () => { await browser.setCookies({ name: 'locale', value: 'es' }); await browser.refresh(); await privacyPage.waitAndAcceptPolicy(await privacyPage.privacyWrapper(), spanishTexts); - expect(await (await commonElements.messagesTab()).isDisplayed()).to.be.true; + expect(await (await commonPage.tabsSelector.messagesTab()).isDisplayed()).to.be.true; }); it('should show if the user policy changes', async () => { @@ -100,13 +101,13 @@ describe('Privacy policy', () => { await privacyPage.updatePrivacyPolicy(updatedPolicy); if (user.isOffline) { - await commonElements.sync(); + await commonPage.sync(); } await browser.refresh(); await privacyPage.waitAndAcceptPolicy(await privacyPage.privacyWrapper(), text); - expect(await (await commonElements.messagesTab()).isDisplayed()).to.be.true; + expect(await (await commonPage.tabsSelector.messagesTab()).isDisplayed()).to.be.true; }); }); }); @@ -139,8 +140,8 @@ describe('Privacy policy', () => { it('should not fail due to document conflict for new offline user', async () => { await privacyPage.waitForPolicy(await privacyPage.privacyWrapper(), englishTexts); await privacyPage.acceptPrivacyPolicy(); - await commonElements.sync(); - expect(await (await commonElements.messagesTab()).isDisplayed()).to.be.true; + await commonPage.sync(); + expect(await (await commonPage.tabsSelector.messagesTab()).isDisplayed()).to.be.true; passed = true; }); }); diff --git a/tests/e2e/default/reports/delete.wdio-spec.js b/tests/e2e/default/reports/delete.wdio-spec.js index 45200a37ec9..385b3eca094 100644 --- a/tests/e2e/default/reports/delete.wdio-spec.js +++ b/tests/e2e/default/reports/delete.wdio-spec.js @@ -53,7 +53,7 @@ describe('Delete Reports', () => { expect(await (await reportsPage.leftPanelSelectors.reportByUUID(savedReportIds[1])).isDisplayed()).to.be.true; await reportsPage.openReport(savedReportIds[1]); - await reportsPage.deleteReport(); + await commonElements.accessDeleteOption(); await commonElements.goToReports(); expect(await (await reportsPage.leftPanelSelectors.reportByUUID(savedReportIds[0])).isDisplayed()).to.be.true; diff --git a/tests/e2e/default/reports/export.wdio-spec.js b/tests/e2e/default/reports/export.wdio-spec.js index ca6613bbf90..0b7f2ec4afc 100644 --- a/tests/e2e/default/reports/export.wdio-spec.js +++ b/tests/e2e/default/reports/export.wdio-spec.js @@ -3,7 +3,7 @@ const userFactory = require('@factories/cht/users/users'); const placeFactory = require('@factories/cht/contacts/place'); const personFactory = require('@factories/cht/contacts/person'); const reportFactory = require('@factories/cht/reports/generic-report'); -const commonElements = require('@page-objects/default/common/common.wdio.page'); +const commonPage = require('@page-objects/default/common/common.wdio.page'); const reportsPage = require('@page-objects/default/reports/reports.wdio.page'); const loginPage = require('@page-objects/default/login/login.wdio.page'); const fileDownloadUtils = require('@utils/file-download'); @@ -35,8 +35,8 @@ describe('Export Reports', () => { (await utils.saveDocs(reports)).forEach(savedReport => savedReportIds.push(savedReport.id)); await utils.createUsers([ onlineUser ]); await loginPage.login(onlineUser); - await commonElements.waitForPageLoaded(); - await commonElements.goToReports(); + await commonPage.waitForPageLoaded(); + await commonPage.goToReports(); }); after(async () => { @@ -46,7 +46,7 @@ describe('Export Reports', () => { it('should download export file', async () => { await (await reportsPage.leftPanelSelectors.firstReport()).waitForDisplayed(); - await reportsPage.exportReports(); + await commonPage.accessExportOption(); const files = await fileDownloadUtils.waitForDownload(`reports-${today.format('YYYYMMDD')}`); expect(files).to.not.be.undefined; diff --git a/tests/e2e/default/service-worker/service-worker.wdio-spec.js b/tests/e2e/default/service-worker/service-worker.wdio-spec.js index 812f64bb782..3fe432351a0 100644 --- a/tests/e2e/default/service-worker/service-worker.wdio-spec.js +++ b/tests/e2e/default/service-worker/service-worker.wdio-spec.js @@ -73,7 +73,7 @@ describe('Service worker cache', () => { }; const isLoggedIn = async () => { - const tab = await commonPage.messagesTab(); + const tab = await commonPage.tabsSelector.messagesTab(); return await tab.isExisting(); }; @@ -219,7 +219,7 @@ describe('Service worker cache', () => { it('should load the page while offline', async () => { await browser.throttle('offline'); await browser.refresh(); - await (await commonPage.analyticsTab()).waitForDisplayed(); + await (await commonPage.tabsSelector.analyticsTab()).waitForDisplayed(); await browser.throttle('online'); }); diff --git a/tests/e2e/default/tasks/config/tasks-breadcrumbs-config.js b/tests/e2e/default/tasks/config/tasks-breadcrumbs-config.js index 2c6687693e9..d6a4a79f934 100644 --- a/tests/e2e/default/tasks/config/tasks-breadcrumbs-config.js +++ b/tests/e2e/default/tasks/config/tasks-breadcrumbs-config.js @@ -38,7 +38,7 @@ module.exports = [ ], events: [ { - id: 'person-creation-follow-up', + id: 'person-creation', start: 3, end: 7, dueDate: function (event, contact) { @@ -47,4 +47,35 @@ module.exports = [ } ] }, + + { + name: 'person_create_follow_up', + icon: 'icon-person', + title: 'person_create_follow_up', + appliesTo: 'reports', + appliesToType: ['home_visit'], + appliesIf: function () { + return true; + }, + resolvedIf: function (contact) { + return isFormArraySubmittedInWindow(contact.reports, ['home_visit'], contact.contact.reported_date); + }, + actions: [ + { + type: 'report', + form: 'home_visit' + } + ], + events: [ + { + id: 'person-creation-follow-up', + start: 3, + end: 1, + dueDate: function (event, contact) { + return contact.contact.reported_date; + } + } + ] + }, + ]; diff --git a/tests/e2e/default/tasks/due-dates.wdio-spec.js b/tests/e2e/default/tasks/due-dates.wdio-spec.js index 2faeff96317..353510ced11 100644 --- a/tests/e2e/default/tasks/due-dates.wdio-spec.js +++ b/tests/e2e/default/tasks/due-dates.wdio-spec.js @@ -28,7 +28,7 @@ describe('Task list due dates', () => { await sentinelUtils.waitForSentinel(); await loginPage.login(chw); - await (await commonPage.analyticsTab()).waitForDisplayed(); + await (await commonPage.tabsSelector.analyticsTab()).waitForDisplayed(); }); after(async () => { diff --git a/tests/e2e/default/tasks/tasks.wdio-spec.js b/tests/e2e/default/tasks/tasks.wdio-spec.js index e2a1ed6ba26..f0e770a1de0 100644 --- a/tests/e2e/default/tasks/tasks.wdio-spec.js +++ b/tests/e2e/default/tasks/tasks.wdio-spec.js @@ -92,6 +92,24 @@ describe('Tasks', () => { expect(list).to.have.length(2); }); + it('should add a task when CHW completes a task successfully, and that task creates another task', async () => { + await tasksPage.compileTasks('tasks-breadcrumbs-config.js', false); + + await commonPage.goToTasks(); + let list = await tasksPage.getTasks(); + expect(list).to.have.length(2); + let task = await tasksPage.getTaskByContactAndForm('Megan Spice', 'person_create'); + await task.click(); + await tasksPage.waitForTaskContentLoaded('Home Visit'); + const taskElement = await tasksPage.getOpenTaskElement(); + await genericForm.submitForm(); + await taskElement.waitForDisplayed(); + await commonPage.sync(true); + task = await tasksPage.getTaskByContactAndForm('Megan Spice', 'person_create_follow_up'); + list = await tasksPage.getTasks(); + expect(list).to.have.length(3); + }); + it('should load multiple pages of tasks on infinite scrolling', async () => { await tasksPage.compileTasks('tasks-multiple-config.js', true); diff --git a/tests/e2e/default/translations/incorrect-locale.wdio-spec.js b/tests/e2e/default/translations/incorrect-locale.wdio-spec.js index c107f185e7b..b930e192255 100644 --- a/tests/e2e/default/translations/incorrect-locale.wdio-spec.js +++ b/tests/e2e/default/translations/incorrect-locale.wdio-spec.js @@ -5,6 +5,7 @@ const contactElements = require('@page-objects/default/contacts/contacts.wdio.pa const loginPage = require('@page-objects/default/login/login.wdio.page'); const placeFactory = require('@factories/cht/contacts/place'); const sentinelUtils = require('@utils/sentinel'); +const commonPage = require('@page-objects/default/common/common.wdio.page'); describe('Testing Incorrect locale', () => { const LANGUAGE_CODE = 'hil'; @@ -44,8 +45,8 @@ describe('Testing Incorrect locale', () => { await userSettingsElements.setLanguage(LANGUAGE_CODE); - const text = await commonElements.getReportsButtonLabel().getText(); - expect(text).to.equal('HilReports'); + const tabsButtonLabelsNames = await commonPage.getAllButtonLabelsNames(); + expect(tabsButtonLabelsNames).to.include('HilReports'); await commonElements.goToPeople(); await commonElements.waitForPageLoaded(); diff --git a/tests/e2e/default/translations/message-format.wdio-spec.js b/tests/e2e/default/translations/message-format.wdio-spec.js index 16bcb4e170f..c04079211cd 100644 --- a/tests/e2e/default/translations/message-format.wdio-spec.js +++ b/tests/e2e/default/translations/message-format.wdio-spec.js @@ -34,14 +34,13 @@ describe('MessageFormat', () => { // wait for language to load await browser.waitUntil(async () => { - return await (await commonPage.getReportsButtonLabel()).getText() === 'Reports {{thing}}'; + return await commonPage.isElementPresent('div*=Reports {{thing}}'); }, { timeout: 2000, timeoutMsg: 'Timed out waiting for translations to update' }); - expect(await (await commonPage.getReportsButtonLabel()).getText()).to.equal('Reports {{thing}}'); - expect(await (await commonPage.getTasksButtonLabel()).getText()).to.equal('Tasks {thing'); - expect(await (await commonPage.getMessagesButtonLabel()).getText()).to.equal('Messages {thing}'); + const tabsButtonLabelsNames = await commonPage.getAllButtonLabelsNames(); + expect(tabsButtonLabelsNames).to.include.members(['Reports {{thing}}', 'Tasks {thing', 'Messages {thing}']); }); }); diff --git a/tests/e2e/default/translations/nepali-dates-and-numbers.wdio-spec.js b/tests/e2e/default/translations/nepali-dates-and-numbers.wdio-spec.js index 9c356f7096c..2f87ff9da9b 100644 --- a/tests/e2e/default/translations/nepali-dates-and-numbers.wdio-spec.js +++ b/tests/e2e/default/translations/nepali-dates-and-numbers.wdio-spec.js @@ -95,7 +95,7 @@ describe('Bikram Sambat date display', () => { await chtConfUtils.compileAndUploadAppForms(formsPath); await loginPage.cookieLogin(); - await (await commonPage.analyticsTab()).waitForDisplayed(); + await (await commonPage.tabsSelector.analyticsTab()).waitForDisplayed(); }); after(async () => { diff --git a/tests/e2e/default/translations/new-language.wdio-spec.js b/tests/e2e/default/translations/new-language.wdio-spec.js index 16ee6e53765..81d59f65999 100644 --- a/tests/e2e/default/translations/new-language.wdio-spec.js +++ b/tests/e2e/default/translations/new-language.wdio-spec.js @@ -57,7 +57,7 @@ describe('Adding new language', () => { await addTranslations(NEW_LANG_CODE, NEW_TRANSLATIONS); await commonPage.goToBase(); await userSettingsElements.setLanguage(NEW_LANG_CODE); - await browser.waitUntil(async () => await (await commonPage.analyticsTab()).getText() === 'Analytiks'); + await browser.waitUntil(async () => await (await commonPage.tabsSelector.analyticsTab()).getText() === 'Analytiks'); // Check for translations in the UI await commonPage.goToMessages(); diff --git a/tests/integration/api/server.spec.js b/tests/integration/api/server.spec.js index 16c529221c6..2b50dec116c 100644 --- a/tests/integration/api/server.spec.js +++ b/tests/integration/api/server.spec.js @@ -430,4 +430,28 @@ describe('server', () => { }); }); + + describe('api startup', () => { + it('should start up with broken forms', async () => { + const waitForLogs = await utils.waitForApiLogs(/Failed to update xform/); + + const formName = 'broken'; + const formDoc = { + _id: `form:${formName}`, + title: formName, + type: 'form', + _attachments: { + xml: { + content_type: 'application/octet-stream', + data: btoa('this is totally not an xml'), + }, + }, + }; + await utils.db.put(formDoc); // don't use utils.saveDoc because that actually waits for good forms + await waitForLogs.promise; + + await utils.stopApi(); + await utils.startApi(); + }); + }); }); diff --git a/tests/integration/haproxy/keep-alive-script/Dockerfile b/tests/integration/haproxy/keep-alive-script/Dockerfile index a3a88e64e1f..1d9a42c33eb 100644 --- a/tests/integration/haproxy/keep-alive-script/Dockerfile +++ b/tests/integration/haproxy/keep-alive-script/Dockerfile @@ -1,4 +1,4 @@ -FROM alpine:3.19 +FROM alpine:3.20 RUN apk add --update --no-cache curl diff --git a/tests/page-objects/default/about/about.wdio.page.js b/tests/page-objects/default/about/about.wdio.page.js index f2baf0a89b0..1fef86546e3 100644 --- a/tests/page-objects/default/about/about.wdio.page.js +++ b/tests/page-objects/default/about/about.wdio.page.js @@ -2,7 +2,6 @@ const userName = () => $('label=User name'); const partners = () => $('.partners'); const version = () => $('[test-id="about-version"]'); const aboutCard = () => $('mat-card-title*=About'); -const RELOAD_BUTTON = '.about.page .mat-primary'; const getPartnerImage = async (name) => { await (await partners()).waitForDisplayed(); @@ -23,5 +22,4 @@ module.exports = { getPartnerImage, getVersion, aboutCard, - RELOAD_BUTTON, }; diff --git a/tests/page-objects/default/admin/admin.wdio.page.js b/tests/page-objects/default/admin/admin.wdio.page.js index d4bb0cc8d5a..fcd8e4f30f1 100644 --- a/tests/page-objects/default/admin/admin.wdio.page.js +++ b/tests/page-objects/default/admin/admin.wdio.page.js @@ -1,4 +1,4 @@ -const utils = require('../../../utils'); +const utils = require('@utils'); const adminNavbarLogo = () => $('.navbar-header .navbar-brand'); const languagesPanel = () => $('.tab-content > #language-accordion > .panel'); diff --git a/tests/page-objects/default/analytics/analytics.wdio.page.js b/tests/page-objects/default/analytics/analytics.wdio.page.js index e9c4fd284a2..3fdf68b8e17 100644 --- a/tests/page-objects/default/analytics/analytics.wdio.page.js +++ b/tests/page-objects/default/analytics/analytics.wdio.page.js @@ -1,35 +1,21 @@ const TARGET_MET_COLOR = '#76b0b0'; - const TARGET_UNMET_COLOR = '#000000'; const goToTargets = () => browser.url('/#/analytics/targets'); - const noSelectedTarget = () => $('.empty-selection'); - const targets = () => $$('.target'); - const targetWrap = () => $('.page .targets'); - const targetTitle = (targetElement) => targetElement.$('.heading .title h2'); - const targetGoal = (targetElement) => targetElement.$('.body .count .goal'); - const targetCountNumber = (targetElement) => targetElement.$('.body .count .number'); - const targetCountNumberColor = (targetElement) => targetElement.$('.body .count .number:not(.goal-met)'); - const targetProgressNumber = (targetElement) => targetElement.$('.body .target-progress .number'); - const targetNumberPercent = (targetElement) => targetElement.$('.body .target-progress .number .value'); - const targetNumberPercentCount = (targetElement) => targetElement.$('.body .target-progress .number span:nth-child(2)'); - const targetGoalValue = (targetElement) => targetElement.$('.body .count .goal'); const EMPTY_SELECTION = '.content-pane .item-content.empty-selection'; - const emptySelectionError = () => $(`${EMPTY_SELECTION}.selection-error`); - const emptySelectionNoError = () => $(`${EMPTY_SELECTION}:not(.selection-error)`); const getTargetInfo = async (targetElement) => { diff --git a/tests/page-objects/default/common/common.wdio.page.js b/tests/page-objects/default/common/common.wdio.page.js index 938b8e20c1a..4c196d6f2f1 100644 --- a/tests/page-objects/default/common/common.wdio.page.js +++ b/tests/page-objects/default/common/common.wdio.page.js @@ -1,84 +1,170 @@ -const modalPage = require('./modal.wdio.page'); -const constants = require('@constants'); -const aboutPage = require('@page-objects/default/about/about.wdio.page'); const fs = require('fs'); +const modalPage = require('@page-objects/default/common/modal.wdio.page'); +const constants = require('@constants'); + +const ELEMENT_DISPLAY_PAUSE = 500; // 500ms + +const tabsSelector = { + getAllButtonLabels: async () => await $$('.header .tabs .button-label'), + messagesTab: () => $('#messages-tab'), + taskTab: () => $('#tasks-tab'), + analyticsTab: () => $('#analytics-tab'), +}; + +const hamburgerMenuSelectors = { + hamburgerMenu: () => $('aria/Application menu'), + closeSideBarMenu: () => $('.panel-header-close'), + sideBarMenuTitle: () => $('aria/Menu'), + appManagementButton: () => $('aria/App Management'), + syncButton: () => $('aria/Sync now'), + syncSuccess: () => $('aria/All reports synced'), + syncInProgress: () => $('mat-sidenav-content').$('*="Currently syncing"'), + aboutButton: () => $('aria/About'), + userSettingsButton: () => $('aria/User settings'), + feedbackMenuOption: () => $('aria/Report bug'), + logoutButton: () => $('aria/Log out'), +}; + +const kebabMenuSelectors = { + moreOptionsMenu: () => $('aria/Actions menu'), + edit: () => $('aria/Edit'), + delete: () => $('aria/Delete'), + export: () => $('aria/Export'), + review: () => $('aria/Review'), +}; -const hamburgerMenu = () => $('aria/Application menu'); -const closeSideBarMenu = () => $('.panel-header-close'); const FAST_ACTION_TRIGGER = '.fast-action-trigger'; -const fastActionFAB = () => $$(`${FAST_ACTION_TRIGGER} .fast-action-fab-button`); -const fastActionFlat = () => $(`${FAST_ACTION_TRIGGER} .fast-action-flat-button`); -const multipleActions = () => $(`${FAST_ACTION_TRIGGER}[test-id="multiple-actions-menu"]`); const FAST_ACTION_LIST_CONTAINER = '.fast-action-content-wrapper'; -const fastActionListContainer = () => $(FAST_ACTION_LIST_CONTAINER); -const fastActionListCloseButton = () => $(`${FAST_ACTION_LIST_CONTAINER} .panel-header .panel-header-close`); -const fastActionById = (id) => $(`${FAST_ACTION_LIST_CONTAINER} .fast-action-item[test-id="${id}"]`); -const fastActionItems = () => $$(`${FAST_ACTION_LIST_CONTAINER} .fast-action-item`); -const moreOptionsMenu = () => $('aria/Actions menu'); -const hamburgerMenuItemSelector = 'mat-sidenav-content'; -const logoutButton = () => $('aria/Log out'); -const syncButton = () => $('aria/Sync now'); -const messagesTab = () => $('#messages-tab'); -const analyticsTab = () => $('#analytics-tab'); -const taskTab = () => $('#tasks-tab'); -const getReportsButtonLabel = () => $('#reports-tab .button-label'); -const getMessagesButtonLabel = () => $('#messages-tab .button-label'); -const getTasksButtonLabel = () => $('#tasks-tab .button-label'); -const getAllButtonLabels = async () => await $$('.header .tabs .button-label'); -const loaders = () => $$('.container-fluid .loader'); -const syncSuccess = () => $('aria/All reports synced'); -const syncInProgress = () => $(hamburgerMenuItemSelector).$('*="Currently syncing"'); -const syncRequired = () => $(`${hamburgerMenuItemSelector} .sync-status .required`); -const jsonError = async () => (await $('pre')).getText(); -const REPORTS_CONTENT_SELECTOR = '#reports-content'; -const reportsFastActionFAB = () => $(`${REPORTS_CONTENT_SELECTOR} .fast-action-fab-button mat-icon`); - -//languages -const activeSnackbar = () => $('#snackbar.active'); -const inactiveSnackbar = () => $('#snackbar:not(.active)'); -const snackbar = () => $('#snackbar.active .snackbar-message'); -const snackbarMessage = async () => (await $('#snackbar.active .snackbar-message')).getText(); -const snackbarAction = () => $('#snackbar.active .snackbar-action'); - -// Mobile -const mobileTopBarTitle = () => $('mm-navigation .ellipsis-title'); - -//User settings -const USER_SETTINGS = 'aria/User settings'; -const EDIT_PROFILE = '.user .configuration.page i.fa-user'; -// Feedback or Report bug -const feedbackMenuOption = () => $('aria/Report bug'); -const FEEDBACK = '#feedback'; -//About menu -const ABOUT_MENU = 'aria/About'; -//Configuration App -const ELEMENT_DISPLAY_PAUSE = 500; // 500ms +const fabSelectors = { + fastActionFAB: () => $$(`${FAST_ACTION_TRIGGER} .fast-action-fab-button`), + fastActionFlat: () => $(`${FAST_ACTION_TRIGGER} .fast-action-flat-button`), + multipleActions: () => $(`${FAST_ACTION_TRIGGER}[test-id="multiple-actions-menu"]`), + fastActionListContainer: () => $(FAST_ACTION_LIST_CONTAINER), + fastActionListCloseButton: () => $(`${FAST_ACTION_LIST_CONTAINER} .panel-header .panel-header-close`), + fastActionById: (id) => $(`${FAST_ACTION_LIST_CONTAINER} .fast-action-item[test-id="${id}"]`), + fastActionItems: () => $$(`${FAST_ACTION_LIST_CONTAINER} .fast-action-item`), + reportsFastActionFAB: () => $('#reports-content .fast-action-fab-button mat-icon'), +}; + +const userSettingsSelectors = { + editProfileButton: () => $('.user .configuration.page i.fa-user'), +}; -const configurationAppMenuOption = () => $('aria/App Management'); -const errorLog = () => $(`error-log`); -const sideBarMenuTitle = () => $('aria/Menu'); +const getJsonErrorText = async () => await $('pre').getText(); const isHamburgerMenuOpen = async () => { return await (await $('mat-sidenav-container.mat-drawer-container-has-open')).isExisting(); }; +const openHamburgerMenu = async () => { + if (!(await isHamburgerMenuOpen())) { + await (await hamburgerMenuSelectors.hamburgerMenu()).waitForClickable(); + await (await hamburgerMenuSelectors.hamburgerMenu()).click(); + // Adding pause here as we have to wait for sidebar nav menu animation to load + await browser.pause(ELEMENT_DISPLAY_PAUSE); + } + await (await hamburgerMenuSelectors.sideBarMenuTitle()).waitForDisplayed(); +}; + +const closeHamburgerMenu = async () => { + if (await isHamburgerMenuOpen()) { + await (await hamburgerMenuSelectors.closeSideBarMenu()).waitForClickable(); + await (await hamburgerMenuSelectors.closeSideBarMenu()).click(); + } + + await (await hamburgerMenuSelectors.sideBarMenuTitle()).waitForDisplayed({ reverse: true }); +}; + const openMoreOptionsMenu = async () => { - await (await moreOptionsMenu()).waitForClickable(); - await (await moreOptionsMenu()).click(); + await (await kebabMenuSelectors.moreOptionsMenu()).waitForClickable(); + await (await kebabMenuSelectors.moreOptionsMenu()).click(); +}; + +const performMenuAction = async (actionSelector) => { + await openMoreOptionsMenu(); + const actionElement = await actionSelector(); + await actionElement.waitForClickable(); + await actionElement.click(); +}; + +const accessEditOption = async () => { + await performMenuAction(kebabMenuSelectors.edit); +}; + +const accessDeleteOption = async () => { + await performMenuAction(kebabMenuSelectors.delete); +}; + +const accessExportOption = async () => { + await performMenuAction(kebabMenuSelectors.export); +}; + +const accessReviewOption = async () => { + await performMenuAction(kebabMenuSelectors.review); }; const waitForSnackbarToClose = async () => { - if (await (await snackbar()).isExisting()) { - await (await snackbar()).waitForDisplayed({ reverse: true }); + const snackbar = await $('#snackbar.active .snackbar-message'); + if (await snackbar.isExisting()) { + await snackbar.waitForDisplayed({ reverse: true }); + } +}; + +const hideSnackbar = () => { + // snackbar appears in the bottom of the page for 5 seconds when certain actions are made + // for example when filling a form, or creating a contact and intercepts all clicks in the FAB and Flat buttons + // this action is temporary, and will be undone with a refresh + return browser.execute(() => { + // eslint-disable-next-line no-undef + window.jQuery('.snackbar-content').hide(); + }); +}; + +const getVisibleLoaders = async () => { + const visible = []; + for (const loader of await $$('.container-fluid .loader')) { + if (await loader.isDisplayedInViewport()) { + visible.push(loader); + } } + + return visible; +}; + +const waitForLoaderToDisappear = async (element) => { + const loaderSelector = '.loader'; + const loader = await (element ? element.$(loaderSelector) : $(loaderSelector)); + await loader.waitForDisplayed({ reverse: true }); +}; + +const waitForLoaders = async () => { + await browser.waitUntil(async () => { + const visibleLoaders = await getVisibleLoaders(); + return !visibleLoaders.length; + }, { timeoutMsg: 'Waiting for Loading spinners to hide timed out.' }); +}; + +const waitForAngularLoaded = async (timeout = 40000) => { + await (await hamburgerMenuSelectors.hamburgerMenu()).waitForDisplayed({ timeout }); +}; + +const waitForPageLoaded = async () => { + // if we immediately check for app loaders, we might bypass the initial page load (the bootstrap loader) + // so waiting for the main page to load. + await waitForAngularLoaded(); + // ideally we would somehow target all loaders that we expect (like LHS + RHS loaders), but not all pages + // get all loaders. + do { + await waitForLoaders(); + } while ((await getVisibleLoaders()).length > 0); }; const clickFastActionById = async (id) => { // Wait for the Angular Material's animation to complete. await browser.pause(ELEMENT_DISPLAY_PAUSE); - await (await fastActionListContainer()).waitForDisplayed(); - await (await fastActionById(id)).waitForClickable(); - await (await fastActionById(id)).click(); + await (await fabSelectors.fastActionListContainer()).waitForDisplayed(); + await (await fabSelectors.fastActionById(id)).waitForClickable(); + await (await fabSelectors.fastActionById(id)).click(); }; /** @@ -86,7 +172,7 @@ const clickFastActionById = async (id) => { * @returns {Promise} */ const findVisibleFAB = async () => { - for (const button of await fastActionFAB()) { + for (const button of await fabSelectors.fastActionFAB()) { if (await button.isDisplayed()) { return button; } @@ -97,7 +183,7 @@ const clickFastActionFAB = async ({ actionId, waitForList }) => { await closeHamburgerMenu(); const fab = await findVisibleFAB(); await fab.waitForClickable(); - waitForList = waitForList === undefined ? await (await multipleActions()).isExisting() : waitForList; + waitForList = waitForList === undefined ? await (await fabSelectors.multipleActions()).isExisting() : waitForList; await fab.click(); if (waitForList) { await clickFastActionById(actionId); @@ -111,17 +197,17 @@ const getFastActionItemsLabels = async () => { await fab.click(); await browser.pause(ELEMENT_DISPLAY_PAUSE); - await (await fastActionListContainer()).waitForDisplayed(); + await (await fabSelectors.fastActionListContainer()).waitForDisplayed(); - const items = await fastActionItems(); + const items = await fabSelectors.fastActionItems(); return await items.map(item => item.getText()); }; const clickFastActionFlat = async ({ actionId, waitForList }) => { - await (await fastActionFlat()).waitForDisplayed(); - await (await fastActionFlat()).waitForClickable(); - waitForList = waitForList === undefined ? await (await multipleActions()).isExisting() : waitForList; - await (await fastActionFlat()).click(); + await (await fabSelectors.fastActionFlat()).waitForDisplayed(); + await (await fabSelectors.fastActionFlat()).waitForClickable(); + waitForList = waitForList === undefined ? await (await fabSelectors.multipleActions()).isExisting() : waitForList; + await (await fabSelectors.fastActionFlat()).click(); if (waitForList) { await clickFastActionById(actionId); } @@ -140,90 +226,55 @@ const openFastActionReport = async (formId, rightSideAction = true) => { const getFastActionFABTextById = async (actionId) => { await clickFastActionFAB({ actionId, waitForList: false }); - await (await fastActionListContainer()).waitForDisplayed(); - return await (await fastActionById(actionId)).getText(); + await (await fabSelectors.fastActionListContainer()).waitForDisplayed(); + return await (await fabSelectors.fastActionById(actionId)).getText(); }; const getFastActionFlatText = async () => { await waitForSnackbarToClose(); - await (await fastActionFlat()).waitForDisplayed(); - return await (await fastActionFlat()).getText(); + await (await fabSelectors.fastActionFlat()).waitForDisplayed(); + return await (await fabSelectors.fastActionFlat()).getText(); }; const closeFastActionList = async () => { - await (await fastActionListContainer()).waitForDisplayed(); - await (await fastActionListCloseButton()).waitForClickable(); - await (await fastActionListCloseButton()).click(); + await (await fabSelectors.fastActionListContainer()).waitForDisplayed(); + await (await fabSelectors.fastActionListCloseButton()).waitForClickable(); + await (await fabSelectors.fastActionListCloseButton()).click(); }; const isReportActionDisplayed = async () => { return await browser.waitUntil(async () => { - const exists = await (await reportsFastActionFAB()).isExisting(); + const exists = await (await fabSelectors.reportsFastActionFAB()).isExisting(); if (exists) { - await (await reportsFastActionFAB()).waitForDisplayed(); + await (await fabSelectors.reportsFastActionFAB()).waitForDisplayed(); } return exists; }); }; -const isMessagesListPresent = () => { - return isElementByIdPresent('message-list'); -}; - -const isTasksListPresent = () => { - return isElementByIdPresent('tasks-list'); -}; - -const isReportsListPresent = () => { - return isElementByIdPresent('reports-list'); -}; - -const isPeopleListPresent = () => { - return isElementByIdPresent('contacts-list'); +const isElementPresent = async (selector) => { + return await (await $(selector)).isExisting(); }; -const isTargetMenuItemPresent = async () => { - return await (await $(`=Target`)).isExisting(); -}; +const isMessagesListPresent = () => isElementPresent('#message-list'); -const isTargetAggregatesMenuItemPresent = async () => { - return await (await $(`=Target aggregates`)).isExisting(); -}; +const isTasksListPresent = () => isElementPresent('#tasks-list'); -const isElementByIdPresent = async (elementId) => { - return await (await $(`#${elementId}`)).isExisting(); -}; +const isReportsListPresent = () => isElementPresent('#reports-list'); -const getHeaderTitleOnMobile = async () => { - return { - name: await mobileTopBarTitle().getText(), - }; -}; +const isPeopleListPresent = () => isElementPresent('#contacts-list'); -const openHamburgerMenu = async () => { - if (!(await isHamburgerMenuOpen())) { - await (await hamburgerMenu()).waitForClickable(); - await (await hamburgerMenu()).click(); - // Adding pause here as we have to wait for sidebar nav menu animation to load - await browser.pause(ELEMENT_DISPLAY_PAUSE); - } - await (await sideBarMenuTitle()).waitForDisplayed(); -}; +const isTargetMenuItemPresent = () => isElementPresent('=Target'); -const closeHamburgerMenu = async () => { - if (await isHamburgerMenuOpen()) { - await (await closeSideBarMenu()).waitForClickable(); - await (await closeSideBarMenu()).click(); - } +const isTargetAggregatesMenuItemPresent = () => isElementPresent('=Target aggregates'); - await (await sideBarMenuTitle()).waitForDisplayed({ reverse: true }); -}; +const isMoreOptionsMenuPresent = async () => await (await kebabMenuSelectors.moreOptionsMenu()).isExisting(); const navigateToLogoutModal = async () => { await openHamburgerMenu(); - await (await logoutButton()).waitForClickable(); - await (await logoutButton()).click(); + await (await hamburgerMenuSelectors.logoutButton()).waitForClickable(); + await (await hamburgerMenuSelectors.logoutButton()).click(); await (await modalPage.body()).waitForDisplayed(); }; @@ -259,92 +310,54 @@ const goToBase = async () => { await waitForPageLoaded(); }; -const goToReports = async (reportId = '') => { - await goToUrl(`/#/reports/${reportId}`); - await waitForPageLoaded(); -}; - -const goToPeople = async (contactId = '', shouldLoad = true) => { - await goToUrl(`/#/contacts/${contactId}`); - if (shouldLoad) { - await waitForPageLoaded(); - } +const goToAboutPage = async () => { + await goToUrl(`/#/about`); + await waitForLoaders(); }; const goToMessages = async () => { await goToUrl(`/#/messages`); - await (await messagesTab()).waitForDisplayed(); + await (await tabsSelector.messagesTab()).waitForDisplayed(); }; const goToTasks = async () => { await goToUrl(`/#/tasks`); - await (await taskTab()).waitForDisplayed(); + await (await tabsSelector.taskTab()).waitForDisplayed(); await waitForPageLoaded(); }; -const goToAnalytics = async () => { - await goToUrl(`/#/analytics`); - await (await analyticsTab()).waitForDisplayed(); +const goToReports = async (reportId = '') => { + await goToUrl(`/#/reports/${reportId}`); await waitForPageLoaded(); }; -const goToAboutPage = async () => { - await goToUrl(`/#/about`); - await waitForLoaders(); -}; - -const waitForLoaderToDisappear = async (element) => { - const loaderSelector = '.loader'; - const loader = await (element ? element.$(loaderSelector) : $(loaderSelector)); - await loader.waitForDisplayed({ reverse: true }); -}; - -const hideSnackbar = () => { - // snackbar appears in the bottom of the page for 5 seconds when certain actions are made - // for example when filling a form, or creating a contact and intercepts all clicks in the FAB and Flat buttons - // this action is temporary, and will be undone with a refresh - return browser.execute(() => { - // eslint-disable-next-line no-undef - window.jQuery('.snackbar-content').hide(); - }); -}; - -const getVisibleLoaders = async () => { - const visible = []; - for (const loader of await loaders()) { - if (await loader.isDisplayedInViewport()) { - visible.push(loader); - } +const goToPeople = async (contactId = '', shouldLoad = true) => { + await goToUrl(`/#/contacts/${contactId}`); + if (shouldLoad) { + await waitForPageLoaded(); } - - return visible; -}; - -const waitForLoaders = async () => { - await browser.waitUntil(async () => { - const visibleLoaders = await getVisibleLoaders(); - return !visibleLoaders.length; - }, { timeoutMsg: 'Waiting for Loading spinners to hide timed out.' }); }; -const waitForAngularLoaded = async (timeout = 40000) => { - await (await hamburgerMenu()).waitForDisplayed({ timeout }); +const goToAnalytics = async () => { + await goToUrl(`/#/analytics`); + await (await tabsSelector.analyticsTab()).waitForDisplayed(); + await waitForPageLoaded(); }; -const waitForPageLoaded = async () => { - // if we immediately check for app loaders, we might bypass the initial page load (the bootstrap loader) - // so waiting for the main page to load. - await waitForAngularLoaded(); - // ideally we would somehow target all loaders that we expect (like LHS + RHS loaders), but not all pages - // get all loaders. - do { - await waitForLoaders(); - } while ((await getVisibleLoaders()).length > 0); +const closeReloadModal = async (shouldUpdate = false, timeout = 5000) => { + try { + shouldUpdate ? await modalPage.submit(timeout) : await modalPage.cancel(timeout); + shouldUpdate && await waitForAngularLoaded(); + return true; + } catch (err) { + timeout && console.error('Reload modal has not showed up'); + return false; + } }; const syncAndNotWaitForSuccess = async () => { await openHamburgerMenu(); - await (await syncButton()).click(); + await (await hamburgerMenuSelectors.syncButton()).click(); }; const syncAndWaitForSuccess = async (timeout = 20000, retry = 10) => { @@ -355,13 +368,13 @@ const syncAndWaitForSuccess = async (timeout = 20000, retry = 10) => { try { await openHamburgerMenu(); - if (!await (await syncInProgress()).isExisting()) { - await (await syncButton()).click(); + if (!await (await hamburgerMenuSelectors.syncInProgress()).isExisting()) { + await (await hamburgerMenuSelectors.syncButton()).click(); await openHamburgerMenu(); } - await (await syncInProgress()).waitForDisplayed({ timeout, reverse: true }); - await (await syncSuccess()).waitForDisplayed({ timeout }); + await (await hamburgerMenuSelectors.syncInProgress()).waitForDisplayed({ timeout, reverse: true }); + await (await hamburgerMenuSelectors.syncSuccess()).waitForDisplayed({ timeout }); } catch (err) { console.error(err); await syncAndWaitForSuccess(timeout, retry - 1); @@ -393,33 +406,13 @@ const sync = async (expectReload, timeout) => { await closeHamburgerMenu(); }; -const syncAndWaitForFailure = async () => { - await openHamburgerMenu(); - await (await syncButton()).click(); - await openHamburgerMenu(); - await (await syncRequired()).waitForDisplayed({ timeout: 20000 }); -}; - -const closeReloadModal = async (shouldUpdate = false, timeout = 5000) => { - try { - shouldUpdate ? await modalPage.submit(timeout) : await modalPage.cancel(timeout); - shouldUpdate && await waitForAngularLoaded(); - return true; - } catch (err) { - timeout && console.error('Reload modal has not showed up'); - return false; - } -}; - const openReportBugAndFetchProperties = async () => { - await (await feedbackMenuOption()).waitForClickable(); - await (await feedbackMenuOption()).click(); + await (await hamburgerMenuSelectors.feedbackMenuOption()).waitForClickable(); + await (await hamburgerMenuSelectors.feedbackMenuOption()).click(); return await modalPage.getModalDetails(); }; -const isReportBugOpen = async () => { - return await (await $(FEEDBACK)).isExisting(); -}; +const isReportBugOpen = () => isElementPresent('#feedback'); const closeReportBug = async () => { if (await isReportBugOpen()) { @@ -428,29 +421,29 @@ const closeReportBug = async () => { }; const openAboutMenu = async () => { - await (await $(ABOUT_MENU)).waitForClickable(); - await (await $(ABOUT_MENU)).click(); - await (await $(aboutPage.RELOAD_BUTTON)).waitForDisplayed(); + await (await hamburgerMenuSelectors.aboutButton()).waitForClickable(); + await (await hamburgerMenuSelectors.aboutButton()).click(); + await (await $('.about.page .mat-primary')).waitForDisplayed(); }; const openUserSettings = async () => { - await (await $(USER_SETTINGS)).waitForClickable(); - await (await $(USER_SETTINGS)).click(); + await (await hamburgerMenuSelectors.userSettingsButton()).waitForClickable(); + await (await hamburgerMenuSelectors.userSettingsButton()).click(); }; const openUserSettingsAndFetchProperties = async () => { - await (await $(USER_SETTINGS)).waitForClickable(); - await (await $(USER_SETTINGS)).click(); - await (await $(EDIT_PROFILE)).waitForDisplayed(); + await openUserSettings(); + await (await userSettingsSelectors.editProfileButton()).waitForDisplayed(); }; const openEditProfile = async () => { - await (await $(EDIT_PROFILE)).click(); + await (await userSettingsSelectors.editProfileButton()).waitForClickable(); + await (await userSettingsSelectors.editProfileButton()).click(); }; const openAppManagement = async () => { - await (await configurationAppMenuOption()).waitForClickable(); - await (await configurationAppMenuOption()).click(); + await (await hamburgerMenuSelectors.appManagementButton()).waitForClickable(); + await (await hamburgerMenuSelectors.appManagementButton()).click(); await (await $('.navbar-brand')).waitForDisplayed(); }; @@ -460,18 +453,16 @@ const getTextForElements = async (elements) => { }; const getAllButtonLabelsNames = async () => { - return await getTextForElements(getAllButtonLabels); + return await getTextForElements(tabsSelector.getAllButtonLabels); }; -//more options menu -const optionSelector = (action, item) => $(`[test-id="${action}-${item}"]`); - -const isMenuOptionEnabled = async (action, item) => { - return await (await optionSelector(action, item)).isEnabled(); +const isMenuOptionEnabled = async (action) => { + const parent = await (await kebabMenuSelectors[action]()).parentElement().parentElement(); + return await parent.getAttribute('aria-disabled') === 'false'; }; -const isMenuOptionVisible = async (action, item) => { - return await (await optionSelector(action, item)).isDisplayed(); +const isMenuOptionVisible = async (action) => { + return await (await kebabMenuSelectors[action]()).isDisplayed(); }; const loadNextInfiniteScrollPage = async () => { @@ -482,7 +473,7 @@ const loadNextInfiniteScrollPage = async () => { }; const getErrorLog = async () => { - await errorLog().waitForDisplayed(); + await (await $('error-log')).waitForDisplayed(); const errorMessage = await (await $('.error-details span')).getText(); const userDetails = await (await $$('.error-details dl dd')); @@ -494,9 +485,9 @@ const getErrorLog = async () => { }; const createFormDoc = (path, formId) => { - const id = formId ? formId : path.split('/').pop(); + const id = formId || path.split('/').pop(); const formXML = fs.readFileSync(`${path}.xml`, 'utf8'); - const formDoc = { + return { _id: `form:${id}`, internalId: id, title: id, @@ -512,74 +503,66 @@ const createFormDoc = (path, formId) => { }, }, }; - return formDoc; }; module.exports = { + tabsSelector, + fabSelectors, + getJsonErrorText, + openHamburgerMenu, + closeHamburgerMenu, openMoreOptionsMenu, - closeFastActionList, + accessEditOption, + accessDeleteOption, + accessExportOption, + accessReviewOption, + hideSnackbar, + waitForLoaderToDisappear, + waitForLoaders, + waitForAngularLoaded, + waitForPageLoaded, clickFastActionFAB, + getFastActionItemsLabels, clickFastActionFlat, openFastActionReport, getFastActionFABTextById, getFastActionFlatText, - logout, - logoutButton, - getLogoutMessage, - messagesTab, - analyticsTab, - goToReports, - goToPeople, - getReportsButtonLabel, - getMessagesButtonLabel, - getTasksButtonLabel, - goToBase, - hideSnackbar, - waitForLoaders, - sync, - syncAndNotWaitForSuccess, - syncButton, - closeReloadModal, - goToMessages, - goToTasks, - goToAnalytics, + closeFastActionList, + isReportActionDisplayed, + isElementPresent, isMessagesListPresent, isTasksListPresent, isPeopleListPresent, isReportsListPresent, isTargetMenuItemPresent, isTargetAggregatesMenuItemPresent, - openHamburgerMenu, - closeHamburgerMenu, + isMoreOptionsMenuPresent, + logout, + getLogoutMessage, + goToUrl, + refresh, + goToBase, + goToAboutPage, + goToMessages, + goToTasks, + goToReports, + goToPeople, + goToAnalytics, + closeReloadModal, + syncAndNotWaitForSuccess, + sync, + openReportBugAndFetchProperties, + closeReportBug, openAboutMenu, - openUserSettingsAndFetchProperties, openUserSettings, + openUserSettingsAndFetchProperties, openEditProfile, - openReportBugAndFetchProperties, openAppManagement, - waitForLoaderToDisappear, - goToAboutPage, - waitForPageLoaded, - activeSnackbar, - inactiveSnackbar, - snackbarMessage, - snackbarAction, getTextForElements, - jsonError, + getAllButtonLabelsNames, isMenuOptionEnabled, isMenuOptionVisible, - moreOptionsMenu, - refresh, - syncAndWaitForFailure, - waitForAngularLoaded, - closeReportBug, - getAllButtonLabelsNames, loadNextInfiniteScrollPage, - goToUrl, - getFastActionItemsLabels, getErrorLog, - reportsFastActionFAB, - isReportActionDisplayed, - getHeaderTitleOnMobile, createFormDoc, }; diff --git a/tests/page-objects/default/contacts/contacts.wdio.page.js b/tests/page-objects/default/contacts/contacts.wdio.page.js index 1cd4d8533c8..c55384273ea 100644 --- a/tests/page-objects/default/contacts/contacts.wdio.page.js +++ b/tests/page-objects/default/contacts/contacts.wdio.page.js @@ -11,12 +11,6 @@ const searchSelectors = { searchBox: () => $('.mm-search-bar-container input#freetext'), }; -const menuSelectors = { - exportButton: () => $(`.mat-mdc-menu-content .mat-mdc-menu-item[test-id="export-contacts"]`), - editContactButton: () => $(`.mat-mdc-menu-content .mat-mdc-menu-item[test-id="edit-contacts"]`), - deleteContactButton: () => $(`.mat-mdc-menu-content .mat-mdc-menu-item[test-id="delete-contacts"]`), -}; - const CONTACT_LIST_SELECTOR = '#contacts-list'; const CONTENT_ROW_SELECTOR = `${CONTACT_LIST_SELECTOR} .content-row`; const leftPanelSelectors = { @@ -206,16 +200,9 @@ const addPerson = async ({ return (await contactCardSelectors.contactCardName()).getText(); }; -const openEditContactForm = async () => { - await waitForContactLoaded(); - await commonPage.openMoreOptionsMenu(); - await (await menuSelectors.editContactButton()).waitForClickable(); - await (await menuSelectors.editContactButton()).click(); -}; - const editPerson = async (currentName, { name, phone, dob }) => { await selectLHSRowByText(currentName); - await openEditContactForm(); + await commonPage.accessEditOption(); await (await genericForm.nextPage()); if (name !== undefined) { @@ -237,9 +224,7 @@ const editPersonName = async (name, updatedName) => { }; const deletePerson = async () => { - await commonPage.openMoreOptionsMenu(); - await (await menuSelectors.deleteContactButton()).waitForClickable(); - await (await menuSelectors.deleteContactButton()).click(); + await commonPage.accessDeleteOption(); await modalPage.submit(); }; @@ -284,7 +269,7 @@ const allContactsList = async () => { const editPlace = async (currentName, editedName) => { await selectLHSRowByText(currentName, true); - await openEditContactForm(); + await commonPage.accessEditOption(); await commonEnketoPage.setInputValue('Name of this', editedName); await genericForm.submitForm(); @@ -339,12 +324,6 @@ const getDeathCardInfo = async () => { }; }; -const exportContacts = async () => { - await commonPage.openMoreOptionsMenu(); - await (await menuSelectors.exportButton()).waitForClickable(); - await (await menuSelectors.exportButton()).click(); -}; - const getCurrentContactId = async () => { const currentUrl = await browser.getUrl(); const contactBaseUrl = utils.getBaseUrl() + 'contacts/'; @@ -407,11 +386,9 @@ module.exports = { getAllRHSPeopleNames, waitForContactLoaded, waitForContactUnloaded, - openEditContactForm, editPerson, editPersonName, editPlace, - exportContacts, getContactSummaryField, getAllRHSReportsNames, getAllRHSTaskNames, diff --git a/tests/page-objects/default/enketo/custom-doc.wdio.page.js b/tests/page-objects/default/enketo/custom-doc.wdio.page.js index 2a72ee5577c..b6471e9f070 100644 --- a/tests/page-objects/default/enketo/custom-doc.wdio.page.js +++ b/tests/page-objects/default/enketo/custom-doc.wdio.page.js @@ -46,7 +46,6 @@ const reportModelXml = ` `; - const editReportWithAttachmentDoc ={ _id: uuid(), form: 'one-text-form', @@ -71,8 +70,6 @@ const editReportWithAttachmentDoc ={ } }; - - module.exports = { extensionLibDoc, editReportWithAttachmentDoc, diff --git a/tests/page-objects/default/login/login.wdio.page.js b/tests/page-objects/default/login/login.wdio.page.js index 67a5120cf3b..9aa5a65d8f1 100644 --- a/tests/page-objects/default/login/login.wdio.page.js +++ b/tests/page-objects/default/login/login.wdio.page.js @@ -220,4 +220,5 @@ module.exports = { updatePasswordButton, getPasswordResetTranslations, getPasswordResetErrorMessage, + NEW_PASSWORD, }; diff --git a/tests/page-objects/default/old-navigation/old-navigation.wdio.page.js b/tests/page-objects/default/old-navigation/old-navigation.wdio.page.js index f7ac9e15eca..6df5e55da5b 100644 --- a/tests/page-objects/default/old-navigation/old-navigation.wdio.page.js +++ b/tests/page-objects/default/old-navigation/old-navigation.wdio.page.js @@ -137,6 +137,13 @@ const logout = async () => { await browser.pause(100); // wait for login page js to execute }; +const mobileTopBarTitle = () => $('mm-navigation .ellipsis-title'); +const getHeaderTitleOnMobile = async () => { + return { + name: await mobileTopBarTitle().getText(), + }; +}; + module.exports = { goToBase, goToMessages, @@ -147,4 +154,5 @@ module.exports = { sync, waitForPageLoaded, logout, + getHeaderTitleOnMobile, }; diff --git a/tests/page-objects/default/privacy-policy/privacy-policy.wdio.page.js b/tests/page-objects/default/privacy-policy/privacy-policy.wdio.page.js index ddb3b815315..b089763bcbc 100644 --- a/tests/page-objects/default/privacy-policy/privacy-policy.wdio.page.js +++ b/tests/page-objects/default/privacy-policy/privacy-policy.wdio.page.js @@ -37,7 +37,7 @@ const waitAndAcceptPolicy = async (elm, { header, paragraph, language }, sync = timeout: 15 * 1000, timeoutMsg: `Timed out waiting for messages tag to be displayed` }; - await browser.waitUntil(async () => (await commonElements.messagesTab()).isDisplayed(), timeoutOpts); + await browser.waitUntil(async () => (await commonElements.tabsSelector.messagesTab()).isDisplayed(), timeoutOpts); if (sync) { await commonElements.sync(); } diff --git a/tests/page-objects/default/reports/reports.wdio.page.js b/tests/page-objects/default/reports/reports.wdio.page.js index 82577aa1dd9..5ff38721d29 100644 --- a/tests/page-objects/default/reports/reports.wdio.page.js +++ b/tests/page-objects/default/reports/reports.wdio.page.js @@ -52,13 +52,6 @@ const rightPanelSelectors = { sentTask: () => $(`${REPORT_BODY_DETAILS} ul .task-list .task-state .state`), }; -const kebabMenuSelectors = { - edit: () => $('.mat-mdc-menu-content .mat-mdc-menu-item[test-id="edit-reports"]'), - delete: () => $('.mat-mdc-menu-content .mat-mdc-menu-item[test-id="delete-reports"]'), - export: () => $('.mat-mdc-menu-content .mat-mdc-menu-item[test-id="export-reports"]'), - review: () => $('.mat-mdc-menu-content .mat-mdc-menu-item[test-id="review-report"]'), -}; - const REVIEW_REPORT_CONTAINER = '.verify-report-options-wrapper'; const reviewDialogSelectors = { container: () => $(REVIEW_REPORT_CONTAINER), @@ -403,29 +396,8 @@ const fieldByIndex = async (index) => { return await (await $(`${REPORT_BODY_DETAILS} li:nth-child(${index}) p`)).getText(); }; -const performMenuAction = async (actionSelector) => { - await commonElements.openMoreOptionsMenu(); - const actionElement = await actionSelector(); - await actionElement.waitForClickable(); - await actionElement.click(); -}; - -const editReport = async () => { - await performMenuAction(kebabMenuSelectors.edit); -}; - -const exportReports = async () => { - await performMenuAction(kebabMenuSelectors.export); -}; - -const deleteReport = async () => { - await performMenuAction(kebabMenuSelectors.delete); -}; - const openReview = async () => { - await commonElements.openMoreOptionsMenu(); - await (await kebabMenuSelectors.review()).waitForClickable(); - await (await kebabMenuSelectors.review()).click(); + await commonElements.accessReviewOption(); await (await reviewDialogSelectors.container()).waitForDisplayed(); }; @@ -524,9 +496,6 @@ module.exports = { getOpenReportInfo, getListReportInfo, openReport, - editReport, - deleteReport, - exportReports, fieldByIndex, clickOnCaseId, getReportListLoadingStatus, diff --git a/tests/page-objects/default/users/user-settings.wdio.page.js b/tests/page-objects/default/users/user-settings.wdio.page.js index 031db284a3b..4ecb2e3d5e8 100644 --- a/tests/page-objects/default/users/user-settings.wdio.page.js +++ b/tests/page-objects/default/users/user-settings.wdio.page.js @@ -1,5 +1,5 @@ -const commonPage = require('../common/common.wdio.page'); -const modalPage = require('../common/modal.wdio.page'); +const commonPage = require('@page-objects/default/common/common.wdio.page'); +const modalPage = require('@page-objects/default/common/modal.wdio.page'); const languageDropDown = () => $('#language'); diff --git a/tests/page-objects/default/users/user.wdio.page.js b/tests/page-objects/default/users/user.wdio.page.js index 54b0566ab3b..8da7f95267d 100644 --- a/tests/page-objects/default/users/user.wdio.page.js +++ b/tests/page-objects/default/users/user.wdio.page.js @@ -1,5 +1,5 @@ const _ = require('lodash'); -const commonElements = require('../common/common.wdio.page'); +const commonElements = require('@page-objects/default/common/common.wdio.page'); const addUserButton = () => $('a#add-user'); const cancelButton = () => $('a[test-id="modal-cancel-btn"]'); @@ -223,7 +223,6 @@ const closeAddUserDialog = async () => { await (await addUserDialog()).waitForDisplayed({ reverse: true }); }; - module.exports = { addUserDialog, goToAdminUser,