Page
createPage makes it possible to describe a page on the same model as a component, with the addition of a makePath(...) function to build its path.
In practice, it is the right abstraction when a screen must be both navigable and manipulable like a component.
Simple example
ts
import { createComponent, createPage, createWebsite, type Website } from "@duplojs/playwright";
import test from "playwright/test";
interface TestFixtures {
website: Website;
}
const testClient = test.extend<TestFixtures>({
async website({ page, context }, use) {
const website = createWebsite({
playwrightPage: page,
playwrightBrowserContext: context,
envConfig: {
baseUrl: "https://example.com",
},
});
await use(website);
},
});
const toolbar = createComponent(
"toolbar",
{
getMainElement({ body }) {
return body.locator("[data-toolbar]");
},
},
);
const articlePage = createPage(
"article",
{
makePath({ slug }: { slug: string }) {
return `/articles/${slug}`;
},
getMainElement({ body }) {
return body.locator("main");
},
getElements({ mainElement }) {
return {
title: mainElement.locator("h1"),
};
},
components: [toolbar],
},
);
testClient("page example", async({ website }) => {
const article = await website.iNavigateTo(articlePage, { slug: "articleId" });
const toolbar = await article.iWantToSeeComponent("toolbar");
});What is happening here
- the example shows an extended Playwright client, then the page definition.
createPage(...)describes anarticlepage.makePath(...)builds the navigation path.getMainElement(...)defines the main element of the page.- the page then exposes its elements like a regular component.
Parameters
name- the public name of the page in the test model.params.makePath- builds the page path.params.getMainElement- returns the root locator of the page.params.getElements?- exposes named elements.params.getMethods?- exposes methods built from the page context.params.components?- registers sub-components accessible from the page.
Syntax
ts
interface CreatePageParams {
makePath(...args: any[]): string;
getMainElement(params: {
body: Locator;
}): Locator;
getElements?(params: {
mainElement: Locator;
body: Locator;
}): Record<string, Locator>;
getMethods?(params: {
mainElement: Locator;
body: Locator;
elements: Record<string, Locator> | undefined;
website: Website;
}): Record<string, (...args: any[]) => any>;
components?: ComponentEngine[];
}
type PageEngine = (website: Website) => Page;
interface Page extends Component {
makePath(...args: any[]): string;
}What is it for?
Page is used to bring together in the same object:
- path construction
- access to a screen's elements
- methods specific to this page
- composition with other components
In other words, it makes it possible to navigate to a page and then manipulate it with the same abstraction.
See also
Website- to navigate to a page withiNavigateTo(...)oriGoTo(...).Component- for the common model also used by pages.Component Interaction- to create reusable interactions on a page's elements.Actions- for ready-to-use actions on the page's elements.Assertions- for ready-to-use assertions on the page's elements.
