2016-06-09 65 views
1

有麻烦,以了解究竟是如何量角器为了执行工程..量角器和执行

如果我有PageObject:InvitePage

和执行顺序的定义是这样的:

InvitePage.EnterUsername() 
InvitePage.EnterPassword() 
InvitePage.EnterEmail() 
InvitePage.Invite(); 
InviteHelper.waitForEmail() 
browser.go(invitationUrl) 
... 
expect(somecondition) 

所有页面方法都返回量角器承诺(例如,用于输入密码的browser.sendKeys) waitForEmail还返回我已创建的使用承诺:

protractor.promise.defer() 

问题是,waitForEmail得到执行第一和之后方法不等待waitForEmail完成,我预计用量角器方法创建的承诺真的......反正我找到解决它,它看起来像这样:

lastMethodBeforeWaitForEmail.then(function(){ 
    browser.driver.wait(InvitationHelper.waitForEmail(userEmail)) 
     .then(function(recievedUrl){ 
     ... 
     //methods that I want after 
     expect(someCondition) 
    }); 
    }); 

很丑很难道你不觉得呢?

有没有办法更好地做到这一点,任何建议? 围绕量角器的异步性质,我没有得到哪个部分?我错过了什么吗?

getInvitationEmail

var getInvitationEmail = function (emailAddress){ 
var deferred = protractor.promise.defer(); 
mailbox.getEmailsByRecipient(emailAddress, function(err, emails) { 
    if (err) { 
    console.log('>Fetch email - call rejected'); 
    deferred.reject(err); 
    }else{ 
    console.log('>Email service fetched.') 
    deferred.fulfill(emails); 
    } 
}); 

return deferred.promise; 

};

然后waitForEmail

this.waitForEmail = function(email){ 
var deferred = protractor.promise.defer(); 
var timeout; 
var interval = 3000; 
var timePassed = 0; 

var recursive = function() { 
    var message = '>Checking for invitational email'; 
    if(timePassed>0) { 
    message = message + ":" + timePassed/1000 + "s"; 
    } 
    console.log(message); 
    timePassed += interval; 

    getInvitationEmail(email).then(function(data){ 
    if(data.length>0){ 
     var loginUrl = data[0].html.links[0].href; 
     if(interval) clearTimeout(timeout); 
     console.log(">Email retrieved.Fetching stopped.") 
     deferred.fulfill(loginUrl); 
    }else{ 
     console.log(">Still no email."); 
    } 
    }); 

    timeout = setTimeout(recursive,interval); 
}; 

recursive(); 

return deferred.promise; 

};

回答

3

在量角器/ WebDriverJS中,有一种称为Control Flow的特殊机制,它基本上是一个承诺队列。如果你有一个“自定义”的诺言,为了它是在排队,你需要put it there

flow = protractor.promise.controlFlow(); 
flow.await(InviteHelper.waitForEmail()); 

或者:

browser.controlFlow().wait(InviteHelper.waitForEmail()); 
+0

hm,不起作用,waitForEmail在之前的方法之前执行... – Marko

+1

@Marko好的,你能不能展示函数内部是什么? – alecxe

+0

我编辑了这个问题,添加了waitForEmail方法 – Marko

0

一个问题和一个备注。

  • 如果你想控制执行流程,你不应该在ControlFlow中放置其他方法吗?
  • 当需要时,JavaScript引擎在命令结尾处添加;,但最好自己放置它们。
+0

1)他们已经在流程中,他们每个返回protractor.promise,例如browser.sendKeys或元素(by.model(...)) 2)我已禁用原子插件,当我跳过时,警告我; :d – Marko

0

waitForEmail您已经定义了一个承诺,但是您需要将其插入到controlFlow中。正如您所知,所有正常的网络驱动器操作click(), getText(), etc已经知道如何以正确的顺序执行,因此您不必每次都将您的所有承诺链接到.then

... the bottom of your function should look like this 
recursive(); 
return browser.controlFlow().execute(function() { 
    return deferred.promise; 
}); 

你丑陋的解决方案lastMethodBeforeWaitForEmail.then(function() ...工作,因为这是确保waitForEmail承诺是按照正确的顺序执行的一种方法,但上面的代码是你正在寻找的可爱。