Question
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?
Answer
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
.