Jasmine, RequireJS and Rails



我开始为我正在构建的项目转移到requireJS。我目前正在使用jasminece,rails 3.2和require rails gem。

我试着实现http://ryantownsend.co.uk/post/31662285280/jasminerice-and-requirejs-rails-fix虽然收效甚微,但这些规格根本无法运行。

我开始想,也许我最好单独使用requirejs,或者茉莉花宝石?

我既不喜欢jasminerice,也不需要rails宝石,所以有人对最好的工具有什么建议,以及如何启动和运行它/好的教程有什么建议吗?

好吧,因为我没有得到任何回应,我设法找到了一种稍微有点技巧的方法来实现它。

如果您在视图文件夹jasminice/spec/index.html.erb(或haml)中创建一个文件,并从jasminice gem中复制html。将spec.js调用替换为:

%script{"data-main"=>"/assets/#{@specenv}", src:"/assets/require.js"}

然后像这样写你的规范文件需要模板:

require.config {
  paths:{
    'jquery':'/assets/jquery'
    'underscore': '/assets/underscore-min'
    'sinon':'sinon-1.6.0'
    'jasmine-sinon':'jasmine-sinon'
    'my_js':'my_js'
    'my_spec':'my_spec'
  }
}

require ['sinon', 'jasmine-sinon', 'jquery', 'underscore', 'my_js', 'my_spec'], () ->
  jasmine.getEnv().execute()

这将防止茉莉酸触发测试

jasmine.rice.autoExecute = false

使用类似的beforeFilter设置测试(取自http://kilon.org/blog/2012/08/testing-backbone-requirejs-applications-with-jasmine/)

describe "MySpec", ->
  beforeEach ->
    flag = false
    @thing = ""
    that = @
    require ['myjs'], (Myjs) ->
      flag = true
      that.thing = new Myjs()
    waitsFor ->
      flag

  it 'It should exsist', ->
    expect(@thing).toBeDefined()

希望这能帮助任何有类似问题的人,如果有人有更好的解决方案,请发帖!:)

我有同样的设置,以下是我所做的(从最初问题中提到的博客文章开始):

1.创建一个助手来加载所有规范文件

在文件lib/jasminerice/spec_helper.rb中,输入以下代码:

require "requirejs-rails"
module Jasminerice
  module SpecHelper
    include RequirejsHelper
    def spec_files
      Rails.application.assets.each_logical_path.select { |lp| lp =~ %r{^spec/.*.js$} }
    end
  end
end

这将创建一个辅助方法spec_files,您可以在Jasmierice runner视图中调用该方法来自动获取所有规格,因此您不需要每次添加新规格时都更新规格列表。

2.覆盖默认的Jasmierice索引视图

使用以下内容创建名为app/views/jasminerice/spec/index.html.erb的视图:

<!doctype html>
<head>
  <title>Jasmine Spec Runner</title>
  <%= stylesheet_link_tag "jasmine", "spec" %>
  <%= requirejs_include_tag 'application' %>
  <%= javascript_include_tag "jasminerice", "spec", :debug => true %>
  <script>
    jasmine.rice.autoExecute = false;
    require([<%= spec_files.map { |f| "'#{f.sub(/.js$/,'')}'" }.join(',').html_safe %>],
      function() { jasmine.getEnv().execute() },
      function(err) {
        var failedId = err.requireModules && err.requireModules[0];
        requirejs.undef(failedId);
        define(failedId, function() { return function() { console.debug(failedId + ': ' + err); null }; });
        require([ failedId ], function() {} );
      });
  </script>
  <%= csrf_meta_tags %>
</head>
<body>
</body>
</html>

在运行Jasmine(带有jasmine.getEnv().execute())之前,这将需要所有规格。我有一个丑陋的破解方法,使用规范路径数组,生成一个用引号括起来的模块名称数组,然后传递给require

我还包含了一个错误回调,以防加载模块时出现问题——如果不这样做,当模块加载失败时,您的规范将挂起。当你通过guard-jasmine在命令行上运行它们时,这尤其是一个问题,我就是这么做的

不幸的是,我还没有找到一个很好的方法来处理这些错误——在这里,我向console.debug写入了一些信息,然后要求使用失败的模块,并在其位置返回一个匿名函数。这允许规范运行,但会产生不可预测的结果(总比没有结果好)。我一直在努力寻找更好的方法来处理这种情况,建议将不胜感激。

3.编写一些规范

我的Jasmine眼镜采用以下形式:

define (require) ->
  MyModule = require 'my-module'
  # any other dependencies needed to test
  describe 'MyModule', ->
    it 'exists', ->
      expect(MyModule).toBeDefined()

等等。请注意,我在spec.js.coffee:中加载的所有测试依赖项(jasmine、sinon、jasmine sinon等)都超出了require

#=require sinon
#=require jasmine-sinon
#=require_tree ./helpers/

我把我需要的任何其他助手函数放在helpers目录中。

4.奖金

另一个提示:如果你有问题,因为你的浏览器即使在模块更改时也不会重新加载模块,我会使用添加一个带有时间戳的伪参数的技巧,这样浏览器就会始终看到一个新文件并正确加载它。

我在ApplicationController中创建了这个函数,并将其加载到前过滤器中:

before_filter :set_requirejs_config
def set_requirejs_config
  opts = { :urlArgs => "bust=#{Time.now.to_i}" }) if Rails.env == "development"
  Requirejs::Rails::Engine.config.requirejs.run_config.merge!(opts)
end

如果我们处于开发模式,这会在每个模块名称的末尾添加一个查询参数bust=...,以便我们始终重新加载模块并获得最新版本。SO上有一篇文章解释了如何在RequireJS中做到这一点,但要让它与RequireJS rails一起工作,你必须将它放入ApplicationController(而不是config/requirejs.yml)中,这样每次加载页面时都会加载它。

希望这能为其他使用此配置的人提供一些提示!

最新更新