How to getText on an input in protractor

PaulL picture PaulL · Dec 1, 2013 · Viewed 102.7k times · Source

In the documentation for protractor, I see the following example:

describe('by model', function() {
  it('should find an element by text input model', function() {
    var username = element(by.model('username'));
    username.clear();
    username.sendKeys('Jane Doe');

    var name = element(by.binding('username'));

    expect(name.getText()).toEqual('Jane Doe');
  });

What appears clear here is that you can use "by.model" to set values in an input box, but if you want to look at an input box and see what's in it, you need to use "by.binding".

I have a set of code where (in summary) I do:

element(by.model('risk.name')).sendKeys('A value');
expect(element(by.model('risk.name')).getText()).toEqual('A value');

(in my real code I save the entity then come back to it in edit mode, and I'm checking my value was actually saved. But it still boils down to the same thing, and this sample code gives the same problem).

This gives me an error:

Error: Expected '' to equal 'A value'.

In theory, following the example from the docs, I can instead do:

element(by.model('risk.name')).sendKeys('A value');
expect(element(by.binding('risk.name)).getText()).toEqual('A value');

But the by.binding doesn't appear to like the fully qualified model, I get an error:

Error: No element found using locator: by.binding("risk.name")

It does work (after a fashion) if I do:

element(by.model('risk.name')).sendKeys('A value');
expect(element(by.binding('name')).getText()).toEqual('A value');

This finds an element, but also gives a warning that I have more than one element that matches 'name'. And unfortunately the one it picks isn't the right one.

So, two questions:

  1. Should the by.model be able to return a getText(), or is there a design decision that it not do that and we need to use by.binding instead?
  2. Should I be able to use a fully qualified entity in the by.binding, or is there a design decision that by.binding doesn't like the full model name? If so, what other qualifier can I use to select between my different bindings?

EDIT:

I have also tried the solution suggested by vdrulerz, I modified the code as follows:

element(by.model('risk.name')).getText().then(function(text) {
  console.log(text);
  expect(text).toEqual('A risk name');  
});

The console.log is returning a blank value (not a promise or an object), and the expect fails giving the message:

Expected '' to equal 'A risk name'.

My understanding is that protractor already patches the expect to deal with the promise, so I feel that the underlying problem is the getText not working on a field identified via a model (I can successfully getText on labels and other widgets).

I can also run the following code, using getAttribute rather than getText():

expect(element(by.model('risk.name')).getAttribute('autofocus')).toEqual('true');
element(by.model('risk.name')).getAttribute('autofocus').then(function(text) {
  console.log(text);
  expect(text).toEqual('true');  
});

The first part passes - the expect works. The second part also works, suggesting that vdrulerz' syntax is also valid, and it logs 'true' to the console. I think there is potentially a defect with getText?

Answer

Jmr picture Jmr · Dec 4, 2013

This is answered in the Protractor FAQ: https://github.com/angular/protractor/blob/master/docs/faq.md#the-result-of-gettext-from-an-input-element-is-always-empty

The result of getText from an input element is always empty

This is a webdriver quirk. and elements always have empty getText values. Instead, try:

element.getAttribute('value')

As for question 2, yes, you should be able to use a fully qualified name for by.binding. I suspect that your template does not actually having an element that is bound to risk.name via {{}} or ng-bind.