What is browser.ignoreSynchronization in protractor?

JavascriptAngularjsTestingProtractorEnd to-End

Javascript Problem Overview


I have seen it so many times where people suggest to use:

browser.ignoreSynchronization=true;  // or false

But I do not understand why do we need it?

Javascript Solutions


Solution 1 - Javascript

The simple answer is that it makes protractor not wait for Angular promises, such as those from $http or $timeout to resolve, which you might want to do if you're testing behaviour during $http or $timeout (e.g., a "loading" message), or testing non-Angular sites or pages, such as a separate login page.

For example, to test a button that sets a loading message during a request you can set it to true when fetching an element + checking its contents

element(by.css('button[type="submit"]')).click();
browser.ignoreSynchronization = true;
expect(element(by.css('.message')).getText().toBe('Loading...');    
browser.ignoreSynchronization = false;
expect(element(by.css('.message')).getText().toBe('Loaded'); 

A more involved answer is that setting it to true means that subsequent additions/injections to the control flow don't also add browser.waitForAngular. There are cases when an understanding of the control flow, and when/how things are added/injected into it is important. For example if you're using browser.wait to test a multi-stage process, the function passed to wait is injected into to the control flow after the rest of the functions in the test have added to the control flow.

element(by.css('button[type="submit"]')).click();
browser.ignoreSynchronization = true;
expect(element(by.css('.message')).getText().toBe('Stage 1');
browser.wait(function () {
   // This function is added to the control flow after the final
   // browser.ignoreSynchronization = false in the test
   // so we need to set it again here 
   browser.ignoreSynchronization = true;
   return element(by.cssContainingText('.message', 'Stage 2')).isPresent().then(function(isPresent) { 
     // Cleanup so later tests have the default value of false
     browser.ignoreSynchronization = false;
     return !isPresent;
   });
});
expect(element(by.css('.message')).getText().toBe('Stage 2');
browser.ignoreSynchronization = false;
expect(element(by.css('.message')).getText().toBe('Stage 3');

An alternative to using browser.ignoreSynchronization is to access the standard webdriver API directly

element(by.css('button[type="submit"]')).click();
expect(browser.driver.findElement(by.css('.message')).getText().toBe('Loading...');    
expect(element(by.css('.message')).getText().toBe('Loaded'); 

Using the driver methods directly to find the elements means that the system will try to find them without waiting for any ongoing $http requests to finish, much like setting browser.ignoreSynchronization = true.

Solution 2 - Javascript

This setting controls whether protractor should wait for angular on a page or not. It is not properly documented, but here is the documentation string from the code:

/**
   * If true, Protractor will not attempt to synchronize with the page before
   * performing actions. This can be harmful because Protractor will not wait
   * until $timeouts and $http calls have been processed, which can cause
   * tests to become flaky. This should be used only when necessary, such as
   * when a page continuously polls an API using $timeout.
   *
   * @type {boolean}
   */

In other words, if you are testing against a non-angular site - set ignoreSynchronization setting to true. As a real world example, see one of the challenges I had while opening a non-angular page from an angular page: https://stackoverflow.com/questions/28511013/non-angular-page-opened-after-a-click.

Solution 3 - Javascript

2021 answer

browser.ignoreSynchronization is nothing these days. Literally

This command has been deprecated on Jan 25, 2018 when protractor v5.3.0 was released

Instead browser.waitForAngularEnabled() should be used

But what it does and what ignoreSynchronization used to do, it enables Protractor's built-in handling for waiting of angular applications. Imagine, you click login button, and you don't need to use 'sleep for 10 seconds' command, or 'wait until loading animation is gone' etc. All of that should in theory be handled by protractor out of the box

But in reality, there are too many edge cases when you can't rely on this, and have to disable this feature, because it makes the script to hang. And this is when await browser.waitForAngularEnabled(false) comes into play. Or await browser.waitForAngularEnabled(true) for enabling it back on

Read how it can be used

Attributions

All content for this solution is sourced from the original question on Stackoverflow.

The content on this page is licensed under the Attribution-ShareAlike 4.0 International (CC BY-SA 4.0) license.

Content TypeOriginal AuthorOriginal Content on Stackoverflow
QuestionPriyanshu ShekharView Question on Stackoverflow
Solution 1 - JavascriptMichal CharemzaView Answer on Stackoverflow
Solution 2 - JavascriptalecxeView Answer on Stackoverflow
Solution 3 - JavascriptSergey PleshakovView Answer on Stackoverflow