Skip to content
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

Refactor/suite desktop core/e2e refactor emu press timeouts #17291

Draft
wants to merge 3 commits into
base: develop
Choose a base branch
from
Draft
Show file tree
Hide file tree
Changes from all commits
Commits
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
9 changes: 7 additions & 2 deletions packages/suite-desktop-core/e2e/support/common.ts
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
/* eslint-disable no-console */

import test, { TestInfo, _electron as electron } from '@playwright/test';
import test, { ElectronApplication, Page, TestInfo, _electron as electron } from '@playwright/test';
import { readdirSync, removeSync } from 'fs-extra';
import { isEqual, omit } from 'lodash';
import path from 'path';
Expand All @@ -25,6 +25,11 @@ type LaunchSuiteParams = {
viewport: { width: number; height: number };
};

export type Suite = {
electronApp: ElectronApplication;
window: Page;
};

const formatErrorLogMessage = (data: string) => {
const red = '\x1b[31m';
const reset = '\x1b[0m';
Expand Down Expand Up @@ -101,7 +106,7 @@ export const launchSuiteElectronApp = async (params: LaunchSuiteParams) => {
return electronApp;
};

export const launchSuite = async (params: LaunchSuiteParams) => {
export const launchSuite = async (params: LaunchSuiteParams): Promise<Suite> => {
const electronApp = await launchSuiteElectronApp(params);
const window = await electronApp.firstWindow();

Expand Down
197 changes: 22 additions & 175 deletions packages/suite-desktop-core/e2e/support/fixtures.ts
Original file line number Diff line number Diff line change
@@ -1,21 +1,5 @@
/* eslint-disable react-hooks/rules-of-hooks */
import { Page, test as base } from '@playwright/test';

import {
type Model,
type SetupEmu,
type StartEmu,
type TrezorUserEnvLinkClass,
} from '@trezor/trezor-user-env-link';

import { AnalyticsFixture } from './analytics';
import {
TrezorUserEnvLinkProxy,
getElectronVideoPath,
getUrl,
isDesktopProject,
launchSuite,
} from './common';
import { IndexedDbFixture } from './indexedDb';
import { BlockbookMock } from './mocks/blockBookMock';
import { MetadataProviderMock } from './mocks/metadataProviderMock';
Expand All @@ -32,18 +16,9 @@ import { SettingsActions } from './pageActions/settings/settingsActions';
import { SuiteGuide } from './pageActions/suiteGuideActions';
import { TrezorInputActions } from './pageActions/trezorInputActions';
import { WalletActions } from './pageActions/walletActions';

type StartEmuModelRequired = StartEmu & { model: Model };
import { suiteBaseTest } from './testExtends/suiteBaseFixture';

type Fixtures = {
startEmulator: boolean;
setupEmulator: boolean;
emulatorStartConf: StartEmuModelRequired;
emulatorSetupConf: SetupEmu;
url: string;
trezorUserEnvLink: TrezorUserEnvLinkClass;
electronWindow: Page | undefined;
page: Page;
dashboardPage: DashboardActions;
settingsPage: SettingsActions;
suiteGuidePage: SuiteGuide;
Expand All @@ -61,164 +36,55 @@ type Fixtures = {
metadataProviderMock: MetadataProviderMock;
blockbookMock: BlockbookMock;
tradingMock: TradingMock;
exceptionLogger: void;
};

const test = base.extend<Fixtures>({
startEmulator: true,
setupEmulator: true,
emulatorStartConf: { model: 'T3T1', wipe: true },
emulatorSetupConf: {},
/* eslint-disable-next-line no-empty-pattern */
url: async ({}, use, testInfo) => {
await use(getUrl(testInfo));
},
/* eslint-disable-next-line no-empty-pattern */
trezorUserEnvLink: async ({}, use) => {
await use(TrezorUserEnvLinkProxy);
},
electronWindow: async (
{
trezorUserEnvLink,
startEmulator,
setupEmulator,
emulatorStartConf,
emulatorSetupConf,
locale,
colorScheme,
},
use,
testInfo,
) => {
// We need to ensure emulator is running before launching the suite
await trezorUserEnvLink.logTestDetails(
` - - - STARTING TEST ${testInfo.titlePath.join(' - ')}`,
);
await trezorUserEnvLink.stopBridge();
await trezorUserEnvLink.stopEmu();
await trezorUserEnvLink.connect();
if (startEmulator) {
await trezorUserEnvLink.startEmu(emulatorStartConf);
}

if (startEmulator && setupEmulator) {
await trezorUserEnvLink.setupEmu(emulatorSetupConf);
}

if (isDesktopProject(testInfo)) {
const suite = await launchSuite({
locale,
colorScheme,
videoFolder: testInfo.outputDir,
viewport: testInfo.project.use.viewport!,
});
await use(suite.window);
await suite.electronApp.close(); // Ensure cleanup after tests
} else {
if (startEmulator) {
await trezorUserEnvLink.startBridge();
}
await use(undefined);
}
await trezorUserEnvLink.logTestDetails(
` - - - FINISHING TEST ${testInfo.titlePath.join(' - ')}`,
);
},
page: async ({ electronWindow, page: webPage }, use, testInfo) => {
if (electronWindow) {
await webPage.close(); // Close the default chromium page
await electronWindow.context().tracing.start({ screenshots: true, snapshots: true });
await use(electronWindow);
const tracePath = `${testInfo.outputDir}/trace.electron.zip`;
await electronWindow.context().tracing.stop({ path: tracePath });
testInfo.attachments.push({
name: 'trace',
path: tracePath,
contentType: 'application/zip',
});
testInfo.attachments.push({
name: 'video',
path: getElectronVideoPath(testInfo.outputDir),
contentType: 'video/webm',
});
} else {
await webPage.context().addInitScript(() => {
// Tells the app to attach Redux Store to window object. packages/suite-web/src/support/usePlaywright.ts
window.Playwright = true;
});
await webPage.goto('./');
await use(webPage);
}
},
const test = suiteBaseTest.extend<Fixtures>({
dashboardPage: async ({ page, devicePrompt }, use) => {
const dashboardPage = new DashboardActions(page, devicePrompt);
await use(dashboardPage);
await use(new DashboardActions(page, devicePrompt));
},
settingsPage: async ({ page, url }, use) => {
const settingsPage = new SettingsActions(page, url);
await use(settingsPage);
await use(new SettingsActions(page, url));
},
suiteGuidePage: async ({ page }, use) => {
const suiteGuidePage = new SuiteGuide(page);
await use(suiteGuidePage);
await use(new SuiteGuide(page));
},
walletPage: async ({ page }, use) => {
const walletPage = new WalletActions(page);
await use(walletPage);
},
onboardingPage: async (
{ page, analyticsPage, devicePrompt, emulatorStartConf },
use,
testInfo,
) => {
const onboardingPage = new OnboardingActions(
page,
analyticsPage,
devicePrompt,
emulatorStartConf.model,
testInfo,
);
await use(onboardingPage);
await use(new WalletActions(page));
},
onboardingPage: async ({ page, emulatorStartConf }, use, testInfo) => {
await use(new OnboardingActions(page, emulatorStartConf.model, testInfo));
},
analyticsPage: async ({ page }, use) => {
const analyticsPage = new AnalyticsActions(page);
await use(analyticsPage);
await use(new AnalyticsActions(page));
},
devicePrompt: async ({ page }, use) => {
const devicePromptActions = new DevicePromptActions(page);
await use(devicePromptActions);
await use(new DevicePromptActions(page));
},
recoveryPage: async ({ page }, use) => {
const recoveryPage = new RecoveryActions(page);
await use(recoveryPage);
await use(new RecoveryActions(page));
},
marketPage: async ({ page }, use) => {
const marketPage = new MarketActions(page);
await use(marketPage);
await use(new MarketActions(page));
},
assetsPage: async ({ page }, use) => {
const assetPage = new AssetsActions(page);
await use(assetPage);
await use(new AssetsActions(page));
},
metadataPage: async ({ page, devicePrompt }, use) => {
const metadataPage = new MetadataActions(page, devicePrompt);
await use(metadataPage);
await use(new MetadataActions(page, devicePrompt));
},
trezorInput: async ({ page }, use) => {
const trezorInput = new TrezorInputActions(page);
await use(trezorInput);
await use(new TrezorInputActions(page));
},
analytics: async ({ page }, use) => {
const analytics = new AnalyticsFixture(page);
await use(analytics);
await use(new AnalyticsFixture(page));
},
indexedDb: async ({ page }, use) => {
const indexedDb = new IndexedDbFixture(page);
await use(indexedDb);
await use(new IndexedDbFixture(page));
},
metadataProviderMock: async ({ page }, use) => {
const metadataProviderMock = new MetadataProviderMock(page);
await use(metadataProviderMock);
await metadataProviderMock.stop();
},
/* eslint-disable-next-line no-empty-pattern */
blockbookMock: async ({}, use) => {
Expand All @@ -227,28 +93,9 @@ const test = base.extend<Fixtures>({
blockbookMock.stop();
},
tradingMock: async ({ page }, use) => {
const tradingMock = new TradingMock(page);
await use(tradingMock);
},
exceptionLogger: [
async ({ page }, use) => {
const errors: Error[] = [];
page.on('pageerror', error => {
errors.push(error);
});

await use();

if (errors.length > 0) {
throw new Error(
`There was a JS exception during test run.
\n${errors.map(error => `${error.message}\n${error.stack}`).join('\n-----\n')}`,
);
}
},
{ auto: true },
],
await use(new TradingMock(page));
},
});

export { test };
export { expect } from './customMatchers';
export { expect } from './testExtends/customMatchers';
Original file line number Diff line number Diff line change
Expand Up @@ -6,9 +6,9 @@ import { NetworkSymbol } from '@suite-common/wallet-config';

import { buyQuotesBTC, invityEndpoint } from '../../fixtures/invity';
import { TrezorUserEnvLinkProxy, step } from '../common';
import { expect } from '../customMatchers';
import { DevicePromptActions } from './devicePromptActions';
import { solanaUrlPattern } from '../mocks/tradingMock';
import { expect } from '../testExtends/customMatchers';

const quoteProviderLocator = '@trading/offers/quote/provider';
const quoteAmountLocator = '@trading/offers/quote/crypto-amount';
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,8 @@ import { TrezorUserEnvLinkProxy, step } from '../../common';
import { DevicePromptActions } from '../devicePromptActions';

export class BackupActions {
private devicePrompt: DevicePromptActions;

readonly startButton: Locator;
readonly undertandWhatSeedIsCheckbox: Locator;
readonly hasEnoughTimeCheckbox: Locator;
Expand All @@ -13,10 +15,8 @@ export class BackupActions {
readonly willHideSeedCheckbox: Locator;
readonly closeButton: Locator;

constructor(
private page: Page,
private devicePrompt: DevicePromptActions,
) {
constructor(private page: Page) {
this.devicePrompt = new DevicePromptActions(page);
this.startButton = page.getByTestId('@backup/start-button');
this.undertandWhatSeedIsCheckbox = page.getByTestId(
'@backup/check-item/understands-what-seed-is',
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -17,6 +17,8 @@ export class OnboardingActions {
readonly firmware: FirmwareActions;
readonly pin: PinActions;
readonly tutorial: TutorialActions;
private readonly devicePrompt: DevicePromptActions;
private readonly analyticsPage: AnalyticsActions;

readonly welcomeBody: Locator;
readonly onboardingContinueButton: Locator;
Expand All @@ -42,12 +44,12 @@ export class OnboardingActions {

constructor(
public page: Page,
private analyticsPage: AnalyticsActions,
private readonly devicePrompt: DevicePromptActions,
private readonly model: Model,
readonly model: Model,
private readonly testInfo: TestInfo,
) {
this.backup = new BackupActions(page, devicePrompt);
this.analyticsPage = new AnalyticsActions(page);
this.devicePrompt = new DevicePromptActions(page);
this.backup = new BackupActions(page);
this.firmware = new FirmwareActions(page);
this.tutorial = new TutorialActions(page);
this.pin = new PinActions(page);
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,7 @@ import { Locator, Page } from '@playwright/test';
import { BackendType, NetworkSymbol } from '@suite-common/wallet-config';

import { step } from '../../common';
import { expect } from '../../customMatchers';
import { expect } from '../../testExtends/customMatchers';

export class CoinsActions {
readonly networkButton = (symbol: NetworkSymbol) =>
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,7 @@ import { capitalizeFirstLetter } from '@trezor/utils';
import { CoinsActions } from './coinActions';
import { DeviceActions } from './deviceActions';
import { TrezorUserEnvLinkProxy, step } from '../../common';
import { expect } from '../../customMatchers';
import { expect } from '../../testExtends/customMatchers';

export enum Theme {
System = 'system',
Expand Down
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
import { Locator, Page, test } from '@playwright/test';

import { TrezorUserEnvLinkProxy, step } from '../common';
import { expect } from '../customMatchers';
import { expect } from '../testExtends/customMatchers';

export class TrezorInputActions {
readonly wordSelectInput: Locator;
Expand Down
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
import { Locator, Request, expect as baseExpect } from '@playwright/test';
import { diff } from 'jest-diff';

import { isEqualWithOmit } from './common';
import { isEqualWithOmit } from '../common';

const compareTextAndNumber = async (
locator: Locator,
Expand Down
Loading
Loading