Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Wait for element to change its value(text)

I'm on my third day working with Protractor and I'm constantly hitting bric walls in regards to waiting around for pages to load and elements to appear. This test case in particular has grown ugly and I would like to solve the issues without having to rely on sleeps.

I am currently "outside of the land of AngularJS"

it('it should reflect in both the field and the title when the personnel name is changed', function() {
  var inputField, personnelHeader, personnelName;
  personnelName = element(By.css(".overlay.editnameoverlay")).click();
  personnelHeader = element(By.id("personnel_name_header"));
  inputField = element(By.css("input[name='newvalue']"));
  inputField.clear();
  inputField.sendKeys("Test 123");
  element(By.css("input[name='ok_button']")).click();
  // browser.driver.sleep(2000); This test only works with this sleep added
  browser.wait(function() {
    console.log("Waiting for header to change...");
    return personnelHeader.getText().then(function(text) {
      return text === "Test 123";
    });
  }, 5000);
  return expect(personnelHeader.getText()).toBe(personnelName.getText());
});

So the test here changes the name in an input field. submits it and waits for the changes to become reflected in the header of the modal. The problem is that without the browser.driver.sleep(2000) I get an error saying

Stacktrace:
     StaleElementReferenceError: stale element reference: element is not attached to the page document

How do I go about solving this in this particular case?

like image 342
CodePrimate Avatar asked Nov 25 '14 12:11

CodePrimate


2 Answers

From the documentation for Expect Conditions:

var EC = protractor.ExpectedConditions;
// Waits for the element with id 'abc' to contain the text 'foo'.
browser.wait(EC.textToBePresentInElement($('#abc'), 'foo'), 5000);
like image 143
Lee Goddard Avatar answered Oct 06 '22 01:10

Lee Goddard


When you use Protractor to test for non-angular pages you're on your own regarding waiting for elements to be ready for interaction.

StaleElementReferenceError is probably the most useless selenium error, it happens when the element got removed from the DOM but is still cached somehow, I also suffered this problem when started with Protractor and even tried to convince it should be automatically retried Protractor-side.

The solution for me is to always explicitly wait for an element to appear on the page using a custom function waitReady() that browser.wait for elements ready, i.e: waits for the element to be ready for interaction:

    expect($('#login_field').waitReady()).toBeTruthy();

First integrate this snippet in your code: https://gist.github.com/elgalu/2939aad2b2e31418c1bb

Not only the custom waitReady() waits for the element but it also swallows any unrelated useless webdriver error like StaleElementReferenceError and will simply retry up until finding the element or it will timeout.

So waitReady() each element before interacting, i.e. before clear() or sendKeys() or click() ...

// TODO: Move to Page Objects module
var personnelNameElm = $(".overlay.editnameoverlay");
var personnelHeaderElm = $("#personnel_name_header");
var inputFieldElm = $("input[name='newvalue']");
var okBtnElm = $("input[name='ok_button']");

it('it should reflect in both the field and the title when the ' +
    'personnel name is changed', function() {

  expect(personnelNameElm.waitReady()).toBeTruthy();
  personnelNameElm.click();
  expect(inputFieldElm.waitReady()).toBeTruthy();
  inputFieldElm.clear().sendKeys("Test 123");
  expect(okBtnElm.waitReady()).toBeTruthy();
  okBtnElm.click();

  browser.wait(function() {
    console.log("Waiting for header to change...");
    // Using waitReady() before getText() avoids Stale element errors
    return personnelHeaderElm.waitReady().then(function() {
      return personnelHeaderElm.getText().then(function(text) {
        return text === "Test 123";
      });
    });
  }, 5000);

  expect(personnelHeaderElm.getText()).toEqual(personnelNameElm.getText());
});
like image 40
Leo Gallucci Avatar answered Oct 06 '22 00:10

Leo Gallucci