Free tools Windows power users keep installed

One-click scans. No signup required.

Special offer. See more information about Outbyte and uninstall instructions. Please review EULA and Privacy policy.

Some links on this page are affiliate links: if you buy through them we may earn a commission, at no extra cost to you.

In a legacy Protractor test, use browser.wait with a condition that re-queries the element and resolves to true only when the required class state is reached. To detect a transition, record the original class before triggering the change. For “disappear,” decide whether the test requires the element to be removed from the DOM or merely become invisible; those are different conditions.

Wait for a class change with browser.wait

getAttribute('class') reads the element’s class attribute. A browser.wait condition can return a promise that resolves to a Boolean, so the wait can poll the page until the predicate is satisfied or the timeout expires.

To detect any change, read the starting class before the action that causes the update, then compare each later reading with it:

Special offer. See more information about Outbyte and uninstall instructions. Please review EULA and Privacy policy.
var notice = element(by.css('.notice'));
var initialClass;

notice.getAttribute('class').then(function(className) {
  initialClass = className || '';

  // Trigger the application change only after recording the before-state.
  element(by.css('.save-button')).click();

  return browser.wait(function() {
    return element(by.css('.notice')).getAttribute('class').then(function(className) {
      return (className || '') !== initialClass;
    });
  }, 5000, 'Expected the notice class to change');
});

The example uses a five-second bound and a message that identifies the failed expectation. Adjust the locator, triggering action, and timeout to match the application and suite. The important ordering is that the initial value is read before the action: if the first poll happens after the update, a value captured during polling cannot reliably serve as the old state.

If the test only cares that a particular class appears, wait for that desired state instead of any difference. This is usually clearer and less likely to pass because of an unrelated class change:

var readyClass = /(^|s)is-ready(s|$)/;

element(by.css('.notice')).click();

browser.wait(function() {
  return element(by.css('.notice')).getAttribute('class').then(function(className) {
    return readyClass.test(className || '');
  });
}, 5000, 'Expected the notice to gain the is-ready class');

For a class that must be removed, negate the token check:

var loadingClass = /(^|s)is-loading(s|$)/;

element(by.css('.notice')).click();

browser.wait(function() {
  return element(by.css('.notice')).getAttribute('class').then(function(className) {
    return !loadingClass.test(className || '');
  });
}, 5000, 'Expected the notice to lose the is-loading class');

The token-boundary expression matches a complete class token, not a substring. For example, checking whether the class string contains ready could also match a different token such as not-ready. Use a predicate for the state the test actually requires; “class differs” is appropriate only when any transition is meaningful.

Special offer. See more information about Outbyte and uninstall instructions. Please review EULA and Privacy policy.

Choose what “disappear” means

An element can remain attached to the DOM while hidden, or it can be removed entirely. Choose the assertion that matches the application behavior and what the test needs to prove.

Requirement Condition to wait for What it establishes
Removed from the DOM A fresh lookup’s isPresent() resolves to false. No matching element is present at the time of the check.
Hidden or otherwise not visible An invisibility expected condition resolves successfully, if the installed Protractor version provides the helper. The target is not visible; it may be absent or still attached but hidden.

Wait for DOM removal

For removal, poll a locator rather than checking a previously resolved element reference:

browser.wait(function() {
  return element(by.css('.notice')).isPresent().then(function(present) {
    return !present;
  });
}, 5000, 'Expected the notice to be removed from the DOM');

This expresses absence specifically. A hidden element still satisfies isPresent(), so this wait will continue until the element is actually gone or the timeout is reached.

Wait for invisibility

If the application hides the element for reuse, a visibility condition is the more appropriate assertion. In Protractor versions that expose the expected-condition helper, the pattern is:

Special offer. See more information about Outbyte and uninstall instructions. Please review EULA and Privacy policy.
var EC = protractor.ExpectedConditions;
var notice = element(by.css('.notice'));

browser.wait(
  EC.invisibilityOf(notice),
  5000,
  'Expected the notice to become invisible'
);

Check the API exposed by the version pinned in your project before relying on this helper. The underlying meaning of invisibility can include an absent target as well as a present-but-hidden one; it does not prove DOM removal. Do not substitute a visibility wait for a removal requirement, or demand removal when the application intentionally keeps hidden nodes.

Re-query when the application replaces the node

Some updates change attributes on the same node; others destroy it and render a replacement. A reference resolved before the update may then point to a detached node. Reading it can fail with a stale-element error, a known failure mode when the page changes between lookup and read.

Build the ElementFinder from the locator inside the wait callback when replacement is possible, as in the examples above. Each poll then performs a fresh lookup before reading the class or checking presence. Keep the callback limited to observing state: it may run repeatedly, so clicks and other side effects inside it can happen more than once.

Re-querying reduces stale-reference problems but does not make every race impossible. If the locator can temporarily match no node during replacement, decide whether that transient absence is itself success, a condition to retry, or an application defect. If the expected behavior is specifically that the old node is replaced, test replacement explicitly using an API available in the project’s pinned Protractor/WebDriver version, then locate and assert the new node’s state.

Special offer. See more information about Outbyte and uninstall instructions. Please review EULA and Privacy policy.

Timeouts, polling, and readable failures

A wait needs a finite timeout and a predicate that eventually becomes true. Use a timeout appropriate to the operation rather than an unbounded wait, and provide a message that says which state failed. When the timeout is reached, the message should help distinguish a missing class transition from a broken locator or an action that never completed.

  • Keep the condition focused. Read the relevant attribute or presence state; avoid doing work unrelated to the asserted condition.
  • Assert the desired state. Prefer “has is-ready” to “some class value changed” when that is what the user-visible behavior requires.
  • Record the before-state at the right time. Capture it before the triggering action when comparing old and new values.
  • Use the same meaningful locator. A locator that becomes ambiguous after rendering can make a correct wait unreliable.
  • Do not swallow unexpected errors. A broken selector or other WebDriver failure should remain visible rather than being converted into a false result that obscures the cause.

Troubleshoot a wait that fails

The wait times out although the UI appears updated

Check whether the predicate matches the actual target state. A test waiting for any class difference can be replaced with a token check, or vice versa, depending on the requirement. Inspect whether the class token is spelled and cased as rendered, and confirm the locator identifies the updated element rather than another matching node.

The test reports a stale element

The DOM may have replaced the node between lookup and attribute read. Avoid retaining a resolved WebElement across the update; create the ElementFinder from the locator inside each poll. If replacement is intentional, assert the replacement behavior directly rather than treating the old reference as the new element.

The removal wait never succeeds

The application may hide the node instead of removing it, or the selector may still match another element. If the requirement is only that the user cannot see it, use a supported invisibility condition. If the requirement is DOM absence, keep the presence check and investigate why a match remains.

Special offer. See more information about Outbyte and uninstall instructions. Please review EULA and Privacy policy.

The invisibility wait succeeds too soon

An invisibility condition can consider a missing element invisible. If the test must prove that an element first appeared and then became hidden, establish the visible state before triggering the hide action, then wait for invisibility. If it must prove removal, use the DOM-presence predicate instead.

The test passes without observing a transition

A “class differs from initial value” wait can pass on a change unrelated to the intended result. Wait for the specific class token or other final state that represents successful completion. Also ensure the initial class was recorded before the action; otherwise the comparison may not describe a real before-and-after transition.

Independent reader supportYour contribution helps us test, update, and keep practical guides available for everyone.Support on Ko-Fi

Protractor status and whether to use this pattern

These are documentation-based patterns for maintaining an existing Protractor suite, not a claim that they were executed against a particular installed version. Protractor is an Angular and AngularJS end-to-end testing framework built on WebDriverJS. Its official repository was archived on July 29, 2024, and the project’s future-of-testing discussion encouraged migration toward a modern, framework-agnostic testing platform. For a new test suite, evaluate maintained alternatives; for an existing suite, verify helper availability and behavior against the version pinned by that project.

Or skip the browser setup

For a website screenshot rather than an assertion inside a Protractor test, ScreenshotNeo provides a screenshot API and MCP server. Its one-call request can return an image or PDF; see the API documentation for request options.

Special offer. See more information about Outbyte and uninstall instructions. Please review EULA and Privacy policy.
curl -G "https://api.screenshotneo.com/v1/shot" -d access_key=YOUR_API_KEY --data-urlencode url=https://stripe.com -o shot.webp

ScreenshotNeo accepts cookie or consent banners like a visitor and removes 60+ known consent platforms, newsletter popups, and chat widgets before capture; each cleanup step can be turned off. Bot checks and CAPTCHAs, blank pages, timeouts, failed loads, and cache hits are not billed, and responses identify the page verdict and billing status in headers. Its MCP server provides take_screenshot, get_page_info, and capture_pdf for Claude, Cursor, and other MCP clients. The free plan includes 1,000 screenshots a month with no card; paid plans start at $5 for 3,000.

Sign up for ScreenshotNeo’s free plan to get 1,000 screenshots a month with no card.

Frequently Asked Questions

Does browser.wait accept a promise-returning condition in Protractor?

A promise-returning Boolean condition is the pattern shown in the historical Protractor issue example. Confirm the behavior against the version your project pins.

Should I wait for a class to change or for a specific class to appear?

Use a class-difference predicate only when any change is sufficient; check for a specific class token when the test depends on a known final state.

Special offer. See more information about Outbyte and uninstall instructions. Please review EULA and Privacy policy.

Is Protractor suitable for a brand-new test suite?

Protractor’s official repository has been archived since July 29, 2024. The project discussion encouraged migration to a modern, framework-agnostic testing platform.

Product prices and availability are accurate as of the date/time indicated and are subject to change. Any price and availability information displayed on Amazon at the time of purchase will apply.