Assertions
Expect makes an assertion that is checked again until it holds, or until its time runs out. Use it for anything the page may still be changing: after a click, the result may take a moment to appear, and an assertion that reads the page once would fail, or pass, by chance.
Expect is a static method of Assertions; bring it in with using static Dramaturge.Assertions;.
Elements
await Expect(page.GetByRole("alert")).ToBeVisibleAsync();
await Expect(page.GetByRole("button", "Submit")).ToBeEnabledAsync();
await Expect(page.GetByLabel("Email")).ToHaveValueAsync("ada@example.com");
await Expect(page.GetByRole("status")).ToHaveTextAsync("Saved");
await Expect(page.GetByRole("listitem")).ToHaveCountAsync(3);
await Expect(page.GetByTestId("total")).ToHaveTextAsync(new Regex(@"^\$\d+\.\d{2}$"));
| Matcher | Holds when the element |
|---|---|
ToBeVisibleAsync, ToBeHiddenAsync |
Is visible, or hidden; no element at all is hidden |
ToBeAttachedAsync |
Exists in the document |
ToBeEnabledAsync, ToBeDisabledAsync |
Is enabled, or disabled |
ToBeEditableAsync |
Can be edited: neither disabled nor read-only |
ToBeCheckedAsync |
Is a checked checkbox or radio button; a mixed checkbox is not checked |
ToBeEmptyAsync |
Is an input or text area without a value, or an element with no child elements and only white space |
ToBeFocusedAsync |
Has focus in its document or shadow root |
ToBeInViewportAsync |
Is at least partly within its frame's viewport |
ToHaveTextAsync, ToContainTextAsync |
Has, or contains, a text; see Text |
ToHaveValueAsync |
Is an input, text area, or select with a value |
ToHaveAttributeAsync |
Has an attribute, optionally with a value |
ToHaveIdAsync, ToHaveClassAsync |
Has an id, or a whole class attribute |
ToHaveCssAsync |
Has a computed CSS property value |
ToHaveCountAsync |
Is one of exactly the given number of elements the locator finds |
ToMatchAriaSnapshotAsync |
Has an accessibility snapshot that matches a template; see Accessibility Snapshots |
Each matcher that compares a value takes a string, for an exact match, or a Regex, which may match anywhere in the value. A matcher about one element throws AmbiguousElementException at once if the locator finds several; ToHaveCountAsync and the list forms of the text matchers work with every match. A matcher that cannot apply to the element, such as ToHaveValueAsync on a paragraph, throws InvalidOperationException at once.
Negation
Not waits until the condition stops holding:
// Waits until the spinner is gone, and fails if it is still showing after the timeout.
await Expect(page.GetByRole("progressbar")).Not.ToBeVisibleAsync();
await Expect(page.GetByRole("status")).Not.ToHaveTextAsync("Saving");
No element at all satisfies the negation of a matcher about an element's state or text, so Not.ToBeVisibleAsync() passes once the element is gone.
Text
// White space is collapsed and trimmed, on the page and in the expected text.
await Expect(page.GetByRole("heading")).ToHaveTextAsync("Order summary");
await Expect(page.GetByRole("heading")).ToContainTextAsync("summary", ignoreCase: true);
// The rendered text, without text hidden by CSS.
await Expect(page.GetByTestId("price")).ToHaveTextAsync("$10.00", useInnerText: true);
// Every matching element, in order.
await Expect(page.GetByRole("listitem")).ToHaveTextAsync(["Apples", "Bread", "Cheese"]);
await Expect(page.GetByRole("listitem")).ToContainTextAsync(["Apples", "Cheese"]);
- White space is collapsed and trimmed, in the element's text and in an expected string, so line breaks and indentation in the HTML do not matter. A
Regexis matched against the collapsed text, unchanged. - Case is compared exactly unless
ignoreCaseis set. For aRegex, useRegexOptions.IgnoreCase. - Hidden text is included: the matchers read
textContent.useInnerText: truereads the rendered text instead, without what CSS hides. - A list of texts checks every matching element, in order.
ToHaveTextAsyncrequires exactly those texts;ToContainTextAsyncrequires each text in a later element than the one before, with other elements allowed between.
ToHaveValueAsync, ToHaveAttributeAsync, and the other value matchers compare the value as it is, because a value's white space can matter.
Pages
await Expect(page).ToHaveUrlAsync(new Regex("/orders/\\d+$"));
await Expect(page).ToHaveTitleAsync("Order confirmed");
ToHaveUrlAsync follows the URL the browser reports for each navigation, fragment change, and history update, without sending a command. ToHaveTitleAsync reads the title, with white space collapsed, again after each navigation.
Timeouts and Failures
An expectation retries for ExpectTimeout, 5 seconds unless configured, or the timeout given to the matcher. When it runs out, it throws ExpectationFailedException, which works with any test framework:
try
{
await Expect(page.GetByRole("status")).ToHaveTextAsync("Saved", timeout: TimeSpan.FromSeconds(2));
}
catch (ExpectationFailedException ex)
{
// Expected getByRole "status" to have text "Saved"; received "Saving…" after 2 seconds.
Console.WriteLine(ex.Message);
Console.WriteLine($"{ex.Expected} / {ex.Actual} / {ex.Timeout}");
}
Expected says what was required, Actual what the last check saw (or null if no element ever matched), and Timeout how long it retried.