lecture 10 of 180 completed

Keeping selectors in one place

When the same locators appear in ten files, one UI change breaks all of them. Put them in one class.

Fixtures fixed repeated actions, like login. There is a second kind of repetition that hurts just as much.

These lines appear in eight different test files:

await page.getByTestId('contact-name-input').fill('Dana');
await page.getByTestId('contact-email-input').fill('dana@foxlabs.io');
await page.getByTestId('save-contact').click();

A developer renames contact-name-input. Now you search the whole project and fix eight files. Miss one, and a test fails tomorrow for a reason unrelated to the feature.

Put the locators in one place:

export class ContactForm {
  constructor(private page: Page) {}

  get name() { return this.page.getByTestId('contact-name-input'); }
  get email() { return this.page.getByTestId('contact-email-input'); }
  get save() { return this.page.getByTestId('save-contact'); }

  async fill(contact: { name: string; email: string }) {
    await this.name.fill(contact.name);
    await this.email.fill(contact.email);
    await this.save.click();
  }
}

Each getter returns a locator. fill is a shortcut that uses them together. When that test id changes, you edit one line in one file.

Your test now reads almost like English:

const form = new ContactForm(page);
await form.fill({ name: 'Dana Fox', email: 'dana@foxlabs.io' });
await expect(page.getByTestId('contact-row').filter({ hasText: 'Dana Fox' })).toBeVisible();

This pattern is called the Page Object Model. You will be asked about it in interviews. The short answer: it keeps locators and page actions in one place, so a UI change is one edit instead of many.

Now the mistake almost everyone makes at first. Do not put your assertions inside the page object:

// Do not do this
async verifySaved() {
  await expect(this.page.getByTestId('toast')).toContainText('Contact created');
}

It looks tidy, but now nobody can read a test and see what it proves without opening a second file. Keep it simple: the page object holds locators and actions. The test holds the assertions.

Remember this: if you cannot tell what a test proves without opening another file, you have gone too far.

Reference: Page object models.