Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

What is browser.ignoreSynchronization in protractor?

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?

like image 450
Priyanshu Shekhar Avatar asked Mar 02 '15 11:03

Priyanshu Shekhar


2 Answers

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.

like image 83
Michal Charemza Avatar answered Sep 19 '22 17:09

Michal Charemza


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: Non-angular page opened after a click.

like image 32
alecxe Avatar answered Sep 18 '22 17:09

alecxe