satisfaction-jasmine 0.4.3

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (33) hide show
  1. data/README.markdown +37 -0
  2. data/bin/jasmine +58 -0
  3. data/generators/jasmine/jasmine_generator.rb +25 -0
  4. data/generators/jasmine/templates/INSTALL +9 -0
  5. data/generators/jasmine/templates/lib/tasks/jasmine.rake +23 -0
  6. data/generators/jasmine/templates/spec/javascripts/ExampleSpec.js +11 -0
  7. data/generators/jasmine/templates/spec/javascripts/SpecHelper.js +1 -0
  8. data/generators/jasmine/templates/spec/javascripts/support/jasmine-rails-with-src-base-url.yml +23 -0
  9. data/generators/jasmine/templates/spec/javascripts/support/jasmine-rails.yml +20 -0
  10. data/generators/jasmine/templates/spec/javascripts/support/jasmine.yml +20 -0
  11. data/generators/jasmine/templates/spec/javascripts/support/jasmine_config.rb +61 -0
  12. data/generators/jasmine/templates/spec/javascripts/support/jasmine_runner.rb +17 -0
  13. data/jasmine/contrib/ruby/jasmine_runner.rb +334 -0
  14. data/jasmine/contrib/ruby/jasmine_spec_builder.rb +153 -0
  15. data/jasmine/contrib/ruby/run.html +47 -0
  16. data/jasmine/lib/TrivialReporter.js +117 -0
  17. data/jasmine/lib/consolex.js +28 -0
  18. data/jasmine/lib/jasmine-0.10.0.js +2261 -0
  19. data/jasmine/lib/jasmine.css +86 -0
  20. data/jasmine/lib/json2.js +478 -0
  21. data/lib/jasmine.rb +6 -0
  22. data/lib/jasmine/base.rb +63 -0
  23. data/lib/jasmine/config.rb +166 -0
  24. data/lib/jasmine/run.html.erb +43 -0
  25. data/lib/jasmine/selenium_driver.rb +44 -0
  26. data/lib/jasmine/server.rb +125 -0
  27. data/lib/jasmine/spec_builder.rb +152 -0
  28. data/spec/config_spec.rb +138 -0
  29. data/spec/jasmine_self_test_config.rb +15 -0
  30. data/spec/jasmine_self_test_spec.rb +18 -0
  31. data/spec/server_spec.rb +65 -0
  32. data/spec/spec_helper.rb +4 -0
  33. metadata +145 -0
data/README.markdown ADDED
@@ -0,0 +1,37 @@
1
+ jasmine-ruby
2
+ ============
3
+
4
+ Jasmine Ruby dynamically serves HTML suites for [Jasmine](http://github.com/pivotal/jasmine)
5
+
6
+ To use:
7
+
8
+ `(sudo) gem install jasmine`
9
+
10
+ Post-installation:
11
+
12
+ For Rails support, use
13
+
14
+ `script/generate jasmine`
15
+
16
+ For other projects, use
17
+
18
+ `jasmine init`
19
+
20
+ After initializing a project, you may
21
+
22
+ `rake jasmine`
23
+
24
+ to set up a server. Opening localhost:8888 in a web browser will now run your jasmine specs.
25
+
26
+ You may also
27
+
28
+ `rake jasmine:ci`
29
+
30
+ which will run your Jasmine suites using selenium and rspec. This task is suitable for running in continuous integration environments.
31
+
32
+ Simple Configuration:
33
+
34
+ Customize `spec/javascripts/support/jasmine.yaml` to enumerate the source files, stylesheets, and spec files you would like the Jasmine runner to include.
35
+ You may use dir glob strings.
36
+
37
+ It is also possible to add overrides into the `spec/javascripts/support/jasmine_config.rb` file directly if you require further customization.
data/bin/jasmine ADDED
@@ -0,0 +1,58 @@
1
+ #!/usr/bin/env ruby
2
+ require 'rubygems'
3
+ require 'rake'
4
+
5
+ def cwd
6
+ File.expand_path(File.join(File.dirname(__FILE__), '..'))
7
+ end
8
+
9
+ def expand(*paths)
10
+ File.expand_path(File.join(*paths))
11
+ end
12
+
13
+ def template_path(filepath)
14
+ expand(cwd, File.join("generators/jasmine/templates", filepath))
15
+ end
16
+
17
+ def dest_path(filepath)
18
+ expand(Dir.pwd, filepath)
19
+ end
20
+
21
+ def copy_unless_exists(relative_path, dest_path = nil)
22
+ unless File.exist?(dest_path(relative_path))
23
+ File.copy(template_path(relative_path), dest_path(dest_path || relative_path))
24
+ end
25
+ end
26
+
27
+ if ARGV[0] == 'init'
28
+ require 'ftools'
29
+ File.makedirs('spec/javascripts')
30
+ File.makedirs('spec/javascripts/support')
31
+
32
+ copy_unless_exists('spec/javascripts/SpecHelper.js')
33
+ copy_unless_exists('spec/javascripts/ExampleSpec.js')
34
+ copy_unless_exists('spec/javascripts/support/jasmine_config.rb')
35
+ copy_unless_exists('spec/javascripts/support/jasmine_runner.rb')
36
+
37
+ rails_tasks_dir = dest_path('lib/tasks')
38
+ if File.exist?(rails_tasks_dir)
39
+ copy_unless_exists('lib/tasks/jasmine.rake')
40
+ copy_unless_exists('spec/javascripts/support/jasmine-rails.yml', 'spec/javascripts/support/jasmine.yml')
41
+ else
42
+ copy_unless_exists('spec/javascripts/support/jasmine.yml')
43
+ write_mode = 'w'
44
+ if File.exist?(dest_path('Rakefile'))
45
+ load dest_path('Rakefile')
46
+ write_mode = 'a'
47
+ end
48
+ unless Rake::Task.task_defined?('jasmine')
49
+ File.open(dest_path('Rakefile'), write_mode) do |f|
50
+ f.write(File.read(template_path('lib/tasks/jasmine.rake')))
51
+ end
52
+ end
53
+ end
54
+ File.open(template_path('INSTALL'), 'r').each_line do |line|
55
+ puts line
56
+ end
57
+ end
58
+
@@ -0,0 +1,25 @@
1
+ class JasmineGenerator < Rails::Generator::Base
2
+ def manifest
3
+ record do |m|
4
+
5
+ m.directory "spec/javascripts"
6
+ m.file "spec/javascripts/SpecHelper.js", "spec/javascripts/SpecHelper.js"
7
+ m.file "spec/javascripts/ExampleSpec.js", "spec/javascripts/ExampleSpec.js"
8
+
9
+ m.directory "spec/javascripts/support"
10
+ m.file "spec/javascripts/support/jasmine_config.rb", "spec/javascripts/support/jasmine_config.rb"
11
+ m.file "spec/javascripts/support/jasmine_runner.rb", "spec/javascripts/support/jasmine_runner.rb"
12
+ m.file "spec/javascripts/support/jasmine-rails.yml", "spec/javascripts/support/jasmine.yml"
13
+
14
+ m.directory "lib/tasks"
15
+ m.file "lib/tasks/jasmine.rake", "lib/tasks/jasmine.rake"
16
+
17
+ m.readme "INSTALL"
18
+ end
19
+ end
20
+
21
+ def file_name
22
+ "create_blog"
23
+ end
24
+
25
+ end
@@ -0,0 +1,9 @@
1
+ Jasmine has been installed with example specs.
2
+
3
+ To run the server:
4
+
5
+ rake jasmine
6
+
7
+ To run the automated CI task with Selenium:
8
+
9
+ rake jasmine:ci
@@ -0,0 +1,23 @@
1
+ namespace :jasmine do
2
+ require 'jasmine'
3
+
4
+ desc "Run continuous integration tests"
5
+ require "spec"
6
+ require 'spec/rake/spectask'
7
+ Spec::Rake::SpecTask.new(:ci) do |t|
8
+ t.spec_opts = ["--color", "--format", "specdoc"]
9
+ t.verbose = true
10
+ t.spec_files = ['spec/javascripts/support/jasmine_runner.rb']
11
+ end
12
+ task :server do
13
+ require 'spec/javascripts/support/jasmine_config'
14
+
15
+ puts "your tests are here:"
16
+ puts " http://localhost:8888/run.html"
17
+
18
+ Jasmine::Config.new.start_server
19
+ end
20
+ end
21
+
22
+ desc "Run specs via server"
23
+ task :jasmine => ['jasmine:server']
@@ -0,0 +1,11 @@
1
+ describe('Example', function () {
2
+ it('should have a passing test', function() {
3
+ expect(true).toEqual(true);
4
+ });
5
+
6
+ describe('nested describe', function () {
7
+ it('should also have a passing test', function () {
8
+ expect(true).toEqual(true);
9
+ });
10
+ });
11
+ });
@@ -0,0 +1 @@
1
+ //You may load required files here, or create test-runner-wide environment settings.
@@ -0,0 +1,23 @@
1
+ # Return an array of filepaths relative to src_dir to include before jasmine specs.
2
+ src_files:
3
+ - javascripts/prototype.js
4
+ - javascripts/effects.js
5
+ - javascripts/controls.js
6
+ - javascripts/dragdrop.js
7
+ - javascripts/application.js
8
+
9
+ # Return an array of stylesheet filepaths relative to src_dir to include before jasmine specs.
10
+ stylesheets:
11
+ - stylesheets/**/*.css
12
+ # Return an array of filepaths relative to spec_dir to include before jasmine specs.
13
+ spec_files:
14
+ - **/*.js
15
+
16
+ # Set a url base instead of a file system base to load src files from. For example you could use this to load dynamically generated js files.
17
+ src_base_url: 'http://localhost:3000'
18
+
19
+ # Source directory path. Your src_files must be returned relative to this path. Will use root if left blank.
20
+ src_dir: public
21
+
22
+ # Spec directory path. Your spec_files must be returned relative to this path.
23
+ spec_dir: spec/javascripts
@@ -0,0 +1,20 @@
1
+ # Return an array of filepaths relative to src_dir to include before jasmine specs.
2
+ src_files:
3
+ - javascripts/prototype.js
4
+ - javascripts/effects.js
5
+ - javascripts/controls.js
6
+ - javascripts/dragdrop.js
7
+ - javascripts/application.js
8
+
9
+ # Return an array of stylesheet filepaths relative to src_dir to include before jasmine specs.
10
+ stylesheets:
11
+ - stylesheets/**/*.css
12
+ # Return an array of filepaths relative to spec_dir to include before jasmine specs.
13
+ spec_files:
14
+ - **/*.js
15
+
16
+ # Source directory path. Your src_files must be returned relative to this path. Will use root if left blank.
17
+ src_dir: public
18
+
19
+ # Spec directory path. Your spec_files must be returned relative to this path.
20
+ spec_dir: spec/javascripts
@@ -0,0 +1,20 @@
1
+ # Return an array of filepaths relative to src_dir to include before jasmine specs.
2
+ #src_files:
3
+ # - lib/source1.js
4
+ # - lib/source2.js
5
+ # - dist/**/*.js
6
+
7
+ # Return an array of stylesheet filepaths relative to src_dir to include before jasmine specs.
8
+ #stylesheets:
9
+ # - css/style.css
10
+ # - stylesheets/*.css
11
+
12
+ # Return an array of filepaths relative to spec_dir to include before jasmine specs.
13
+ #spec_files:
14
+ # - **/*.js
15
+
16
+ # Source directory path. Your src_files must be returned relative to this path. Will use root if left blank.
17
+ #src_dir:
18
+
19
+ # Spec directory path. Your spec_files must be returned relative to this path.
20
+ #spec_dir: spec/javascripts
@@ -0,0 +1,61 @@
1
+ require 'jasmine'
2
+
3
+ class Jasmine::Config
4
+
5
+ # Override these methods if necessary
6
+
7
+ # def project_root
8
+ # Dir.pwd
9
+ # end
10
+
11
+ # Path to your jasmine.yml
12
+ # def simple_config_file
13
+ # File.join(project_root, 'spec/javascripts/support/jasmine.yml')
14
+ # end
15
+
16
+ # Source directory path. Your src_files must be returned relative to this path.
17
+ # def src_dir
18
+ # if simple_config['src_dir']
19
+ # File.join(project_root, simple_config['src_dir'])
20
+ # else
21
+ # project_root
22
+ # end
23
+ # end
24
+
25
+ # Spec directory path. Your spec_files must be returned relative to this path.
26
+ # def spec_dir
27
+ # if simple_config['spec_dir']
28
+ # File.join(project_root, simple_config['spec_dir'])
29
+ # else
30
+ # File.join(project_root, 'spec/javascripts')
31
+ # end
32
+ # end
33
+
34
+ # Return an array of filepaths relative to src_dir to include before jasmine specs.
35
+ # def src_files
36
+ # files = []
37
+ # if simple_config['src_files']
38
+ # files = simple_config['src_files'].collect {|filepath| Dir.glob(filepath)}
39
+ # end
40
+ # files
41
+ # end
42
+
43
+ # Return an array of filepaths relative to spec_dir to include before jasmine specs.
44
+ # def spec_files
45
+ # files = match_files(spec_dir, "**/*.js")
46
+ # if simple_config['spec_files']
47
+ # files = simple_config['spec_files'].collect {|filepath| Dir.glob(filepath)}
48
+ # end
49
+ # files
50
+ # end
51
+
52
+ # Return an array of filepaths relative to src_dir to include before jasmine specs.
53
+ # def stylesheets
54
+ # files = []
55
+ # if simple_config['stylesheets']
56
+ # files = simple_config['stylesheets'].collect {|filepath| Dir.glob(filepath)}
57
+ # end
58
+ # files
59
+ # end
60
+
61
+ end
@@ -0,0 +1,17 @@
1
+ require 'rubygems'
2
+ require File.expand_path(File.join(File.dirname(__FILE__), 'jasmine_config'))
3
+
4
+ jasmine_config = Jasmine::Config.new
5
+ spec_builder = Jasmine::SpecBuilder.new(jasmine_config)
6
+
7
+ should_stop = false
8
+
9
+ Spec::Runner.configure do |config|
10
+ config.after(:suite) do
11
+ spec_builder.stop if should_stop
12
+ end
13
+ end
14
+
15
+ spec_builder.start
16
+ should_stop = true
17
+ spec_builder.declare_suites
@@ -0,0 +1,334 @@
1
+ require 'socket'
2
+ require 'erb'
3
+ require 'json'
4
+
5
+ module Jasmine
6
+ def self.root
7
+ File.expand_path(File.join(File.dirname(__FILE__), '../..'))
8
+ end
9
+
10
+ # this seemingly-over-complex method is necessary to get an open port on at least some of our Macs
11
+ def self.open_socket_on_unused_port
12
+ infos = Socket::getaddrinfo("localhost", nil, Socket::AF_UNSPEC, Socket::SOCK_STREAM, 0, Socket::AI_PASSIVE)
13
+ families = Hash[*infos.collect { |af, *_| af }.uniq.zip([]).flatten]
14
+
15
+ return TCPServer.open('0.0.0.0', 0) if families.has_key?('AF_INET')
16
+ return TCPServer.open('::', 0) if families.has_key?('AF_INET6')
17
+ return TCPServer.open(0)
18
+ end
19
+
20
+ def self.find_unused_port
21
+ socket = open_socket_on_unused_port
22
+ port = socket.addr[1]
23
+ socket.close
24
+ port
25
+ end
26
+
27
+ def self.server_is_listening_on(hostname, port)
28
+ require 'socket'
29
+ begin
30
+ socket = TCPSocket.open(hostname, port)
31
+ rescue Errno::ECONNREFUSED
32
+ return false
33
+ end
34
+ socket.close
35
+ true
36
+ end
37
+
38
+ def self.wait_for_listener(port, name = "required process", seconds_to_wait = 10)
39
+ time_out_at = Time.now + seconds_to_wait
40
+ until server_is_listening_on "localhost", port
41
+ sleep 0.1
42
+ puts "Waiting for #{name} on #{port}..."
43
+ raise "#{name} didn't show up on port #{port} after #{seconds_to_wait} seconds." if Time.now > time_out_at
44
+ end
45
+ end
46
+
47
+ def self.kill_process_group(process_group_id, signal="TERM")
48
+ Process.kill signal, -process_group_id # negative pid means kill process group. (see man 2 kill)
49
+ end
50
+
51
+ def self.cachebust(files, root_dir="", replace=nil, replace_with=nil)
52
+ require 'digest/md5'
53
+ files.collect do |file_name|
54
+ real_file_name = replace && replace_with ? file_name.sub(replace, replace_with) : file_name
55
+ begin
56
+ digest = Digest::MD5.hexdigest(File.read("#{root_dir}#{real_file_name}"))
57
+ rescue
58
+ digest = "MISSING-FILE"
59
+ end
60
+ "#{file_name}?cachebust=#{digest}"
61
+ end
62
+ end
63
+
64
+ class RunAdapter
65
+ def initialize(spec_files_or_proc, options = {})
66
+ @spec_files_or_proc = Jasmine.files(spec_files_or_proc) || []
67
+ @jasmine_files = Jasmine.files(options[:jasmine_files]) || [
68
+ "/__JASMINE_ROOT__/lib/" + File.basename(Dir.glob("#{Jasmine.root}/lib/jasmine*.js").first),
69
+ "/__JASMINE_ROOT__/lib/TrivialReporter.js",
70
+ "/__JASMINE_ROOT__/lib/json2.js",
71
+ "/__JASMINE_ROOT__/lib/consolex.js",
72
+ ]
73
+ @stylesheets = ["/__JASMINE_ROOT__/lib/jasmine.css"] + (Jasmine.files(options[:stylesheets]) || [])
74
+ @spec_helpers = Jasmine.files(options[:spec_helpers]) || []
75
+ end
76
+
77
+ def call(env)
78
+ run
79
+ end
80
+
81
+ def run
82
+ stylesheets = @stylesheets
83
+ spec_helpers = @spec_helpers
84
+ spec_files = @spec_files_or_proc
85
+
86
+ jasmine_files = @jasmine_files
87
+ jasmine_files = jasmine_files.call if jasmine_files.respond_to?(:call)
88
+
89
+ css_files = @stylesheets
90
+
91
+
92
+ body = ERB.new(File.read(File.join(File.dirname(__FILE__), "run.html"))).result(binding)
93
+ [
94
+ 200,
95
+ { 'Content-Type' => 'text/html' },
96
+ body
97
+ ]
98
+ end
99
+
100
+
101
+ end
102
+
103
+ class Redirect
104
+ def initialize(url)
105
+ @url = url
106
+ end
107
+
108
+ def call(env)
109
+ [
110
+ 302,
111
+ { 'Location' => @url },
112
+ []
113
+ ]
114
+ end
115
+ end
116
+
117
+ class JsAlert
118
+ def call(env)
119
+ [
120
+ 200,
121
+ { 'Content-Type' => 'application/javascript' },
122
+ "document.write('<p>Couldn\\'t load #{env["PATH_INFO"]}!</p>');"
123
+ ]
124
+ end
125
+ end
126
+
127
+ class FocusedSuite
128
+ def initialize(spec_files_or_proc, options)
129
+ @spec_files_or_proc = Jasmine.files(spec_files_or_proc) || []
130
+ @options = options
131
+ end
132
+
133
+ def call(env)
134
+ spec_files = @spec_files_or_proc
135
+ matching_specs = spec_files.select {|spec_file| spec_file =~ /#{Regexp.escape(env["PATH_INFO"])}/ }.compact
136
+ if !matching_specs.empty?
137
+ run_adapter = Jasmine::RunAdapter.new(matching_specs, @options)
138
+ run_adapter.run
139
+ else
140
+ [
141
+ 200,
142
+ { 'Content-Type' => 'application/javascript' },
143
+ "document.write('<p>Couldn\\'t find any specs matching #{env["PATH_INFO"]}!</p>');"
144
+ ]
145
+ end
146
+ end
147
+
148
+ end
149
+
150
+ class SimpleServer
151
+ def self.start(port, spec_files_or_proc, mappings, options = {})
152
+ require 'thin'
153
+ config = {
154
+ '/__suite__' => Jasmine::FocusedSuite.new(spec_files_or_proc, options),
155
+ '/run.html' => Jasmine::Redirect.new('/'),
156
+ '/' => Jasmine::RunAdapter.new(spec_files_or_proc, options)
157
+ }
158
+ mappings.each do |from, to|
159
+ config[from] = Rack::File.new(to)
160
+ end
161
+
162
+ config["/__JASMINE_ROOT__"] = Rack::File.new(Jasmine.root)
163
+
164
+ app = Rack::Cascade.new([
165
+ Rack::URLMap.new(config),
166
+ JsAlert.new
167
+ ])
168
+
169
+ begin
170
+ Thin::Server.start('0.0.0.0', port, app)
171
+ rescue RuntimeError => e
172
+ raise e unless e.message == 'no acceptor'
173
+ raise RuntimeError.new("A server is already running on port #{port}")
174
+ end
175
+ end
176
+ end
177
+
178
+ class SimpleClient
179
+ def initialize(selenium_host, selenium_port, selenium_browser_start_command, http_address)
180
+ require 'selenium/client'
181
+ @driver = Selenium::Client::Driver.new(
182
+ selenium_host,
183
+ selenium_port,
184
+ selenium_browser_start_command,
185
+ http_address
186
+ )
187
+ @http_address = http_address
188
+ end
189
+
190
+ def tests_have_finished?
191
+ @driver.get_eval("window.jasmine.getEnv().currentRunner.finished") == "true"
192
+ end
193
+
194
+ def connect
195
+ @driver.start
196
+ @driver.open("/")
197
+ end
198
+
199
+ def disconnect
200
+ @driver.stop
201
+ end
202
+
203
+ def run
204
+ until tests_have_finished? do
205
+ sleep 0.1
206
+ end
207
+
208
+ puts @driver.get_eval("window.results()")
209
+ failed_count = @driver.get_eval("window.jasmine.getEnv().currentRunner.results().failedCount").to_i
210
+ failed_count == 0
211
+ end
212
+
213
+ def eval_js(script)
214
+ escaped_script = "'" + script.gsub(/(['\\])/) { '\\' + $1 } + "'"
215
+
216
+ result = @driver.get_eval(" try { eval(#{escaped_script}, window); } catch(err) { window.eval(#{escaped_script}); }")
217
+ JSON.parse("[#{result}]")[0]
218
+ end
219
+ end
220
+
221
+ class Runner
222
+ def initialize(selenium_jar_path, spec_files, dir_mappings, options={})
223
+ @selenium_jar_path = selenium_jar_path
224
+ @spec_files = spec_files
225
+ @dir_mappings = dir_mappings
226
+ @options = options
227
+
228
+ @browser = options[:browser] ? options[:browser].delete(:browser) : 'firefox'
229
+ @selenium_pid = nil
230
+ @jasmine_server_pid = nil
231
+ @selenium_host = 'localhost'
232
+ @jasmine_server_port = Jasmine::find_unused_port
233
+ @selenium_server_port = Jasmine::find_unused_port
234
+ end
235
+
236
+ def start
237
+ start_jasmine_server
238
+ start_selenium_server
239
+ @client = Jasmine::SimpleClient.new(@selenium_host, @selenium_server_port, "*#{@browser}", "http://localhost:#{@jasmine_server_port}/")
240
+ @client.connect
241
+ end
242
+
243
+ def stop
244
+ @client.disconnect
245
+ stop_selenium_server
246
+ stop_jasmine_server
247
+ end
248
+
249
+ def start_jasmine_server
250
+ @jasmine_server_pid = fork do
251
+ Process.setpgrp
252
+ Jasmine::SimpleServer.start(@jasmine_server_port, @spec_files, @dir_mappings, @options)
253
+ exit! 0
254
+ end
255
+ puts "jasmine server started. pid is #{@jasmine_server_pid}"
256
+ Jasmine::wait_for_listener(@jasmine_server_port, "jasmine server")
257
+ end
258
+
259
+ def start_selenium_server
260
+ @selenium_pid = fork do
261
+ Process.setpgrp
262
+ exec "java -jar #{@selenium_jar_path} -port #{@selenium_server_port} > /dev/null 2>&1"
263
+ end
264
+ puts "selenium started. pid is #{@selenium_pid}"
265
+ Jasmine::wait_for_listener(@selenium_server_port, "selenium server")
266
+ end
267
+
268
+ def stop_jasmine_server
269
+ puts "shutting down Jasmine server..."
270
+ Jasmine::kill_process_group(@jasmine_server_pid) if @jasmine_server_pid
271
+ end
272
+
273
+ def stop_selenium_server
274
+ puts "shutting down Selenium server..."
275
+ Jasmine::kill_process_group(@selenium_pid) if @selenium_pid
276
+ end
277
+
278
+ def run
279
+ begin
280
+ start
281
+ puts "servers are listening on their ports -- running the test script..."
282
+ tests_passed = @client.run
283
+ ensure
284
+ stop
285
+ end
286
+ return tests_passed
287
+ end
288
+
289
+ def eval_js(script)
290
+ @client.eval_js(script)
291
+ end
292
+ end
293
+
294
+ class SauceLabsRunner < Runner
295
+ def initialize(spec_files, dir_mappings, options={})
296
+ @spec_files = spec_files
297
+ @dir_mappings = dir_mappings
298
+ @options = options
299
+
300
+ @browser = options[:browser] ? options[:browser].delete(:browser) : 'firefox'
301
+ @jasmine_server_pid = nil
302
+ @jasmine_server_port = Jasmine::find_unused_port
303
+ @saucelabs_config = SeleniumConfig.new(options[:saucelabs_config], options[:saucelabs_config_file], @jasmine_server_port)
304
+ end
305
+
306
+ def start_selenium_server
307
+ @sauce_tunnel = SauceTunnel.new(@saucelabs_config)
308
+ end
309
+
310
+ def start
311
+ start_jasmine_server
312
+ start_selenium_server
313
+ @client = Jasmine::SimpleClient.new(@saucelabs_config['selenium_server_address'],
314
+ 4444,
315
+ @saucelabs_config['selenium_browser_key'],
316
+ "http://#{@saucelabs_config['application_address']}")
317
+ @client.connect
318
+ end
319
+
320
+ def stop
321
+ @client.disconnect
322
+ @sauce_tunnel.shutdown
323
+ stop_jasmine_server
324
+ end
325
+
326
+ end
327
+
328
+ def self.files(f)
329
+ result = f
330
+ result = result.call if result.respond_to?(:call)
331
+ result
332
+ end
333
+
334
+ end