使用Velocity和Jasmine测试Meteor时需要超时
Requiring timeouts when testing Meteor with Velocity and Jasmine
对流星、速度和茉莉花都很陌生,所以不确定我是不是做错了什么,用茉莉花做了一些不适合的事情,或者这只是它的工作方式。
我发现我需要为几乎所有的测试设置超时,才能让它们通过。应该是这样吗?还是我做错了什么?
例如,我正在运行一些测试来检查验证消息:
describe("add quote validation", function() {
beforeEach(function (done) {
Router.go('addQuote');
Tracker.afterFlush(function(){
done();
});
});
beforeEach(waitForRouter);
it("should show validation when Quote is missing", function(done) {
$('#quote').val('');
$('#author').val('Some author');
Meteor.setTimeout(function(){
$('#addQuoteBtn').click();
}, 500);
Meteor.setTimeout(function(){
expect($('.parsley-custom-error-message').text()).toEqual("Quote can't be empty.");
done();
}, 500);
});
}
好吧,我们遇到了完全相同的问题,并设计了一个非常优雅的解决方案,它不需要超时,是运行测试的最快方法。基本上,我们使用两种策略中的一种,这取决于您正在等待的屏幕元素。
所有代码都进入tests/mocha/client/lib.coffee,而不是100%的Jasmine等效代码,但它应该可用于所有客户端测试代码。我把它放在了Coffeescript中,但你可以在Coffeescript.org上将它编译成Javascript,它应该也能正常工作。
如果您所做的任何操作(路由或其他类似于更改反应变量的操作)导致Template
(重新)渲染,则可以使用Template.<your_template>.rendered
挂钩来检测它何时完成渲染。因此,我们在lib.coffee中添加了以下功能:
@afterRendered = (template,f)->
cb = template.rendered
template.rendered = ->
cb?()
template.rendered = cb
f?()
return
return
它做什么?它基本上"记住"了原始的rendered
回调,在呈现template
并调用原始回调后,暂时用一个调用额外函数的回调来替换它。它需要进行这种内务管理,以避免破坏任何可能依赖于rendered
回调的代码,因为您基本上是在直接干扰Meteor代码。
在你的测试中,你可以做这样的事情:
it.only "should check stuff after routing", (done)->
try
Router.go "<somewhere>"
afterRendered Template.<expected_template>, ->
<your tests here>
done()
catch e
done(e)
我也推荐try-catch,因为我注意到异步错误并不总是会进入速度系统,只会导致超时失败。
好吧,有些东西实际上并没有重新渲染,而是用JS或某种"显示/隐藏"机制生成的。为此,您确实需要某种超时,但您可以通过使用轮询机制来降低超时的"时间成本"。
# evaluates if a JQuery element is visible or not
$.fn.visible = -> this.length > 0 and this.css('display') isnt 'none'
# This superduper JQuery helper function will trigger a function when an element becomes visible (display != none). If the element is already visible, it triggers immediately.
$.fn.onVisible = (fn,it)->
sel = this.selector
if this.visible()
console.log "Found immediately"
fn?(this)
else
counter = 0
timer = setInterval ->
counter++
el = $(sel)
if el.visible()
fn?(el)
clearInterval timer
console.log "Found on iteration #{counter}"
else
it?(el)
, 50
如果您愿意,可以删除控制台日志记录和辅助it
迭代器函数,它们并不重要。这允许你在测试中做这样的事情:
$('#modalId').onVisible (el)->
<tests here>
done()
, (el)->
console.log "Waiting for #{el.selector}"
如果需要,可以删除第二个函数,它就是上面提到的it
迭代器函数。但是,请注意,这个特定的代码使用"display:hidden"作为不可见性的标记(Bootstrap就是这样做的)。如果您的代码使用另一种机制来隐藏/显示部件,请更改它。
对我们来说就像一种魅力!
- Meteor如何接收HTTP请求
- Meteor-将选定窗体中的对象添加到集合中
- Meteor上的启动页面
- Meteor方法在客户端返回null,在客户端运行的相同方法返回正确的值
- Meteor-添加用户自定义字段的方法不起作用
- Meteor忘记了密码的实现
- 链接所有<a>Meteor
- 在Meteor项目中安装并包含npm模块后出错
- Meteor JS中代码的重复使用部分
- Meteor Router数据函数被调用两次
- 基于localStorage的Meteor激活模板
- React+Meteor:this.ops返回未定义
- 如何将PHP get查询转换为Meteor's HTTP.get()
- 使用优化器在慢速连接上加载main.js时需要js超时
- 如何将javascript变量传递到Meteor Spacebars模板中
- 部署时使用npm包时发生Meteor错误
- Meteor如何运行服务器端python脚本
- 谷歌地图根本不适用于Meteor-iOS
- 使用Velocity和Jasmine测试Meteor时需要超时
- MongoError:游标被杀死或超时-Meteor超时设置无效