1

I'm new to protractor, so please bear with me.

I've seen this question asked many times, but none of the proposed solutions are suitable for me. My app under test starts on a non-angular login page. I set browser.ignoreSynchronization = true, log in, set it back to false, and reload the page. Then I try to interact with elements on the resulting page. There's no problem with the first element, but trying to find the second element throws a type error with the message

"Failed: Cannot assign to read only property 'stack' of Timed out waiting for Protractor to synchronize with the page after 11 seconds. Please see https://github.com/angular/protractor/blob/master/docs/faq.md While waiting for element with locator - Locator: [valid locator]"

I can get it to work by leaving ignoreSychronization set to true and using sleeps, but doesn't that defeat the entire purpose of using protractor?! I could just use java+selenium, at which I'm already proficient.

I'm certain that the page is loading, and that there are no outstanding http, timeouts, or other calls. Just to be sure, I set the timeout to 2 minutes, with the same result.

My test looks something like this:

describe('this does not work', function() {
    beforeEach(function() {
        // log in on non-angular page
        // ignoreSynchronization because this isn't an angular page
        browser.ignoreSynchronization = true;
        var d = browser.driver;
        d.get(g.url);

        var username_field = d.findElement([valid locator]);
        username_field.sendKeys(username);

        var next_button = d.findElement([valid locator]);
        next_button.click();

        var password_field = d.findElement([valid locator]);
        password_field.sendKeys(password);

        var login_button = d.findElement([valid locator]);
        login_button.click();

        // done with non-angular page
        browser.ignoreSynchronization = false;
        browser.get(g.url);

    });
    it('does not work', function() {

        //  if you comment out this line, the next will execute successfully
        // this succeeds, so page is loaded
        expect(element([valid locator]).getText()).toBe('some string');

        // otherwise, the exception is thrown trying to get this element
        element([valid locator]).click();
        element([valid locator]).click();
    });
});

Any help/pointers/suggestions would be gratefully welcomed.

EDIT: I should have included my conf.js:

exports.config = {
  framework: 'jasmine',
  seleniumAddress: 'http://localhost:4444/wd/hub',
  specs: ['./specs/**/broken_spec.js'],
  useAllAngular2AppRoots: true
}
dstaraster
  • 191
  • 1
  • 2
  • 7
  • Quick check - does adding `browser.waitForAngular()` after the `browser.get(g.url)` make any difference? Thanks. – alecxe Jun 07 '16 at 15:23
  • @alecxe - no, browser.waitForAngular() was one of the things I tried. It makes no difference, which doesn't actually surprise me. The first element I look for is found, so I know the page is loaded. But thanks for trying! – dstaraster Jun 08 '16 at 15:53

1 Answers1

1

After thinking about it overnight (yes, I dream in protractor), I realized that proper use of promises might be the answer. I found some very helpful tips at How can I wait for a condition?, and implemented my test as:

describe('this does not work', function() {
    beforeEach(function() {
        // log in on non-angular page
        // ignoreSynchronization because this isn't an angular page
        browser.ignoreSynchronization = true;
        [login]
        // done with non-angular page
        browser.ignoreSynchronization = false;
        browser.get(g.url);
    });
    it('should work', function() {
        // log out
        var userInfoButton = [valid locator];
        browser.driver.isElementPresent(userInfoButton).then(function() {
            browser.driver.findElement(userInfoButton).then(function(button) {
                button.click();
                var logoutButton = [valid locator];
                browser.driver.isElementPresent(logoutButton).then(function() {
                    browser.driver.findElement(logoutButton).then(function(button) {
                        button.click();
                    });
                });
            });
        });
    });
});
Community
  • 1
  • 1
dstaraster
  • 191
  • 1
  • 2
  • 7
  • I think you are overcomplicating things. First of all, you can use `element` and `browser` directly inside `it` since you've already turned the sync on and on a angular page. Also, `browser.wait()` with a set of Expected Conditions should be used instead - it would make things easier. – alecxe Jun 07 '16 at 15:44
  • @alecxe - ExpectedConditions doesn't work for me, either. I wait for the button to be clickable and then try to click on it, but nothing happens. I'm really frustrated. I'd love to get to the bottom of this and get my tests working in protractor, but I accomplished more yesterday writing tests in java+selenium than in a week of protractor :-( – dstaraster Jun 08 '16 at 15:56
  • There is a learning curve of course, and there are difficult situations. Anyway, +1 for dreaming in Protractor :) – alecxe Jun 08 '16 at 16:00