Skip to content

Commit f23c6fe

Browse files
authored
chore: Refactor page object implementation [WPB-18373] (#19172)
* Add PageManager to avoid come duplication and allow better page object handling * Addressing Sonar Qube report
1 parent e0290eb commit f23c6fe

File tree

4 files changed

+347
-165
lines changed

4 files changed

+347
-165
lines changed

test/e2e_tests/criticalFlow.spec.ts

Lines changed: 82 additions & 138 deletions
Original file line numberDiff line numberDiff line change
@@ -21,49 +21,20 @@ import {faker} from '@faker-js/faker';
2121

2222
import {Services} from './data/serviceInfo';
2323
import {getUser, User} from './data/user';
24-
import {AccountPage} from './pages/account.page';
25-
import {AppLockModal} from './pages/appLock.modal';
26-
import {BlockWarningModal} from './pages/blockWarning.modal';
27-
import {ConversationPage} from './pages/conversation.page';
28-
import {ConversationListPage} from './pages/conversationList.page';
29-
import {ConversationSidebar} from './pages/conversationSidebar.page';
30-
import {DataShareConsentModal} from './pages/dataShareConsent.modal';
31-
import {DeleteAccountModal} from './pages/deleteAccount.modal';
32-
import {DeleteAccountPage} from './pages/deleteAccount.page';
33-
import {EmailVerificationPage} from './pages/emailVerification.page';
34-
import {GroupCreationPage} from './pages/groupCreation.page';
35-
import {LoginPage} from './pages/login.page';
36-
import {MarketingConsentModal} from './pages/marketingConsent.modal';
37-
import {OutgoingConnectionPage} from './pages/outgoingConnection.page';
38-
import {RegistrationPage} from './pages/registration.page';
39-
import {SetUsernamePage} from './pages/setUsername.page';
40-
import {SingleSignOnPage} from './pages/singleSignOn.page';
41-
import {StartUIPage} from './pages/startUI.page';
42-
import {UserProfileModal} from './pages/userProfile.modal';
43-
import {WelcomePage} from './pages/welcome.page';
4424
import {test, expect} from './test.fixtures';
4525
import {generateSecurePassword} from './utils/userDataGenerator';
4626

47-
const webAppPath = process.env.WEBAPP_URL ?? '';
4827
const createdUsers: User[] = [];
4928
const createdTeams: Map<User, string> = new Map();
5029

51-
test('Team owner adds whole team to an all team chat', {tag: ['@TC-8631', '@crit-flow']}, async ({page, api}) => {
30+
test('Team owner adds whole team to an all team chat', {tag: ['@TC-8631', '@crit-flow']}, async ({pages, api}) => {
5231
// Generating test data
5332
const owner = getUser();
5433
const member1 = getUser();
5534
const member2 = getUser();
5635
const teamName = 'Critical';
5736
const conversationName = 'Crits';
5837

59-
// Initializing page objects
60-
const singleSignOnPage = new SingleSignOnPage(page);
61-
const loginPage = new LoginPage(page);
62-
const dataShareConsentModal = new DataShareConsentModal(page);
63-
const conversationListPage = new ConversationListPage(page);
64-
const groupCreationPage = new GroupCreationPage(page);
65-
const startUIPage = new StartUIPage(page);
66-
6738
await test.step('Preconditions: Creating preconditions for the test via API', async () => {
6839
await api.createTeamOwner(owner, teamName);
6940
owner.teamId = await api.team.getTeamIdForUser(owner);
@@ -79,23 +50,23 @@ test('Team owner adds whole team to an all team chat', {tag: ['@TC-8631', '@crit
7950
});
8051

8152
await test.step('Team owner logs in into a client and creates group conversation', async () => {
82-
await page.goto(webAppPath);
83-
await singleSignOnPage.enterEmailOnSSOPage(owner.email);
84-
await loginPage.inputPassword(owner.password);
85-
await loginPage.clickSignInButton();
86-
await dataShareConsentModal.clickDecline();
53+
await pages.openMainPage();
54+
await pages.singleSignOnPage.enterEmailOnSSOPage(owner.email);
55+
await pages.loginPage.inputPassword(owner.password);
56+
await pages.loginPage.clickSignInButton();
57+
await pages.dataShareConsentModal.clickDecline();
8758
});
8859

8960
await test.step('Team owner adds a service to newly created group', async () => {
9061
await api.team.addServiceToTeamWhitelist(owner.teamId!, Services.POLL_SERVICE, owner.token!);
9162
});
9263

9364
await test.step('Team owner adds team members to a group', async () => {
94-
await conversationListPage.clickCreateGroup();
95-
await groupCreationPage.setGroupName(conversationName);
96-
await startUIPage.selectUsers([member1.username, member2.username]);
97-
await groupCreationPage.clickCreateGroupButton();
98-
expect(await conversationListPage.isConversationItemVisible(conversationName)).toBeTruthy();
65+
await pages.conversationListPage.clickCreateGroup();
66+
await pages.groupCreationPage.setGroupName(conversationName);
67+
await pages.startUIPage.selectUsers([member1.username, member2.username]);
68+
await pages.groupCreationPage.clickCreateGroupButton();
69+
expect(await pages.conversationListPage.isConversationItemVisible(conversationName)).toBeTruthy();
9970
});
10071

10172
// Steps below require [WPB-18075] and [WPB-17547]
@@ -111,7 +82,7 @@ test('Team owner adds whole team to an all team chat', {tag: ['@TC-8631', '@crit
11182
await test.step('Team owner removes a service from a group', async () => {});
11283
});
11384

114-
test('Account Management', {tag: ['@TC-8639', '@crit-flow']}, async ({page, api}) => {
85+
test('Account Management', {tag: ['@TC-8639', '@crit-flow']}, async ({pages, api}) => {
11586
test.slow(); // Increasing test timeout to 90 seconds to accommodate the full flow
11687

11788
// Generating test data
@@ -121,15 +92,6 @@ test('Account Management', {tag: ['@TC-8639', '@crit-flow']}, async ({page, api}
12192
const conversationName = 'Tracking';
12293
const appLockPassphrase = generateSecurePassword();
12394

124-
// Initializing page objects
125-
const singleSignOnPage = new SingleSignOnPage(page);
126-
const loginPage = new LoginPage(page);
127-
const dataShareConsentModal = new DataShareConsentModal(page);
128-
const conversationSidebar = new ConversationSidebar(page);
129-
const accountPage = new AccountPage(page);
130-
const appLockModal = new AppLockModal(page);
131-
const conversationListPage = new ConversationListPage(page);
132-
13395
// Creating preconditions for the test via API
13496
await test.step('Preconditions: Creating preconditions for the test via API', async () => {
13597
await api.createTeamOwner(owner, teamName);
@@ -150,37 +112,37 @@ test('Account Management', {tag: ['@TC-8639', '@crit-flow']}, async ({page, api}
150112

151113
// Test steps
152114
await test.step('Members logs in into the application', async () => {
153-
await page.goto(webAppPath);
154-
await singleSignOnPage.enterEmailOnSSOPage(owner.email);
155-
await loginPage.inputPassword(owner.password);
156-
await loginPage.clickSignInButton();
157-
await dataShareConsentModal.clickDecline();
115+
await pages.openMainPage();
116+
await pages.singleSignOnPage.enterEmailOnSSOPage(owner.email);
117+
await pages.loginPage.inputPassword(owner.password);
118+
await pages.loginPage.clickSignInButton();
119+
await pages.dataShareConsentModal.clickDecline();
158120
});
159121

160122
await test.step('Member opens settings', async () => {
161-
await conversationSidebar.clickPreferencesButton();
123+
await pages.conversationSidebar.clickPreferencesButton();
162124
});
163125

164126
await test.step('Member enables logging in settings', async () => {
165-
await accountPage.toggleSendUsageData();
127+
await pages.accountPage.toggleSendUsageData();
166128
});
167129

168130
await test.step('Member enables applock and sets their password', async () => {
169-
await accountPage.toggleAppLock();
170-
await appLockModal.setPasscode(appLockPassphrase);
171-
await conversationSidebar.clickAllConversationsButton();
172-
expect(await conversationListPage.isConversationItemVisible(conversationName));
131+
await pages.accountPage.toggleAppLock();
132+
await pages.appLockModal.setPasscode(appLockPassphrase);
133+
await pages.conversationSidebar.clickAllConversationsButton();
134+
expect(await pages.conversationListPage.isConversationItemVisible(conversationName));
173135
});
174136

175137
await test.step('Member verifies if applock is working', async () => {
176-
await page.reload();
177-
expect(await appLockModal.isVisible());
178-
expect(await appLockModal.getAppLockModalHeader()).toContain('Enter passcode to unlock');
179-
expect(await appLockModal.getAppLockModalText()).toContain('Passcode');
180-
181-
await appLockModal.unlockAppWithPasscode(appLockPassphrase);
182-
expect(await appLockModal.isHidden());
183-
expect(await conversationListPage.isConversationItemVisible(conversationName));
138+
await pages.refreshPage();
139+
expect(await pages.appLockModal.isVisible());
140+
expect(await pages.appLockModal.getAppLockModalHeader()).toContain('Enter passcode to unlock');
141+
expect(await pages.appLockModal.getAppLockModalText()).toContain('Passcode');
142+
143+
await pages.appLockModal.unlockAppWithPasscode(appLockPassphrase);
144+
expect(await pages.appLockModal.isHidden());
145+
expect(await pages.conversationListPage.isConversationItemVisible(conversationName));
184146
});
185147

186148
// TODO: Missing test steps for TC-8639 from testiny:
@@ -193,32 +155,14 @@ test('Account Management', {tag: ['@TC-8639', '@crit-flow']}, async ({page, api}
193155
await test.step('Member resets their password ', async () => {});
194156
});
195157

196-
test('Personal Account Lifecycle', {tag: ['@TC-8638', '@crit-flow']}, async ({page, api}) => {
158+
test('Personal Account Lifecycle', {tag: ['@TC-8638', '@crit-flow']}, async ({pages, api}) => {
197159
test.setTimeout(120_000); // Increasing test timeout to 120 seconds to accommodate the full flow
198160

199161
// Generating test data
200162
// userB is the contact user, userA is the user who registers
201163
const userB = getUser();
202164
const userA = getUser();
203165

204-
// Initializing page objects
205-
const singleSignOnPage = new SingleSignOnPage(page);
206-
const welcomePage = new WelcomePage(page);
207-
const registrationPage = new RegistrationPage(page);
208-
const verificationPage = new EmailVerificationPage(page);
209-
const marketingConsentModal = new MarketingConsentModal(page);
210-
const setUsernamePage = new SetUsernamePage(page);
211-
const dataShareConsentModal = new DataShareConsentModal(page);
212-
const conversationSidebar = new ConversationSidebar(page);
213-
const conversationPage = new ConversationPage(page);
214-
const startUIPage = new StartUIPage(page);
215-
const userProfileModal = new UserProfileModal(page);
216-
const conversationListPage = new ConversationListPage(page);
217-
const outgoingConnectionPage = new OutgoingConnectionPage(page);
218-
const blockWarningModal = new BlockWarningModal(page);
219-
const deleteAccountModal = new DeleteAccountModal(page);
220-
const accountPage = new AccountPage(page);
221-
222166
await test.step('Preconditions: Creating preconditions for the test via API', async () => {
223167
await api.createPersonalUser(userB);
224168
createdUsers.push(userB);
@@ -228,66 +172,66 @@ test('Personal Account Lifecycle', {tag: ['@TC-8638', '@crit-flow']}, async ({pa
228172

229173
// Test steps
230174
await test.step('User A opens the application and registers personal account', async () => {
231-
await page.goto(webAppPath);
232-
await singleSignOnPage.enterEmailOnSSOPage(userA.email);
233-
await welcomePage.clickCreateAccountButton();
234-
await welcomePage.clickCreatePersonalAccountButton();
235-
expect(await registrationPage.isPasswordPolicyInfoVisible());
175+
await pages.openMainPage();
176+
await pages.singleSignOnPage.enterEmailOnSSOPage(userA.email);
177+
await pages.welcomePage.clickCreateAccountButton();
178+
await pages.welcomePage.clickCreatePersonalAccountButton();
179+
expect(await pages.registrationPage.isPasswordPolicyInfoVisible());
236180

237-
await registrationPage.fillInUserInfo(userA);
238-
expect(await registrationPage.isSubmitButtonEnabled()).toBeFalsy();
181+
await pages.registrationPage.fillInUserInfo(userA);
182+
expect(await pages.registrationPage.isSubmitButtonEnabled()).toBeFalsy();
239183

240-
await registrationPage.toggleTermsCheckbox();
241-
expect(await registrationPage.isSubmitButtonEnabled()).toBeTruthy();
184+
await pages.registrationPage.toggleTermsCheckbox();
185+
expect(await pages.registrationPage.isSubmitButtonEnabled()).toBeTruthy();
242186

243-
await registrationPage.clickSubmitButton();
187+
await pages.registrationPage.clickSubmitButton();
244188
const verificationCode = await api.inbucket.getVerificationCode(userA.email);
245-
await verificationPage.enterVerificationCode(verificationCode);
246-
await marketingConsentModal.clickConfirmButton();
189+
await pages.verificationPage.enterVerificationCode(verificationCode);
190+
await pages.marketingConsentModal.clickConfirmButton();
247191
});
248192

249193
await test.step('Personal user A sets user name', async () => {
250194
// Expect that automatic username generation is correct
251-
expect(await setUsernamePage.getHandleInputValue()).toBe(userA.username);
195+
expect(await pages.setUsernamePage.getHandleInputValue()).toBe(userA.username);
252196
const newUsername = userA.username.slice(0, 10) + faker.string.alpha(5).toLowerCase();
253197
userA.username = newUsername;
254-
await setUsernamePage.setUsername(newUsername);
255-
await setUsernamePage.clickNextButton();
198+
await pages.setUsernamePage.setUsername(newUsername);
199+
await pages.setUsernamePage.clickNextButton();
256200
});
257201

258202
await test.step('Personal user A declines sending anonymous usage data', async () => {
259-
await dataShareConsentModal.isModalPresent();
260-
await dataShareConsentModal.clickDecline();
203+
await pages.dataShareConsentModal.isModalPresent();
204+
await pages.dataShareConsentModal.clickDecline();
261205
});
262206

263207
await test.step('Personal user A checks that username was set correctly', async () => {
264-
expect(await conversationSidebar.getPersonalStatusName()).toBe(`${userA.firstName} ${userA.lastName}`);
265-
expect(await conversationSidebar.getPersonalUserName()).toContain(userA.username);
266-
expect(await conversationPage.isWatermarkVisible());
208+
expect(await pages.conversationSidebar.getPersonalStatusName()).toBe(`${userA.firstName} ${userA.lastName}`);
209+
expect(await pages.conversationSidebar.getPersonalUserName()).toContain(userA.username);
210+
expect(await pages.conversationPage.isWatermarkVisible());
267211
});
268212

269213
await test.step('Personal user A searches for other personal user B', async () => {
270-
await conversationSidebar.clickConnectButton();
271-
await startUIPage.selectUser(userB.username);
272-
expect(await userProfileModal.isVisible());
214+
await pages.conversationSidebar.clickConnectButton();
215+
await pages.startUIPage.selectUser(userB.username);
216+
expect(await pages.userProfileModal.isVisible());
273217
});
274218

275219
await test.step('Personal user A sends a connection request to personal user B', async () => {
276-
await userProfileModal.clickConnectButton();
277-
await conversationListPage.openConversation(userB.fullName);
278-
expect(await outgoingConnectionPage.getOutgoingConnectionUsername()).toContain(userB.username);
279-
expect(await outgoingConnectionPage.isPendingIconVisible(userB.fullName));
220+
await pages.userProfileModal.clickConnectButton();
221+
await pages.conversationListPage.openConversation(userB.fullName);
222+
expect(await pages.outgoingConnectionPage.getOutgoingConnectionUsername()).toContain(userB.username);
223+
expect(await pages.outgoingConnectionPage.isPendingIconVisible(userB.fullName));
280224
});
281225

282226
await test.step('Personal user B accepts request', async () => {
283227
await api.acceptConnectionRequest(userB);
284-
expect(await outgoingConnectionPage.isPendingIconHidden(userB.fullName));
228+
expect(await pages.outgoingConnectionPage.isPendingIconHidden(userB.fullName));
285229
});
286230

287231
await test.step('Personal user A and personal user B exchange some messages', async () => {
288232
// TODO: Conversation sometimes closes after connection request was approved, so we need to reopen it
289-
await conversationListPage.openConversation(userB.fullName);
290-
expect(await conversationPage.isConversationOpen(userB.fullName));
233+
await pages.conversationListPage.openConversation(userB.fullName);
234+
expect(await pages.conversationPage.isConversationOpen(userB.fullName));
291235

292236
// TODO: Bug [WPB-18226] Message is not visible in the conversation after sending it
293237
// await conversationPage.sendMessage('Hello there');
@@ -299,45 +243,45 @@ test('Personal Account Lifecycle', {tag: ['@TC-8638', '@crit-flow']}, async ({pa
299243
});
300244

301245
await test.step('Personal user A blocks personal user B', async () => {
302-
await conversationListPage.clickConversationOptions(userB.fullName);
303-
await conversationListPage.clickBlockConversation();
304-
expect(await blockWarningModal.isModalPresent());
305-
expect(await blockWarningModal.getModalTitle()).toContain(`Block ${userB.fullName}`);
306-
expect(await blockWarningModal.getModalText()).toContain(
246+
await pages.conversationListPage.clickConversationOptions(userB.fullName);
247+
await pages.conversationListPage.clickBlockConversation();
248+
expect(await pages.blockWarningModal.isModalPresent());
249+
expect(await pages.blockWarningModal.getModalTitle()).toContain(`Block ${userB.fullName}`);
250+
expect(await pages.blockWarningModal.getModalText()).toContain(
307251
`${userB.fullName} won’t be able to contact you or add you to group conversations.`,
308252
);
309253

310-
await blockWarningModal.clickBlock();
311-
expect(await conversationListPage.isConversationBlocked(userB.fullName));
254+
await pages.blockWarningModal.clickBlock();
255+
expect(await pages.conversationListPage.isConversationBlocked(userB.fullName));
312256

313257
// [WPB-18093] Backend not returning the blocked 1:1 in conversations list
314258
// When User <Contact> sends message "See this?" to personal MLS conversation <Name>
315259
// Then I do not see text message See this?
316260
});
317261

318262
await test.step('Personal user A opens settings', async () => {
319-
await conversationSidebar.clickPreferencesButton();
263+
await pages.conversationSidebar.clickPreferencesButton();
320264
});
321265

322266
await test.step('Personal User A deletes their account', async () => {
323-
await accountPage.clickDeleteAccountButton();
324-
expect(await deleteAccountModal.isModalPresent());
325-
expect(await deleteAccountModal.getModalTitle()).toContain('Delete account');
326-
expect(await deleteAccountModal.getModalText()).toContain(
267+
await pages.accountPage.clickDeleteAccountButton();
268+
expect(await pages.deleteAccountModal.isModalPresent());
269+
expect(await pages.deleteAccountModal.getModalTitle()).toContain('Delete account');
270+
expect(await pages.deleteAccountModal.getModalText()).toContain(
327271
'We will send you an email. Follow the link to delete your account permanently.',
328272
);
329273

330-
await deleteAccountModal.clickDelete();
274+
await pages.deleteAccountModal.clickDelete();
331275
const url = await api.inbucket.getAccountDeletionURL(userA.email);
332276

333-
const newTab = await page.context().newPage();
334-
await newTab.goto(url);
335-
const deleteAccountPage = new DeleteAccountPage(newTab);
336-
await deleteAccountPage.clickDeleteAccountButton();
337-
expect(await deleteAccountPage.isAccountDeletedHeadlineVisible());
277+
await pages.openNewTab(url, async tab => {
278+
await tab.deleteAccountPage.clickDeleteAccountButton();
279+
expect(await tab.deleteAccountPage.isAccountDeletedHeadlineVisible());
280+
});
338281

339-
await newTab.close();
340-
expect(await welcomePage.getLogoutReasonText()).toContain('You were signed out because your account was deleted');
282+
expect(await pages.welcomePage.getLogoutReasonText()).toContain(
283+
'You were signed out because your account was deleted',
284+
);
341285
});
342286
});
343287

0 commit comments

Comments
 (0)