Coding For Rent

A blog by Josh Moore all about working with Rails, Ruby, and other programming stuff

By: Joshua Moore

Jasmine with Rails 3.1

I have been writing a JavaScript intensive Rails 3.1 application recently and haven been using Jasmine to test my JavaScript. When I started this application I was using the RC version of Rails 3.1 and was generating my assets based on Jeff Dean’s post however with the release of 3.1 stable I found this method does not work any more. So I had to change the jasmine_config.rb to make it work again.

Also because Rails is out of beta now so I am no longer calling the rake task, instead I am. Using the API that the rake task uses.

So to keep things brief here is what my jasmine.rb looks like (located in spec/javascript/support)

 1 module Jasmine
 2   class Config
 3 
 4     def js_files(spec_filter = nil)
 5       generated_files_directory = File.expand_path("../../generated", __FILE__)
 6       rm_rf generated_files_directory, :secure => true
 7       precompile_app_assets
 8       compile_jasmine_javascripts
 9 
10       # this is code from the original jasmine config js_files method - you could also just alias_method_chain it
11       spec_files_to_include = spec_filter.nil? ? spec_files : match_files(spec_dir, [spec_filter])
12       src_files.collect {|f| "/" + f } + helpers.collect {|f| File.join(spec_path, f) } + spec_files_to_include.collect {|f| File.join(spec_path, f) }
13     end
14 
15     private
16 
17     # this method compiles all the same javascript files your app will
18     def precompile_app_assets
19       puts "Precompiling assets..."
20 
21       # make sure the Rails environment is loaded
22       require 'config/environment'
23       # ::Rake.application['environment'].invoke
24 
25     
26 
27       config = Rails.application.config
28       env    = Rails.application.assets
29       target = Rails.root.join("spec/javascripts/generated/assets")
30 
31 
32       config.assets.precompile.each do |path|
33         env.each_logical_path do |logical_path|
34           if path.is_a?(Regexp)
35             next unless path.match(logical_path)
36           elsif path.is_a?(Proc)
37             next unless path.call(logical_path)
38           else
39             next unless File.fnmatch(path.to_s, logical_path)
40           end
41 
42           if asset = env.find_asset(logical_path)
43             asset_path = config.assets.digest ? asset.digest_path : logical_path
44             filename = target.join(asset_path)
45 
46             mkdir_p filename.dirname
47             asset.write_to(filename)
48             asset.write_to("#{filename}.gz") if filename.to_s =~ /\.(css|js)$/
49           end
50         end
51       end
52     end
53 
54     # this method compiles all of the spec files into js files that jasmine can run
55     def compile_jasmine_javascripts
56       puts "Compiling jasmine coffee scripts into javascript..."
57       root = File.expand_path("../../../../spec/javascripts/coffee", __FILE__)
58       destination_dir = File.expand_path("../../generated/specs", __FILE__)
59 
60       glob = File.expand_path("**/*.js.coffee", root)
61 
62       Dir.glob(glob).each do |srcfile|
63         srcfile = Pathname.new(srcfile)
64         destfile = srcfile.sub(root, destination_dir).sub(".coffee", "")
65         FileUtils.mkdir_p(destfile.dirname)
66         File.open(destfile, "w") {|f| f.write(CoffeeScript.compile(File.new(srcfile)))}
67       end
68     end
69 
70   end
71 end
72 
73 
74 # Note - this is necessary for rspec2, which has removed the backtrace
75 module Jasmine
76   class SpecBuilder
77     def declare_spec(parent, spec)
78       me = self
79       example_name = spec["name"]
80       @spec_ids << spec["id"]
81       backtrace = @example_locations[parent.description + " " + example_name]
82       parent.it example_name, {} do
83         me.report_spec(spec["id"])
84       end
85     end
86   end
87 end

Here is an exert from jasmine.yml, also located in spec/javascript/support.

src_files:
  - spec/javascripts/generated/assets/application*.js 

With these changes I have not had any problems with my jasmine suite running correctly.

blog comments powered by Disqus
RSS profile for Josh Moore at Stack Overflow, Q&A for professional and enthusiast programmers