通常,我们需要在渲染完成后安排更新以响应属性更改。这是一个例子:
page_changed: function() {
Ember.run.scheduleOnce('afterRender', this, this.scroll);
}.observes('current_page')
这不适用于测试,因为在调用scheduleOnce
时没有runloop。我们可以简单地将scheduleOnce
包裹在Ember.run
page_changed: function() {
Ember.run(function() {
Ember.run.scheduleOnce('afterRender', that, that.scroll);
});
).observes('current_page')
..但我被告知这不是正确的方法。我以为我会伸手去拿一些其他的想法。
此处参考是我在ember.js#10536
中打开的问题答案 0 :(得分:1)
根据@ StefanPenner的评论看起来这样做是可行的。而不是修改应用程序代码本身只需使用Ember.run
test('it renders', function() {
expect(2);
var component = this.subject();
var that = this;
equal(component._state, 'preRender');
// Wrapping render in Ember.run
Ember.run(function() {
that.render();
});
equal(component._state, 'inDOM');
});
答案 1 :(得分:1)
测试中应用程序的入口点需要Ember.run
。例如
test('foo', function() {
user.set('foo', 1); // may have side-affects
});
test('foo', function() {
Ember.run(function() {
user.set('foo', 1);
});
});
为什么需要这个? Ember.run
包装了由click / user-actions / ajax等触发的所有调用栈的根。为什么?运行循环允许ember批处理
在编写单元测试时,我们正在“伪造”用户或网络操作,将您想要“批处理”的更改组包含在一起并不明显。
我们可以将Ember.run
视为创建批处理或更改事务的方法。最终我们使用它来批量DOM读/写以理想的方式与DOM交互。
虽然在你掌握它之前可能会感到沮丧,但它是创建简洁和确定性测试的好方法。例如:
test('a series of grouped things', function() {
Ember.run(function() {
component.set('firstName', 'Stef');
component.set('lastName', 'Penner');
// DOM isn't updated yet
});
// DOM is updated;
// assert the DOM is updated
Ember.run(function() {
component.set('firstName', 'Kris');
component.set('lastName', 'Selden');
// DOM isn't updated yet, (its still Stef Penner)
});
// DOM is once again updated, its now Kris Selden.
});
为什么这很酷? Ember为我们提供了细粒度的控制,这使我们不仅可以非常轻松地单独测试应用程序的各个方面,还可以测试基于用户或基于ajax推送的操作的序列,而无需合并这些方面。
随着时间的推移,我们希望改善测试助手和清晰度。
答案 2 :(得分:0)
..但我被告知这不是正确的方法。
原因是在执行回调时需要Ember.run
调用 ,而不是在调度时。像这样:
Ember.run.scheduleOnce('afterRender', function() {
Ember.run(function() {
that.scroll();
});
});
在您的代码中,在调度回调时调用Ember.run
。这可能是不必要的,因为您可能已经在运行循环中。我的版本确保在调用回调时,即使运行循环很久以前完成,也会启动另一个运行循环并在运行循环中调用that.scroll()
。这有道理吗?