Skip to content

feat: device-aware logging + screenshots on test failure #55

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Merged
merged 19 commits into from
Jul 2, 2025
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
19 commits
Select commit Hold shift + click to select a range
6d3b034
chore: remove unused logger.ts
Miki-Session Jun 28, 2025
ff0aebb
feat: enhance logging and add screenshot-on-fail capability
Miki-Session Jun 28, 2025
b98aedd
feat: pass testinfo to every test for screenshot-on-fail
Miki-Session Jun 28, 2025
bbcda0a
chore: linting, removing debug code
Miki-Session Jun 28, 2025
ecd4f24
feat: delegate screenshot handling to separate file
Miki-Session Jun 28, 2025
9b0ada1
fix: non state-builder utils also set device identity
Miki-Session Jun 28, 2025
91451ce
refactor: import type TestInfo instead of import
Miki-Session Jun 28, 2025
d2cf0dc
feat: testInfo parameter is mandatory for all tests
Miki-Session Jun 28, 2025
15907a7
chore: linting
Miki-Session Jun 28, 2025
70330e7
Merge remote-tracking branch 'origin/main' into screenshot-on-fail
Miki-Session Jun 30, 2025
531942e
refactor: simplify setDeviceIdentity and openApp logic
Miki-Session Jun 30, 2025
bba8005
fix: remove debug error
Miki-Session Jun 30, 2025
b1d469d
feat: add and run perfectionist/sort-imports and /sort-named-imports
Miki-Session Jun 30, 2025
87100ca
refactor: make DeviceWrapper logging methods public and apply them in…
Miki-Session Jul 1, 2025
1a9d3e9
fix: use Object.values when registering devices
Miki-Session Jul 2, 2025
0c5a967
fix: scope screenshot capture and unregistering devices to a finally …
Miki-Session Jul 2, 2025
46941e2
refactor: streamline screenshot composition logic
Miki-Session Jul 2, 2025
a14dfb2
fix: include worker index in device registration and unregistration
Miki-Session Jul 2, 2025
b4231fa
chore: linting
Miki-Session Jul 2, 2025
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
10 changes: 9 additions & 1 deletion eslint.config.mjs
Original file line number Diff line number Diff line change
@@ -1,11 +1,17 @@
import eslint from '@eslint/js';
import tseslint from 'typescript-eslint';
import perfectionist from 'eslint-plugin-perfectionist';
import globals from 'globals';
import tseslint from 'typescript-eslint';

export default tseslint.config(
{
files: ['**/*.{ts,tsx,cts,mts,js,cjs,mjs}'],
},
{
plugins: {
perfectionist,
},
},
{
ignores: [
'**/node_modules/**',
Expand Down Expand Up @@ -51,6 +57,8 @@ export default tseslint.config(
caughtErrorsIgnorePattern: '^_',
},
],
'perfectionist/sort-imports': 'error',
'perfectionist/sort-named-imports': 'error',
},
}
);
2 changes: 2 additions & 0 deletions package.json
Original file line number Diff line number Diff line change
Expand Up @@ -33,13 +33,15 @@
"allure-commandline": "^2.34.0",
"allure-playwright": "^3.2.2",
"eslint": "^9.14.0",
"eslint-plugin-perfectionist": "^4.15.0",
"fs-extra": "^11.3.0",
"gh-pages": "^6.3.0",
"globals": "^15.12.0",
"lodash": "^4.17.21",
"looks-same": "^9.0.1",
"png-js": "^1.0.0",
"prettier": "^3.3.3",
"sharp": "^0.34.2",
"sinon": "^19.0.2",
"ts-node": "^10.9.1",
"typescript": "^5.6.3",
Expand Down
3 changes: 2 additions & 1 deletion playwright.config.ts
Original file line number Diff line number Diff line change
Expand Up @@ -2,12 +2,13 @@ import dotenv from 'dotenv';
dotenv.config();

import { defineConfig, ReporterDescription } from '@playwright/test';

import { allureResultsDir } from './run/constants/allure';
import {
getRepeatEachCount,
getRetriesCount,
getWorkersCount,
} from './run/test/specs/utils/binaries';
import { allureResultsDir } from './run/constants/allure';

// NOTE: without this, the wrong source map is loaded and the stacktraces are all wrong
// eslint-disable-next-line @typescript-eslint/no-require-imports
Expand Down
13 changes: 7 additions & 6 deletions run/test/specs/app_disguise_icons.spec.ts
Original file line number Diff line number Diff line change
@@ -1,12 +1,13 @@
import type { TestInfo } from '@playwright/test';

import { bothPlatformsIt } from '../../types/sessionIt';
import { SupportedPlatformsType, closeApp, openAppOnPlatformSingleDevice } from './utils/open_app';
import { newUser } from './utils/create_account';
import { USERNAME } from '../../types/testing';
import { AppearanceMenuItem, SelectAppIcon, UserSettings } from './locators/settings';
import { verifyElementScreenshot } from './utils/verify_screenshots';
import { AppDisguisePageScreenshot } from './utils/screenshot_paths';
import { sleepFor } from './utils';
import type { TestInfo } from '@playwright/test';
import { newUser } from './utils/create_account';
import { closeApp, openAppOnPlatformSingleDevice, SupportedPlatformsType } from './utils/open_app';
import { AppDisguisePageScreenshot } from './utils/screenshot_paths';
import { verifyElementScreenshot } from './utils/verify_screenshots';

bothPlatformsIt({
title: 'App disguise icons',
Expand All @@ -16,7 +17,7 @@ bothPlatformsIt({
});

async function appDisguiseIcons(platform: SupportedPlatformsType, testInfo: TestInfo) {
const { device } = await openAppOnPlatformSingleDevice(platform);
const { device } = await openAppOnPlatformSingleDevice(platform, testInfo);
await newUser(device, USERNAME.ALICE);
await device.clickOnElementAll(new UserSettings(device));
// Must scroll down to reveal the Appearance menu item
Expand Down
16 changes: 9 additions & 7 deletions run/test/specs/app_disguise_set.spec.ts
Original file line number Diff line number Diff line change
@@ -1,20 +1,22 @@
import type { TestInfo } from '@playwright/test';

import { englishStrippedStr } from '../../localizer/englishStrippedStr';
import { androidIt } from '../../types/sessionIt';
import { SupportedPlatformsType, openAppOnPlatformSingleDevice } from './utils/open_app';
import { newUser } from './utils/create_account';
import { USERNAME } from '../../types/testing';
import { DisguisedApp } from './locators/external';
import {
AppDisguiseMeetingIcon,
AppearanceMenuItem,
CloseAppButton,
SelectAppIcon,
UserSettings,
} from './locators/settings';
import { DisguisedApp } from './locators/external';
import { sleepFor } from './utils';
import { runScriptAndLog } from './utils/utilities';
import { getAdbFullPath } from './utils/binaries';
import { newUser } from './utils/create_account';
import { openAppOnPlatformSingleDevice, SupportedPlatformsType } from './utils/open_app';
import { closeApp } from './utils/open_app';
import { englishStrippedStr } from '../../localizer/englishStrippedStr';
import { runScriptAndLog } from './utils/utilities';

// iOS implementation blocked by SES-3809
androidIt({
Expand All @@ -24,8 +26,8 @@ androidIt({
testCb: appDisguiseSetIcon,
});

async function appDisguiseSetIcon(platform: SupportedPlatformsType) {
const { device } = await openAppOnPlatformSingleDevice(platform);
async function appDisguiseSetIcon(platform: SupportedPlatformsType, testInfo: TestInfo) {
const { device } = await openAppOnPlatformSingleDevice(platform, testInfo);
await newUser(device, USERNAME.ALICE);
await device.clickOnElementAll(new UserSettings(device));
// Must scroll down to reveal the Appearance menu item
Expand Down
17 changes: 10 additions & 7 deletions run/test/specs/check_avatar_color.spec.ts
Original file line number Diff line number Diff line change
@@ -1,10 +1,12 @@
import type { TestInfo } from '@playwright/test';

import { bothPlatformsItSeparate } from '../../types/sessionIt';
import { SupportedPlatformsType, closeApp } from './utils/open_app';
import { isSameColor } from './utils/check_colour';
import { UserSettings } from './locators/settings';
import { ConversationSettings } from './locators/conversation';
import { open_Alice1_Bob1_friends } from './state_builder';
import { ConversationItem } from './locators/home';
import { UserSettings } from './locators/settings';
import { open_Alice1_Bob1_friends } from './state_builder';
import { isSameColor } from './utils/check_colour';
import { closeApp, SupportedPlatformsType } from './utils/open_app';

bothPlatformsItSeparate({
title: 'Avatar color',
Expand All @@ -20,24 +22,25 @@ bothPlatformsItSeparate({
},
});

async function avatarColor(platform: SupportedPlatformsType) {
async function avatarColor(platform: SupportedPlatformsType, testInfo: TestInfo) {
const {
devices: { alice1, bob1 },
prebuilt: { alice },
} = await open_Alice1_Bob1_friends({
platform,
focusFriendsConvo: false,
testInfo,
});

// Get Alice's avatar color on device 1 (Settings screen avatar) and turn it into a hex value
await alice1.clickOnElementAll(new UserSettings(alice1));
const alice1PixelColor = await alice1.getElementPixelColor(new UserSettings(alice1));
console.log(alice1PixelColor);
alice1.log(alice1PixelColor);
// Get Alice's avatar color on device 2 and turn it into a hex value
// Open the conversation with Alice on Bob's device
await bob1.clickOnElementAll(new ConversationItem(bob1, alice.userName));
const bob1PixelColor = await bob1.getElementPixelColor(new ConversationSettings(bob1));
console.log(bob1PixelColor);
bob1.log(bob1PixelColor);
// Color matching devices 1 and 2
const colorMatch = isSameColor(alice1PixelColor, bob1PixelColor);
if (!colorMatch) {
Expand Down
11 changes: 7 additions & 4 deletions run/test/specs/community_tests_image.spec.ts
Original file line number Diff line number Diff line change
@@ -1,10 +1,12 @@
import type { TestInfo } from '@playwright/test';

import { testCommunityLink, testCommunityName } from '../../constants/community';
import { bothPlatformsItSeparate } from '../../types/sessionIt';
import { USERNAME } from '../../types/testing';
import { open_Alice1_Bob1_friends } from './state_builder';
import { newUser } from './utils/create_account';
import { joinCommunity } from './utils/join_community';
import { SupportedPlatformsType, closeApp, openAppTwoDevices } from './utils/open_app';
import { closeApp, openAppTwoDevices, SupportedPlatformsType } from './utils/open_app';

bothPlatformsItSeparate({
title: 'Send image to community',
Expand All @@ -23,13 +25,14 @@ bothPlatformsItSeparate({
// Tests skipped due to both platforms having unique issues, have made a ticket
// to investigate further https://optf.atlassian.net/browse/QA-486

async function sendImageCommunityiOS(platform: SupportedPlatformsType) {
async function sendImageCommunityiOS(platform: SupportedPlatformsType, testInfo: TestInfo) {
const {
devices: { alice1, bob1 },
prebuilt: { alice },
} = await open_Alice1_Bob1_friends({
platform,
focusFriendsConvo: false,
testInfo,
});
const testMessage = 'Testing sending images to communities';
const testImageMessage = `Image message + ${new Date().getTime()} - ${platform}`;
Expand All @@ -43,8 +46,8 @@ async function sendImageCommunityiOS(platform: SupportedPlatformsType) {
await closeApp(alice1, bob1);
}

async function sendImageCommunityAndroid(platform: SupportedPlatformsType) {
const { device1: alice1, device2: bob1 } = await openAppTwoDevices(platform);
async function sendImageCommunityAndroid(platform: SupportedPlatformsType, testInfo: TestInfo) {
const { device1: alice1, device2: bob1 } = await openAppTwoDevices(platform, testInfo);
const time = await alice1.getTimeFromDevice(platform);
const testMessage = `Testing sending images to communities + ${time} - ${platform}`;
// Create user A and user B
Expand Down
8 changes: 5 additions & 3 deletions run/test/specs/community_tests_join.spec.ts
Original file line number Diff line number Diff line change
@@ -1,10 +1,12 @@
import type { TestInfo } from '@playwright/test';

import { testCommunityLink, testCommunityName } from '../../constants/community';
import { bothPlatformsIt } from '../../types/sessionIt';
import { ConversationItem } from './locators/home';
import { open_Alice2 } from './state_builder';
import { sleepFor } from './utils';
import { joinCommunity } from './utils/join_community';
import { SupportedPlatformsType, closeApp } from './utils/open_app';
import { closeApp, SupportedPlatformsType } from './utils/open_app';

bothPlatformsIt({
title: 'Join community test',
Expand All @@ -13,10 +15,10 @@ bothPlatformsIt({
countOfDevicesNeeded: 2,
});

async function joinCommunityTest(platform: SupportedPlatformsType) {
async function joinCommunityTest(platform: SupportedPlatformsType, testInfo: TestInfo) {
const {
devices: { alice1, alice2 },
} = await open_Alice2({ platform });
} = await open_Alice2({ platform, testInfo });
const testMessage = `Test message + ${new Date().getTime()}`;

await joinCommunity(alice1, testCommunityLink, testCommunityName);
Expand Down
5 changes: 4 additions & 1 deletion run/test/specs/disappear_after_read.spec.ts
Original file line number Diff line number Diff line change
@@ -1,3 +1,5 @@
import type { TestInfo } from '@playwright/test';

import { bothPlatformsIt } from '../../types/sessionIt';
import { DISAPPEARING_TIMES, DisappearModes } from '../../types/testing';
import { open_Alice1_Bob1_friends } from './state_builder';
Expand All @@ -13,12 +15,13 @@ bothPlatformsIt({
countOfDevicesNeeded: 2,
});

async function disappearAfterRead(platform: SupportedPlatformsType) {
async function disappearAfterRead(platform: SupportedPlatformsType, testInfo: TestInfo) {
const {
devices: { alice1, bob1 },
prebuilt: { alice, bob },
} = await open_Alice1_Bob1_friends({
platform,
testInfo,
focusFriendsConvo: true,
});

Expand Down
10 changes: 6 additions & 4 deletions run/test/specs/disappear_after_send.spec.ts
Original file line number Diff line number Diff line change
@@ -1,10 +1,12 @@
import type { TestInfo } from '@playwright/test';

import { bothPlatformsIt } from '../../types/sessionIt';
import { DisappearActions, DISAPPEARING_TIMES, DisappearModes } from '../../types/testing';
import { open_Alice1_Bob1_friends } from './state_builder';
import { sleepFor } from './utils';
import { checkDisappearingControlMessage } from './utils/disappearing_control_messages';
import { SupportedPlatformsType, closeApp } from './utils/open_app';
import { closeApp, SupportedPlatformsType } from './utils/open_app';
import { setDisappearingMessage } from './utils/set_disappearing_messages';
import { open_Alice1_Bob1_friends } from './state_builder';

bothPlatformsIt({
title: 'Disappear after send',
Expand All @@ -13,15 +15,15 @@ bothPlatformsIt({
countOfDevicesNeeded: 2,
});

async function disappearAfterSend(platform: SupportedPlatformsType) {
async function disappearAfterSend(platform: SupportedPlatformsType, testInfo: TestInfo) {
const {
devices: { alice1, bob1 },
prebuilt: { alice, bob },
} = await open_Alice1_Bob1_friends({
platform,
focusFriendsConvo: true,
testInfo,
});

const mode: DisappearModes = 'send';
const testMessage = `Checking disappear after ${mode} is working`;
const controlMode: DisappearActions = 'sent';
Expand Down
5 changes: 4 additions & 1 deletion run/test/specs/disappear_after_send_groups.spec.ts
Original file line number Diff line number Diff line change
@@ -1,3 +1,5 @@
import type { TestInfo } from '@playwright/test';

import { englishStrippedStr } from '../../localizer/englishStrippedStr';
import { bothPlatformsIt } from '../../types/sessionIt';
import { DisappearActions, DISAPPEARING_TIMES } from '../../types/testing';
Expand All @@ -13,7 +15,7 @@ bothPlatformsIt({
countOfDevicesNeeded: 3,
});

async function disappearAfterSendGroups(platform: SupportedPlatformsType) {
async function disappearAfterSendGroups(platform: SupportedPlatformsType, testInfo: TestInfo) {
const testGroupName = 'Disappear after send test';
const testMessage = 'Testing disappear after sent in groups';
const controlMode: DisappearActions = 'sent';
Expand All @@ -25,6 +27,7 @@ async function disappearAfterSendGroups(platform: SupportedPlatformsType) {
platform,
groupName: testGroupName,
focusGroupConvo: true,
testInfo,
});

await setDisappearingMessage(platform, alice1, ['Group', `Disappear after send option`, time]);
Expand Down
6 changes: 4 additions & 2 deletions run/test/specs/disappear_after_send_note_to_self.spec.ts
Original file line number Diff line number Diff line change
@@ -1,3 +1,5 @@
import type { TestInfo } from '@playwright/test';

import { bothPlatformsIt } from '../../types/sessionIt';
import { DisappearActions, DISAPPEARING_TIMES, USERNAME } from '../../types/testing';
import { PlusButton } from './locators/home';
Expand All @@ -14,8 +16,8 @@ bothPlatformsIt({
countOfDevicesNeeded: 1,
});

async function disappearAfterSendNoteToSelf(platform: SupportedPlatformsType) {
const { device } = await openAppOnPlatformSingleDevice(platform);
async function disappearAfterSendNoteToSelf(platform: SupportedPlatformsType, testInfo: TestInfo) {
const { device } = await openAppOnPlatformSingleDevice(platform, testInfo);
const testMessage = `Testing disappearing messages in Note to Self`;
const alice = await newUser(device, USERNAME.ALICE);
const controlMode: DisappearActions = 'sent';
Expand Down
6 changes: 4 additions & 2 deletions run/test/specs/disappear_after_send_off_1o1.spec.ts
Original file line number Diff line number Diff line change
@@ -1,3 +1,5 @@
import type { TestInfo } from '@playwright/test';

import { englishStrippedStr } from '../../localizer/englishStrippedStr';
import { bothPlatformsIt } from '../../types/sessionIt';
import { DisappearActions, DISAPPEARING_TIMES, DisappearModes } from '../../types/testing';
Expand All @@ -22,11 +24,11 @@ bothPlatformsIt({
countOfDevicesNeeded: 3,
});

async function disappearAfterSendOff1o1(platform: SupportedPlatformsType) {
async function disappearAfterSendOff1o1(platform: SupportedPlatformsType, testInfo: TestInfo) {
const {
devices: { alice1, alice2, bob1 },
prebuilt: { alice, bob },
} = await open_Alice2_Bob1_friends({ platform, focusFriendsConvo: true });
} = await open_Alice2_Bob1_friends({ platform, focusFriendsConvo: true, testInfo });

const mode: DisappearModes = 'send';
const controlMode: DisappearActions = 'sent';
Expand Down
Loading
Loading