这是一个简单的组件:
App.FooBarComponent = Ember.Component.extend({
tagName: "button",
status: "Ready",
revertStatusPeriodMs: 2000,
click: function() {
this.set('status', 'Pending');
// A fake ajax
this.run()
.then( function() {
this.updateStatus('Finished');
}.bind(this))
.catch( function() {
this.updateStatus('Error');
}.bind(this));
},
run: function() {
return new Ember.RSVP.Promise( function(resolve) {
Ember.run.later( function() {
resolve();
}, 500);
});
},
updateStatus: function(statusText) {
this.set('status', statusText);
var periodMs = this.get('revertStatusPeriodMs') || 1000;
Ember.run.later( function() {
this.set('status', 'Ready');
}.bind(this), periodMs);
}
});
它做了一件简单的事情:单击时,它会显示一些文本。稍后用另一文本替换该文本。即使稍后,它也会将文本恢复为初始文本。
该代码运行良好。我的问题是我无法为其编写测试。
test('clicking the button should set the label', function(assert) {
expect(4);
visit('/');
assert.equal( find('button').text().trim(), 'Ready', 'Should initially be "Ready"');
andThen(function() {
click('button');
assert.equal( find('button').text().trim(), 'Pending', 'Should "Pending" right after click');
});
// This one fires too late!
andThen(function() {
assert.equal( find('button').text().trim(), 'Finished', 'Should become "Finished" after promise fulfills');
});
andThen(function() {
assert.equal( find('button').text().trim(), 'Ready', 'Should eventually return to the "Ready" state');
});
});
我有两个问题:
-
我无法测试Finished
状态。看起来andThen
等待所有的承诺和run.later
即将完成,而我想测试中间状态。我如何在两个连续的 Promise/ 之间运行断言run.later
s?
-
时间可能很长,测试可能需要很长时间才能完成。我通常不介意重构代码以获得更好的可测试性,但我拒绝根据环境调整应用程序中的时间(例如,2000 用于开发/生产,0 用于测试)。相反,我想使用计时器模拟或其他解决方案。
我尝试过Sinon但失败了:当我嘲笑计时器时,andThen
永远不会回来。两者都不是these https://stackoverflow.com/questions/21896003/how-do-i-test-ember-run-later-with-sinon解决方案帮助了我。
JSBin: http://emberjs.jsbin.com/fohava/2/edit?html,js,输出 http://emberjs.jsbin.com/fohava/2/edit?html,js,output(诗乃也包含在内)