From bd8fa3e53685ce65a74638eef209a0818d770d55 Mon Sep 17 00:00:00 2001 From: John Bintz Date: Thu, 1 Sep 2011 08:36:11 -0400 Subject: [PATCH 1/6] appease rubygems --- ext/jasmine-webkit-specrunner/Makefile.dummy | 5 +++++ ext/jasmine-webkit-specrunner/extconf.rb | 1 + 2 files changed, 6 insertions(+) create mode 100644 ext/jasmine-webkit-specrunner/Makefile.dummy diff --git a/ext/jasmine-webkit-specrunner/Makefile.dummy b/ext/jasmine-webkit-specrunner/Makefile.dummy new file mode 100644 index 0000000..9b9a271 --- /dev/null +++ b/ext/jasmine-webkit-specrunner/Makefile.dummy @@ -0,0 +1,5 @@ +build: + true +install: + true + diff --git a/ext/jasmine-webkit-specrunner/extconf.rb b/ext/jasmine-webkit-specrunner/extconf.rb index d950511..6980885 100644 --- a/ext/jasmine-webkit-specrunner/extconf.rb +++ b/ext/jasmine-webkit-specrunner/extconf.rb @@ -7,3 +7,4 @@ require 'qt/qmake' system %{make clean} Qt::Qmake.make!('jasmine-headless-webkit', 'specrunner.pro') +FileUtils.cp File.expand_path('../Makefile.dummy', __FILE__), File.expand_path('../Makefile', __FILE__) From fa27ee715a5244fed2d783bb9a10677ac71785c2 Mon Sep 17 00:00:00 2001 From: John Bintz Date: Thu, 1 Sep 2011 09:38:53 -0400 Subject: [PATCH 2/6] enable coffeescript cache, step 1 of a big speedup --- .gitignore | 1 + Gemfile | 1 + lib/jasmine-headless-webkit.rb | 3 +- lib/jasmine/files_list.rb | 56 +++-------- lib/jasmine/headless/coffee_script_cache.rb | 66 +++++++++++++ lib/jasmine/headless/options.rb | 7 ++ lib/jasmine/headless/runner.rb | 2 + spec/lib/jasmine/files_list_spec.rb | 96 +++++-------------- .../headless/coffee_script_cache_spec.rb | 87 +++++++++++++++++ spec/spec_helper.rb | 56 ++++++----- 10 files changed, 238 insertions(+), 137 deletions(-) create mode 100644 lib/jasmine/headless/coffee_script_cache.rb create mode 100644 spec/lib/jasmine/headless/coffee_script_cache_spec.rb diff --git a/.gitignore b/.gitignore index 801dd0a..b523b09 100644 --- a/.gitignore +++ b/.gitignore @@ -11,3 +11,4 @@ moc_*.* .DS_Store hydra-runner.log jhw-test +.jhw-cache/ diff --git a/Gemfile b/Gemfile index fc8fa1e..bfcf6b6 100644 --- a/Gemfile +++ b/Gemfile @@ -14,3 +14,4 @@ gem 'rake', '0.8.7' gem 'mocha', '0.9.12' gem 'guard-jasmine-headless-webkit' gem 'facter' + diff --git a/lib/jasmine-headless-webkit.rb b/lib/jasmine-headless-webkit.rb index d5b1fb7..0ca38a4 100644 --- a/lib/jasmine-headless-webkit.rb +++ b/lib/jasmine-headless-webkit.rb @@ -1,7 +1,6 @@ module Jasmine module Headless - module Webkit - end + autoload :CoffeeScriptCache, 'jasmine/headless/coffee_script_cache' end end diff --git a/lib/jasmine/files_list.rb b/lib/jasmine/files_list.rb index 0b4db1b..21ed3ce 100644 --- a/lib/jasmine/files_list.rb +++ b/lib/jasmine/files_list.rb @@ -1,3 +1,4 @@ +require 'jasmine/headless/coffee_script_cache' require 'jasmine-core' require 'iconv' @@ -66,53 +67,26 @@ module Jasmine private def to_html(files) - coffeescript_run = [] - files.collect { |file| - coffeescript_run << file if (ext = File.extname(file)) == '.coffee' - - output = [] - if (files.last == file or ext != '.coffee') and !coffeescript_run.empty? - output << ensure_coffeescript_run!(coffeescript_run) - end - - if ext != '.coffee' - output << case File.extname(file) - when '.js' - %{} - when '.css' - %{} + case File.extname(file) + when '.coffee' + begin + %{} + 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 - - output }.flatten.reject(&:empty?) end - def ensure_coffeescript_run!(files) - data = StringIO.new - files.each { |file| data << File.read(file) << "\n" } - data.rewind - - %{} - rescue CoffeeScript::CompilationError => e - files.each do |file| - begin - CoffeeScript.compile(fh = File.open(file)) - rescue CoffeeScript::CompilationError => ne - puts "[%s] %s: %s" % [ 'coffeescript'.color(:red), file.color(:yellow), ne.message.to_s.color(:white) ] - raise ne - ensure - fh.close - end - end - rescue StandardError => e - puts "[%s] Error in compiling one of the followng: %s" % [ 'coffeescript'.color(:red), files.join(' ').color(:yellow) ] - raise e - ensure - files.clear - end - def spec_filter @spec_filter ||= (@options[:only] ? @options[:only].collect { |path| Dir[path] }.flatten : []) end diff --git a/lib/jasmine/headless/coffee_script_cache.rb b/lib/jasmine/headless/coffee_script_cache.rb new file mode 100644 index 0000000..5a1b103 --- /dev/null +++ b/lib/jasmine/headless/coffee_script_cache.rb @@ -0,0 +1,66 @@ +require 'coffee_script' +require 'digest/sha1' +require 'fileutils' + +module Jasmine + module Headless + class CoffeeScriptCache + class << self + def enabled=(bool) + @enabled = bool + end + + def enabled? + @enabled = true if @enabled == nil + @enabled + end + + def cache_dir=(dir) + @cache_dir = dir + end + + def cache_dir + @cache_dir ||= '.jhw-cache' + end + + def for(file) + new(file).handle + end + end + + attr_reader :file + + def initialize(file) + @file = file + end + + def handle + if self.class.enabled? + if fresh? + File.read(cache_file) + else + result = compile + FileUtils.mkdir_p self.class.cache_dir + File.open(cache_file, 'wb') { |fh| fh.print result } + result + end + else + compile + end + end + + def cache_file + @cache_file ||= File.join(self.class.cache_dir, Digest::SHA1.hexdigest(file)) + end + + def fresh? + File.exist?(cache_file) && (File.mtime(file) < File.mtime(cache_file)) + end + + def compile + CoffeeScript.compile(File.read(file)) + end + end + end +end + diff --git a/lib/jasmine/headless/options.rb b/lib/jasmine/headless/options.rb index 7afbd63..fff6302 100644 --- a/lib/jasmine/headless/options.rb +++ b/lib/jasmine/headless/options.rb @@ -15,6 +15,7 @@ module Jasmine :report => false, :do_list => false, :full_run => true, + :enable_cache => true, :files => [] } @@ -42,6 +43,10 @@ module Jasmine @options[:colors] = true when '--no-colors', '-nc' @options[:colors] = false + when '--cache' + @options[:enable_cache] = true + when '--no-cache' + @options[:enable_cache] = false when '--keep' @options[:remove_html_file] = false when '--report' @@ -67,6 +72,8 @@ module Jasmine command_line_args = GetoptLong.new( [ '--colors', '-c', GetoptLong::NO_ARGUMENT ], [ '--no-colors', GetoptLong::NO_ARGUMENT ], + [ '--cache', GetoptLong::NO_ARGUMENT ], + [ '--no-t stcache', GetoptLong::NO_ARGUMENT ], [ '--keep', GetoptLong::NO_ARGUMENT ], [ '--report', GetoptLong::REQUIRED_ARGUMENT ], [ '--jasmine-config', '-j', GetoptLong::REQUIRED_ARGUMENT ], diff --git a/lib/jasmine/headless/runner.rb b/lib/jasmine/headless/runner.rb index f3e4343..7f7613b 100644 --- a/lib/jasmine/headless/runner.rb +++ b/lib/jasmine/headless/runner.rb @@ -61,6 +61,8 @@ module Jasmine end def run + Jasmine::Headless::CoffeeScriptCache.enabled = @options[:enable_cache] + files_list = Jasmine::FilesList.new( :config => jasmine_config, :only => @options[:files] diff --git a/spec/lib/jasmine/files_list_spec.rb b/spec/lib/jasmine/files_list_spec.rb index 26cd34a..9daaade 100644 --- a/spec/lib/jasmine/files_list_spec.rb +++ b/spec/lib/jasmine/files_list_spec.rb @@ -147,83 +147,37 @@ describe Jasmine::FilesList do describe '#.*files_to_html' do include FakeFS::SpecHelpers - context 'one coffeescript file' do - before do - files_list.instance_variable_set(:@files, [ - 'test.js', - 'test.coffee', - 'test.css' - ]) + before do + files_list.instance_variable_set(:@files, [ + 'test.js', + 'test.coffee', + 'test.css' + ]) - files_list.instance_variable_set(:@filtered_files, [ - 'test.js', - 'test.coffee' - ]) + files_list.instance_variable_set(:@filtered_files, [ + 'test.js', + 'test.coffee' + ]) - File.open('test.coffee', 'w') { |fh| fh.print "first" } + Jasmine::Headless::CoffeeScriptCache.stubs(:for).with('test.coffee').returns("i compiled") + end - CoffeeScript.stubs(:compile).with() { |field| field.read == "first\n" }.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 + context '#files_to_html' do + it "should create the right HTML" do + files_list.files_to_html.should == [ + %{}, + %{}, + %{} + ] end end - context 'two coffeescript files' do - before do - files_list.instance_variable_set(:@files, [ - 'test.js', - 'test.coffee', - 'test2.coffee', - 'test.css' - ]) - - files_list.instance_variable_set(:@filtered_files, [ - 'test.js', - 'test.coffee' - ]) - - File.open('test.coffee', 'w') { |fh| fh.print "first" } - File.open('test2.coffee', 'w') { |fh| fh.print "second" } - end - - context '#files_to_html' do - it "should create the right HTML" do - CoffeeScript.stubs(:compile).with() { |field| field.read == "first\nsecond\n" }.returns("i compiled") - - files_list.files_to_html.should == [ - %{}, - %{}, - %{} - ] - end - end - - context '#filtered_files_to_html' do - it "should create the right HTML" do - CoffeeScript.stubs(:compile).with() { |field| field.read == "first\n" }.returns("i compiled") - - files_list.filtered_files_to_html.should == [ - %{}, - %{} - ] - end + context '#filtered_files_to_html' do + it "should create the right HTML" do + files_list.filtered_files_to_html.should == [ + %{}, + %{} + ] end end end diff --git a/spec/lib/jasmine/headless/coffee_script_cache_spec.rb b/spec/lib/jasmine/headless/coffee_script_cache_spec.rb new file mode 100644 index 0000000..9629a00 --- /dev/null +++ b/spec/lib/jasmine/headless/coffee_script_cache_spec.rb @@ -0,0 +1,87 @@ +require 'spec_helper' + +describe Jasmine::Headless::CoffeeScriptCache do + include FakeFS::SpecHelpers + + let(:file) { 'file.coffee' } + let(:data) { 'data' } + let(:compiled) { 'compiled' } + + before do + File.open(file, 'wb') { |fh| fh.print(data) } + described_class.cache_dir = cache_dir + end + + let(:coffee_script_compiles!) do + CoffeeScript.expects(:compile).with(data).returns(compiled) + end + + let(:cache_dir) { 'cache' } + let(:cache_file) { File.join(cache_dir, Digest::SHA1.hexdigest(file)) } + let(:cache_file_data) { File.read(cache_file) } + + describe '.for' do + context 'cache disabled' do + before do + described_class.enabled = false + p described_class.enabled? + end + + it 'should compile' do + coffee_script_compiles! + described_class.for(file).should == compiled + cache_file.should_not be_a_file + end + end + + context 'cache enabled' do + before do + described_class.enabled = true + FileUtils.mkdir_p(cache_dir) + + File.stubs(:mtime).with(file).returns(Time.at(10)) + File.stubs(:mtime).with(cache_file).returns(Time.at(cache_file_mtime)) + end + + context 'cache empty' do + let(:cache_file_mtime) { 0 } + + it 'should compile' do + coffee_script_compiles! + described_class.for(file).should == compiled + + cache_file_data.should == compiled + end + end + + context 'cache fresh' do + let(:cache_file_mtime) { 15 } + + before do + File.open(cache_file, 'wb') { |fh| fh.print compiled } + end + + it 'should not compile' do + coffee_script_compiles!.never + + described_class.for(file).should == compiled + + cache_file_data.should == compiled + end + end + + context 'cache stale' do + let(:cache_file_mtime) { 5 } + + it 'should compile' do + coffee_script_compiles! + + described_class.for(file).should == compiled + + cache_file_data.should == compiled + end + end + end + end +end + diff --git a/spec/spec_helper.rb b/spec/spec_helper.rb index 1f9e555..0fcd858 100644 --- a/spec/spec_helper.rb +++ b/spec/spec_helper.rb @@ -1,3 +1,6 @@ +require 'jasmine-headless-webkit' +require 'fakefs/spec_helpers' + RSpec.configure do |c| c.mock_with :mocha end @@ -10,32 +13,39 @@ if !File.file?(specrunner) end end -RSpec::Matchers.define :be_a_report_containing do |total, fails, used_console| - match do |filename| - parts(filename).length.should == 4 - parts[0].should == total.to_s - parts[1].should == fails.to_s - parts[2].should == (used_console ? "T" : "F") - true +module RSpec::Matchers + define :be_a_report_containing do |total, fails, used_console| + match do |filename| + parts(filename).length.should == 4 + parts[0].should == total.to_s + parts[1].should == fails.to_s + parts[2].should == (used_console ? "T" : "F") + true + end + + failure_message_for_should do |filename| + parts(filename) + "expected #{filename} to be a report containing (#{total}, #{fails}, #{used_console.inspect}), instead it contained (#{parts[0]}, #{parts[1]}, #{(parts[2] == "T").inspect})" + end + + def parts(filename = nil) + @parts ||= File.readlines(filename).first.strip.split('/') + end end - failure_message_for_should do |filename| - parts(filename) - "expected #{filename} to be a report containing (#{total}, #{fails}, #{used_console.inspect}), instead it contained (#{parts[0]}, #{parts[1]}, #{(parts[2] == "T").inspect})" + define :contain_a_failing_spec do |*parts| + match do |filename| + report(filename).include?(parts.join("||")).should be_true + end + + def report(filename) + @report ||= File.readlines(filename)[1..-1].collect(&:strip) + end end - def parts(filename = nil) - @parts ||= File.readlines(filename).first.strip.split('/') + define :be_a_file do + match do |file| + File.file?(file) + end end end - -RSpec::Matchers.define :contain_a_failing_spec do |*parts| - match do |filename| - report(filename).include?(parts.join("||")).should be_true - end - - def report(filename) - @report ||= File.readlines(filename)[1..-1].collect(&:strip) - end -end - From c523a1e31041e50aac936244904b3d3b81285e80 Mon Sep 17 00:00:00 2001 From: John Bintz Date: Thu, 1 Sep 2011 10:39:29 -0400 Subject: [PATCH 3/6] second part - cache spec file analysis --- Rakefile | 1 + bin/jasmine-headless-webkit | 1 + lib/jasmine-headless-webkit.rb | 2 + lib/jasmine/files_list.rb | 20 +---- lib/jasmine/headless/cacheable_action.rb | 77 ++++++++++++++++ lib/jasmine/headless/coffee_script_cache.rb | 54 +----------- lib/jasmine/headless/runner.rb | 2 +- lib/jasmine/headless/spec_file_analyzer.rb | 37 ++++++++ spec/bin/jasmine-headless-webkit_spec.rb | 1 - spec/lib/jasmine/files_list_spec.rb | 44 ---------- .../jasmine/headless/cacheable_action_spec.rb | 88 +++++++++++++++++++ .../headless/coffee_script_cache_spec.rb | 84 ++---------------- .../headless/spec_file_analyzer_spec.rb | 57 ++++++++++++ spec/spec_helper.rb | 4 + specrunner.104.filter.html | 0 specrunner.123.filter.html | 0 specrunner.137.filter.html | 0 specrunner.151.filter.html | 0 specrunner.165.filter.html | 0 specrunner.835.filter.html | 0 specrunner.849.filter.html | 0 specrunner.863.filter.html | 0 specrunner.877.filter.html | 0 specrunner.891.filter.html | 0 specrunner.99208.filter.html | 0 specrunner.99222.filter.html | 0 specrunner.99236.filter.html | 0 specrunner.99250.filter.html | 0 specrunner.99264.filter.html | 0 29 files changed, 283 insertions(+), 189 deletions(-) create mode 100644 lib/jasmine/headless/cacheable_action.rb create mode 100644 lib/jasmine/headless/spec_file_analyzer.rb create mode 100644 spec/lib/jasmine/headless/cacheable_action_spec.rb create mode 100644 spec/lib/jasmine/headless/spec_file_analyzer_spec.rb create mode 100644 specrunner.104.filter.html create mode 100644 specrunner.123.filter.html create mode 100644 specrunner.137.filter.html create mode 100644 specrunner.151.filter.html create mode 100644 specrunner.165.filter.html create mode 100644 specrunner.835.filter.html create mode 100644 specrunner.849.filter.html create mode 100644 specrunner.863.filter.html create mode 100644 specrunner.877.filter.html create mode 100644 specrunner.891.filter.html create mode 100644 specrunner.99208.filter.html create mode 100644 specrunner.99222.filter.html create mode 100644 specrunner.99236.filter.html create mode 100644 specrunner.99250.filter.html create mode 100644 specrunner.99264.filter.html diff --git a/Rakefile b/Rakefile index d13a827..db8bed4 100644 --- a/Rakefile +++ b/Rakefile @@ -9,6 +9,7 @@ RSpec::Core::RakeTask.new(:spec) $: << File.expand_path('../lib', __FILE__) +require 'jasmine-headless-webkit' require 'jasmine/headless/task' Jasmine::Headless::Task.new diff --git a/bin/jasmine-headless-webkit b/bin/jasmine-headless-webkit index a38610d..8d48998 100755 --- a/bin/jasmine-headless-webkit +++ b/bin/jasmine-headless-webkit @@ -8,6 +8,7 @@ def gem_dir end $:.unshift(File.join(gem_dir, 'lib')) +require 'jasmine-headless-webkit' require 'jasmine/headless/errors' require 'jasmine/headless/runner' require 'jasmine/headless/options' diff --git a/lib/jasmine-headless-webkit.rb b/lib/jasmine-headless-webkit.rb index 0ca38a4..9626790 100644 --- a/lib/jasmine-headless-webkit.rb +++ b/lib/jasmine-headless-webkit.rb @@ -1,6 +1,8 @@ module Jasmine module Headless autoload :CoffeeScriptCache, 'jasmine/headless/coffee_script_cache' + autoload :SpecFileAnalyzer, 'jasmine/headless/spec_file_analyzer' + autoload :CacheableAction, 'jasmine/headless/cacheable_action' end end diff --git a/lib/jasmine/files_list.rb b/lib/jasmine/files_list.rb index 21ed3ce..def12b8 100644 --- a/lib/jasmine/files_list.rb +++ b/lib/jasmine/files_list.rb @@ -12,22 +12,6 @@ module Jasmine File.expand_path('../../../jasmine/jasmine.headless-reporter.js', __FILE__) ] - class << self - def get_spec_line_numbers(file) - line_numbers = {} - - ic = Iconv.new('UTF-8//IGNORE', 'UTF-8') - file.lines.each_with_index.each { |line, index| - line = ic.iconv(line + ' ')[0..-2] - if description = line[%r{(describe|context|it)[( ]*(["'])(.*)\2}, 3] - (line_numbers[description] ||= []) << (index + 1) - end - } - - line_numbers - end - end - def initialize(options = {}) @options = options @files = DEFAULT_FILES.dup @@ -56,7 +40,7 @@ module Jasmine def spec_file_line_numbers @spec_file_line_numbers ||= Hash[@spec_files.collect { |file| if File.exist?(file) - if !(lines = self.class.get_spec_line_numbers(File.read(file))).empty? + if !(lines = Jasmine::Headless::SpecFileAnalyzer.for(file)).empty? [ file, lines ] end else @@ -105,7 +89,7 @@ module Jasmine @files += found_files if searches == 'spec_files' - @spec_files = @files + spec_filter + @spec_files += spec_filter end @filtered_files += (if searches == 'spec_files' diff --git a/lib/jasmine/headless/cacheable_action.rb b/lib/jasmine/headless/cacheable_action.rb new file mode 100644 index 0000000..1b7e474 --- /dev/null +++ b/lib/jasmine/headless/cacheable_action.rb @@ -0,0 +1,77 @@ +module Jasmine::Headless + class CacheableAction + class << self + def enabled=(bool) + @enabled = bool + end + + def enabled? + @enabled = true if @enabled == nil + @enabled + end + + def cache_type + raise ArgumentError.new("No cache type defined for #{self.name}") if @cache_type == nil + @cache_type + end + + def cache_type=(type) + @cache_type = type + end + + def cache_dir=(dir) + @cache_dir = dir + end + + def cache_dir + @cache_dir ||= '.jhw-cache' + end + + def for(file) + new(file).handle + end + end + + attr_reader :file + + def initialize(file) + @file = file + end + + def handle + if CacheableAction.enabled? + if fresh? + unserialize(File.read(cache_file)) + else + result = action + FileUtils.mkdir_p File.split(cache_file).first + File.open(cache_file, 'wb') { |fh| fh.print serialize(result) } + result + end + else + action + end + end + + def cache_file + @cache_file ||= File.join(self.class.cache_dir, self.class.cache_type, Digest::SHA1.hexdigest(file)) + end + + def fresh? + File.exist?(cache_file) && (File.mtime(file) < File.mtime(cache_file)) + end + + def action + raise StandardError.new("Override action") + end + + def serialize(data) + data + end + + def unserialize(data) + data + end + end +end + diff --git a/lib/jasmine/headless/coffee_script_cache.rb b/lib/jasmine/headless/coffee_script_cache.rb index 5a1b103..5ae5efe 100644 --- a/lib/jasmine/headless/coffee_script_cache.rb +++ b/lib/jasmine/headless/coffee_script_cache.rb @@ -4,60 +4,14 @@ require 'fileutils' module Jasmine module Headless - class CoffeeScriptCache + class CoffeeScriptCache < CacheableAction class << self - def enabled=(bool) - @enabled = bool - end - - def enabled? - @enabled = true if @enabled == nil - @enabled - end - - def cache_dir=(dir) - @cache_dir = dir - end - - def cache_dir - @cache_dir ||= '.jhw-cache' - end - - def for(file) - new(file).handle + def cache_type + "coffee_script" end end - attr_reader :file - - def initialize(file) - @file = file - end - - def handle - if self.class.enabled? - if fresh? - File.read(cache_file) - else - result = compile - FileUtils.mkdir_p self.class.cache_dir - File.open(cache_file, 'wb') { |fh| fh.print result } - result - end - else - compile - end - end - - def cache_file - @cache_file ||= File.join(self.class.cache_dir, Digest::SHA1.hexdigest(file)) - end - - def fresh? - File.exist?(cache_file) && (File.mtime(file) < File.mtime(cache_file)) - end - - def compile + def action CoffeeScript.compile(File.read(file)) end end diff --git a/lib/jasmine/headless/runner.rb b/lib/jasmine/headless/runner.rb index 7f7613b..672a8c6 100644 --- a/lib/jasmine/headless/runner.rb +++ b/lib/jasmine/headless/runner.rb @@ -61,7 +61,7 @@ module Jasmine end def run - Jasmine::Headless::CoffeeScriptCache.enabled = @options[:enable_cache] + Jasmine::Headless::CacheableAction.enabled = @options[:enable_cache] files_list = Jasmine::FilesList.new( :config => jasmine_config, diff --git a/lib/jasmine/headless/spec_file_analyzer.rb b/lib/jasmine/headless/spec_file_analyzer.rb new file mode 100644 index 0000000..252b067 --- /dev/null +++ b/lib/jasmine/headless/spec_file_analyzer.rb @@ -0,0 +1,37 @@ +require 'iconv' +require 'multi_json' + +module Jasmine::Headless + class SpecFileAnalyzer < CacheableAction + class << self + def cache_type + "spec_file_analysis" + end + end + + def action + line_numbers = {} + + ic = Iconv.new('UTF-8//IGNORE', 'US-ASCII') + data = ic.iconv(File.read(file) + ' ')[0..-2] + data.force_encoding('US-ASCII') if data.respond_to?(:force_encoding) + + data.lines.each_with_index.each { |line, index| + if description = line[%r{(describe|context|it)[( ]*(["'])(.*)\2}, 3] + (line_numbers[description] ||= []) << (index + 1) + end + } + + line_numbers + end + + def serialize(data) + MultiJson.encode(data) + end + + def unserialize(data) + MultiJson.decode(data) + end + end +end + diff --git a/spec/bin/jasmine-headless-webkit_spec.rb b/spec/bin/jasmine-headless-webkit_spec.rb index 37a4fbf..9bd3765 100644 --- a/spec/bin/jasmine-headless-webkit_spec.rb +++ b/spec/bin/jasmine-headless-webkit_spec.rb @@ -120,7 +120,6 @@ describe "jasmine-headless-webkit" do describe 'files' do it 'should list all the files that will be found' do files = %x{bin/jasmine-headless-webkit -l -j spec/jasmine/success/success.yml} - p files $?.exitstatus.should == 0 files.lines.to_a.should include("./spec/jasmine/success/success.js\n") diff --git a/spec/lib/jasmine/files_list_spec.rb b/spec/lib/jasmine/files_list_spec.rb index 9daaade..39bc53a 100644 --- a/spec/lib/jasmine/files_list_spec.rb +++ b/spec/lib/jasmine/files_list_spec.rb @@ -182,50 +182,6 @@ describe Jasmine::FilesList do end end - describe '.get_spec_line_numbers' do - let(:line_numbers) do - described_class.get_spec_line_numbers(file) - end - - context 'coffeescript' do - let(:file) do - <<-SPEC -describe 'test', -> - context 'yes', -> - it 'should do something', -> - "yes" - "PR.registerLangHandler(PR.createSimpleLexer([[\"com\",/^#[^\\n\\r]*/,null,\"#\"],[\"pln\",/^[\\t\\n\\r \\xa0]+/,null,\"\\t\\n\\r \xC2\\xa0\"],[\"str\",/^\"(?:[^\"\\\\]|\\\\[\\S\\s])*(?:\"|$)/,null,'\"']],[[\"kwd\",/^(?:ADS|AD|AUG|BZF|BZMF|CAE|CAF|CA|CCS|COM|CS|DAS|DCA|DCOM|DCS|DDOUBL|DIM|DOUBLE|DTCB|DTCF|DV|DXCH|EDRUPT|EXTEND|INCR|INDEX|NDX|INHINT|LXCH|MASK|MSK|MP|MSU|NOOP|OVSK|QXCH|RAND|READ|RELINT|RESUME|RETURN|ROR|RXOR|SQUARE|SU|TCR|TCAA|OVSK|TCF|TC|TS|WAND|WOR|WRITE|XCH|XLQ|XXALQ|ZL|ZQ|ADD|ADZ|SUB|SUZ|MPY|MPR|MPZ|DVP|COM|ABS|CLA|CLZ|LDQ|STO|STQ|ALS|LLS|LRS|TRA|TSQ|TMI|TOV|AXT|TIX|DLY|INP|OUT)\\s/,\n" - SPEC - end - - it 'should get the line numbers' do - line_numbers['test'].should == [ 1 ] - line_numbers['yes'].should == [ 2 ] - line_numbers['should do something'].should == [ 3 ] - end - end - - context 'javascript' do - let(:file) do - <<-SPEC -describe('test', function() { - context('yes', function() { - it('should do something', function() { - - }); - }); -}); - SPEC - end - - it 'should get the line numbers' do - line_numbers['test'].should == [ 1 ] - line_numbers['yes'].should == [ 2 ] - line_numbers['should do something'].should == [ 3 ] - end - end - end - describe '#spec_file_line_numbers' do include FakeFS::SpecHelpers diff --git a/spec/lib/jasmine/headless/cacheable_action_spec.rb b/spec/lib/jasmine/headless/cacheable_action_spec.rb new file mode 100644 index 0000000..5e55a91 --- /dev/null +++ b/spec/lib/jasmine/headless/cacheable_action_spec.rb @@ -0,0 +1,88 @@ +require 'spec_helper' + +describe Jasmine::Headless::CacheableAction do + include FakeFS::SpecHelpers + + let(:file) { 'file.whatever' } + let(:data) { 'data' } + let(:compiled) { 'compiled' } + + before do + File.open(file, 'wb') { |fh| fh.print(data) } + described_class.cache_dir = cache_dir + described_class.cache_type = cache_type + end + + let(:action_runs!) do + described_class.any_instance.expects(:action).returns(compiled) + end + + let(:cache_type) { 'action' } + let(:cache_dir) { 'cache' } + let(:cache_file) { File.join(cache_dir, cache_type, Digest::SHA1.hexdigest(file)) } + let(:cache_file_data) { YAML.load(File.read(cache_file)) } + + describe '.for' do + context 'cache disabled' do + before do + described_class.enabled = false + end + + it 'should compile' do + action_runs! + described_class.for(file).should == compiled + cache_file.should_not be_a_file + end + end + + context 'cache enabled' do + before do + described_class.enabled = true + FileUtils.mkdir_p(cache_dir) + + File.stubs(:mtime).with(file).returns(Time.at(10)) + File.stubs(:mtime).with(cache_file).returns(Time.at(cache_file_mtime)) + end + + context 'cache empty' do + let(:cache_file_mtime) { 0 } + + it 'should compile' do + action_runs! + described_class.for(file).should == compiled + + cache_file_data.should == compiled + end + end + + context 'cache fresh' do + let(:cache_file_mtime) { 15 } + + before do + File.open(cache_file, 'wb') { |fh| fh.print compiled } + end + + it 'should not compile' do + action_runs!.never + + described_class.for(file).should == compiled + + cache_file_data.should == compiled + end + end + + context 'cache stale' do + let(:cache_file_mtime) { 5 } + + it 'should compile' do + action_runs! + + described_class.for(file).should == compiled + + cache_file_data.should == compiled + end + end + end + end +end + diff --git a/spec/lib/jasmine/headless/coffee_script_cache_spec.rb b/spec/lib/jasmine/headless/coffee_script_cache_spec.rb index 9629a00..9952270 100644 --- a/spec/lib/jasmine/headless/coffee_script_cache_spec.rb +++ b/spec/lib/jasmine/headless/coffee_script_cache_spec.rb @@ -3,84 +3,18 @@ require 'spec_helper' describe Jasmine::Headless::CoffeeScriptCache do include FakeFS::SpecHelpers - let(:file) { 'file.coffee' } - let(:data) { 'data' } - let(:compiled) { 'compiled' } + describe '#action' do + let(:file) { 'file' } + let(:data) { 'data' } + let(:compiled) { 'compiled' } - before do - File.open(file, 'wb') { |fh| fh.print(data) } - described_class.cache_dir = cache_dir - end - - let(:coffee_script_compiles!) do - CoffeeScript.expects(:compile).with(data).returns(compiled) - end - - let(:cache_dir) { 'cache' } - let(:cache_file) { File.join(cache_dir, Digest::SHA1.hexdigest(file)) } - let(:cache_file_data) { File.read(cache_file) } - - describe '.for' do - context 'cache disabled' do - before do - described_class.enabled = false - p described_class.enabled? - end - - it 'should compile' do - coffee_script_compiles! - described_class.for(file).should == compiled - cache_file.should_not be_a_file - end + before do + CoffeeScript.expects(:compile).with(data).returns(compiled) + File.open(file, 'wb') { |fh| fh.print(data) } end - context 'cache enabled' do - before do - described_class.enabled = true - FileUtils.mkdir_p(cache_dir) - - File.stubs(:mtime).with(file).returns(Time.at(10)) - File.stubs(:mtime).with(cache_file).returns(Time.at(cache_file_mtime)) - end - - context 'cache empty' do - let(:cache_file_mtime) { 0 } - - it 'should compile' do - coffee_script_compiles! - described_class.for(file).should == compiled - - cache_file_data.should == compiled - end - end - - context 'cache fresh' do - let(:cache_file_mtime) { 15 } - - before do - File.open(cache_file, 'wb') { |fh| fh.print compiled } - end - - it 'should not compile' do - coffee_script_compiles!.never - - described_class.for(file).should == compiled - - cache_file_data.should == compiled - end - end - - context 'cache stale' do - let(:cache_file_mtime) { 5 } - - it 'should compile' do - coffee_script_compiles! - - described_class.for(file).should == compiled - - cache_file_data.should == compiled - end - end + it 'should compile coffeescript' do + described_class.new(file).action.should == compiled end end end diff --git a/spec/lib/jasmine/headless/spec_file_analyzer_spec.rb b/spec/lib/jasmine/headless/spec_file_analyzer_spec.rb new file mode 100644 index 0000000..fbde25c --- /dev/null +++ b/spec/lib/jasmine/headless/spec_file_analyzer_spec.rb @@ -0,0 +1,57 @@ +require 'spec_helper' + +describe Jasmine::Headless::SpecFileAnalyzer do + include FakeFS::SpecHelpers + + let(:file) { 'file' } + let(:analyzer) { described_class.new(file) } + + describe '#action' do + let(:line_numbers) do + analyzer.action + end + + before do + File.open(file, 'wb') { |fh| fh.print file_data } + end + + context 'coffeescript' do + let(:file_data) do + <<-SPEC +describe 'test', -> + context 'yes', -> + it 'should do something', -> + "yes" + "PR.registerLangHandler(PR.createSimpleLexer([[\"com\",/^#[^\\n\\r]*/,null,\"#\"],[\"pln\",/^[\\t\\n\\r \\xa0]+/,null,\"\\t\\n\\r \xC2\\xa0\"],[\"str\",/^\"(?:[^\"\\\\]|\\\\[\\S\\s])*(?:\"|$)/,null,'\"']],[[\"kwd\",/^(?:ADS|AD|AUG|BZF|BZMF|CAE|CAF|CA|CCS|COM|CS|DAS|DCA|DCOM|DCS|DDOUBL|DIM|DOUBLE|DTCB|DTCF|DV|DXCH|EDRUPT|EXTEND|INCR|INDEX|NDX|INHINT|LXCH|MASK|MSK|MP|MSU|NOOP|OVSK|QXCH|RAND|READ|RELINT|RESUME|RETURN|ROR|RXOR|SQUARE|SU|TCR|TCAA|OVSK|TCF|TC|TS|WAND|WOR|WRITE|XCH|XLQ|XXALQ|ZL|ZQ|ADD|ADZ|SUB|SUZ|MPY|MPR|MPZ|DVP|COM|ABS|CLA|CLZ|LDQ|STO|STQ|ALS|LLS|LRS|TRA|TSQ|TMI|TOV|AXT|TIX|DLY|INP|OUT)\\s/,\n" +SPEC + end + + it 'should get the line numbers' do + line_numbers['test'].should == [ 1 ] + line_numbers['yes'].should == [ 2 ] + line_numbers['should do something'].should == [ 3 ] + end + end + + context 'javascript' do + let(:file_data) do + <<-SPEC +describe('test', function() { + context('yes', function() { + it('should do something', function() { + + }); + }); +}); +SPEC + end + + it 'should get the line numbers' do + line_numbers['test'].should == [ 1 ] + line_numbers['yes'].should == [ 2 ] + line_numbers['should do something'].should == [ 3 ] + end + end + end +end + diff --git a/spec/spec_helper.rb b/spec/spec_helper.rb index 0fcd858..472d170 100644 --- a/spec/spec_helper.rb +++ b/spec/spec_helper.rb @@ -3,6 +3,10 @@ require 'fakefs/spec_helpers' RSpec.configure do |c| c.mock_with :mocha + + c.before(:each) do + Jasmine::Headless::CacheableAction.enabled = false + end end specrunner = 'ext/jasmine-webkit-specrunner/jasmine-webkit-specrunner' diff --git a/specrunner.104.filter.html b/specrunner.104.filter.html new file mode 100644 index 0000000..e69de29 diff --git a/specrunner.123.filter.html b/specrunner.123.filter.html new file mode 100644 index 0000000..e69de29 diff --git a/specrunner.137.filter.html b/specrunner.137.filter.html new file mode 100644 index 0000000..e69de29 diff --git a/specrunner.151.filter.html b/specrunner.151.filter.html new file mode 100644 index 0000000..e69de29 diff --git a/specrunner.165.filter.html b/specrunner.165.filter.html new file mode 100644 index 0000000..e69de29 diff --git a/specrunner.835.filter.html b/specrunner.835.filter.html new file mode 100644 index 0000000..e69de29 diff --git a/specrunner.849.filter.html b/specrunner.849.filter.html new file mode 100644 index 0000000..e69de29 diff --git a/specrunner.863.filter.html b/specrunner.863.filter.html new file mode 100644 index 0000000..e69de29 diff --git a/specrunner.877.filter.html b/specrunner.877.filter.html new file mode 100644 index 0000000..e69de29 diff --git a/specrunner.891.filter.html b/specrunner.891.filter.html new file mode 100644 index 0000000..e69de29 diff --git a/specrunner.99208.filter.html b/specrunner.99208.filter.html new file mode 100644 index 0000000..e69de29 diff --git a/specrunner.99222.filter.html b/specrunner.99222.filter.html new file mode 100644 index 0000000..e69de29 diff --git a/specrunner.99236.filter.html b/specrunner.99236.filter.html new file mode 100644 index 0000000..e69de29 diff --git a/specrunner.99250.filter.html b/specrunner.99250.filter.html new file mode 100644 index 0000000..e69de29 diff --git a/specrunner.99264.filter.html b/specrunner.99264.filter.html new file mode 100644 index 0000000..e69de29 From 23bd56ee21bf14e3bb6160b23bb9b8716fcf629d Mon Sep 17 00:00:00 2001 From: John Bintz Date: Thu, 1 Sep 2011 10:41:06 -0400 Subject: [PATCH 4/6] remove a bunch of specrunners --- specrunner.104.filter.html | 0 specrunner.123.filter.html | 0 specrunner.137.filter.html | 0 specrunner.151.filter.html | 0 specrunner.165.filter.html | 0 specrunner.835.filter.html | 0 specrunner.849.filter.html | 0 specrunner.863.filter.html | 0 specrunner.877.filter.html | 0 specrunner.891.filter.html | 0 specrunner.99208.filter.html | 0 specrunner.99222.filter.html | 0 specrunner.99236.filter.html | 0 specrunner.99250.filter.html | 0 specrunner.99264.filter.html | 0 15 files changed, 0 insertions(+), 0 deletions(-) delete mode 100644 specrunner.104.filter.html delete mode 100644 specrunner.123.filter.html delete mode 100644 specrunner.137.filter.html delete mode 100644 specrunner.151.filter.html delete mode 100644 specrunner.165.filter.html delete mode 100644 specrunner.835.filter.html delete mode 100644 specrunner.849.filter.html delete mode 100644 specrunner.863.filter.html delete mode 100644 specrunner.877.filter.html delete mode 100644 specrunner.891.filter.html delete mode 100644 specrunner.99208.filter.html delete mode 100644 specrunner.99222.filter.html delete mode 100644 specrunner.99236.filter.html delete mode 100644 specrunner.99250.filter.html delete mode 100644 specrunner.99264.filter.html diff --git a/specrunner.104.filter.html b/specrunner.104.filter.html deleted file mode 100644 index e69de29..0000000 diff --git a/specrunner.123.filter.html b/specrunner.123.filter.html deleted file mode 100644 index e69de29..0000000 diff --git a/specrunner.137.filter.html b/specrunner.137.filter.html deleted file mode 100644 index e69de29..0000000 diff --git a/specrunner.151.filter.html b/specrunner.151.filter.html deleted file mode 100644 index e69de29..0000000 diff --git a/specrunner.165.filter.html b/specrunner.165.filter.html deleted file mode 100644 index e69de29..0000000 diff --git a/specrunner.835.filter.html b/specrunner.835.filter.html deleted file mode 100644 index e69de29..0000000 diff --git a/specrunner.849.filter.html b/specrunner.849.filter.html deleted file mode 100644 index e69de29..0000000 diff --git a/specrunner.863.filter.html b/specrunner.863.filter.html deleted file mode 100644 index e69de29..0000000 diff --git a/specrunner.877.filter.html b/specrunner.877.filter.html deleted file mode 100644 index e69de29..0000000 diff --git a/specrunner.891.filter.html b/specrunner.891.filter.html deleted file mode 100644 index e69de29..0000000 diff --git a/specrunner.99208.filter.html b/specrunner.99208.filter.html deleted file mode 100644 index e69de29..0000000 diff --git a/specrunner.99222.filter.html b/specrunner.99222.filter.html deleted file mode 100644 index e69de29..0000000 diff --git a/specrunner.99236.filter.html b/specrunner.99236.filter.html deleted file mode 100644 index e69de29..0000000 diff --git a/specrunner.99250.filter.html b/specrunner.99250.filter.html deleted file mode 100644 index e69de29..0000000 diff --git a/specrunner.99264.filter.html b/specrunner.99264.filter.html deleted file mode 100644 index e69de29..0000000 From 8b8fc32f80b94da1b02127b3a3553f88569326b9 Mon Sep 17 00:00:00 2001 From: John Bintz Date: Fri, 2 Sep 2011 10:49:15 -0400 Subject: [PATCH 5/6] change how includes work and shuffle things around --- bin/jasmine-headless-webkit | 1 + jasmine-headless-webkit.gemspec | 4 ++-- lib/jasmine-headless-webkit.rb | 9 +++++++++ lib/jasmine-headless-webkit/version.rb | 7 ------- lib/jasmine/files_list.rb | 1 - lib/jasmine/headless/railtie.rb | 2 -- lib/jasmine/headless/runner.rb | 6 ------ lib/jasmine/headless/task.rb | 2 -- lib/jasmine/headless/version.rb | 5 +++++ 9 files changed, 17 insertions(+), 20 deletions(-) delete mode 100644 lib/jasmine-headless-webkit/version.rb create mode 100644 lib/jasmine/headless/version.rb diff --git a/bin/jasmine-headless-webkit b/bin/jasmine-headless-webkit index 8d48998..2988f6c 100755 --- a/bin/jasmine-headless-webkit +++ b/bin/jasmine-headless-webkit @@ -9,6 +9,7 @@ end $:.unshift(File.join(gem_dir, 'lib')) require 'jasmine-headless-webkit' + require 'jasmine/headless/errors' require 'jasmine/headless/runner' require 'jasmine/headless/options' diff --git a/jasmine-headless-webkit.gemspec b/jasmine-headless-webkit.gemspec index 17aeb06..834f207 100644 --- a/jasmine-headless-webkit.gemspec +++ b/jasmine-headless-webkit.gemspec @@ -1,10 +1,10 @@ # -*- encoding: utf-8 -*- $:.push File.expand_path("../lib", __FILE__) -require "jasmine-headless-webkit/version" +require "jasmine/headless/version" Gem::Specification.new do |s| s.name = "jasmine-headless-webkit" - s.version = Jasmine::Headless::Webkit::VERSION + s.version = Jasmine::Headless::VERSION s.platform = Gem::Platform::RUBY s.authors = ["John Bintz", "Sencha Inc.", "Pivotal Labs"] s.email = ["john@coswellproductions.com"] diff --git a/lib/jasmine-headless-webkit.rb b/lib/jasmine-headless-webkit.rb index 9626790..561a8a1 100644 --- a/lib/jasmine-headless-webkit.rb +++ b/lib/jasmine-headless-webkit.rb @@ -1,10 +1,19 @@ module Jasmine + autoload :FilesList, 'jasmine/files_list' + autoload :TemplateWriter, 'jasmine/template_writer' + module Headless autoload :CoffeeScriptCache, 'jasmine/headless/coffee_script_cache' autoload :SpecFileAnalyzer, 'jasmine/headless/spec_file_analyzer' autoload :CacheableAction, 'jasmine/headless/cacheable_action' + autoload :VERSION, 'jasmine/headless/version' + autoload :Runner, 'jasmine/headless/runner' + autoload :Options, 'jasmine/headless/options' + autoload :Task, 'jasmine/headless/task' end end +require 'jasmine/headless/errors' + require 'jasmine/headless/railtie' if defined?(Rails) && Rails::VERSION::MAJOR >= 3 diff --git a/lib/jasmine-headless-webkit/version.rb b/lib/jasmine-headless-webkit/version.rb deleted file mode 100644 index b429569..0000000 --- a/lib/jasmine-headless-webkit/version.rb +++ /dev/null @@ -1,7 +0,0 @@ -module Jasmine - module Headless - module Webkit - VERSION = "0.6.4" - end - end -end diff --git a/lib/jasmine/files_list.rb b/lib/jasmine/files_list.rb index def12b8..0201cd8 100644 --- a/lib/jasmine/files_list.rb +++ b/lib/jasmine/files_list.rb @@ -1,4 +1,3 @@ -require 'jasmine/headless/coffee_script_cache' require 'jasmine-core' require 'iconv' diff --git a/lib/jasmine/headless/railtie.rb b/lib/jasmine/headless/railtie.rb index 02441c4..5af2660 100644 --- a/lib/jasmine/headless/railtie.rb +++ b/lib/jasmine/headless/railtie.rb @@ -1,5 +1,3 @@ -require 'jasmine/headless/task' - module Jasmine module Headless class Railtie < Rails::Railtie diff --git a/lib/jasmine/headless/runner.rb b/lib/jasmine/headless/runner.rb index 672a8c6..7791103 100644 --- a/lib/jasmine/headless/runner.rb +++ b/lib/jasmine/headless/runner.rb @@ -1,14 +1,8 @@ -require 'jasmine/headless/errors' -require 'jasmine/headless/options' - require 'fileutils' require 'coffee-script' require 'rainbow' -require 'jasmine/files_list' -require 'jasmine/template_writer' - require 'yaml' module Jasmine diff --git a/lib/jasmine/headless/task.rb b/lib/jasmine/headless/task.rb index 113030e..d6456a2 100644 --- a/lib/jasmine/headless/task.rb +++ b/lib/jasmine/headless/task.rb @@ -1,5 +1,3 @@ -require 'jasmine/headless/runner' - module Digest class JasmineTest def self.file(file) diff --git a/lib/jasmine/headless/version.rb b/lib/jasmine/headless/version.rb new file mode 100644 index 0000000..8fd51dc --- /dev/null +++ b/lib/jasmine/headless/version.rb @@ -0,0 +1,5 @@ +module Jasmine + module Headless + VERSION = "0.6.4" + end +end From b21573b1dc535006dc3480b1ef0105837daca4b3 Mon Sep 17 00:00:00 2001 From: John Bintz Date: Fri, 2 Sep 2011 11:31:58 -0400 Subject: [PATCH 6/6] fix a bug and give a message when the cache is building --- lib/jasmine/files_list.rb | 12 +++++++++++- spec/lib/jasmine/files_list_spec.rb | 1 + 2 files changed, 12 insertions(+), 1 deletion(-) diff --git a/lib/jasmine/files_list.rb b/lib/jasmine/files_list.rb index 0201cd8..fc482c8 100644 --- a/lib/jasmine/files_list.rb +++ b/lib/jasmine/files_list.rb @@ -1,5 +1,6 @@ require 'jasmine-core' require 'iconv' +require 'time' module Jasmine class FilesList @@ -11,6 +12,8 @@ module Jasmine File.expand_path('../../../jasmine/jasmine.headless-reporter.js', __FILE__) ] + PLEASE_WAIT_IM_WORKING_TIME = 2 + def initialize(options = {}) @options = options @files = DEFAULT_FILES.dup @@ -50,7 +53,14 @@ module Jasmine 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 + case File.extname(file) when '.coffee' begin @@ -67,7 +77,7 @@ module Jasmine when '.css' %{} end - }.flatten.reject(&:empty?) + }.flatten.compact.reject(&:empty?) end def spec_filter diff --git a/spec/lib/jasmine/files_list_spec.rb b/spec/lib/jasmine/files_list_spec.rb index 39bc53a..324ee62 100644 --- a/spec/lib/jasmine/files_list_spec.rb +++ b/spec/lib/jasmine/files_list_spec.rb @@ -151,6 +151,7 @@ describe Jasmine::FilesList do files_list.instance_variable_set(:@files, [ 'test.js', 'test.coffee', + 'test.whatever', 'test.css' ])