I'm having a problem where getText() is working on labels, but not working on input elements. I've raised a question on stackoverflow: http://stackoverflow.com/questions/20310442/how-to-gettext-on-an-input-in-protractor on the assumption that this is probably a usage error on my part, but I'm not seeing anything that I'm doing that's wrong or that's obvious. It's possible that getText is broken, so I'm raising here.
My use case is that I can sendKeys to my input element, I can expect and retrieve attributes from that input element, but I cannot getText that input element:
element(by.model('risk.name')).sendKeys('A value');
expect(element(by.model('risk.name')).getAttribute('autofocus')).toEqual('true');
expect(element(by.model('risk.name')).getText()).toEqual('A value');
The first two work, the third does not match the expect, returning:
Expected '' to equal 'A value'.
The documentation provides 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');
});
Which might suggest that getText() isn't supposed to work on a by.model, and that instead I should use by.binding. This doesn't make intuitive sense to me, but more importantly, by.binding doesn't like a fully qualified model name. So:
expect(element(by.binding('risk.name)).getText()).toEqual('A value');
Returns an error:
Error: No element found using locator: by.binding("risk.name")
Without the full qualification it works, but unfortunately for me "name" matches more than one item on my page, and the way I'm compositing pages means that sometimes there are more elements than others - so I cannot easily rely on this.
expect(element(by.binding('name')).getText()).toEqual('A value');
I could change my attribute name, which I think would work, but this is inconvenient in terms of my naming standards, and means that my testing logic would rely on every attribute being globally unique (i.e. if I put two views on the same page, I have to guarantee there are no name collisions in the attributes).
Is needing to use by.binding instead of by.model a deliberate design decision? Is the fact that by.binding doesn't accept a fully qualified name a deliberate design decision?
Check out this question in the FAQ: https://github.com/angular/protractor/blob/master/docs/faq.md#the-result-of-gettext-from-an-input-element-is-always-empty
Oh bother, I really thought I had looked everywhere. Sorry about that.
Might I suggest updating the content in the getting_started.md as follows:
describe('angularjs homepage', function() {
it('should greet the named user', function() {
// Load the AngularJS homepage.
browser.get('http://www.angularjs.org');
// Find the element with ng-model matching 'yourName', and then
// type 'Julie' into it.
element(by.model('yourName')).sendKeys('Julie');
+ // Verify that the input field has 'Julie' in it
+ expect(element(by.model('yourName')).getAttribute('value')).toEqual('Julie');
// Find the element with binding matching 'yourName' - this will
// find the <h1>Hello {{yourName}}!</h1> element.
var greeting = element(by.binding('yourName'));
// Assert that the text element has the expected value.
// Protractor patches 'expect' to understand promises.
expect(greeting.getText()).toEqual('Hello Julie!');
});
});
And in control-flow.md:
it('should find an element by text input model', function() {
browser.get('app/index.html#/form');
- var username = element(by.input('username'));
+ var username = element(by.model('username'));
username.clear();
username.sendKeys('Jane Doe');
- var name = element(by.binding('username'));
+ var name = element(by.model('username'));
- expect(name.getText()).toEqual('Jane Doe');
+ expect(name.getAttribute('value')).toEqual('Jane Doe');
// Point A
});
These were really the bits that led me astray, but now that I'm reading it again it should have been obvious on the first that it was "Hello Julie" being pulled out, not just Julie, therefore it was kinda obvious that it was a different field. Thanks for your help.
No problem! And sorry if my reply was curt, I've answered this question too many times :) - which obviously means it does need to be easier to find the answer. Just a quick question - was the FAQ hard to find, or was the question inside the FAQ unclear?
I think it makes sense to clarify on the readme - I'll add something.
To be honest, I had found the FAQ before, and when you pointed it out to me, I even remembered reading it, which was a bit embarrassing. And I didn't think your answer was curt - just efficient. :-)
I read the FAQ when I first started and probably didn't absorb all of it. It didn't immediately come to mind as the place to look for this information when I had this problem, I trawled through the API documentation (that's where I've spent most of my time as I build out the test suite), and the associated code comments. When I couldn't get it to work I then went to the sample code and the readme, but it didn't cross my mind to look in the FAQ. And once I saw the examples in that doco I figured I must be doing it right, because my code sort of looked like the examples, so I didn't look any further.
In terms of where I would have found this information most accessible - if the by.model locator comments had noted that the by.model on an input has a gremlin with getText(), I would have found it there, and if the getText() documentation / API doco had noted that it doesn't work on inputs, I would have found it there. But I suspect this is also one of those things that everybody is different on, so you'll fix the bits I ask for and the next person will turn up and make the same mistake.
Hopefully the question on stackoverflow will help some people, that's where I normally go as my first source when I can't get something working.
Added some clarification with 6a2dfd7f1f8b413df2ad74449dd55a22b43a2004
return(this.webelement.getAttribute('value').then(function(text)
{
console.log(text);
}))
Most helpful comment
Check out this question in the FAQ: https://github.com/angular/protractor/blob/master/docs/faq.md#the-result-of-gettext-from-an-input-element-is-always-empty