Question:
How do I click on every link in a ul > li a
from one test?
Problem: this test is passing; however, it isn't clicking on the links. I know this because It isn't redirecting or waiting 2000ms.
Test:
it("should have proper page linking to all footer link", function() {
browser.driver.sleep(2000);
browser.ignoreSynchronization = true;
//creates an array of strings of all the menu items
var titles = element.all(by.css('.leftMenu.first .submenu li a'))
.map(function(elm) {
return elm.getText().then(function(text){
return text;
});
});
//iterates through the links via titles array
for (var i = 0; i < titles.length; i++) {
// creates a link via selection of cssContainText of the titles array
var link = element(by.cssContainingText('.submenu li a', titles[i]));
//click event
link.click().then(function() {
browser.driver.sleep(2000);
//currently arbitrary expectation but will pass
expect(browser.driver.getTitle()).toBe('welcome to: ' + title[i]);
});
}
});
UPDATE: Found the answer: ANSWER
the above answers and approaches all seem to take a 'synchronous' approach, so I'd like to offer the solution I found for the same issue which uses the standard asynchronous protractor approach.
In this example, the footer links are text links such as 'ABOUT', CONTACT', etc. - and these map to URLs such as '/about' and '/contact', etc.
Edit: ptor is defined earlier from protractor.getInstance();
it('should have a working set of footer links to internal pages', function() {
// element.all( -your selectors- )
// .then() is passed an ARRAY of element finders
element.all(by.css('.footer .nav .links')).then(function(elems) {
// for each element .getText() returns a promise
var txts = elems.map(function(elem) {
return elem.getText().then(function(txt) {
if(txt != ''){
return txt;
}
});
});
// txts is now an ARRAY of promises
// When they are ALL fulfilled the loop below is run
protractor.promise.all(txts).then(function(links) {
for (var i=0; i<links.length; i++) {
// reset browser back to page of interest
// the home page in this case
browser.get('/');
// get a fresh instance of the element and click it
// attempts to click pre-created element list
// will result in 'stale' elements references as pages
// are being navigated
element.all(by.css('.footer .nav .links')).get(i).click();
// expectation of navigation
expect(ptor.getCurrentUrl()).toContain(links[i].toLowerCase());
}
});
});
});
DUPLICATE: ANSWER HERE
You need to wrap the it
block in an IIFE to force synchrony
for(var i=0; i < testParams.length; i++) {
(function(testSpec) {
it('write your test here', function() {
//test code here
}
})(testParams[i]);
};
Your main problem is:
return elm.getText;
getText is a method that returns a promise. So what you'll need is more like
return elm.getText().then(function(text){
return text;
});
When you call a method like getText or getInnerHtml, it only returns a promise. Provided you aren't using expect, If you want the promise resolved in order to get the value, you need to chain then to return the value.