diff --git a/.gitignore b/.gitignore
index 420aafa..f301dd4 100644
--- a/.gitignore
+++ b/.gitignore
@@ -14,3 +14,4 @@ jhw-test
.jhw-cache/
_site/
jhw.*.html
+coverage/
diff --git a/Gemfile b/Gemfile
index d6151f4..59c357c 100644
--- a/Gemfile
+++ b/Gemfile
@@ -15,3 +15,7 @@ gem 'mocha', '0.9.12'
gem 'guard-jasmine-headless-webkit', :git => 'git://github.com/johnbintz/guard-jasmine-headless-webkit.git'
gem 'facter'
+gem 'jquery-rails'
+gem 'ejs'
+
+gem 'simplecov'
diff --git a/Rakefile b/Rakefile
index cff7720..6f33603 100644
--- a/Rakefile
+++ b/Rakefile
@@ -43,3 +43,22 @@ task :build_runner do
end
end
+desc "Generate vendored JS"
+task :generate_js do
+ require 'sprockets'
+
+ source = 'vendor/assets/coffeescripts'
+ target = 'vendor/assets/javascripts'
+
+ env = Sprockets::Environment.new { |s| s.append_path 'vendor/assets/coffeescripts' }
+
+ Dir[File.join(File.expand_path(source), '*.coffee')].each do |file|
+ file_target = file.gsub(source, target).gsub('.coffee', '.js')
+ puts "#{file} => #{file_target}"
+
+ File.open(file_target, 'wb') do |fh|
+ fh.print env.find_asset(File.expand_path(file)).to_s
+ end
+ end
+end
+
diff --git a/bin/jasmine-headless-webkit b/bin/jasmine-headless-webkit
index 4a29588..975c765 100755
--- a/bin/jasmine-headless-webkit
+++ b/bin/jasmine-headless-webkit
@@ -1,31 +1,11 @@
#!/usr/bin/env ruby
require 'rubygems'
-require 'rainbow'
-def gem_dir
- File.expand_path('../..', __FILE__)
-end
+$: << File.expand_path('../../lib', __FILE__)
-$:.unshift(File.join(gem_dir, 'lib'))
require 'jasmine-headless-webkit'
require 'coffee-script'
-begin
- options = Jasmine::Headless::Options.from_command_line
- runner = Jasmine::Headless::Runner.new(options)
-
- if options[:do_list]
- files_list = Jasmine::FilesList.new(:config => runner.jasmine_config)
- files_list.files.each { |file| puts file }
- else
- exit runner.run
- end
-rescue CoffeeScript::CompilationError
- exit 1
-rescue StandardError => e
- $stderr.puts "[%s] %s (%s)" % [ "jasmine-headless-webkit".color(:red), e.message.color(:white), e.class.name.color(:yellow) ]
- $stderr.puts e.backtrace.collect { |line| " #{line}" }.join("\n")
- exit 1
-end
+Jasmine::Headless::CommandLine.run!
diff --git a/jasmine-headless-webkit.gemspec b/jasmine-headless-webkit.gemspec
index 834f207..2a6c27e 100644
--- a/jasmine-headless-webkit.gemspec
+++ b/jasmine-headless-webkit.gemspec
@@ -20,8 +20,9 @@ Gem::Specification.new do |s|
s.executables = `git ls-files -- bin/*`.split("\n").map{ |f| File.basename(f) }
s.require_paths = ["lib"]
- s.add_dependency 'jasmine-core', '~>1.1.beta'
- s.add_dependency 'coffee-script', '>= 2.2'
- s.add_dependency 'rainbow'
- s.add_dependency 'multi_json'
+ s.add_runtime_dependency 'jasmine-core', '~> 1.1'
+ s.add_runtime_dependency 'coffee-script'
+ s.add_runtime_dependency 'rainbow'
+ s.add_runtime_dependency 'multi_json'
+ s.add_runtime_dependency 'sprockets', '~> 2'
end
diff --git a/lib/digest/jasmine_test.rb b/lib/digest/jasmine_test.rb
new file mode 100644
index 0000000..f29e207
--- /dev/null
+++ b/lib/digest/jasmine_test.rb
@@ -0,0 +1,20 @@
+module Digest
+ class JasmineTest
+ def self.file(file)
+ new
+ end
+
+ def file(file)
+ self
+ end
+
+ def hexdigest
+ 'test'
+ end
+
+ def update(prefix)
+ self
+ end
+ end
+end
+
diff --git a/lib/jasmine-headless-webkit.rb b/lib/jasmine-headless-webkit.rb
index c279e93..a99ab37 100644
--- a/lib/jasmine-headless-webkit.rb
+++ b/lib/jasmine-headless-webkit.rb
@@ -1,7 +1,7 @@
-module Jasmine
- autoload :FilesList, 'jasmine/files_list'
-end
-
require 'jasmine/headless'
require 'jasmine/headless/railtie' if defined?(Rails) && Rails::VERSION::MAJOR >= 3
+module Digest
+ autoload :JasmineTest, 'digest/jasmine_test'
+end
+
diff --git a/lib/jasmine/files_list.rb b/lib/jasmine/files_list.rb
deleted file mode 100644
index 828637d..0000000
--- a/lib/jasmine/files_list.rb
+++ /dev/null
@@ -1,176 +0,0 @@
-require 'jasmine-core'
-require 'time'
-require 'multi_json'
-
-module Jasmine
- class FilesList
- attr_reader :files, :spec_files, :filtered_files, :spec_outside_scope
-
- class << self
- def find_vendored_asset_paths(*names)
- require 'rubygems'
-
- raise StandardError.new("A newer version of Rubygems is required to use vendored assets. Please upgrade.") if !Gem::Specification.respond_to?(:map)
- all_spec_files.find_all do |file|
- names.any? { |name| file["/#{name}.js"] }
- end
- end
-
- def all_spec_files
- @all_spec_files ||= Gem::Specification.map { |spec| spec.files.find_all { |file|
- file["vendor/assets/javascripts"]
- }.compact.collect { |file| File.join(spec.gem_dir, file) } }.flatten
- end
- end
-
- DEFAULT_FILES = [
- File.join(Jasmine::Core.path, "jasmine.js"),
- File.join(Jasmine::Core.path, "jasmine-html.js"),
- File.join(Jasmine::Core.path, "jasmine.css")
- ] + %w{jasmine-extensions intense headless_reporter_result jasmine.HeadlessConsoleReporter jsDump beautify-html}.collect { |name|
- Jasmine::Headless.root.join("vendor/assets/javascripts/#{name}.js").to_s
- }
-
- PLEASE_WAIT_IM_WORKING_TIME = 2
-
- def initialize(options = {})
- @options = options
- @files = DEFAULT_FILES.dup
- @filtered_files = @files.dup
- @spec_outside_scope = false
- @spec_files = []
- use_config! if config?
- end
-
- def has_spec_outside_scope?
- @spec_outside_scope
- end
-
- def filtered?
- files != filtered_files
- end
-
- def files_to_html
- to_html(files)
- end
-
- def filtered_files_to_html
- to_html(filtered_files)
- end
-
- def spec_file_line_numbers
- @spec_file_line_numbers ||= Hash[@spec_files.collect { |file|
- if File.exist?(file)
- if !(lines = Jasmine::Headless::SpecFileAnalyzer.for(file)).empty?
- [ file, lines ]
- end
- else
- nil
- end
- }.compact]
- end
-
- private
- def to_html(files)
- alert_time = Time.now + PLEASE_WAIT_IM_WORKING_TIME
-
- files.collect { |file|
- if alert_time && alert_time < Time.now
- puts "Rebuilding cache, please wait..."
- alert_time = nil
- end
-
- source = nil
-
- result = case File.extname(file)
- when '.coffee'
- begin
- cache = Jasmine::Headless::CoffeeScriptCache.new(file)
- source = cache.handle
- if cache.cached?
- %{
- }
- else
- %{}
- end
- rescue CoffeeScript::CompilationError => ne
- puts "[%s] %s: %s" % [ 'coffeescript'.color(:red), file.color(:yellow), ne.message.to_s.color(:white) ]
- raise ne
- rescue StandardError => e
- puts "[%s] Error in compiling one of the followng: %s" % [ 'coffeescript'.color(:red), files.join(' ').color(:yellow) ]
- raise e
- end
- when '.js'
- %{}
- when '.css'
- %{}
- end
-
- result
- }.flatten.compact.reject(&:empty?)
- end
-
- def spec_filter
- return @spec_filter if @spec_filter
-
- @spec_filter = begin
- if @options[:only]
- @options[:only].collect { |path| expanded_dir(path) }.flatten
- else
- []
- end
- end
- end
-
- def use_config!
- @filtered_files = @files.dup
-
- data = @options[:config].dup
- [ [ 'src_files', 'src_dir' ], [ 'stylesheets', 'src_dir' ], [ 'vendored_helpers' ], [ 'helpers', 'spec_dir' ], [ 'spec_files', 'spec_dir' ] ].each do |searches, root|
- if data[searches]
- case searches
- when 'vendored_helpers'
- data[searches].each do |name|
- found_files = self.class.find_vendored_asset_path(name)
-
- @files += found_files
- @filtered_files += found_files
- end
- else
- data[searches].flatten.collect do |search|
- path = search
- path = File.join(data[root], path) if data[root]
- found_files = expanded_dir(path) - @files
-
- @files += found_files
-
- if searches == 'spec_files'
- @spec_files += spec_filter.empty? ? found_files : (found_files & spec_filter)
- end
-
- @filtered_files += begin
- if searches == 'spec_files'
- @spec_outside_scope = ((spec_filter | found_files).sort != found_files.sort)
- spec_filter.empty? ? found_files : (spec_filter || found_files)
- else
- found_files
- end
- end
- end
- end
- end
- end
- end
-
- def config?
- @options[:config]
- end
-
- def expanded_dir(path)
- Dir[path].collect { |file| File.expand_path(file) }
- end
- end
-end
-
diff --git a/lib/jasmine/headless.rb b/lib/jasmine/headless.rb
index b35ff93..76d96ea 100644
--- a/lib/jasmine/headless.rb
+++ b/lib/jasmine/headless.rb
@@ -1,6 +1,8 @@
require 'pathname'
module Jasmine::Headless
+ autoload :CommandLine, 'jasmine/headless/command_line'
+
autoload :CoffeeScriptCache, 'jasmine/headless/coffee_script_cache'
autoload :SpecFileAnalyzer, 'jasmine/headless/spec_file_analyzer'
autoload :CacheableAction, 'jasmine/headless/cacheable_action'
@@ -8,9 +10,15 @@ module Jasmine::Headless
autoload :Runner, 'jasmine/headless/runner'
autoload :Options, 'jasmine/headless/options'
autoload :Task, 'jasmine/headless/task'
+ autoload :FilesList, 'jasmine/headless/files_list'
autoload :TemplateWriter, 'jasmine/headless/template_writer'
+ autoload :CoffeeTemplate, 'jasmine/headless/coffee_template'
+ autoload :JSTemplate, 'jasmine/headless/js_template'
+ autoload :JSTTemplate, 'jasmine/headless/jst_template'
+ autoload :CSSTemplate, 'jasmine/headless/css_template'
+
autoload :Report, 'jasmine/headless/report'
autoload :ReportMessage, 'jasmine/headless/report_message'
diff --git a/lib/jasmine/headless/coffee_template.rb b/lib/jasmine/headless/coffee_template.rb
new file mode 100644
index 0000000..5ad8918
--- /dev/null
+++ b/lib/jasmine/headless/coffee_template.rb
@@ -0,0 +1,30 @@
+require 'tilt/template'
+require 'rainbow'
+
+module Jasmine::Headless
+ class CoffeeTemplate < Tilt::Template
+ self.default_mime_type = 'application/javascript'
+
+ def prepare ; end
+
+ def evaluate(scope, locals, &block)
+ begin
+ cache = Jasmine::Headless::CoffeeScriptCache.new(file)
+ source = cache.handle
+ if cache.cached?
+ %{
+ }
+ else
+ %{}
+ end
+ rescue CoffeeScript::CompilationError => ne
+ puts "[%s] %s: %s" % [ 'coffeescript'.color(:red), file.color(:yellow), "#{ne.message}".color(:white) ]
+ raise ne
+ rescue StandardError => e
+ puts "[%s] Error in compiling file: %s" % [ 'coffeescript'.color(:red), file.color(:yellow) ]
+ raise e
+ end
+ end
+ end
+end
+
diff --git a/lib/jasmine/headless/command_line.rb b/lib/jasmine/headless/command_line.rb
new file mode 100644
index 0000000..f1181a9
--- /dev/null
+++ b/lib/jasmine/headless/command_line.rb
@@ -0,0 +1,31 @@
+module Jasmine::Headless
+ class CommandLine
+ class << self
+ def run!
+ require 'coffee-script'
+ require 'rainbow'
+
+ begin
+ options = Options.from_command_line
+ runner = Runner.new(options)
+
+ if options[:do_list]
+ FilesList.reset!
+
+ files_list = FilesList.new(:config => runner.jasmine_config)
+ files_list.files.each { |file| puts file }
+ else
+ exit runner.run
+ end
+ rescue CoffeeScript::CompilationError
+ exit 1
+ rescue StandardError => e
+ $stderr.puts "[%s] %s (%s)" % [ "jasmine-headless-webkit".color(:red), e.message.color(:white), e.class.name.color(:yellow) ]
+ $stderr.puts e.backtrace.collect { |line| " #{line}" }.join("\n")
+ exit 1
+ end
+ end
+ end
+ end
+end
+
diff --git a/lib/jasmine/headless/css_template.rb b/lib/jasmine/headless/css_template.rb
new file mode 100644
index 0000000..7829548
--- /dev/null
+++ b/lib/jasmine/headless/css_template.rb
@@ -0,0 +1,14 @@
+require 'tilt/template'
+
+module Jasmine::Headless
+ class CSSTemplate < Tilt::Template
+ self.default_mime_type = 'text/css'
+
+ def prepare ; end
+
+ def evaluate(scope, locals, &block)
+ file ? %{} : data
+ end
+ end
+end
+
diff --git a/lib/jasmine/headless/files_list.rb b/lib/jasmine/headless/files_list.rb
new file mode 100644
index 0000000..f533218
--- /dev/null
+++ b/lib/jasmine/headless/files_list.rb
@@ -0,0 +1,275 @@
+require 'jasmine-core'
+require 'time'
+require 'multi_json'
+require 'set'
+require 'sprockets'
+require 'sprockets/engines'
+
+module Jasmine::Headless
+ class FilesList
+ class << self
+ def vendor_asset_paths
+ return @vendor_asset_paths if @vendor_asset_paths
+
+ require 'rubygems'
+
+ raise StandardError.new("A newer version of Rubygems is required to use vendored assets. Please upgrade.") if !Gem::Specification.respond_to?(:map)
+
+ @vendor_asset_paths = []
+
+ Gem::Specification.map { |spec|
+ path = File.join(spec.gem_dir, 'vendor/assets/javascripts')
+
+ File.directory?(path) ? path : nil
+ }.compact
+ end
+
+ def reset!
+ @vendor_asset_paths = nil
+
+ # register haml-sprockets if it's available...
+ %w{haml-sprockets}.each do |library|
+ begin
+ require library
+ rescue LoadError
+ end
+ end
+
+ # ...and unregister ones we don't want/need
+ Sprockets.instance_eval do
+ %w{less sass scss erb str}.each do |extension|
+ @engines.delete(".#{extension}")
+ end
+
+ register_engine '.coffee', Jasmine::Headless::CoffeeTemplate
+ register_engine '.js', Jasmine::Headless::JSTemplate
+ register_engine '.css', Jasmine::Headless::CSSTemplate
+ register_engine '.jst', Jasmine::Headless::JSTTemplate
+ end
+ end
+
+ def default_files
+ %w{jasmine.js jasmine-html jasmine.css jasmine-extensions intense headless_reporter_result jasmine.HeadlessConsoleReporter jsDump beautify-html}
+ end
+ end
+
+ PLEASE_WAIT_IM_WORKING_TIME = 2
+
+ attr_reader :required_files, :potential_files_to_filter
+
+ def initialize(options = {})
+ @options = options
+
+ @required_files = []
+ @potential_files_to_filter = []
+
+ self.class.default_files.each do |file|
+ @required_files << sprockets_environment.find_asset(file, :bundle => false)
+ end
+
+ use_config! if config?
+ end
+
+ def files
+ required_files.collect { |file| file.to_a.collect { |asset| asset.pathname.to_s } }.flatten.uniq
+ end
+
+ def spec_files
+ filter_for_requested_specs(
+ files.find_all { |file| spec_dir.any? { |dir| file[dir] } }
+ )
+ end
+
+ def filtered_files
+ filter_for_requested_specs(files)
+ end
+
+ def search_paths
+ return @search_paths if @search_paths
+
+ @search_paths = [ Jasmine::Core.path ]
+ @search_paths += src_dir.collect { |dir| File.expand_path(dir) }
+ @search_paths += spec_dir.collect { |dir| File.expand_path(dir) }
+ @search_paths += self.class.vendor_asset_paths
+
+ @search_paths
+ end
+
+ def sprockets_environment
+ return @sprockets_environment if @sprockets_environment
+
+ @sprockets_environment = Sprockets::Environment.new
+ search_paths.each do |path|
+ @sprockets_environment.append_path(path)
+ end
+
+ @sprockets_environment.unregister_postprocessor('application/javascript', Sprockets::SafetyColons)
+ @sprockets_environment
+ end
+
+ def has_spec_outside_scope?
+ if is_outside_scope = !spec_filter.empty?
+ is_outside_scope = spec_dir.any? do |dir|
+ spec_file_searches.any? do |search|
+ !spec_files.any? { |file|
+ File.fnmatch?(File.join(dir, search), file)
+ }
+ end
+ end
+ end
+
+ is_outside_scope
+ end
+
+ def filtered?
+ files != filtered_files
+ end
+
+ def files_to_html
+ to_html(files)
+ end
+
+ def filtered_files_to_html
+ to_html(filtered_files)
+ end
+
+ def spec_file_line_numbers
+ @spec_file_line_numbers ||= Hash[spec_files.collect { |file|
+ if File.exist?(file)
+ if !(lines = Jasmine::Headless::SpecFileAnalyzer.for(file)).empty?
+ [ file, lines ]
+ end
+ else
+ nil
+ end
+ }.compact]
+ end
+
+ private
+ def to_html(files)
+ alert_time = Time.now + PLEASE_WAIT_IM_WORKING_TIME
+
+ files.collect do |file|
+ if alert_time && alert_time < Time.now
+ puts "Rebuilding cache, please wait..."
+ alert_time = nil
+ end
+
+ sprockets_environment.find_asset(file, :bundle => false).body
+ end.flatten.compact.reject(&:empty?)
+ end
+
+ def spec_filter
+ return @spec_filter if @spec_filter
+
+ @spec_filter = begin
+ if @options[:only]
+ @options[:only].collect { |path| expanded_dir(path) }.flatten
+ else
+ []
+ end
+ end
+ end
+
+ SEARCH_ROOTS = {
+ 'src_files' => 'src_dir',
+ 'stylesheets' => 'src_dir',
+ 'helpers' => 'spec_dir',
+ 'spec_files' => 'spec_dir'
+ }
+
+ def use_config!
+ @config = @options[:config].dup
+ @searches = {}
+ @potential_files_to_filter = []
+
+ %w{src_files stylesheets helpers spec_files}.each do |type|
+ if data = @config[type]
+ dirs = send(SEARCH_ROOTS[type])
+
+ add_files(@searches[type] = data.flatten, type, dirs)
+ end
+ end
+
+ filtered_required_files = []
+
+ @required_files.each do |file|
+ if !filtered_required_files.any? { |other_file| other_file.logical_path == file.logical_path }
+ filtered_required_files << file
+ end
+ end
+
+ @required_files = filtered_required_files
+ end
+
+ def add_files(patterns, type, dirs)
+ dirs.each do |dir|
+ patterns.each do |search|
+ search = File.expand_path(File.join(dir, search))
+
+ Dir[search].find_all { |file| file[extension_filter] }.each do |path|
+ add_path(path, type) if File.file?(path)
+ end
+ end
+ end
+
+ if type == 'spec_files'
+ spec_filter.each { |path| add_path(path, type) }
+ end
+ end
+
+ def config?
+ @options[:config]
+ end
+
+ def expanded_dir(path)
+ Dir[path].collect { |file| File.expand_path(file) }.find_all { |path| File.file?(path) && path[extension_filter] }
+ end
+
+ def extension_filter
+ %r{(#{(%w{.js .css} + Sprockets.engine_extensions).join('|')})$}
+ end
+
+ def add_path(path, type)
+ asset = sprockets_environment.find_asset(path)
+
+ @required_files << asset
+
+ if type == 'spec_files'
+ @potential_files_to_filter << path
+ end
+ end
+
+ def src_dir
+ config_dir_or_pwd('src_dir')
+ end
+
+ def spec_dir
+ config_dir_or_pwd('spec_dir')
+ end
+
+ def spec_file_searches
+ @searches['spec_files']
+ end
+
+ def config_dir_or_pwd(dir)
+ found_dir = Dir.pwd
+
+ if @options[:config]
+ found_dir = @options[:config][dir] || found_dir
+ end
+
+ [ found_dir ].flatten.collect { |dir| File.expand_path(dir) }
+ end
+
+ def filter_for_requested_specs(files)
+ files.find_all do |file|
+ if potential_files_to_filter.include?(file)
+ spec_filter.empty? || spec_filter.any? { |pattern| File.fnmatch?(pattern, file) }
+ else
+ true
+ end
+ end
+ end
+ end
+end
diff --git a/lib/jasmine/headless/js_template.rb b/lib/jasmine/headless/js_template.rb
new file mode 100644
index 0000000..e4a134f
--- /dev/null
+++ b/lib/jasmine/headless/js_template.rb
@@ -0,0 +1,18 @@
+require 'tilt/template'
+
+module Jasmine::Headless
+ class JSTemplate < Tilt::Template
+ self.default_mime_type = 'application/javascript'
+
+ def prepare ; end
+
+ def evaluate(scope, locals, &block)
+ if data['from="jhw"']
+ data
+ else
+ file ? %{} : data
+ end
+ end
+ end
+end
+
diff --git a/lib/jasmine/headless/jst_template.rb b/lib/jasmine/headless/jst_template.rb
new file mode 100644
index 0000000..f350686
--- /dev/null
+++ b/lib/jasmine/headless/jst_template.rb
@@ -0,0 +1,10 @@
+require 'sprockets/jst_processor'
+
+module Jasmine::Headless
+ class JSTTemplate < Sprockets::JstProcessor
+ def evaluate(*args)
+ %{}
+ end
+ end
+end
+
diff --git a/lib/jasmine/headless/runner.rb b/lib/jasmine/headless/runner.rb
index c82a30d..33de5c9 100644
--- a/lib/jasmine/headless/runner.rb
+++ b/lib/jasmine/headless/runner.rb
@@ -4,6 +4,8 @@ require 'coffee-script'
require 'rainbow'
require 'yaml'
+require 'sprockets'
+
module Jasmine
module Headless
@@ -23,9 +25,11 @@ module Jasmine
attr_reader :options
- def self.run(options = {})
- options = Options.new(options) if !options.kind_of?(Options)
- new(options).run
+ class << self
+ def run(options = {})
+ options = Options.new(options) if !options.kind_of?(Options)
+ new(options).run
+ end
end
def initialize(options)
@@ -65,8 +69,9 @@ module Jasmine
def run
Jasmine::Headless::CacheableAction.enabled = @options[:enable_cache]
+ FilesList.reset!
- files_list = Jasmine::FilesList.new(
+ files_list = Jasmine::Headless::FilesList.new(
:config => jasmine_config,
:only => @options[:files]
)
diff --git a/lib/jasmine/headless/task.rb b/lib/jasmine/headless/task.rb
index d6456a2..3368c6b 100644
--- a/lib/jasmine/headless/task.rb
+++ b/lib/jasmine/headless/task.rb
@@ -1,23 +1,3 @@
-module Digest
- class JasmineTest
- def self.file(file)
- new
- end
-
- def file(file)
- self
- end
-
- def hexdigest
- 'test'
- end
-
- def update(prefix)
- self
- end
- end
-end
-
module Jasmine
module Headless
class Task
@@ -41,8 +21,9 @@ module Jasmine
private
def create_rails_compliant_task
if Rails.respond_to?(:version) && Rails.version >= "3.1.0"
- desc 'Force generate static assets without an MD5 hash, all assets end with -test.'
task 'assets:precompile:for_testing' => :environment do
+ $stderr.puts "This task is deprecated and will be removed after 2012-01-01"
+
Rails.application.assets.digest_class = Digest::JasmineTest
Rake::Task['assets:precompile'].invoke
diff --git a/skel/template.html.erb b/skel/template.html.erb
index 05f7038..4da2057 100644
--- a/skel/template.html.erb
+++ b/skel/template.html.erb
@@ -23,7 +23,15 @@
if (window.JHW) {
jasmine.getEnv().addReporter(new jasmine.HeadlessConsoleReporter());
} else {
- jasmine.getEnv().addReporter(new jasmine.HtmlReporter());
+ types = [ 'HtmlReporter', 'TrivialReporter' ];
+
+ for (var i = 0, j = types.length; i < j; ++i) {
+ var type = jasmine[types[i]]
+ if (type) {
+ jasmine.getEnv().addReporter(new type());
+ break;
+ }
+ }
}
jasmine.getEnv().execute();
diff --git a/spec/bin/jasmine-headless-webkit_spec.rb b/spec/bin/jasmine-headless-webkit_spec.rb
index 72845c0..cd665d7 100644
--- a/spec/bin/jasmine-headless-webkit_spec.rb
+++ b/spec/bin/jasmine-headless-webkit_spec.rb
@@ -138,5 +138,23 @@ describe "jasmine-headless-webkit" do
File.size(runner_path.path).should_not == 0
end
end
+
+ describe 'sprockets' do
+ it 'should pull in the code via sprockets' do
+ files = %x{bin/jasmine-headless-webkit -l -j spec/jasmine/with_sprockets_includes/with_sprockets_includes.yml}
+ $?.exitstatus.should == 0
+
+ files.lines.to_a.should contain_in_order_in_file_list(
+ 'vendor/assets/javascripts/jquery.js',
+ 'templates/that.jst.ejs',
+ 'templates/this.jst',
+ 'assets/things/required.js',
+ 'assets/things/code.js',
+ 'assets/things/subcode/more_code.js',
+ 'spec_helper.js',
+ 'spec/things/code_spec.js'
+ )
+ end
+ end
end
diff --git a/spec/jasmine/with_sprockets_includes/assets/application.js b/spec/jasmine/with_sprockets_includes/assets/application.js
new file mode 100644
index 0000000..5d11335
--- /dev/null
+++ b/spec/jasmine/with_sprockets_includes/assets/application.js
@@ -0,0 +1,2 @@
+//= require 'jquery'
+//= require_tree '.'
diff --git a/spec/jasmine/with_sprockets_includes/assets/things/code.js b/spec/jasmine/with_sprockets_includes/assets/things/code.js
new file mode 100644
index 0000000..d437925
--- /dev/null
+++ b/spec/jasmine/with_sprockets_includes/assets/things/code.js
@@ -0,0 +1,6 @@
+//= require 'jquery'
+//= require_tree './templates'
+//= require 'things/required'
+
+window.a = '1';
+
diff --git a/spec/jasmine/with_sprockets_includes/assets/things/required.js b/spec/jasmine/with_sprockets_includes/assets/things/required.js
new file mode 100644
index 0000000..18241c9
--- /dev/null
+++ b/spec/jasmine/with_sprockets_includes/assets/things/required.js
@@ -0,0 +1,2 @@
+//= require 'jquery'
+
diff --git a/spec/jasmine/with_sprockets_includes/assets/things/subcode/more_code.js b/spec/jasmine/with_sprockets_includes/assets/things/subcode/more_code.js
new file mode 100644
index 0000000..d40811b
--- /dev/null
+++ b/spec/jasmine/with_sprockets_includes/assets/things/subcode/more_code.js
@@ -0,0 +1,2 @@
+//= require 'things/required'
+
diff --git a/spec/jasmine/with_sprockets_includes/assets/things/templates/that.jst.ejs b/spec/jasmine/with_sprockets_includes/assets/things/templates/that.jst.ejs
new file mode 100644
index 0000000..30f1577
--- /dev/null
+++ b/spec/jasmine/with_sprockets_includes/assets/things/templates/that.jst.ejs
@@ -0,0 +1 @@
+'hello'
diff --git a/spec/jasmine/with_sprockets_includes/assets/things/templates/this.jst b/spec/jasmine/with_sprockets_includes/assets/things/templates/this.jst
new file mode 100644
index 0000000..9424e78
--- /dev/null
+++ b/spec/jasmine/with_sprockets_includes/assets/things/templates/this.jst
@@ -0,0 +1,2 @@
+'hello'
+
diff --git a/spec/jasmine/with_sprockets_includes/spec/spec_helper.js b/spec/jasmine/with_sprockets_includes/spec/spec_helper.js
new file mode 100644
index 0000000..4817b36
--- /dev/null
+++ b/spec/jasmine/with_sprockets_includes/spec/spec_helper.js
@@ -0,0 +1 @@
+//= require 'jquery'
diff --git a/spec/jasmine/with_sprockets_includes/spec/things/code_spec.js b/spec/jasmine/with_sprockets_includes/spec/things/code_spec.js
new file mode 100644
index 0000000..8eed82a
--- /dev/null
+++ b/spec/jasmine/with_sprockets_includes/spec/things/code_spec.js
@@ -0,0 +1,9 @@
+//= require 'things/code'
+
+describe('code', function() {
+ it('should equal 1', function() {
+ expect(window.a).toEqual(1)
+ expect(jQuery).not.toBeUndefined()
+ });
+});
+
diff --git a/spec/jasmine/with_sprockets_includes/with_sprockets_includes.yml b/spec/jasmine/with_sprockets_includes/with_sprockets_includes.yml
new file mode 100644
index 0000000..99cd320
--- /dev/null
+++ b/spec/jasmine/with_sprockets_includes/with_sprockets_includes.yml
@@ -0,0 +1,12 @@
+src_dir: spec/jasmine/with_sprockets_includes/assets
+spec_dir: spec/jasmine/with_sprockets_includes/spec
+
+spec_files:
+ - "**/*_spec.js"
+
+src_files:
+ - "things/**/*"
+
+helpers:
+ - "spec_helper.js"
+
diff --git a/spec/lib/jasmine/files_list_spec.rb b/spec/lib/jasmine/files_list_spec.rb
deleted file mode 100644
index bb39811..0000000
--- a/spec/lib/jasmine/files_list_spec.rb
+++ /dev/null
@@ -1,248 +0,0 @@
-# encoding: UTF-8
-
-require 'spec_helper'
-require 'jasmine/files_list'
-require 'fakefs/spec_helpers'
-require 'coffee-script'
-
-describe Jasmine::FilesList do
- let(:files_list) { described_class.new }
-
- describe '#initialize' do
- it "should have default files" do
- files_list.files.should == [
- File.join(Jasmine::Core.path, "jasmine.js"),
- File.join(Jasmine::Core.path, "jasmine-html.js"),
- File.join(Jasmine::Core.path, "jasmine.css"),
- File.expand_path('vendor/assets/javascripts/jasmine-extensions.js'),
- File.expand_path('vendor/assets/javascripts/intense.js'),
- File.expand_path('vendor/assets/javascripts/headless_reporter_result.js'),
- File.expand_path('vendor/assets/javascripts/jasmine.HeadlessConsoleReporter.js'),
- File.expand_path('vendor/assets/javascripts/jsDump.js'),
- File.expand_path('vendor/assets/javascripts/beautify-html.js'),
- ]
- end
- end
-
- describe '#use_config' do
- let(:files_list) { described_class.new(:config => config) }
-
- include FakeFS::SpecHelpers
-
- let(:src_dir) { 'src' }
- let(:spec_dir) { 'spec' }
-
- let(:first_file) { File.join(src_dir, 'js/first_file.js') }
- let(:src_file) { File.join(src_dir, 'js/src_file.js') }
- let(:spec_file) { File.join(spec_dir, 'spec_file_spec.js') }
- let(:helper_file) { File.join(spec_dir, 'helper/helper_file.js') }
- let(:stylesheet_file) { File.join(src_dir, 'stylesheet/blah.css') }
-
- before do
- [ first_file, src_file, spec_file, helper_file, stylesheet_file ].each do |file|
- FileUtils.mkdir_p File.split(file).first
- File.open(file, 'w')
- end
- end
-
- shared_examples_for :reading_data do
- it 'should read the data from the jasmine.yml file and add the files' do
- files_list.files.should == Jasmine::FilesList::DEFAULT_FILES + [
- File.expand_path(first_file),
- File.expand_path(src_file),
- File.expand_path(stylesheet_file),
- File.expand_path(helper_file),
- File.expand_path(spec_file)
- ]
-
- files_list.spec_files.should == [ File.expand_path(spec_file) ]
- end
- end
-
- context 'with normal list' do
- let(:config) { {
- 'src_dir' => src_dir,
- 'spec_dir' => spec_dir,
- 'src_files' => [ 'js/first_file.js', 'js/*.js' ],
- 'spec_files' => [ '*_spec.js' ],
- 'helpers' => [ 'helper/*.js' ],
- 'stylesheets' => [ 'stylesheet/*.css' ]
- } }
-
- it_should_behave_like :reading_data
- end
-
- context 'with multidimensional list' do
- let(:config) { {
- 'src_dir' => src_dir,
- 'spec_dir' => spec_dir,
- 'src_files' => [ [ 'js/first_file.js', 'js/*.js' ] ],
- 'spec_files' => [ '*_spec.js' ],
- 'helpers' => [ 'helper/*.js' ],
- 'stylesheets' => [ 'stylesheet/*.css' ]
- } }
-
- it_should_behave_like :reading_data
- end
-
- context 'with vendored helpers' do
- let(:config) { {
- 'src_dir' => src_dir,
- 'spec_dir' => spec_dir,
- 'src_files' => [ 'js/first_file.js', 'js/*.js' ],
- 'spec_files' => [ '*_spec.js' ],
- 'helpers' => [],
- 'stylesheets' => [ 'stylesheet/*.css' ],
- 'vendored_helpers' => [ 'one', 'two' ]
- } }
-
- let(:helper_file) { "path/one.js" }
- let(:other_helper_file) { "path/two.js" }
-
- before do
- described_class.expects(:find_vendored_asset_path).with('one').returns([ helper_file ])
- described_class.expects(:find_vendored_asset_path).with('two').returns([ other_helper_file ])
- end
-
- it 'should find the vendored file' do
- files_list.files.should include(helper_file)
- files_list.files.should include(other_helper_file)
-
- files_list.files.index(helper_file).should be < files_list.files.index(other_helper_file)
- end
- end
- end
-
- context 'with filtered specs' do
- let(:files_list) { Jasmine::FilesList.new(:only => filter, :config => config) }
- let(:spec_dir) { 'spec' }
-
- include FakeFS::SpecHelpers
-
- let(:config) { {
- 'spec_files' => [ '*_spec.js' ],
- 'spec_dir' => spec_dir
- } }
-
- let(:spec_files) { %w{one_spec.js two_spec.js whatever.js} }
-
- before do
- spec_files.each do |file|
- FileUtils.mkdir_p spec_dir
- File.open(File.join(spec_dir, file), 'w')
- end
- end
-
- context 'empty filter' do
- let(:filter) { [] }
-
- it 'should return all files for filtered and all files' do
- files_list.files.any? { |file| file['two_spec.js'] }.should be_true
- files_list.filtered?.should be_false
- files_list.should_not have_spec_outside_scope
- files_list.spec_files.sort.should == %w{one_spec.js two_spec.js}.sort.collect { |file| File.expand_path(File.join(spec_dir, file)) }
- end
- end
-
- context 'filter with a file that is matchable' do
- let(:filter) { [ File.expand_path('spec/one_spec.js') ] }
-
- it 'should return all files for files' do
- files_list.files.any? { |file| file['two_spec.js'] }.should be_true
- files_list.filtered?.should be_true
- files_list.should_not have_spec_outside_scope
- files_list.spec_files.should == filter
- end
-
- it 'should return only filtered files for filtered_files' do
- files_list.filtered_files.any? { |file| file['two_spec.js'] }.should be_false
- files_list.should_not have_spec_outside_scope
- end
- end
-
- context 'filter with a glob' do
- let(:filter) { [ File.expand_path('spec/one*') ] }
-
- it 'should return all files for files' do
- files_list.files.any? { |file| file['two_spec.js'] }.should be_true
- files_list.filtered?.should be_true
- files_list.should_not have_spec_outside_scope
- end
-
- it 'should return only filtered files for filtered_files' do
- files_list.filtered_files.any? { |file| file['two_spec.js'] }.should be_false
- files_list.should_not have_spec_outside_scope
- end
- end
-
- context 'filter with a file that is not even there' do
- let(:filter) { [ File.expand_path('spec/whatever.js') ] }
-
- it 'should use the provided file' do
- files_list.filtered_files.any? { |file| file['whatever.js'] }.should be_true
- files_list.should have_spec_outside_scope
- end
- end
- end
-
- describe '#.*files_to_html' do
- include FakeFS::SpecHelpers
-
- before do
- files_list.instance_variable_set(:@files, [
- 'test.js',
- 'test.coffee',
- 'test.whatever',
- 'test.css'
- ])
-
- files_list.instance_variable_set(:@filtered_files, [
- 'test.js',
- 'test.coffee'
- ])
-
- File.stubs(:read)
- Jasmine::Headless::CoffeeScriptCache.any_instance.stubs(:handle).returns("i compiled")
- end
-
- context '#files_to_html' do
- it "should create the right HTML" do
- files_list.files_to_html.should == [
- %{},
- %{},
- %{}
- ]
- end
- end
-
- context '#filtered_files_to_html' do
- it "should create the right HTML" do
- files_list.filtered_files_to_html.should == [
- %{},
- %{}
- ]
- end
- end
- end
-
- describe '#spec_file_line_numbers' do
- include FakeFS::SpecHelpers
-
- before do
- files_list.instance_variable_set(:@spec_files, [
- 'test.coffee',
- 'test2.coffee'
- ])
-
- File.open('test.coffee', 'w') { |fh| fh.print "describe('cat')\ndescribe('cat')" }
- File.open('test2.coffee', 'w') { |fh| fh.print "no matches" }
- end
-
- it 'should generate filenames and line number info' do
- files_list.spec_file_line_numbers.should == {
- 'test.coffee' => { 'cat' => [ 1, 2 ] }
- }
- end
- end
-end
-
diff --git a/spec/lib/jasmine/headless/coffee_template_spec.rb b/spec/lib/jasmine/headless/coffee_template_spec.rb
new file mode 100644
index 0000000..c4abdea
--- /dev/null
+++ b/spec/lib/jasmine/headless/coffee_template_spec.rb
@@ -0,0 +1,55 @@
+require 'spec_helper'
+
+describe Jasmine::Headless::CoffeeTemplate do
+ let(:data) { 'data' }
+ let(:path) { 'path.coffee' }
+
+ let(:template) { described_class.new(path) { data } }
+
+ subject { template.render }
+
+ let(:handle_expectation) { Jasmine::Headless::CoffeeScriptCache.any_instance.stubs(:handle) }
+
+ context 'compilation error' do
+ let(:error) { CoffeeScript::CompilationError.new("fail") }
+
+ before do
+ handle_expectation.raises(error)
+ end
+
+ it 'should pass along the error' do
+ expect { subject }.to raise_error(CoffeeScript::CompilationError)
+ end
+ end
+
+ context 'compiles fine' do
+ let(:source) { 'source' }
+
+ before do
+ Jasmine::Headless::CoffeeScriptCache.any_instance.stubs(:cached?).returns(cache_return)
+ handle_expectation.returns(source)
+ end
+
+ context 'cached' do
+ let(:file_path) { 'dir/file.js' }
+ let(:cache_return) { true }
+
+ before do
+ Jasmine::Headless::CoffeeScriptCache.any_instance.stubs(:cache_file).returns(file_path)
+ end
+
+ it 'should return the cached file' do
+ subject.should include(%{})
+ end
+ end
+
+ context 'not cached' do
+ let(:cache_return) { false }
+
+ it 'should return the generated js' do
+ subject.should include(%{})
+ end
+ end
+ end
+end
+
diff --git a/spec/lib/jasmine/headless/css_template_spec.rb b/spec/lib/jasmine/headless/css_template_spec.rb
new file mode 100644
index 0000000..ca180e8
--- /dev/null
+++ b/spec/lib/jasmine/headless/css_template_spec.rb
@@ -0,0 +1,25 @@
+require 'spec_helper'
+
+describe Jasmine::Headless::CSSTemplate do
+ include FakeFS::SpecHelpers
+
+ let(:template) { described_class.new(file) { data } }
+ let(:file) { 'file' }
+ let(:data) { 'data' }
+
+ subject { template.render }
+
+ before do
+ File.open(file, 'wb') if file
+ end
+
+ context "no file'" do
+ let(:file) { nil }
+
+ it { should == data }
+ end
+
+ context 'file' do
+ it { should == %{} }
+ end
+end
diff --git a/spec/lib/jasmine/headless/files_list_spec.rb b/spec/lib/jasmine/headless/files_list_spec.rb
new file mode 100644
index 0000000..219f5b3
--- /dev/null
+++ b/spec/lib/jasmine/headless/files_list_spec.rb
@@ -0,0 +1,179 @@
+require 'spec_helper'
+require 'fakefs/spec_helpers'
+require 'coffee-script'
+
+describe Jasmine::Headless::FilesList do
+ let(:files_list) { described_class.new }
+
+ describe '#initialize' do
+ it "should have default files" do
+ files_list.files.should == [
+ File.join(Jasmine::Core.path, "jasmine.js"),
+ File.join(Jasmine::Core.path, "jasmine-html.js"),
+ File.join(Jasmine::Core.path, "jasmine.css"),
+ File.expand_path('vendor/assets/javascripts/jasmine-extensions.js'),
+ File.expand_path('vendor/assets/javascripts/intense.js'),
+ File.expand_path('vendor/assets/javascripts/headless_reporter_result.js'),
+ File.expand_path('vendor/assets/javascripts/jasmine.HeadlessConsoleReporter.js'),
+ File.expand_path('vendor/assets/javascripts/jsDump.js'),
+ File.expand_path('vendor/assets/javascripts/beautify-html.js'),
+ ]
+ end
+ end
+
+ def self.no_default_files!
+ before do
+ described_class.stubs(:default_files).returns([])
+ end
+ end
+
+ it 'should have tests for #use_config!'
+ it 'should have tests for #add_files'
+
+ describe '#spec_file_line_numbers' do
+ include FakeFS::SpecHelpers
+
+ no_default_files!
+
+ before do
+ files_list.stubs(:spec_files).returns(['test.coffee', 'test2.coffee'])
+
+ File.open('test.coffee', 'w') { |fh| fh.print "describe('cat')\ndescribe('cat')" }
+ File.open('test2.coffee', 'w') { |fh| fh.print "no matches" }
+ end
+
+ it 'should generate filenames and line number info' do
+ files_list.spec_file_line_numbers.should == {
+ 'test.coffee' => { 'cat' => [ 1, 2 ] }
+ }
+ end
+ end
+
+ describe '#search_paths' do
+ no_default_files!
+
+ let(:files_list) { described_class.new(:config => config) }
+
+ let(:config) { {
+ 'src_dir' => src_dir,
+ 'spec_dir' => spec_dir
+ } }
+
+ let(:src_dir) { 'src dir' }
+ let(:spec_dir) { 'spec dir' }
+ let(:path) { 'path' }
+
+ before do
+ Jasmine::Headless::FilesList.stubs(:vendor_asset_paths).returns([])
+ end
+
+ context 'no vendored gem paths' do
+ it 'should take the src dir and spec dirs' do
+ files_list.search_paths.should == [ Jasmine::Core.path, File.expand_path(src_dir), File.expand_path(spec_dir) ]
+ end
+ end
+
+ context 'vendored gem paths' do
+ before do
+ Jasmine::Headless::FilesList.stubs(:vendor_asset_paths).returns([ path ])
+ end
+
+ it 'should add the vendor gem paths to the list' do
+ files_list.search_paths.should == [ Jasmine::Core.path, File.expand_path(src_dir), File.expand_path(spec_dir), path ]
+ end
+ end
+
+ context 'src_dir is an array' do
+ let(:dir_1) { 'dir 1' }
+ let(:dir_2) { 'dir 2' }
+
+ let(:src_dir) { [ dir_1, dir_2 ] }
+
+ it 'should take the src dir and spec dirs' do
+ files_list.search_paths.should == [ Jasmine::Core.path, File.expand_path(dir_1), File.expand_path(dir_2), File.expand_path(spec_dir) ]
+ end
+ end
+ end
+
+ describe '.vendor_asset_paths' do
+ include FakeFS::SpecHelpers
+
+ let(:dir_one) { 'dir_one' }
+ let(:dir_two) { 'dir_two' }
+
+ let(:gem_one) { stub(:gem_dir => dir_one) }
+ let(:gem_two) { stub(:gem_dir => dir_two) }
+
+ before do
+ described_class.instance_variable_set(:@vendor_asset_paths, nil)
+
+ FileUtils.mkdir_p File.join(dir_two, 'vendor/assets/javascripts')
+
+ Gem::Specification.stubs(:_all).returns([gem_one, gem_two])
+ end
+
+ it 'should return all matching gems with vendor/assets/javascripts directories' do
+ described_class.vendor_asset_paths.should == [ File.join(dir_two, 'vendor/assets/javascripts') ]
+ end
+ end
+
+ describe '#files' do
+ let(:path_one) { 'one' }
+ let(:path_two) { 'two' }
+ let(:path_three) { 'three' }
+
+ let(:file_one) { stub(:to_a => [ asset_one, asset_two ] ) }
+ let(:file_two) { stub(:to_a => [ asset_two, asset_three ] ) }
+
+ let(:asset_one) { stub(:pathname => Pathname(path_one)) }
+ let(:asset_two) { stub(:pathname => Pathname(path_two)) }
+ let(:asset_three) { stub(:pathname => Pathname(path_three)) }
+
+ before do
+ files_list.stubs(:required_files).returns([ file_one, file_two ])
+ end
+
+ subject { files_list.files }
+
+ it { should == [ path_one, path_two, path_three ] }
+ end
+
+ describe '#filtered_files' do
+ let(:spec_dir) { 'spec' }
+
+ let(:file_one) { "#{spec_dir}/one" }
+ let(:file_two) { "#{spec_dir}/two" }
+ let(:file_three) { "#{spec_dir}/three" }
+ let(:file_four) { 'other/four' }
+
+ before do
+ files_list.stubs(:files).returns([
+ file_one,
+ file_two,
+ file_three,
+ file_four
+ ])
+
+ files_list.stubs(:potential_files_to_filter).returns([ file_one, file_two, file_three ])
+ end
+
+ subject { files_list.filtered_files }
+
+ context 'empty filter' do
+ before do
+ files_list.stubs(:spec_filter).returns([])
+ end
+
+ it { should == [ file_one, file_two, file_three, file_four ] }
+ end
+
+ context 'with filter' do
+ before do
+ files_list.stubs(:spec_filter).returns([ "#{spec_dir}/one", '**/tw*' ])
+ end
+
+ it { should == [ file_one, file_two, file_four ] }
+ end
+ end
+end
+
diff --git a/spec/lib/jasmine/headless/js_template_spec.rb b/spec/lib/jasmine/headless/js_template_spec.rb
new file mode 100644
index 0000000..2f75b28
--- /dev/null
+++ b/spec/lib/jasmine/headless/js_template_spec.rb
@@ -0,0 +1,31 @@
+require 'spec_helper'
+
+describe Jasmine::Headless::JSTemplate do
+ include FakeFS::SpecHelpers
+
+ let(:template) { described_class.new(file) { data } }
+ let(:file) { 'file' }
+ let(:data) { 'data' }
+
+ subject { template.render }
+
+ before do
+ File.open(file, 'wb') if file
+ end
+
+ context "no file'" do
+ let(:file) { nil }
+
+ it { should == data }
+ end
+
+ context 'file' do
+ it { should == %{} }
+ end
+
+ context 'jhw content' do
+ let(:data) { 'from="jhw"' }
+
+ it { should == data }
+ end
+end
diff --git a/spec/lib/jasmine/headless/jst_template_spec.rb b/spec/lib/jasmine/headless/jst_template_spec.rb
new file mode 100644
index 0000000..943a7e8
--- /dev/null
+++ b/spec/lib/jasmine/headless/jst_template_spec.rb
@@ -0,0 +1,21 @@
+require 'spec_helper'
+
+describe Jasmine::Headless::JSTTemplate do
+ include FakeFS::SpecHelpers
+
+ let(:template) { described_class.new(file) }
+ let(:file) { 'file' }
+ let(:data) { 'data' }
+
+ let(:context) { stub(:logical_path => 'path') }
+
+ before do
+ File.open(file, 'wb') { |fh| fh.print data }
+ end
+
+ subject { template.render(context) }
+
+ it { should include(%{