[英]Resolving promises in Protractor and Cucumber using Chai as Promised
Lately a colleague and I have had some disagreements on the "right" way to implement Cucumber step definitions using Protractor and Chai as Promised. 最近,我和一位同事在使用Protractor和Chai作为Promised来实现黄瓜步骤定义的“正确”方法上存在一些分歧。 Our contention comes from a mutual lack of understanding of precisely what is going with promise resolution in the context of Cucumber.
我们的争论源于相互之间缺乏对Cucumber环境中诺言解决方案的确切了解。
We're testing against an AngularJS application, so resolving promises and asynchronous behavior is a necessary evil. 我们正在针对AngularJS应用进行测试,因此解决承诺和异步行为是必不可少的。 The biggest problem we've had is forcing synchronous test behavior and getting Cucumber to wait on promises between step definitions.
我们遇到的最大问题是强制同步测试行为,并使Cucumber等待步骤定义之间的承诺。 In some cases, we've observed situations such that Cucumber seems to plow straight through step definitions before Webdriver even executes them.
在某些情况下,我们已经观察到Cucumber似乎在Webdriver甚至没有执行它们之前就直接浏览步骤定义。 Our solutions to this problem vary...
我们针对这个问题的解决方案各不相同...
Consider the hypothetical scenario: 考虑假设的情况:
Scenario: When a user logs in, they should see search form
Given a user exists in the system
When the user logs into the application
Then the search form should be displayed
Most of the confusion originates in the Then step. 大多数混乱源自“然后”步骤。 In this example the definition should assert that all fields for the search form exist on the page, meaning multiple isPresent() checks.
在此示例中,定义应断言搜索表单的所有字段都在页面上,这意味着要进行多次isPresent()检查。
From the documentation and examples I was able to find, I felt the assertion should look something like this: 从我可以找到的文档和示例中,我认为断言应该看起来像这样:
this.Then(/the search form should be displayed/, function(next) {
expect(element(by.model('searchTerms')).isPresent()).to.eventually.be.true;
expect(element(by.model('optionsBox')).isPresent()).to.eventually.be.true;
expect(element(by.button('Run Search')).isPresent()).to.eventually.be.true.and.notify(next);
});
However, my colleague contends that in order to satisfy promise resolution, you need to chain your expects with then() like this: 但是,我的同事争辩说,为了满足承诺解决方案,您需要使用then()链接期望,如下所示:
this.Then(/the search form should be displayed/, function(next) {
element(by.model('searchTerms')).isPresent().then(function(result) {
expect(result).to.be.true;
}).then(function() {
element(by.model('optionsBox')).isPresent().then(function(result) {
expect(result).to.be.true;
}).then(function() {
element(by.button('Run Search')).isPresent().then(function(result) {
expect(result).to.be.true;
next;
});
});
});
});
The latter feels really wrong to me, but I don't really know if the former is correct either. 后者对我来说真的很不对劲,但是我真的不知道前者是否正确。 The way I understand eventually() is that it works similarly to then(), in that it waits for the promise to resolve before moving on.
我对finally()的理解是,它的工作方式与then()类似,因为它在继续执行之前要等待诺言解决。 I would expect the former example to wait on each expect() call in order, and then call next() through notify() in the final expect() to signal to cucumber to move on to the next step.
我希望前面的示例按顺序等待每个Expect()调用,然后在最终的Expect()中通过notify()调用next(),以发出信号通知黄瓜继续进行下一步。
To add even more confusion, I've observed other colleagues write their expects like this: 更令人困惑的是,我观察到其他同事这样写他们的期望:
expect(some_element).to.eventually.be.true.then(function() {
expect(some_other_element).to.eventually.be.true.then(function() {
expect(third_element).to.eventually.be.true.then(function() {
next();
});
});
});
So the questions I think I'm alluding to are: 所以我想提到的问题是:
Many thanks in advance. 提前谢谢了。
element(by.button('Run Search')).isPresent()
will not resolve until both element(by.model('optionsBox')).isPresent()
and element(by.model('searchTerms')).isPresent()
are done. element(by.button('Run Search')).isPresent()
将不能解决直到两个element(by.model('optionsBox')).isPresent()
和element(by.model('searchTerms')).isPresent()
完成。 eventually
resolves promises. eventually
兑现诺言。 An explanation is here: https://stackoverflow.com/a/30790425/1432449 next()
inside of then()
next()
放在then()
内没有什么不同 What works for me is this - The function below searches for something that will always equal true - in the case the existence of a html tag. 对我有用的是-如果存在html标记,则下面的函数将搜索始终等于true的内容。 I call this function at the end of each test, passing in the callback
我在每次测试结束时都调用此函数,并传入回调
function callbackWhenDone(callback) {
browser.wait(EC.presenceOf(element(by.css('html'))))
.then(function () {callback();})
}
This is the usage in a simple test: 这是一个简单测试中的用法:
this.Given(/^I go on "([^"]*)"$/, function (arg1, callback) {
browser.get('/' + arg1);
callbackWhenDone(callback);
});
A bit of a hack I know but it gets the job done and looks pretty clean when used everywhere 我知道一点技巧,但是可以完成工作,并且在任何地方使用时看起来都非常干净
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.