Reputation: 21
Using Playwright TypeScript, I have a base fixture file and then another fixture file that extends this base fixture and adds specific logic for a set of api tests, including a beforeEach hook. The folder of api spec files intended for execution uses the extended fixture for their test cases.
Base fixture file:
import { test as base } from "@playwright/test";
import { ApiTest, ApiTestFixture } from "{custom-package}";
export const test = base.extend<ApiTestFixture>({
apiTest: async ({}, use) => {
const apiTest = new ApiTest();
await use(apiTest);
},
});
export { expect } from "@playwright/test";
Extended fixture file:
import { ApiTestFixture } from "{custom-package}";
import { test as base } from "@playwright/test";
import { UserClient } from "../../../shared/clients/users/user-client";
import { ProjectClient } from "../../../shared/clients/projects/project-client";
export type UserApiFixture = ApiTestFixture & {
projectClient: ProjectClient;
userClient: UserClient;
};
export const test = base.extend<UserApiFixture>({
projectClient: async ({ }, use) => {
const projectClient = new ProjectClient();
await use(projectClient);
},
userClient: async ({ }, use) => {
const userClient = new UserClient();
await use(userClient);
}
});
test.beforeEach(async ({ apiTest }) => {
await apiTest.beforeEach(test, "Users");
});
export { expect } from "@playwright/test";
When I run the api folder containing multiple spec files, I would expect the beforeEach hook in the extended fixture file to be run before every test in every file.
What actually happens is the beforeEach hook will run before each test in whichever spec file happens to execute first. This beforeEach hook then does not get executed for further spec files in the run using this fixture.
If run the spec files individually, everything runs as I would expect.
Does anybody know anything that may help me?
Upvotes: 2
Views: 68
Reputation: 648
One issue I see in your fixture files is that your extended test
function does not extend your base test
function. Both your base test
and extended test
just extend Playwright's base test
and add different sets of fixtures.
Your are saying that "the beforeEach hook will run before each test in whichever spec file happens to execute first." I'm not quite sure why that happens. It seems your beforeEach
hook would throw an error when executed, because the apiTest
fixture is not defined for the extended test
function. Maybe I'm missing something here.
I'll showcase a setup of layered fixture files that works for me:
// base-fixtures.ts
import { test as base } from "@playwright/test";
import type { Locator, Page } from "@playwright/test";
export class ExamplePage {
readonly url = "https://example.org/";
readonly page: Page;
readonly moreInformationLink: Locator;
constructor(page: Page) {
this.page = page;
this.moreInformationLink = this.page.getByRole('link', { name: 'More information...' })
}
async goto() {
await this.page.goto(this.url);
}
}
export type BaseFixtures = {
examplePage: ExamplePage;
}
export const test = base.extend<BaseFixtures>({
examplePage: async ({ page }, use) => {
use(new ExamplePage(page));
}
});
export { expect } from "@playwright/test";
// extended-fixtures.ts
import { test as base } from "./base-fixtures";
import type { Locator, Page } from "@playwright/test";
export class ExampleHelpPage {
readonly page: Page
readonly url = "http://www.iana.org/help/example-domains";
readonly heading: Locator;
constructor(page: Page) {
this.page = page;
this.heading = this.page.getByRole('heading', { name: 'Example Domains' });
}
}
export type ExtendedFixtures = {
exampleHelpPage: ExampleHelpPage;
}
export const test = base.extend<ExtendedFixtures>({
exampleHelpPage: async ({ page }, use) => {
use(new ExampleHelpPage(page));
}
});
test.beforeEach(async ({ examplePage }) => {
await examplePage.goto();
});
export { expect } from "./base-fixtures";
// example.spec.ts
import { test, expect } from './extended-fixtures';
test('has title', async ({ page }) => {
await expect(page).toHaveTitle("Example Domain");
});
test('get more information', async ({ page, examplePage, exampleHelpPage }) => {;
await examplePage.moreInformationLink.click();
await expect(exampleHelpPage.heading).toBeVisible();
});
When I execute the example tests, both of them are passing for me. The beforeEach
hook seems to trigger as expected and navigates to the example page both times.
Upvotes: 0