Playwright Assertions
On This Page What are Playwright Assertions?Playwright Expect ()
- What are Playwright Assertions?
- Playwright Expect () Function
- Different Types of Playwright Assertions
- Playwright Custom Matchers with Examples
- Handling Dynamic UI States with Assertions
- Assertions for Network Requests and Responses
- Mutual Mistakes with Playwright Assertions
- Best Practices to use Playwright Expect ()
- Why run Playwright Tests on Real Device Cloud?
Understanding Playwright Assertions [2026]
When a test bunk, I always wonder—did the app really behave the way I await, or did the hand just move on? That incertitude is exactly where Playwright averment come in.
I use assertions to intermit the test and requirement proof. Is the component visible? Did the value modification? Did the action actually succeed? Each cheque forces the application to reveal whether it ’ s bear correctly.
That moment of proof decides everything. If the prospect holds, the test surpass. If not, it betray instantly. With affirmation in spot, I ’ m no longer assuming correctness—I ’ m verify it, tread by step.
What are Playwright Assertions?
Playwright Assertionsare a set of built-in purpose which includesexpect () functionply by the Playwright prove framework to validate the behavior and state of a web coating during machine-controlled tests.
Playwright Assertions are used to verify whether specific conditions are met, such as ensure if an element exists, contains certain text, or has a particular state. These assertions are essential for confirming that the application carry as expected during end-to-end testing.
Playwright provides diverse assertion types:
- Element States:Check the visibility, availability, and interactivity of UI elements.
- Contented Validation:Ensure elements display the correct text, values, or match specific form.
- Page Properties:Assertions can support page details like URLs, titles, or cookie presence.
- Network Interactions:Verify the outcomes of network postulation and responses to ensure proper information loading and form submissions.
Playwright Expect () Function
Playwrightexpectis the built-in asseveration API used to validate how an application behaves during a test.
It allows tests towait for conditions to be trueand so control outcomes such as element visibleness, text content, attributes, URLs, or network states. Instead of checking value instantly, look mechanically retries until the condition passes or the timeout is hit, which helps handle dynamical UI behavior.
In simple terms, expect is how Playwright affirm whether the app under test matches the expected province and decides if a tryout should pass or fail.
For Example:
test (`` Validate BrowserStack demo application site title '', async ({page}) = & gt; {await page.goto (`` https: //bstackdemo.com/ '') expect expect (page) .toHaveTitle (`` StackDemo '')})In the above codification example, using BrowserStack ’ s Demo application in the playwright test to validate the Site Title.
Code Breakdown:
Below code will access the BrowserStack ’ s Demo Application
await page.goto (`` https: //bstackdemo.com/ '')
Below codification Asserts the BrowserStack ’ s Website Title.
await anticipate (page) .toHaveTitle (`` StackDemo '')
Here, Playwright await until the component becomes visible before marking the assertion successful.
Different Types of Playwright Assertions
Assertions in Playwright is broadly classified into below case
Types of Playwright Assertions:
- Auto-retrying Assertions
- Non-retrying Assertions
- Negating Matchers
- Soft Assertions
Let ’ s look into each assertion character.
Auto-retrying Assertion
Auto-retrying affirmation in Playwright are a lively functionality that significantly boosts the reliability and stability of test playscript by repeatedly attempting to control assertions until they either succeed or a predefined timeout is gain.
Auto-retrying feature is especially utilitarian in scenario where web element might not immediately meet expected conditions due to network delays, dynamical content loading, or client-side scripting operations.
Let ’ s write a test which asserts a schoolbook from BrowserStack ’ s Demo Application Website.
In this exam, performing below steps:
- Access BrowserStack ’ s Demo application
- Validate the default Number of Products found
exam (`` Validate BrowserStack nonpayment products found enumeration '', async ({page}) = & gt; {await page.goto (`` https: //bstackdemo.com/ '') const productLocator = await page.locator (`` .products-found span '') wait expect (productLocator) .toHaveText ('25 Product (s) found ')})Code Breakdown
Visit the BrowserStack ’ s Demo application
await page.goto (`` https: //bstackdemo.com/ '')
Get the locator reference
const productLocator = await page.locator (`` .products-found span '')
Assert the Number of Products found from Web page against expected value
await expect (productLocator) .toHaveText ('25 Product (s) found ')Observe that in the above assertion you pass the locator acknowledgment and then you are using matchmakertoHaveTextwhich take expected value as string.
If you run the above test, the test will fail in assertion with automobile retry timeout.
Note that the exam is timed out after retrying for 5000 milliseconds, this is because Playwright has a default timeout of 5000 milliseconds.
You can overwrite the assertion timeout at command level like below.
await expect (productLocator) .toHaveText ('25 Product (s) found ', {timeout: 2000})Below is the full inclination of Auto-Retrying assertions.
| Assertion | Description |
|---|---|
| await expect (locater) .toBeAttached () | Element is attached |
| await expect (locator) .toBeChecked () | Checkbox is insure |
| await await (locater) .toBeDisabled () | Element is disabled |
| await wait (locator) .toBeEditable () | Element is editable |
| await expect (locator) .toBeEmpty () | Container is vacuous |
| await expect (locator) .toBeEnabled () | Element is enabled |
| await expect (locater) .toBeFocused () | Element is concentrate |
| await await (locator) .toBeHidden () | Element is not visible |
| await expect (locator) .toBeInViewport () | Element intersects viewport |
| await expect (locator) .toBeVisible () | Element is visible |
| await expect (locator) .toContainText () | Element contains text |
| await expect (locator) .toHaveAttribute () | Element has a DOM attribute |
| await anticipate (locater) .toHaveClass () | Element has a class holding |
| await ask (locater) .toHaveCount () | List has exact number of children |
| await wait (locator) .toHaveCSS () | Element has CSS property |
| await expect (locator) .toHaveId () | Element has an ID |
| await expect (locater) .toHaveJSProperty () | Element has a JavaScript property |
| await anticipate (locator) .toHaveScreenshot () | Element has a screenshot |
| await expect (locator) .toHaveText () | Element matches text |
| await ask (locator) .toHaveValue () | Input has a value |
| await expect (locator) .toHaveValues () | Select has option selected |
| await expect (page) .toHaveScreenshot () | Page has a screenshot |
| await ask (page) .toHaveTitle () | Page has a title |
| await expect (page) .toHaveURL () | Page has a URL |
| await wait (response) .toBeOK () | Response has an OK status |
Non-retrying Assertions
Non-retrying Assertions are only useful when web pages load data asynchronously. Test assertion will fail without any timeout or rehear when using the Non-retrying Assertion and below is an instance test for the same.
test (`` example for non-retrying averment '', async ({page}) = & gt; {await page.goto (`` https: //bstackdemo.com/ '') const productLocator = await page.locator (`` .products-found couplet '') const productSearchText = await productLocator.innerText () await expect (productSearchText) .toBe ('25 Product (s) found ')})When you run this test, it will fail with affirmation without retrying.
Below is the full list of Non-retrying assertion matchers
| Assertion | Description |
|---|---|
| expect (value) .toBe () | Value is the same |
| expect (value) .toBeCloseTo () | Number is approximately equal |
| expect (value) .toBeDefined () | Value is not vague |
| expect (value) .toBeFalsy () | Value is falsy, e.g.false, 0, null, etc. |
| expect (value) .toBeGreaterThan () | Number is more than |
| expect (value) .toBeGreaterThanOrEqual () | Number is more than or equal |
| expect (value) .toBeInstanceOf () | Object is an representative of a class |
| expect (value) .toBeLessThan () | Number is less than |
| expect (value) .toBeLessThanOrEqual () | Number is less than or equal |
| expect (value) .toBeNaN () | Value is NaN |
| expect (value) .toBeNull () | Value is null |
| expect (value) .toBeTruthy () | Value is truthy, i.e. notfalse, 0, null, etc. |
| expect (value) .toBeUndefined () | Value is undefined |
| expect (value) .toContain () | String contains a substring |
| expect (value) .toContain () | Array or set contains an element |
| expect (value) .toContainEqual () | Array or set contains a like factor |
| expect (value) .toEqual () | Value is alike & # 8211; deep equality and pattern matching |
| expect (value) .toHaveLength () | Array or string has length |
| expect (value) .toHaveProperty () | Object has a property |
| expect (value) .toMatch () | String matches a veritable face |
| expect (value) .toMatchObject () | Object contains specified properties |
| expect (value) .toStrictEqual () | Value is similar, including property types |
| expect (value) .toThrow () | Function throws an error |
| expect (value) .any () | Matches any example of a class/primitive |
| expect (value) .anything () | Matches anything |
| expect (value) .arrayContaining () | Array contains specific elements |
| expect (value) .closeTo () | Number is approximately equal |
| expect (value) .objectContaining () | Object contains specific property |
| expect (value) .stringContaining () | String control a substring |
| expect (value) .stringMatching () | String match a veritable face |
Negating Matchers
Negating Matchers are used when we want to check that a certain condition perform not hold true. It basically reverses the condition you & # 8217; re checking for, enabling you to assert the absence of a condition or element. Negating Matchers are especially helpful for ensuring that a web page or application is gratuitous from errors, incorrect province, or unwanted elements.
For autonomous testing across multiple user personas, check out SUSATest — it explores your app like 10 different real users.
Below is the example test. The tryout will assert for filter count not matching the value 3
test (`` example for negate matchmaker '', async ({page}) = & gt; {await page.goto (`` https: //bstackdemo.com/ '') const filter = await page.locator (`` .filters .filters-available-size '') const filterCount = await filter.count () look expect (filterCount) .not.toEqual (3)})Soft Assertions
By nonremittal Assertion will abort the examination as soon as the expected result is not mate with the actual result. There are cases where we have to control multiple assertions and at the end of the test shed the assertion error.
Soft statement is good for cases where we want to swan multiple cases and then fail the test at the end.
Below is the example trial. The test has two assertions and both will execute and fail.
test (`` example for soft assertion '', async ({page}) = & gt; {await page.goto (`` https: //bstackdemo.com/ '') const filter = await page.locator (`` .filters .filters-available-size '') const filterCount = await filter.count () await expect.soft (filterCount) .not.toEqual (4) await expect.soft (page) .toHaveTitle (`` StackDemo! '')})If you don ’ t use soft assertion, so the test will fail at the first assertion check and doesn ’ t continue.
Running the above test will shew two assertion fault.
Playwright Custom Matchers with Examples
Playwright render users to create their own Custom Matchers, which can be chained withexpect() for Assertions
To create Custom Matchers, we need to go theexpect() map from Playwright and then add our Custom Matchers within the extend function like below
import { expect asbaseExpect}from' @ playwright/test ';importtype {Page, Locator}from' @ playwright/test ';export { test } from' @ playwright/test ';export constexpect = baseExpect.extend ({asynctoHavePrice (locater: Locator, expected: number, pick?: {timeout?: number}) {constassertionName = 'toHavePrice ';letpass: boolean;letmatcherResult: any;try {
awaitbaseExpect (locator) .toHaveText (String (expected), options); pass = true;}catch(e: any) {matcherResult = e.matcherResult; pass = false;}constcontent = passing? () = & gt;this.utils.matcherHint (assertionName, undefined, undefined, {isNot:this.isNot}) + '\n\n ' + ` Locator: $ {locater} \n ` + ` Expected: $ {this.isNot? 'not ': ``} $ {this.utils.printExpected (expected)} \n ` + (matcherResult? ` Received: $ {this.utils.printReceived (matcherResult.actual)} `: ``): () = & gt;this.utils.matcherHint (assertionName, undefined, undefined, {isNot:this.isNot}) + '\n\n ' + ` Locator: $ {locator} \n ` + ` Expected: $ {this.utils.printExpected (expected)} \n ` + (matcherResult? ` Received: $ {this.utils.printReceived (matcherResult.actual)} `: ``);return{message, pass, gens: assertionName, expected, actual: matcherResult? .actual,};},});We can make a new file called fixture.ts and add the above code in that file. Once the code is added we can then write a tryout like below.
import{test, expect}from' .. /fixtures/fixtures '; test (`` example for usage matcher '',async({page}) = & gt; {awaitpage.goto (`` https: //bstackdemo.com/ '')const phone = awaitpage.locator (`` .shelf-item__title '', {hasText: '' iPhone 12 Mini '',})constphoneParent =awaitphone.locator (`` .. '')constphonePrice = phoneParent.locator (`` .shelf-item__price .val b '')awaitexpect (phonePrice) .toHavePrice (`` 699 '')})Handling Dynamic UI States with Assertions
Modern web coating rarely abide still. Elements lade asynchronously, UI states vary based on user actions, and content updates after network calls. Assertions in Playwright are designed to care this dynamism without relying on manual waits or fragile timing logic.
Playwright ’ s expect () averment automatically wait for the expected condition to be met before failing. This makes them effective for corroborate UI states that appear, disappear, or update over time.
Mutual active scenario handled with affirmation include:
- Elements turn seeable after an API response
- Buttons enable or disabling establish on form stimulant
- Text or property updating after user interaction
- Loaders or spinner disappearing before content renders
For instance:
await expect (page.locator ('.loader ')) .toBeHidden (); await expect (page.locator (' # condition ')) .toHaveText ('Completed ');Here, the assertions await until the UI reaches the expected state instead of checking immediately. This access cut flakiness and keeps test aligned with how existent users get the covering.
Are your Playwright statement really reliable?
Assertions for Network Requests and Responses
UI validation alone is frequently not plenty. Many user-visible changes bet on network activity, and Playwright allows affirmation to validate those interactions straight.
Assertions can be combine with web interception to control:
- API response status codes
- Request payload post by the application
- Response body affecting UI behavior
- Completion of critical backend operation
A common pattern involve look for a reaction and so asseverate on its outcome:
const response = await page.waitForResponse (resp = & gt; resp.url () .includes ('/api/order ') & amp; & amp; resp.status () === 200); await expect (response.ok ()) .toBeTruthy ();By asserting on mesh doings, trial confirm not merely that the UI changed, but that it changed for the right intellect. This strengthens test reporting for data-driven workflow and reduces blind spot where UI-only assertions might pass despite backend issue.
Common Mistakes with Playwright Assertions
Even with powerful defaults, assertions can inclose imbalance when used incorrectly. Many flaky tests follow backward to assertion misuse rather than application defects.
Frequent misunderstanding include:
- Using manual waits instead of relying on auto-retrying assertions
- Asserting too early on constituent that depend on async provide
- Overusing hard assertions where soft assertions are more appropriate
- Validating effectuation details instead of user-visible behavior
For example, checking textbook now after navigation:
// Fragile approach await page.click (' # submit '); wait (await page.textContent (' # msg ')) .toBe ('Success ');A more stable approach:
await page.click (' # submit '); await ask (page.locator (' # msg ')) .toHaveText ('Success ');This allows Playwright to wait until the UI is truly ready. Open, user-focused assertions combined with built-in retries result in tests that fail for real issues, not timing quirks or transient states
Best Practices to use Playwright Expect ()
The expect()function is a cornerstone of assertions in Playwright, volunteer the ability to assert on elements, net response, and other test conditions.
Below are the few Best Practices for Playwright Expect ():
1. Leverage Built-In Retry Mechanism
Understand the reflexive retry characteristic in Playwright ’ s expect ():
- Utilize this feature for dynamic message where elements may appear or vary province over time.
- Avoid extravagant trust which might conceal execution issues or complex race weather.
2. Employ Semantic Locators
Opt for Playwright ’ s progress picker like role and text selectors to improve both the legibility and maintainability of your tests:
awaitanticipate (page.locator ('text=Sign In ')) .toBeVisible ();awaitexpect (page.locator ('role=button ', {gens: 'Send '})) .toBeEnabled ();These chooser heighten the semantic clarity and handiness focus of your tests.
3. Integrate Actions with Verification
Simultaneously perform user activity and control outcomes to mime real user flows:
awaitpage.click ('button # save ');awaitask (page.locator ('text=Saved successfully ')) .toBeVisible ();This method validates user interactions in real-time.
4. Customize Timeouts
Adjust timeouts inexpect()when the default scene do not align with specific test requirements:
- Modify the timeout parameter to suit specific expect want without overextending test durations.
5. Assert Non-Presence
Assert the non-presence of constituent or messages, particularly useful in validate error handling and user feedback:
awaitexpect (page.locator ('text=Error ')) .not.toBeVisible ();6. Utilize State-Specific Assertions
Make total use of Playwright ’ s state-specific averment to directly valuate the user interface:
awaitrequire (page.locator ('input [type= '' checkbox ''] ')) .toBeChecked ();7. Assert Network Interactions
Capture and assert network response to ensure backend integration is functioning as expected:
const[reaction] =awaitPromise.all ([page.waitForResponse (resp = & gt; resp.url () .includes ('/api/submit ') & amp; & amp; resp.status () === 200), page.click ('button # submit ')]);awaitexpect (response) .toBeOK ();8. Validate Accessibility Features
Assert on accessibility characteristic to ensure your application is accessible:
awaitexpect (page.locator (& # 8216; role=button & # 8217;, {gens: & # 8216; Confirm & # 8217;})) .toHaveAttribute (& # 8216; aria-live & # 8217;, & # 8216; polite & # 8217;);
9. Enhance Assertion Failures
Incorporate symptomatic creature like screenshots or logs to enquire why averment betray:
test.fail (async({page}) = & gt; {awaitpage.screenshot ({route: 'error-snapshot.png '});});Why run Playwright Tests on Real Device Cloud?
Here & # 8217; s why you should run Playwright examination on existent browsers & amp; devices employ a cloud-based testing platform like:
- Accurate UI behavior validation:Assertions related to visibility, text rendering, focus states, and animations can behave differently across existent browser and device. Running them onBrowserStack Automateensures these checks hold true in real environments.
- Reduced mistaken positives in test results:Assertions may legislate locally but fail for exploiter due to OS-level differences, browser engines, or device-specific timing. Existent device testing helps catch these gaps betimes.
- Logical assertion timing under real conditions:Real devices reveal performance variations that impact assertion retries and timeouts. This makes assertions more reliable and align with real-world load and rendering behavior.
- Scalable validation across environments:BrowserStack Automate enables scat assertion-heavy Playwright tests in parallel across multiple browser–OS combinations, ensuring extensive coverage without increasing execution clip.
- Better debug when averment fail:Screenshots, videos, and logarithm from existent device runs ply clear context for why an asseveration failed, making root cause analysis quicker and more accurate.
Conclusion
The expect()office of Playwright is a critical plus for automation testers, delivering powerful and adaptable assertions crucial for control the integrity and functionality of web coating. Its inherent retry capability, couple with its proficiency in handling complex assertions on component, network interactions, and accessibility attributes, is particularly efficacious for modern web applications qualify by dynamic and asynchronous behavior.
Utilizing expect()adeptly within Playwright exam enables testers to sustain that their applications not alone adhere to specific essential but also present a stable exploiter experience across divers scenarios. This map & # 8217; s ability to exactly adjust statement conditions, such as timeouts, and to assess a all-embracing spectrum of criteria—from the visibleness of elements to the rightness of API responses—increases the preciseness and dependability of tests.
Running your Playwright Tests on BrowserStack ’ s helps you get access to 3500+ real device and browser combinations for. It grant you to, which will facilitate name the bottlenecks in the real user experience and rectify them. BrowserStack ’ s allows you to run Playwright exam on the cloud and across browser and device simultaneously by leveraging for faster testing with a vast coverage.
On This Page
- What are Playwright Assertions?
- Playwright Expect () Function
- Different Types of Playwright Assertions
- Playwright Custom Matchers with Examples
- Handling Dynamic UI States with Assertions
- Assertions for Network Requests and Responses
- Common Mistakes with Playwright Assertions
- Best Practices to use Playwright Expect ()
- Why run Playwright Tests on Real Device Cloud?
# Ask-and-Contributeabout this topic with our Discord community.
Related Guides
Automate This With SUSA
Upload your APK or URL. SUSA explores like 10 real users — finds bugs, accessibility violations, and security issues. No scripts needed.
Try SUSA FreeTest Your App Autonomously
Upload your APK or URL. SUSA explores like 10 real users — finds bugs, accessibility violations, and security issues. No scripts.
Try SUSA Free