Reputation: 85
Learning AngularJS from a book and there was an example of simple Protractor test:
it('Should redirect to #/posts/1/sample-title1', function () {
var posts = element.all(by.repeater('post in posts'));
posts.first().then(function (postElem) {
postElem.findElement(by.tagName('a')).then(function (a) {
a.click();
expect(protractor.getCurrentUrl()).toMatch('/posts/1/sample-title1');
});
});
});
It didn't work and threw an error: Failed: undefined is not a function
Not sure what was wrong, dig into the Protractor documentation and figured out a solution that work, which is:
it('Should redirect to #/posts/1/sample-title1', function () {
var link = element.all(by.repeater('post in posts')).first().element(by.tagName('a'));
link.click();
expect(browser.getCurrentUrl()).toMatch('/posts/1/sample-title1');
});
});
I'm happy that it works, however I don't quite understand why it work, still the documentation isn't very helpful here (or I'm just too tired at the moment).
Seems that I don't understand the difference between .findElement and .element
When I change the line:
var link = element.all(by.repeater('post in posts')).first().element(by.tagName('a'));
To:
var link = element.all(by.repeater('post in posts')).first().getWebElement().findElement(by.tagName('a'));
It also works, however it doesn't work when it's:
var link = element.all(by.repeater('post in posts')).first().findElement(by.tagName('a'));
Can someone explain this ? Thanks in advance !
Upvotes: 1
Views: 4354
Reputation: 6962
There are differences to each of those functions. In your first case you got an error: Failed: undefined is not a function
because the usage of .first()
was incorrect. first()
function returns an ElementFinder
and not a promise.
.then()
. element()
, $$
, getText()
, etc.Next, the lines that you wrote -
var link1 = element.all(by.repeater('post in posts')).first().element(by.tagName('a'));
var link2 = element.all(by.repeater('post in posts')).first().getWebElement().findElement(by.tagName('a'));
var link3 = element.all(by.repeater('post in posts')).first().findElement(by.tagName('a'));
Explanation -
.findElement()
works on top of two instances, one is an element
and the other one is a browser
or driver
.
link1
works because it has an element()
(which is also an ElementFinder) function chained to another ElementFinder and its valid.link2
is valid in its syntax because findElement()
is chained to getWebElement()
. As explained above this is valid because getWebElement()
returns an element
. link3
doesn't work because the syntax chaining of function/method is improper. findElement()
is neither chained to an element
nor a browser
instance, but it is chained to an ElementFinder
and so you get an error while you use it..element()
is an ElementFinder and so works when used alone or chained with other ElementArrayFinder
or ElementFinder
. link1
is an example of that. Valid syntaxes for ElementFinder -
element(LOCATOR);
element(LOCATOR1).element(LOCATOR2);
element.all(PARENT_LOCATOR).element(LOCATOR);
Hope it helps.
Upvotes: 2
Reputation: 1993
FindElement is a webdriver.webElement function, so you must use it after a webElement which is why it doesn't work in your last example. The documentation in the protractor API may help you for webdriver.WebElement.findElement:
http://angular.github.io/protractor/#/api?view=webdriver.WebElement.prototype.findElement
Upvotes: 0