可以将文章内容翻译成中文,广告屏蔽插件可能会导致该功能失效(如失效,请关闭广告屏蔽插件后再试):
问题:
I'm new on protractor, and I'm trying to implement an e2e test.
I don't know if this is the right way to do this, but...
The page that I want to test is not a full angular page based, so... I'm having some trouble.
On my first spec I have:
describe('should open contact page', function() {
var ptor = protractor.getInstance();
beforeEach(function(){
var Login = require('./util/Login');
new Login(ptor);
});
I have created this Login class, but after login I want to open the contact page, but protractor immediately try to find element before the page is fully loaded.
I've tried to use:
browser.driver.wait(function() {
expect(browser.findElement(by.xpath("//a[@href='#/contacts']")).isDisplayed());
ptor.findElement(by.xpath("//a[@href='#/contacts']")).click();
});
But it doesn't work... it always try to find the element before the page loads.
I tried this one too:
browser.driver.wait(function() {
expect(ptor.isElementPresent(by.xpath("//a[@href='#/contacts']")));
ptor.findElement(by.xpath("//a[@href='#/contacts']")).click();
});
I'm able to do that using browser.sleep();
but I don't think that is a good option. Any idea? On my login class I have:
ptor.ignoreSynchronization = true;
How can I wait for this @href='#/contacts
before protractor tries to click on it?
回答1:
I had the same problem you were having for the longest time while using protractor. In my e2e test I start in a non angular app, then get into an angular portion, then get back out to a non angular portion. Made things tricky. The key is to understand promises and how they work. Here's some examples of my real world code in a functioning e2e test. Hoping this gives you an idea of how to structure your tests. Probably some bad practice in this code, please feel free to improve upon this, but I know that it works, maybe not the best way.
To get to angular I use
var ptor;
var events = require('events');
var eventEmitter = new events.EventEmitter();
var secondClick = require('./second-click');
beforeEach(function () {
browser.driver.get('http://localhost:8080/');
},10000);
it("should start the test", function () {
describe("starting", function () {
it("should find the link and start the test", function(){
var elementToFind = by.linkText('Start'); //what element we are looking for
browser.driver.isElementPresent(elementToFind).then(function(isPresent){
expect(isPresent).toBe(true); //the test, kind of redundant but it helps pass or fail
browser.driver.findElement(elementToFind).then(function(start){
start.click().then(function(){ //once we've found the element and its on the page click it!! :)
ptor = protractor.getInstance(); //pass down protractor and the events to other files so we can emit events
secondClick(eventEmitter, ptor); //this is your callback to keep going on to other actions or test in another file
});
});
});
});
});
},60000);
While in angular this code works
describe("type in a message ", function(){
it("should find and type in a random message", function(){
var elementToFind = by.css('form textarea.limited');
browser.driver.isElementPresent(elementToFind).then(function(isPresent){
element(elementToFind).sendKeys(randomSentence).then(function(){
console.log("typed in random message");
continueOn();
});
});
});
},15000);
After exiting angular
browser.driver.wait(function(){
console.log("polling for a firstName to appear");
return browser.driver.isElementPresent(by.name('firstName')).then(function(el){
return el === true;
});
}).
then(function(){
somefunctionToExecute()
});
Hope that gives some guidance and helps you out!
回答2:
Protractor 1.7.0
has also introduced a new feature: Expected Conditions.
There are several predefined conditions to explicitly wait for. In case you want to wait for an element to become present:
var EC = protractor.ExpectedConditions;
var e = element(by.id('xyz'));
browser.wait(EC.presenceOf(e), 10000);
expect(e.isPresent()).toBeTruthy();
See also:
- Expected conditions in protractor
回答3:
I finally find out...
var waitLoading = by.css('#loading.loader-state-hidden');
browser.wait(function() {
return ptor.isElementPresent(waitLoading);
}, 8000);
expect(ptor.isElementPresent(waitLoading)).toBeTruthy();
var openContact = by.xpath("//a[@href='#/contacts']");
element(openContact).click();
With this protractor could wait for that element until it loading page disappears.
Thanks for those who tried to help XD.
回答4:
browser.driver.wait(function() {
return browser.driver.isElementPresent(by.xpath("//a[@href='#/contacts']"));
});
This works for me too (without the timeout param)..
for more information, see http://angular.github.io/protractor/#/api?view=webdriver.WebDriver.prototype.wait
回答5:
Thanks to answers above, this was my simplified and updated usage
function waitFor (selector) {
return browser.wait(function () {
return browser.isElementPresent(by.css(selector));
}, 50000);
}
回答6:
Have you tried putting the ng-app
in the <html>
tag (assuming this part of code is under your control)? This solved a lot of initialization timing problems for me.
回答7:
Best way to use wait conditions in protractor that helps to show proper error message to particular element if test case failed
const EC = ExpectedConditions;
const ele = element(by.xpath(your xpath));
return browser.wait(EC.visibilityOf(ele),9000,'element not found').then(() => {
ele.click();
});
回答8:
I'm surprised that nobody has added this solution. Basically, if you are using modal dialogues you often get an element visible and available to click but not being clickable due to the modal dialogue being in front of it. This happens because protractor moves faster than angular and is ready to click the next element while angular is still closing the modal.
I suggest using
public async clickElementBug(elementLocator: Locator) {
const elem = await element(elementLocator);
await browser.wait(
async function() {
try {
await elem.click();
return true;
} catch (error) {
return false;
}
},
this.TIMEOUT_MILLIS,
'Clicking of element failed: ' + elem
);
}