2

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

我尝试实施http://ryantownsend.co.uk/post/31662285280/jasminerice-and-requirejs-rails-fix 但收效甚微,规范根本没有运行。

我开始认为,也许我自己使用 requirejs 或者茉莉花宝石可能会更好?

我没有出售 jasminerice 或 require-rails gems,所以有没有人对最好的工具有任何建议,以及关于如何启动和运行/好的教程的任何提示?

4

2 回答 2

2

我有相同的设置,这就是我所做的(从原始问题中提到的博客文章开始):

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,您可以在 Jasminerice 运行器视图中调用该方法以自动获取所有规格,因此您无需在每次添加新规格时都更新规格列表。

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

创建一个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. 写一些规范

我的茉莉花规格采用以下形式:

define (require) ->
  MyModule = require 'my-module'
  # any other dependencies needed to test

  describe 'MyModule', ->

    it 'exists', ->
      expect(MyModule).toBeDefined()

等请注意,我在 require 之外加载的所有测试依赖项(jasmine、sinon、jasmine-sinon 等)spec.js.coffee

#=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),以便每次加载页面时都会加载它。

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

于 2013-09-22T14:53:15.007 回答
2

好的,因为我没有得到任何回应,所以我设法找到了一种稍微笨拙的方法来让它工作。

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

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

然后像 require 模板一样编写您的规范文件,如下所示:

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()

希望对遇到类似问题的人有所帮助,如果有人有更好的解决方案,请发布!:)

于 2013-06-28T16:11:34.143 回答