Просматривая некоторые уроки, я хотел реализовать универсальный импортер для объектов страницы. Вместо вызова my_file.page.ts
в каждом тесте я хотел импортировать все *.page.ts
в один index.ts
файл, но я больше не могу вызывать локаторы и использовать для этого собственные методы Playwright.
Вот index.ts
const { test: base, expect } = require('@playwright/test')
import { LoginPage } from '../pages/login.page';
import { AssignFields } from '../pages/assignFields.page';
const test = base.extend({
page: async ({ page }: any, use: (arg0: any) => any) => {
await use({
...page,
login: new LoginPage(page),
assignfields: new AssignFields(page),
})
}
})
export { test, expect };
Я ничего не менял в assignFields.page.ts
import { Page } from '@playwright/test';
const selectors = {
btnAssignFields: 'selector1',
btnEdit: 'selector2',
tableFields: 'selector3',
tableFieldsItems: 'selector4',
};
export class AssignFields {
readonly page: Page;
readonly selectors : any;
constructor(page: Page) {
this.page = page;
this.selectors = selectors
}
async assignFields() {
await this.page.locator(this.selectors.btnAssignFields).click();
}
async edit() {
if (await this.page.isVisible(this.selectors.btnEdit)) {
await this.page.locator(this.selectors.btnEdit).click();
}
}
async searchByField(fieldName: string) {
await this.page.getByPlaceholder('Search').fill(fieldName);
}
}
При этом я импортирую файл index.ts
и провожу тесты на assignFields.spec.ts
.
import { test, expect } from '../support/index';
test('Filter by text', async ({ page }) => {
await page.login.goto();
await page.login.fillEmail('[email protected]');
await page.login.fillPass('my_password');
await page.login.clickLogin();
await page.locator(page.assignfields.selectors.btnAssignFields).waitFor();
await page.assignfields.assignFields();
await page.waitForSelector(page.assignfields.selectors.tableFields);
await page.assignfields.edit();
await page.assignfields.searchByField('my_field');
await expect(
page.locator(page.assignfields.selectors.tableFieldsItems)
).toHaveCount(1);
});
При запуске проекта я получил следующее сообщение:
@assignFields.spec.ts:9
TypeError: page.locator is not a function
Эта строка первая await page.locator
и я из этого понимаю, что что-то не правильно импортируется, может сам Драматург, может еще что-то, но я не могу исходить из этого.
Похоже, вы перепутали страницы — которые являются настоящим объектом page
, предоставленным Playwright, и созданными вами страницами с именами LoginPage и AssignFields.
Вместо использования page.locator вы можете вызвать page.page.locator, чтобы устранить проблему, но для этого могут потребоваться некоторые дополнительные изменения в index.ts.
Вместо этого я бы пошел и изменил соглашение об именах.
Вот мои предложения:
const test = base.extend({
app: async ({ page }, use) => {
await use({
page, // Keep the original page object
login: new LoginPage(page),
assignfields: new AssignFields(page),
});
}
});
app
вместо page.test('Filter by text', async ({ app }) => {
await app.login.goto();
await app.login.fillEmail('[email protected]');
await app.login.fillPass('my_password');
await app.login.clickLogin();
await app.page.locator(app.assignfields.selectors.btnAssignFields).waitFor();
...
Эти изменения должны дать вам представление о том, как решить проблему.
вызов page.page.locator
возвращает ошибку на линии goto()
.
стратегия app
сработала отлично
Настоятельно рекомендую не выставлять локаторы непосредственно внутри тестов.
Причина, по которой я предлагаю, — не выставлять локаторы внутри тестов, чтобы избежать ненужного обслуживания на случай, если их потребуется изменить позже. В этой ситуации вам придется изменить их во всех тестах, где бы они ни были определены. По сути, держите их СУХИМИ — en.wikipedia.org/wiki/Don%27t_repeat_yourself
Привет, Вишал! Да, мы уже это исправляем, спасибо!
Используйте объектную модель страницы правильно. Посмотрите это — stackoverflow.com/a/75088985/1831456