mirror of
https://github.com/oxen-io/session-desktop.git
synced 2023-12-14 02:12:57 +01:00
Merge remote-tracking branch 'emily/integration_tests_2' into onboarding-with-integrationtest-2
This commit is contained in:
commit
3827298078
63 changed files with 1575 additions and 847 deletions
|
@ -45,6 +45,8 @@
|
|||
"lint-full": "yarn format-full && eslint . && tslint --format stylish --project .",
|
||||
"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\"",
|
||||
"coverage": "nyc --reporter=html mocha -r jsdom-global/register --recursive --exit --timeout 10000 \"./ts/test/**/*_test.js\"",
|
||||
|
|
|
@ -4,6 +4,7 @@ export interface FlexProps {
|
|||
children?: any;
|
||||
className?: string;
|
||||
container?: boolean;
|
||||
dataTestId?: string;
|
||||
/****** Container Props ********/
|
||||
flexDirection?: 'row' | 'column';
|
||||
justifyContent?:
|
||||
|
|
|
@ -46,6 +46,7 @@ type Props = {
|
|||
active: boolean;
|
||||
onClick: () => void;
|
||||
confirmationDialogParams?: any | undefined;
|
||||
dataTestId?: string;
|
||||
};
|
||||
|
||||
export const SessionToggle = (props: Props) => {
|
||||
|
@ -84,7 +85,12 @@ export const SessionToggle = (props: Props) => {
|
|||
};
|
||||
|
||||
return (
|
||||
<StyledSessionToggle role="button" onClick={clickHandler} active={props.active}>
|
||||
<StyledSessionToggle
|
||||
role="button"
|
||||
onClick={clickHandler}
|
||||
active={props.active}
|
||||
data-testid={props.dataTestId}
|
||||
>
|
||||
<StyledKnob active={props.active} />
|
||||
</StyledSessionToggle>
|
||||
);
|
||||
|
|
|
@ -4,6 +4,7 @@ import styled from 'styled-components';
|
|||
type Props = {
|
||||
size: 'small' | 'normal';
|
||||
direction?: string;
|
||||
dataTestId?: string;
|
||||
};
|
||||
|
||||
// Module: Spinner
|
||||
|
@ -69,7 +70,7 @@ export const Spinner = (props: Props) => {
|
|||
|
||||
if (size === 'small') {
|
||||
return (
|
||||
<SpinnerContainerSmall>
|
||||
<SpinnerContainerSmall data-testid="loading-animation">
|
||||
<SpinnerArcSmall>
|
||||
<path d={spinner24Path} />
|
||||
</SpinnerArcSmall>
|
||||
|
@ -78,7 +79,7 @@ export const Spinner = (props: Props) => {
|
|||
}
|
||||
|
||||
return (
|
||||
<SpinnerContainer>
|
||||
<SpinnerContainer data-testid="loading-animation">
|
||||
<SpinnerArc>
|
||||
<path d={spinner56Path} />
|
||||
</SpinnerArc>
|
||||
|
|
|
@ -283,6 +283,7 @@ export const HangUpButton = ({ isFullScreen }: { isFullScreen: boolean }) => {
|
|||
borderRadius="50%"
|
||||
onClick={handleEndCall}
|
||||
margin="10px"
|
||||
dataTestId="end-call"
|
||||
/>
|
||||
</StyledCallActionButton>
|
||||
);
|
||||
|
|
|
@ -242,6 +242,7 @@ const CallButton = () => {
|
|||
onClick={() => {
|
||||
void callRecipient(selectedConvoKey, canCall);
|
||||
}}
|
||||
dataTestId="call-button"
|
||||
/>
|
||||
);
|
||||
};
|
||||
|
|
|
@ -129,6 +129,7 @@ export class SessionRecording extends React.Component<Props, State> {
|
|||
iconSize="medium"
|
||||
iconColor={'var(--danger-color)'}
|
||||
onClick={actionPauseFn}
|
||||
dataTestId="end-voice-message"
|
||||
/>
|
||||
)}
|
||||
{actionPauseAudio && (
|
||||
|
@ -175,6 +176,7 @@ export class SessionRecording extends React.Component<Props, State> {
|
|||
iconRotation={90}
|
||||
onClick={this.onSendVoiceMessage}
|
||||
margin={'var(--margins-sm)'}
|
||||
dataTestId="send-message-button"
|
||||
/>
|
||||
</div>
|
||||
)}
|
||||
|
|
|
@ -25,6 +25,7 @@ export const AddStagedAttachmentButton = (props: { onClick: () => void }) => {
|
|||
borderRadius="300px"
|
||||
iconPadding="8px"
|
||||
onClick={props.onClick}
|
||||
dataTestId="attachments-button"
|
||||
/>
|
||||
</StyledChatButtonContainer>
|
||||
);
|
||||
|
@ -41,6 +42,7 @@ export const StartRecordingButton = (props: { onClick: () => void }) => {
|
|||
borderRadius="300px"
|
||||
iconPadding="6px"
|
||||
onClick={props.onClick}
|
||||
dataTestId="microphone-button"
|
||||
/>
|
||||
</StyledChatButtonContainer>
|
||||
);
|
||||
|
@ -59,6 +61,7 @@ export const ToggleEmojiButton = React.forwardRef<HTMLDivElement, { onClick: ()
|
|||
borderRadius="300px"
|
||||
iconPadding="6px"
|
||||
onClick={props.onClick}
|
||||
dataTestId="emoji-button"
|
||||
/>
|
||||
</StyledChatButtonContainer>
|
||||
);
|
||||
|
|
|
@ -185,7 +185,7 @@ export const ReadableMessage = (props: ReadableMessageProps) => {
|
|||
triggerOnce={false}
|
||||
trackVisibility={true}
|
||||
key={`inview-msg-${messageId}`}
|
||||
data-testid="readable-message"
|
||||
data-testid="control-message"
|
||||
>
|
||||
{props.children}
|
||||
</InView>
|
||||
|
|
|
@ -67,6 +67,7 @@ export const SessionNicknameDialog = (props: Props) => {
|
|||
onKeyUp={e => {
|
||||
void onNicknameInput(_.cloneDeep(e));
|
||||
}}
|
||||
data-testid="nickname-input"
|
||||
/>
|
||||
|
||||
<div className="session-modal__button-group">
|
||||
|
@ -74,6 +75,7 @@ export const SessionNicknameDialog = (props: Props) => {
|
|||
text={window.i18n('ok')}
|
||||
buttonType={SessionButtonType.Simple}
|
||||
onClick={saveNickname}
|
||||
dataTestId="confirm-nickname"
|
||||
/>
|
||||
<SessionButton
|
||||
text={window.i18n('cancel')}
|
||||
|
|
|
@ -86,6 +86,7 @@ const SessionIconButtonInner = React.forwardRef<HTMLDivElement, SProps>((props,
|
|||
backgroundColor={backgroundColor}
|
||||
borderRadius={borderRadius}
|
||||
iconPadding={iconPadding}
|
||||
data-testid={dataTestId}
|
||||
/>
|
||||
{Boolean(notificationCount) && <SessionNotificationCount count={notificationCount} />}
|
||||
</StyledSessionIconButton>
|
||||
|
|
|
@ -208,6 +208,7 @@ export const SignInTab = () => {
|
|||
pointerEvents: 'all',
|
||||
backgroundColor: 'var(--background-primary-color)',
|
||||
}}
|
||||
dataTestId="three-dot-loading-animation"
|
||||
>
|
||||
<SessionSpinner loading={true} />
|
||||
</Flex>
|
||||
|
|
|
@ -128,6 +128,7 @@ export const SessionToggleWithDescription = (props: {
|
|||
onClickToggle: () => void;
|
||||
confirmationDialogParams?: SessionConfirmDialogProps;
|
||||
childrenDescription?: React.ReactNode; // if set, those elements will be appended next to description field (only used for typing message settings as of now)
|
||||
dataTestId?: string;
|
||||
}) => {
|
||||
const {
|
||||
title,
|
||||
|
@ -136,6 +137,7 @@ export const SessionToggleWithDescription = (props: {
|
|||
onClickToggle,
|
||||
confirmationDialogParams,
|
||||
childrenDescription,
|
||||
dataTestId,
|
||||
} = props;
|
||||
|
||||
return (
|
||||
|
@ -149,6 +151,7 @@ export const SessionToggleWithDescription = (props: {
|
|||
active={active}
|
||||
onClick={onClickToggle}
|
||||
confirmationDialogParams={confirmationDialogParams}
|
||||
dataTestId={dataTestId}
|
||||
/>
|
||||
</SessionSettingsItemWrapper>
|
||||
);
|
||||
|
|
|
@ -64,6 +64,7 @@ export const SettingsCategoryPermissions = (props: { hasPassword: boolean | null
|
|||
title={window.i18n('mediaPermissionsTitle')}
|
||||
description={window.i18n('mediaPermissionsDescription')}
|
||||
active={Boolean(window.getSettingValue('media-permissions'))}
|
||||
dataTestId="enable-microphone"
|
||||
/>
|
||||
<SessionToggleWithDescription
|
||||
onClickToggle={async () => {
|
||||
|
@ -73,6 +74,7 @@ export const SettingsCategoryPermissions = (props: { hasPassword: boolean | null
|
|||
title={window.i18n('callMediaPermissionsTitle')}
|
||||
description={window.i18n('callMediaPermissionsDescription')}
|
||||
active={Boolean(window.getCallMediaPermissions())}
|
||||
dataTestId="enable-calls"
|
||||
/>
|
||||
<SessionToggleWithDescription
|
||||
onClickToggle={async () => {
|
||||
|
|
|
@ -84,7 +84,7 @@ import { installPermissionsHandler } from '../node/permissions'; // checked - on
|
|||
|
||||
let appStartInitialSpellcheckSetting = true;
|
||||
|
||||
const enableTestIntegrationWiderWindow = true;
|
||||
const enableTestIntegrationWiderWindow = false;
|
||||
const isTestIntegration =
|
||||
enableTestIntegrationWiderWindow &&
|
||||
Boolean(
|
||||
|
|
|
@ -1,57 +0,0 @@
|
|||
import { _electron, Page, test } from '@playwright/test';
|
||||
import { beforeAllClean, forceCloseAllWindows } from './setup/beforeEach';
|
||||
import { openAppsAndNewUsers } from './setup/new_user';
|
||||
import { sendNewMessage } from './send_message';
|
||||
import {
|
||||
clickOnMatchingText,
|
||||
clickOnTestIdWithText,
|
||||
waitForMatchingText,
|
||||
waitForTestIdWithText,
|
||||
} from './utils';
|
||||
|
||||
let windows: Array<Page> = [];
|
||||
test.beforeEach(beforeAllClean);
|
||||
|
||||
test.afterEach(() => forceCloseAllWindows(windows));
|
||||
|
||||
test('Block User', async () => {
|
||||
// Open app and create user
|
||||
const windowLoggedIn = await openAppsAndNewUsers(2);
|
||||
windows = windowLoggedIn.windows;
|
||||
const users = windowLoggedIn.users;
|
||||
const [windowA, windowB] = windows;
|
||||
const [userA, userB] = users;
|
||||
// Create contact and send new message
|
||||
|
||||
await sendNewMessage(windowA, userB.sessionid, `A -> B: ${Date.now()}`);
|
||||
await sendNewMessage(windowB, userA.sessionid, `B -> A: ${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');
|
||||
});
|
27
ts/test/automation/call_checks.spec.ts
Normal file
27
ts/test/automation/call_checks.spec.ts
Normal file
|
@ -0,0 +1,27 @@
|
|||
import { test } from '@playwright/test';
|
||||
import { sleepFor } from '../../session/utils/Promise';
|
||||
import { newUser } from './setup/new_user';
|
||||
import { openApp } from './setup/open';
|
||||
import { createContact } from './utilities/create_contact';
|
||||
import { clickOnMatchingText, clickOnTestIdWithText } from './utilities/utils';
|
||||
|
||||
test('Voice calls', async () => {
|
||||
const [windowA, windowB] = await openApp(2);
|
||||
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');
|
||||
});
|
|
@ -1,43 +0,0 @@
|
|||
import { _electron, expect, Page, test } from '@playwright/test';
|
||||
import { openAppAndWait } from './setup/open';
|
||||
import { beforeAllClean, forceCloseAllWindows } from './setup/beforeEach';
|
||||
import { newUser } from './setup/new_user';
|
||||
import { clickOnTestIdWithText, waitForTestIdWithText } from './utils';
|
||||
import { sleepFor } from '../../session/utils/Promise';
|
||||
|
||||
let window: Page | undefined;
|
||||
test.beforeEach(beforeAllClean);
|
||||
|
||||
test.afterEach(async () => {
|
||||
if (window) {
|
||||
await forceCloseAllWindows([window]);
|
||||
}
|
||||
});
|
||||
|
||||
test('Change profile picture/avatar', async () => {
|
||||
window = await openAppAndWait('1');
|
||||
|
||||
await newUser(window, 'userA');
|
||||
// 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' });
|
||||
});
|
|
@ -1,36 +0,0 @@
|
|||
import { _electron, expect, Page, test } from '@playwright/test';
|
||||
import { newUser } from './setup/new_user';
|
||||
import { openAppAndWait } from './setup/open';
|
||||
import { beforeAllClean, forceCloseAllWindows } from './setup/beforeEach';
|
||||
import { clickOnTestIdWithText, typeIntoInput } from './utils';
|
||||
let window: Page | undefined;
|
||||
|
||||
test.beforeEach(beforeAllClean);
|
||||
|
||||
test.afterEach(async () => {
|
||||
if (window) {
|
||||
await forceCloseAllWindows([window]);
|
||||
}
|
||||
});
|
||||
|
||||
test('Change username', async () => {
|
||||
// Open App
|
||||
window = await openAppAndWait('1');
|
||||
// Create user
|
||||
await newUser(window, 'userA');
|
||||
// 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', 'new username');
|
||||
// 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('new username');
|
||||
// Exit profile module
|
||||
await window.click('.session-icon-button.small');
|
||||
});
|
|
@ -1,18 +1,22 @@
|
|||
import { _electron, Page, test } from '@playwright/test';
|
||||
import { Page, test } from '@playwright/test';
|
||||
import { sleepFor } from '../../session/utils/Promise';
|
||||
import { beforeAllClean } from './setup/beforeEach';
|
||||
import { newUser } from './setup/new_user';
|
||||
import { openAppAndWait } from './setup/open';
|
||||
import { sleepFor } from '../../session/utils/Promise';
|
||||
import { beforeAllClean, forceCloseAllWindows } from './setup/beforeEach';
|
||||
import { clickOnMatchingText, clickOnTestIdWithText, waitForTestIdWithText } from './utils';
|
||||
import {
|
||||
clickOnMatchingText,
|
||||
clickOnTestIdWithText,
|
||||
waitForTestIdWithText,
|
||||
} from './utilities/utils';
|
||||
|
||||
let window: Page | undefined;
|
||||
test.beforeEach(beforeAllClean);
|
||||
|
||||
test.afterEach(async () => {
|
||||
if (window) {
|
||||
await forceCloseAllWindows([window]);
|
||||
}
|
||||
});
|
||||
// test.afterEach(async () => {
|
||||
// if (window) {
|
||||
// await forceCloseAllWindows([window]);
|
||||
// }
|
||||
// });
|
||||
test('Create User', async () => {
|
||||
// Launch Electron app.
|
||||
window = await openAppAndWait('1');
|
||||
|
|
|
@ -1,23 +1,19 @@
|
|||
import { _electron, Page, test } from '@playwright/test';
|
||||
import { _electron, test } from '@playwright/test';
|
||||
import { beforeAllClean, forceCloseAllWindows } from './setup/beforeEach';
|
||||
import { openAppsAndNewUsers, openAppsNoNewUsers } from './setup/new_user';
|
||||
import { sendNewMessage } from './send_message';
|
||||
import { clickOnMatchingText, clickOnTestIdWithText, typeIntoInput } from './utils';
|
||||
import { newUser } from './setup/new_user';
|
||||
import { sendNewMessage } from './utilities/send_message';
|
||||
import { clickOnMatchingText, clickOnTestIdWithText, typeIntoInput } from './utilities/utils';
|
||||
import { sleepFor } from '../../session/utils/Promise';
|
||||
import { openApp } from './setup/open';
|
||||
// tslint:disable: no-console
|
||||
|
||||
let windows: Array<Page> = [];
|
||||
test.beforeEach(beforeAllClean);
|
||||
|
||||
test.afterEach(() => forceCloseAllWindows(windows));
|
||||
|
||||
test('Delete account from swarm', async () => {
|
||||
const testMessage = `A -> B: ${Date.now()}`;
|
||||
const testReply = `B -> A: ${Date.now()}`;
|
||||
const windowLoggedIn = await openAppsAndNewUsers(2);
|
||||
windows = windowLoggedIn.windows;
|
||||
const [windowA, windowB] = windows;
|
||||
const [userA, userB] = windowLoggedIn.users;
|
||||
const [windowA, windowB] = await openApp(2);
|
||||
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),
|
||||
|
@ -37,7 +33,7 @@ test('Delete account from swarm', async () => {
|
|||
// Wait for window to close and reopen
|
||||
await sleepFor(10000, true);
|
||||
// await windowA.close();
|
||||
const restoringWindows = await openAppsNoNewUsers(1);
|
||||
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');
|
||||
|
|
|
@ -1,21 +1,21 @@
|
|||
import { _electron, Page, test } from '@playwright/test';
|
||||
import { beforeAllClean, forceCloseAllWindows } from './setup/beforeEach';
|
||||
import { messageSent } from './message';
|
||||
import { openAppsAndNewUsers } from './setup/new_user';
|
||||
import { sendNewMessage } from './send_message';
|
||||
import { test } from '@playwright/test';
|
||||
import { sleepFor } from '../../session/utils/Promise';
|
||||
import { beforeAllClean } from './setup/beforeEach';
|
||||
import { newUser } from './setup/new_user';
|
||||
import { openApp } from './setup/open';
|
||||
import { sendMessage } from './utilities/message';
|
||||
import { sendNewMessage } from './utilities/send_message';
|
||||
import {
|
||||
clickOnMatchingText,
|
||||
clickOnTestIdWithText,
|
||||
waitForControlMessageWithText,
|
||||
waitForMatchingText,
|
||||
waitForReadableMessageWithText,
|
||||
waitForTestIdWithText,
|
||||
} from './utils';
|
||||
import { sleepFor } from '../../session/utils/Promise';
|
||||
} from './utilities/utils';
|
||||
|
||||
let windows: Array<Page> = [];
|
||||
test.beforeEach(beforeAllClean);
|
||||
|
||||
test.afterEach(() => forceCloseAllWindows(windows));
|
||||
// test.afterEach(() => forceCloseAllWindows(windows));
|
||||
// tslint:disable: no-console
|
||||
|
||||
const testMessage = 'Test-Message- (A -> B) ';
|
||||
|
@ -23,18 +23,15 @@ const testReply = 'Reply-Test-Message- (B -> A)';
|
|||
const sentMessage = `${testMessage}${Date.now()}`;
|
||||
const sentReplyMessage = `${testReply} :${Date.now()}`;
|
||||
|
||||
test('Disappearing Messages', async () => {
|
||||
test('Disappearing messages', async () => {
|
||||
// Open App
|
||||
// Create User
|
||||
const windowLoggedIn = await openAppsAndNewUsers(2);
|
||||
windows = windowLoggedIn.windows;
|
||||
const users = windowLoggedIn.users;
|
||||
const [windowA, windowB] = windows;
|
||||
const [userA, userB] = users;
|
||||
const [windowA, windowB] = await openApp(2);
|
||||
const [userA, userB] = await Promise.all([newUser(windowA, 'Alice'), newUser(windowB, 'Bob')]);
|
||||
// Create Contact
|
||||
await sendNewMessage(windowA, userB.sessionid, sentMessage);
|
||||
await sendNewMessage(windowB, userA.sessionid, sentReplyMessage);
|
||||
await waitForReadableMessageWithText(windowA, 'Your message request has been accepted');
|
||||
await waitForControlMessageWithText(windowA, 'Your message request has been accepted');
|
||||
// await waitForMatchingText(windowA, `You have accepted ${userA.userName}'s message request`);
|
||||
// await waitForMatchingText(windowB, 'Your message request has been accepted');
|
||||
// Click on user's avatar to open conversation options
|
||||
|
@ -48,7 +45,7 @@ test('Disappearing Messages', async () => {
|
|||
// Check config message
|
||||
await waitForTestIdWithText(
|
||||
windowA,
|
||||
'readable-message',
|
||||
'control-message',
|
||||
'You set the disappearing message timer to 5 seconds'
|
||||
);
|
||||
await sleepFor(2000);
|
||||
|
@ -57,7 +54,7 @@ test('Disappearing Messages', async () => {
|
|||
await waitForTestIdWithText(windowA, 'disappearing-messages-indicator', '5 seconds');
|
||||
// Send message
|
||||
// Wait for tick of confirmation
|
||||
await messageSent(windowA, sentMessage);
|
||||
await sendMessage(windowA, sentMessage);
|
||||
// Check timer is functioning
|
||||
|
||||
// Verify message is deleted
|
||||
|
@ -82,7 +79,7 @@ test('Disappearing Messages', async () => {
|
|||
// Click chevron to close menu
|
||||
await clickOnTestIdWithText(windowA, 'back-button-conversation-options');
|
||||
// Check config message
|
||||
await waitForTestIdWithText(windowA, 'readable-message', 'You disabled disappearing messages.');
|
||||
await waitForTestIdWithText(windowA, 'control-message', 'You disabled disappearing messages.');
|
||||
// Verify message is deleted in windowB for receiver user
|
||||
// Check config message in windowB
|
||||
await waitForMatchingText(
|
||||
|
|
BIN
ts/test/automation/fixtures/test-file.pdf
Normal file
BIN
ts/test/automation/fixtures/test-file.pdf
Normal file
Binary file not shown.
BIN
ts/test/automation/fixtures/test-gif.gif
Normal file
BIN
ts/test/automation/fixtures/test-gif.gif
Normal file
Binary file not shown.
After Width: | Height: | Size: 4.5 MiB |
BIN
ts/test/automation/fixtures/test-image.png
Normal file
BIN
ts/test/automation/fixtures/test-image.png
Normal file
Binary file not shown.
After Width: | Height: | Size: 108 KiB |
BIN
ts/test/automation/fixtures/test-video.mp4
Normal file
BIN
ts/test/automation/fixtures/test-video.mp4
Normal file
Binary file not shown.
|
@ -1,75 +0,0 @@
|
|||
import { _electron, Page, test } from '@playwright/test';
|
||||
import { beforeAllClean, forceCloseAllWindows } from './setup/beforeEach';
|
||||
import { messageSent } from './message';
|
||||
import { openAppsAndNewUsers } from './setup/new_user';
|
||||
import { sendNewMessage } from './send_message';
|
||||
import {
|
||||
clickOnMatchingText,
|
||||
clickOnTestIdWithText,
|
||||
typeIntoInput,
|
||||
waitForReadableMessageWithText,
|
||||
waitForTestIdWithText,
|
||||
} from './utils';
|
||||
|
||||
const testGroupName = 'Test Group Name';
|
||||
|
||||
let windows: Array<Page> = [];
|
||||
test.beforeEach(beforeAllClean);
|
||||
|
||||
test.afterEach(() => forceCloseAllWindows(windows));
|
||||
|
||||
test('Create group', async () => {
|
||||
const windowLoggedIn = await openAppsAndNewUsers(3);
|
||||
windows = windowLoggedIn.windows;
|
||||
const users = windowLoggedIn.users;
|
||||
const [windowA, windowB, windowC] = windows;
|
||||
const [userA, userB, userC] = users;
|
||||
// Add contacts
|
||||
await sendNewMessage(windowA, userC.sessionid, `A -> C: ${Date.now()}`);
|
||||
await Promise.all([
|
||||
sendNewMessage(windowA, userB.sessionid, `A -> B: ${Date.now()}`),
|
||||
sendNewMessage(windowB, userA.sessionid, `B -> A: ${Date.now()}`),
|
||||
sendNewMessage(windowC, userA.sessionid, `C -> A: ${Date.now()}`),
|
||||
]);
|
||||
// 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', testGroupName);
|
||||
// Select user B
|
||||
await clickOnMatchingText(windowA, userB.userName);
|
||||
// Select user C
|
||||
await clickOnMatchingText(windowA, userC.userName);
|
||||
// Click Done
|
||||
await clickOnTestIdWithText(windowA, 'next-button');
|
||||
// Check group was successfully created
|
||||
await clickOnMatchingText(windowB, testGroupName);
|
||||
await waitForTestIdWithText(windowB, 'header-conversation-name', testGroupName);
|
||||
// Send message in group chat from user A
|
||||
const msgAToGroup = 'A -> Group';
|
||||
await messageSent(windowA, msgAToGroup);
|
||||
// Verify it was received by other two accounts
|
||||
// Navigate to group in window B
|
||||
await clickOnTestIdWithText(windowB, 'message-section');
|
||||
// Click on test group
|
||||
await clickOnMatchingText(windowB, testGroupName);
|
||||
// wait for selector 'test message' in chat window
|
||||
await waitForReadableMessageWithText(windowB, msgAToGroup);
|
||||
// Send reply message
|
||||
const msgBToGroup = 'B -> Group';
|
||||
await messageSent(windowB, msgBToGroup);
|
||||
// Navigate to group in window C
|
||||
await clickOnTestIdWithText(windowC, 'message-section');
|
||||
// Click on test group
|
||||
await clickOnMatchingText(windowC, testGroupName);
|
||||
// windowC must see the message from A
|
||||
await waitForReadableMessageWithText(windowC, msgAToGroup);
|
||||
// windowC must see the message from B
|
||||
await waitForReadableMessageWithText(windowC, msgBToGroup);
|
||||
// Send message from C to the group
|
||||
const msgCToGroup = 'C -> Group';
|
||||
await messageSent(windowC, msgCToGroup);
|
||||
// windowA should see the message from B and the message from C
|
||||
await waitForReadableMessageWithText(windowA, msgBToGroup);
|
||||
await waitForReadableMessageWithText(windowA, msgCToGroup);
|
||||
});
|
|
@ -1,38 +1,124 @@
|
|||
import { _electron, expect, Page, test } from '@playwright/test';
|
||||
import { beforeAllClean, forceCloseAllWindows } from './setup/beforeEach';
|
||||
// import { recoverFromSeed } from './setup/recovery_using_seed';
|
||||
import { expect, test } from '@playwright/test';
|
||||
import { beforeAllClean } from './setup/beforeEach';
|
||||
import {
|
||||
clickOnElement,
|
||||
clickOnMatchingText,
|
||||
clickOnTestIdWithText,
|
||||
doesTextIncludeString,
|
||||
typeIntoInput,
|
||||
waitForControlMessageWithText,
|
||||
waitForMatchingText,
|
||||
// waitForTestIdWithText,
|
||||
} from './utils';
|
||||
// import { testContact, testUser } from './setup/test_user';
|
||||
// import { openAppsNoNewUsers } from './setup/new_user';
|
||||
import { renameGroup } from './rename_group';
|
||||
import { leaveGroup } from './leave_group';
|
||||
waitForTestIdWithText,
|
||||
} from './utilities/utils';
|
||||
import { renameGroup } from './utilities/rename_group';
|
||||
import { createGroup } from './setup/create_group';
|
||||
// import { leaveGroup } from './utilities/leave_group';
|
||||
import { newUser } from './setup/new_user';
|
||||
import { leaveGroup } from './utilities/leave_group';
|
||||
import { openApp } from './setup/open';
|
||||
import { sleepFor } from '../../session/utils/Promise';
|
||||
import { createContact } from './utilities/create_contact';
|
||||
|
||||
let windows: Array<Page> = [];
|
||||
test.beforeEach(beforeAllClean);
|
||||
|
||||
test.afterEach(() => forceCloseAllWindows(windows));
|
||||
// test.afterEach(() => forceCloseAllWindows(windows));
|
||||
|
||||
test('Group testing', async () => {
|
||||
test('Create group', async () => {
|
||||
// Open Electron
|
||||
const { windowA, windowB } = await createGroup('Test Group Name');
|
||||
windows = [windowA, windowB];
|
||||
const [windowA, windowB, windowC] = await openApp(3);
|
||||
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');
|
||||
await Promise.all([
|
||||
waitForControlMessageWithText(
|
||||
windowA,
|
||||
`"${userB.userName}", "${userC.userName}", You joined the group.`
|
||||
),
|
||||
waitForControlMessageWithText(
|
||||
windowB,
|
||||
`You, "${userC.userName}", "${userA.userName}" joined the group.`
|
||||
),
|
||||
waitForControlMessageWithText(
|
||||
windowC,
|
||||
`"${userB.userName}", You, "${userA.userName}" joined the group.`
|
||||
),
|
||||
]);
|
||||
});
|
||||
|
||||
test('Add contact to group', async () => {
|
||||
const [windowA, windowB, windowC, windowD] = await openApp(4);
|
||||
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
|
||||
);
|
||||
await doesTextIncludeString(windowD, 'control-message', 'You joined the group.');
|
||||
});
|
||||
|
||||
test('Change group name', async () => {
|
||||
const [windowA, windowB, windowC] = await openApp(3);
|
||||
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, 'Test Group Name', 'newGroupName');
|
||||
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'.");
|
||||
// Change the group name back to original name
|
||||
await clickOnMatchingText(windowB, newGroupName);
|
||||
await waitForMatchingText(windowB, `Group name is now '${newGroupName}'.`);
|
||||
// Click on conversation options
|
||||
await renameGroup(windowA, 'newGroupName', 'Test Group Name');
|
||||
|
||||
// Check to see that you can't change group name to empty string
|
||||
// Click on edit group name
|
||||
await clickOnMatchingText(windowA, 'Edit group name');
|
||||
|
@ -42,7 +128,59 @@ test('Group testing', async () => {
|
|||
await expect(errorMessage).toContainText('Please enter a group name');
|
||||
await clickOnMatchingText(windowA, 'Cancel');
|
||||
await clickOnTestIdWithText(windowA, 'back-button-conversation-options');
|
||||
|
||||
// Leave group and receive config confirmation
|
||||
await leaveGroup(windowB);
|
||||
});
|
||||
|
||||
test('Test mentions', async () => {
|
||||
const [windowA, windowB, windowC] = await openApp(3);
|
||||
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);
|
||||
});
|
||||
|
||||
test('Leave group', async () => {
|
||||
const [windowA, windowB, windowC] = await openApp(3);
|
||||
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);
|
||||
});
|
||||
|
|
|
@ -1,63 +1,70 @@
|
|||
import { _electron, Page, test } from '@playwright/test';
|
||||
import { beforeAllClean, forceCloseAllWindows } from './setup/beforeEach';
|
||||
import { openAppsNoNewUsers } from './setup/new_user';
|
||||
import { sendNewMessage } from './send_message';
|
||||
import { _electron, test } from '@playwright/test';
|
||||
import { beforeAllClean } from './setup/beforeEach';
|
||||
import { sendNewMessage } from './utilities/send_message';
|
||||
import { logIn } from './setup/log_in';
|
||||
import {
|
||||
testContactFour,
|
||||
testContactOne,
|
||||
testContactThree,
|
||||
testContactTwo,
|
||||
testUser,
|
||||
} from './setup/test_user';
|
||||
import { userA, userB, userC, userD, userE } from './setup/test_user';
|
||||
import { openApp } from './setup/open';
|
||||
|
||||
let windows: Array<Page> = [];
|
||||
test.beforeEach(beforeAllClean);
|
||||
|
||||
test.afterEach(() => forceCloseAllWindows(windows));
|
||||
|
||||
test.skip('Group upkeep', async () => {
|
||||
const [windowA, windowB, windowC, windowD, windowE] = await openAppsNoNewUsers(5);
|
||||
windows = [windowA, windowB, windowC, windowD, windowE];
|
||||
const [windowA, windowB, windowC, windowD, windowE] = await openApp(5);
|
||||
|
||||
await Promise.all([
|
||||
logIn(windowA, testUser.recoveryPhrase),
|
||||
logIn(windowB, testContactOne.recoveryPhrase),
|
||||
logIn(windowC, testContactTwo.recoveryPhrase),
|
||||
logIn(windowD, testContactThree.recoveryPhrase),
|
||||
logIn(windowE, testContactFour.recoveryPhrase),
|
||||
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,
|
||||
testContactOne.sessionid,
|
||||
`Test user -> Whale (TC1): ${Date.now()}`
|
||||
userB.sessionid,
|
||||
`${userA.userName} -> ${userB.userName}: ${Date.now()}`
|
||||
);
|
||||
// Send message from Whale to user A
|
||||
await sendNewMessage(windowB, testUser.sessionid, `Whale (TC1) -> Test user : ${Date.now()}`);
|
||||
await sendNewMessage(
|
||||
windowB,
|
||||
userA.sessionid,
|
||||
`${userB.userName} -> ${userA.userName} : ${Date.now()}`
|
||||
);
|
||||
// Send message from user A to Dragon(TC2)
|
||||
await sendNewMessage(
|
||||
windowA,
|
||||
testContactTwo.sessionid,
|
||||
`Test user -> Dragon (TC2): ${Date.now()}`
|
||||
userC.sessionid,
|
||||
`${userA.userName} -> ${userC.userName}: ${Date.now()}`
|
||||
);
|
||||
// Send message from Dragon to user A
|
||||
await sendNewMessage(windowC, testUser.sessionid, `Dragon (TC2) -> Test user : ${Date.now()}`);
|
||||
await sendNewMessage(
|
||||
windowC,
|
||||
userA.sessionid,
|
||||
`${userC.userName} -> ${userA.userName} : ${Date.now()}`
|
||||
);
|
||||
// Send message from user A to Fish(TC3)
|
||||
await sendNewMessage(
|
||||
windowA,
|
||||
testContactThree.sessionid,
|
||||
`Test user -> Fish (TC3): ${Date.now()}`
|
||||
userD.sessionid,
|
||||
`${userA.userName} -> ${userD.userName}: ${Date.now()}`
|
||||
);
|
||||
// Send message from Fish to user A
|
||||
await sendNewMessage(windowD, testUser.sessionid, `Fish (TC3) -> Test user : ${Date.now()}`);
|
||||
await sendNewMessage(
|
||||
windowD,
|
||||
userA.sessionid,
|
||||
`${userD.userName} -> ${userA.userName} : ${Date.now()}`
|
||||
);
|
||||
// Send message from user A to Gopher(TC4)
|
||||
await sendNewMessage(
|
||||
windowA,
|
||||
testContactFour.sessionid,
|
||||
`Test user -> Gopher (TC4): ${Date.now()}`
|
||||
userE.sessionid,
|
||||
`${userA.userName} -> ${userD.userName}: ${Date.now()}`
|
||||
);
|
||||
// Send message from Gopher to user A
|
||||
await sendNewMessage(windowE, testUser.sessionid, `Gopher (TC4) -> Test user : ${Date.now()}`);
|
||||
await sendNewMessage(
|
||||
windowE,
|
||||
userA.sessionid,
|
||||
`${userD.userName} -> ${userA.userName} : ${Date.now()}`
|
||||
);
|
||||
});
|
||||
|
|
70
ts/test/automation/linked_device_group.spec.ts
Normal file
70
ts/test/automation/linked_device_group.spec.ts
Normal file
|
@ -0,0 +1,70 @@
|
|||
import { test } from '@playwright/test';
|
||||
import { sleepFor } from '../../session/utils/Promise';
|
||||
import { beforeAllClean } from './setup/beforeEach';
|
||||
import { createGroup } from './setup/create_group';
|
||||
import { newUser } from './setup/new_user';
|
||||
import { openApp } from './setup/open';
|
||||
import { leaveGroup } from './utilities/leave_group';
|
||||
import { linkedDevice } from './utilities/linked_device';
|
||||
import {
|
||||
clickOnTestIdWithText,
|
||||
waitForControlMessageWithText,
|
||||
waitForTestIdWithText,
|
||||
} from './utilities/utils';
|
||||
|
||||
test.beforeEach(beforeAllClean);
|
||||
|
||||
test('Check group syncs', async () => {
|
||||
const [windowA, windowC, windowD] = await openApp(3);
|
||||
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);
|
||||
});
|
||||
|
||||
test('Check leaving group syncs', async () => {
|
||||
const [windowA, windowC, windowD] = await openApp(3);
|
||||
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.`);
|
||||
});
|
62
ts/test/automation/linked_device_requests.spec.ts
Normal file
62
ts/test/automation/linked_device_requests.spec.ts
Normal file
|
@ -0,0 +1,62 @@
|
|||
import { test } from '@playwright/test';
|
||||
import { beforeAllClean } from './setup/beforeEach';
|
||||
// import { leaveGroup } from './utilities/leave_group';
|
||||
import { newUser } from './setup/new_user';
|
||||
import { openApp } from './setup/open';
|
||||
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';
|
||||
|
||||
test.beforeEach(beforeAllClean);
|
||||
|
||||
test('Accept request syncs', async () => {
|
||||
const [windowA, windowB] = await openApp(2);
|
||||
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);
|
||||
});
|
||||
|
||||
test('Decline request syncs', async () => {
|
||||
const [windowA, windowB] = await openApp(2);
|
||||
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);
|
||||
// Accept 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 waitForTestIdWithText(windowB, 'session-toast', 'Blocked');
|
||||
|
||||
await waitForMatchingText(windowB, 'No pending message requests');
|
||||
await waitForMatchingText(windowC, 'No pending message requests');
|
||||
});
|
178
ts/test/automation/linked_device_user.spec.ts
Normal file
178
ts/test/automation/linked_device_user.spec.ts
Normal file
|
@ -0,0 +1,178 @@
|
|||
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,
|
||||
waitForLoadingAnimationToFinish,
|
||||
waitForMatchingText,
|
||||
waitForTestIdWithText,
|
||||
waitForTextMessage,
|
||||
} from './utilities/utils';
|
||||
|
||||
const windows: Array<Page> = [];
|
||||
test.beforeEach(beforeAllClean);
|
||||
|
||||
test.afterEach(() => forceCloseAllWindows(windows));
|
||||
// tslint:disable: no-console
|
||||
|
||||
test('Link a device', async () => {
|
||||
const [windowA] = await openApp(1);
|
||||
const userA = await newUser(windowA, 'Alice');
|
||||
const [windowB] = await linkedDevice(userA.recoveryPhrase);
|
||||
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('Check 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('Check profile picture syncs', async () => {
|
||||
const [windowA] = await openApp(1);
|
||||
const userA = await newUser(windowA, 'Alice');
|
||||
const [windowB] = await linkedDevice(userA.recoveryPhrase);
|
||||
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');
|
||||
|
||||
await sleepFor(500);
|
||||
const leftpaneAvatarContainer = await waitForTestIdWithText(windowB, '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' });
|
||||
});
|
||||
|
||||
test('Check contacts sync', 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);
|
||||
// Waiting for linked device to finish loading
|
||||
await waitForLoadingAnimationToFinish(windowB, 'loading-spinner');
|
||||
await createContact(windowA, windowC, userA, userB);
|
||||
// Check linked device (windowB)
|
||||
await waitForTestIdWithText(windowB, 'module-conversation__user__profile-name', userB.userName);
|
||||
console.info('Contacts correctly synced');
|
||||
});
|
||||
|
||||
test('Check 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 waitForLoadingAnimationToFinish(windowB, 'loading-spinner');
|
||||
await createContact(windowA, windowC, userA, userB);
|
||||
await sendMessage(windowA, deletedMessage);
|
||||
// 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 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);
|
||||
// Check 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('Check 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 waitForLoadingAnimationToFinish(windowB, 'loading-spinner');
|
||||
await createContact(windowA, windowC, userA, userB);
|
||||
await sendMessage(windowA, unsentMessage);
|
||||
// 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 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');
|
||||
// Check linked device for deleted message
|
||||
await hasTextElementBeenDeleted(windowB, unsentMessage, 1000);
|
||||
});
|
||||
|
||||
// test('Check 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 waitForLoadingAnimationToFinish(windowB, 'loading-spinner');
|
||||
// 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 waitForMatchingText(windowA, 'Unblock this contact to send a message.');
|
||||
// // Check linked device for blocked contact in settings screen
|
||||
// await clickOnTestIdWithText(windowB, 'settings-section');
|
||||
// await clickOnTestIdWithText(windowB, 'conversations-settings-menu-item');
|
||||
// await clickOnTestIdWithText(windowB, 'reveal-blocked-user-settings');
|
||||
// // Check if user B is in blocked contact list
|
||||
// await waitForMatchingText(windowB, userB.userName);
|
||||
// });
|
Binary file not shown.
After Width: | Height: | Size: 1.3 KiB |
|
@ -1,52 +0,0 @@
|
|||
import { _electron, Page, test } from '@playwright/test';
|
||||
import { beforeAllClean, forceCloseAllWindows } from './setup/beforeEach';
|
||||
import { linkedDevice } from './setup/linked_device';
|
||||
import { clickOnTestIdWithText, typeIntoInput, waitForTestIdWithText } from './utils';
|
||||
|
||||
const windows: Array<Page> = [];
|
||||
test.beforeEach(beforeAllClean);
|
||||
|
||||
test.afterEach(() => forceCloseAllWindows(windows));
|
||||
// tslint:disable: no-console
|
||||
|
||||
test('linking device', async () => {
|
||||
const { windowA1, windowA2, userA } = await linkedDevice();
|
||||
windows.push(windowA1, windowA2);
|
||||
|
||||
await clickOnTestIdWithText(windowA1, 'leftpane-primary-avatar');
|
||||
// Verify Username
|
||||
await waitForTestIdWithText(windowA1, 'your-profile-name', userA.userName);
|
||||
// Verify Session ID
|
||||
await waitForTestIdWithText(windowA1, 'your-session-id', userA.sessionid);
|
||||
// exit profile module
|
||||
await clickOnTestIdWithText(windowA1, 'modal-close-button');
|
||||
// You're almost finished isn't displayed
|
||||
const errorDesc = 'Should not be found';
|
||||
try {
|
||||
const elemShouldNotBeFound = windowA2.locator('[data-testid=reveal-recovery-phrase]');
|
||||
if (elemShouldNotBeFound) {
|
||||
console.error('Element not found');
|
||||
throw new Error(errorDesc);
|
||||
}
|
||||
} catch (e) {
|
||||
if (e.message !== errorDesc) {
|
||||
// this is NOT ok
|
||||
throw e;
|
||||
}
|
||||
}
|
||||
await clickOnTestIdWithText(windowA1, 'leftpane-primary-avatar');
|
||||
// Click on pencil icon
|
||||
await clickOnTestIdWithText(windowA1, 'edit-profile-icon');
|
||||
// Replace old username with new username
|
||||
const newUsername = 'new-username';
|
||||
await typeIntoInput(windowA1, 'profile-name-input', newUsername);
|
||||
// Press enter to confirm change
|
||||
await windowA1.keyboard.press('Enter');
|
||||
// Wait for loading animation
|
||||
// Check username change in window B2
|
||||
// Click on profile settings in window B
|
||||
await clickOnTestIdWithText(windowA2, 'leftpane-primary-avatar');
|
||||
// Verify username has changed to new username
|
||||
await waitForTestIdWithText(windowA2, 'your-profile-name', newUsername);
|
||||
// Check message is deleting on both devices
|
||||
});
|
|
@ -1,51 +0,0 @@
|
|||
import { _electron, Page, test } from '@playwright/test';
|
||||
import { beforeAllClean, forceCloseAllWindows } from './setup/beforeEach';
|
||||
import { clickOnTestIdWithText, typeIntoInput, waitForTestIdWithText } from './utils';
|
||||
import { createGroup } from './setup/create_group';
|
||||
|
||||
let windows: Array<Page> = [];
|
||||
test.beforeEach(beforeAllClean);
|
||||
|
||||
test.afterEach(() => forceCloseAllWindows(windows));
|
||||
|
||||
test('Mentions', async () => {
|
||||
const { userA, userB, userC, windowA, windowB, windowC } = await createGroup('Test Group Name');
|
||||
windows = [windowA, windowB, windowC];
|
||||
|
||||
// in windowA we should be able to mentions userB and userC
|
||||
|
||||
await clickOnTestIdWithText(
|
||||
windowA,
|
||||
'module-conversation__user__profile-name',
|
||||
'Test Group Name'
|
||||
);
|
||||
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',
|
||||
'Test Group Name'
|
||||
);
|
||||
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',
|
||||
'Test Group Name'
|
||||
);
|
||||
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);
|
||||
});
|
180
ts/test/automation/message_checks.spec.ts
Normal file
180
ts/test/automation/message_checks.spec.ts
Normal file
|
@ -0,0 +1,180 @@
|
|||
import { test } from '@playwright/test';
|
||||
import { sleepFor } from '../../session/utils/Promise';
|
||||
import { beforeAllClean } from './setup/beforeEach';
|
||||
import { newUser } from './setup/new_user';
|
||||
import { openApp } from './setup/open';
|
||||
import { createContact } from './utilities/create_contact';
|
||||
import { sendMessage } from './utilities/message';
|
||||
import { replyTo } from './utilities/reply_message';
|
||||
import {
|
||||
clickOnElement,
|
||||
clickOnMatchingText,
|
||||
clickOnTestIdWithText,
|
||||
hasTextElementBeenDeleted,
|
||||
typeIntoInput,
|
||||
waitForLoadingAnimationToFinish,
|
||||
waitForMatchingText,
|
||||
waitForTestIdWithText,
|
||||
waitForTextMessage,
|
||||
} from './utilities/utils';
|
||||
|
||||
test.beforeEach(beforeAllClean);
|
||||
|
||||
test('Send image and reply test', async () => {
|
||||
const [windowA, windowB] = await openApp(2);
|
||||
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);
|
||||
});
|
||||
|
||||
test('Send video and reply test', async () => {
|
||||
const [windowA, windowB] = await openApp(2);
|
||||
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);
|
||||
});
|
||||
|
||||
test('Send document and reply test', async () => {
|
||||
const [windowA, windowB] = await openApp(2);
|
||||
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);
|
||||
});
|
||||
|
||||
test('Send voice message and reply test', async () => {
|
||||
const [windowA, windowB] = await openApp(2);
|
||||
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');
|
||||
});
|
||||
|
||||
test('Send GIF and reply test', async () => {
|
||||
const [windowA, windowB] = await openApp(2);
|
||||
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');
|
||||
});
|
||||
|
||||
test('Send long text and reply test', async () => {
|
||||
const [windowA, windowB] = await openApp(2);
|
||||
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 =
|
||||
'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);
|
||||
});
|
||||
|
||||
test('Unsend text message', async () => {
|
||||
const [windowA, windowB] = await openApp(2);
|
||||
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');
|
||||
});
|
||||
|
||||
test('Delete message', async () => {
|
||||
const [windowA, windowB] = await openApp(2);
|
||||
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 hasTextElementBeenDeleted(windowA, deletedMessage, 1000);
|
||||
// Still should exist in window B
|
||||
await waitForMatchingText(windowB, deletedMessage);
|
||||
});
|
||||
|
||||
// *************** NEED TO WAIT FOR LINK PREVIEW FIX *************************************************
|
||||
// test('Send link and reply test', async () => {
|
||||
// const [windowA, windowB] = await openApp(2);
|
||||
// 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);
|
||||
// });
|
|
@ -1,25 +1,27 @@
|
|||
import { _electron, Page, test } from '@playwright/test';
|
||||
import { sendNewMessage } from './send_message';
|
||||
import { beforeAllClean, forceCloseAllWindows } from './setup/beforeEach';
|
||||
import { openAppsAndNewUsers } from './setup/new_user';
|
||||
import { clickOnTestIdWithText, waitForMatchingText, waitForTestIdWithText } from './utils';
|
||||
import { test } from '@playwright/test';
|
||||
import { beforeAllClean } from './setup/beforeEach';
|
||||
import { newUser } from './setup/new_user';
|
||||
import { openApp } from './setup/open';
|
||||
import { sendMessage } from './utilities/message';
|
||||
import { sendNewMessage } from './utilities/send_message';
|
||||
import {
|
||||
clickOnMatchingText,
|
||||
clickOnTestIdWithText,
|
||||
waitForMatchingText,
|
||||
waitForTestIdWithText,
|
||||
} from './utilities/utils';
|
||||
|
||||
const testMessage = 'A -> B';
|
||||
|
||||
let windows: Array<Page> = [];
|
||||
test.beforeEach(beforeAllClean);
|
||||
|
||||
test.afterEach(() => forceCloseAllWindows(windows));
|
||||
// test.afterEach(() => forceCloseAllWindows(windows));
|
||||
// Open two windows and log into 2 separate accounts
|
||||
test.describe('Message requests', () => {
|
||||
test('Message request acceptance', async () => {
|
||||
const windowLoggedIn = await openAppsAndNewUsers(2);
|
||||
windows = windowLoggedIn.windows;
|
||||
const users = windowLoggedIn.users;
|
||||
const [windowA, windowB] = windows;
|
||||
const [userA, userB] = users;
|
||||
test('Message requests accept', async () => {
|
||||
const [windowA, windowB] = await openApp(2);
|
||||
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}${Date.now()}`);
|
||||
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
|
||||
|
@ -29,19 +31,38 @@ test.describe('Message requests', () => {
|
|||
// Check config message of message request acceptance
|
||||
await waitForTestIdWithText(
|
||||
windowB,
|
||||
'readable-message',
|
||||
'control-message',
|
||||
`You have accepted ${userA.userName}'s message request`
|
||||
);
|
||||
await waitForMatchingText(windowB, 'No pending message requests');
|
||||
});
|
||||
test('Message request rejection', async () => {
|
||||
const windowLoggedIn = await openAppsAndNewUsers(2);
|
||||
windows = windowLoggedIn.windows;
|
||||
const users = windowLoggedIn.users;
|
||||
const [windowA, windowB] = windows;
|
||||
const [userA, userB] = users;
|
||||
test('Message requests text reply', async () => {
|
||||
const [windowA, windowB] = await openApp(2);
|
||||
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}${Date.now()}`);
|
||||
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');
|
||||
});
|
||||
test('Message requests decline', async () => {
|
||||
const [windowA, windowB] = await openApp(2);
|
||||
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
|
||||
|
@ -54,4 +75,26 @@ test.describe('Message requests', () => {
|
|||
await waitForTestIdWithText(windowB, 'session-toast', 'Blocked');
|
||||
await waitForMatchingText(windowB, 'No pending message requests');
|
||||
});
|
||||
test('Message requests clear all', async () => {
|
||||
const [windowA, windowB] = await openApp(2);
|
||||
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');
|
||||
// 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)
|
||||
|
|
|
@ -1,35 +0,0 @@
|
|||
import { _electron, Page, test } from '@playwright/test';
|
||||
import { beforeAllClean, forceCloseAllWindows } from './setup/beforeEach';
|
||||
|
||||
import { sendNewMessage } from './send_message';
|
||||
import { openAppsAndNewUsers } from './setup/new_user';
|
||||
import { clickOnTestIdWithText, waitForTestIdWithText } from './utils';
|
||||
|
||||
const testMessage = 'A -> B';
|
||||
const testReply = 'B -> A';
|
||||
|
||||
let windows: Array<Page> = [];
|
||||
test.beforeEach(beforeAllClean);
|
||||
|
||||
test.afterEach(() => forceCloseAllWindows(windows));
|
||||
|
||||
// Send message in one to one conversation with new contact
|
||||
test('Send message to new contact', async () => {
|
||||
const windowLoggedIn = await openAppsAndNewUsers(2);
|
||||
windows = windowLoggedIn.windows;
|
||||
const users = windowLoggedIn.users;
|
||||
const [windowA, windowB] = windows;
|
||||
const [userA, userB] = users;
|
||||
// User A sends message to User B
|
||||
await sendNewMessage(windowA, userB.sessionid, `${testMessage}${Date.now()}`);
|
||||
// User B sends message to User B to USER A
|
||||
await sendNewMessage(windowB, userA.sessionid, `${testReply}${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');
|
||||
});
|
|
@ -1,6 +1,6 @@
|
|||
import { _electron, Page, test } from '@playwright/test';
|
||||
import { Page, test } from '@playwright/test';
|
||||
import { sleepFor } from '../../session/utils/Promise';
|
||||
import { beforeAllClean, forceCloseAllWindows } from './setup/beforeEach';
|
||||
import { beforeAllClean } from './setup/beforeEach';
|
||||
import { newUser } from './setup/new_user';
|
||||
import { openAppAndWait } from './setup/open';
|
||||
import {
|
||||
|
@ -9,127 +9,120 @@ import {
|
|||
typeIntoInput,
|
||||
waitForMatchingText,
|
||||
waitForTestIdWithText,
|
||||
} from './utils';
|
||||
} from './utilities/utils';
|
||||
let window: Page | undefined;
|
||||
// tslint:disable: no-console
|
||||
|
||||
test.beforeEach(beforeAllClean);
|
||||
|
||||
test.afterEach(async () => {
|
||||
if (window) {
|
||||
await forceCloseAllWindows([window]);
|
||||
}
|
||||
});
|
||||
|
||||
const testPassword = '123456';
|
||||
const newTestPassword = '789101112';
|
||||
|
||||
test.describe('Password checks', () => {
|
||||
test('Set Password', async () => {
|
||||
// open Electron
|
||||
window = await openAppAndWait('1');
|
||||
// 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
|
||||
test('Set Password', async () => {
|
||||
// open Electron
|
||||
window = await openAppAndWait('1');
|
||||
// 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);
|
||||
await typeIntoInput(window, 'password-input', testPassword);
|
||||
|
||||
// Click Done
|
||||
await clickOnMatchingText(window, 'Done');
|
||||
await clickOnTestIdWithText(window, 'settings-section');
|
||||
// Click Done
|
||||
await clickOnMatchingText(window, 'Done');
|
||||
await clickOnTestIdWithText(window, 'settings-section');
|
||||
|
||||
// Change password
|
||||
await clickOnTestIdWithText(window, 'change-password-settings-button', 'Change Password');
|
||||
// Change password
|
||||
await clickOnTestIdWithText(window, 'change-password-settings-button', 'Change Password');
|
||||
|
||||
console.info('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.'
|
||||
);
|
||||
});
|
||||
test('Wrong password', async () => {
|
||||
// Check if incorrect password works
|
||||
window = await openAppAndWait('1');
|
||||
// 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');
|
||||
});
|
||||
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.'
|
||||
);
|
||||
});
|
||||
|
||||
test('Wrong password', async () => {
|
||||
// Check if incorrect password works
|
||||
window = await openAppAndWait('1');
|
||||
// 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');
|
||||
});
|
||||
|
|
|
@ -1,7 +1,8 @@
|
|||
import { _electron, Page } from '@playwright/test';
|
||||
import { Page } from '@playwright/test';
|
||||
import { readdirSync, rmdirSync } from 'fs-extra';
|
||||
import { dirname, join } from 'path';
|
||||
import { MULTI_PREFIX, NODE_ENV, openElectronAppOnly } from './open';
|
||||
import { join } from 'path';
|
||||
import { isMacOS } from '../../../OS';
|
||||
import { MULTI_PREFIX, NODE_ENV } from './open';
|
||||
// tslint:disable: no-console
|
||||
|
||||
const getDirectoriesOfSessionDataPath = (source: string) =>
|
||||
|
@ -12,33 +13,21 @@ const getDirectoriesOfSessionDataPath = (source: string) =>
|
|||
})
|
||||
.filter(n => n.includes(`${NODE_ENV}-${MULTI_PREFIX}`));
|
||||
|
||||
let alreadyCleaned = false;
|
||||
const alreadyCleaned = false;
|
||||
let alreadyCleanedWaiting = false;
|
||||
|
||||
const cleanUpOtherTest = async () => {
|
||||
function cleanUpOtherTest() {
|
||||
if (alreadyCleaned || alreadyCleanedWaiting) {
|
||||
return;
|
||||
}
|
||||
alreadyCleaned = true;
|
||||
|
||||
const electronApp = await openElectronAppOnly('start');
|
||||
|
||||
const appPath = await electronApp.evaluate(async ({ app }) => {
|
||||
return app.getPath('userData');
|
||||
});
|
||||
const window = await electronApp.firstWindow();
|
||||
await window.close();
|
||||
if (alreadyCleaned && alreadyCleanedWaiting) {
|
||||
return;
|
||||
}
|
||||
alreadyCleanedWaiting = true;
|
||||
|
||||
if (!appPath.length) {
|
||||
throw new Error('appDataPath unset');
|
||||
const parentFolderOfAllDataPath = isMacOS() ? '~/Library/Application Support/' : null;
|
||||
if (!parentFolderOfAllDataPath) {
|
||||
throw new Error('Only macOS is currrently supported ');
|
||||
}
|
||||
|
||||
const parentFolderOfAllDataPath = dirname(appPath);
|
||||
|
||||
if (!parentFolderOfAllDataPath || parentFolderOfAllDataPath.length < 20) {
|
||||
throw new Error('parentFolderOfAllDataPath not found or invalid');
|
||||
}
|
||||
|
@ -48,14 +37,11 @@ const cleanUpOtherTest = async () => {
|
|||
console.info('allAppDataPath', allAppDataPath);
|
||||
|
||||
allAppDataPath.map(folder => {
|
||||
if (!appPath) {
|
||||
throw new Error('parentFolderOfAllDataPath unset');
|
||||
}
|
||||
const pathToRemove = join(parentFolderOfAllDataPath, folder);
|
||||
rmdirSync(pathToRemove, { recursive: true });
|
||||
});
|
||||
console.info('...done');
|
||||
};
|
||||
}
|
||||
|
||||
export const beforeAllClean = cleanUpOtherTest;
|
||||
|
||||
|
|
|
@ -1,29 +1,41 @@
|
|||
import { _electron, Page } from '@playwright/test';
|
||||
import { messageSent } from '../message';
|
||||
import { openAppsAndNewUsers } from '../setup/new_user';
|
||||
import { sendNewMessage } from '../send_message';
|
||||
import { sendMessage } from '../utilities/message';
|
||||
import { sendNewMessage } from '../utilities/send_message';
|
||||
import {
|
||||
clickOnMatchingText,
|
||||
clickOnTestIdWithText,
|
||||
typeIntoInput,
|
||||
waitForReadableMessageWithText,
|
||||
waitForControlMessageWithText,
|
||||
waitForTestIdWithText,
|
||||
} from '../utils';
|
||||
} from '../utilities/utils';
|
||||
import { Group, User } from '../types/testing';
|
||||
|
||||
let windows: Array<Page> = [];
|
||||
// let windows: Array<Page> = [];
|
||||
|
||||
export const createGroup = async (groupName: string) => {
|
||||
const windowLoggedIn = await openAppsAndNewUsers(3);
|
||||
windows = windowLoggedIn.windows;
|
||||
const users = windowLoggedIn.users;
|
||||
const [windowA, windowB, windowC] = windows;
|
||||
const [userA, userB, userC] = users;
|
||||
export const createGroup = async (
|
||||
userName: string,
|
||||
userOne: User,
|
||||
windowA: Page,
|
||||
userTwo: User,
|
||||
windowB: Page,
|
||||
userThree: User,
|
||||
windowC: Page
|
||||
): Promise<Group> => {
|
||||
const group: Group = { userName, userOne, userTwo, userThree };
|
||||
|
||||
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, userC.sessionid, `A -> C: ${Date.now()}`);
|
||||
await sendNewMessage(windowA, userThree.sessionid, `${messageAC} Time: ${Date.now()}`);
|
||||
await Promise.all([
|
||||
sendNewMessage(windowA, userB.sessionid, `A -> B: ${Date.now()}`),
|
||||
sendNewMessage(windowB, userA.sessionid, `B -> A: ${Date.now()}`),
|
||||
sendNewMessage(windowC, userA.sessionid, `C -> A: ${Date.now()}`),
|
||||
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');
|
||||
|
@ -33,47 +45,44 @@ export const createGroup = async (groupName: string) => {
|
|||
await clickOnTestIdWithText(windowA, 'new-conversation-button');
|
||||
await clickOnTestIdWithText(windowA, 'chooser-new-group');
|
||||
// Enter group name
|
||||
await typeIntoInput(windowA, 'new-closed-group-name', groupName);
|
||||
await typeIntoInput(windowA, 'new-closed-group-name', group.userName);
|
||||
// Select user B
|
||||
await clickOnMatchingText(windowA, userB.userName);
|
||||
await clickOnMatchingText(windowA, userTwo.userName);
|
||||
// Select user C
|
||||
await clickOnMatchingText(windowA, userC.userName);
|
||||
await clickOnMatchingText(windowA, userThree.userName);
|
||||
// Click Next
|
||||
await clickOnTestIdWithText(windowA, 'next-button');
|
||||
// Check group was successfully created
|
||||
await clickOnMatchingText(windowB, groupName);
|
||||
await waitForTestIdWithText(windowB, 'header-conversation-name', groupName);
|
||||
await clickOnMatchingText(windowB, group.userName);
|
||||
await waitForTestIdWithText(windowB, 'header-conversation-name', group.userName);
|
||||
// Send message in group chat from user A
|
||||
const msgAToGroup = 'A -> Group';
|
||||
await messageSent(windowA, msgAToGroup);
|
||||
await sendMessage(windowA, msgAToGroup);
|
||||
// Focus screen
|
||||
await clickOnMatchingText(windowA, msgAToGroup);
|
||||
// Verify it was received by other two accounts
|
||||
// Navigate to group in window B
|
||||
await clickOnTestIdWithText(windowB, 'message-section');
|
||||
// Click on test group
|
||||
await clickOnMatchingText(windowB, groupName);
|
||||
await clickOnMatchingText(windowB, userName);
|
||||
// wait for selector 'test message' in chat window
|
||||
await waitForReadableMessageWithText(windowB, msgAToGroup);
|
||||
await waitForControlMessageWithText(windowB, msgAToGroup);
|
||||
// Send reply message
|
||||
const msgBToGroup = 'B -> Group';
|
||||
await messageSent(windowB, msgBToGroup);
|
||||
await sendMessage(windowB, msgBToGroup);
|
||||
// Focus screen
|
||||
// await clickOnTestIdWithText(windowB, 'scroll-to-bottom-button');
|
||||
await clickOnMatchingText(windowB, msgBToGroup);
|
||||
// Navigate to group in window C
|
||||
await clickOnTestIdWithText(windowC, 'message-section');
|
||||
// Click on test group
|
||||
await clickOnMatchingText(windowC, groupName);
|
||||
await clickOnMatchingText(windowC, userName);
|
||||
// windowC must see the message from A and the message from B
|
||||
await waitForReadableMessageWithText(windowC, msgAToGroup);
|
||||
await waitForReadableMessageWithText(windowC, msgBToGroup);
|
||||
await waitForControlMessageWithText(windowC, msgAToGroup);
|
||||
await waitForControlMessageWithText(windowC, msgBToGroup);
|
||||
// Send message from C to the group
|
||||
const msgCToGroup = 'C -> Group';
|
||||
await messageSent(windowC, msgCToGroup);
|
||||
await sendMessage(windowC, msgCToGroup);
|
||||
// windowA should see the message from B and the message from C
|
||||
await waitForReadableMessageWithText(windowA, msgBToGroup);
|
||||
await waitForReadableMessageWithText(windowA, msgCToGroup);
|
||||
await waitForControlMessageWithText(windowA, msgBToGroup);
|
||||
await waitForControlMessageWithText(windowA, msgCToGroup);
|
||||
|
||||
return { userA, userB, windowA, windowB, userC, windowC };
|
||||
return { userName, userOne, userTwo, userThree };
|
||||
};
|
||||
|
|
|
@ -1,15 +0,0 @@
|
|||
import { _electron } from 'playwright-core';
|
||||
import { openAppsAndNewUsers, openAppsNoNewUsers } from './new_user';
|
||||
import { logIn } from '../setup/log_in';
|
||||
|
||||
export async function linkedDevice() {
|
||||
const windowLoggedIn = await openAppsAndNewUsers(1);
|
||||
const [windowA1] = windowLoggedIn.windows;
|
||||
const users = windowLoggedIn.users;
|
||||
const [userA] = users;
|
||||
const [windowA2] = await openAppsNoNewUsers(1);
|
||||
|
||||
await logIn(windowA2, userA.recoveryPhrase);
|
||||
|
||||
return { windowA1, windowA2, userA };
|
||||
}
|
|
@ -1,10 +1,20 @@
|
|||
import { _electron, Page } from '@playwright/test';
|
||||
import { clickOnTestIdWithText, typeIntoInput } from '../utils';
|
||||
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');
|
||||
|
||||
return { window };
|
||||
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.'
|
||||
);
|
||||
}
|
||||
|
|
|
@ -1,16 +1,8 @@
|
|||
import { _electron, Page } from '@playwright/test';
|
||||
import _ from 'lodash';
|
||||
import { clickOnMatchingText, typeIntoInput } from '../utils';
|
||||
import { openAppAndWait } from './open';
|
||||
const multisAvailable = 'ABCDEFGHIJKLMNOPQRSTUVWXYZ';
|
||||
|
||||
export type UserLoggedInType = {
|
||||
userName: string;
|
||||
sessionid: string;
|
||||
recoveryPhrase: string;
|
||||
};
|
||||
|
||||
export const newUser = async (window: Page, userName: string): Promise<UserLoggedInType> => {
|
||||
import { Page } from '@playwright/test';
|
||||
import { User } from '../types/testing';
|
||||
import { clickOnMatchingText, typeIntoInput } from '../utilities/utils';
|
||||
// tslint:disable: no-console
|
||||
export const newUser = async (window: Page, userName: string): Promise<User> => {
|
||||
// Create User
|
||||
await clickOnMatchingText(window, 'Create Session ID');
|
||||
// Wait for animation for finish creating ID
|
||||
|
@ -25,46 +17,34 @@ export const newUser = async (window: Page, userName: string): Promise<UserLogge
|
|||
await clickOnMatchingText(window, 'Reveal Recovery Phrase');
|
||||
const recoveryPhrase = await window.innerText('[data-testid=recovery-phrase-seed-modal]');
|
||||
|
||||
console.info(`${userName}: Session ID: ${sessionid} and Recovery phrase: ${recoveryPhrase}`);
|
||||
await window.click('.session-icon-button.small');
|
||||
return { userName, sessionid, recoveryPhrase };
|
||||
};
|
||||
|
||||
const openAppAndNewUser = async (multi: string): Promise<UserLoggedInType & { window: Page }> => {
|
||||
const window = await openAppAndWait(multi);
|
||||
// const openAppAndNewUser = async (multi: string): Promise<User & { window: Page }> => {
|
||||
// const window = await openAppAndWait(multi);
|
||||
|
||||
const userName = `${multi}-user`;
|
||||
const loggedIn = await newUser(window, userName);
|
||||
return { window, ...loggedIn };
|
||||
};
|
||||
// const userName = `${multi}-user`;
|
||||
// const loggedIn = await newUser(window, userName);
|
||||
// return { window, ...loggedIn };
|
||||
// };
|
||||
|
||||
export async function openAppsAndNewUsers(windowToCreate: number) {
|
||||
if (windowToCreate >= 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, windowToCreate);
|
||||
const loggedInDetails = await Promise.all(
|
||||
[...multisToUse].map(async m => {
|
||||
return openAppAndNewUser(m);
|
||||
})
|
||||
);
|
||||
// export async function openAppsAndNewUsers(windowToCreate: number) {
|
||||
// if (windowToCreate >= 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, windowToCreate);
|
||||
// const loggedInDetails = await Promise.all(
|
||||
// [...multisToUse].map(async m => {
|
||||
// return openAppAndNewUser(m);
|
||||
// })
|
||||
// );
|
||||
|
||||
const windows = loggedInDetails.map(w => w.window);
|
||||
const users = loggedInDetails.map(w => {
|
||||
return _.pick(w, ['sessionid', 'recoveryPhrase', 'userName']);
|
||||
});
|
||||
return { windows, users };
|
||||
}
|
||||
|
||||
export async function openAppsNoNewUsers(windowToCreate: number) {
|
||||
if (windowToCreate >= 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, windowToCreate);
|
||||
return Promise.all(
|
||||
[...multisToUse].map(async m => {
|
||||
return openAppAndWait(`${m}`);
|
||||
})
|
||||
);
|
||||
}
|
||||
// const windows = loggedInDetails.map(w => w.window);
|
||||
// const users = loggedInDetails.map(w => {
|
||||
// return _.pick(w, ['sessionid', 'recoveryPhrase', 'userName']);
|
||||
// });
|
||||
// return { windows, users };
|
||||
// }
|
||||
|
|
|
@ -4,8 +4,22 @@ import { getAppRootPath } from '../../../node/getRootPath';
|
|||
|
||||
export const NODE_ENV = 'production';
|
||||
export const MULTI_PREFIX = 'test-integration-testnet-';
|
||||
const multisAvailable = 'ABCDEFGHIJKLMNOPQRSTUVWXYZ';
|
||||
// tslint:disable: no-console
|
||||
|
||||
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;
|
||||
|
|
|
@ -1,5 +1,5 @@
|
|||
import { _electron, Page } from '@playwright/test';
|
||||
import { clickOnTestIdWithText, typeIntoInput } from '../utils';
|
||||
import { clickOnTestIdWithText, typeIntoInput } from '../utilities/utils';
|
||||
|
||||
export async function recoverFromSeed(window: Page, userName: string, recoveryPhrase: string) {
|
||||
await clickOnTestIdWithText(window, 'restore-using-recovery');
|
||||
|
|
|
@ -1,36 +1,36 @@
|
|||
import { _electron } from '@playwright/test';
|
||||
|
||||
export const testUser = {
|
||||
userName: 'testUser',
|
||||
sessionid: '05560802be231abc2fbaa860f09da4c2f20dafa4e5f560f77d61c5f587ef2c741f',
|
||||
export const userA = {
|
||||
userName: 'Alice',
|
||||
sessionid: '059e36f9bb03ac4e1ff9ff7d4aedd791d1f412770c6cd2796b855af12a7c7ea000',
|
||||
recoveryPhrase:
|
||||
'pinched total ongoing sushi etched rest gone long oilfield incur code grunt code',
|
||||
'tuition remedy sieve ivory wiggle gemstone hawk optical issued damp selfish fewest damp',
|
||||
};
|
||||
|
||||
export const testContactOne = {
|
||||
userName: 'Whale',
|
||||
sessionid: '059c587e1e027368d4a0ebbf5982fe25e4129fdd79c2328616ceb394cbaf852c52',
|
||||
export const userB = {
|
||||
userName: 'Bob',
|
||||
sessionid: '05ead902602c1f7b59aaa3932b9cdefe8ee4075c03b09811d31bc9b122cb292d0c',
|
||||
recoveryPhrase:
|
||||
'jeers apart cuffs mailed sleepless mystery dads tobacco elite lopped fudge arena mystery',
|
||||
'misery testing template jeopardy yahoo asylum kettle wise unveil wept bygones dice dice',
|
||||
};
|
||||
|
||||
export const testContactTwo = {
|
||||
userName: 'Dragon',
|
||||
sessionid: '05c189b54cea50fa7a3e1fc3ddb6e9c5bcf34ffa7d17af5d8478a45d5a8f629e02',
|
||||
export const userC = {
|
||||
userName: 'Chloe',
|
||||
sessionid: '055f4bcc665b94a0f4c2aa9c2d543ae015db167014aac316bc21f5d7c6fdb11025',
|
||||
recoveryPhrase:
|
||||
'gossip megabyte rogue pheasants rural romance opus grunt amidst runway erected unveil opus',
|
||||
'bakery broken circle ginger pistons deity deity degrees today insult fidget ouch deity',
|
||||
};
|
||||
|
||||
export const testContactThree = {
|
||||
userName: 'Fish',
|
||||
sessionid: '058781e8f5845c22649c6c6e9fdb5c98e63e04832aec78fe6cacd62c3e71600464',
|
||||
export const userD = {
|
||||
userName: 'Doug',
|
||||
sessionid: '0555274f98d9f681d37446797bdebfa0e53d872213450663141bedb58a8ca67675',
|
||||
recoveryPhrase:
|
||||
'hookup reinvest deepest waxing lukewarm aztec invoke fugitive aces onward hire tomorrow hire',
|
||||
'biscuit bomb hire update suede money balding rest fuming alchemy ridges deity update',
|
||||
};
|
||||
|
||||
export const testContactFour = {
|
||||
userName: 'Gopher',
|
||||
sessionid: '0577ee81a6ac9c1a6f80daddcc22a85bd0dc9cfc3a513b5d2368e2da483886ca11',
|
||||
export const userE = {
|
||||
userName: 'Egbert',
|
||||
sessionid: '058b523d3f00773c745c965cf9482dd2fd6ea7a67ec4643c187309e4bbf96a936a',
|
||||
recoveryPhrase:
|
||||
'odds annoyed maps apply diplomat custom boat iceberg extra kitchens adventure luggage maps',
|
||||
'dusted coffee hoisting ringing titans dangerous technical bomb bubble pancakes wipeout goldfish technical',
|
||||
};
|
||||
|
|
|
@ -1,19 +1,18 @@
|
|||
import { _electron, expect, Page, test } from '@playwright/test';
|
||||
import { beforeAllClean, forceCloseAllWindows } from './setup/beforeEach';
|
||||
import { openAppsAndNewUsers } from './setup/new_user';
|
||||
import { clickOnTestIdWithText } from './utils';
|
||||
import { expect, test } from '@playwright/test';
|
||||
import { beforeAllClean } from './setup/beforeEach';
|
||||
import { newUser } from './setup/new_user';
|
||||
import { openApp } from './setup/open';
|
||||
import { clickOnTestIdWithText } from './utilities/utils';
|
||||
|
||||
let windows: Array<Page> = [];
|
||||
test.beforeEach(beforeAllClean);
|
||||
|
||||
test.afterEach(() => forceCloseAllWindows(windows));
|
||||
// test.afterEach(() => forceCloseAllWindows(windows));
|
||||
|
||||
test('Switch themes', async () => {
|
||||
// Open App
|
||||
const [windowA] = await openApp(1);
|
||||
// Create User
|
||||
const windowLoggedIn = await openAppsAndNewUsers(1);
|
||||
windows = windowLoggedIn.windows;
|
||||
const [windowA] = windows;
|
||||
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)');
|
||||
|
|
11
ts/test/automation/test.spec.ts
Normal file
11
ts/test/automation/test.spec.ts
Normal file
|
@ -0,0 +1,11 @@
|
|||
import { test } from '@playwright/test';
|
||||
import { beforeAllClean } from './setup/beforeEach';
|
||||
import { openApp } from './setup/open';
|
||||
import { clickOnMatchingText } from './utilities/utils';
|
||||
|
||||
test.beforeEach(beforeAllClean);
|
||||
|
||||
test('Tiny test', async () => {
|
||||
const [windowA] = await openApp(1);
|
||||
await clickOnMatchingText(windowA, 'Create Session ID');
|
||||
});
|
1
ts/test/automation/to do
Normal file
1
ts/test/automation/to do
Normal file
|
@ -0,0 +1 @@
|
|||
//
|
16
ts/test/automation/types/testing.ts
Normal file
16
ts/test/automation/types/testing.ts
Normal file
|
@ -0,0 +1,16 @@
|
|||
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';
|
|
@ -1,41 +0,0 @@
|
|||
import { _electron, Page, test } from '@playwright/test';
|
||||
import { beforeAllClean, forceCloseAllWindows } from './setup/beforeEach';
|
||||
import { openAppsAndNewUsers } from './setup/new_user';
|
||||
import { sendNewMessage } from './send_message';
|
||||
import {
|
||||
clickOnMatchingText,
|
||||
clickOnTestIdWithText,
|
||||
waitForMatchingText,
|
||||
waitForTestIdWithText,
|
||||
} from './utils';
|
||||
|
||||
const testMessage = 'A -> B: ';
|
||||
const testReply = 'B -> A: ';
|
||||
|
||||
let windows: Array<Page> = [];
|
||||
test.beforeEach(beforeAllClean);
|
||||
|
||||
test.afterEach(() => forceCloseAllWindows(windows));
|
||||
|
||||
test('Unsend message', async () => {
|
||||
// Open App
|
||||
const windowLoggedIn = await openAppsAndNewUsers(2);
|
||||
windows = windowLoggedIn.windows;
|
||||
const users = windowLoggedIn.users;
|
||||
const [windowA, windowB] = windows;
|
||||
const [userA, userB] = users;
|
||||
// Send message between two users
|
||||
await sendNewMessage(windowA, userB.sessionid, `${testMessage}${Date.now()}`);
|
||||
await sendNewMessage(windowB, userA.sessionid, `${testReply}${Date.now()}`);
|
||||
// Unsend message from User A to User B
|
||||
// Right click on message
|
||||
await windowA.click('.module-message.module-message--outgoing', { button: 'right' });
|
||||
// Select delete for everyone
|
||||
await clickOnMatchingText(windowA, 'Delete for everyone');
|
||||
// Select delete for everyone confirmation
|
||||
await clickOnTestIdWithText(windowA, 'session-confirm-ok-button', 'Delete for everyone');
|
||||
// Check that toast notification opens and says 'deleted'
|
||||
await waitForTestIdWithText(windowA, 'session-toast', 'Deleted');
|
||||
// Check that message is deleted in receivers window
|
||||
await waitForMatchingText(windowB, 'This message has been deleted');
|
||||
});
|
197
ts/test/automation/user_actions.spec.ts
Normal file
197
ts/test/automation/user_actions.spec.ts
Normal file
|
@ -0,0 +1,197 @@
|
|||
import { expect, test } from '@playwright/test';
|
||||
import { beforeAllClean } from './setup/beforeEach';
|
||||
import { sleepFor } from '../../session/utils/Promise';
|
||||
import { newUser } from './setup/new_user';
|
||||
import { sendNewMessage } from './utilities/send_message';
|
||||
import {
|
||||
clickOnMatchingText,
|
||||
clickOnTestIdWithText,
|
||||
typeIntoInput,
|
||||
typeIntoInputSlow,
|
||||
waitForMatchingText,
|
||||
waitForTestIdWithText,
|
||||
} from './utilities/utils';
|
||||
import { openApp } from './setup/open';
|
||||
import { createContact } from './utilities/create_contact';
|
||||
|
||||
test.beforeEach(beforeAllClean);
|
||||
|
||||
// test.afterEach(() => forceCloseAllWindows(windows));
|
||||
|
||||
// Send message in one to one conversation with new contact
|
||||
test('Create contact', async () => {
|
||||
const [windowA, windowB] = await openApp(2);
|
||||
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');
|
||||
});
|
||||
|
||||
test('Block user in conversation options', async () => {
|
||||
// Open app and create user
|
||||
const [windowA, windowB] = await openApp(2);
|
||||
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');
|
||||
});
|
||||
|
||||
test('Block user in conversation list', async () => {
|
||||
// Open app and create user
|
||||
const [windowA, windowB] = await openApp(2);
|
||||
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');
|
||||
});
|
||||
|
||||
test('Change username', async () => {
|
||||
// Open App
|
||||
const [window] = await openApp(1);
|
||||
// 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');
|
||||
});
|
||||
|
||||
test('Change avatar', async () => {
|
||||
const [window] = await openApp(1);
|
||||
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' });
|
||||
});
|
||||
|
||||
test('Set nickname', async () => {
|
||||
const [windowA, windowB] = await openApp(2);
|
||||
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);
|
||||
});
|
Binary file not shown.
After Width: | Height: | Size: 1,014 B |
20
ts/test/automation/utilities/create_contact.ts
Normal file
20
ts/test/automation/utilities/create_contact.ts
Normal file
|
@ -0,0 +1,20 @@
|
|||
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');
|
||||
};
|
|
@ -9,5 +9,5 @@ export const leaveGroup = async (window: Page) => {
|
|||
// Confirm leave group
|
||||
await clickOnTestIdWithText(window, 'session-confirm-ok-button', 'OK');
|
||||
// check config message
|
||||
await waitForTestIdWithText(window, 'readable-message', 'You have left the group.');
|
||||
await waitForTestIdWithText(window, 'control-message', 'You have left the group.');
|
||||
};
|
11
ts/test/automation/utilities/linked_device.ts
Normal file
11
ts/test/automation/utilities/linked_device.ts
Normal file
|
@ -0,0 +1,11 @@
|
|||
import { _electron } from 'playwright-core';
|
||||
import { logIn } from '../setup/log_in';
|
||||
import { openApp } from '../setup/open';
|
||||
|
||||
export async function linkedDevice(recoveryPhrase: string) {
|
||||
const [windowB] = await openApp(1);
|
||||
|
||||
await logIn(windowB, recoveryPhrase);
|
||||
|
||||
return [windowB];
|
||||
}
|
|
@ -2,13 +2,13 @@ import { _electron, Page } from '@playwright/test';
|
|||
import { clickOnTestIdWithText, typeIntoInput } from './utils';
|
||||
// tslint:disable: no-console
|
||||
|
||||
export const messageSent = async (window: Page, message: string) => {
|
||||
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=readable-message]:has-text("${message}"):has([data-testid=msg-status-outgoing][data-testtype=sent])`;
|
||||
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 });
|
11
ts/test/automation/utilities/reply_message.ts
Normal file
11
ts/test/automation/utilities/reply_message.ts
Normal file
|
@ -0,0 +1,11 @@
|
|||
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();
|
||||
};
|
|
@ -1,5 +1,5 @@
|
|||
import { _electron, Page } from '@playwright/test';
|
||||
import { messageSent } from './message';
|
||||
import { sendMessage } from './message';
|
||||
import { clickOnTestIdWithText, typeIntoInput } from './utils';
|
||||
|
||||
export const sendNewMessage = async (window: Page, sessionid: string, message: string) => {
|
||||
|
@ -9,5 +9,5 @@ export const sendNewMessage = async (window: Page, sessionid: string, message: s
|
|||
await typeIntoInput(window, 'new-session-conversation', sessionid);
|
||||
// click next
|
||||
await clickOnTestIdWithText(window, 'next-new-conversation-button', 'Next');
|
||||
await messageSent(window, message);
|
||||
await sendMessage(window, message);
|
||||
};
|
201
ts/test/automation/utilities/utils.ts
Normal file
201
ts/test/automation/utilities/utils.ts
Normal file
|
@ -0,0 +1,201 @@
|
|||
import { ElementHandle } from '@playwright/test';
|
||||
import { Page } from 'playwright-core';
|
||||
import { sleepFor } from '../../../session/utils/Promise';
|
||||
import { loaderType, Strategy } from '../types/testing';
|
||||
// tslint:disable: no-console
|
||||
|
||||
// WAIT FOR FUNCTIONS
|
||||
|
||||
export async function waitForTestIdWithText(window: Page, dataTestId: string, text?: string) {
|
||||
let builtSelector = `css=[data-testid=${dataTestId}]`;
|
||||
if (text) {
|
||||
// " => \\\"
|
||||
/* prettier-ignore */
|
||||
// tslint:disable-next-line: quotemark
|
||||
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
|
||||
) {
|
||||
const builtSelector = `css=[${strategy}=${selector}]`;
|
||||
|
||||
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 */
|
||||
// tslint:disable-next-line: quotemark
|
||||
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 waitForLoadingAnimationToFinish(
|
||||
window: Page,
|
||||
loader: loaderType,
|
||||
maxWait?: number
|
||||
) {
|
||||
let loadingAnimation: ElementHandle<SVGElement | HTMLElement> | undefined;
|
||||
|
||||
await waitForElement(window, 'data-testid', `${loader}`, maxWait);
|
||||
|
||||
do {
|
||||
try {
|
||||
loadingAnimation = await waitForElement(window, 'data-testid', `${loader}`, 100);
|
||||
await sleepFor(100);
|
||||
console.info('loading-animation was found, waiting for it to be gone');
|
||||
} catch (e) {
|
||||
loadingAnimation = undefined;
|
||||
}
|
||||
} while (loadingAnimation);
|
||||
console.info('Loading animation has finished');
|
||||
}
|
||||
|
||||
// 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);
|
||||
return;
|
||||
}
|
||||
|
||||
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: string,
|
||||
text?: string,
|
||||
rightButton?: boolean
|
||||
) {
|
||||
console.info(`clickOnTestIdWithText with testId:${dataTestId} and text:${text ? text : 'none'}`);
|
||||
|
||||
const builtSelector = !text
|
||||
? `css=[data-testid=${dataTestId}]`
|
||||
: `css=[data-testid=${dataTestId}]:has-text("${text}")`;
|
||||
|
||||
await window.waitForSelector(builtSelector);
|
||||
return window.click(builtSelector, rightButton ? { button: 'right' } : undefined);
|
||||
}
|
||||
|
||||
export function getMessageTextContentNow() {
|
||||
return `Test message timestamp: ${Date.now()}`;
|
||||
}
|
||||
|
||||
export async function typeIntoInput(window: Page, dataTestId: string, 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: string, 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 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 doesTextIncludeString(window: Page, dataTestId: string, 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 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);
|
||||
}
|
||||
}
|
|
@ -1,54 +0,0 @@
|
|||
import { Page } from 'playwright-core';
|
||||
// tslint:disable: no-console
|
||||
|
||||
export async function waitForTestIdWithText(window: Page, dataTestId: string, text?: string) {
|
||||
let builtSelector = `css=[data-testid=${dataTestId}]`;
|
||||
if (text) {
|
||||
builtSelector += `:has-text("${text}")`;
|
||||
}
|
||||
|
||||
console.info('looking for selector', builtSelector);
|
||||
const found = await window.waitForSelector(builtSelector, { timeout: 55000 });
|
||||
console.info('found selector', builtSelector);
|
||||
|
||||
return found;
|
||||
}
|
||||
|
||||
export async function waitForReadableMessageWithText(window: Page, text: string) {
|
||||
return waitForTestIdWithText(window, 'readable-message', text);
|
||||
}
|
||||
|
||||
export async function waitForMatchingText(window: Page, text: string) {
|
||||
const builtSelector = `css=:has-text("${text}")`;
|
||||
console.info(`waitForMatchingText: ${text}`);
|
||||
|
||||
await window.waitForSelector(builtSelector, { timeout: 55000 });
|
||||
|
||||
console.info(`got matchingText: ${text}`);
|
||||
}
|
||||
|
||||
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: string, text?: string) {
|
||||
console.info(`clickOnTestIdWithText with testId:${dataTestId} and text:${text ? text : 'none'}`);
|
||||
|
||||
const builtSelector = !text
|
||||
? `css=[data-testid=${dataTestId}]`
|
||||
: `css=[data-testid=${dataTestId}]:has-text("${text}")`;
|
||||
|
||||
await window.waitForSelector(builtSelector);
|
||||
return window.click(builtSelector);
|
||||
}
|
||||
|
||||
export function getMessageTextContentNow() {
|
||||
return `Test message timestamp: ${Date.now()}`;
|
||||
}
|
||||
|
||||
export async function typeIntoInput(window: Page, dataTestId: string, text: string) {
|
||||
console.info(`typeIntoInput testId: ${dataTestId} : "${text}"`);
|
||||
const builtSelector = `css=[data-testid=${dataTestId}]`;
|
||||
return window.fill(builtSelector, text);
|
||||
}
|
Loading…
Reference in a new issue