I need to configure Playwright to use different POM fixtures for different project settings.
All examples I find configure the POM while extending the base test. This works, but this way Playwright would use the same POM fixture for all projects.
import { test as base } from '@playwright/test';
type TestOptions = {
productDetailPom: ProductDetailPom
};
export const test = base.extend<TestOptions>({
productDetailPom: async ({ browser }, use) => {
await use(await ProductDetailPom.create(browser, 'url'));
},
});
What I need are different POMs for each configured project. Is there a way to create a POM instance with the browser
or page
fixture for each project in the config?
// playwright.config.ts
const config: PlaywrightTestConfig<TestOptions> = {
...
projects: [
{
name: 'proj1',
use: {
productDetailPom: new ProductDetailPom1(browser, 'url1') // POM instance 1
}
},
{
name: 'proj2',
use: {
productDetailPom: new ProductDetailPom2(browser, 'url2') // POM instance 2
}
}
],
};
I found no way to construct POMs in the config, but a workaround. Here is what I came up with. Please tell me if you have a better solution.
In short: The POM instances are created not in the config, but later. For instantiation I use a factory, which can be the same for all projects. Only the data fed into the factory differ per project.
In the config I add the data I need for construction: the POM class itself and data that will get passed to the constructor. Those data can be different in each project.
// playwright.config.ts
const config: PlaywrightTestConfig<TestOptions> = {
...
projects: [
{
name: 'proj1',
use: {
productDetailPomConstr: [ProductDetailPom1, 'url1']
},
},
{
name: 'proj2',
use: {
productDetailPomConstr: [ProductDetailPom2, 'url2']
}
}
]
};
For creating the instance of the POM I use a factory, which is the same for all projects and because of this can be added by extending the base test. This is where I get the browser
instance from (you could also get all other fixtures like page
).
import { test as base } from '@playwright/test';
type TestOptions = {
pomFactory: PomFactory,
productDetailPomConstr: [typeof ProductDetailPom, Record<string, any>]
};
export const test = base.extend<TestOptions>({
pomFactory: async ({ browser }, use) => {
const pomFactory = new PomFactory(browser);
await use(pomFactory);
},
productDetailPomConstr: [null, { option: true }],
});
In the test I can get both fixtures, factory and PomConstruction data, and instantiate my POM with them.
test('someTest', async ({pomFactory, productDetailPomConstr}) => {
const pdPom = await pomFactory.create<ProductDetailPom>(productDetailPomConstr);
});
Maybe this helps someone.