What is browser.ignoreSynchronization in protractor?
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
.
What is difference between waitForAngularEnabled and browser.ignoreSynchronization in protractor?
They are the exact same, if you look at the source code ignoreSynchronization
actually calls waitForAngularEnabled
. The only thing to note is, ignoreSynchronization
is being deprecated and eventually will no longer be available. They are switching to waitForAngularEnabled
as the main property.
As far as what they do, that has been answered here in good detail.
Protractor: what's the difference between ignoreSynchronization and async/await in Protractor
ignoreSynchronization
and async/ await
are very different from each other.
ignoreSynchronization :
This function is already deprecated and replaced by waitForAngularEnabled()
function.
Why is it needed?
Protractor is widely used to test Angular websites. So when execution starts, the protractor searches for angular components in the application under test.
So if we are testing angular application, one can initialize
browser.waitForAngularEnabled(true)
which also means
browser.ignoreSynchronization = false
But if anyone wants to test a non-angular website, one must disable searching for angular components during execution. Hence below settings are used
browser.waitForAngularEnabled(false)
which also means
browser.ignoreSynchronization = true
asynch / await
They are used to handle promised. As JavaScript is a synchronous language, and it is asynchronous in the sense of callback functions that are called during execution, and promise is used to handle these functions
Now I will explain the outputs on 2nd and 3rd programs:
await console.log('1'); // 1 will be printed
await element(by.css('#kw')).sendKeys('protractor').then(() => {
console.log('2'); // as `await` keyword is used, execution will wait till promise is resolved and then 2 is printed
});
await console.log('3'); // print 3
await console.log('4'); // print 4
await element(by.css('#su')).click().then(() => {
console.log('5'); // again execution will wait till promise is resolved and 5 is printed
})
await console.log('6'); // print 6
Hence op is 1,2,3,4,5,6
for 3rd code
console.log('1'); // print 1
element(by.css('#kw')).sendKeys('protractor').then(() => {
console.log('2'); // this block will be handled by browser for execution and executed once stack is emppty
});
console.log('3'); // print 3
console.log('4'); // print 4
element(by.css('#su')).click().then(() => {
console.log('5'); // this block will be handled by browser for execution and executed once stack is empty, after printing 2
})
console.log('6'); // print 6. Now stack is empty and after printing 6, 2 will be printed
Hence op is 1,3,4,6,2,5
If you want to learn more about asynchronous programming, do check out this video by Philip Roberts at JSConfEU
Hope this will solve your query :-)
How to not forget to turn the Protractor to Angular sync on again?
I just do afterTest hook (depends on your test runner), where i set everything back to its starting state, so if i even forgot to switch back in test, or test crashed for some reason on any point - next tests wont be affected:
My code for jasmine. Protractor config:
onPrepare() {
...
afterEach(function () {
// Setting ignoreSychronization back to true, in case it was changed in tests
browser.waitForAngularEnabled(true);
// Setting back to default frame. In case test was working in iframe
browser.switchTo().defaultContent();
// This depends on your architecture. We do clean run for each test.
browser.manage().deleteAllCookies();
browser.executeScript('window.sessionStorage.clear(); window.localStorage.clear();').then(
undefined,
function (err) {
// Errors will be thrown when browser is on default data URL.
// Session and Local storage is disabled for data URLs
// This callback is needed to not crash test, and just ignore error.
});
browser.manage().timeouts().implicitlyWait(5000); // I even rewrite implicit wait back to default value, in case i touched it in tests
// Also you might want to clear indexdb storage after tests.
})
In real code i would wrap this into function called resetBrowser
or something like this. Also you can return promise from it, and then return that promise from hook - so new test wont start until promise resolved
Protractor: multiple browser instances in a Non-Angular app: ignoreSynchronization Not working
After checking the code. Few things that I saw are:
1. If you declare a variable as global
, I think you need to include it when using them.
e.g. global.agent.ignoreSynchronization
2. isElementPresent
seems to be used for angular pages.
In your case, I replaced it with isPresent
Please see sample code below:
describe('First interaction customer-agent', () => {
var agent = browser;
var customer = browser.forkNewDriverInstance();
beforeEach(function() {
agent.ignoreSynchronization = true;
customer.ignoreSynchronization = true;
agent.get('http://engager-stage.brandembassy.com/');
customer.get('https://vps-web-utils.awsbrandembassy.com/livechat-window-gherkin/');
agent.driver.manage().window().maximize();
customer.driver.manage().window().maximize();
});
it('should be seen offline when agent is offline and viceversa', () => {
// check that default status is minimized
browser.sleep(2000);
var elm = customer.element(by.css('[class="be-chat-wrap be-chat-wrap--minimize"]'));
expect(elm.isPresent()).toBe(true);
});
});
Note: I did not use global, since we can just declare the variable outside it
function.
Related Topics
How to Smoothly Scroll to an Element in Pure JavaScript
How to Filter JSON Data in JavaScript or Jquery
How to Sort Numbers Correctly with Array.Sort()
How to Reset <Input Type = "File">
Is There a Difference Between (Function() {...}()); and (Function() {...})();
Canvas Todataurl() Returns Blank Image
How to Display Binary Data as Image in React
How to Search JSON Tree with Jquery
How to Pass Data to Url from Jqgrid Row If Hyperlink Is Clicked
How to Access 'Window' (Target Page) Objects When @Grant Values Are Set
Utf-8 Word Boundary Regex in JavaScript
Es6 Promise.All() Error Handle - Is .Settle() Needed
Nodemailer with Gmail and Nodejs