I'm working with Playwright and TypeScript and have noticed that Page Object Models (POMs) always require a page
parameter for initialization.
Since the page object is only available from the beforeEach
block onwards, I'm forced to use this pattern:
test.describe('describe name', () => {
let potentialSnippetPage: PotentialSnippetPage
test.beforeEach(async ({ page }) => {
potentialSnippetPage = new PotentialSnippetPage(page);
});
test('test title', async () => {
await potentialSnippetPage.someMethod();
});
});
This approach feels cumbersome because I have to declare the POM variable with let
first, then initialize it properly in the beforeEach
block with the actual page
object.
Is there a way to handle POM initialization in Playwright without beforeEach
and let
?
I'm looking for patterns that would reduce the repetitive setup while maintaining type safety.
This precise case is covered in the docs, using fixtures:
import { test as base } from '@playwright/test';
import { PotentialSnippetPage } from './potential-snippet-page';
const test = base.extend<{ potentialSnippetPage: PotentialSnippetPage }>({
potentialSnippetPage: async ({ page }, use) => {
const potentialSnippetPage = new PotentialSnippetPage(page);
await potentialSnippetPage.goto();
await use(potentialSnippetPage);
},
});
test.describe('describe name', () => {
test('test title', async ({ potentialSnippetPage }) => {
await potentialSnippetPage.someMethod();
});
});
Where const test = ...
can be exported/imported and hidden away in another file, if desired.
That said, the let
/beforeEach
pattern isn't that bad, IMO. It's a ubiquitous idiom in the Jest world, which Playwright was modeled after.
Related questions: