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(%{