Non-angular page opened after a click

2020-01-25 10:45发布

问题:

I'm trying to implement the following test scenario:

  • perform a click on a logo on the page
  • assert there is a new browser window opened (tab in Chrome) and check the current URL

The problem is that the page opened in a new browser window is a non-angular page while the main page I'm performing the click in is an angular page.

Here is my first attempt:

it("should show logo", function () {
    var logo = scope.page.logo;
    expect(logo.isDisplayed()).toEqual(true);

    // opens a new page on click
    logo.click().then(function () {
        browser.getAllWindowHandles().then(function (handles) {
            browser.switchTo().window(handles[1]).then(function () {
                expect(browser.getCurrentUrl()).toEqual('http://myurl.com/');
            });

            // switch back to the main window
            browser.switchTo().window(handles[0]);
        });
    });
});

which fails with:

Error: Error while waiting for Protractor to sync with the page: "angular could not be found on the window"

which is understandable.

My second attempt was to play around with ignoreSynchronization boolean flag:

browser.ignoreSynchronization = true;
logo.click().then(function () {
    browser.getAllWindowHandles().then(function (handles) {
        browser.switchTo().window(handles[1]).then(function () {
            expect(browser.getCurrentUrl()).toEqual('http://myurl.com/');
        });

        // switch back to the main window
        browser.switchTo().window(handles[0]);
    });

This actually makes this particular test pass without any errors, but it affects every test executed after this one, because browser is a global object and is shared between tests - protractor no longer syncs with angular on a page which results into all sorts of errors.

How should I implement the test?


As a workaround, I can change the restartBrowserBetweenTests setting to true and change ignoreSynchronization value without any problems - but it slows down the tests dramatically.

回答1:

You can set ignoreSynchronization to be false once your verification is done. However, note that ignoreSynchronization is synchronous while everything else (click/get/etc) is asynchronous, so you need to be careful with that. Probably the safest way is to set it to true in beforeEach and false in afterEach, and just test that single logo click in that test.



回答2:

Another solution: I have used sleep since getWindowHandles was returning only one window name(parent/angular window). Let me know if there is a better way.

this.validateProductPageInfo = function (productTitle) {
    browser.sleep(5000);
    browser.getAllWindowHandles().then(function (handles) {
        if (handles.length === 2) {
            browser.switchTo().window(handles[1]).then(function () {
                var prodTitle = by.xpath('//h1[@id="fw-pagetitle"]');
                browser.driver.findElement(prodTitle).getText().then(function (text) {
                    expect(text).toBe(productTitle);
                });
            });
            browser.switchTo().window(handles[0]);
        } else {
            console.log("Error in switching to non angular window");
        }
    });
};