xian-test-jasmine 0.1.2 → 0.1.3
Sign up to get free protection for your applications and to get access to all the features.
- data/bin/autospec +3 -0
- data/bin/firefox +142 -0
- data/bin/rackup +3 -0
- data/bin/selenium-rc +3 -0
- data/bin/spec +3 -0
- data/bin/thin +3 -0
- data/lib/jasmine.rb +7 -0
- data/lib/jasmine/base.rb +63 -0
- data/lib/jasmine/config.rb +124 -0
- data/lib/{jasmine-ruby → jasmine}/jasmine_helper.rb +1 -1
- data/lib/{jasmine-ruby → jasmine}/jasmine_meta_spec.rb +1 -1
- data/lib/{jasmine-ruby/run.html → jasmine/run.html.erb} +2 -6
- data/lib/jasmine/selenium_driver.rb +44 -0
- data/lib/jasmine/server.rb +130 -0
- data/lib/{jasmine-ruby/jasmine_spec_builder.rb → jasmine/spec_builder.rb} +6 -5
- data/spec/config_spec.rb +53 -0
- data/spec/jasmine_self_test_config.rb +15 -0
- data/spec/jasmine_self_test_spec.rb +18 -0
- data/spec/server_spec.rb +65 -0
- data/spec/spec_helper.rb +3 -0
- data/templates/Rakefile +2 -2
- metadata +28 -12
- data/lib/jasmine-ruby.rb +0 -3
- data/lib/jasmine-ruby/jasmine_runner.rb +0 -300
- data/spec/jasmine_spec.rb +0 -26
- data/templates/example_spec.js +0 -11
- data/templates/jasmine_helper.rb +0 -12
- data/templates/spec_helper.js +0 -1
data/bin/autospec
ADDED
data/bin/firefox
ADDED
@@ -0,0 +1,142 @@
|
|
1
|
+
#!/bin/sh
|
2
|
+
#
|
3
|
+
# ***** BEGIN LICENSE BLOCK *****
|
4
|
+
# Version: MPL 1.1/GPL 2.0/LGPL 2.1
|
5
|
+
#
|
6
|
+
# The contents of this file are subject to the Mozilla Public License Version
|
7
|
+
# 1.1 (the "License"); you may not use this file except in compliance with
|
8
|
+
# the License. You may obtain a copy of the License at
|
9
|
+
# http://www.mozilla.org/MPL/
|
10
|
+
#
|
11
|
+
# Software distributed under the License is distributed on an "AS IS" basis,
|
12
|
+
# WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
|
13
|
+
# for the specific language governing rights and limitations under the
|
14
|
+
# License.
|
15
|
+
#
|
16
|
+
# The Original Code is mozilla.org Code.
|
17
|
+
#
|
18
|
+
# The Initial Developer of the Original Code is
|
19
|
+
# Netscape Communications Corporation.
|
20
|
+
# Portions created by the Initial Developer are Copyright (C) 1998
|
21
|
+
# the Initial Developer. All Rights Reserved.
|
22
|
+
#
|
23
|
+
# Contributor(s):
|
24
|
+
#
|
25
|
+
# Alternatively, the contents of this file may be used under the terms of
|
26
|
+
# either the GNU General Public License Version 2 or later (the "GPL"), or
|
27
|
+
# the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
|
28
|
+
# in which case the provisions of the GPL or the LGPL are applicable instead
|
29
|
+
# of those above. If you wish to allow use of your version of this file only
|
30
|
+
# under the terms of either the GPL or the LGPL, and not to allow others to
|
31
|
+
# use your version of this file under the terms of the MPL, indicate your
|
32
|
+
# decision by deleting the provisions above and replace them with the notice
|
33
|
+
# and other provisions required by the GPL or the LGPL. If you do not delete
|
34
|
+
# the provisions above, a recipient may use your version of this file under
|
35
|
+
# the terms of any one of the MPL, the GPL or the LGPL.
|
36
|
+
#
|
37
|
+
# ***** END LICENSE BLOCK *****
|
38
|
+
|
39
|
+
## $Id: mozilla.in,v 1.16 2007/10/05 07:29:26 reed%reedloden.com Exp $
|
40
|
+
##
|
41
|
+
## Usage:
|
42
|
+
##
|
43
|
+
## $ mozilla [args]
|
44
|
+
##
|
45
|
+
## This script is meant to run the mozilla-bin binary from either
|
46
|
+
## mozilla/xpfe/bootstrap or mozilla/dist/bin.
|
47
|
+
##
|
48
|
+
## The script will setup all the environment voodoo needed to make
|
49
|
+
## the mozilla-bin binary to work.
|
50
|
+
##
|
51
|
+
|
52
|
+
#uncomment for debugging
|
53
|
+
#set -x
|
54
|
+
|
55
|
+
moz_libdir=/usr/local/lib/firefox-3.0.9
|
56
|
+
|
57
|
+
# Use run-mozilla.sh in the current dir if it exists
|
58
|
+
# If not, then start resolving symlinks until we find run-mozilla.sh
|
59
|
+
found=0
|
60
|
+
progname="$0"
|
61
|
+
curdir=`dirname "$progname"`
|
62
|
+
progbase=`basename "$progname"`
|
63
|
+
run_moz="$curdir/run-mozilla.sh"
|
64
|
+
if test -x "$run_moz"; then
|
65
|
+
dist_bin="$curdir"
|
66
|
+
found=1
|
67
|
+
else
|
68
|
+
here=`/bin/pwd`
|
69
|
+
while [ -h "$progname" ]; do
|
70
|
+
bn=`basename "$progname"`
|
71
|
+
cd `dirname "$progname"`
|
72
|
+
progname=`/bin/ls -l "$bn" | sed -e 's/^.* -> //' `
|
73
|
+
progbase=`basename "$progname"`
|
74
|
+
if [ ! -x "$progname" ]; then
|
75
|
+
break
|
76
|
+
fi
|
77
|
+
curdir=`dirname "$progname"`
|
78
|
+
run_moz="$curdir/run-mozilla.sh"
|
79
|
+
if [ -x "$run_moz" ]; then
|
80
|
+
cd "$curdir"
|
81
|
+
dist_bin=`pwd`
|
82
|
+
run_moz="$dist_bin/run-mozilla.sh"
|
83
|
+
found=1
|
84
|
+
break
|
85
|
+
fi
|
86
|
+
done
|
87
|
+
cd "$here"
|
88
|
+
fi
|
89
|
+
if [ $found = 0 ]; then
|
90
|
+
# Check default compile-time libdir
|
91
|
+
if [ -x "$moz_libdir/run-mozilla.sh" ]; then
|
92
|
+
dist_bin="$moz_libdir"
|
93
|
+
else
|
94
|
+
echo "Cannot find mozilla runtime directory. Exiting."
|
95
|
+
exit 1
|
96
|
+
fi
|
97
|
+
fi
|
98
|
+
|
99
|
+
script_args=""
|
100
|
+
debugging=0
|
101
|
+
MOZILLA_BIN="${progbase}-bin"
|
102
|
+
|
103
|
+
if [ "$OSTYPE" = "beos" ]; then
|
104
|
+
mimeset -F "$MOZILLA_BIN"
|
105
|
+
fi
|
106
|
+
|
107
|
+
pass_arg_count=0
|
108
|
+
while [ $# -gt $pass_arg_count ]
|
109
|
+
do
|
110
|
+
case "$1" in
|
111
|
+
-p | --pure | -pure)
|
112
|
+
MOZILLA_BIN="${MOZILLA_BIN}.pure"
|
113
|
+
shift
|
114
|
+
;;
|
115
|
+
-g | --debug)
|
116
|
+
script_args="$script_args -g"
|
117
|
+
debugging=1
|
118
|
+
shift
|
119
|
+
;;
|
120
|
+
-d | --debugger)
|
121
|
+
script_args="$script_args -d $2"
|
122
|
+
shift 2
|
123
|
+
;;
|
124
|
+
*)
|
125
|
+
# Move the unrecognized argument to the end of the list.
|
126
|
+
arg="$1"
|
127
|
+
shift
|
128
|
+
set -- "$@" "$arg"
|
129
|
+
pass_arg_count=`expr $pass_arg_count + 1`
|
130
|
+
;;
|
131
|
+
esac
|
132
|
+
done
|
133
|
+
|
134
|
+
if [ $debugging = 1 ]
|
135
|
+
then
|
136
|
+
echo $dist_bin/run-mozilla.sh $script_args $dist_bin/$MOZILLA_BIN "$@"
|
137
|
+
fi
|
138
|
+
"$dist_bin/run-mozilla.sh" $script_args "$dist_bin/$MOZILLA_BIN" "$@"
|
139
|
+
exitcode=$?
|
140
|
+
|
141
|
+
exit $exitcode
|
142
|
+
# EOF.
|
data/bin/rackup
ADDED
data/bin/selenium-rc
ADDED
data/bin/spec
ADDED
data/bin/thin
ADDED
data/lib/jasmine.rb
ADDED
data/lib/jasmine/base.rb
ADDED
@@ -0,0 +1,63 @@
|
|
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__), '../../jasmine'))
|
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
|
+
end
|
@@ -0,0 +1,124 @@
|
|
1
|
+
module Jasmine
|
2
|
+
class Config
|
3
|
+
def initialize(options = {})
|
4
|
+
require 'selenium_rc'
|
5
|
+
@selenium_jar_path = SeleniumRC::Server.allocate.jar_path
|
6
|
+
@options = options
|
7
|
+
|
8
|
+
@browser = options[:browser] ? options.delete(:browser) : 'firefox'
|
9
|
+
@selenium_pid = nil
|
10
|
+
@jasmine_server_pid = nil
|
11
|
+
end
|
12
|
+
|
13
|
+
def start_server(port = 8888)
|
14
|
+
Jasmine::Server.new(port, self).start
|
15
|
+
end
|
16
|
+
|
17
|
+
def start
|
18
|
+
start_servers
|
19
|
+
@client = Jasmine::SeleniumDriver.new("localhost", @selenium_server_port, "*#{@browser}", "http://localhost:#{@jasmine_server_port}/")
|
20
|
+
@client.connect
|
21
|
+
end
|
22
|
+
|
23
|
+
def stop
|
24
|
+
@client.disconnect
|
25
|
+
stop_servers
|
26
|
+
end
|
27
|
+
|
28
|
+
def start_servers
|
29
|
+
@jasmine_server_port = Jasmine::find_unused_port
|
30
|
+
@selenium_server_port = Jasmine::find_unused_port
|
31
|
+
|
32
|
+
server = Jasmine::Server.new(@jasmine_server_port, self)
|
33
|
+
|
34
|
+
@selenium_pid = fork do
|
35
|
+
Process.setpgrp
|
36
|
+
exec "java -jar #{@selenium_jar_path} -port #{@selenium_server_port} > /dev/null 2>&1"
|
37
|
+
end
|
38
|
+
puts "selenium started. pid is #{@selenium_pid}"
|
39
|
+
|
40
|
+
@jasmine_server_pid = fork do
|
41
|
+
Process.setpgrp
|
42
|
+
server.start
|
43
|
+
exit! 0
|
44
|
+
end
|
45
|
+
puts "jasmine server started. pid is #{@jasmine_server_pid}"
|
46
|
+
|
47
|
+
Jasmine::wait_for_listener(@selenium_server_port, "selenium server")
|
48
|
+
Jasmine::wait_for_listener(@jasmine_server_port, "jasmine server")
|
49
|
+
end
|
50
|
+
|
51
|
+
def stop_servers
|
52
|
+
puts "shutting down the servers..."
|
53
|
+
Jasmine::kill_process_group(@selenium_pid) if @selenium_pid
|
54
|
+
Jasmine::kill_process_group(@jasmine_server_pid) if @jasmine_server_pid
|
55
|
+
end
|
56
|
+
|
57
|
+
def run
|
58
|
+
begin
|
59
|
+
start
|
60
|
+
puts "servers are listening on their ports -- running the test script..."
|
61
|
+
tests_passed = @client.run
|
62
|
+
ensure
|
63
|
+
stop
|
64
|
+
end
|
65
|
+
return tests_passed
|
66
|
+
end
|
67
|
+
|
68
|
+
def eval_js(script)
|
69
|
+
@client.eval_js(script)
|
70
|
+
end
|
71
|
+
|
72
|
+
def mappings
|
73
|
+
raise "You need to declare a mappings method in #{self.class}!"
|
74
|
+
end
|
75
|
+
|
76
|
+
def stylesheets
|
77
|
+
[]
|
78
|
+
end
|
79
|
+
|
80
|
+
def src_files
|
81
|
+
[]
|
82
|
+
end
|
83
|
+
|
84
|
+
def spec_files
|
85
|
+
raise "You need to declare a spec_files method in #{self.class}!"
|
86
|
+
end
|
87
|
+
|
88
|
+
def match_files(dir, pattern)
|
89
|
+
dir = File.expand_path(dir)
|
90
|
+
Dir.glob(File.join(dir, pattern)).collect {|f| f.sub("#{dir}/", "")}.sort
|
91
|
+
end
|
92
|
+
|
93
|
+
def src_files
|
94
|
+
match_files(src_dir, "**/*.js")
|
95
|
+
end
|
96
|
+
|
97
|
+
def src_path
|
98
|
+
"src"
|
99
|
+
end
|
100
|
+
|
101
|
+
def spec_path
|
102
|
+
"spec"
|
103
|
+
end
|
104
|
+
|
105
|
+
def spec_files
|
106
|
+
match_files(spec_dir, "**/*.js")
|
107
|
+
end
|
108
|
+
|
109
|
+
def mappings
|
110
|
+
{
|
111
|
+
"/" + src_path => src_dir,
|
112
|
+
"/" + spec_path => spec_dir
|
113
|
+
}
|
114
|
+
end
|
115
|
+
|
116
|
+
def js_files
|
117
|
+
src_files.collect {|f| File.join(src_path, f) } + spec_files.collect {|f| File.join(spec_path, f) }
|
118
|
+
end
|
119
|
+
|
120
|
+
def spec_files_full_paths
|
121
|
+
spec_files.collect {|spec_file| File.join(spec_dir, spec_file) }
|
122
|
+
end
|
123
|
+
end
|
124
|
+
end
|
@@ -34,7 +34,7 @@ class JasmineHelper
|
|
34
34
|
end
|
35
35
|
|
36
36
|
def self.meta_spec_path
|
37
|
-
File.expand_path(File.join(File.dirname(__FILE__), '..', '..', 'lib', 'jasmine
|
37
|
+
File.expand_path(File.join(File.dirname(__FILE__), '..', '..', 'lib', 'jasmine', 'jasmine_meta_spec.rb'))
|
38
38
|
end
|
39
39
|
|
40
40
|
def self.files
|
@@ -6,7 +6,7 @@ if File.exist?(helper_overrides)
|
|
6
6
|
require helper_overrides
|
7
7
|
end
|
8
8
|
require File.expand_path(File.join(File.dirname(__FILE__), "jasmine_runner.rb"))
|
9
|
-
require File.expand_path(File.join(File.dirname(__FILE__), "
|
9
|
+
require File.expand_path(File.join(File.dirname(__FILE__), "spec_builder"))
|
10
10
|
|
11
11
|
jasmine_runner = Jasmine::Runner.new(SeleniumRC::Server.new.jar_path,
|
12
12
|
Dir.pwd,
|
@@ -11,10 +11,6 @@
|
|
11
11
|
<script src="<%= jasmine_file %>" type="text/javascript"></script>
|
12
12
|
<% end %>
|
13
13
|
|
14
|
-
<% spec_helpers.each do |spec_helper| %>
|
15
|
-
<script src="<%= spec_helper %>" type="text/javascript"></script>
|
16
|
-
<% end %>
|
17
|
-
|
18
14
|
<script type="text/javascript">
|
19
15
|
var jsApiReporter;
|
20
16
|
(function() {
|
@@ -36,8 +32,8 @@
|
|
36
32
|
})();
|
37
33
|
</script>
|
38
34
|
|
39
|
-
<%
|
40
|
-
<script src="<%=
|
35
|
+
<% js_files.each do |js_file| %>
|
36
|
+
<script src="<%= js_file %>" type="text/javascript"></script>
|
41
37
|
<% end %>
|
42
38
|
|
43
39
|
</head>
|
@@ -0,0 +1,44 @@
|
|
1
|
+
module Jasmine
|
2
|
+
class SeleniumDriver
|
3
|
+
def initialize(selenium_host, selenium_port, selenium_browser_start_command, http_address)
|
4
|
+
require 'selenium/client'
|
5
|
+
@driver = Selenium::Client::Driver.new(
|
6
|
+
selenium_host,
|
7
|
+
selenium_port,
|
8
|
+
selenium_browser_start_command,
|
9
|
+
http_address
|
10
|
+
)
|
11
|
+
@http_address = http_address
|
12
|
+
end
|
13
|
+
|
14
|
+
def tests_have_finished?
|
15
|
+
@driver.get_eval("window.jasmine.getEnv().currentRunner.finished") == "true"
|
16
|
+
end
|
17
|
+
|
18
|
+
def connect
|
19
|
+
@driver.start
|
20
|
+
@driver.open("/")
|
21
|
+
end
|
22
|
+
|
23
|
+
def disconnect
|
24
|
+
@driver.stop
|
25
|
+
end
|
26
|
+
|
27
|
+
def run
|
28
|
+
until tests_have_finished? do
|
29
|
+
sleep 0.1
|
30
|
+
end
|
31
|
+
|
32
|
+
puts @driver.get_eval("window.results()")
|
33
|
+
failed_count = @driver.get_eval("window.jasmine.getEnv().currentRunner.results().failedCount").to_i
|
34
|
+
failed_count == 0
|
35
|
+
end
|
36
|
+
|
37
|
+
def eval_js(script)
|
38
|
+
escaped_script = "'" + script.gsub(/(['\\])/) { '\\' + $1 } + "'"
|
39
|
+
|
40
|
+
result = @driver.get_eval(" try { eval(#{escaped_script}, window); } catch(err) { window.eval(#{escaped_script}); }")
|
41
|
+
JSON.parse("[#{result}]")[0]
|
42
|
+
end
|
43
|
+
end
|
44
|
+
end
|
@@ -0,0 +1,130 @@
|
|
1
|
+
module Jasmine
|
2
|
+
class RunAdapter
|
3
|
+
def initialize(config)
|
4
|
+
@config = config
|
5
|
+
@jasmine_files = [
|
6
|
+
"/__JASMINE_ROOT__/lib/" + File.basename(Dir.glob("#{Jasmine.root}/lib/jasmine*.js").first),
|
7
|
+
"/__JASMINE_ROOT__/lib/TrivialReporter.js",
|
8
|
+
"/__JASMINE_ROOT__/lib/json2.js",
|
9
|
+
"/__JASMINE_ROOT__/lib/consolex.js",
|
10
|
+
]
|
11
|
+
@jasmine_stylesheets = ["/__JASMINE_ROOT__/lib/jasmine.css"]
|
12
|
+
end
|
13
|
+
|
14
|
+
def call(env)
|
15
|
+
run
|
16
|
+
end
|
17
|
+
|
18
|
+
#noinspection RubyUnusedLocalVariable
|
19
|
+
def run
|
20
|
+
jasmine_files = @jasmine_files
|
21
|
+
css_files = @jasmine_stylesheets + (Jasmine.files(@config.stylesheets) || [])
|
22
|
+
js_files = Jasmine.files(@config.js_files)
|
23
|
+
|
24
|
+
body = ERB.new(File.read(File.join(File.dirname(__FILE__), "run.html.erb"))).result(binding)
|
25
|
+
[
|
26
|
+
200,
|
27
|
+
{ 'Content-Type' => 'text/html' },
|
28
|
+
body
|
29
|
+
]
|
30
|
+
end
|
31
|
+
|
32
|
+
|
33
|
+
end
|
34
|
+
|
35
|
+
class Redirect
|
36
|
+
def initialize(url)
|
37
|
+
@url = url
|
38
|
+
end
|
39
|
+
|
40
|
+
def call(env)
|
41
|
+
[
|
42
|
+
302,
|
43
|
+
{ 'Location' => @url },
|
44
|
+
[]
|
45
|
+
]
|
46
|
+
end
|
47
|
+
end
|
48
|
+
|
49
|
+
class JsAlert
|
50
|
+
def call(env)
|
51
|
+
[
|
52
|
+
200,
|
53
|
+
{ 'Content-Type' => 'application/javascript' },
|
54
|
+
"document.write('<p>Couldn\\'t load #{env["PATH_INFO"]}!</p>');"
|
55
|
+
]
|
56
|
+
end
|
57
|
+
end
|
58
|
+
|
59
|
+
class FocusedSuite
|
60
|
+
def initialize(config)
|
61
|
+
@config = config
|
62
|
+
# @spec_files_or_proc = Jasmine.files(spec_files_or_proc) || []
|
63
|
+
# @options = options
|
64
|
+
end
|
65
|
+
|
66
|
+
def call(env)
|
67
|
+
spec_files = Jasmine.files(@config.spec_files_or_proc)
|
68
|
+
matching_specs = spec_files.select {|spec_file| spec_file =~ /#{Regexp.escape(env["PATH_INFO"])}/ }.compact
|
69
|
+
if !matching_specs.empty?
|
70
|
+
run_adapter = Jasmine::RunAdapter.new(matching_specs, @options)
|
71
|
+
run_adapter.run
|
72
|
+
else
|
73
|
+
[
|
74
|
+
200,
|
75
|
+
{ 'Content-Type' => 'application/javascript' },
|
76
|
+
"document.write('<p>Couldn\\'t find any specs matching #{env["PATH_INFO"]}!</p>');"
|
77
|
+
]
|
78
|
+
end
|
79
|
+
end
|
80
|
+
|
81
|
+
end
|
82
|
+
|
83
|
+
def self.files(f)
|
84
|
+
result = f
|
85
|
+
result = result.call if result.respond_to?(:call)
|
86
|
+
result
|
87
|
+
end
|
88
|
+
|
89
|
+
class Server
|
90
|
+
attr_reader :thin
|
91
|
+
|
92
|
+
def initialize(port, config)
|
93
|
+
@port = port
|
94
|
+
@config = config
|
95
|
+
|
96
|
+
require 'thin'
|
97
|
+
thin_config = {
|
98
|
+
'/__suite__' => Jasmine::FocusedSuite.new(@config),
|
99
|
+
'/run.html' => Jasmine::Redirect.new('/'),
|
100
|
+
'/' => Jasmine::RunAdapter.new(@config)
|
101
|
+
}
|
102
|
+
|
103
|
+
@config.mappings.each do |from, to|
|
104
|
+
thin_config[from] = Rack::File.new(to)
|
105
|
+
end
|
106
|
+
|
107
|
+
thin_config["/__JASMINE_ROOT__"] = Rack::File.new(Jasmine.root)
|
108
|
+
|
109
|
+
app = Rack::Cascade.new([
|
110
|
+
Rack::URLMap.new(thin_config),
|
111
|
+
JsAlert.new
|
112
|
+
])
|
113
|
+
|
114
|
+
@thin = Thin::Server.new('0.0.0.0', @port, app)
|
115
|
+
end
|
116
|
+
|
117
|
+
def start
|
118
|
+
begin
|
119
|
+
thin.start
|
120
|
+
rescue RuntimeError => e
|
121
|
+
raise e unless e.message == 'no acceptor'
|
122
|
+
raise RuntimeError.new("A server is already running on port #{@port}")
|
123
|
+
end
|
124
|
+
end
|
125
|
+
|
126
|
+
def stop
|
127
|
+
thin.stop
|
128
|
+
end
|
129
|
+
end
|
130
|
+
end
|
@@ -1,12 +1,13 @@
|
|
1
1
|
require 'enumerator'
|
2
|
-
module Jasmine
|
3
2
|
|
3
|
+
module Jasmine
|
4
4
|
class SpecBuilder
|
5
5
|
attr_accessor :suites
|
6
6
|
|
7
|
-
def initialize(
|
8
|
-
@
|
9
|
-
@
|
7
|
+
def initialize(config)
|
8
|
+
@config = config
|
9
|
+
@spec_files = config.spec_files
|
10
|
+
@runner = config
|
10
11
|
@spec_ids = []
|
11
12
|
end
|
12
13
|
|
@@ -31,7 +32,7 @@ module Jasmine
|
|
31
32
|
|
32
33
|
example_name_parts = []
|
33
34
|
previous_indent_level = 0
|
34
|
-
@
|
35
|
+
@config.spec_files_full_paths.each do |filename|
|
35
36
|
line_number = 1
|
36
37
|
File.open(filename, "r") do |file|
|
37
38
|
file.readlines.each do |line|
|
data/spec/config_spec.rb
ADDED
@@ -0,0 +1,53 @@
|
|
1
|
+
require File.expand_path(File.join(File.dirname(__FILE__), "spec_helper"))
|
2
|
+
|
3
|
+
describe Jasmine::Config do
|
4
|
+
before(:each) do
|
5
|
+
@template_dir = File.expand_path(File.join(File.dirname(__FILE__), "../templates"))
|
6
|
+
@config = Jasmine::Config.new
|
7
|
+
@config.stub!(:src_dir).and_return(File.join(@template_dir, "public"))
|
8
|
+
@config.stub!(:spec_dir).and_return(File.join(@template_dir, "spec"))
|
9
|
+
end
|
10
|
+
|
11
|
+
it "should provide a list of all src and spec files" do
|
12
|
+
@config.src_files.should == ['javascripts/Example.js']
|
13
|
+
@config.spec_files.should == ['javascript/ExampleSpec.js', 'javascript/SpecHelper.js']
|
14
|
+
end
|
15
|
+
|
16
|
+
it "should provide a list of all spec files with full paths" do
|
17
|
+
@config.spec_files_full_paths.should == [
|
18
|
+
File.join(@template_dir, 'spec/javascript/ExampleSpec.js'),
|
19
|
+
File.join(@template_dir, 'spec/javascript/SpecHelper.js')
|
20
|
+
]
|
21
|
+
end
|
22
|
+
|
23
|
+
it "should provide a list of all js files" do
|
24
|
+
@config.js_files.should == [
|
25
|
+
'src/javascripts/Example.js',
|
26
|
+
'spec/javascript/ExampleSpec.js',
|
27
|
+
'spec/javascript/SpecHelper.js',
|
28
|
+
]
|
29
|
+
end
|
30
|
+
|
31
|
+
it "should provide dir mappings" do
|
32
|
+
@config.mappings.should == {
|
33
|
+
'/src' => @config.src_dir,
|
34
|
+
'/spec' => @config.spec_dir
|
35
|
+
}
|
36
|
+
end
|
37
|
+
|
38
|
+
it "should allow overriding src and spec paths" do
|
39
|
+
@config.stub!(:src_path).and_return("public")
|
40
|
+
@config.stub!(:spec_path).and_return("spekz")
|
41
|
+
|
42
|
+
@config.js_files.should == [
|
43
|
+
'public/javascripts/Example.js',
|
44
|
+
'spekz/javascript/ExampleSpec.js',
|
45
|
+
'spekz/javascript/SpecHelper.js',
|
46
|
+
]
|
47
|
+
|
48
|
+
@config.mappings.should == {
|
49
|
+
'/public' => @config.src_dir,
|
50
|
+
'/spekz' => @config.spec_dir
|
51
|
+
}
|
52
|
+
end
|
53
|
+
end
|
@@ -0,0 +1,15 @@
|
|
1
|
+
require 'jasmine'
|
2
|
+
|
3
|
+
class JasmineSelfTestConfig < Jasmine::Config
|
4
|
+
def proj_root
|
5
|
+
File.expand_path(File.join(File.dirname(__FILE__), ".."))
|
6
|
+
end
|
7
|
+
|
8
|
+
def src_dir
|
9
|
+
File.join(proj_root, 'src')
|
10
|
+
end
|
11
|
+
|
12
|
+
def spec_dir
|
13
|
+
File.join(proj_root, 'jasmine/spec')
|
14
|
+
end
|
15
|
+
end
|
@@ -0,0 +1,18 @@
|
|
1
|
+
require File.expand_path(File.join(File.dirname(__FILE__), "spec_helper"))
|
2
|
+
|
3
|
+
require 'jasmine_self_test_config'
|
4
|
+
|
5
|
+
jasmine_config = JasmineSelfTestConfig.new
|
6
|
+
spec_builder = Jasmine::SpecBuilder.new(jasmine_config)
|
7
|
+
|
8
|
+
should_stop = false
|
9
|
+
|
10
|
+
Spec::Runner.configure do |config|
|
11
|
+
config.after(:suite) do
|
12
|
+
spec_builder.stop if should_stop
|
13
|
+
end
|
14
|
+
end
|
15
|
+
|
16
|
+
spec_builder.start
|
17
|
+
should_stop = true
|
18
|
+
spec_builder.declare_suites
|
data/spec/server_spec.rb
ADDED
@@ -0,0 +1,65 @@
|
|
1
|
+
require File.expand_path(File.join(File.dirname(__FILE__), "spec_helper"))
|
2
|
+
|
3
|
+
def read(body)
|
4
|
+
return body if body.is_a?(String)
|
5
|
+
out = ""
|
6
|
+
body.each {|data| out += data }
|
7
|
+
out
|
8
|
+
end
|
9
|
+
|
10
|
+
describe Jasmine::Server do
|
11
|
+
before(:each) do
|
12
|
+
config = Jasmine::Config.new
|
13
|
+
config.stub!(:mappings).and_return({
|
14
|
+
"/src" => File.join(Jasmine.root, "src"),
|
15
|
+
"/spec" => File.join(Jasmine.root, "spec")
|
16
|
+
})
|
17
|
+
|
18
|
+
config.stub!(:js_files).and_return(["/src/file1.js", "/spec/file2.js"])
|
19
|
+
|
20
|
+
@server = Jasmine::Server.new(0, config)
|
21
|
+
@thin_app = @server.thin.app
|
22
|
+
end
|
23
|
+
|
24
|
+
after(:each) do
|
25
|
+
@server.thin.stop if @server && @server.thin.running?
|
26
|
+
end
|
27
|
+
|
28
|
+
it "should serve static files" do
|
29
|
+
code, headers, body = @thin_app.call("PATH_INFO" => "/spec/suites/EnvSpec.js", "SCRIPT_NAME" => "xxx")
|
30
|
+
code.should == 200
|
31
|
+
headers["Content-Type"].should == "application/javascript"
|
32
|
+
read(body).should == File.read(File.join(Jasmine.root, "spec/suites/EnvSpec.js"))
|
33
|
+
end
|
34
|
+
|
35
|
+
it "should serve Jasmine static files under /__JASMINE_ROOT__/" do
|
36
|
+
code, headers, body = @thin_app.call("PATH_INFO" => "/__JASMINE_ROOT__/lib/jasmine.css", "SCRIPT_NAME" => "xxx")
|
37
|
+
code.should == 200
|
38
|
+
headers["Content-Type"].should == "text/css"
|
39
|
+
read(body).should == File.read(File.join(Jasmine.root, "lib/jasmine.css"))
|
40
|
+
end
|
41
|
+
|
42
|
+
it "should redirect /run.html to /" do
|
43
|
+
code, headers, body = @thin_app.call("PATH_INFO" => "/run.html", "SCRIPT_NAME" => "xxx")
|
44
|
+
code.should == 302
|
45
|
+
headers["Location"].should == "/"
|
46
|
+
end
|
47
|
+
|
48
|
+
describe "/ page" do
|
49
|
+
it "should load each js file in order" do
|
50
|
+
code, headers, body = @thin_app.call("PATH_INFO" => "/", "SCRIPT_NAME" => "xxx")
|
51
|
+
code.should == 200
|
52
|
+
body = read(body)
|
53
|
+
body.should include("\"/src/file1.js")
|
54
|
+
body.should include("\"/spec/file2.js")
|
55
|
+
body.should satisfy {|s| s.index("/src/file1.js") < s.index("/spec/file2.js") }
|
56
|
+
end
|
57
|
+
end
|
58
|
+
|
59
|
+
it "should display an error using JS for 404's" do
|
60
|
+
code, headers, body = @thin_app.call("PATH_INFO" => "/spec/NonExistantFile.js", "SCRIPT_NAME" => "xxx")
|
61
|
+
code.should == 200 # todo: shouldn't this be 404? will that work with all browsers?
|
62
|
+
headers["Content-Type"].should == "application/javascript"
|
63
|
+
read(body).should == "document.write('<p>Couldn\\'t load /spec/NonExistantFile.js!</p>');"
|
64
|
+
end
|
65
|
+
end
|
data/spec/spec_helper.rb
ADDED
data/templates/Rakefile
CHANGED
@@ -1,5 +1,5 @@
|
|
1
1
|
namespace :jasmine do
|
2
|
-
require 'jasmine
|
2
|
+
require 'jasmine'
|
3
3
|
helper_overrides = File.expand_path(File.join(File.dirname(__FILE__), "spec/helpers/jasmine_helper.rb"))
|
4
4
|
if File.exist?(helper_overrides)
|
5
5
|
require helper_overrides
|
@@ -17,7 +17,7 @@ namespace :jasmine do
|
|
17
17
|
puts "your tests are here:"
|
18
18
|
puts " http://localhost:8888/run.html"
|
19
19
|
|
20
|
-
Jasmine::
|
20
|
+
Jasmine::Server.start(8888,
|
21
21
|
File.expand_path(Dir.pwd),
|
22
22
|
lambda { JasmineHelper.specs },
|
23
23
|
{ :spec_helpers => JasmineHelper.files + JasmineHelper.spec_helpers,
|
metadata
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: xian-test-jasmine
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 0.1.
|
4
|
+
version: 0.1.3
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- Rajan Agaskar
|
@@ -9,7 +9,7 @@ autorequire:
|
|
9
9
|
bindir: bin
|
10
10
|
cert_chain: []
|
11
11
|
|
12
|
-
date: 2009-12-
|
12
|
+
date: 2009-12-28 00:00:00 -06:00
|
13
13
|
default_executable:
|
14
14
|
dependencies:
|
15
15
|
- !ruby/object:Gem::Dependency
|
@@ -65,40 +65,52 @@ dependencies:
|
|
65
65
|
description: Jasmine Ruby
|
66
66
|
email: ragaskar@gmail.com
|
67
67
|
executables:
|
68
|
+
- autospec
|
68
69
|
- edit_json.rb
|
70
|
+
- firefox
|
69
71
|
- git
|
70
72
|
- jasmine
|
71
73
|
- jeweler
|
72
74
|
- prettify_json.rb
|
75
|
+
- rackup
|
73
76
|
- rake
|
74
77
|
- rubyforge
|
78
|
+
- selenium-rc
|
79
|
+
- spec
|
80
|
+
- thin
|
75
81
|
extensions: []
|
76
82
|
|
77
83
|
extra_rdoc_files:
|
78
84
|
- README.markdown
|
79
85
|
files:
|
86
|
+
- bin/autospec
|
80
87
|
- bin/edit_json.rb
|
88
|
+
- bin/firefox
|
81
89
|
- bin/git
|
82
90
|
- bin/jasmine
|
83
91
|
- bin/jeweler
|
84
92
|
- bin/prettify_json.rb
|
93
|
+
- bin/rackup
|
85
94
|
- bin/rake
|
86
95
|
- bin/rubyforge
|
96
|
+
- bin/selenium-rc
|
97
|
+
- bin/spec
|
98
|
+
- bin/thin
|
87
99
|
- jasmine/lib/TrivialReporter.js
|
88
100
|
- jasmine/lib/consolex.js
|
89
101
|
- jasmine/lib/jasmine-0.10.0.js
|
90
102
|
- jasmine/lib/jasmine.css
|
91
103
|
- jasmine/lib/json2.js
|
92
|
-
- lib/jasmine
|
93
|
-
- lib/jasmine
|
94
|
-
- lib/jasmine
|
95
|
-
- lib/jasmine
|
96
|
-
- lib/jasmine
|
97
|
-
- lib/jasmine
|
104
|
+
- lib/jasmine.rb
|
105
|
+
- lib/jasmine/base.rb
|
106
|
+
- lib/jasmine/config.rb
|
107
|
+
- lib/jasmine/jasmine_helper.rb
|
108
|
+
- lib/jasmine/jasmine_meta_spec.rb
|
109
|
+
- lib/jasmine/run.html.erb
|
110
|
+
- lib/jasmine/selenium_driver.rb
|
111
|
+
- lib/jasmine/server.rb
|
112
|
+
- lib/jasmine/spec_builder.rb
|
98
113
|
- templates/Rakefile
|
99
|
-
- templates/example_spec.js
|
100
|
-
- templates/jasmine_helper.rb
|
101
|
-
- templates/spec_helper.js
|
102
114
|
- README.markdown
|
103
115
|
has_rdoc: true
|
104
116
|
homepage: http://github.com/ragaskar/jasmine-ruby
|
@@ -129,4 +141,8 @@ signing_key:
|
|
129
141
|
specification_version: 3
|
130
142
|
summary: Jasmine Ruby
|
131
143
|
test_files:
|
132
|
-
- spec/
|
144
|
+
- spec/config_spec.rb
|
145
|
+
- spec/jasmine_self_test_config.rb
|
146
|
+
- spec/jasmine_self_test_spec.rb
|
147
|
+
- spec/server_spec.rb
|
148
|
+
- spec/spec_helper.rb
|
data/lib/jasmine-ruby.rb
DELETED
@@ -1,300 +0,0 @@
|
|
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__), '../../jasmine'))
|
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, root_path, spec_files_or_proc, 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
|
-
if (options[:mappings])
|
159
|
-
options[:mappings].each do |from, to|
|
160
|
-
config[from] = Rack::File.new(to)
|
161
|
-
end
|
162
|
-
end
|
163
|
-
|
164
|
-
config["/__JASMINE_ROOT__"] = Rack::File.new(Jasmine.root)
|
165
|
-
|
166
|
-
file_serve_config = {
|
167
|
-
'/' => Rack::File.new(root_path)
|
168
|
-
}
|
169
|
-
|
170
|
-
app = Rack::Cascade.new([
|
171
|
-
Rack::URLMap.new(file_serve_config),
|
172
|
-
Rack::URLMap.new(config),
|
173
|
-
JsAlert.new
|
174
|
-
])
|
175
|
-
|
176
|
-
begin
|
177
|
-
Thin::Server.start('0.0.0.0', port, app)
|
178
|
-
rescue RuntimeError => e
|
179
|
-
raise e unless e.message == 'no acceptor'
|
180
|
-
raise RuntimeError.new("A server is already running on port #{port}")
|
181
|
-
end
|
182
|
-
end
|
183
|
-
end
|
184
|
-
|
185
|
-
class SimpleClient
|
186
|
-
def initialize(selenium_host, selenium_port, selenium_browser_start_command, http_address)
|
187
|
-
require 'selenium/client'
|
188
|
-
@driver = Selenium::Client::Driver.new(
|
189
|
-
selenium_host,
|
190
|
-
selenium_port,
|
191
|
-
selenium_browser_start_command,
|
192
|
-
http_address
|
193
|
-
)
|
194
|
-
@http_address = http_address
|
195
|
-
end
|
196
|
-
|
197
|
-
def tests_have_finished?
|
198
|
-
@driver.get_eval("window.jasmine.getEnv().currentRunner.finished") == "true"
|
199
|
-
end
|
200
|
-
|
201
|
-
def connect
|
202
|
-
@driver.start
|
203
|
-
@driver.open("/")
|
204
|
-
end
|
205
|
-
|
206
|
-
def disconnect
|
207
|
-
@driver.stop
|
208
|
-
end
|
209
|
-
|
210
|
-
def run
|
211
|
-
until tests_have_finished? do
|
212
|
-
sleep 0.1
|
213
|
-
end
|
214
|
-
|
215
|
-
puts @driver.get_eval("window.results()")
|
216
|
-
failed_count = @driver.get_eval("window.jasmine.getEnv().currentRunner.results().failedCount").to_i
|
217
|
-
failed_count == 0
|
218
|
-
end
|
219
|
-
|
220
|
-
def eval_js(script)
|
221
|
-
escaped_script = "'" + script.gsub(/(['\\])/) { '\\' + $1 } + "'"
|
222
|
-
|
223
|
-
result = @driver.get_eval(" try { eval(#{escaped_script}, window); } catch(err) { window.eval(#{escaped_script}); }")
|
224
|
-
JSON.parse("[#{result}]")[0]
|
225
|
-
end
|
226
|
-
end
|
227
|
-
|
228
|
-
class Runner
|
229
|
-
def initialize(selenium_jar_path, root_path, spec_files, options={})
|
230
|
-
@root_path = root_path
|
231
|
-
@selenium_jar_path = selenium_jar_path
|
232
|
-
@spec_files = spec_files
|
233
|
-
@options = options
|
234
|
-
|
235
|
-
@browser = options[:browser] ? options[:browser].delete(:browser) : 'firefox'
|
236
|
-
@selenium_pid = nil
|
237
|
-
@jasmine_server_pid = nil
|
238
|
-
end
|
239
|
-
|
240
|
-
def start
|
241
|
-
start_servers
|
242
|
-
@client = Jasmine::SimpleClient.new("localhost", @selenium_server_port, "*#{@browser}", "http://localhost:#{@jasmine_server_port}/")
|
243
|
-
@client.connect
|
244
|
-
end
|
245
|
-
|
246
|
-
def stop
|
247
|
-
@client.disconnect
|
248
|
-
stop_servers
|
249
|
-
end
|
250
|
-
|
251
|
-
def start_servers
|
252
|
-
@jasmine_server_port = Jasmine::find_unused_port
|
253
|
-
@selenium_server_port = Jasmine::find_unused_port
|
254
|
-
|
255
|
-
@selenium_pid = fork do
|
256
|
-
Process.setpgrp
|
257
|
-
exec "java -jar #{@selenium_jar_path} -port #{@selenium_server_port} > /dev/null 2>&1"
|
258
|
-
end
|
259
|
-
puts "selenium started. pid is #{@selenium_pid}"
|
260
|
-
|
261
|
-
@jasmine_server_pid = fork do
|
262
|
-
Process.setpgrp
|
263
|
-
Jasmine::SimpleServer.start(@jasmine_server_port, @root_path, @spec_files, @options)
|
264
|
-
exit! 0
|
265
|
-
end
|
266
|
-
puts "jasmine server started. pid is #{@jasmine_server_pid}"
|
267
|
-
|
268
|
-
Jasmine::wait_for_listener(@selenium_server_port, "selenium server")
|
269
|
-
Jasmine::wait_for_listener(@jasmine_server_port, "jasmine server")
|
270
|
-
end
|
271
|
-
|
272
|
-
def stop_servers
|
273
|
-
puts "shutting down the servers..."
|
274
|
-
Jasmine::kill_process_group(@selenium_pid) if @selenium_pid
|
275
|
-
Jasmine::kill_process_group(@jasmine_server_pid) if @jasmine_server_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
|
-
def self.files(f)
|
295
|
-
result = f
|
296
|
-
result = result.call if result.respond_to?(:call)
|
297
|
-
result
|
298
|
-
end
|
299
|
-
|
300
|
-
end
|
data/spec/jasmine_spec.rb
DELETED
@@ -1,26 +0,0 @@
|
|
1
|
-
require 'rubygems'
|
2
|
-
require "selenium_rc"
|
3
|
-
|
4
|
-
JASMINE_SPEC_DIR = File.join(File.dirname(__FILE__), "..", "jasmine", "spec")
|
5
|
-
|
6
|
-
require File.expand_path(File.join(File.dirname(__FILE__), "..", "lib", "jasmine-ruby", "jasmine_helper.rb"))
|
7
|
-
require File.expand_path(File.join(JasmineHelper.root, "contrib/ruby/jasmine_spec_builder"))
|
8
|
-
|
9
|
-
jasmine_runner = Jasmine::Runner.new(SeleniumRC::Server.new.jar_path,
|
10
|
-
JasmineHelper.spec_file_urls,
|
11
|
-
JasmineHelper.dir_mappings,
|
12
|
-
:spec_helpers => JasmineHelper.spec_helpers)
|
13
|
-
|
14
|
-
spec_builder = Jasmine::SpecBuilder.new(JasmineHelper.raw_spec_files, jasmine_runner)
|
15
|
-
|
16
|
-
should_stop = false
|
17
|
-
|
18
|
-
Spec::Runner.configure do |config|
|
19
|
-
config.after(:suite) do
|
20
|
-
spec_builder.stop if should_stop
|
21
|
-
end
|
22
|
-
end
|
23
|
-
|
24
|
-
spec_builder.start
|
25
|
-
should_stop = true
|
26
|
-
spec_builder.declare_suites
|
data/templates/example_spec.js
DELETED
@@ -1,11 +0,0 @@
|
|
1
|
-
describe('ExampleSuite', 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
|
-
});
|
data/templates/jasmine_helper.rb
DELETED
data/templates/spec_helper.js
DELETED
@@ -1 +0,0 @@
|
|
1
|
-
//You may load required files here, or create test-runner-wide environment settings.
|