mirror of
https://github.com/oxen-io/session-desktop.git
synced 2023-12-14 02:12:57 +01:00
Adding in data test-id to path light and fixing disappearing messages test
This commit is contained in:
parent
9e3a569fac
commit
75c42356c7
9 changed files with 74 additions and 97 deletions
|
@ -26,6 +26,7 @@ export type StatusLightType = {
|
|||
glowStartDelay: number;
|
||||
glowDuration: number;
|
||||
color?: string;
|
||||
dataTestId?: string
|
||||
};
|
||||
|
||||
const StyledCountry = styled.div`
|
||||
|
@ -143,19 +144,21 @@ const OnionPathModalInner = () => {
|
|||
export type OnionNodeStatusLightType = {
|
||||
glowStartDelay: number;
|
||||
glowDuration: number;
|
||||
dataTestId?: string
|
||||
};
|
||||
|
||||
/**
|
||||
* Component containing a coloured status light.
|
||||
*/
|
||||
export const OnionNodeStatusLight = (props: OnionNodeStatusLightType): JSX.Element => {
|
||||
const { glowStartDelay, glowDuration } = props;
|
||||
const { glowStartDelay, glowDuration, dataTestId } = props;
|
||||
|
||||
return (
|
||||
<ModalStatusLight
|
||||
glowDuration={glowDuration}
|
||||
glowStartDelay={glowStartDelay}
|
||||
color={'var(--button-path-default-color)'}
|
||||
dataTestId={dataTestId}
|
||||
/>
|
||||
);
|
||||
};
|
||||
|
@ -186,10 +189,9 @@ export const ModalStatusLight = (props: StatusLightType) => {
|
|||
export const ActionPanelOnionStatusLight = (props: {
|
||||
isSelected: boolean;
|
||||
handleClick: () => void;
|
||||
dataTestId?: string;
|
||||
id: string;
|
||||
}) => {
|
||||
const { isSelected, handleClick, dataTestId, id } = props;
|
||||
const { isSelected, handleClick, id } = props;
|
||||
|
||||
const onionPathsCount = useSelector(getOnionPathsCount);
|
||||
const firstPathLength = useSelector(getFirstOnionPathLength);
|
||||
|
@ -218,7 +220,8 @@ export const ActionPanelOnionStatusLight = (props: {
|
|||
glowStartDelay={0}
|
||||
noScale={true}
|
||||
isSelected={isSelected}
|
||||
dataTestId={dataTestId}
|
||||
dataTestId={"path-light-container"}
|
||||
dataTestIdIcon={"path-light-svg"}
|
||||
id={id}
|
||||
/>
|
||||
);
|
||||
|
|
|
@ -14,6 +14,7 @@ export type SessionIconProps = {
|
|||
glowStartDelay?: number;
|
||||
noScale?: boolean;
|
||||
backgroundColor?: string;
|
||||
dataTestId?: string
|
||||
};
|
||||
|
||||
const getIconDimensionFromIconSize = (iconSize: SessionIconSize | number) => {
|
||||
|
@ -122,7 +123,7 @@ const animation = (props: {
|
|||
};
|
||||
|
||||
//tslint:disable no-unnecessary-callback-wrapper
|
||||
const Svg = React.memo(styled.svg<StyledSvgProps>`
|
||||
const Svg = styled.svg<StyledSvgProps>`
|
||||
width: ${props => props.width};
|
||||
transform: ${props => `rotate(${props.iconRotation}deg)`};
|
||||
animation: ${props => animation(props)};
|
||||
|
@ -134,7 +135,7 @@ const Svg = React.memo(styled.svg<StyledSvgProps>`
|
|||
fill: ${props => (props.iconColor ? props.iconColor : '--button-icon-stroke-color')};
|
||||
padding: ${props => (props.iconPadding ? props.iconPadding : '')};
|
||||
transition: inherit;
|
||||
`);
|
||||
`;
|
||||
// tslint:enable no-unnecessary-callback-wrapper
|
||||
|
||||
const SessionSvg = (props: {
|
||||
|
@ -151,6 +152,7 @@ const SessionSvg = (props: {
|
|||
borderRadius?: string;
|
||||
backgroundColor?: string;
|
||||
iconPadding?: string;
|
||||
dataTestId?: string
|
||||
}) => {
|
||||
const colorSvg = props.iconColor ? props.iconColor : '--button-icon-stroke-color';
|
||||
const pathArray = props.path instanceof Array ? props.path : [props.path];
|
||||
|
@ -167,10 +169,11 @@ const SessionSvg = (props: {
|
|||
backgroundColor: props.backgroundColor,
|
||||
borderRadius: props.borderRadius,
|
||||
iconPadding: props.iconPadding,
|
||||
dataTestId: props.dataTestId
|
||||
};
|
||||
|
||||
return (
|
||||
<Svg {...propsToPick}>
|
||||
<Svg data-testid={props.dataTestId} {...propsToPick}>
|
||||
{pathArray.map((path, index) => {
|
||||
return <path key={index} fill={colorSvg} d={path} />;
|
||||
})}
|
||||
|
@ -189,6 +192,8 @@ export const SessionIcon = (props: SessionIconProps) => {
|
|||
noScale,
|
||||
backgroundColor,
|
||||
iconPadding,
|
||||
dataTestId
|
||||
|
||||
} = props;
|
||||
let { iconSize, iconRotation } = props;
|
||||
iconSize = iconSize || 'medium';
|
||||
|
@ -197,6 +202,9 @@ export const SessionIcon = (props: SessionIconProps) => {
|
|||
const iconDimensions = getIconDimensionFromIconSize(iconSize);
|
||||
const iconDef = icons[iconType];
|
||||
const ratio = iconDef?.ratio || 1;
|
||||
if(iconType === 'circle') {
|
||||
console.warn("props",props)
|
||||
}
|
||||
|
||||
return (
|
||||
<SessionSvg
|
||||
|
@ -213,6 +221,7 @@ export const SessionIcon = (props: SessionIconProps) => {
|
|||
iconColor={iconColor}
|
||||
backgroundColor={backgroundColor}
|
||||
iconPadding={iconPadding}
|
||||
dataTestId={dataTestId}
|
||||
/>
|
||||
);
|
||||
};
|
||||
|
|
|
@ -12,6 +12,7 @@ interface SProps extends SessionIconProps {
|
|||
isHidden?: boolean;
|
||||
margin?: string;
|
||||
dataTestId?: string;
|
||||
dataTestIdIcon?: string;
|
||||
id?: string;
|
||||
style?: object;
|
||||
}
|
||||
|
@ -54,6 +55,7 @@ const SessionIconButtonInner = React.forwardRef<HTMLDivElement, SProps>((props,
|
|||
margin,
|
||||
id,
|
||||
dataTestId,
|
||||
dataTestIdIcon,
|
||||
style,
|
||||
} = props;
|
||||
const clickHandler = (e: React.MouseEvent<HTMLDivElement>) => {
|
||||
|
@ -86,7 +88,7 @@ const SessionIconButtonInner = React.forwardRef<HTMLDivElement, SProps>((props,
|
|||
backgroundColor={backgroundColor}
|
||||
borderRadius={borderRadius}
|
||||
iconPadding={iconPadding}
|
||||
data-testid={dataTestId}
|
||||
dataTestId={dataTestIdIcon}
|
||||
/>
|
||||
{Boolean(notificationCount) && <SessionNotificationCount count={notificationCount} />}
|
||||
</StyledSessionIconButton>
|
||||
|
|
|
@ -124,7 +124,6 @@ const Section = (props: { type: SectionType }) => {
|
|||
case SectionType.PathIndicator:
|
||||
return (
|
||||
<ActionPanelOnionStatusLight
|
||||
dataTestId="onion-status-section"
|
||||
handleClick={handleClick}
|
||||
isSelected={isSelected}
|
||||
id={'onion-path-indicator-led-id'}
|
||||
|
|
|
@ -1,6 +1,6 @@
|
|||
import { Data, Snode } from '../../../ts/data/data';
|
||||
import * as SnodePool from '../apis/snode_api/snodePool';
|
||||
import _ from 'lodash';
|
||||
import _, { compact } from 'lodash';
|
||||
import { default as insecureNodeFetch } from 'node-fetch';
|
||||
import { UserUtils } from '../utils';
|
||||
import { Onions, snodeHttpsAgent } from '../apis/snode_api/onions';
|
||||
|
@ -150,6 +150,7 @@ export async function getOnionPath({ toExclude }: { toExclude?: Snode }): Promis
|
|||
throw new Error(`Failed to build enough onion paths, current count: ${onionPaths.length}`);
|
||||
}
|
||||
}
|
||||
onionPaths = onionPaths.map(compact)
|
||||
|
||||
if (onionPaths.length === 0) {
|
||||
if (!_.isEmpty(window.inboxStore?.getState().onionPaths.snodePaths)) {
|
||||
|
@ -182,6 +183,7 @@ export async function getOnionPath({ toExclude }: { toExclude?: Snode }): Promis
|
|||
const onionPathsWithoutExcluded = onionPaths.filter(
|
||||
path => !_.some(path, node => node.pubkey_ed25519 === toExclude.pubkey_ed25519)
|
||||
);
|
||||
|
||||
if (!onionPathsWithoutExcluded || onionPathsWithoutExcluded.length === 0) {
|
||||
throw new Error('No onion paths available after filtering');
|
||||
}
|
||||
|
|
|
@ -6,7 +6,7 @@ import { openAppAndWait } from './setup/open';
|
|||
import {
|
||||
clickOnMatchingText,
|
||||
clickOnTestIdWithText,
|
||||
waitForTestIdWithText,
|
||||
waitForTestIdWithText
|
||||
} from './utilities/utils';
|
||||
|
||||
let window: Page | undefined;
|
||||
|
|
|
@ -4,14 +4,13 @@ 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,
|
||||
hasTextElementBeenDeleted,
|
||||
waitForTestIdWithText,
|
||||
} from './utilities/utils';
|
||||
import { createContact } from './utilities/create_contact';
|
||||
|
||||
test.beforeEach(beforeAllClean);
|
||||
|
||||
|
@ -19,9 +18,9 @@ test.beforeEach(beforeAllClean);
|
|||
// tslint:disable: no-console
|
||||
|
||||
const testMessage = 'Test-Message- (A -> B) ';
|
||||
const testReply = 'Reply-Test-Message- (B -> A)';
|
||||
// const testReply = 'Reply-Test-Message- (B -> A)';
|
||||
const sentMessage = `${testMessage}${Date.now()}`;
|
||||
const sentReplyMessage = `${testReply} :${Date.now()}`;
|
||||
// const sentReplyMessage = `${testReply} :${Date.now()}`;
|
||||
|
||||
test('Disappearing messages', async () => {
|
||||
// Open App
|
||||
|
@ -29,11 +28,9 @@ test('Disappearing messages', async () => {
|
|||
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 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');
|
||||
await createContact(windowA, windowB, userA, userB);
|
||||
// Need to wait for contact approval
|
||||
await sleepFor(5000);
|
||||
// Click on user's avatar to open conversation options
|
||||
await clickOnTestIdWithText(windowA, 'conversation-options-avatar');
|
||||
// Select disappearing messages drop down
|
||||
|
@ -48,57 +45,21 @@ test('Disappearing messages', async () => {
|
|||
'control-message',
|
||||
'You set the disappearing message timer to 5 seconds'
|
||||
);
|
||||
await sleepFor(2000);
|
||||
// Check top right hand corner indicator
|
||||
|
||||
await waitForTestIdWithText(windowA, 'disappearing-messages-indicator', '5 seconds');
|
||||
// Send message
|
||||
// Wait for tick of confirmation
|
||||
await sendMessage(windowA, sentMessage);
|
||||
// Check timer is functioning
|
||||
|
||||
// Verify message is deleted
|
||||
const errorDesc = 'Should not be found';
|
||||
try {
|
||||
const elemShouldNotBeFound = windowA.locator(sentMessage);
|
||||
if (elemShouldNotBeFound) {
|
||||
console.error('Sent message not found in window A');
|
||||
throw new Error(errorDesc);
|
||||
}
|
||||
} catch (e) {
|
||||
if (e.message !== errorDesc) {
|
||||
throw e;
|
||||
}
|
||||
}
|
||||
// Click on user's avatar for options
|
||||
await clickOnTestIdWithText(windowA, 'conversation-options-avatar');
|
||||
// Click on disappearing messages drop down
|
||||
await clickOnMatchingText(windowA, 'Disappearing messages');
|
||||
// Select off
|
||||
await clickOnMatchingText(windowA, 'Off');
|
||||
// Click chevron to close menu
|
||||
await clickOnTestIdWithText(windowA, 'back-button-conversation-options');
|
||||
// Check config message
|
||||
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(
|
||||
await waitForTestIdWithText(
|
||||
windowB,
|
||||
'control-message',
|
||||
`${userA.userName} set the disappearing message timer to 5 seconds`
|
||||
);
|
||||
// Wait 5 seconds
|
||||
await waitForMatchingText(windowB, `${userA.userName} has turned off disappearing messages.`);
|
||||
// verify message is deleted in windowB
|
||||
const errorDesc2 = 'Should not be found';
|
||||
try {
|
||||
const elemShouldNotBeFound = windowA.locator(sentMessage);
|
||||
if (elemShouldNotBeFound) {
|
||||
console.error('Sent message not found in window B');
|
||||
throw new Error(errorDesc2);
|
||||
}
|
||||
} catch (e) {
|
||||
if (e.message !== errorDesc2) {
|
||||
throw e;
|
||||
}
|
||||
}
|
||||
await sleepFor(500);
|
||||
// Check top right hand corner indicator
|
||||
await waitForTestIdWithText(windowA, 'disappearing-messages-indicator', '5 seconds');
|
||||
// Send message
|
||||
await sendMessage(windowA, sentMessage);
|
||||
// Check timer is functioning
|
||||
await sleepFor(6000);
|
||||
// Verify message is deleted
|
||||
await hasTextElementBeenDeleted(windowA, sentMessage, 3000);
|
||||
// focus window B
|
||||
await clickOnTestIdWithText(windowB, "control-message", `${userA.userName} set the disappearing message timer to 5 seconds`);
|
||||
await hasTextElementBeenDeleted(windowB, sentMessage, 4000);
|
||||
});
|
||||
|
|
|
@ -1,6 +1,6 @@
|
|||
import { Page } from '@playwright/test';
|
||||
import { User } from '../types/testing';
|
||||
import { clickOnMatchingText, typeIntoInput } from '../utilities/utils';
|
||||
import { checkPathLight, clickOnMatchingText, typeIntoInput } from '../utilities/utils';
|
||||
// tslint:disable: no-console
|
||||
export const newUser = async (window: Page, userName: string): Promise<User> => {
|
||||
// Create User
|
||||
|
@ -19,32 +19,8 @@ export const newUser = async (window: Page, userName: string): Promise<User> =>
|
|||
|
||||
console.info(`${userName}: Session ID: ${sessionid} and Recovery phrase: ${recoveryPhrase}`);
|
||||
await window.click('.session-icon-button.small');
|
||||
await checkPathLight(window);
|
||||
return { userName, sessionid, recoveryPhrase };
|
||||
};
|
||||
|
||||
// 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 };
|
||||
// };
|
||||
|
||||
// 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 };
|
||||
// }
|
||||
|
|
|
@ -88,6 +88,31 @@ export async function waitForLoadingAnimationToFinish(
|
|||
console.info('Loading animation has finished');
|
||||
}
|
||||
|
||||
export async function checkPathLight(window: Page, maxWait?: number) {
|
||||
let pathLight: ElementHandle<SVGElement | HTMLElement> | undefined;
|
||||
const maxWaitTime = maxWait || 100000;
|
||||
const waitPerLoop = 100;
|
||||
let start = Date.now();
|
||||
|
||||
pathLight = await waitForElement(window, 'data-testid', "path-light-container", maxWait);
|
||||
let pathColor = await pathLight.getAttribute('color');
|
||||
|
||||
while(pathColor === 'var(--button-path-error-color)') {
|
||||
await sleepFor(waitPerLoop)
|
||||
pathLight = await waitForElement(window, 'data-testid', "path-light-container", maxWait);
|
||||
pathColor = await pathLight.getAttribute('color');
|
||||
start += waitPerLoop
|
||||
if(Date.now() - start >= (maxWaitTime / 2)) {
|
||||
console.log('Path building...')
|
||||
}
|
||||
|
||||
if(Date.now() - start >= maxWaitTime) {
|
||||
throw new Error('Timed out waiting for path')
|
||||
}
|
||||
}
|
||||
console.log('Path built correctly, Yay!', pathColor)
|
||||
}
|
||||
|
||||
// ACTIONS
|
||||
|
||||
export async function clickOnElement(
|
||||
|
|
Loading…
Reference in a new issue