I have simple test:
test.("Accept all cookies", async ({ base, cookies }) => {
await test.step("Open main page", async() => {
await base.openMainPage();
})
await test.step("Accept all cookies", async() => {
await cookies.acceptAllCookies();
})
await test.step("Verify that cookies are not displayed", async() => {
await expect(cookies.acceptAllCookiesButton).toBeVisible();
})
})
Problem is: When I have toBeVisible() - test passed. and when I have not.toBeVisible() - test also passed.
Why ? ๐ What I should change ?
This thread is trying to answer question "Why do both toBeVisible() and not.toBeVisible() pass in the test case?"
This is a pretty generic case of negative expectations in test automation. A good rule of thumb is to add a positive expectation before a negative one.
For example your call to acceptAllCookies()
(which I'm assuming is a pretty basic button click?) could allow for the button to be visible in the DOM for any duration of time. So based on your timeout settings, a not
expectation would potentially wait up to that timeout for the button to disappear, whereas .toBeVisible()
could pass even if the button is displayed for a split second.
Related Ask AI answer for "What is the difference between toBeVisible() and isVisible() in Playwright?".
toBeVisible()
and not.toBeVisible()
in PlaywrightIn Playwright, toBeVisible()
and not.toBeVisible()
are web first assertions. They ensure your tests are reliable by waiting for expected conditions to be met before proceeding.
toBeVisible()
AssertionWhen you use toBeVisible()
, Playwright waits until the expected condition is met. For instance, if your test clicks a button and expects an alert message to appear, toBeVisible()
waits for the alert message to be visible before proceeding.
import { test } from '@playwright/test';
test('alert should be visible', async ({ page }) => {
await page.goto('https://ray.run');
await page.click('#alertButton');
await expect(page.locator('#alertMessage')).toBeVisible();
});
not.toBeVisible()
AssertionOn the contrary, manual assertions like isVisible()
don't wait for any condition. They simply check if the locator is there and return immediately. This means that if you use expect(await page.getByText('welcome').isVisible()).toBe(true)
, it may return true even if the element is not actually visible.
import { test } from '@playwright/test';
test('welcome text should not be visible', async ({ page }) => {
await page.goto('https://ray.run');
await expect(await page.getByText('welcome').isVisible()).toBe(true);
});
In summary, toBeVisible()
and not.toBeVisible()
pass because they utilize web first assertions provided by Playwright. They ensure your tests wait until expected conditions are met before proceeding.
Rayrun is a community for QA engineers. I am constantly looking for new ways to add value to people learning Playwright and other browser automation frameworks. If you have feedback, email [email protected].