Here is a test that looks fine and proves almost nothing:
await page.getByTestId('add-to-cart').first().click();
await expect(page.getByTestId('cart-count')).toBeVisible();
You add a product. You check the cart badge is visible. It passes.
Now imagine a developer breaks the cart counter, and the badge always shows 0. Is the badge still visible? Yes. Does this test still pass? Yes.
So this test tells you the badge exists. Nobody was worried about that.
Check the value your customer actually depends on:
await expect(page.getByTestId('cart-count')).toHaveText('1');
Now a broken counter fails the test immediately. That is the difference between code that runs and a test that proves something.
There is a second habit worth building right away. One action usually has more than one effect.
When you add a product to the cart, the app promises two things: the badge goes to 1, and a confirmation message appears. Those are two separate promises, and either one can break on its own:
await page.getByTestId('add-to-cart').first().click();
await expect(page.getByTestId('cart-count')).toHaveText('1');
await expect(page.getByTestId('toast')).toContainText('added to cart');
If you only check the toast, the counter can break silently for weeks.
One thing that makes this easy in Playwright: assertions written as await expect(locator)... retry automatically. They keep checking until the condition is true or time runs out. So checking an exact value does not make your test less stable.
Remember this: for every action, ask what the user is promised, then check each promise.
Reference: Assertions.