diff --git a/.eslintignore b/.eslintignore index 23d7f9589..a10b486c8 100644 --- a/.eslintignore +++ b/.eslintignore @@ -9,7 +9,6 @@ mnemonic_languages/** ts/**/*.js **/ts/**/*.js -playwright.config.js preload.js stylesheets/dist/ compiled.d.ts diff --git a/.prettierignore b/.prettierignore index ea50e9191..1319d4b6f 100644 --- a/.prettierignore +++ b/.prettierignore @@ -17,7 +17,6 @@ ts/test/automation/notes # Third-party files node_modules/** mnemonic_languages/** -playwright.config.js .vscode/ # Managed by package manager (`yarn`/`npm`): diff --git a/.yarnclean b/.yarnclean index d502bb8db..8cd6c20d9 100644 --- a/.yarnclean +++ b/.yarnclean @@ -3,7 +3,6 @@ __tests__ test tests powered-test -!@playwright/test/** # asset directories docs diff --git a/package.json b/package.json index ac0e63e8f..454bf2434 100644 --- a/package.json +++ b/package.json @@ -45,9 +45,7 @@ "clean": "rimraf 'ts/**/*.js' 'ts/*.js' 'ts/*.js.map' 'ts/**/*.js.map' && rimraf tsconfig.tsbuildinfo;", "lint-full": "yarn format-full && eslint .", "format-full": "prettier --list-different --write \"*.{css,js,json,scss,ts,tsx}\" \"./**/*.{css,js,json,scss,ts,tsx}\"", - "integration-test": "npx playwright test", "start-prod-test": "cross-env NODE_ENV=production NODE_APP_INSTANCE=$MULTI electron .", - "integration-test-snapshots": "npx playwright test -g 'profile picture' --update-snapshots", "test": "mocha -r jsdom-global/register --recursive --exit --timeout 10000 \"./ts/test/**/*_test.js\"", "build-release": "run-script-os", "build-release-non-linux": "yarn build-everything && cross-env SIGNAL_ENV=production electron-builder --config.extraMetadata.environment=production --publish=never --config.directories.output=release", @@ -135,7 +133,6 @@ }, "devDependencies": { "@electron/notarize": "^2.1.0", - "@playwright/test": "1.16.3", "@types/backbone": "1.4.2", "@types/blueimp-load-image": "5.14.4", "@types/buffer-crc32": "^0.2.0", @@ -191,7 +188,6 @@ "mocha": "10.0.0", "node-loader": "^2.0.0", "patch-package": "^6.4.7", - "playwright": "1.16.3", "postinstall-prepare": "^1.0.1", "prettier": "1.19.0", "protobufjs-cli": "^1.1.1", diff --git a/playwright.config.ts b/playwright.config.ts deleted file mode 100644 index e5f200855..000000000 --- a/playwright.config.ts +++ /dev/null @@ -1,21 +0,0 @@ -/* eslint-disable import/no-extraneous-dependencies */ -/* eslint-disable import/no-import-module-exports */ -import { PlaywrightTestConfig } from '@playwright/test'; -import { toNumber } from 'lodash'; - -const config: PlaywrightTestConfig = { - timeout: 350000, - globalTimeout: 6000000, - reporter: 'list', - testDir: './ts/test/automation', - testIgnore: '*.js', - outputDir: './ts/test/automation/test-results', - retries: process.env.PLAYWRIGHT_RETRIES_COUNT - ? toNumber(process.env.PLAYWRIGHT_RETRIES_COUNT) - : 1, - - workers: toNumber(process.env.PLAYWRIGHT_WORKER_COUNT) || 1, - reportSlowTests: null, -}; - -module.exports = config; diff --git a/ts/test/automation/call_checks.spec.ts b/ts/test/automation/call_checks.spec.ts deleted file mode 100644 index 8285de6ba..000000000 --- a/ts/test/automation/call_checks.spec.ts +++ /dev/null @@ -1,25 +0,0 @@ -import { sleepFor } from '../../session/utils/Promise'; -import { newUser } from './setup/new_user'; -import { createContact } from './utilities/create_contact'; -import { clickOnMatchingText, clickOnTestIdWithText } from './utilities/utils'; -import { sessionTestTwoWindows } from './setup/sessionTest'; - -sessionTestTwoWindows('Voice calls', async ([windowA, windowB]) => { - const [userA, userB] = await Promise.all([newUser(windowA, 'Alice'), newUser(windowB, 'Bob')]); - - await createContact(windowA, windowB, userA, userB); - await clickOnTestIdWithText(windowA, 'call-button'); - await clickOnTestIdWithText(windowA, 'session-toast'); - await clickOnTestIdWithText(windowA, 'enable-calls'); - await clickOnTestIdWithText(windowA, 'session-confirm-ok-button'); - await clickOnTestIdWithText(windowA, 'message-section'); - await clickOnTestIdWithText(windowA, 'module-conversation__user__profile-name', userB.userName); - await clickOnTestIdWithText(windowA, 'call-button'); - // Enable calls in window B - await clickOnTestIdWithText(windowB, 'session-toast'); - await clickOnTestIdWithText(windowB, 'enable-calls'); - await clickOnTestIdWithText(windowB, 'session-confirm-ok-button'); - await clickOnMatchingText(windowB, 'Accept'); - await sleepFor(5000); - await clickOnTestIdWithText(windowA, 'end-call'); -}); diff --git a/ts/test/automation/change_avatar.spec.ts-snapshots/avatar-updated-blue-darwin.jpeg b/ts/test/automation/change_avatar.spec.ts-snapshots/avatar-updated-blue-darwin.jpeg deleted file mode 100644 index 9bb7cffef..000000000 Binary files a/ts/test/automation/change_avatar.spec.ts-snapshots/avatar-updated-blue-darwin.jpeg and /dev/null differ diff --git a/ts/test/automation/change_avatar.spec.ts-snapshots/avatar-updated-blue-linux.jpeg b/ts/test/automation/change_avatar.spec.ts-snapshots/avatar-updated-blue-linux.jpeg deleted file mode 100644 index c45feae52..000000000 Binary files a/ts/test/automation/change_avatar.spec.ts-snapshots/avatar-updated-blue-linux.jpeg and /dev/null differ diff --git a/ts/test/automation/create_user.spec.ts b/ts/test/automation/create_user.spec.ts deleted file mode 100644 index f44e0ad8b..000000000 --- a/ts/test/automation/create_user.spec.ts +++ /dev/null @@ -1,30 +0,0 @@ -import { sleepFor } from '../../session/utils/Promise'; -import { newUser } from './setup/new_user'; -import { - clickOnMatchingText, - clickOnTestIdWithText, - waitForTestIdWithText -} from './utilities/utils'; -import { sessionTestOneWindow } from './setup/sessionTest'; - -sessionTestOneWindow('Create User', async ([window]) => { - // // Create User - const userA = await newUser(window, 'userA'); - // Open profile tab - await clickOnTestIdWithText(window, 'leftpane-primary-avatar'); - await sleepFor(100, true); - // check username matches - await waitForTestIdWithText(window, 'your-profile-name', userA.userName); - // check session id matches - await waitForTestIdWithText(window, 'your-session-id', userA.sessionid); - - // exit profile module - await window.click('.session-icon-button.small'); - // go to settings section - await clickOnTestIdWithText(window, 'settings-section'); - // check recovery phrase matches - await clickOnMatchingText(window, 'Recovery Phrase'); - await waitForTestIdWithText(window, 'recovery-phrase-seed-modal', userA.recoveryPhrase); - // Exit profile module - await window.click('.session-icon-button.small'); -}); diff --git a/ts/test/automation/delete_account.spec.ts b/ts/test/automation/delete_account.spec.ts deleted file mode 100644 index 9fed05b62..000000000 --- a/ts/test/automation/delete_account.spec.ts +++ /dev/null @@ -1,124 +0,0 @@ -import { test } from '@playwright/test'; -import { sleepFor } from '../../session/utils/Promise'; -import { beforeAllClean, forceCloseAllWindows } from './setup/beforeEach'; -import { newUser } from './setup/new_user'; -import { openApp } from './setup/open'; -import { createContact } from './utilities/create_contact'; -import { sendNewMessage } from './utilities/send_message'; -import { - clickOnElement, - clickOnMatchingText, - clickOnTestIdWithText, - hasElementBeenDeleted, - hasTextElementBeenDeleted, - typeIntoInput, - waitForElement, - waitForLoadingAnimationToFinish, -} from './utilities/utils'; - -test.beforeEach(beforeAllClean); - -test('Delete account from swarm', async () => { - const [windowA, windowB] = await openApp(2); // not using sessionTest here as we need to close and reopen one of the window - const [userA, userB] = await Promise.all([newUser(windowA, 'Alice'), newUser(windowB, 'Bob')]); - const testMessage = `${userA.userName} to ${userB.userName}`; - const testReply = `${userB.userName} to ${userA.userName}`; - // Create contact and send new message - await Promise.all([ - sendNewMessage(windowA, userB.sessionid, testMessage), - sendNewMessage(windowB, userA.sessionid, testReply), - ]); - // Delete all data from device - // Click on settings tab - await clickOnTestIdWithText(windowA, 'settings-section'); - // Click on clear all data - await clickOnTestIdWithText(windowA, 'clear-data-settings-menu-item', 'Clear Data'); - // Select entire account - await clickOnTestIdWithText(windowA, 'label-device_and_network', 'Clear Device and Network'); - // Confirm deletion by clicking Clear, twice - await clickOnMatchingText(windowA, 'Clear'); - await clickOnMatchingText(windowA, 'Clear'); - await waitForLoadingAnimationToFinish(windowA, 'loading-spinner'); - // await windowA.waitForTimeout(7500); - // Wait for window to close and reopen - await sleepFor(10000, true); - // await windowA.close(); - const restoringWindows = await openApp(1); // not using sessionTest here as we need to close and reopen one of the window - const [restoringWindow] = restoringWindows; - // Sign in with deleted account and check that nothing restores - await clickOnTestIdWithText(restoringWindow, 'restore-using-recovery', 'Restore your account'); - // Fill in recovery phrase - await typeIntoInput(restoringWindow, 'recovery-phrase-input', userA.recoveryPhrase); - // Enter display name - await typeIntoInput(restoringWindow, 'display-name-input', userA.userName); - // Click continue - await clickOnTestIdWithText(restoringWindow, 'continue-session-button'); - console.log('sleeping for 20000ms'); - await sleepFor(20000); // just to allow any messages from our swarm to show up - - // Need to verify that no conversation is found at all - - await hasElementBeenDeleted(restoringWindow, 'data-testid', 'conversation-list-item'); - - await clickOnTestIdWithText(restoringWindow, 'new-conversation-button'); // Expect contacts list to be empty - - await hasTextElementBeenDeleted(restoringWindow, 'contact'); - await forceCloseAllWindows(restoringWindows); -}); - -test('Delete account from device', async () => { - const [windowA, windowB] = await openApp(2); - const [userA, userB] = await Promise.all([newUser(windowA, 'Alice'), newUser(windowB, 'Bob')]); - // Create contact and send new message - await createContact(windowA, windowB, userA, userB); - // Delete all data from device - // Click on settings tab - await clickOnTestIdWithText(windowA, 'settings-section'); - // Click on clear all data - await clickOnTestIdWithText(windowA, 'clear-data-settings-menu-item', 'Clear Data'); - // Keep 'Clear Device only' selection - // Confirm deletion by clicking Clear, twice - await clickOnMatchingText(windowA, 'Clear'); - await clickOnMatchingText(windowA, 'Clear'); - await waitForLoadingAnimationToFinish(windowA, 'loading-spinner'); - await windowA.waitForTimeout(7500); - // Wait for window to close and reopen - await sleepFor(10000, true); - // await windowA.close(); - const restoringWindows = await openApp(1); - const [restoringWindow] = restoringWindows; - // Sign in with deleted account and check that nothing restores - await clickOnTestIdWithText(restoringWindow, 'restore-using-recovery', 'Restore your account'); - // Fill in recovery phrase - await typeIntoInput(restoringWindow, 'recovery-phrase-input', userA.recoveryPhrase); - // Enter display name - await typeIntoInput(restoringWindow, 'display-name-input', userA.userName); - // Click continue - await clickOnTestIdWithText(restoringWindow, 'continue-session-button'); - console.log('sleeping for 2000ms'); - await sleepFor(2000); // just to allow any messages from our swarm to show up - // Check if message from user B is restored - await waitForElement( - restoringWindow, - 'data-testid', - 'module-conversation__user__profile-name', - 1000, - userB.userName - ); - // Check if contact is available in contacts section - await clickOnElement(restoringWindow, 'data-testid', 'new-conversation-button'); - await waitForElement( - restoringWindow, - 'data-testid', - 'module-conversation__user__profile-name', - 1000, - userB.userName - ); - - await hasElementBeenDeleted(restoringWindow, 'data-testid', 'conversation-list-item'); - - await clickOnTestIdWithText(restoringWindow, 'new-conversation-button'); // Expect contacts list to be empty - - await hasTextElementBeenDeleted(restoringWindow, 'contact'); - await forceCloseAllWindows(restoringWindows); -}); diff --git a/ts/test/automation/disappearing_messages.spec.ts b/ts/test/automation/disappearing_messages.spec.ts deleted file mode 100644 index 4a08b1c31..000000000 --- a/ts/test/automation/disappearing_messages.spec.ts +++ /dev/null @@ -1,63 +0,0 @@ -import { sleepFor } from '../../session/utils/Promise'; -import { newUser } from './setup/new_user'; -import { sessionTestTwoWindows } from './setup/sessionTest'; -import { createContact } from './utilities/create_contact'; -import { sendMessage } from './utilities/message'; -import { - clickOnTestIdWithText, - hasTextElementBeenDeleted, - waitForMatchingText, - waitForTestIdWithText, -} from './utilities/utils'; - -const testMessage = 'Test-Message- (A -> B) '; -const sentMessage = `${testMessage}${Date.now()}`; - -sessionTestTwoWindows('Disappearing messages', async ([windowA, windowB]) => { - // Open App - // Create User - const [userA, userB] = await Promise.all([newUser(windowA, 'Alice'), newUser(windowB, 'Bob')]); - // Create Contact - await createContact(windowA, windowB, userA, userB); - // Need to wait for contact approval - await sleepFor(5000); - // Click on user's avatar to open conversation options - await clickOnTestIdWithText(windowA, 'conversation-options-avatar'); - await waitForMatchingText(windowA, 'Your message request has been accepted'); - // Select disappearing messages drop down - await clickOnTestIdWithText(windowA, 'disappearing-messages-dropdown', 'Disappearing messages'); - // Select 5 seconds - await sleepFor(200); - await clickOnTestIdWithText(windowA, 'dropdownitem-5-seconds', '5 seconds'); - // Click chevron to close menu - await clickOnTestIdWithText(windowA, 'back-button-conversation-options'); - // Check config message - await waitForTestIdWithText( - windowA, - 'control-message', - 'You set the disappearing message timer to 5 seconds' - ); - await waitForTestIdWithText( - windowB, - 'control-message', - `${userA.userName} set the disappearing message timer to 5 seconds` - ); - await sleepFor(500); - // Check top right hand corner indicator - await waitForTestIdWithText(windowA, 'disappearing-messages-indicator', '5 seconds'); - // Send message - await sendMessage(windowA, sentMessage); - // Check timer is functioning - await sleepFor(6000); - // Verify message is deleted - await hasTextElementBeenDeleted(windowA, sentMessage, 3000); - // focus window B - await windowA.close(); - await windowB.bringToFront(); - await clickOnTestIdWithText( - windowB, - 'control-message', - `${userA.userName} set the disappearing message timer to 5 seconds` - ); - await hasTextElementBeenDeleted(windowB, sentMessage, 5000); -}); diff --git a/ts/test/automation/fixtures/test-file.pdf b/ts/test/automation/fixtures/test-file.pdf deleted file mode 100644 index 82b84599a..000000000 Binary files a/ts/test/automation/fixtures/test-file.pdf and /dev/null differ diff --git a/ts/test/automation/fixtures/test-gif.gif b/ts/test/automation/fixtures/test-gif.gif deleted file mode 100644 index f2f50fa79..000000000 Binary files a/ts/test/automation/fixtures/test-gif.gif and /dev/null differ diff --git a/ts/test/automation/fixtures/test-image.png b/ts/test/automation/fixtures/test-image.png deleted file mode 100644 index 79b0dab07..000000000 Binary files a/ts/test/automation/fixtures/test-image.png and /dev/null differ diff --git a/ts/test/automation/fixtures/test-video.mp4 b/ts/test/automation/fixtures/test-video.mp4 deleted file mode 100644 index ed139d6d5..000000000 Binary files a/ts/test/automation/fixtures/test-video.mp4 and /dev/null differ diff --git a/ts/test/automation/group_testing.spec.ts b/ts/test/automation/group_testing.spec.ts deleted file mode 100644 index b10fda3da..000000000 --- a/ts/test/automation/group_testing.spec.ts +++ /dev/null @@ -1,162 +0,0 @@ -import { expect } from '@playwright/test'; -import { createGroup } from './setup/create_group'; -import { renameGroup } from './utilities/rename_group'; -import { - clickOnElement, - clickOnMatchingText, - clickOnTestIdWithText, - typeIntoInput, - waitForControlMessageWithText, - waitForMatchingText, - waitForTestIdWithText, -} from './utilities/utils'; -// import { leaveGroup } from './utilities/leave_group'; -import { sleepFor } from '../../session/utils/Promise'; -import { newUser } from './setup/new_user'; -import { sessionTestFourWindows, sessionTestThreeWindows } from './setup/sessionTest'; -import { createContact } from './utilities/create_contact'; -import { leaveGroup } from './utilities/leave_group'; - -sessionTestThreeWindows('Create group', async ([windowA, windowB, windowC]) => { - // Open Electron - const [userA, userB, userC] = await Promise.all([ - newUser(windowA, 'Alice'), - newUser(windowB, 'Bob'), - newUser(windowC, 'Chloe'), - ]); - - await createGroup('Tiny Bubble Gang', userA, windowA, userB, windowB, userC, windowC); - // Check config messages in all windows - await sleepFor(1000); - // await waitForTestIdWithText(windowA, 'control-message'); -}); - -sessionTestFourWindows('Add contact to group', async ([windowA, windowB, windowC, windowD]) => { - const [userA, userB, userC, userD] = await Promise.all([ - newUser(windowA, 'Alice'), - newUser(windowB, 'Bob'), - newUser(windowC, 'Chloe'), - newUser(windowD, 'Dracula'), - ]); - const testGroup = await createGroup( - 'Tiny Bubble Gang', - userA, - windowA, - userB, - windowB, - userC, - windowC - ); - // Check config messages in all windows - await sleepFor(1000); - await createContact(windowA, windowD, userA, userD); - await clickOnTestIdWithText( - windowA, - 'module-conversation__user__profile-name', - testGroup.userName - ); - await clickOnElement(windowA, 'data-testid', 'conversation-options-avatar'); - await clickOnElement(windowA, 'data-testid', 'add-user-button'); - // Waiting for animation of right panel to appear - await sleepFor(1000); - await clickOnMatchingText(windowA, userD.userName); - await clickOnMatchingText(windowA, 'OK'); - await waitForControlMessageWithText(windowA, `"${userD.userName}" joined the group.`); - await waitForControlMessageWithText(windowB, `${userD.sessionid} joined the group.`); - await waitForControlMessageWithText(windowC, `${userD.sessionid} joined the group.`); - await clickOnTestIdWithText( - windowD, - 'module-conversation__user__profile-name', - testGroup.userName - ); - const emptyStateGroupText = `You have no messages from ${testGroup.userName}. Send a message to start the conversation!`; - await waitForTestIdWithText(windowD, 'empty-conversation-notification', emptyStateGroupText); -}); - -sessionTestThreeWindows('Change group name', async ([windowA, windowB, windowC]) => { - const [userA, userB, userC] = await Promise.all([ - newUser(windowA, 'Alice'), - newUser(windowB, 'Bob'), - newUser(windowC, 'Chloe'), - ]); - const newGroupName = 'Otter lovers'; - const group = await createGroup( - 'Tiny Bubble Gang', - userA, - windowA, - userB, - windowB, - userC, - windowC - ); - // Change the name of the group and check that it syncs to all devices (config messages) - // Click on already created group - // Check that renaming a group is working - await renameGroup(windowA, group.userName, newGroupName); - // Check config message in window B for group name change - await clickOnMatchingText(windowB, newGroupName); - await waitForMatchingText(windowB, `Group name is now '${newGroupName}'.`); - // Click on conversation options - // Check to see that you can't change group name to empty string - // Click on edit group name - await clickOnMatchingText(windowA, 'Edit group name'); - await windowA.fill('.profile-name-input', ' '); - await windowA.keyboard.press('Enter'); - const errorMessage = windowA.locator('.error-message'); - await expect(errorMessage).toContainText('Please enter a group name'); - await clickOnMatchingText(windowA, 'Cancel'); - await clickOnTestIdWithText(windowA, 'back-button-conversation-options'); -}); - -sessionTestThreeWindows('Test mentions', async ([windowA, windowB, windowC]) => { - const [userA, userB, userC] = await Promise.all([ - newUser(windowA, 'Alice'), - newUser(windowB, 'Bob'), - newUser(windowC, 'Chloe'), - ]); - const group = await createGroup( - 'Tiny Bubble Gang', - userA, - windowA, - userB, - windowB, - userC, - windowC - ); - - // in windowA we should be able to mentions userB and userC - - await clickOnTestIdWithText(windowA, 'module-conversation__user__profile-name', group.userName); - await typeIntoInput(windowA, 'message-input-text-area', '@'); - // does 'message-input-text-area' have aria-expanded: true when @ is typed into input - await waitForTestIdWithText(windowA, 'mentions-popup-row'); - await waitForTestIdWithText(windowA, 'mentions-popup-row', userB.userName); - await waitForTestIdWithText(windowA, 'mentions-popup-row', userC.userName); - - // in windowB we should be able to mentions userA and userC - await clickOnTestIdWithText(windowB, 'module-conversation__user__profile-name', group.userName); - await typeIntoInput(windowB, 'message-input-text-area', '@'); - // does 'message-input-text-area' have aria-expanded: true when @ is typed into input - await waitForTestIdWithText(windowB, 'mentions-popup-row'); - await waitForTestIdWithText(windowB, 'mentions-popup-row', userA.userName); - await waitForTestIdWithText(windowB, 'mentions-popup-row', userC.userName); - - // in windowC we should be able to mentions userA and userB - await clickOnTestIdWithText(windowC, 'module-conversation__user__profile-name', group.userName); - await typeIntoInput(windowC, 'message-input-text-area', '@'); - // does 'message-input-text-area' have aria-expanded: true when @ is typed into input - await waitForTestIdWithText(windowC, 'mentions-popup-row'); - await waitForTestIdWithText(windowC, 'mentions-popup-row', userA.userName); - await waitForTestIdWithText(windowC, 'mentions-popup-row', userB.userName); -}); - -sessionTestThreeWindows('Leave group', async ([windowA, windowB, windowC]) => { - const [userA, userB, userC] = await Promise.all([ - newUser(windowA, 'Alice'), - newUser(windowB, 'Bob'), - newUser(windowC, 'Chloe'), - ]); - await createGroup('Tiny Bubble Gang', userA, windowA, userB, windowB, userC, windowC); - - await leaveGroup(windowC); -}); diff --git a/ts/test/automation/group_upkeep.spec.ts b/ts/test/automation/group_upkeep.spec.ts deleted file mode 100644 index 281904233..000000000 --- a/ts/test/automation/group_upkeep.spec.ts +++ /dev/null @@ -1,63 +0,0 @@ -// FIXME enable this test again once we fixed it -// sessionTestFiveWindows( -// 'Group upkeep - should be skipped', -// async ([windowA, windowB, windowC, windowD, windowE]) => { -// await Promise.all([ -// logIn(windowA, userA.recoveryPhrase), -// logIn(windowB, userB.recoveryPhrase), -// logIn(windowC, userC.recoveryPhrase), -// logIn(windowD, userD.recoveryPhrase), -// logIn(windowE, userE.recoveryPhrase), -// ]); -// // Send message from test users to all of it's contacts to maintain contact status - -// // Send message from user A to Whale(TC1) -// await sendNewMessage( -// windowA, -// userB.sessionid, -// `${userA.userName} -> ${userB.userName}: ${Date.now()}` -// ); -// // Send message from Whale to user A -// await sendNewMessage( -// windowB, -// userA.sessionid, -// `${userB.userName} -> ${userA.userName} : ${Date.now()}` -// ); -// // Send message from user A to Dragon(TC2) -// await sendNewMessage( -// windowA, -// userC.sessionid, -// `${userA.userName} -> ${userC.userName}: ${Date.now()}` -// ); -// // Send message from Dragon to user A -// await sendNewMessage( -// windowC, -// userA.sessionid, -// `${userC.userName} -> ${userA.userName} : ${Date.now()}` -// ); -// // Send message from user A to Fish(TC3) -// await sendNewMessage( -// windowA, -// userD.sessionid, -// `${userA.userName} -> ${userD.userName}: ${Date.now()}` -// ); -// // Send message from Fish to user A -// await sendNewMessage( -// windowD, -// userA.sessionid, -// `${userD.userName} -> ${userA.userName} : ${Date.now()}` -// ); -// // Send message from user A to Gopher(TC4) -// await sendNewMessage( -// windowA, -// userE.sessionid, -// `${userA.userName} -> ${userD.userName}: ${Date.now()}` -// ); -// // Send message from Gopher to user A -// await sendNewMessage( -// windowE, -// userA.sessionid, -// `${userD.userName} -> ${userA.userName} : ${Date.now()}` -// ); -// } -// ); diff --git a/ts/test/automation/linked_device_group.spec.ts b/ts/test/automation/linked_device_group.spec.ts deleted file mode 100644 index 09ee6984d..000000000 --- a/ts/test/automation/linked_device_group.spec.ts +++ /dev/null @@ -1,64 +0,0 @@ -import { sleepFor } from '../../session/utils/Promise'; -import { createGroup } from './setup/create_group'; -import { newUser } from './setup/new_user'; -import { sessionTestThreeWindows } from './setup/sessionTest'; -import { leaveGroup } from './utilities/leave_group'; -import { linkedDevice } from './utilities/linked_device'; -import { - clickOnTestIdWithText, - waitForControlMessageWithText, - waitForTestIdWithText, -} from './utilities/utils'; - -sessionTestThreeWindows('Check group and name syncs', async ([windowA, windowC, windowD]) => { - const [userA, userB, userC] = await Promise.all([ - newUser(windowA, 'Alice'), - newUser(windowC, 'Bob'), - newUser(windowD, 'Chloe'), - ]); - const [windowB] = await linkedDevice(userA.recoveryPhrase); - - const group = await createGroup( - 'Tiny Bubble Gang', - userA, - windowA, - userB, - windowC, - userC, - windowD - ); - // Check group conversation is in conversation list - await waitForTestIdWithText(windowB, 'module-conversation__user__profile-name', group.userName); -}); - -sessionTestThreeWindows('Leaving group syncs', async ([windowA, windowC, windowD]) => { - const [userA, userB, userC] = await Promise.all([ - newUser(windowA, 'Alice'), - newUser(windowC, 'Bob'), - newUser(windowD, 'Chloe'), - ]); - const [windowB] = await linkedDevice(userA.recoveryPhrase); - - const group = await createGroup( - 'Tiny Bubble Gang', - userA, - windowA, - userB, - windowC, - userC, - windowD - ); - // Check group conversation is in conversation list - await waitForTestIdWithText(windowB, 'module-conversation__user__profile-name', group.userName); - // User C to leave group - await leaveGroup(windowD); - // Check for user A - await sleepFor(1000); - await clickOnTestIdWithText(windowA, 'module-conversation__user__profile-name', group.userName); - await waitForControlMessageWithText(windowA, `"${userC.userName}" has left the group.`); - // Check for linked device (userA) - await clickOnTestIdWithText(windowB, 'module-conversation__user__profile-name', group.userName); - await waitForControlMessageWithText(windowB, `"${userC.userName}" has left the group.`); - // Check for user B - await waitForControlMessageWithText(windowC, `"${userC.userName}" has left the group.`); -}); diff --git a/ts/test/automation/linked_device_requests.spec.ts b/ts/test/automation/linked_device_requests.spec.ts deleted file mode 100644 index 4f63ce95d..000000000 --- a/ts/test/automation/linked_device_requests.spec.ts +++ /dev/null @@ -1,54 +0,0 @@ -import { newUser } from './setup/new_user'; -import { sessionTestTwoWindows } from './setup/sessionTest'; -import { linkedDevice } from './utilities/linked_device'; -import { sendMessage } from './utilities/message'; -import { sendNewMessage } from './utilities/send_message'; -import { - clickOnTestIdWithText, - waitForMatchingText, - waitForTestIdWithText, - waitForTextMessage, -} from './utilities/utils'; - -sessionTestTwoWindows('Accept request syncs', async ([windowA, windowB]) => { - const [userA, userB] = await Promise.all([newUser(windowA, 'Alice'), newUser(windowB, 'Bob')]); - const [windowC] = await linkedDevice(userB.recoveryPhrase); - - const testMessage = `${userA.userName} sending message request to ${userB.userName}`; - const testReply = `${userB.userName} accepting message request from ${userA.userName}`; - await sendNewMessage(windowA, userB.sessionid, testMessage); - // Accept request in windowB - await clickOnTestIdWithText(windowB, 'message-request-banner'); - await clickOnTestIdWithText(windowC, 'message-request-banner'); - await clickOnTestIdWithText(windowB, 'module-conversation__user__profile-name', userA.userName); - await clickOnTestIdWithText(windowB, 'accept-message-request'); - await waitForTestIdWithText( - windowB, - 'control-message', - `You have accepted ${userA.userName}'s message request` - ); - await waitForMatchingText(windowB, 'No pending message requests'); - await waitForMatchingText(windowC, 'No pending message requests'); - await sendMessage(windowB, testReply); - await waitForTextMessage(windowA, testReply); - await clickOnTestIdWithText(windowC, 'new-conversation-button'); - await waitForTestIdWithText(windowC, 'module-conversation__user__profile-name', userA.userName); -}); - -sessionTestTwoWindows('Decline request syncs', async ([windowA, windowB]) => { - const [userA, userB] = await Promise.all([newUser(windowA, 'Alice'), newUser(windowB, 'Bob')]); - const [windowC] = await linkedDevice(userB.recoveryPhrase); - - const testMessage = `${userA.userName} sending message request to ${userB.userName}`; - await sendNewMessage(windowA, userB.sessionid, testMessage); - // Decline request in windowB - await clickOnTestIdWithText(windowB, 'message-request-banner'); - await clickOnTestIdWithText(windowB, 'module-conversation__user__profile-name', userA.userName); - await clickOnTestIdWithText(windowC, 'message-request-banner'); - await waitForTestIdWithText(windowC, 'module-conversation__user__profile-name', userA.userName); - await clickOnTestIdWithText(windowB, 'decline-message-request'); - await clickOnTestIdWithText(windowB, 'session-confirm-ok-button', 'Decline'); - - await waitForMatchingText(windowB, 'No pending message requests'); - await waitForMatchingText(windowC, 'No pending message requests'); -}); diff --git a/ts/test/automation/linked_device_user.spec.ts b/ts/test/automation/linked_device_user.spec.ts deleted file mode 100644 index f1c931f7a..000000000 --- a/ts/test/automation/linked_device_user.spec.ts +++ /dev/null @@ -1,183 +0,0 @@ -import { expect, Page, test } from '@playwright/test'; -import { sleepFor } from '../../session/utils/Promise'; -import { beforeAllClean, forceCloseAllWindows } from './setup/beforeEach'; -import { newUser } from './setup/new_user'; -import { openApp } from './setup/open'; -import { createContact } from './utilities/create_contact'; -import { linkedDevice } from './utilities/linked_device'; -import { sendMessage } from './utilities/message'; -import { - clickOnElement, - clickOnMatchingText, - clickOnTestIdWithText, - hasTextElementBeenDeleted, - typeIntoInput, - waitForMatchingPlaceholder, - waitForMatchingText, - waitForTestIdWithText, - waitForTextMessage, -} from './utilities/utils'; - -const windows: Array = []; -test.beforeEach(beforeAllClean); - -test.afterEach(() => forceCloseAllWindows(windows)); - -test('Link a device', async () => { - const [windowA] = await openApp(1); // not using sessionTest here as we need to close and reopen one of the window - const userA = await newUser(windowA, 'Alice'); - const [windowB] = await linkedDevice(userA.recoveryPhrase); // not using sessionTest here as we need to close and reopen one of the window - await clickOnTestIdWithText(windowA, 'leftpane-primary-avatar'); - // Verify Username - await waitForTestIdWithText(windowA, 'your-profile-name', userA.userName); - // Verify Session ID - await waitForTestIdWithText(windowA, 'your-session-id', userA.sessionid); - // exit profile module - await clickOnTestIdWithText(windowA, 'modal-close-button'); - // You're almost finished isn't displayed - const errorDesc = 'Should not be found'; - try { - const elemShouldNotBeFound = windowB.locator('[data-testid=reveal-recovery-phrase]'); - if (elemShouldNotBeFound) { - console.error('Continue to save recovery phrase not found, excellent news'); - throw new Error(errorDesc); - } - } catch (e) { - if (e.message !== errorDesc) { - // this is NOT ok - throw e; - } - } -}); - -test('Changed username syncs', async () => { - const [windowA] = await openApp(1); - const userA = await newUser(windowA, 'Alice'); - const [windowB] = await linkedDevice(userA.recoveryPhrase); - const newUsername = 'Tiny bubble'; - await clickOnTestIdWithText(windowA, 'leftpane-primary-avatar'); - // Click on pencil icon - await clickOnTestIdWithText(windowA, 'edit-profile-icon'); - // Replace old username with new username - await typeIntoInput(windowA, 'profile-name-input', newUsername); - // Press enter to confirm change - await clickOnElement(windowA, 'data-testid', 'save-button-profile-update'); - // Wait for loading animation - // Check username change in window B - // Click on profile settings in window B - await clickOnTestIdWithText(windowB, 'leftpane-primary-avatar'); - // Verify username has changed to new username - await waitForTestIdWithText(windowB, 'your-profile-name', newUsername); -}); - -test('Profile picture syncs', async () => { - const [windowA] = await openApp(1); // not using sessionTest here as we need to close and reopen one of the window - const userA = await newUser(windowA, 'Alice'); - const [windowB] = await linkedDevice(userA.recoveryPhrase); // not using sessionTest here as we need to close and reopen one of the window - await clickOnTestIdWithText(windowA, 'leftpane-primary-avatar'); - // Click on current profile picture - await waitForTestIdWithText(windowA, 'copy-button-profile-update', 'Copy'); - - await clickOnTestIdWithText(windowA, 'image-upload-section'); - await clickOnTestIdWithText(windowA, 'save-button-profile-update'); - await waitForTestIdWithText(windowA, 'loading-spinner'); - - await waitForTestIdWithText(windowA, 'copy-button-profile-update', 'Copy'); - await clickOnTestIdWithText(windowA, 'modal-close-button'); - // TODO this test should retry a few times for the avatar to match - await sleepFor(500, true); - const leftpaneAvatarContainer = await waitForTestIdWithText(windowB, 'leftpane-primary-avatar'); - await sleepFor(500, true); - const screenshot = await leftpaneAvatarContainer.screenshot({ - type: 'jpeg', - // path: 'avatar-updated-blue', - }); - expect(screenshot).toMatchSnapshot({ name: 'avatar-updated-blue.jpeg' }); -}); - -test('Contacts syncs', async () => { - const [windowA, windowC] = await openApp(2); // not using sessionTest here as we need to close and reopen one of the window - const [userA, userB] = await Promise.all([newUser(windowA, 'Alice'), newUser(windowC, 'Bob')]); - const [windowB] = await linkedDevice(userA.recoveryPhrase); // not using sessionTest here as we need to close and reopen one of the window - await createContact(windowA, windowC, userA, userB); - // linked device (windowB) - await waitForTestIdWithText(windowB, 'module-conversation__user__profile-name', userB.userName); - console.info('Contacts correctly synced'); -}); - -test('Deleted message syncs', async () => { - const [windowA, windowC] = await openApp(2); - const [userA, userB] = await Promise.all([newUser(windowA, 'Alice'), newUser(windowC, 'Bob')]); - const [windowB] = await linkedDevice(userA.recoveryPhrase); - const deletedMessage = 'Testing deletion functionality for linked device'; - await createContact(windowA, windowC, userA, userB); - await sendMessage(windowA, deletedMessage); - // Navigate to conversation on linked device and for message from user A to user B - await clickOnTestIdWithText(windowB, 'module-conversation__user__profile-name', userB.userName); - await waitForTextMessage(windowB, deletedMessage); - await waitForTextMessage(windowC, deletedMessage); - await clickOnTestIdWithText(windowA, 'control-message', deletedMessage, true); - await clickOnMatchingText(windowA, 'Delete just for me'); - await clickOnMatchingText(windowA, 'Delete'); - await waitForTestIdWithText(windowA, 'session-toast', 'Deleted'); - await hasTextElementBeenDeleted(windowA, deletedMessage, 1000); - // linked device for deleted message - // Waiting for message to be removed - await sleepFor(5000); - await hasTextElementBeenDeleted(windowB, deletedMessage, 1000); - // Still should exist for user B - await waitForMatchingText(windowC, deletedMessage); -}); - -test('Unsent message syncs', async () => { - const [windowA, windowC] = await openApp(2); - const [userA, userB] = await Promise.all([newUser(windowA, 'Alice'), newUser(windowC, 'Bob')]); - const [windowB] = await linkedDevice(userA.recoveryPhrase); - const unsentMessage = 'Testing unsending functionality for linked device'; - await createContact(windowA, windowC, userA, userB); - await sendMessage(windowA, unsentMessage); - // Navigate to conversation on linked device and for message from user A to user B - await clickOnTestIdWithText(windowB, 'module-conversation__user__profile-name', userB.userName); - await waitForTextMessage(windowB, unsentMessage); - await waitForTextMessage(windowC, unsentMessage); - await clickOnTestIdWithText(windowA, 'control-message', unsentMessage, true); - await clickOnMatchingText(windowA, 'Delete for everyone'); - await clickOnElement(windowA, 'data-testid', 'session-confirm-ok-button'); - await waitForTestIdWithText(windowA, 'session-toast', 'Deleted'); - await hasTextElementBeenDeleted(windowA, unsentMessage, 1000); - await waitForMatchingText(windowC, 'This message has been deleted'); - // linked device for deleted message - await hasTextElementBeenDeleted(windowB, unsentMessage, 1000); -}); - -test('Blocked user syncs', async () => { - const [windowA, windowC] = await openApp(2); - const [userA, userB] = await Promise.all([newUser(windowA, 'Alice'), newUser(windowC, 'Bob')]); - const [windowB] = await linkedDevice(userA.recoveryPhrase); - const testMessage = 'Testing blocking functionality for linked device'; - - await createContact(windowA, windowC, userA, userB); - await sendMessage(windowA, testMessage); - // Navigate to conversation on linked device and check for message from user A to user B - await clickOnTestIdWithText(windowB, 'module-conversation__user__profile-name', userB.userName); - await clickOnElement(windowA, 'data-testid', 'three-dots-conversation-options'); - await clickOnMatchingText(windowA, 'Block'); - await waitForTestIdWithText(windowA, 'session-toast', 'Blocked'); - await waitForMatchingPlaceholder( - windowA, - 'message-input-text-area', - 'Unblock this contact to send a message.' - ); - await waitForMatchingPlaceholder( - windowB, - 'message-input-text-area', - 'Unblock this contact to send a message.' - ); // reveal-blocked-user-settings is not updated once opened - // Check linked device for blocked contact in settings screen - await clickOnTestIdWithText(windowB, 'settings-section'); - await clickOnTestIdWithText(windowB, 'conversations-settings-menu-item'); - // a conf sync job can take 30s (if the last one failed) + 10s polling to show a change on a linked device. - await clickOnTestIdWithText(windowB, 'reveal-blocked-user-settings', undefined, undefined, 50000); - // Check if user B is in blocked contact list - await waitForMatchingText(windowB, userB.userName); -}); diff --git a/ts/test/automation/linked_device_user.spec.ts-snapshots/avatar-updated-blue-darwin.jpeg b/ts/test/automation/linked_device_user.spec.ts-snapshots/avatar-updated-blue-darwin.jpeg deleted file mode 100644 index 453383765..000000000 Binary files a/ts/test/automation/linked_device_user.spec.ts-snapshots/avatar-updated-blue-darwin.jpeg and /dev/null differ diff --git a/ts/test/automation/message_checks.spec.ts b/ts/test/automation/message_checks.spec.ts deleted file mode 100644 index ab5af3554..000000000 --- a/ts/test/automation/message_checks.spec.ts +++ /dev/null @@ -1,184 +0,0 @@ -import { sleepFor } from '../../session/utils/Promise'; -import { newUser } from './setup/new_user'; -import { sessionTestTwoWindows } from './setup/sessionTest'; -import { createContact } from './utilities/create_contact'; -import { sendMessage } from './utilities/message'; -import { replyTo } from './utilities/reply_message'; -import { - clickOnElement, - clickOnMatchingText, - clickOnTestIdWithText, - hasTextElementBeenDeletedNew, - measureSendingTime, - typeIntoInput, - waitForLoadingAnimationToFinish, - waitForMatchingText, - waitForTestIdWithText, - waitForTextMessage, -} from './utilities/utils'; - -sessionTestTwoWindows('Send image', async ([windowA, windowB]) => { - const [userA, userB] = await Promise.all([newUser(windowA, 'Alice'), newUser(windowB, 'Bob')]); - const testMessage = `${userA.userName} sending image to ${userB.userName}`; - const testReply = `${userB.userName} replying to image from ${userA.userName}`; - await createContact(windowA, windowB, userA, userB); - - await windowA.setInputFiles("input[type='file']", 'ts/test/automation/fixtures/test-image.png'); - await typeIntoInput(windowA, 'message-input-text-area', testMessage); - await clickOnTestIdWithText(windowA, 'send-message-button'); - // Click on untrusted attachment in window B - await sleepFor(1000); - await clickOnMatchingText(windowB, 'Click to download media'); - await clickOnTestIdWithText(windowB, 'session-confirm-ok-button'); - await waitForLoadingAnimationToFinish(windowB, 'loading-animation'); - // Waiting for image to change from loading state to loaded (takes a second) - await sleepFor(1000); - - await replyTo(windowB, testMessage, testReply); -}); - -sessionTestTwoWindows('Send video', async ([windowA, windowB]) => { - const [userA, userB] = await Promise.all([newUser(windowA, 'Alice'), newUser(windowB, 'Bob')]); - const testMessage = `${userA.userName} sending video to ${userB.userName}`; - const testReply = `${userB.userName} replying to video from ${userA.userName}`; - await createContact(windowA, windowB, userA, userB); - - await windowA.setInputFiles("input[type='file']", 'ts/test/automation/fixtures/test-video.mp4'); - await typeIntoInput(windowA, 'message-input-text-area', testMessage); - await sleepFor(100); - await clickOnTestIdWithText(windowA, 'send-message-button'); - await sleepFor(1000); - await clickOnMatchingText(windowB, 'Click to download media'); - await clickOnTestIdWithText(windowB, 'session-confirm-ok-button'); - await waitForLoadingAnimationToFinish(windowB, 'loading-animation'); - // Waiting for videoto change from loading state to loaded (takes a second) - await sleepFor(1000); - await replyTo(windowB, testMessage, testReply); -}); - -sessionTestTwoWindows('Send document', async ([windowA, windowB]) => { - const [userA, userB] = await Promise.all([newUser(windowA, 'Alice'), newUser(windowB, 'Bob')]); - const testMessage = `${userA.userName} sending document to ${userB.userName}`; - const testReply = `${userB.userName} replying to document from ${userA.userName}`; - await createContact(windowA, windowB, userA, userB); - - await windowA.setInputFiles("input[type='file']", 'ts/test/automation/fixtures/test-file.pdf'); - await typeIntoInput(windowA, 'message-input-text-area', testMessage); - await sleepFor(100); - await clickOnTestIdWithText(windowA, 'send-message-button'); - await sleepFor(1000); - await clickOnMatchingText(windowB, 'Click to download media'); - await clickOnTestIdWithText(windowB, 'session-confirm-ok-button'); - await waitForLoadingAnimationToFinish(windowB, 'loading-animation'); - // Waiting for video to change from loading state to loaded (takes a second) - await sleepFor(500); - await replyTo(windowB, testMessage, testReply); -}); - -sessionTestTwoWindows('Send voice message', async ([windowA, windowB]) => { - const [userA, userB] = await Promise.all([newUser(windowA, 'Alice'), newUser(windowB, 'Bob')]); - // const testReply = `${userB.userName} to ${userA.userName}`; - await createContact(windowA, windowB, userA, userB); - - await clickOnTestIdWithText(windowA, 'microphone-button'); - await clickOnTestIdWithText(windowA, 'session-toast'); - await clickOnTestIdWithText(windowA, 'enable-microphone'); - await clickOnTestIdWithText(windowA, 'message-section'); - await clickOnTestIdWithText(windowA, 'microphone-button'); - await sleepFor(5000); - await clickOnTestIdWithText(windowA, 'end-voice-message'); - await sleepFor(4000); - await clickOnTestIdWithText(windowA, 'send-message-button'); - await sleepFor(1000); - await clickOnMatchingText(windowB, 'Click to download media'); - await clickOnTestIdWithText(windowB, 'session-confirm-ok-button'); -}); - -sessionTestTwoWindows('Send GIF', async ([windowA, windowB]) => { - const [userA, userB] = await Promise.all([newUser(windowA, 'Alice'), newUser(windowB, 'Bob')]); - // const testReply = `${userB.userName} to ${userA.userName}`; - await createContact(windowA, windowB, userA, userB); - - await windowA.setInputFiles("input[type='file']", 'ts/test/automation/fixtures/test-gif.gif'); - await sleepFor(100); - await clickOnTestIdWithText(windowA, 'send-message-button'); - await sleepFor(1000); - await clickOnMatchingText(windowB, 'Click to download media'); -}); - -sessionTestTwoWindows('Send long text', async ([windowA, windowB]) => { - const [userA, userB] = await Promise.all([newUser(windowA, 'Alice'), newUser(windowB, 'Bob')]); - - const testReply = `${userB.userName} replying to long text message from ${userA.userName}`; - const longText = - // eslint-disable-next-line max-len - 'Lorem ipsum dolor sit amet, consectetur adipiscing elit. Vestibulum quis lacinia mi. Praesent fermentum vehicula rhoncus. Aliquam ac purus lobortis, convallis nisi quis, pulvinar elit. Nam commodo eros in molestie lobortis. Donec at mattis est. In tempor ex nec velit mattis, vitae feugiat augue maximus. Nullam risus libero, bibendum et enim et, viverra viverra est. Suspendisse potenti. Sed ut nibh in sem rhoncus suscipit. Etiam tristique leo sit amet ullamcorper dictum. Suspendisse sollicitudin, lectus et suscipit eleifend, libero dui ultricies neque, non elementum nulla orci bibendum lorem. Suspendisse potenti. Aenean a tellus imperdiet, iaculis metus quis, pretium diam. Nunc varius vitae enim vestibulum interdum. In hac habitasse platea dictumst. Donec auctor sem quis eleifend fermentum. Vestibulum neque nulla, maximus non arcu gravida, condimentum euismod turpis. Cras ac mattis orci. Quisque ac enim pharetra felis sodales eleifend. Aliquam erat volutpat. Donec sit amet mollis nibh, eget feugiat ipsum. Integer vestibulum purus ac suscipit egestas. Duis vitae aliquet ligula.'; - - await createContact(windowA, windowB, userA, userB); - - await typeIntoInput(windowA, 'message-input-text-area', longText); - await sleepFor(100); - await clickOnTestIdWithText(windowA, 'send-message-button'); - await sleepFor(1000); - await replyTo(windowB, longText, testReply); -}); - -sessionTestTwoWindows('Unsend message', async ([windowA, windowB]) => { - const [userA, userB] = await Promise.all([newUser(windowA, 'Alice'), newUser(windowB, 'Bob')]); - const unsendMessage = 'Testing unsend functionality'; - await createContact(windowA, windowB, userA, userB); - - await sendMessage(windowA, unsendMessage); - await waitForTextMessage(windowB, unsendMessage); - await clickOnTestIdWithText(windowA, 'control-message', unsendMessage, true); - await clickOnMatchingText(windowA, 'Delete for everyone'); - await clickOnElement(windowA, 'data-testid', 'session-confirm-ok-button'); - await waitForTestIdWithText(windowA, 'session-toast', 'Deleted'); - await sleepFor(1000); - await waitForMatchingText(windowB, 'This message has been deleted'); -}); - -sessionTestTwoWindows('Delete message', async ([windowA, windowB]) => { - const [userA, userB] = await Promise.all([newUser(windowA, 'Alice'), newUser(windowB, 'Bob')]); - const deletedMessage = 'Testing deletion functionality'; - await createContact(windowA, windowB, userA, userB); - await sendMessage(windowA, deletedMessage); - await waitForTextMessage(windowB, deletedMessage); - await clickOnTestIdWithText(windowA, 'control-message', deletedMessage, true); - await clickOnMatchingText(windowA, 'Delete just for me'); - await clickOnMatchingText(windowA, 'Delete'); - await waitForTestIdWithText(windowA, 'session-toast', 'Deleted'); - await hasTextElementBeenDeletedNew(windowA, deletedMessage, 1000); - // Still should exist in window B - await waitForMatchingText(windowB, deletedMessage); -}); - -sessionTestTwoWindows('Check performance', async ([windowA, windowB]) => { - const [userA, userB] = await Promise.all([newUser(windowA, 'Alice'), newUser(windowB, 'Bob')]); - // Create contact - await createContact(windowA, windowB, userA, userB); - const timesArray: Array = []; - - let i; - for (i = 1; i <= 10; i++) { - // eslint-disable-next-line no-await-in-loop - const timeMs = await measureSendingTime(windowA, i); - timesArray.push(timeMs); - } - console.log(timesArray); -}); - -// *************** NEED TO WAIT FOR LINK PREVIEW FIX ************************************************* -// sessionTestTwoWindows('Send link and reply test', async ([windowA, windowB]) => { -// const [userA, userB] = await Promise.all([newUser(windowA, 'Alice'), newUser(windowB, 'Bob')]); -// const testMessage = 'https://nerdlegame.com/'; -// const testReply = `${userB.userName} replying to link from ${userA.userName}`; - -// await createContact(windowA, windowB, userA, userB); - -// await typeIntoInput(windowA, 'message-input-text-area', testMessage); -// await sleepFor(5000); -// await clickOnTestIdWithText(windowA, 'send-message-button'); -// await sleepFor(1000); -// await replyTo(windowB, testMessage, testReply); -// }); diff --git a/ts/test/automation/message_requests.spec.ts b/ts/test/automation/message_requests.spec.ts deleted file mode 100644 index fa711f74c..000000000 --- a/ts/test/automation/message_requests.spec.ts +++ /dev/null @@ -1,97 +0,0 @@ -import { test } from '@playwright/test'; -import { beforeAllClean } from './setup/beforeEach'; -import { newUser } from './setup/new_user'; -import { sendMessage } from './utilities/message'; -import { sendNewMessage } from './utilities/send_message'; -import { - clickOnMatchingText, - clickOnTestIdWithText, - waitForMatchingText, - waitForTestIdWithText, -} from './utilities/utils'; -import { sessionTestTwoWindows } from './setup/sessionTest'; - -test.beforeEach(beforeAllClean); - -// test.afterEach(() => forceCloseAllWindows(windows)); -// Open two windows and log into 2 separate accounts -test.describe('Message requests', () => { - sessionTestTwoWindows('Message requests accept', async ([windowA, windowB]) => { - const [userA, userB] = await Promise.all([newUser(windowA, 'Alice'), newUser(windowB, 'Bob')]); - const testMessage = `Sender: ${userA.userName} Receiver: ${userB.userName}`; - // send a message to User B from User A - await sendNewMessage(windowA, userB.sessionid, `${testMessage}`); - // Check the message request banner appears and click on it - await clickOnTestIdWithText(windowB, 'message-request-banner'); - // Select message request from User A - await clickOnTestIdWithText(windowB, 'module-conversation__user__profile-name', userA.userName); - // Check that using the accept button has intended use - await clickOnTestIdWithText(windowB, 'accept-message-request'); - // Check config message of message request acceptance - await waitForTestIdWithText( - windowB, - 'control-message', - `You have accepted ${userA.userName}'s message request` - ); - await waitForMatchingText(windowB, 'No pending message requests'); - }); - sessionTestTwoWindows('Message requests text reply', async ([windowA, windowB]) => { - const [userA, userB] = await Promise.all([newUser(windowA, 'Alice'), newUser(windowB, 'Bob')]); - const testMessage = `Sender: ${userA.userName}, Receiver: ${userB.userName}`; - const testReply = `Sender: ${userB.userName}, Receiver: ${userA.userName}`; - // send a message to User B from User A - await sendNewMessage(windowA, userB.sessionid, `${testMessage}`); - // Check the message request banner appears and click on it - await clickOnTestIdWithText(windowB, 'message-request-banner'); - // Select message request from User A - await clickOnTestIdWithText(windowB, 'module-conversation__user__profile-name', userA.userName); - // Check that using the accept button has intended use - await sendMessage(windowB, testReply); - // Check config message of message request acceptance - await waitForTestIdWithText( - windowB, - 'control-message', - `You have accepted ${userA.userName}'s message request` - ); - await waitForMatchingText(windowB, 'No pending message requests'); - }); - sessionTestTwoWindows('Message requests decline', async ([windowA, windowB]) => { - const [userA, userB] = await Promise.all([newUser(windowA, 'Alice'), newUser(windowB, 'Bob')]); - const testMessage = `Sender: ${userA.userName}, Receiver: ${userB.userName}`; - // send a message to User B from User A - await sendNewMessage(windowA, userB.sessionid, `${testMessage}`); - // Check the message request banner appears and click on it - await clickOnTestIdWithText(windowB, 'message-request-banner'); - // Select message request from User A - await clickOnTestIdWithText(windowB, 'module-conversation__user__profile-name', userA.userName); - // Check that using the accept button has intended use - await clickOnTestIdWithText(windowB, 'decline-message-request'); - // Confirm decline - await clickOnTestIdWithText(windowB, 'session-confirm-ok-button', 'Decline'); - // Check config message of message request acceptance - await waitForMatchingText(windowB, 'No pending message requests'); - }); - sessionTestTwoWindows('Message requests clear all', async ([windowA, windowB]) => { - const [userA, userB] = await Promise.all([newUser(windowA, 'Alice'), newUser(windowB, 'Bob')]); - const testMessage = `Sender: ${userA.userName}, Receiver: ${userB.userName}`; - // send a message to User B from User A - await sendNewMessage(windowA, userB.sessionid, `${testMessage}`); - // Check the message request banner appears and click on it - await clickOnTestIdWithText(windowB, 'message-request-banner'); - // Select 'Clear All' button - await clickOnMatchingText(windowB, 'Clear All'); - // Confirm decline - await clickOnTestIdWithText(windowB, 'session-confirm-ok-button', 'OK'); - // Navigate back to message request folder to check - await clickOnTestIdWithText(windowB, 'settings-section'); - - await clickOnTestIdWithText(windowB, 'message-requests-settings-menu-item', 'Message Requests'); - // Check config message of message request acceptance - await waitForMatchingText(windowB, 'No pending message requests'); - }); -}); - -// Clear all requests - -// Delete request (not a feature yet) -// Block request (not a feature yet) diff --git a/ts/test/automation/password.spec.ts b/ts/test/automation/password.spec.ts deleted file mode 100644 index b6e5eb8a0..000000000 --- a/ts/test/automation/password.spec.ts +++ /dev/null @@ -1,119 +0,0 @@ -import { sleepFor } from '../../session/utils/Promise'; -import { newUser } from './setup/new_user'; -import { sessionTestOneWindow } from './setup/sessionTest'; -import { - clickOnMatchingText, - clickOnTestIdWithText, - typeIntoInput, - waitForMatchingText, - waitForTestIdWithText, -} from './utilities/utils'; - -const testPassword = '123456'; -const newTestPassword = '789101112'; - -sessionTestOneWindow('Set Password', async ([window]) => { - // Create user - await newUser(window, 'userA'); - // Click on settings tab - await clickOnTestIdWithText(window, 'settings-section'); - // Click on privacy - await clickOnTestIdWithText(window, 'privacy-settings-menu-item'); - // Click set password - await clickOnTestIdWithText(window, 'set-password-button'); - // Enter password - await typeIntoInput(window, 'password-input', testPassword); - // Confirm password - await typeIntoInput(window, 'password-input-confirm', testPassword); - // Click Done - await clickOnMatchingText(window, 'Done'); - // Check toast notification - await waitForTestIdWithText( - window, - 'session-toast', - 'Your password has been set. Please keep it safe.' - ); - // Click on settings tab - await sleepFor(300); - await clickOnTestIdWithText(window, 'settings-section'); - // Type password into input field - - await typeIntoInput(window, 'password-input', testPassword); - - // Click Done - await clickOnMatchingText(window, 'Done'); - await clickOnTestIdWithText(window, 'settings-section'); - - // Change password - await clickOnTestIdWithText(window, 'change-password-settings-button', 'Change Password'); - - console.warn('clicked Change Password'); - // Enter old password - await typeIntoInput(window, 'password-input', testPassword); - // Enter new password - await typeIntoInput(window, 'password-input-confirm', newTestPassword); - await window.keyboard.press('Tab'); - // Confirm new password - await typeIntoInput(window, 'password-input-reconfirm', newTestPassword); - // Press enter on keyboard - await window.keyboard.press('Enter'); - // Check toast notification for 'changed password' - await waitForTestIdWithText( - window, - 'session-toast', - 'Your password has been changed. Please keep it safe.' - ); -}); - -sessionTestOneWindow('Wrong password', async ([window]) => { - // Check if incorrect password works - // Create user - await newUser(window, 'userA'); - // Click on settings tab - await clickOnTestIdWithText(window, 'settings-section'); - // Click on privacy - await clickOnMatchingText(window, 'Privacy'); - // Click set password - await clickOnMatchingText(window, 'Set Password'); - // Enter password - await typeIntoInput(window, 'password-input', testPassword); - // Confirm password - await typeIntoInput(window, 'password-input-confirm', testPassword); - // Click Done - await window.keyboard.press('Enter'); - // // Click on settings tab - await sleepFor(100); - await clickOnTestIdWithText(window, 'settings-section'); - - // Type password into input field - await sleepFor(100); - await typeIntoInput(window, 'password-input', testPassword); - // Click Done - await clickOnMatchingText(window, 'Done'); - await sleepFor(100); - await window.mouse.click(0, 0); - await clickOnTestIdWithText(window, 'message-section'); - await sleepFor(100); - - // // Click on settings tab - await sleepFor(1000); - await clickOnTestIdWithText(window, 'settings-section'); - // // Try with incorrect password - await typeIntoInput(window, 'password-input', '000000'); - // Confirm - await clickOnMatchingText(window, 'Done'); - // // invalid password banner showing? - await waitForMatchingText(window, 'Invalid password'); - // // Empty password - // // Navigate away from settings tab - await window.mouse.click(0, 0); - await sleepFor(100); - await clickOnTestIdWithText(window, 'message-section'); - await sleepFor(100); - // // Click on settings tab - await clickOnTestIdWithText(window, 'settings-section'); - // // No password entered - await clickOnMatchingText(window, 'Done'); - // // Banner should ask for password to be entered - await waitForMatchingText(window, 'Enter password'); -}); diff --git a/ts/test/automation/setup/beforeEach.ts b/ts/test/automation/setup/beforeEach.ts deleted file mode 100644 index fad660465..000000000 --- a/ts/test/automation/setup/beforeEach.ts +++ /dev/null @@ -1,54 +0,0 @@ -import { join } from 'path'; -import { homedir } from 'os'; -import { Page } from '@playwright/test'; -import { readdirSync, rmdirSync } from 'fs-extra'; -import { isLinux, isMacOS } from '../../../OS'; -import { MULTI_PREFIX, NODE_ENV } from './open'; - -const getDirectoriesOfSessionDataPath = (source: string) => - readdirSync(source, { withFileTypes: true }) - .filter(dirent => dirent.isDirectory()) - .map(dirent => { - return dirent.name; - }) - .filter(n => n.includes(`${NODE_ENV}-${MULTI_PREFIX}`)); - -const alreadyCleaned = false; -let alreadyCleanedWaiting = false; - -function cleanUpOtherTest() { - if (alreadyCleaned || alreadyCleanedWaiting) { - return; - } - - alreadyCleanedWaiting = true; - - const parentFolderOfAllDataPath = isMacOS() - ? join(homedir(), 'Library', 'Application Support') - : isLinux() - ? join(homedir(), '.config') - : null; - if (!parentFolderOfAllDataPath) { - throw new Error('Only macOS is currrently supported '); - } - - if (!parentFolderOfAllDataPath || parentFolderOfAllDataPath.length < 9) { - throw new Error(`parentFolderOfAllDataPath not found or invalid: ${parentFolderOfAllDataPath}`); - } - console.info('cleaning other tests leftovers...', parentFolderOfAllDataPath); - - const allAppDataPath = getDirectoriesOfSessionDataPath(parentFolderOfAllDataPath); - console.info('allAppDataPath', allAppDataPath); - - allAppDataPath.forEach(folder => { - const pathToRemove = join(parentFolderOfAllDataPath, folder); - rmdirSync(pathToRemove, { recursive: true }); - }); - console.info('...done'); -} - -export const beforeAllClean = cleanUpOtherTest; - -export const forceCloseAllWindows = async (windows: Array) => { - return Promise.all(windows.map(w => w.close())); -}; diff --git a/ts/test/automation/setup/create_group.ts b/ts/test/automation/setup/create_group.ts deleted file mode 100644 index fb6496cf4..000000000 --- a/ts/test/automation/setup/create_group.ts +++ /dev/null @@ -1,121 +0,0 @@ -import { Page } from '@playwright/test'; -import { sendMessage } from '../utilities/message'; -import { sendNewMessage } from '../utilities/send_message'; -import { - clickOnMatchingText, - clickOnTestIdWithText, - typeIntoInput, - waitForControlMessageWithText, - waitForTestIdWithText, -} from '../utilities/utils'; -import { Group, User } from '../types/testing'; - -export const createGroup = async ( - userName: string, - userOne: User, - windowA: Page, - userTwo: User, - windowB: Page, - userThree: User, - windowC: Page -): Promise => { - const group: Group = { userName, userOne, userTwo, userThree }; - const emptyStateGroupText = `You have no messages from ${group.userName}. Send a message to start the conversation!`; - - const messageAB = `${userOne.userName} to ${userTwo.userName}`; - const messageBA = `${userTwo.userName} to ${userOne.userName}`; - const messageCA = `${userThree.userName} to ${userOne.userName}`; - const messageAC = `${userOne.userName} to ${userThree.userName}`; - const msgAToGroup = `${userOne.userName} -> ${group.userName}`; - const msgBToGroup = `${userTwo.userName} -> ${group.userName}`; - const msgCToGroup = `${userThree.userName} -> ${group.userName}`; - // Add contacts - await sendNewMessage(windowA, userThree.sessionid, `${messageAC} Time: ${Date.now()}`); - await Promise.all([ - sendNewMessage(windowA, userTwo.sessionid, `${messageAB} Time: ${Date.now()}`), - sendNewMessage(windowB, userOne.sessionid, `${messageBA} Time: ${Date.now()}`), - sendNewMessage(windowC, userOne.sessionid, `${messageCA} Time: ${Date.now()}`), - ]); - // Focus screen on window C to allow user C to become contact - await clickOnTestIdWithText(windowC, 'messages-container'); - // wait for user C to be contact before moving to create group - // Create group with existing contact and session ID (of non-contact) - // Click new closed group tab - await clickOnTestIdWithText(windowA, 'new-conversation-button'); - await clickOnTestIdWithText(windowA, 'chooser-new-group'); - // Enter group name - await typeIntoInput(windowA, 'new-closed-group-name', group.userName); - // Select user B - await clickOnMatchingText(windowA, userTwo.userName); - // Select user C - await clickOnMatchingText(windowA, userThree.userName); - // Click Next - await clickOnTestIdWithText(windowA, 'next-button'); - // Check group was successfully created - await clickOnMatchingText(windowB, group.userName); - await waitForTestIdWithText(windowB, 'header-conversation-name', group.userName); - // Make sure the empty state is in windowA - await waitForTestIdWithText(windowA, 'empty-conversation-notification', emptyStateGroupText); - - await Promise.all([ - (async () => { - // Navigate to group in window B - await clickOnTestIdWithText(windowB, 'message-section'); - // Click on test group - await clickOnMatchingText(windowB, group.userName); - // Make sure the empty state is in windowB - return waitForTestIdWithText(windowB, 'empty-conversation-notification', emptyStateGroupText); - })(), - (async () => { - // Navigate to group in window C - await clickOnTestIdWithText(windowC, 'message-section'); - // Click on test group - await clickOnMatchingText(windowC, group.userName); - // Make sure the empty state is in windowC - return waitForTestIdWithText(windowC, 'empty-conversation-notification', emptyStateGroupText); - })(), - ]); - - await Promise.all([ - (async () => { - // Send message in group chat from user A - await sendMessage(windowA, msgAToGroup); - // Focus screen - await clickOnMatchingText(windowA, msgAToGroup); - })(), - (async () => { - // Send message in group chat from user B - await sendMessage(windowB, msgBToGroup); - await clickOnMatchingText(windowB, msgBToGroup); - })(), - (async () => { - // Send message from C to the group - await sendMessage(windowC, msgCToGroup); - await clickOnMatchingText(windowC, msgCToGroup); - })(), - ]); - - // Verify that each messages was received by the other two accounts - await Promise.all([ - (async () => { - // windowA should see the message from B and the message from C - await waitForControlMessageWithText(windowA, msgBToGroup); - await waitForControlMessageWithText(windowA, msgCToGroup); - })(), - (async () => { - // windowB should see the message from A and the message from C - await waitForControlMessageWithText(windowB, msgAToGroup); - await waitForControlMessageWithText(windowB, msgCToGroup); - })(), - (async () => { - // windowC must see the message from A and the message from B - await waitForControlMessageWithText(windowC, msgAToGroup); - await waitForControlMessageWithText(windowC, msgBToGroup); - })(), - ]); - - // Focus screen - // await clickOnTestIdWithText(windowB, 'scroll-to-bottom-button'); - - return { userName, userOne, userTwo, userThree }; -}; diff --git a/ts/test/automation/setup/log_in.ts b/ts/test/automation/setup/log_in.ts deleted file mode 100644 index f2e0471f7..000000000 --- a/ts/test/automation/setup/log_in.ts +++ /dev/null @@ -1,20 +0,0 @@ -import { Page } from '@playwright/test'; -import { - clickOnTestIdWithText, - hasElementPoppedUpThatShouldnt, - typeIntoInput, - waitForLoadingAnimationToFinish, -} from '../utilities/utils'; - -export async function logIn(window: Page, recoveryPhrase: string) { - await clickOnTestIdWithText(window, 'link-device'); - await typeIntoInput(window, 'recovery-phrase-input', recoveryPhrase); - await clickOnTestIdWithText(window, 'continue-session-button'); - await waitForLoadingAnimationToFinish(window, 'loading-spinner', 5000); - await hasElementPoppedUpThatShouldnt( - window, - 'data-testid', - 'session-toast', - 'Could not find your display name. Please Sign In by Restoring Your Account instead.' - ); -} diff --git a/ts/test/automation/setup/new_user.ts b/ts/test/automation/setup/new_user.ts deleted file mode 100644 index 49f8f0554..000000000 --- a/ts/test/automation/setup/new_user.ts +++ /dev/null @@ -1,32 +0,0 @@ -import { Page } from '@playwright/test'; -import { User } from '../types/testing'; -import { - checkPathLight, - clickOnMatchingText, - clickOnTestIdWithText, - typeIntoInput, -} from '../utilities/utils'; - -export const newUser = async (window: Page, userName: string): Promise => { - // Create User - await clickOnMatchingText(window, 'Create Session ID'); - await clickOnMatchingText(window, 'Continue'); - // Input username = testuser - await typeIntoInput(window, 'display-name-input', userName); - await clickOnMatchingText(window, 'Get started'); - // save recovery phrase - await clickOnMatchingText(window, 'Reveal Recovery Phrase'); - const recoveryPhrase = await window.innerText('[data-testid=recovery-phrase-seed-modal]'); - await window.click('.session-icon-button.small'); - - await clickOnTestIdWithText(window, 'leftpane-primary-avatar'); - - // Save session ID to a variable - let sessionid = await window.innerText('[data-testid=your-session-id]'); - sessionid = sessionid.replace(/(\r\n|\n|\r)/gm, ''); // remove the new line in the SessionID as it is rendered with one forced - - console.info(`${userName}: Session ID: ${sessionid} and Recovery phrase: ${recoveryPhrase}`); - await window.click('.session-icon-button.small'); - await checkPathLight(window); - return { userName, sessionid, recoveryPhrase }; -}; diff --git a/ts/test/automation/setup/open.ts b/ts/test/automation/setup/open.ts deleted file mode 100644 index 0db2f167b..000000000 --- a/ts/test/automation/setup/open.ts +++ /dev/null @@ -1,41 +0,0 @@ -import { join } from 'path'; -import { _electron } from '@playwright/test'; -import { getAppRootPath } from '../../../node/getRootPath'; - -export const NODE_ENV = 'production'; -export const MULTI_PREFIX = 'test-integration-testnet-'; -const multisAvailable = 'ABCDEFGHIJKLMNOPQRSTUVWXYZ'; - -export async function openApp(windowsToCreate: number) { - if (windowsToCreate >= multisAvailable.length) { - throw new Error(`Do you really need ${multisAvailable.length} windows?!`); - } - // if windowToCreate = 3, this array will be ABC. If windowToCreate = 5, this array will be ABCDE - const multisToUse = multisAvailable.slice(0, windowsToCreate); - return Promise.all( - [...multisToUse].map(async m => { - return openAppAndWait(`${m}`); - }) - ); -} - -export const openElectronAppOnly = async (multi: string) => { - process.env.NODE_APP_INSTANCE = `${MULTI_PREFIX}-${Date.now()}-${multi}`; - process.env.NODE_ENV = NODE_ENV; - - console.info(' NODE_ENV', process.env.NODE_ENV); - console.info(' NODE_APP_INSTANCE', process.env.NODE_APP_INSTANCE); - const electronApp = await _electron.launch({ - args: [join(getAppRootPath(), 'ts', 'mains', 'main_node.js')], - }); - return electronApp; -}; - -const openAppAndWait = async (multi: string) => { - const electronApp = await openElectronAppOnly(multi); - // Get the first window that the app opens, wait if necessary. - const window = await electronApp.firstWindow(); - - // await window.reload(); - return window; -}; diff --git a/ts/test/automation/setup/recovery_using_seed.ts b/ts/test/automation/setup/recovery_using_seed.ts deleted file mode 100644 index d2b033371..000000000 --- a/ts/test/automation/setup/recovery_using_seed.ts +++ /dev/null @@ -1,11 +0,0 @@ -import { Page } from '@playwright/test'; -import { clickOnTestIdWithText, typeIntoInput } from '../utilities/utils'; - -export async function recoverFromSeed(window: Page, userName: string, recoveryPhrase: string) { - await clickOnTestIdWithText(window, 'restore-using-recovery'); - await typeIntoInput(window, 'recovery-phrase-input', recoveryPhrase); - await typeIntoInput(window, 'display-name-input', userName); - await clickOnTestIdWithText(window, 'continue-session-button'); - - return { window }; -} diff --git a/ts/test/automation/setup/sessionTest.ts b/ts/test/automation/setup/sessionTest.ts deleted file mode 100644 index e9a80de16..000000000 --- a/ts/test/automation/setup/sessionTest.ts +++ /dev/null @@ -1,83 +0,0 @@ -/* eslint-disable @typescript-eslint/array-type */ -import { Page, test } from '@playwright/test'; -import { beforeAllClean, forceCloseAllWindows } from './beforeEach'; -import { openApp } from './open'; - -// This is not ideal, most of our test needs to open a specific number of windows and close them once the test is done or failed. -// This file contains a bunch of utility function to use to open those windows and clean them afterwards. -// Note: those function only keep track (and close) the windows they open. If you open a new window or need to close and reopen an existing one, this won't take of it. - -type Tuple = N extends N - ? number extends N - ? T[] - : _TupleOf - : never; -type _TupleOf = R['length'] extends N - ? R - : _TupleOf; - -type CountWindows = 1 | 2 | 3 | 4 | 5; - -function sessionTest>( - testName: string, - testCallback: (windows: N) => Promise, - count: T -) { - return test(testName, async () => { - beforeAllClean(); - const windows = await openApp(count); - - try { - if (windows.length !== count) { - throw new Error(`openApp should have opened ${count} windows but did not.`); - } - await testCallback(windows as N); - // eslint-disable-next-line no-useless-catch - } catch (e) { - throw e; - } finally { - try { - await forceCloseAllWindows(windows); - } catch (e) { - console.error(`forceCloseAllWindows of ${testName} failed with: `, e); - } - } - }); -} - -export function sessionTestOneWindow( - testName: string, - testCallback: (windows: Tuple) => Promise -) { - return sessionTest(testName, testCallback, 1); -} - -export function sessionTestTwoWindows( - testName: string, - testCallback: ([windowA, windowB]: [Page, Page]) => Promise -) { - return sessionTest(testName, testCallback, 2); -} - -export function sessionTestThreeWindows( - testName: string, - testCallback: ([windowA, windowB, windowC]: [Page, Page, Page]) => Promise -) { - return sessionTest(testName, testCallback, 3); -} - -export function sessionTestFourWindows( - testName: string, - testCallback: ([windowA, windowB, windowC, windowD]: [Page, Page, Page, Page]) => Promise -) { - return sessionTest(testName, testCallback, 4); -} - -export function sessionTestFiveWindows( - testName: string, - testCallback: ([windowA, windowB, windowC, windowD]: [Page, Page, Page, Page, Page]) => Promise< - void - > -) { - return sessionTest(testName, testCallback, 5); -} diff --git a/ts/test/automation/setup/test_user.ts b/ts/test/automation/setup/test_user.ts deleted file mode 100644 index 960219c67..000000000 --- a/ts/test/automation/setup/test_user.ts +++ /dev/null @@ -1,34 +0,0 @@ -export const userA = { - userName: 'Alice', - sessionid: '059e36f9bb03ac4e1ff9ff7d4aedd791d1f412770c6cd2796b855af12a7c7ea000', - recoveryPhrase: - 'tuition remedy sieve ivory wiggle gemstone hawk optical issued damp selfish fewest damp', -}; - -export const userB = { - userName: 'Bob', - sessionid: '05ead902602c1f7b59aaa3932b9cdefe8ee4075c03b09811d31bc9b122cb292d0c', - recoveryPhrase: - 'misery testing template jeopardy yahoo asylum kettle wise unveil wept bygones dice dice', -}; - -export const userC = { - userName: 'Chloe', - sessionid: '055f4bcc665b94a0f4c2aa9c2d543ae015db167014aac316bc21f5d7c6fdb11025', - recoveryPhrase: - 'bakery broken circle ginger pistons deity deity degrees today insult fidget ouch deity', -}; - -export const userD = { - userName: 'Doug', - sessionid: '0555274f98d9f681d37446797bdebfa0e53d872213450663141bedb58a8ca67675', - recoveryPhrase: - 'biscuit bomb hire update suede money balding rest fuming alchemy ridges deity update', -}; - -export const userE = { - userName: 'Egbert', - sessionid: '058b523d3f00773c745c965cf9482dd2fd6ea7a67ec4643c187309e4bbf96a936a', - recoveryPhrase: - 'dusted coffee hoisting ringing titans dangerous technical bomb bubble pancakes wipeout goldfish technical', -}; diff --git a/ts/test/automation/switching_theme.spec.ts b/ts/test/automation/switching_theme.spec.ts deleted file mode 100644 index 5627d9643..000000000 --- a/ts/test/automation/switching_theme.spec.ts +++ /dev/null @@ -1,23 +0,0 @@ -import { expect } from '@playwright/test'; -import { newUser } from './setup/new_user'; -import { clickOnTestIdWithText } from './utilities/utils'; -import { sessionTestOneWindow } from './setup/sessionTest'; - -sessionTestOneWindow('Switch themes', async ([windowA]) => { - // Create User - await newUser(windowA, 'Alice'); - // Check light theme colour is correct - const darkThemeColor = windowA.locator('.inbox.index'); - await expect(darkThemeColor).toHaveCSS('background-color', 'rgb(27, 27, 27)'); - - // Click theme button and change to dark theme - await clickOnTestIdWithText(windowA, 'theme-section'); - // Check background colour of background to verify dark theme - const lightThemeColor = windowA.locator('.inbox.index'); - await expect(lightThemeColor).toHaveCSS('background-color', 'rgb(255, 255, 255)'); - - // Toggle back to light theme - await clickOnTestIdWithText(windowA, 'theme-section'); - // Check background colour again - await expect(darkThemeColor).toHaveCSS('background-color', 'rgb(27, 27, 27)'); -}); diff --git a/ts/test/automation/test.spec.ts b/ts/test/automation/test.spec.ts deleted file mode 100644 index 4910014be..000000000 --- a/ts/test/automation/test.spec.ts +++ /dev/null @@ -1,6 +0,0 @@ -import { clickOnMatchingText } from './utilities/utils'; -import { sessionTestOneWindow } from './setup/sessionTest'; - -sessionTestOneWindow('Tiny test', async ([windowA]) => { - await clickOnMatchingText(windowA, 'Create Session ID'); -}); diff --git a/ts/test/automation/types/testing.ts b/ts/test/automation/types/testing.ts deleted file mode 100644 index f82960a64..000000000 --- a/ts/test/automation/types/testing.ts +++ /dev/null @@ -1,79 +0,0 @@ -export type User = { - userName: string; - sessionid: string; - recoveryPhrase: string; -}; - -export type Group = { - userName: string; - userOne: User; - userTwo: User; - userThree: User; -}; - -export type Strategy = 'data-testid' | 'class' | ':has-text'; - -export type loaderType = 'loading-animation' | 'loading-spinner'; - -export type DataTestId = - | 'session-id-signup' - | 'display-name-input' - | 'recovery-phrase-seed-modal' - | 'path-light-container' - | 'new-conversation-button' - | 'chooser-new-conversation-button' - | 'new-session-conversation' - | 'next-new-conversation-button' - | 'control-message' - | 'disappearing-messages-indicator' - | 'back-button-conversation-options' - | 'conversation-options-avatar' - | 'settings-section' - | 'clear-data-settings-menu-item' - | 'message-requests-settings-menu-item' - | 'restore-using-recovery' - | 'recovery-phrase-input' - | 'continue-session-button' - | 'label-device_and_network' - | 'message-request-banner' - | 'module-conversation__user__profile-name' - | 'decline-message-request' - | 'session-confirm-ok-button' - | 'dropdownitem-5-seconds' - | 'disappearing-messages-dropdown' - | 'session-toast' - | 'accept-message-request' - | 'confirm-nickname' - | 'nickname-input' - | 'three-dots-conversation-options' - | 'message-section' - | 'conversations-settings-menu-item' - | 'reveal-blocked-user-settings' - | 'unblock-button-settings-screen' - | 'leftpane-primary-avatar' - | 'edit-profile-icon' - | 'profile-name-input' - | 'image-upload-section' - | 'save-button-profile-update' - | 'modal-close-button' - | 'send-message-button' - | 'message-input-text-area' - | 'end-voice-message' - | 'microphone-button' - | 'enable-microphone' - | 'theme-section' - | 'call-button' - | 'enable-calls' - | 'end-call' - | 'privacy-settings-menu-item' - | 'set-password-button' - | 'password-input' - | 'password-input-confirm' - | 'change-password-settings-button' - | 'password-input-reconfirm' - | 'messages-container' - | 'chooser-new-group' - | 'new-closed-group-name' - | 'next-button' - | 'link-device' - | 'group-name-input'; diff --git a/ts/test/automation/user_actions.spec.ts b/ts/test/automation/user_actions.spec.ts deleted file mode 100644 index cb3f9ea87..000000000 --- a/ts/test/automation/user_actions.spec.ts +++ /dev/null @@ -1,200 +0,0 @@ -import { expect } from '@playwright/test'; -import { sleepFor } from '../../session/utils/Promise'; -import { newUser } from './setup/new_user'; -import { createContact } from './utilities/create_contact'; -import { sendNewMessage } from './utilities/send_message'; -import { - clickOnElement, - clickOnMatchingText, - clickOnTestIdWithText, - typeIntoInput, - typeIntoInputSlow, - waitForMatchingText, - waitForTestIdWithText, -} from './utilities/utils'; -import { sessionTestOneWindow, sessionTestTwoWindows } from './setup/sessionTest'; -import { sendMessage } from './utilities/message'; - -// Send message in one to one conversation with new contact -sessionTestTwoWindows('Create contact', async ([windowA, windowB]) => { - const [userA, userB] = await Promise.all([newUser(windowA, 'Alice'), newUser(windowB, 'Bob')]); - - const testMessage = `${userA.userName} to ${userB.userName}`; - const testReply = `${userB.userName} to ${userA.userName}`; - // User A sends message to User B - await sendNewMessage(windowA, userB.sessionid, `${testMessage} Time: '${Date.now()}'`); - // User B sends message to User B to USER A - await sendNewMessage(windowB, userA.sessionid, `${testReply} Time: '${Date.now()}'`); - // Navigate to contacts tab in User B's window - - await clickOnTestIdWithText(windowA, 'new-conversation-button'); - await windowA.waitForTimeout(2000); - await waitForTestIdWithText(windowB, 'module-conversation__user__profile-name', userA.userName); - - // Navigate to contacts tab in User A's window - await clickOnTestIdWithText(windowA, 'new-conversation-button'); -}); - -sessionTestTwoWindows('Block user in conversation options', async ([windowA, windowB]) => { - // Open app and create user - const [userA, userB] = await Promise.all([newUser(windowA, 'Alice'), newUser(windowB, 'Bob')]); - - const testMessage = `${userA.userName} to ${userB.userName}`; - const testReply = `${userB.userName} to ${userA.userName}`; - // Create contact and send new message - - await sendNewMessage(windowA, userB.sessionid, `${testMessage} Time: '${Date.now()}'`); - await sendNewMessage(windowB, userA.sessionid, `${testReply} Time: '${Date.now()}'`); - // Check to see if User B is a contact - await clickOnTestIdWithText(windowA, 'new-conversation-button'); - await waitForTestIdWithText(windowA, 'module-conversation__user__profile-name', userB.userName); - // Click on three dots menu - await clickOnTestIdWithText(windowA, 'message-section'); - - await clickOnTestIdWithText(windowA, 'three-dots-conversation-options'); - // Select block - await clickOnMatchingText(windowA, 'Block'); - // Verify toast notification 'blocked' - await waitForTestIdWithText(windowA, 'session-toast', 'Blocked'); - // Verify the user was moved to the blocked contact list - // Click on settings tab - await clickOnTestIdWithText(windowA, 'settings-section'); - // click on settings section 'conversation' - await clickOnTestIdWithText(windowA, 'conversations-settings-menu-item'); - // Navigate to blocked users tab' - await clickOnTestIdWithText(windowA, 'reveal-blocked-user-settings'); - // select the contact to unblock by clicking on it by name - await clickOnMatchingText(windowA, userB.userName); - // Unblock user by clicking on unblock - await clickOnTestIdWithText(windowA, 'unblock-button-settings-screen'); - // Verify toast notification says unblocked - await waitForTestIdWithText(windowA, 'session-toast', 'Unblocked'); - await waitForMatchingText(windowA, 'No blocked contacts'); -}); - -sessionTestTwoWindows('Block user in conversation list', async ([windowA, windowB]) => { - // Open app and create user - const [userA, userB] = await Promise.all([newUser(windowA, 'Alice'), newUser(windowB, 'Bob')]); - - const testMessage = `${userA.userName} to ${userB.userName}`; - const testReply = `${userB.userName} to ${userA.userName}`; - // Create contact and send new message - - await sendNewMessage(windowA, userB.sessionid, `${testMessage} Time: '${Date.now()}'`); - await sendNewMessage(windowB, userA.sessionid, `${testReply} Time: '${Date.now()}'`); - // Check to see if User B is a contact - await clickOnTestIdWithText(windowA, 'new-conversation-button'); - await waitForTestIdWithText(windowA, 'module-conversation__user__profile-name', userB.userName); - // Click on three dots menu - await clickOnTestIdWithText(windowA, 'message-section'); - - await clickOnTestIdWithText( - windowA, - 'module-conversation__user__profile-name', - userB.userName, - true - ); - // Select block - await clickOnMatchingText(windowA, 'Block'); - // Verify toast notification 'blocked' - await waitForTestIdWithText(windowA, 'session-toast', 'Blocked'); - // Verify the user was moved to the blocked contact list - // Click on settings tab - await clickOnTestIdWithText(windowA, 'settings-section'); - // click on settings section 'conversation' - await clickOnTestIdWithText(windowA, 'conversations-settings-menu-item'); - // Navigate to blocked users tab' - await clickOnTestIdWithText(windowA, 'reveal-blocked-user-settings'); - // select the contact to unblock by clicking on it by name - await clickOnMatchingText(windowA, userB.userName); - // Unblock user by clicking on unblock - await clickOnTestIdWithText(windowA, 'unblock-button-settings-screen'); - // Verify toast notification says unblocked - await waitForTestIdWithText(windowA, 'session-toast', 'Unblocked'); - await waitForMatchingText(windowA, 'No blocked contacts'); -}); -sessionTestOneWindow('Change username', async ([window]) => { - // Create user - const newUsername = 'Tiny bubble'; - await newUser(window, 'Alice'); - // Open Profile - await clickOnTestIdWithText(window, 'leftpane-primary-avatar'); - // Click on current username to open edit field - await clickOnTestIdWithText(window, 'edit-profile-icon'); - // Type in new username - await typeIntoInput(window, 'profile-name-input', newUsername); - // await window.fill('.profile-name-input', 'new username'); - // Press enter to confirm username input - await window.keyboard.press('Enter'); - // Wait for Copy button to appear to verify username change - await window.isVisible("'Copy'"); - // verify name change - expect(await window.innerText('[data-testid=your-profile-name]')).toBe(newUsername); - // Exit profile module - await window.click('.session-icon-button.small'); -}); - -sessionTestOneWindow('Change avatar', async ([window]) => { - await newUser(window, 'Alice'); - // Open profile - await clickOnTestIdWithText(window, 'leftpane-primary-avatar'); - // Click on current profile picture - await waitForTestIdWithText(window, 'copy-button-profile-update', 'Copy'); - - await clickOnTestIdWithText(window, 'image-upload-section'); - await clickOnTestIdWithText(window, 'save-button-profile-update'); - await waitForTestIdWithText(window, 'loading-spinner'); - - await waitForTestIdWithText(window, 'copy-button-profile-update', 'Copy'); - await clickOnTestIdWithText(window, 'modal-close-button'); - - await sleepFor(500); - const leftpaneAvatarContainer = await waitForTestIdWithText(window, 'leftpane-primary-avatar'); - await sleepFor(500); - const screenshot = await leftpaneAvatarContainer.screenshot({ - type: 'jpeg', - // path: 'avatar-updated-blue', - }); - expect(screenshot).toMatchSnapshot({ name: 'avatar-updated-blue.jpeg' }); -}); - -sessionTestTwoWindows('Set nickname', async ([windowA, windowB]) => { - const [userA, userB] = await Promise.all([newUser(windowA, 'Alice'), newUser(windowB, 'Bob')]); - const nickname = 'new nickname for Bob'; - - await createContact(windowA, windowB, userA, userB); - await sleepFor(100); - await clickOnTestIdWithText(windowA, 'three-dots-conversation-options'); - await clickOnMatchingText(windowA, 'Change Nickname'); - await sleepFor(1000); - - await typeIntoInputSlow(windowA, 'nickname-input', nickname); - await sleepFor(100); - await clickOnTestIdWithText(windowA, 'confirm-nickname', 'OK'); - const headerUsername = await waitForTestIdWithText(windowA, 'header-conversation-name'); - const headerUsernameText = await headerUsername.innerText(); - console.warn('Innertext ', headerUsernameText); - - expect(headerUsernameText).toBe(nickname); - // Check conversation list name also - const conversationListUsernameText = await waitForTestIdWithText( - windowA, - 'module-conversation__user__profile-name' - ); - const conversationListUsername = await conversationListUsernameText.innerText(); - expect(conversationListUsername).toBe(nickname); -}); - -sessionTestTwoWindows('Read status', async ([windowA, windowB]) => { - const [userA, userB] = await Promise.all([newUser(windowA, 'Alice'), newUser(windowB, 'Bob')]); - await createContact(windowA, windowB, userA, userB); - await clickOnElement(windowA, 'data-testid', 'setting-section'); - await clickOnElement(windowA, 'data-testid', 'enable-read-receipts'); - await clickOnElement(windowA, 'data-testid', 'message-section'); - await clickOnTestIdWithText(windowA, 'module-conversation__user__profile-name', userB.userName); - await clickOnElement(windowB, 'data-testid', 'setting-section'); - await clickOnElement(windowB, 'data-testid', 'enable-read-receipts'); - await clickOnElement(windowB, 'data-testid', 'message-section'); - await clickOnTestIdWithText(windowB, 'module-conversation__user__profile-name', userA.userName); - await sendMessage(windowA, 'Testing read receipts'); -}); diff --git a/ts/test/automation/user_actions.spec.ts-snapshots/avatar-updated-blue-darwin.jpeg b/ts/test/automation/user_actions.spec.ts-snapshots/avatar-updated-blue-darwin.jpeg deleted file mode 100644 index 079323ef7..000000000 Binary files a/ts/test/automation/user_actions.spec.ts-snapshots/avatar-updated-blue-darwin.jpeg and /dev/null differ diff --git a/ts/test/automation/utilities/create_contact.ts b/ts/test/automation/utilities/create_contact.ts deleted file mode 100644 index df2a7e69c..000000000 --- a/ts/test/automation/utilities/create_contact.ts +++ /dev/null @@ -1,20 +0,0 @@ -import { Page } from '@playwright/test'; -import { User } from '../types/testing'; -import { sendNewMessage } from './send_message'; -import { clickOnTestIdWithText, waitForTestIdWithText } from './utils'; - -export const createContact = async (windowA: Page, windowB: Page, userA: User, userB: User) => { - const testMessage = `${userA.userName} to ${userB.userName}`; - const testReply = `${userB.userName} to ${userA.userName}`; - // User A sends message to User B - await sendNewMessage(windowA, userB.sessionid, testMessage); - // User B sends message to User B to USER A - await sendNewMessage(windowB, userA.sessionid, testReply); - - await clickOnTestIdWithText(windowA, 'new-conversation-button'); - await windowA.waitForTimeout(2000); - await waitForTestIdWithText(windowB, 'module-conversation__user__profile-name', userA.userName); - - // Navigate to contacts tab in User A's window - await clickOnTestIdWithText(windowA, 'new-conversation-button'); -}; diff --git a/ts/test/automation/utilities/leave_group.ts b/ts/test/automation/utilities/leave_group.ts deleted file mode 100644 index 3318755c5..000000000 --- a/ts/test/automation/utilities/leave_group.ts +++ /dev/null @@ -1,13 +0,0 @@ -import { Page } from '@playwright/test'; -import { clickOnMatchingText, clickOnTestIdWithText, waitForTestIdWithText } from './utils'; - -export const leaveGroup = async (window: Page) => { - // go to three dots menu - await clickOnTestIdWithText(window, 'three-dots-conversation-options'); - // Select Leave Group - await clickOnMatchingText(window, 'Leave Group'); - // Confirm leave group - await clickOnTestIdWithText(window, 'session-confirm-ok-button', 'OK'); - // check config message - await waitForTestIdWithText(window, 'control-message', 'You have left the group.'); -}; diff --git a/ts/test/automation/utilities/linked_device.ts b/ts/test/automation/utilities/linked_device.ts deleted file mode 100644 index 0dc169e1c..000000000 --- a/ts/test/automation/utilities/linked_device.ts +++ /dev/null @@ -1,10 +0,0 @@ -import { logIn } from '../setup/log_in'; -import { openApp } from '../setup/open'; - -export async function linkedDevice(recoveryPhrase: string) { - const [windowB] = await openApp(1); // not using sessionTest here as we need to close and reopen one of the window - - await logIn(windowB, recoveryPhrase); - - return [windowB]; -} diff --git a/ts/test/automation/utilities/message.ts b/ts/test/automation/utilities/message.ts deleted file mode 100644 index 18799eb50..000000000 --- a/ts/test/automation/utilities/message.ts +++ /dev/null @@ -1,15 +0,0 @@ -import { Page } from '@playwright/test'; -import { clickOnTestIdWithText, typeIntoInput } from './utils'; - -export const sendMessage = async (window: Page, message: string) => { - // type into message input box - await typeIntoInput(window, 'message-input-text-area', message); - // click up arrow (send) - await clickOnTestIdWithText(window, 'send-message-button'); - // wait for confirmation tick to send reply message - const selc = `css=[data-testid=control-message]:has-text("${message}"):has([data-testid=msg-status-outgoing][data-testtype=sent])`; - console.error('waiting for sent tick of message: ', message); - - const tickMessageSent = await window.waitForSelector(selc, { timeout: 30000 }); - console.error('found the tick of message sent: ', message, Boolean(tickMessageSent)); -}; diff --git a/ts/test/automation/utilities/rename_group.ts b/ts/test/automation/utilities/rename_group.ts deleted file mode 100644 index 2c5981f34..000000000 --- a/ts/test/automation/utilities/rename_group.ts +++ /dev/null @@ -1,20 +0,0 @@ -import { Page } from '@playwright/test'; -import { - clickOnMatchingText, - clickOnTestIdWithText, - typeIntoInput, - waitForMatchingText, - waitForTestIdWithText, -} from './utils'; - -export const renameGroup = async (window: Page, oldGroupName: string, newGroupName: string) => { - await clickOnMatchingText(window, oldGroupName); - await clickOnTestIdWithText(window, 'conversation-options-avatar'); - await clickOnMatchingText(window, 'Edit group name'); - await typeIntoInput(window, 'group-name-input', newGroupName); - await window.keyboard.press('Enter'); - await waitForTestIdWithText(window, 'right-panel-group-name', newGroupName); - await clickOnTestIdWithText(window, 'back-button-conversation-options'); - // Check config message - await waitForMatchingText(window, `Group name is now '${newGroupName}'.`); -}; diff --git a/ts/test/automation/utilities/reply_message.ts b/ts/test/automation/utilities/reply_message.ts deleted file mode 100644 index a9a949a76..000000000 --- a/ts/test/automation/utilities/reply_message.ts +++ /dev/null @@ -1,11 +0,0 @@ -import { Page } from '@playwright/test'; -import { sendMessage } from './message'; -import { clickOnMatchingText, clickOnTestIdWithText, waitForTextMessage } from './utils'; - -export const replyTo = async (window: Page, textMessage: string, replyText: string) => { - await waitForTextMessage(window, textMessage); - await clickOnTestIdWithText(window, 'control-message', textMessage, true); - await clickOnMatchingText(window, 'Reply to message'); - await sendMessage(window, replyText); - console.warn(); -}; diff --git a/ts/test/automation/utilities/send_message.ts b/ts/test/automation/utilities/send_message.ts deleted file mode 100644 index aa716348e..000000000 --- a/ts/test/automation/utilities/send_message.ts +++ /dev/null @@ -1,13 +0,0 @@ -import { Page } from '@playwright/test'; -import { sendMessage } from './message'; -import { clickOnTestIdWithText, typeIntoInput } from './utils'; - -export const sendNewMessage = async (window: Page, sessionid: string, message: string) => { - await clickOnTestIdWithText(window, 'new-conversation-button'); - await clickOnTestIdWithText(window, 'chooser-new-conversation-button'); - // Enter session ID of USER B - await typeIntoInput(window, 'new-session-conversation', sessionid); - // click next - await clickOnTestIdWithText(window, 'next-new-conversation-button', 'Next'); - await sendMessage(window, message); -}; diff --git a/ts/test/automation/utilities/utils.ts b/ts/test/automation/utilities/utils.ts deleted file mode 100644 index f9abeaf61..000000000 --- a/ts/test/automation/utilities/utils.ts +++ /dev/null @@ -1,288 +0,0 @@ -/* eslint-disable no-useless-escape */ -/* eslint-disable import/no-extraneous-dependencies */ -/* eslint-disable no-await-in-loop */ -import { ElementHandle, Page } from '@playwright/test'; -import { sleepFor } from '../../../session/utils/Promise'; -import { DataTestId, loaderType, Strategy } from '../types/testing'; -import { sendMessage } from './message'; - -// WAIT FOR FUNCTIONS - -export async function waitForTestIdWithText(window: Page, dataTestId: string, text?: string) { - let builtSelector = `css=[data-testid=${dataTestId}]`; - if (text) { - // " => \\\" - /* prettier-ignore */ - - const escapedText = text.replace(/"/g, '\\\"'); - - builtSelector += `:has-text("${escapedText}")`; - console.warn('builtSelector:', builtSelector); - // console.warn('Text is tiny bubble: ', escapedText); - } - // console.info('looking for selector', builtSelector); - const found = await window.waitForSelector(builtSelector, { timeout: 55000 }); - // console.info('found selector', builtSelector); - - return found; -} - -export async function waitForElement( - window: Page, - strategy: Strategy, - selector: string, - maxWaitMs?: number, - text?: string -) { - const builtSelector = !text - ? `css=[${strategy}=${selector}]` - : `css=[${strategy}=${selector}]:has-text("${text.replace(/"/g, '\\"')}")`; - - return window.waitForSelector(builtSelector, { timeout: maxWaitMs }); -} - -export async function waitForTextMessage(window: Page, text: string, maxWait?: number) { - let builtSelector = `css=[data-testid=control-message]:has-text("${text}")`; - if (text) { - // " => \\\" - /* prettier-ignore */ - - const escapedText = text.replace(/"/g, '\\\"'); - - builtSelector += `:has-text("${escapedText}")`; - console.warn('builtSelector:', builtSelector); - // console.warn('Text is tiny bubble: ', escapedText); - } - const el = await window.waitForSelector(builtSelector, { timeout: maxWait }); - console.info(`Text message found. Text: , ${text}`); - return el; -} - -export async function waitForControlMessageWithText(window: Page, text: string) { - return waitForTestIdWithText(window, 'control-message', text); -} - -export async function waitForMatchingText(window: Page, text: string, maxWait?: number) { - const builtSelector = `css=:has-text("${text}")`; - const maxTimeout = maxWait ?? 55000; - console.info(`waitForMatchingText: ${text}`); - - await window.waitForSelector(builtSelector, { timeout: maxTimeout }); - - console.info(`got matchingText: ${text}`); -} - -export async function waitForMatchingPlaceholder( - window: Page, - dataTestId: string, - placeholder: string, - maxWait: number = 30000 -) { - let found = false; - const start = Date.now(); - console.info(`waitForMatchingPlaceholder: ${placeholder} with datatestId: ${dataTestId}`); - - do { - try { - const elem = await waitForElement(window, 'data-testid', dataTestId); - const elemPlaceholder = await elem.getAttribute('placeholder'); - if (elemPlaceholder === placeholder) { - console.info( - `waitForMatchingPlaceholder foudn matching element with placeholder: "${placeholder}"` - ); - - found = true; - } - } catch (e) { - await sleepFor(1000, true); - console.info(`waitForMatchingPlaceholder failed with ${e.message}, retrying in 1s`); - } - } while (!found && Date.now() - start <= maxWait); - - if (!found) { - throw new Error(`Failed to find datatestid:"${dataTestId}" with placeholder: "${placeholder}"`); - } -} -export async function waitForLoadingAnimationToFinish( - window: Page, - loader: loaderType, - maxWait?: number -) { - let loadingAnimation: ElementHandle | undefined; - - await waitForElement(window, 'data-testid', `${loader}`, maxWait); - - do { - try { - loadingAnimation = await waitForElement(window, 'data-testid', `${loader}`, 100); - await sleepFor(500); - console.info(`${loader} was found, waiting for it to be gone`); - } catch (e) { - loadingAnimation = undefined; - } - } while (loadingAnimation); - console.info('Loading animation has finished'); -} - -export async function checkPathLight(window: Page, maxWait?: number) { - let pathLight: ElementHandle | undefined; - const maxWaitTime = maxWait || 100000; - const waitPerLoop = 100; - let start = Date.now(); - - pathLight = await waitForElement(window, 'data-testid', 'path-light-container', maxWait); - let pathColor = await pathLight.getAttribute('color'); - - while (pathColor === 'var(--button-path-error-color)') { - await sleepFor(waitPerLoop); - pathLight = await waitForElement(window, 'data-testid', 'path-light-container', maxWait); - pathColor = await pathLight.getAttribute('color'); - start += waitPerLoop; - if (Date.now() - start >= maxWaitTime / 2) { - console.log('Path building...'); - } - - if (Date.now() - start >= maxWaitTime) { - throw new Error('Timed out waiting for path'); - } - } - console.log('Path built correctly, Yay!', pathColor); -} - -// ACTIONS - -export async function clickOnElement( - window: Page, - strategy: Strategy, - selector: string, - maxWait?: number -) { - const builtSelector = `css=[${strategy}=${selector}]`; - await window.waitForSelector(builtSelector, { timeout: maxWait }); - await window.click(builtSelector); -} - -export async function clickOnMatchingText(window: Page, text: string, rightButton = false) { - console.info(`clickOnMatchingText: "${text}"`); - return window.click(`"${text}"`, rightButton ? { button: 'right' } : undefined); -} - -export async function clickOnTestIdWithText( - window: Page, - dataTestId: DataTestId, - text?: string, - rightButton?: boolean, - maxWait?: number -) { - console.info(`clickOnTestIdWithText with testId:${dataTestId} and text:${text || 'none'}`); - - const builtSelector = !text - ? `css=[data-testid=${dataTestId}]` - : `css=[data-testid=${dataTestId}]:has-text("${text}")`; - - await window.waitForSelector(builtSelector, { timeout: maxWait }); - return window.click(builtSelector, rightButton ? { button: 'right' } : undefined); -} - -export function getMessageTextContentNow() { - return `Test message timestamp: ${Date.now()}`; -} - -export async function typeIntoInput(window: Page, dataTestId: DataTestId, text: string) { - console.info(`typeIntoInput testId: ${dataTestId} : "${text}"`); - const builtSelector = `css=[data-testid=${dataTestId}]`; - return window.fill(builtSelector, text); -} - -export async function typeIntoInputSlow(window: Page, dataTestId: DataTestId, text: string) { - console.info(`typeIntoInput testId: ${dataTestId} : "${text}"`); - const builtSelector = `css=[data-testid=${dataTestId}]`; - await window.waitForSelector(builtSelector); - return window.type(builtSelector, text, { delay: 100 }); -} - -export async function doesTextIncludeString(window: Page, dataTestId: DataTestId, text: string) { - const element = await waitForTestIdWithText(window, dataTestId); - const el = await element.innerText(); - - const builtSelector = el.includes(text); - if (builtSelector) { - console.info('Text found:', text); - } else { - throw new Error(`Text not found: "${text}"`); - } -} - -export async function hasElementBeenDeleted( - window: Page, - strategy: Strategy, - selector: string, - maxWait?: number -) { - const fakeError = `Element ${selector} has been found... oops`; - try { - await waitForElement(window, strategy, selector, maxWait); - throw new Error(fakeError); - } catch (e) { - if (e.message === fakeError) { - throw e; - } - } - console.info(`${selector} has not been found, congrats`); -} - -export async function hasTextElementBeenDeleted(window: Page, text: string, maxWait?: number) { - const fakeError = `Matching text: ${text} has been found... oops`; - try { - await waitForMatchingText(window, text, maxWait); - throw new Error(fakeError); - } catch (e) { - if (e.message === fakeError) { - throw e; - } - } - console.info('Element has not been found, congratulations', text); -} - -export async function hasTextElementBeenDeletedNew(window: Page, text: string, maxWait?: number) { - const textElement = await waitForElement(window, ':has-text', text, maxWait); - try { - if (textElement) { - await sleepFor(100); - } else { - console.log('Element has been deleted, congratulations'); - } - } catch (e) { - throw new Error('Element not defined'); - } -} - -export async function hasElementPoppedUpThatShouldnt( - window: Page, - strategy: Strategy, - selector: string, - text?: string -) { - const builtSelector = !text - ? `css=[${strategy}=${selector}]` - : `css=[${strategy}=${selector}]:has-text("${text.replace(/"/g, '\\"')}")`; - - const fakeError = `Found ${selector}, oops..`; - const elVisible = await window.isVisible(builtSelector); - if (elVisible === true) { - throw new Error(fakeError); - } -} - -export async function measureSendingTime(window: Page, messageNumber: number) { - const message = `Test-message`; - const timeStart = Date.now(); - - await sendMessage(window, message); - - const timeEnd = Date.now(); - const timeMs = timeEnd - timeStart; - - console.log(`Message ${messageNumber}: ${timeMs}`); - return timeMs; -}