Protractor: Parsing getText() return in JavaScript

Created on 24 May 2014  路  7Comments  路  Source: angular/protractor

Dear Protractor Community,

Thank you for the excellent software. I want to parse http://baconipsum.com/ then take the returned generated meaty text and slice it thinner in protractor before inserting it into my app (for savory filler content). The test below works well, but if I try to convert the return of getText() as a string it comes back empty or as a string that just says 'object'. For example, if I add:

This works:

'use strict';
describe('Visiting the butcher', function() {
  it('should get meat', function() {

    var ptor = protractor.getInstance();
    ptor.ignoreSynchronization = true;
    var driver = ptor.driver;

    driver.get("http://baconipsum.com/api/?type=all-meat&sentences=1&start-with-lorem=1");

    var meat = ""
    meat = driver.getPageSource();

    expect(meat).toContain("Bacon");
  });
});

But not if I change:

    var meat = ""
    driver.getPageSource().then(function(ss){
        meat = ss;
    });

because meat becomes empty and this fails: expect(meat).toContain("Bacon");
with error: Expected '' to contain 'Bacon'.

I am even running it in interactive console mode with selenium and can parse the return as text using a then function to process the response after the promise. Why does this work in interactive selenium driver land and not my protractor js test?:

var meat = "";
driver.findElement(By.tagName("body")).getText().then(function(stuff){meat = stuff;});
> meat.indexOf('Bacon')
89
question

Most helpful comment

Closing, since this bacon is crispy and done.

All 7 comments

expect tries to be smart for you and unwrap promises, but you're tricking it. So, in the first case, when you do:

meat = driver.getPageSource();
expect(meat).toContain("Bacon");

expect sees that meat is a promise, so it waits until meat is resolved before testing on its value.

However, in the second case, expect sees:

var meat = "";
driver.blah blah blah some other stuff whatevs
expect(meat).toContain("Bacon");

In this case, meat isn't a promise, it's just an empty string! expect doesn't know that it will be changed later, so it goes ahead and runs the expectation right away - thus you get the error Expected '' to contain 'Bacon'.

That makes total sense, thanks. So how would one get at the returned meat text and for example split it up on space and then send the first couple words via keysends: meat.split(" ") ?

You could do that all within the promise callback, like so:

var meat = driver.getPageSource().then(function(ss) {
  return ss.split(" ");
});
// Now meat is a promise which will resolve to an array of strings
meat.then(function(slices) {
  // You could do expectations in here
  expect(slices[0]).toEqual('salami');
  expect(slices[1]).toEqual('black forest');
});

You are a champion, Julie that totally helps me. I can not only expect stuff in the then block but I can even go to my app page and deliver the slices. I tried setting the value inside the then and accessing it later after I arrived at my app page but this didn't work. Then I realized I should put all remaining steps like the visit to my app inside the then and that is working nicely. Meat is being delivered into the app no problem. Thanks a lot!

it ('should load the add fact page and add 1001 facts', function(){

    for (var j=0;j<1001;j++) {
      var ptor = protractor.getInstance();
      ptor.ignoreSynchronization = false;
      var driver = ptor.driver;

      driver.get("http://baconipsum.com/api/?type=all-meat&paras=1");


      var content = "";
      var meat = driver.getPageSource().then(function(ss) {
        return ss.split("[\"")[1].split("\"]")[0]
      });

      // Now meat is a promise which will resolve to an array of strings
      meat.then(function(slices) {
        content = slices
        browser.get("#/fact/537e6b26e4b086269c0cb045");

        element(by.css('.redactor_box .redactor_form-control')).sendKeys(content);
        element(by.css('.btn-add-fact')).click()
      });      
    }
  });

Closing, since this bacon is crispy and done.

Woops, forgot to close I think, so thanks, and yes the bacon is perfect.

Hello! I have a problem using cucumber + Protractor: I don't know how to manage promises when I have an array. I need to work with all the elements of the array but when the Promise is resolved, the function ends and the others values can not be evaluated.

verifiesIfHoursIsPresent = function(){
var d = Q.defer();
var recordingsList = element.all(by.binding('itemData.title'))
.then(function(rows) {
for (var i = 0; i < rows.length; ++i) {
var recordingsListName = element.all(by.binding("itemData.start | date : 'shortTime' | uppercase")).get(i)
.then(function(recordingsListName) {
recordingsListName.getText().then(function(date){
if(date == null){
d.reject();
}
else {
d.resolve();
} }); }); }});
return d.promise;
}

Was this page helpful?
0 / 5 - 0 ratings

Related issues

juliemr picture juliemr  路  3Comments

mvolkmann picture mvolkmann  路  3Comments

jmcollin78 picture jmcollin78  路  3Comments

vishalshivnath picture vishalshivnath  路  3Comments

andyman3693 picture andyman3693  路  3Comments