lecture 11 of 170 completed

Tables and lists

Checking that your search result is visible passes even when the search did nothing at all.

You type "Maya" into a search box and check the result:

cy.get('[data-testid="search-input"]').type('Maya');
cy.contains('Maya Chen').should('be.visible');

Maya is visible. The test passes. Now let me show you why this test is nearly useless.

Imagine the search box is completely broken and ignores what you type. All eight contacts stay on the screen. Is Maya Chen one of those eight? Yes. Is she visible? Yes.

The test passes on a search that does nothing.

The mistake is easy to make, because you tested what you were looking for. But a filter is not defined by what it keeps. A filter is defined by what it removes.

So count the rows:

cy.get('[data-testid="contact-row"]').should('have.length', 8); // before

cy.get('[data-testid="search-input"]').type('Maya');

cy.get('[data-testid="contact-row"]').should('have.length', 1); // after
cy.get('[data-testid="contact-row"]').should('contain', 'Maya Chen');

Now the test knows the difference between a working filter and a broken one. Going from 8 rows to 1 row is the proof. The last line then confirms the one row left is the right one.

Notice the first line too. Checking the starting count is a small habit worth having. If the table was empty before your search, a result of "1 row" might mean something else entirely.

This idea goes beyond search boxes. Any time your test makes a list smaller, count it:

  • Filtering by status.
  • Deleting a row.
  • Emptying a cart.

For deleting especially. A test that checks "the deleted item is gone" passes when the app deleted everything.

Remember this: when a list changes, check its size, not just one item in it.

Reference: Assertions.

now prove it

Reading is the setup. Solve these problems in the editor. We break the app on purpose to check your test would catch it.