Protractor End-to-End Testing: Locating Elements and Handling Async Operations
Learn how to locate elements and handle async operations in Protractor for stable Angular end-to-end tests. Covers by locator strategies, element finders, and built-in waiting mechanisms.
20 Jan 2026, 11:05 UTC

The Challenge with Protractor Element Locating
When writing end-to-end tests for Angular applications, one of the most common pain points is reliably locating elements and handling asynchronous operations. Protractor provides specific mechanisms to address these issues, but understanding how to use them correctly is crucial for stable tests.
Key Prerequisites
Before diving into element location and waiting strategies, ensure you have:
- Protractor installed via
npm install protractor --save-dev - A configured
protractor.conf.jsfile pointing to your application URL - An understanding of Angular's asynchronous nature and how it affects DOM rendering
Element Locating with the 'by' Strategy
Protractor uses the by locator strategies to find elements in the DOM. The most commonly used strategies include:
by.css(selector)- Finds elements using CSS selectorsby.binding(expression)- Finds elements by Angular binding expressionsby.repeater(selector)- Finds elements in ng-repeat directives
Creating Element Finders
The element() function returns an ElementFinder that must be used with methods like .getText(), .click(), or .sendKeys() to interact with elements. For example:
const element = element(by.css('.my-button'));
const text = await element.getText();
await element.click();
Working with Multiple Elements
Use element.all() to create an ElementArrayFinder for handling multiple elements. This provides methods like .count() and .each():
const elements = element.all(by.css('.list-item'));
const count = await elements.count();
await elements.each(async (el, index) => {
const text = await el.getText();
console.log('Item ' + index + ': ' + text);
});
Protractor's Built-in Waiting Mechanism
One of Protractor's key features is its automatic waiting mechanism. It automatically waits for elements to be present and visible before interaction, which helps prevent flaky tests caused by timing issues.
Ensuring Angular Has Finished Rendering
Use browser.waitForAngular() to ensure Angular has finished rendering before running tests. This is especially important after actions that might trigger Angular's digest cycle:
await browser.waitForAngular();
const title = await element(by.css('h1')).getText();
Practical Example: Testing a Dynamic Form
Here's a complete example demonstrating element location and waiting for a form with dynamic content:
describe('Dynamic Form Test', () => {
it('should fill and submit the form', async () => {
await browser.get('http://localhost:4200/dynamic-form');
await browser.waitForAngular();
// Wait for form to be visible
const form = element(by.css('form#dynamicForm'));
await browser.waitForAngular();
// Fill in input fields
await element(by.css('input[name="name"]')).sendKeys('John Doe');
await element(by.css('input[name="email"]')).sendKeys('[contact removed]');
// Select from dropdown
await element(by.css('select[name="country"]')).element(by.css('option[value="us"]')).click();
// Submit form
await element(by.css('button[type="submit"]')).click();
// Verify success message
await browser.waitForAngular();
const successMsg = element(by.binding('successMessage'));
expect(await successMsg.getText()).toContain('Form submitted successfully');
});
});
Expected Checks and Verification
To verify your setup is working correctly:
- Run
protractor --versionto confirm installation - Create a simple test file using
describeanditblocks withbrowser.get()to navigate to an application URL - Use
element(by.css(selector)).getText()to verify text content and check if the promise resolves correctly - Run your tests with
npm run e2eor configure aprotractor.conf.jsfile to execute tests against a live application
Important Limitations and Considerations
Be aware of the following limitations when using Protractor:
- Deprecation Notice: Protractor is now deprecated in favor of Cypress or Playwright for new projects
- Version Compatibility: Version compatibility issues exist between Protractor and newer Angular versions
- Flakiness: The framework relies on Selenium WebDriver which can cause flakiness in tests
- Async Operations: End-to-end tests may require careful handling of asynchronous operations
Recovery Options for Common Issues
If you encounter issues with Protractor tests:
- Element Not Found: Ensure your selectors are correct and the page has fully loaded. Use
browser.waitForAngular()after navigation - Timeout Errors: Increase the timeout in your
protractor.conf.jsfile - Flaky Tests: Add explicit waits using
browser.wait()with conditions likeExpectedConditions.elementToBeClickable - Migration Path: Check the Protractor GitHub repository for migration guides to Cypress or Playwright
Conclusion
Mastering Protractor's element locating and waiting mechanisms is essential for creating reliable end-to-end tests. While Protractor is being deprecated, understanding these concepts remains valuable for maintaining existing Angular test suites and for understanding the fundamentals of end-to-end testing in general.
0 replies
A thoughtful contribution can make all the difference. Be the first to share one.