What Is Browser.Ignoresynchronization in Protractor

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



Leave a reply



Submit