Protractor
async/await
UnhandledPromiseRejectionWarning
JavaScript
promise rejection

Protractor async/await UnhandledPromiseRejectionWarning Unhandled promise rejection

Interview Questions practice on Codemia

Over 8,000 real interview questions from top companies, searchable by company and role.

Browse interview questions

Introduction

UnhandledPromiseRejectionWarning in Protractor usually means one async step failed and nothing awaited or caught that failure properly. The visible warning is often only the symptom. The real issue is usually a missing await, mixing old promise chains with async functions, or letting rejected browser actions escape the test flow without a try or explicit return.

What the Warning Means

In JavaScript, an unhandled rejection is a promise that fails without a corresponding catch or try/catch around the awaited call. In test code, this often leads to confusing behavior because the test may continue briefly before the runner reports failure.

Example of a risky pattern:

javascript
1it('logs in', async () => {
2  element(by.id('submit')).click(); // missing await
3  await expect(browser.getCurrentUrl()).toContain('/home');
4});

If click() fails, the rejection may not be connected to the test's awaited flow.

Always Await Browser and Element Actions

In async/await-style Protractor tests, every async operation should be awaited unless you have a very specific reason not to.

javascript
1it('logs in', async () => {
2  await element(by.id('username')).sendKeys('demo');
3  await element(by.id('password')).sendKeys('secret');
4  await element(by.id('submit')).click();
5  await expect(browser.getCurrentUrl()).toContain('/home');
6});

This keeps failures attached to the current spec instead of escaping as detached rejections.

Do Not Mix Old Promise Chains and async Style Carelessly

Legacy Protractor code often mixes then chains with async tests. That is where many warnings start.

Problematic mix:

javascript
1it('opens profile', async () => {
2  element(by.css('.profile')).click().then(() => {
3    return browser.sleep(100);
4  });
5});

The test function is async, but the inner chain is neither awaited nor returned. Rewrite it consistently:

javascript
1it('opens profile', async () => {
2  await element(by.css('.profile')).click();
3  await browser.sleep(100);
4});

Consistency matters more than style preference here.

Catch Expected Failures Explicitly

If a rejection is part of what you are testing, catch it on purpose.

javascript
1it('shows an error for bad credentials', async () => {
2  try {
3    await login('bad-user', 'bad-pass');
4  } catch (err) {
5    expect(String(err)).toContain('Unauthorized');
6  }
7});

If you expect failure but do not handle it explicitly, Protractor sees an unhandled rejection instead of a meaningful test assertion.

Return or Await Custom Async Helpers

Custom helper functions should themselves return promises or be marked async.

javascript
1async function login(username, password) {
2  await element(by.id('username')).sendKeys(username);
3  await element(by.id('password')).sendKeys(password);
4  await element(by.id('submit')).click();
5}

Then the test must await the helper:

javascript
await login('demo', 'secret');

If the helper forgets to return or await internal steps, errors surface later as loose rejections.

Protractor Is Legacy Software

Because Protractor is a legacy framework, many codebases contain transitional async styles from older control-flow behavior. When working in such a codebase, the safest rule is to make every spec and helper fully explicit about async boundaries. Do not rely on historical magic behavior.

Debugging Workflow

When the warning appears:

  1. find the first async action in the failing spec
  2. add missing await keywords
  3. inspect custom helpers for unreturned promises
  4. remove mixed then plus async patterns

That usually finds the root cause faster than reading the final warning stack alone.

Common Pitfalls

  • Forgetting await on element or browser actions.
  • Mixing then chains with async functions and not returning the promise.
  • Writing custom helpers that launch async work without returning or awaiting it.
  • Expecting rejected login or navigation flows without wrapping them in explicit assertions.
  • Assuming old Protractor control-flow behavior still manages async steps automatically.

Summary

  • 'UnhandledPromiseRejectionWarning means a promise failed outside the test's handled async flow.'
  • In async Protractor tests, await every browser and element action explicitly.
  • Keep helpers consistently async and return their promise chain.
  • Avoid mixing old then style with modern async style unless you handle it carefully.
  • Treat expected rejections as assertions, not as loose failing side effects.

Related reading
Free course
Beginner
7 lessons
2 hours
Tackling System Design Interview Problems

A short course that equips you with the skills to approach system design interviews methodically.

Start the free course
Track what you have practised

A free account saves your progress, solutions and study plan across every problem on Codemia.

Interview Questions practice on Codemia

Over 8,000 real interview questions from top companies, searchable by company and role.

Browse interview questions

All Rights Reserved.