-
-
Notifications
You must be signed in to change notification settings - Fork 279
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(e2e): Refactor fixtures #17287
base: develop
Are you sure you want to change the base?
Changes from 1 commit
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
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'; | ||
|
@@ -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; | ||
|
@@ -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)); | ||
}, | ||
Comment on lines
-169
to
56
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. the page object initilizes everything it needs and can to reduce passing of unnecessary params There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. I am not entirely sure I like this. Some of the fixtures are not stateless and one could assume, that all of them are singletons. I know we have used initialization within the fixtures in the past as well, but I am not 100% sure that it is desired. We can definitely use this approach, because I don't know what is right/wrong, I am just pointing it out as something to consider. |
||
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(); | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. global teardown to DRY tests |
||
}, | ||
/* eslint-disable-next-line no-empty-pattern */ | ||
blockbookMock: async ({}, use) => { | ||
|
@@ -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'; |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Lot of fixtures moved to suiteBaseFixtures.ts:
all the config/boolean switches, url, trezorUserEnvLink, page, exceptionLogger
The electronWindow stopped existing.
Remaining fixtures here are page objects and mocks.
Fixtures extands here are based of the suiteBaseFixtures.ts so that they use the correct page object