lecture 8 of 150 completed

Keeping selectors in one place

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

Custom commands fixed repeated actions, like login. There is a second kind of repetition, and it hurts just as much.

Look at these three lines. They appear in eight different test files:

cy.get('[data-testid="contact-name-input"]').type('Dana');
cy.get('[data-testid="contact-email-input"]').type('dana@foxlabs.io');
cy.get('[data-testid="save-contact"]').click();

A developer renames contact-name-input to contact-full-name. Now you search the whole project for that string and fix eight files. Miss one, and a test fails tomorrow for a reason that has nothing to do with the feature.

The answer is to keep the selectors in one place. Create a file that describes the screen:

export const contactForm = {
  name: () => cy.get('[data-testid="contact-name-input"]'),
  email: () => cy.get('[data-testid="contact-email-input"]'),
  save: () => cy.get('[data-testid="save-contact"]'),

  fill(contact) {
    this.name().type(contact.name);
    this.email().type(contact.email);
    this.save().click();
  },
};

Each key is a small function that returns the element. fill is a shortcut that uses them together. When the developer renames that test id, you change one line in one file.

Your test then reads almost like English:

contactForm.fill({ name: 'Dana Fox', email: 'dana@foxlabs.io' });
cy.contains('[data-testid="contact-row"]', 'Dana Fox').should('exist');

This pattern has a name: the Page Object Model. You will be asked about it in interviews. The short answer they want is: it keeps selectors 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 checks inside the page object:

// Do not do this
verifyContactSaved() {
  cy.get('[data-testid="toast"]').should('contain', 'Contact created');
}

It looks tidy, but now nobody can read a test and see what it proves. They have to open another file. Keep it simple: the page object holds selectors and actions. The test holds the checks.

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

Reference: Best Practices.