From 24a8bb7825ddb34f08540c1d6e38306c475fcd35 Mon Sep 17 00:00:00 2001 From: Christian Williams Date: Sun, 27 Dec 2009 11:54:54 -0600 Subject: [PATCH 01/16] Switch to jasmine remove-contrib branch. --- jasmine | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/jasmine b/jasmine index 701ee71..a16cbe7 160000 --- a/jasmine +++ b/jasmine @@ -1 +1 @@ -Subproject commit 701ee719e6e1e7d9f2ac84707302cb430ac123e4 +Subproject commit a16cbe7e5b1582fac691fdf5fa77224417f621e9 From 1f50e2b2fb6dd7b2a54b95434dbd3fa315ac996c Mon Sep 17 00:00:00 2001 From: Christian Williams Date: Sun, 27 Dec 2009 14:39:37 -0600 Subject: [PATCH 02/16] Version bump to 0.2.0 --- Gemfile | 0 VERSION.yml | 5 +++-- geminstaller.yml | 6 ------ 3 files changed, 3 insertions(+), 8 deletions(-) create mode 100644 Gemfile delete mode 100644 geminstaller.yml diff --git a/Gemfile b/Gemfile new file mode 100644 index 0000000..e69de29 diff --git a/VERSION.yml b/VERSION.yml index 92d1d86..a366aa7 100644 --- a/VERSION.yml +++ b/VERSION.yml @@ -1,4 +1,5 @@ ---- -:minor: 1 +--- +:minor: 2 +:build: :patch: 0 :major: 0 diff --git a/geminstaller.yml b/geminstaller.yml deleted file mode 100644 index f33b27a..0000000 --- a/geminstaller.yml +++ /dev/null @@ -1,6 +0,0 @@ ---- -gems: -- name: rake - version: 0.8.7 -- name: jeweler - version: 1.4.0 From dd0e3e5cf1f507a1a0dbb8fcd110afaa61e27682 Mon Sep 17 00:00:00 2001 From: Christian Williams Date: Sun, 27 Dec 2009 14:41:20 -0600 Subject: [PATCH 03/16] Version bump to 0.0.0 --- VERSION.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/VERSION.yml b/VERSION.yml index a366aa7..54ce9e4 100644 --- a/VERSION.yml +++ b/VERSION.yml @@ -1,5 +1,5 @@ --- -:minor: 2 +:minor: 0 :build: :patch: 0 :major: 0 From 81748d166da5355c62fc44f6fb6c443014237c5d Mon Sep 17 00:00:00 2001 From: Christian Williams Date: Sun, 27 Dec 2009 14:41:29 -0600 Subject: [PATCH 04/16] Version bump to 0.1.0 --- VERSION.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/VERSION.yml b/VERSION.yml index 54ce9e4..a080362 100644 --- a/VERSION.yml +++ b/VERSION.yml @@ -1,5 +1,5 @@ --- -:minor: 0 +:minor: 1 :build: :patch: 0 :major: 0 From ffb69b4bde5b06a2e835ef08ca05d8ac3fca0651 Mon Sep 17 00:00:00 2001 From: Christian Williams Date: Sun, 27 Dec 2009 14:41:33 -0600 Subject: [PATCH 05/16] Version bump to 0.1.1 --- VERSION.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/VERSION.yml b/VERSION.yml index a080362..2047f7e 100644 --- a/VERSION.yml +++ b/VERSION.yml @@ -1,5 +1,5 @@ --- :minor: 1 :build: -:patch: 0 +:patch: 1 :major: 0 From 945b167131f1ace0d483fbf89213c4c6313cadc2 Mon Sep 17 00:00:00 2001 From: Christian Williams Date: Sun, 27 Dec 2009 14:49:06 -0600 Subject: [PATCH 06/16] Version bump to 0.1.2 --- VERSION.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/VERSION.yml b/VERSION.yml index 2047f7e..a375942 100644 --- a/VERSION.yml +++ b/VERSION.yml @@ -1,5 +1,5 @@ --- :minor: 1 :build: -:patch: 1 +:patch: 2 :major: 0 From 0c8258996e5125224d77f11579454c5917189ea6 Mon Sep 17 00:00:00 2001 From: Christian Williams Date: Mon, 28 Dec 2009 12:08:23 -0600 Subject: [PATCH 07/16] Rearrange, refactor, ruin and raze. --- Gemfile | 11 +++ Rakefile | 82 ++++++++++++++----- jasmine-ruby.gemspec | 21 ++--- lib/jasmine-ruby.rb | 3 - lib/jasmine.rb | 3 + .../jasmine_helper.rb | 2 +- .../jasmine_meta_spec.rb | 0 .../jasmine_runner.rb | 32 ++++---- .../jasmine_spec_builder.rb | 4 +- lib/{jasmine-ruby => jasmine}/run.html | 0 spec/jasmine_self_test_runner.rb | 27 ++++++ spec/jasmine_spec.rb | 16 +--- templates/Rakefile | 2 +- 13 files changed, 136 insertions(+), 67 deletions(-) delete mode 100644 lib/jasmine-ruby.rb create mode 100644 lib/jasmine.rb rename lib/{jasmine-ruby => jasmine}/jasmine_helper.rb (94%) rename lib/{jasmine-ruby => jasmine}/jasmine_meta_spec.rb (100%) rename lib/{jasmine-ruby => jasmine}/jasmine_runner.rb (92%) rename lib/{jasmine-ruby => jasmine}/jasmine_spec_builder.rb (98%) rename lib/{jasmine-ruby => jasmine}/run.html (100%) create mode 100644 spec/jasmine_self_test_runner.rb diff --git a/Gemfile b/Gemfile index e69de29..3dd5c29 100644 --- a/Gemfile +++ b/Gemfile @@ -0,0 +1,11 @@ +gem "rake", "0.8.7" +gem "jeweler", "1.4.0" +gem "gemcutter", "0.2.1" + +gem "rspec", ">= 1.1.5", :only => :testing +gem "rack", ">= 1.0.0", :only => :testing +gem "thin", ">= 1.2.4", :only => :testing +gem "selenium-rc", ">=2.1.0", :only => :testing +gem "selenium-client", ">=1.2.17", :only => :testing + +disable_system_gems \ No newline at end of file diff --git a/Rakefile b/Rakefile index 10c3822..d5dd5d9 100644 --- a/Rakefile +++ b/Rakefile @@ -1,24 +1,66 @@ -namespace :jeweler do +require "#{File.dirname(__FILE__)}/vendor/gems/environment" +Bundler.require_env :rake - begin - require 'jeweler' - require 'rake' - Jeweler::Tasks.new do |gemspec| - gemspec.name = "jasmine-ruby" - gemspec.summary = "Jasmine Ruby" - gemspec.description = "Javascript BDD testings" - gemspec.email = "ragaskar@gmail.com" - gemspec.homepage = "http://github.com/ragaskar/jasmine-ruby" - gemspec.description = "Jasmine Ruby" - gemspec.authors = ["Rajan Agaskar"] - gemspec.files = FileList.new('bin/*', 'lib/**/**', 'jasmine/lib/**', 'jasmine/contrib/ruby/**', 'tasks/**', 'templates/**') +$LOAD_PATH.unshift File.expand_path("#{File.dirname(__FILE__)}/lib") - gemspec.add_dependency('rspec', '>= 1.1.5') - gemspec.add_dependency('rack', '>= 1.0.0') - gemspec.add_dependency('thin', '>= 1.2.4') - end - Jeweler::GemcutterTasks.new - rescue LoadError - puts "Jeweler not available. Install it with: sudo gem install technicalpickles-jeweler -s http://gems.github.com" +require 'spec' +require 'spec/rake/spectask' + +desc "Run all examples" +Spec::Rake::SpecTask.new('spec') do |t| + t.spec_files = FileList['spec/**/*.rb'] +end + +namespace :jasmine do +# require 'jasmine' + require 'spec/jasmine_self_test_runner' + +# desc "Run continuous integration tests" +# require "spec" +# require 'spec/rake/spectask' +# Spec::Rake::SpecTask.new(:ci) do |t| +# t.spec_opts = ["--color", "--format", "specdoc"] +# t.verbose = true +# t.spec_files = [JasmineHelper.meta_spec_path] +# end + + task :server do + puts "your tests are here:" + puts " http://localhost:8888/run.html" + + JasmineSelfTestRunner.new.start_server end end + +desc "Run specs via server" +task :jasmine => ['jasmine:server'] + + +namespace :jeweler do + + unless File.exists?('jasmine/lib') + raise "Jasmine submodule isn't present. Run git submodule init && git submodule update." + end + + require 'jeweler' + require 'rake' + + Jeweler::Tasks.new do |gemspec| + gemspec.name = "xian-test-jasmine" + gemspec.summary = "Jasmine Ruby" + gemspec.description = "Javascript BDD testings" + gemspec.email = "ragaskar@gmail.com" + gemspec.homepage = "http://github.com/ragaskar/jasmine-ruby" + gemspec.description = "Jasmine Ruby" + gemspec.authors = ["Rajan Agaskar"] + gemspec.files = FileList.new('bin/*', 'lib/**/**', 'jasmine/lib/**', 'jasmine/contrib/ruby/**', 'tasks/**', 'templates/**') + + gemspec.add_dependency('rspec', '>= 1.1.5') + gemspec.add_dependency('rack', '>= 1.0.0') + gemspec.add_dependency('thin', '>= 1.2.4') + gemspec.add_dependency('selenium-rc', '>=2.1.0') + gemspec.add_dependency('selenium-client', '>=1.2.17') + end + + Jeweler::GemcutterTasks.new +end diff --git a/jasmine-ruby.gemspec b/jasmine-ruby.gemspec index 98e2f69..4d2d38a 100644 --- a/jasmine-ruby.gemspec +++ b/jasmine-ruby.gemspec @@ -4,12 +4,12 @@ # -*- encoding: utf-8 -*- Gem::Specification.new do |s| - s.name = %q{jasmine-ruby} + s.name = %q{jasmine} s.version = "0.1.0" s.required_rubygems_version = Gem::Requirement.new(">= 0") if s.respond_to? :required_rubygems_version= s.authors = ["Rajan Agaskar"] - s.date = %q{2009-11-26} + s.date = %q{2009-12-27} s.default_executable = %q{jasmine} s.description = %q{Jasmine Ruby} s.email = %q{ragaskar@gmail.com} @@ -19,26 +19,23 @@ Gem::Specification.new do |s| ] s.files = [ "bin/jasmine", - "jasmine/contrib/ruby/jasmine_runner.rb", - "jasmine/contrib/ruby/jasmine_spec_builder.rb", - "jasmine/contrib/ruby/run.html", "jasmine/lib/TrivialReporter.js", "jasmine/lib/consolex.js", "jasmine/lib/jasmine-0.10.0.js", "jasmine/lib/jasmine.css", "jasmine/lib/json2.js", - "lib/jasmine-ruby.rb", - "lib/jasmine-ruby/jasmine_helper.rb", - "lib/jasmine-ruby/jasmine_meta_spec.rb", - "lib/jasmine-ruby/jasmine_runner.rb", - "lib/jasmine-ruby/jasmine_spec_builder.rb", - "lib/jasmine-ruby/run.html", + "lib/jasmine.rb", + "lib/jasmine/jasmine_helper.rb", + "lib/jasmine/jasmine_meta_spec.rb", + "lib/jasmine/jasmine_runner.rb", + "lib/jasmine/jasmine_spec_builder.rb", + "lib/jasmine/run.html", "templates/Rakefile", "templates/example_spec.js", "templates/jasmine_helper.rb", "templates/spec_helper.js" ] - s.homepage = %q{http://github.com/ragaskar/jasmine-ruby} + s.homepage = %q{http://github.com/ragaskar/jasmine} s.rdoc_options = ["--charset=UTF-8"] s.require_paths = ["lib"] s.rubygems_version = %q{1.3.5} diff --git a/lib/jasmine-ruby.rb b/lib/jasmine-ruby.rb deleted file mode 100644 index 8f74c56..0000000 --- a/lib/jasmine-ruby.rb +++ /dev/null @@ -1,3 +0,0 @@ -require 'jasmine-ruby/jasmine_helper' -require 'jasmine-ruby/jasmine_runner' -require 'jasmine-ruby/jasmine_spec_builder' \ No newline at end of file diff --git a/lib/jasmine.rb b/lib/jasmine.rb new file mode 100644 index 0000000..c54da15 --- /dev/null +++ b/lib/jasmine.rb @@ -0,0 +1,3 @@ +require 'jasmine/jasmine_helper' +require 'jasmine/jasmine_runner' +require 'jasmine/jasmine_spec_builder' \ No newline at end of file diff --git a/lib/jasmine-ruby/jasmine_helper.rb b/lib/jasmine/jasmine_helper.rb similarity index 94% rename from lib/jasmine-ruby/jasmine_helper.rb rename to lib/jasmine/jasmine_helper.rb index 54ed746..a2c7b1d 100755 --- a/lib/jasmine-ruby/jasmine_helper.rb +++ b/lib/jasmine/jasmine_helper.rb @@ -34,7 +34,7 @@ class JasmineHelper end def self.meta_spec_path - File.expand_path(File.join(File.dirname(__FILE__), '..', '..', 'lib', 'jasmine-ruby', 'jasmine_meta_spec.rb')) + File.expand_path(File.join(File.dirname(__FILE__), '..', '..', 'lib', 'jasmine', 'jasmine_meta_spec.rb')) end def self.files diff --git a/lib/jasmine-ruby/jasmine_meta_spec.rb b/lib/jasmine/jasmine_meta_spec.rb similarity index 100% rename from lib/jasmine-ruby/jasmine_meta_spec.rb rename to lib/jasmine/jasmine_meta_spec.rb diff --git a/lib/jasmine-ruby/jasmine_runner.rb b/lib/jasmine/jasmine_runner.rb similarity index 92% rename from lib/jasmine-ruby/jasmine_runner.rb rename to lib/jasmine/jasmine_runner.rb index 40df8c8..d0903b4 100644 --- a/lib/jasmine-ruby/jasmine_runner.rb +++ b/lib/jasmine/jasmine_runner.rb @@ -148,27 +148,22 @@ module Jasmine end class SimpleServer - def self.start(port, root_path, spec_files_or_proc, options = {}) + def self.start(port, spec_files_or_proc, options = {}) require 'thin' config = { '/__suite__' => Jasmine::FocusedSuite.new(spec_files_or_proc, options), '/run.html' => Jasmine::Redirect.new('/'), '/' => Jasmine::RunAdapter.new(spec_files_or_proc, options) } - if (options[:mappings]) - options[:mappings].each do |from, to| - config[from] = Rack::File.new(to) - end + + raise "Need :mappings!" unless options[:mappings] + options[:mappings].each do |from, to| + config[from] = Rack::File.new(to) end config["/__JASMINE_ROOT__"] = Rack::File.new(Jasmine.root) - file_serve_config = { - '/' => Rack::File.new(root_path) - } - app = Rack::Cascade.new([ - Rack::URLMap.new(file_serve_config), Rack::URLMap.new(config), JsAlert.new ]) @@ -226,17 +221,24 @@ module Jasmine end class Runner - def initialize(selenium_jar_path, root_path, spec_files, options={}) - @root_path = root_path - @selenium_jar_path = selenium_jar_path + def initialize(options = {}) + require 'selenium_rc' + @selenium_jar_path = SeleniumRC::Server.allocate.jar_path @spec_files = spec_files @options = options - @browser = options[:browser] ? options[:browser].delete(:browser) : 'firefox' + @browser = options[:browser] ? options.delete(:browser) : 'firefox' @selenium_pid = nil @jasmine_server_pid = nil end + def start_server(port = 8888) + p spec_files + Jasmine::SimpleServer.start(port, lambda { spec_files }, :mappings => { + "/spec" => spec_dir + }) + end + def start start_servers @client = Jasmine::SimpleClient.new("localhost", @selenium_server_port, "*#{@browser}", "http://localhost:#{@jasmine_server_port}/") @@ -260,7 +262,7 @@ module Jasmine @jasmine_server_pid = fork do Process.setpgrp - Jasmine::SimpleServer.start(@jasmine_server_port, @root_path, @spec_files, @options) + Jasmine::SimpleServer.start(@jasmine_server_port, @spec_files, @options) exit! 0 end puts "jasmine server started. pid is #{@jasmine_server_pid}" diff --git a/lib/jasmine-ruby/jasmine_spec_builder.rb b/lib/jasmine/jasmine_spec_builder.rb similarity index 98% rename from lib/jasmine-ruby/jasmine_spec_builder.rb rename to lib/jasmine/jasmine_spec_builder.rb index e4ebfc9..b5ecad4 100644 --- a/lib/jasmine-ruby/jasmine_spec_builder.rb +++ b/lib/jasmine/jasmine_spec_builder.rb @@ -4,8 +4,8 @@ module Jasmine class SpecBuilder attr_accessor :suites - def initialize(spec_files, runner) - @spec_files = spec_files + def initialize(runner) + @spec_files = runner.spec_files @runner = runner @spec_ids = [] end diff --git a/lib/jasmine-ruby/run.html b/lib/jasmine/run.html similarity index 100% rename from lib/jasmine-ruby/run.html rename to lib/jasmine/run.html diff --git a/spec/jasmine_self_test_runner.rb b/spec/jasmine_self_test_runner.rb new file mode 100644 index 0000000..75eac41 --- /dev/null +++ b/spec/jasmine_self_test_runner.rb @@ -0,0 +1,27 @@ +require 'jasmine' + +class JasmineSelfTestRunner < Jasmine::Runner + def proj_root + File.expand_path(File.join(File.dirname(__FILE__), "..")) + end + + def src_dir + File.join(proj_root, 'src') + end + + def src_files + Dir.glob(File.join(src_dir, "**/*.js")) + end + + def spec_dir + File.join(proj_root, 'jasmine/spec') + end + + def spec_files + Dir.glob(File.join(spec_dir, "**/*[Ss]pec.js")).collect { |f| f.sub("#{spec_dir}/", "") } + end +# +# def specs +# Jasmine.cachebust(spec_files).collect {|f| f.sub(spec_dir, "/spec")} +# end +end \ No newline at end of file diff --git a/spec/jasmine_spec.rb b/spec/jasmine_spec.rb index 5f652fb..f289ac6 100644 --- a/spec/jasmine_spec.rb +++ b/spec/jasmine_spec.rb @@ -1,17 +1,7 @@ -require 'rubygems' -require "selenium_rc" +require 'jasmine_self_test_runner' -JASMINE_SPEC_DIR = File.join(File.dirname(__FILE__), "..", "jasmine", "spec") - -require File.expand_path(File.join(File.dirname(__FILE__), "..", "lib", "jasmine-ruby", "jasmine_helper.rb")) -require File.expand_path(File.join(JasmineHelper.root, "contrib/ruby/jasmine_spec_builder")) - -jasmine_runner = Jasmine::Runner.new(SeleniumRC::Server.new.jar_path, - JasmineHelper.spec_file_urls, - JasmineHelper.dir_mappings, - :spec_helpers => JasmineHelper.spec_helpers) - -spec_builder = Jasmine::SpecBuilder.new(JasmineHelper.raw_spec_files, jasmine_runner) +jasmine_runner = JasmineSelfTestRunner.new +spec_builder = Jasmine::SpecBuilder.new(jasmine_runner) should_stop = false diff --git a/templates/Rakefile b/templates/Rakefile index 9dae117..93da0dd 100644 --- a/templates/Rakefile +++ b/templates/Rakefile @@ -1,5 +1,5 @@ namespace :jasmine do - require 'jasmine-ruby' + require 'jasmine' helper_overrides = File.expand_path(File.join(File.dirname(__FILE__), "spec/helpers/jasmine_helper.rb")) if File.exist?(helper_overrides) require helper_overrides From e4a5d567e014f6904c373c4ff98f9f53d890f2b0 Mon Sep 17 00:00:00 2001 From: Christian Williams Date: Mon, 28 Dec 2009 14:00:02 -0600 Subject: [PATCH 08/16] Rearrange, start adding specs. --- Rakefile | 4 +- lib/jasmine.rb | 5 +- lib/jasmine/base.rb | 63 ++++ lib/jasmine/config.rb | 74 +++++ lib/jasmine/jasmine_runner.rb | 299 ------------------ lib/jasmine/server.rb | 179 +++++++++++ ..._runner.rb => jasmine_self_test_config.rb} | 8 +- spec/jasmine_spec.rb | 2 +- spec/server_spec.rb | 51 +++ spec/spec_helper.rb | 3 + templates/Rakefile | 2 +- 11 files changed, 385 insertions(+), 305 deletions(-) create mode 100644 lib/jasmine/base.rb create mode 100644 lib/jasmine/config.rb create mode 100644 lib/jasmine/server.rb rename spec/{jasmine_self_test_runner.rb => jasmine_self_test_config.rb} (81%) create mode 100644 spec/server_spec.rb create mode 100644 spec/spec_helper.rb diff --git a/Rakefile b/Rakefile index d5dd5d9..e572ebd 100644 --- a/Rakefile +++ b/Rakefile @@ -13,7 +13,7 @@ end namespace :jasmine do # require 'jasmine' - require 'spec/jasmine_self_test_runner' + require 'spec/jasmine_self_test_config' # desc "Run continuous integration tests" # require "spec" @@ -28,7 +28,7 @@ namespace :jasmine do puts "your tests are here:" puts " http://localhost:8888/run.html" - JasmineSelfTestRunner.new.start_server + JasmineSelfTestConfig.new.start_server end end diff --git a/lib/jasmine.rb b/lib/jasmine.rb index c54da15..1ab5139 100644 --- a/lib/jasmine.rb +++ b/lib/jasmine.rb @@ -1,3 +1,6 @@ +require 'jasmine/base' +require 'jasmine/config' +require 'jasmine/server' + require 'jasmine/jasmine_helper' -require 'jasmine/jasmine_runner' require 'jasmine/jasmine_spec_builder' \ No newline at end of file diff --git a/lib/jasmine/base.rb b/lib/jasmine/base.rb new file mode 100644 index 0000000..2829910 --- /dev/null +++ b/lib/jasmine/base.rb @@ -0,0 +1,63 @@ +require 'socket' +require 'erb' +require 'json' + +module Jasmine + def self.root + File.expand_path(File.join(File.dirname(__FILE__), '../../jasmine')) + end + + # this seemingly-over-complex method is necessary to get an open port on at least some of our Macs + def self.open_socket_on_unused_port + infos = Socket::getaddrinfo("localhost", nil, Socket::AF_UNSPEC, Socket::SOCK_STREAM, 0, Socket::AI_PASSIVE) + families = Hash[*infos.collect { |af, *_| af }.uniq.zip([]).flatten] + + return TCPServer.open('0.0.0.0', 0) if families.has_key?('AF_INET') + return TCPServer.open('::', 0) if families.has_key?('AF_INET6') + return TCPServer.open(0) + end + + def self.find_unused_port + socket = open_socket_on_unused_port + port = socket.addr[1] + socket.close + port + end + + def self.server_is_listening_on(hostname, port) + require 'socket' + begin + socket = TCPSocket.open(hostname, port) + rescue Errno::ECONNREFUSED + return false + end + socket.close + true + end + + def self.wait_for_listener(port, name = "required process", seconds_to_wait = 10) + time_out_at = Time.now + seconds_to_wait + until server_is_listening_on "localhost", port + sleep 0.1 + puts "Waiting for #{name} on #{port}..." + raise "#{name} didn't show up on port #{port} after #{seconds_to_wait} seconds." if Time.now > time_out_at + end + end + + def self.kill_process_group(process_group_id, signal="TERM") + Process.kill signal, -process_group_id # negative pid means kill process group. (see man 2 kill) + end + + def self.cachebust(files, root_dir="", replace=nil, replace_with=nil) + require 'digest/md5' + files.collect do |file_name| + real_file_name = replace && replace_with ? file_name.sub(replace, replace_with) : file_name + begin + digest = Digest::MD5.hexdigest(File.read("#{root_dir}#{real_file_name}")) + rescue + digest = "MISSING-FILE" + end + "#{file_name}?cachebust=#{digest}" + end + end +end \ No newline at end of file diff --git a/lib/jasmine/config.rb b/lib/jasmine/config.rb new file mode 100644 index 0000000..3b64237 --- /dev/null +++ b/lib/jasmine/config.rb @@ -0,0 +1,74 @@ +module Jasmine + class Config + def initialize(options = {}) + require 'selenium_rc' + @selenium_jar_path = SeleniumRC::Server.allocate.jar_path + @options = options + + @browser = options[:browser] ? options.delete(:browser) : 'firefox' + @selenium_pid = nil + @jasmine_server_pid = nil + end + + def start_server(port = 8888) + Jasmine::Server.new(port, self).start + end + + def start + start_servers + @client = Jasmine::SimpleClient.new("localhost", @selenium_server_port, "*#{@browser}", "http://localhost:#{@jasmine_server_port}/") + @client.connect + end + + def stop + @client.disconnect + stop_servers + end + + def start_servers + @jasmine_server_port = Jasmine::find_unused_port + @selenium_server_port = Jasmine::find_unused_port + + @selenium_pid = fork do + Process.setpgrp + exec "java -jar #{@selenium_jar_path} -port #{@selenium_server_port} > /dev/null 2>&1" + end + puts "selenium started. pid is #{@selenium_pid}" + + @jasmine_server_pid = fork do + Process.setpgrp + Jasmine::Server.start(@jasmine_server_port, spec_files, @options) + exit! 0 + end + puts "jasmine server started. pid is #{@jasmine_server_pid}" + + Jasmine::wait_for_listener(@selenium_server_port, "selenium server") + Jasmine::wait_for_listener(@jasmine_server_port, "jasmine server") + end + + def stop_servers + puts "shutting down the servers..." + Jasmine::kill_process_group(@selenium_pid) if @selenium_pid + Jasmine::kill_process_group(@jasmine_server_pid) if @jasmine_server_pid + end + + def run + begin + start + puts "servers are listening on their ports -- running the test script..." + tests_passed = @client.run + ensure + stop + end + return tests_passed + end + + def eval_js(script) + @client.eval_js(script) + end + + def mappings + raise "You need to declare a mappings method in #{self.class}!" + end + end +end \ No newline at end of file diff --git a/lib/jasmine/jasmine_runner.rb b/lib/jasmine/jasmine_runner.rb index d0903b4..da9440a 100644 --- a/lib/jasmine/jasmine_runner.rb +++ b/lib/jasmine/jasmine_runner.rb @@ -1,302 +1,3 @@ -require 'socket' -require 'erb' -require 'json' - module Jasmine - def self.root - File.expand_path(File.join(File.dirname(__FILE__), '../../jasmine')) - end - - # this seemingly-over-complex method is necessary to get an open port on at least some of our Macs - def self.open_socket_on_unused_port - infos = Socket::getaddrinfo("localhost", nil, Socket::AF_UNSPEC, Socket::SOCK_STREAM, 0, Socket::AI_PASSIVE) - families = Hash[*infos.collect { |af, *_| af }.uniq.zip([]).flatten] - - return TCPServer.open('0.0.0.0', 0) if families.has_key?('AF_INET') - return TCPServer.open('::', 0) if families.has_key?('AF_INET6') - return TCPServer.open(0) - end - - def self.find_unused_port - socket = open_socket_on_unused_port - port = socket.addr[1] - socket.close - port - end - - def self.server_is_listening_on(hostname, port) - require 'socket' - begin - socket = TCPSocket.open(hostname, port) - rescue Errno::ECONNREFUSED - return false - end - socket.close - true - end - - def self.wait_for_listener(port, name = "required process", seconds_to_wait = 10) - time_out_at = Time.now + seconds_to_wait - until server_is_listening_on "localhost", port - sleep 0.1 - puts "Waiting for #{name} on #{port}..." - raise "#{name} didn't show up on port #{port} after #{seconds_to_wait} seconds." if Time.now > time_out_at - end - end - - def self.kill_process_group(process_group_id, signal="TERM") - Process.kill signal, -process_group_id # negative pid means kill process group. (see man 2 kill) - end - - def self.cachebust(files, root_dir="", replace=nil, replace_with=nil) - require 'digest/md5' - files.collect do |file_name| - real_file_name = replace && replace_with ? file_name.sub(replace, replace_with) : file_name - begin - digest = Digest::MD5.hexdigest(File.read("#{root_dir}#{real_file_name}")) - rescue - digest = "MISSING-FILE" - end - "#{file_name}?cachebust=#{digest}" - end - end - - class RunAdapter - def initialize(spec_files_or_proc, options = {}) - @spec_files_or_proc = Jasmine.files(spec_files_or_proc) || [] - @jasmine_files = Jasmine.files(options[:jasmine_files]) || [ - "/__JASMINE_ROOT__/lib/" + File.basename(Dir.glob("#{Jasmine.root}/lib/jasmine*.js").first), - "/__JASMINE_ROOT__/lib/TrivialReporter.js", - "/__JASMINE_ROOT__/lib/json2.js", - "/__JASMINE_ROOT__/lib/consolex.js", - ] - @stylesheets = ["/__JASMINE_ROOT__/lib/jasmine.css"] + (Jasmine.files(options[:stylesheets]) || []) - @spec_helpers = Jasmine.files(options[:spec_helpers]) || [] - end - - def call(env) - run - end - - def run - stylesheets = @stylesheets - spec_helpers = @spec_helpers - spec_files = @spec_files_or_proc - - jasmine_files = @jasmine_files - jasmine_files = jasmine_files.call if jasmine_files.respond_to?(:call) - - css_files = @stylesheets - - - body = ERB.new(File.read(File.join(File.dirname(__FILE__), "run.html"))).result(binding) - [ - 200, - { 'Content-Type' => 'text/html' }, - body - ] - end - - - end - - class Redirect - def initialize(url) - @url = url - end - - def call(env) - [ - 302, - { 'Location' => @url }, - [] - ] - end - end - - class JsAlert - def call(env) - [ - 200, - { 'Content-Type' => 'application/javascript' }, - "document.write('

Couldn\\'t load #{env["PATH_INFO"]}!

');" - ] - end - end - - class FocusedSuite - def initialize(spec_files_or_proc, options) - @spec_files_or_proc = Jasmine.files(spec_files_or_proc) || [] - @options = options - end - - def call(env) - spec_files = @spec_files_or_proc - matching_specs = spec_files.select {|spec_file| spec_file =~ /#{Regexp.escape(env["PATH_INFO"])}/ }.compact - if !matching_specs.empty? - run_adapter = Jasmine::RunAdapter.new(matching_specs, @options) - run_adapter.run - else - [ - 200, - { 'Content-Type' => 'application/javascript' }, - "document.write('

Couldn\\'t find any specs matching #{env["PATH_INFO"]}!

');" - ] - end - end - - end - - class SimpleServer - def self.start(port, spec_files_or_proc, options = {}) - require 'thin' - config = { - '/__suite__' => Jasmine::FocusedSuite.new(spec_files_or_proc, options), - '/run.html' => Jasmine::Redirect.new('/'), - '/' => Jasmine::RunAdapter.new(spec_files_or_proc, options) - } - - raise "Need :mappings!" unless options[:mappings] - options[:mappings].each do |from, to| - config[from] = Rack::File.new(to) - end - - config["/__JASMINE_ROOT__"] = Rack::File.new(Jasmine.root) - - app = Rack::Cascade.new([ - Rack::URLMap.new(config), - JsAlert.new - ]) - - begin - Thin::Server.start('0.0.0.0', port, app) - rescue RuntimeError => e - raise e unless e.message == 'no acceptor' - raise RuntimeError.new("A server is already running on port #{port}") - end - end - end - - class SimpleClient - def initialize(selenium_host, selenium_port, selenium_browser_start_command, http_address) - require 'selenium/client' - @driver = Selenium::Client::Driver.new( - selenium_host, - selenium_port, - selenium_browser_start_command, - http_address - ) - @http_address = http_address - end - - def tests_have_finished? - @driver.get_eval("window.jasmine.getEnv().currentRunner.finished") == "true" - end - - def connect - @driver.start - @driver.open("/") - end - - def disconnect - @driver.stop - end - - def run - until tests_have_finished? do - sleep 0.1 - end - - puts @driver.get_eval("window.results()") - failed_count = @driver.get_eval("window.jasmine.getEnv().currentRunner.results().failedCount").to_i - failed_count == 0 - end - - def eval_js(script) - escaped_script = "'" + script.gsub(/(['\\])/) { '\\' + $1 } + "'" - - result = @driver.get_eval(" try { eval(#{escaped_script}, window); } catch(err) { window.eval(#{escaped_script}); }") - JSON.parse("[#{result}]")[0] - end - end - - class Runner - def initialize(options = {}) - require 'selenium_rc' - @selenium_jar_path = SeleniumRC::Server.allocate.jar_path - @spec_files = spec_files - @options = options - - @browser = options[:browser] ? options.delete(:browser) : 'firefox' - @selenium_pid = nil - @jasmine_server_pid = nil - end - - def start_server(port = 8888) - p spec_files - Jasmine::SimpleServer.start(port, lambda { spec_files }, :mappings => { - "/spec" => spec_dir - }) - end - - def start - start_servers - @client = Jasmine::SimpleClient.new("localhost", @selenium_server_port, "*#{@browser}", "http://localhost:#{@jasmine_server_port}/") - @client.connect - end - - def stop - @client.disconnect - stop_servers - end - - def start_servers - @jasmine_server_port = Jasmine::find_unused_port - @selenium_server_port = Jasmine::find_unused_port - - @selenium_pid = fork do - Process.setpgrp - exec "java -jar #{@selenium_jar_path} -port #{@selenium_server_port} > /dev/null 2>&1" - end - puts "selenium started. pid is #{@selenium_pid}" - - @jasmine_server_pid = fork do - Process.setpgrp - Jasmine::SimpleServer.start(@jasmine_server_port, @spec_files, @options) - exit! 0 - end - puts "jasmine server started. pid is #{@jasmine_server_pid}" - - Jasmine::wait_for_listener(@selenium_server_port, "selenium server") - Jasmine::wait_for_listener(@jasmine_server_port, "jasmine server") - end - - def stop_servers - puts "shutting down the servers..." - Jasmine::kill_process_group(@selenium_pid) if @selenium_pid - Jasmine::kill_process_group(@jasmine_server_pid) if @jasmine_server_pid - end - - def run - begin - start - puts "servers are listening on their ports -- running the test script..." - tests_passed = @client.run - ensure - stop - end - return tests_passed - end - - def eval_js(script) - @client.eval_js(script) - end - end - - def self.files(f) - result = f - result = result.call if result.respond_to?(:call) - result - end end diff --git a/lib/jasmine/server.rb b/lib/jasmine/server.rb new file mode 100644 index 0000000..3844d8a --- /dev/null +++ b/lib/jasmine/server.rb @@ -0,0 +1,179 @@ +module Jasmine + class RunAdapter + def initialize(spec_files_or_proc, options = {}) + @spec_files_or_proc = Jasmine.files(spec_files_or_proc) || [] + @jasmine_files = Jasmine.files(options[:jasmine_files]) || [ + "/__JASMINE_ROOT__/lib/" + File.basename(Dir.glob("#{Jasmine.root}/lib/jasmine*.js").first), + "/__JASMINE_ROOT__/lib/TrivialReporter.js", + "/__JASMINE_ROOT__/lib/json2.js", + "/__JASMINE_ROOT__/lib/consolex.js", + ] + @stylesheets = ["/__JASMINE_ROOT__/lib/jasmine.css"] + (Jasmine.files(options[:stylesheets]) || []) + @spec_helpers = Jasmine.files(options[:spec_helpers]) || [] + end + + def call(env) + run + end + + def run + stylesheets = @stylesheets + spec_helpers = @spec_helpers + spec_files = @spec_files_or_proc + + jasmine_files = @jasmine_files + jasmine_files = jasmine_files.call if jasmine_files.respond_to?(:call) + + css_files = @stylesheets + + + body = ERB.new(File.read(File.join(File.dirname(__FILE__), "run.html"))).result(binding) + [ + 200, + { 'Content-Type' => 'text/html' }, + body + ] + end + + + end + + class Redirect + def initialize(url) + @url = url + end + + def call(env) + [ + 302, + { 'Location' => @url }, + [] + ] + end + end + + class JsAlert + def call(env) + [ + 200, + { 'Content-Type' => 'application/javascript' }, + "document.write('

Couldn\\'t load #{env["PATH_INFO"]}!

');" + ] + end + end + + class FocusedSuite + def initialize(config) + @config = config +# @spec_files_or_proc = Jasmine.files(spec_files_or_proc) || [] +# @options = options + end + + def call(env) + spec_files = Jasmine.files(@config.spec_files_or_proc) + matching_specs = spec_files.select {|spec_file| spec_file =~ /#{Regexp.escape(env["PATH_INFO"])}/ }.compact + if !matching_specs.empty? + run_adapter = Jasmine::RunAdapter.new(matching_specs, @options) + run_adapter.run + else + [ + 200, + { 'Content-Type' => 'application/javascript' }, + "document.write('

Couldn\\'t find any specs matching #{env["PATH_INFO"]}!

');" + ] + end + end + + end + + def self.files(f) + result = f + result = result.call if result.respond_to?(:call) + result + end + + class Server + attr_reader :thin + + def initialize(port, config) + @port = port + @config = config + + require 'thin' + thin_config = { + '/__suite__' => Jasmine::FocusedSuite.new(@config), + '/run.html' => Jasmine::Redirect.new('/'), + '/' => Jasmine::RunAdapter.new(@config) + } + + @config.mappings.each do |from, to| + thin_config[from] = Rack::File.new(to) + end + + thin_config["/__JASMINE_ROOT__"] = Rack::File.new(Jasmine.root) + + app = Rack::Cascade.new([ + Rack::URLMap.new(thin_config), + JsAlert.new + ]) + + @thin = Thin::Server.new('0.0.0.0', @port, app) + end + + def start + begin + thin.start + rescue RuntimeError => e + raise e unless e.message == 'no acceptor' + raise RuntimeError.new("A server is already running on port #{@port}") + end + end + + def stop + thin.stop + end + end + + class SimpleClient + def initialize(selenium_host, selenium_port, selenium_browser_start_command, http_address) + require 'selenium/client' + @driver = Selenium::Client::Driver.new( + selenium_host, + selenium_port, + selenium_browser_start_command, + http_address + ) + @http_address = http_address + end + + def tests_have_finished? + @driver.get_eval("window.jasmine.getEnv().currentRunner.finished") == "true" + end + + def connect + @driver.start + @driver.open("/") + end + + def disconnect + @driver.stop + end + + def run + until tests_have_finished? do + sleep 0.1 + end + + puts @driver.get_eval("window.results()") + failed_count = @driver.get_eval("window.jasmine.getEnv().currentRunner.results().failedCount").to_i + failed_count == 0 + end + + def eval_js(script) + escaped_script = "'" + script.gsub(/(['\\])/) { '\\' + $1 } + "'" + + result = @driver.get_eval(" try { eval(#{escaped_script}, window); } catch(err) { window.eval(#{escaped_script}); }") + JSON.parse("[#{result}]")[0] + end + end +end \ No newline at end of file diff --git a/spec/jasmine_self_test_runner.rb b/spec/jasmine_self_test_config.rb similarity index 81% rename from spec/jasmine_self_test_runner.rb rename to spec/jasmine_self_test_config.rb index 75eac41..bd6af13 100644 --- a/spec/jasmine_self_test_runner.rb +++ b/spec/jasmine_self_test_config.rb @@ -1,6 +1,6 @@ require 'jasmine' -class JasmineSelfTestRunner < Jasmine::Runner +class JasmineSelfTestConfig < Jasmine::Config def proj_root File.expand_path(File.join(File.dirname(__FILE__), "..")) end @@ -20,6 +20,12 @@ class JasmineSelfTestRunner < Jasmine::Runner def spec_files Dir.glob(File.join(spec_dir, "**/*[Ss]pec.js")).collect { |f| f.sub("#{spec_dir}/", "") } end + + def mappings + { + "/spec" => spec_dir + } + end # # def specs # Jasmine.cachebust(spec_files).collect {|f| f.sub(spec_dir, "/spec")} diff --git a/spec/jasmine_spec.rb b/spec/jasmine_spec.rb index f289ac6..85666c2 100644 --- a/spec/jasmine_spec.rb +++ b/spec/jasmine_spec.rb @@ -1,4 +1,4 @@ -require 'jasmine_self_test_runner' +require 'jasmine_self_test_config' jasmine_runner = JasmineSelfTestRunner.new spec_builder = Jasmine::SpecBuilder.new(jasmine_runner) diff --git a/spec/server_spec.rb b/spec/server_spec.rb new file mode 100644 index 0000000..363feef --- /dev/null +++ b/spec/server_spec.rb @@ -0,0 +1,51 @@ +require File.expand_path(File.join(File.dirname(__FILE__), "spec_helper")) + +def read(body) + return body if body.is_a?(String) + out = "" + body.each {|data| out += data } + out +end + +describe Jasmine::Server do + before(:each) do + config = Jasmine::Config.new + config.stub!(:mappings).and_return({ + "/src" => File.join(Jasmine.root, "src"), + "/spec" => File.join(Jasmine.root, "spec") + }) + + @server = Jasmine::Server.new(0, config) + @thin_app = @server.thin.app + end + + after(:each) do + @server.thin.stop if @server && @server.thin.running? + end + + it "should serve static files" do + code, headers, body = @thin_app.call("PATH_INFO" => "/spec/suites/EnvSpec.js", "SCRIPT_NAME" => "xxx") + code.should == 200 + headers["Content-Type"].should == "application/javascript" + read(body).should == File.read(File.join(Jasmine.root, "spec/suites/EnvSpec.js")) + end + + it "should serve Jasmine static files under /__JASMINE_ROOT__/" do + code, headers, body = @thin_app.call("PATH_INFO" => "/__JASMINE_ROOT__/lib/jasmine.css", "SCRIPT_NAME" => "xxx") + code.should == 200 + headers["Content-Type"].should == "text/css" + read(body).should == File.read(File.join(Jasmine.root, "lib/jasmine.css")) + end + + it "should redirect /run.html to /" do + code, headers, body = @thin_app.call("PATH_INFO" => "/run.html", "SCRIPT_NAME" => "xxx") + code.should == 302 + headers["Location"].should == "/" + end + + it "should serve /" do + code, headers, body = @thin_app.call("PATH_INFO" => "/", "SCRIPT_NAME" => "xxx") + body = read(body) + p body + end +end \ No newline at end of file diff --git a/spec/spec_helper.rb b/spec/spec_helper.rb new file mode 100644 index 0000000..78c3b71 --- /dev/null +++ b/spec/spec_helper.rb @@ -0,0 +1,3 @@ +require 'spec' + +require File.expand_path(File.join(File.dirname(__FILE__), "../lib/jasmine")) \ No newline at end of file diff --git a/templates/Rakefile b/templates/Rakefile index 93da0dd..ce23bba 100644 --- a/templates/Rakefile +++ b/templates/Rakefile @@ -17,7 +17,7 @@ namespace :jasmine do puts "your tests are here:" puts " http://localhost:8888/run.html" - Jasmine::SimpleServer.start(8888, + Jasmine::Server.start(8888, File.expand_path(Dir.pwd), lambda { JasmineHelper.specs }, { :spec_helpers => JasmineHelper.files + JasmineHelper.spec_helpers, From 59c85355fc311c76a56707dc0f1baa011c8219e2 Mon Sep 17 00:00:00 2001 From: Christian Williams Date: Mon, 28 Dec 2009 14:26:30 -0600 Subject: [PATCH 09/16] More changes, specs. --- lib/jasmine/config.rb | 16 ++++++++++++++++ lib/jasmine/run.html | 8 ++------ lib/jasmine/server.rb | 19 ++++++------------- spec/server_spec.rb | 7 ++++++- 4 files changed, 30 insertions(+), 20 deletions(-) diff --git a/lib/jasmine/config.rb b/lib/jasmine/config.rb index 3b64237..eb5bacc 100644 --- a/lib/jasmine/config.rb +++ b/lib/jasmine/config.rb @@ -70,5 +70,21 @@ module Jasmine def mappings raise "You need to declare a mappings method in #{self.class}!" end + + def stylesheets + [] + end + + def src_files + [] + end + + def spec_files + raise "You need to declare a spec_files method in #{self.class}!" + end + + def js_files + src_files + spec_files + end end end \ No newline at end of file diff --git a/lib/jasmine/run.html b/lib/jasmine/run.html index 9f0ecd0..80a200c 100644 --- a/lib/jasmine/run.html +++ b/lib/jasmine/run.html @@ -11,10 +11,6 @@ <% end %> - <% spec_helpers.each do |spec_helper| %> - - <% end %> - - <% spec_files.each do |spec_file| %> - + <% js_files.each do |js_file| %> + <% end %> diff --git a/lib/jasmine/server.rb b/lib/jasmine/server.rb index 3844d8a..3d79eb6 100644 --- a/lib/jasmine/server.rb +++ b/lib/jasmine/server.rb @@ -1,15 +1,14 @@ module Jasmine class RunAdapter - def initialize(spec_files_or_proc, options = {}) - @spec_files_or_proc = Jasmine.files(spec_files_or_proc) || [] - @jasmine_files = Jasmine.files(options[:jasmine_files]) || [ + def initialize(config) + @config = config + @jasmine_files = [ "/__JASMINE_ROOT__/lib/" + File.basename(Dir.glob("#{Jasmine.root}/lib/jasmine*.js").first), "/__JASMINE_ROOT__/lib/TrivialReporter.js", "/__JASMINE_ROOT__/lib/json2.js", "/__JASMINE_ROOT__/lib/consolex.js", ] - @stylesheets = ["/__JASMINE_ROOT__/lib/jasmine.css"] + (Jasmine.files(options[:stylesheets]) || []) - @spec_helpers = Jasmine.files(options[:spec_helpers]) || [] + @jasmine_stylesheets = ["/__JASMINE_ROOT__/lib/jasmine.css"] end def call(env) @@ -17,15 +16,9 @@ module Jasmine end def run - stylesheets = @stylesheets - spec_helpers = @spec_helpers - spec_files = @spec_files_or_proc - jasmine_files = @jasmine_files - jasmine_files = jasmine_files.call if jasmine_files.respond_to?(:call) - - css_files = @stylesheets - + css_files = @jasmine_stylesheets + (Jasmine.files(@config.stylesheets) || []) + js_files = Jasmine.files(@config.js_files) body = ERB.new(File.read(File.join(File.dirname(__FILE__), "run.html"))).result(binding) [ diff --git a/spec/server_spec.rb b/spec/server_spec.rb index 363feef..f022b0e 100644 --- a/spec/server_spec.rb +++ b/spec/server_spec.rb @@ -15,6 +15,8 @@ describe Jasmine::Server do "/spec" => File.join(Jasmine.root, "spec") }) + config.stub!(:js_files).and_return(["/src/file1.js", "/spec/file2.js"]) + @server = Jasmine::Server.new(0, config) @thin_app = @server.thin.app end @@ -45,7 +47,10 @@ describe Jasmine::Server do it "should serve /" do code, headers, body = @thin_app.call("PATH_INFO" => "/", "SCRIPT_NAME" => "xxx") + code.should == 200 body = read(body) - p body + body.should include("\"/src/file1.js") + body.should include("\"/spec/file2.js") + body.should satisfy {|s| s.index("/src/file1.js") < s.index("/spec/file2.js") } end end \ No newline at end of file From 73c8fef43e6cf8fa681f3e5b341f3a7b86bde6e6 Mon Sep 17 00:00:00 2001 From: Christian Williams Date: Mon, 28 Dec 2009 15:10:27 -0600 Subject: [PATCH 10/16] More changes, specs. --- lib/jasmine/{run.html => run.html.erb} | 0 lib/jasmine/server.rb | 3 ++- spec/server_spec.rb | 16 +++++++++------- 3 files changed, 11 insertions(+), 8 deletions(-) rename lib/jasmine/{run.html => run.html.erb} (100%) diff --git a/lib/jasmine/run.html b/lib/jasmine/run.html.erb similarity index 100% rename from lib/jasmine/run.html rename to lib/jasmine/run.html.erb diff --git a/lib/jasmine/server.rb b/lib/jasmine/server.rb index 3d79eb6..c293f78 100644 --- a/lib/jasmine/server.rb +++ b/lib/jasmine/server.rb @@ -15,12 +15,13 @@ module Jasmine run end + #noinspection RubyUnusedLocalVariable def run jasmine_files = @jasmine_files css_files = @jasmine_stylesheets + (Jasmine.files(@config.stylesheets) || []) js_files = Jasmine.files(@config.js_files) - body = ERB.new(File.read(File.join(File.dirname(__FILE__), "run.html"))).result(binding) + body = ERB.new(File.read(File.join(File.dirname(__FILE__), "run.html.erb"))).result(binding) [ 200, { 'Content-Type' => 'text/html' }, diff --git a/spec/server_spec.rb b/spec/server_spec.rb index f022b0e..8d0ed6b 100644 --- a/spec/server_spec.rb +++ b/spec/server_spec.rb @@ -45,12 +45,14 @@ describe Jasmine::Server do headers["Location"].should == "/" end - it "should serve /" do - code, headers, body = @thin_app.call("PATH_INFO" => "/", "SCRIPT_NAME" => "xxx") - code.should == 200 - body = read(body) - body.should include("\"/src/file1.js") - body.should include("\"/spec/file2.js") - body.should satisfy {|s| s.index("/src/file1.js") < s.index("/spec/file2.js") } + describe "/ page" do + it "should load each js file in order" do + code, headers, body = @thin_app.call("PATH_INFO" => "/", "SCRIPT_NAME" => "xxx") + code.should == 200 + body = read(body) + body.should include("\"/src/file1.js") + body.should include("\"/spec/file2.js") + body.should satisfy {|s| s.index("/src/file1.js") < s.index("/spec/file2.js") } + end end end \ No newline at end of file From 00c7d3ca29672f3c0569de028df9b13431b8a4f2 Mon Sep 17 00:00:00 2001 From: Christian Williams Date: Mon, 28 Dec 2009 15:16:13 -0600 Subject: [PATCH 11/16] Runs server correctly for self-test. --- spec/jasmine_self_test_config.rb | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/spec/jasmine_self_test_config.rb b/spec/jasmine_self_test_config.rb index bd6af13..cf01391 100644 --- a/spec/jasmine_self_test_config.rb +++ b/spec/jasmine_self_test_config.rb @@ -18,11 +18,12 @@ class JasmineSelfTestConfig < Jasmine::Config end def spec_files - Dir.glob(File.join(spec_dir, "**/*[Ss]pec.js")).collect { |f| f.sub("#{spec_dir}/", "") } + Dir.glob(File.join(spec_dir, "**/*[Ss]pec.js")).collect { |f| f.sub("#{spec_dir}/", "spec/") } end def mappings { + "/src" => src_dir, "/spec" => spec_dir } end From 2045226ba731533a31e9d110edbbf2001be1301d Mon Sep 17 00:00:00 2001 From: Christian Williams Date: Mon, 28 Dec 2009 15:24:49 -0600 Subject: [PATCH 12/16] More specs. --- spec/jasmine_self_test_config.rb | 4 ---- spec/server_spec.rb | 7 +++++++ 2 files changed, 7 insertions(+), 4 deletions(-) diff --git a/spec/jasmine_self_test_config.rb b/spec/jasmine_self_test_config.rb index cf01391..f8bd819 100644 --- a/spec/jasmine_self_test_config.rb +++ b/spec/jasmine_self_test_config.rb @@ -27,8 +27,4 @@ class JasmineSelfTestConfig < Jasmine::Config "/spec" => spec_dir } end -# -# def specs -# Jasmine.cachebust(spec_files).collect {|f| f.sub(spec_dir, "/spec")} -# end end \ No newline at end of file diff --git a/spec/server_spec.rb b/spec/server_spec.rb index 8d0ed6b..7397716 100644 --- a/spec/server_spec.rb +++ b/spec/server_spec.rb @@ -55,4 +55,11 @@ describe Jasmine::Server do body.should satisfy {|s| s.index("/src/file1.js") < s.index("/spec/file2.js") } end end + + it "should display an error using JS for 404's" do + code, headers, body = @thin_app.call("PATH_INFO" => "/spec/NonExistantFile.js", "SCRIPT_NAME" => "xxx") + code.should == 200 # todo: shouldn't this be 404? will that work with all browsers? + headers["Content-Type"].should == "application/javascript" + read(body).should == "document.write('

Couldn\\'t load /spec/NonExistantFile.js!

');" + end end \ No newline at end of file From 81aeeeedee149b62d00332fa90ec736449e5b05b Mon Sep 17 00:00:00 2001 From: Christian Williams Date: Mon, 28 Dec 2009 16:27:02 -0600 Subject: [PATCH 13/16] Refactor config file/path handling. --- jasmine-ruby.gemspec | 6 +-- lib/jasmine.rb | 3 +- lib/jasmine/config.rb | 36 ++++++++++++- lib/jasmine/jasmine_meta_spec.rb | 2 +- lib/jasmine/jasmine_runner.rb | 3 -- lib/jasmine/selenium_driver.rb | 44 +++++++++++++++ lib/jasmine/server.rb | 43 --------------- ...asmine_spec_builder.rb => spec_builder.rb} | 11 ++-- spec/config_spec.rb | 53 +++++++++++++++++++ spec/jasmine_self_test_config.rb | 15 ------ ...mine_spec.rb => jasmine_self_test_spec.rb} | 4 +- templates/public/javascripts/example.js | 2 + templates/{ => spec}/jasmine_helper.rb | 0 .../javascript/ExampleSpec.js} | 4 +- .../javascript/SpecHelper.js} | 0 15 files changed, 150 insertions(+), 76 deletions(-) delete mode 100644 lib/jasmine/jasmine_runner.rb create mode 100644 lib/jasmine/selenium_driver.rb rename lib/jasmine/{jasmine_spec_builder.rb => spec_builder.rb} (95%) create mode 100644 spec/config_spec.rb rename spec/{jasmine_spec.rb => jasmine_self_test_spec.rb} (70%) create mode 100644 templates/public/javascripts/example.js rename templates/{ => spec}/jasmine_helper.rb (100%) rename templates/{example_spec.js => spec/javascript/ExampleSpec.js} (69%) rename templates/{spec_helper.js => spec/javascript/SpecHelper.js} (100%) diff --git a/jasmine-ruby.gemspec b/jasmine-ruby.gemspec index 4d2d38a..e8a819f 100644 --- a/jasmine-ruby.gemspec +++ b/jasmine-ruby.gemspec @@ -28,12 +28,12 @@ Gem::Specification.new do |s| "lib/jasmine/jasmine_helper.rb", "lib/jasmine/jasmine_meta_spec.rb", "lib/jasmine/jasmine_runner.rb", - "lib/jasmine/jasmine_spec_builder.rb", + "lib/jasmine/spec_builder.rb", "lib/jasmine/run.html", "templates/Rakefile", - "templates/example_spec.js", + "templates/ExampleSpec.js", "templates/jasmine_helper.rb", - "templates/spec_helper.js" + "templates/SpecHelper.js" ] s.homepage = %q{http://github.com/ragaskar/jasmine} s.rdoc_options = ["--charset=UTF-8"] diff --git a/lib/jasmine.rb b/lib/jasmine.rb index 1ab5139..a4c01aa 100644 --- a/lib/jasmine.rb +++ b/lib/jasmine.rb @@ -1,6 +1,7 @@ require 'jasmine/base' require 'jasmine/config' require 'jasmine/server' +require 'jasmine/selenium_driver' require 'jasmine/jasmine_helper' -require 'jasmine/jasmine_spec_builder' \ No newline at end of file +require 'jasmine/spec_builder' \ No newline at end of file diff --git a/lib/jasmine/config.rb b/lib/jasmine/config.rb index eb5bacc..d07be03 100644 --- a/lib/jasmine/config.rb +++ b/lib/jasmine/config.rb @@ -16,7 +16,7 @@ module Jasmine def start start_servers - @client = Jasmine::SimpleClient.new("localhost", @selenium_server_port, "*#{@browser}", "http://localhost:#{@jasmine_server_port}/") + @client = Jasmine::SeleniumDriver.new("localhost", @selenium_server_port, "*#{@browser}", "http://localhost:#{@jasmine_server_port}/") @client.connect end @@ -83,8 +83,40 @@ module Jasmine raise "You need to declare a spec_files method in #{self.class}!" end + def match_files(dir, pattern) + dir = File.expand_path(dir) + Dir.glob(File.join(dir, pattern)).collect {|f| f.sub("#{dir}/", "")}.sort + end + + def src_files + match_files(src_dir, "**/*.js") + end + + def src_path + "src" + end + + def spec_path + "spec" + end + + def spec_files + match_files(spec_dir, "**/*.js") + end + + def mappings + { + "/" + src_path => src_dir, + "/" + spec_path => spec_dir + } + end + def js_files - src_files + spec_files + src_files.collect {|f| File.join(src_path, f) } + spec_files.collect {|f| File.join(spec_path, f) } + end + + def spec_files_full_paths + spec_files.collect {|spec_file| File.join(spec_dir, spec_file) } end end end \ No newline at end of file diff --git a/lib/jasmine/jasmine_meta_spec.rb b/lib/jasmine/jasmine_meta_spec.rb index 34154a2..3dd0e01 100644 --- a/lib/jasmine/jasmine_meta_spec.rb +++ b/lib/jasmine/jasmine_meta_spec.rb @@ -6,7 +6,7 @@ if File.exist?(helper_overrides) require helper_overrides end require File.expand_path(File.join(File.dirname(__FILE__), "jasmine_runner.rb")) -require File.expand_path(File.join(File.dirname(__FILE__), "jasmine_spec_builder")) +require File.expand_path(File.join(File.dirname(__FILE__), "spec_builder")) jasmine_runner = Jasmine::Runner.new(SeleniumRC::Server.new.jar_path, Dir.pwd, diff --git a/lib/jasmine/jasmine_runner.rb b/lib/jasmine/jasmine_runner.rb deleted file mode 100644 index da9440a..0000000 --- a/lib/jasmine/jasmine_runner.rb +++ /dev/null @@ -1,3 +0,0 @@ -module Jasmine - -end diff --git a/lib/jasmine/selenium_driver.rb b/lib/jasmine/selenium_driver.rb new file mode 100644 index 0000000..7f9bac8 --- /dev/null +++ b/lib/jasmine/selenium_driver.rb @@ -0,0 +1,44 @@ +module Jasmine + class SeleniumDriver + def initialize(selenium_host, selenium_port, selenium_browser_start_command, http_address) + require 'selenium/client' + @driver = Selenium::Client::Driver.new( + selenium_host, + selenium_port, + selenium_browser_start_command, + http_address + ) + @http_address = http_address + end + + def tests_have_finished? + @driver.get_eval("window.jasmine.getEnv().currentRunner.finished") == "true" + end + + def connect + @driver.start + @driver.open("/") + end + + def disconnect + @driver.stop + end + + def run + until tests_have_finished? do + sleep 0.1 + end + + puts @driver.get_eval("window.results()") + failed_count = @driver.get_eval("window.jasmine.getEnv().currentRunner.results().failedCount").to_i + failed_count == 0 + end + + def eval_js(script) + escaped_script = "'" + script.gsub(/(['\\])/) { '\\' + $1 } + "'" + + result = @driver.get_eval(" try { eval(#{escaped_script}, window); } catch(err) { window.eval(#{escaped_script}); }") + JSON.parse("[#{result}]")[0] + end + end +end \ No newline at end of file diff --git a/lib/jasmine/server.rb b/lib/jasmine/server.rb index c293f78..8527abb 100644 --- a/lib/jasmine/server.rb +++ b/lib/jasmine/server.rb @@ -127,47 +127,4 @@ module Jasmine thin.stop end end - - class SimpleClient - def initialize(selenium_host, selenium_port, selenium_browser_start_command, http_address) - require 'selenium/client' - @driver = Selenium::Client::Driver.new( - selenium_host, - selenium_port, - selenium_browser_start_command, - http_address - ) - @http_address = http_address - end - - def tests_have_finished? - @driver.get_eval("window.jasmine.getEnv().currentRunner.finished") == "true" - end - - def connect - @driver.start - @driver.open("/") - end - - def disconnect - @driver.stop - end - - def run - until tests_have_finished? do - sleep 0.1 - end - - puts @driver.get_eval("window.results()") - failed_count = @driver.get_eval("window.jasmine.getEnv().currentRunner.results().failedCount").to_i - failed_count == 0 - end - - def eval_js(script) - escaped_script = "'" + script.gsub(/(['\\])/) { '\\' + $1 } + "'" - - result = @driver.get_eval(" try { eval(#{escaped_script}, window); } catch(err) { window.eval(#{escaped_script}); }") - JSON.parse("[#{result}]")[0] - end - end end \ No newline at end of file diff --git a/lib/jasmine/jasmine_spec_builder.rb b/lib/jasmine/spec_builder.rb similarity index 95% rename from lib/jasmine/jasmine_spec_builder.rb rename to lib/jasmine/spec_builder.rb index b5ecad4..352845e 100644 --- a/lib/jasmine/jasmine_spec_builder.rb +++ b/lib/jasmine/spec_builder.rb @@ -1,12 +1,13 @@ require 'enumerator' -module Jasmine +module Jasmine class SpecBuilder attr_accessor :suites - def initialize(runner) - @spec_files = runner.spec_files - @runner = runner + def initialize(config) + @config = config + @spec_files = config.spec_files + @runner = config @spec_ids = [] end @@ -31,7 +32,7 @@ module Jasmine example_name_parts = [] previous_indent_level = 0 - @spec_files.each do |filename| + @config.spec_files_full_paths.each do |filename| line_number = 1 File.open(filename, "r") do |file| file.readlines.each do |line| diff --git a/spec/config_spec.rb b/spec/config_spec.rb new file mode 100644 index 0000000..731903a --- /dev/null +++ b/spec/config_spec.rb @@ -0,0 +1,53 @@ +require File.expand_path(File.join(File.dirname(__FILE__), "spec_helper")) + +describe Jasmine::Config do + before(:each) do + @template_dir = File.expand_path(File.join(File.dirname(__FILE__), "../templates")) + @config = Jasmine::Config.new + @config.stub!(:src_dir).and_return(File.join(@template_dir, "public")) + @config.stub!(:spec_dir).and_return(File.join(@template_dir, "spec")) + end + + it "should provide a list of all src and spec files" do + @config.src_files.should == ['javascripts/Example.js'] + @config.spec_files.should == ['javascript/ExampleSpec.js', 'javascript/SpecHelper.js'] + end + + it "should provide a list of all spec files with full paths" do + @config.spec_files_full_paths.should == [ + File.join(@template_dir, 'spec/javascript/ExampleSpec.js'), + File.join(@template_dir, 'spec/javascript/SpecHelper.js') + ] + end + + it "should provide a list of all js files" do + @config.js_files.should == [ + 'src/javascripts/Example.js', + 'spec/javascript/ExampleSpec.js', + 'spec/javascript/SpecHelper.js', + ] + end + + it "should provide dir mappings" do + @config.mappings.should == { + '/src' => @config.src_dir, + '/spec' => @config.spec_dir + } + end + + it "should allow overriding src and spec paths" do + @config.stub!(:src_path).and_return("public") + @config.stub!(:spec_path).and_return("spekz") + + @config.js_files.should == [ + 'public/javascripts/Example.js', + 'spekz/javascript/ExampleSpec.js', + 'spekz/javascript/SpecHelper.js', + ] + + @config.mappings.should == { + '/public' => @config.src_dir, + '/spekz' => @config.spec_dir + } + end +end \ No newline at end of file diff --git a/spec/jasmine_self_test_config.rb b/spec/jasmine_self_test_config.rb index f8bd819..2736157 100644 --- a/spec/jasmine_self_test_config.rb +++ b/spec/jasmine_self_test_config.rb @@ -9,22 +9,7 @@ class JasmineSelfTestConfig < Jasmine::Config File.join(proj_root, 'src') end - def src_files - Dir.glob(File.join(src_dir, "**/*.js")) - end - def spec_dir File.join(proj_root, 'jasmine/spec') end - - def spec_files - Dir.glob(File.join(spec_dir, "**/*[Ss]pec.js")).collect { |f| f.sub("#{spec_dir}/", "spec/") } - end - - def mappings - { - "/src" => src_dir, - "/spec" => spec_dir - } - end end \ No newline at end of file diff --git a/spec/jasmine_spec.rb b/spec/jasmine_self_test_spec.rb similarity index 70% rename from spec/jasmine_spec.rb rename to spec/jasmine_self_test_spec.rb index 85666c2..fcb604e 100644 --- a/spec/jasmine_spec.rb +++ b/spec/jasmine_self_test_spec.rb @@ -1,6 +1,8 @@ +require File.expand_path(File.join(File.dirname(__FILE__), "spec_helper")) + require 'jasmine_self_test_config' -jasmine_runner = JasmineSelfTestRunner.new +jasmine_runner = JasmineSelfTestConfig.new spec_builder = Jasmine::SpecBuilder.new(jasmine_runner) should_stop = false diff --git a/templates/public/javascripts/example.js b/templates/public/javascripts/example.js new file mode 100644 index 0000000..3fcc4e1 --- /dev/null +++ b/templates/public/javascripts/example.js @@ -0,0 +1,2 @@ +ExampleClass = function() { +}; \ No newline at end of file diff --git a/templates/jasmine_helper.rb b/templates/spec/jasmine_helper.rb similarity index 100% rename from templates/jasmine_helper.rb rename to templates/spec/jasmine_helper.rb diff --git a/templates/example_spec.js b/templates/spec/javascript/ExampleSpec.js similarity index 69% rename from templates/example_spec.js rename to templates/spec/javascript/ExampleSpec.js index 494539e..07ae14f 100644 --- a/templates/example_spec.js +++ b/templates/spec/javascript/ExampleSpec.js @@ -1,9 +1,9 @@ -describe('ExampleSuite', function () { +describe('Example', function () { it('should have a passing test', function() { expect(true).toEqual(true); }); - describe('Nested Describe', function () { + describe('nested describe', function () { it('should also have a passing test', function () { expect(true).toEqual(true); }); diff --git a/templates/spec_helper.js b/templates/spec/javascript/SpecHelper.js similarity index 100% rename from templates/spec_helper.js rename to templates/spec/javascript/SpecHelper.js From d4683ca485474e8bff076f9282a2c55570db5dba Mon Sep 17 00:00:00 2001 From: Christian Williams Date: Mon, 28 Dec 2009 16:46:50 -0600 Subject: [PATCH 14/16] Refactor. --- lib/jasmine/config.rb | 4 +++- spec/jasmine_self_test_spec.rb | 4 ++-- 2 files changed, 5 insertions(+), 3 deletions(-) diff --git a/lib/jasmine/config.rb b/lib/jasmine/config.rb index d07be03..73aac30 100644 --- a/lib/jasmine/config.rb +++ b/lib/jasmine/config.rb @@ -29,6 +29,8 @@ module Jasmine @jasmine_server_port = Jasmine::find_unused_port @selenium_server_port = Jasmine::find_unused_port + server = Jasmine::Server.new(@jasmine_server_port, self) + @selenium_pid = fork do Process.setpgrp exec "java -jar #{@selenium_jar_path} -port #{@selenium_server_port} > /dev/null 2>&1" @@ -37,7 +39,7 @@ module Jasmine @jasmine_server_pid = fork do Process.setpgrp - Jasmine::Server.start(@jasmine_server_port, spec_files, @options) + server.start exit! 0 end puts "jasmine server started. pid is #{@jasmine_server_pid}" diff --git a/spec/jasmine_self_test_spec.rb b/spec/jasmine_self_test_spec.rb index fcb604e..e66c32e 100644 --- a/spec/jasmine_self_test_spec.rb +++ b/spec/jasmine_self_test_spec.rb @@ -2,8 +2,8 @@ require File.expand_path(File.join(File.dirname(__FILE__), "spec_helper")) require 'jasmine_self_test_config' -jasmine_runner = JasmineSelfTestConfig.new -spec_builder = Jasmine::SpecBuilder.new(jasmine_runner) +jasmine_config = JasmineSelfTestConfig.new +spec_builder = Jasmine::SpecBuilder.new(jasmine_config) should_stop = false From 5821de080151162c1d8abe130d645df05677fe9b Mon Sep 17 00:00:00 2001 From: Christian Williams Date: Mon, 28 Dec 2009 16:47:48 -0600 Subject: [PATCH 15/16] Version bump to 0.1.3 --- VERSION.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/VERSION.yml b/VERSION.yml index a375942..26bc13b 100644 --- a/VERSION.yml +++ b/VERSION.yml @@ -1,5 +1,5 @@ --- :minor: 1 :build: -:patch: 2 +:patch: 3 :major: 0 From c8b38ea47a5a3bfa23fd8b87f53a58a1bb000b7f Mon Sep 17 00:00:00 2001 From: Christian Williams Date: Tue, 29 Dec 2009 17:09:07 -0600 Subject: [PATCH 16/16] Fix js paths when served from somewhere other than /. --- Rakefile | 9 ++++----- lib/jasmine/config.rb | 6 +----- lib/jasmine/server.rb | 14 ++++---------- spec/config_spec.rb | 12 ++++++------ 4 files changed, 15 insertions(+), 26 deletions(-) diff --git a/Rakefile b/Rakefile index e572ebd..bd625b8 100644 --- a/Rakefile +++ b/Rakefile @@ -47,13 +47,12 @@ namespace :jeweler do Jeweler::Tasks.new do |gemspec| gemspec.name = "xian-test-jasmine" - gemspec.summary = "Jasmine Ruby" - gemspec.description = "Javascript BDD testings" + gemspec.summary = "Jasmine for Ruby" + gemspec.description = "Javascript BDD test framework" gemspec.email = "ragaskar@gmail.com" gemspec.homepage = "http://github.com/ragaskar/jasmine-ruby" - gemspec.description = "Jasmine Ruby" - gemspec.authors = ["Rajan Agaskar"] - gemspec.files = FileList.new('bin/*', 'lib/**/**', 'jasmine/lib/**', 'jasmine/contrib/ruby/**', 'tasks/**', 'templates/**') + gemspec.authors = ["Rajan Agaskar", "Christian Williams"] + gemspec.files = FileList.new('bin/jasmine', 'lib/**/**', 'jasmine/lib/**', 'jasmine/contrib/ruby/**', 'tasks/**', 'templates/**') gemspec.add_dependency('rspec', '>= 1.1.5') gemspec.add_dependency('rack', '>= 1.0.0') diff --git a/lib/jasmine/config.rb b/lib/jasmine/config.rb index 73aac30..10b48ba 100644 --- a/lib/jasmine/config.rb +++ b/lib/jasmine/config.rb @@ -69,10 +69,6 @@ module Jasmine @client.eval_js(script) end - def mappings - raise "You need to declare a mappings method in #{self.class}!" - end - def stylesheets [] end @@ -114,7 +110,7 @@ module Jasmine end def js_files - src_files.collect {|f| File.join(src_path, f) } + spec_files.collect {|f| File.join(spec_path, f) } + src_files.collect {|f| "/" + File.join(src_path, f) } + spec_files.collect {|f| "/" + File.join(spec_path, f) } end def spec_files_full_paths diff --git a/lib/jasmine/server.rb b/lib/jasmine/server.rb index 8527abb..90918fb 100644 --- a/lib/jasmine/server.rb +++ b/lib/jasmine/server.rb @@ -18,8 +18,8 @@ module Jasmine #noinspection RubyUnusedLocalVariable def run jasmine_files = @jasmine_files - css_files = @jasmine_stylesheets + (Jasmine.files(@config.stylesheets) || []) - js_files = Jasmine.files(@config.js_files) + css_files = @jasmine_stylesheets + (@config.stylesheets || []) + js_files = @config.js_files body = ERB.new(File.read(File.join(File.dirname(__FILE__), "run.html.erb"))).result(binding) [ @@ -59,12 +59,12 @@ module Jasmine class FocusedSuite def initialize(config) @config = config -# @spec_files_or_proc = Jasmine.files(spec_files_or_proc) || [] +# @spec_files_or_proc = spec_files_or_proc || [] # @options = options end def call(env) - spec_files = Jasmine.files(@config.spec_files_or_proc) + spec_files = @config.spec_files_or_proc matching_specs = spec_files.select {|spec_file| spec_file =~ /#{Regexp.escape(env["PATH_INFO"])}/ }.compact if !matching_specs.empty? run_adapter = Jasmine::RunAdapter.new(matching_specs, @options) @@ -80,12 +80,6 @@ module Jasmine end - def self.files(f) - result = f - result = result.call if result.respond_to?(:call) - result - end - class Server attr_reader :thin diff --git a/spec/config_spec.rb b/spec/config_spec.rb index 731903a..3a8b657 100644 --- a/spec/config_spec.rb +++ b/spec/config_spec.rb @@ -22,9 +22,9 @@ describe Jasmine::Config do it "should provide a list of all js files" do @config.js_files.should == [ - 'src/javascripts/Example.js', - 'spec/javascript/ExampleSpec.js', - 'spec/javascript/SpecHelper.js', + '/src/javascripts/Example.js', + '/spec/javascript/ExampleSpec.js', + '/spec/javascript/SpecHelper.js', ] end @@ -40,9 +40,9 @@ describe Jasmine::Config do @config.stub!(:spec_path).and_return("spekz") @config.js_files.should == [ - 'public/javascripts/Example.js', - 'spekz/javascript/ExampleSpec.js', - 'spekz/javascript/SpecHelper.js', + '/public/javascripts/Example.js', + '/spekz/javascript/ExampleSpec.js', + '/spekz/javascript/SpecHelper.js', ] @config.mappings.should == {