5
votes

So I'm migrating my protractor tests using the async/await(Link).

Migration is somewhat successful so far until I keep running into this issue. So following are steps of my test followed by code as an example of what I'm dealing with :

  • Navigates to a particular page
  • changes the context (Changing school to High school)
  • Grabs High school room list
  • Change context again (Changing school to Middle School)
  • Grab Middle school room list
  • Compare both lists

Related code for steps above:

Test.ts

describe("Update room list based on changing context values", () => {
  let page: HelperClass;
  let highSchoolRoomNameList: string[] = [];
  let middleSchoolRoomNameList: string[] = [];

  beforeAll(async () => {
    page = new HelperClass();
    await page.setBrowserSize();
    await page.commonContextTestSteps();
  });

  it("Changing school dropdown value", async () => {
    await page.waitForElement(page.schoolDropDown, 5000);
    await page.schoolDropDown.click();

    await page.waitForElement(page.dropDownList, 5000);
    await page.dropDownList.get(0).click();

    await browser
      .switchTo()
      .frame(element(by.tagName("iframe")).getWebElement());

    await page.roomList.each( item => {
      item.getAttribute("innerText").then(text => {
        highSchoolRoomNameList.push(text);
      });
    });

    await page.waitForElement(page.schoolDropDown, 5000);
    await page.schoolDropDown.click();

    await page.waitForElement(page.dropDownList, 5000);
    await page.dropDownList.get(1).click();

    await browser.switchTo().defaultContent();

    await browser
      .switchTo()
      .frame(element(by.tagName("iframe")).getWebElement());

    await page.roomList.each(item => {
      item.getAttribute("innerText").then(text => {
        middleSchoolRoomNameList.push(text);
      });
    });

    await protractor.promise.controlFlow().execute(() => {
      expect(highSchoolRoomNameList).not.toEqual(middleSchoolRoomNameList);
    });
  });
});

I keep getting this error :

(node:13672) UnhandledPromiseRejectionWarning: Unhandled promise rejection (rejection id: 1): StaleElementReferenceError: stale element reference: element is not attached to the page document (Session info: chrome=65.0.3325.181) (Driver info: chromedriver=2.38.552522 (437e6fbedfa8762dec75e2c5b3ddb86763dc9dcb),platform=Windows NT 6.1.7601 SP1 x86_64) (node:13672) [DEP0018] DeprecationWarning: Unhandled promise rejections are deprecated. In the future, promise rejections that are not handled will terminate the Node.js process with a non-zero exit code. (node:13672) UnhandledPromiseRejectionWarning: Unhandled promise rejection (rejection id: 2): StaleElementReferenceError: stale element reference: element is not attached to the page document (Session info: chrome=65.0.3325.181)

after debugging I found out it fails at the following steps

await browser
      .switchTo()
      .frame(element(by.tagName("iframe")).getWebElement());

    await page.roomList.each( item => {
      item.getAttribute("innerText").then(text => {
        highSchoolRoomNameList.push(text);
      });
    });

The whole test used to work fine before I started to migrate towards async/await. This is my protractor.conf.js file :

// Protractor configuration file, see link for more information
// https://github.com/angular/protractor/blob/master/lib/config.ts

const { SpecReporter } = require("jasmine-spec-reporter");

exports.config = {

  SELENIUM_PROMISE_MANAGER: false,
  allScriptsTimeout: 11000,
  suites: {
    navigation_suite: "./nav-wrapper/e2e/nav-wrapper-navigationTests/**/*.ts"
  },
  specs: [
     "Test.ts"
  ],
  capabilities: {
    browserName: "chrome"
  },
  directConnect: true,
  baseUrl: "http://localhost:3000",

  framework: "jasmine",
  jasmineNodeOpts: {
    showColors: true,
    // Set a longer Jasmine default Timeout for debugging purposes
    defaultTimeoutInterval: 999999,
    print: function() {}
  },

  onPrepare() {
    require("ts-node").register({
      project: "./nav-wrapper/e2e/tsconfig.e2e.json"
    });
    jasmine
      .getEnv()
      .addReporter(new SpecReporter({ spec: { displayStacktrace: true } }));
  }
};

Any suggestions on how to rewrite those methods will be appreciated!

2
Try add some sleep await browser.sleep(10*1000) for debug purpose after await page.dropDownList.get(0).click(); to wait page changes load completely - yong
I have debugged it multiple times, I basically output the list to the console as well just to see whether it grabbed something or not, but still no luck. It works fine if I don't go the async/await migration route - user3166089

2 Answers

0
votes

This is not a direct answer to the question of rewriting the methods however just wanted to help you get a better error than Unhandled promise rejection (which is not all that helpful)

Where you are using .then if you put a .catch() at the end of that sequence, you can do something with the error, like log it in the console. It's something you should do anyway but also will help you figure out what is causing the error here.

Here is an example of what I mean:

asyncFuncA.then(AsyncFuncB)
      .then(AsyncFuncC)
      .then(AsyncFuncD).catch(e => {
          //Do something with the error here 
            console.error(e) 
            })

and an example of your code

await page.roomList.each((item) => {
        item
            .getAttribute('innerText')
            .then((text) => {
                highSchoolRoomNameList.push(text);
            })
            .catch((e) => {
                console.error(e);
            });
    });
0
votes

If you still have the same error. You may probably try the following snippet(slightly modified from yours): await browser .switchTo() .frame(element(by.tagName("iframe")).getWebElement());

await page.roomList.each(async item => {
  await item.getAttribute("innerText").then(text => {
    highSchoolRoomNameList.push(text);
  });
});