One of the major accomplishments on my current project at work has been adding end-to-end (E2E) tests to our client’s Angular app. When we picked up the project two months ago, only one of us even had experience writing E2E tests, and the app had no E2E coverage to speak of – we now have roughly 50 such tests.

Many of our tests were brittle for a while, though. Protractor, Angular’s default E2E testing tool, often sent input to the browser too fast for it to handle. Our tests wouldn’t sign in to the app successfully, so they failed before they actually could tell us anything useful.

I found a simple solution earlier this week. Here’s the gist of the original (failing) code we were using:

beforeAll(() => {

Often, Protractor would move on despite the browser not receiving all the input, leaving us with something like “userna” in the username field or “passw” in the password field.

Here’s the solution:

export function ensureCorrectInput(inputEl: ElementFinder, value: string) {
	return inputEl.getAttribute('value').then(expectedValue => {
		if (expectedValue !== value) {
			return ensureCorrectInput(inputEl, value);
		} else {
			return Promise.resolve();

beforeAll(() => {
    ensureCorrectInput(page.getSignInEmail(), 'username');
    ensureCorrectInput(page.getSignInPassword(), 'password');

This double-checks the resulting input field value against the value you sent. If they don’t match, Protractor will retry until they do. Since Protractor waits for the completion of each command – in technical terms, the resolution of each Promise – and ensureCorrectInput() returns a Promise, this approach won’t allow the test to proceed until the input is correct. Barring test timeouts, Protractor will take as many tries as it needs – I’ve seen it make 3-4 attempts on a bad day.

Hope this helps you and your team write more stable tests, and ultimately build better software!