I'm currently using the Cucumber-Playwright framework starter code by tallyb to write UI tests as ADO pipelines for my company. However, I thing I don't like is how after every scenario the page fixture is teared down and then set up again. This wastes alot of time when I need to log in which takes around a minute for every single scenario.
Especially for Scenario Outline's where I have a scenario that loops through Examples like this
Scenario Outline: all portlets collapse and expand
When I collapse portlet "<PORTLET>"
Then I cannot see portlet body "<PORTLET>"
When I expand portlet "<PORTLET>"
Then I can see portlet body "<PORTLET>"
Examples:
| PORTLET |
| fum_portlet |
| inflow_chart_portlet |
| fees_chart_portlet |
| pending_investment_instructions_portlet |
| cash_portlet |
| task_portlet |
it wastes alot of time when ran in the pipeline. So what I want is a solution where I tag these Scenario Outlines with something like @preserve so that the page fixture is preserved throughout the examples instead of being torn down and set-up.
I have somewhat of an idea that I need to change up the Before/After hooks however I don't really know how to implement that. This is what my Before/After hooks look right right now:
Before(async function (this: ICustomWorld, { pickle }: ITestCaseHookParameter) {
this.startTime = new Date();
this.testName = pickle.name.replace(/\W/g, '-');
// customize the [browser context](https://playwright.dev/docs/next/api/class-browser#browsernewcontextoptions)
this.context = await browser.newContext({
acceptDownloads: true,
recordVideo: process.env.PWVIDEO ? { dir: 'screenshots' } : undefined,
viewport: { width: 1200, height: 800 },
});
this.server = await request.newContext({
// All requests we send go to this API endpoint.
baseURL: config.BASE_API_URL,
});
await this.context.tracing.start({ screenshots: true, snapshots: true });
this.page = await this.context.newPage();
this.page.on('console', async (msg: ConsoleMessage) => {
if (msg.type() === 'log') {
await this.attach(msg.text());
}
});
this.feature = pickle;
});
After(async function (this: ICustomWorld, { result }: ITestCaseHookParameter) {
if (result) {
await this.attach(`Status: ${result?.status}. Duration:${result.duration?.seconds}s`);
if (result.status !== Status.PASSED) {
const image = await this.page?.screenshot();
// Replace : with _ because colons aren't allowed in Windows paths
const timePart = this.startTime?.toISOString().split('.')[0].replaceAll(':', '_');
image && (await this.attach(image, 'image/png'));
await this.context?.tracing.stop({
path: `${tracesDir}/${this.testName}-${timePart}trace.zip`,
});
}
}
await this.page?.close();
await this.context?.close();
});
Perhaps I could do something like
Before({tag: '@preserve'}, async function (this: ICustomWorld) {
// don't set up new context/page
});
After({tag: '@preserve'}, async function (this: ICustomWorld) {
// don't close page/context
});
but I'm not sure to go about it.