edgecase-jasmine 1.0.1.1
Sign up to get free protection for your applications and to get access to all the features.
- data/README.markdown +45 -0
- data/bin/jasmine +6 -0
- data/generators/jasmine/jasmine_generator.rb +30 -0
- data/generators/jasmine/templates/INSTALL +9 -0
- data/generators/jasmine/templates/jasmine-example/SpecRunner.html +27 -0
- data/generators/jasmine/templates/jasmine-example/spec/PlayerSpec.js +58 -0
- data/generators/jasmine/templates/jasmine-example/spec/SpecHelper.js +9 -0
- data/generators/jasmine/templates/jasmine-example/src/Player.js +22 -0
- data/generators/jasmine/templates/jasmine-example/src/Song.js +7 -0
- data/generators/jasmine/templates/lib/tasks/jasmine.rake +2 -0
- data/generators/jasmine/templates/spec/javascripts/support/jasmine-rails.yml +81 -0
- data/generators/jasmine/templates/spec/javascripts/support/jasmine.yml +73 -0
- data/generators/jasmine/templates/spec/javascripts/support/jasmine_runner.rb +21 -0
- data/jasmine/example/SpecRunner.html +27 -0
- data/jasmine/lib/jasmine-html.js +188 -0
- data/jasmine/lib/jasmine.css +166 -0
- data/jasmine/lib/jasmine.js +2421 -0
- data/jasmine/lib/json2.js +478 -0
- data/lib/jasmine.rb +8 -0
- data/lib/jasmine/base.rb +59 -0
- data/lib/jasmine/command_line_tool.rb +68 -0
- data/lib/jasmine/config.rb +186 -0
- data/lib/jasmine/run.html.erb +43 -0
- data/lib/jasmine/selenium_driver.rb +44 -0
- data/lib/jasmine/server.rb +120 -0
- data/lib/jasmine/spec_builder.rb +152 -0
- data/lib/jasmine/tasks/jasmine.rake +31 -0
- data/spec/config_spec.rb +259 -0
- data/spec/jasmine_command_line_tool_spec.rb +26 -0
- data/spec/jasmine_self_test_config.rb +15 -0
- data/spec/jasmine_self_test_spec.rb +18 -0
- data/spec/rails_generator_spec.rb +27 -0
- data/spec/server_spec.rb +82 -0
- data/spec/spec_helper.rb +40 -0
- metadata +204 -0
@@ -0,0 +1,152 @@
|
|
1
|
+
require 'enumerator'
|
2
|
+
|
3
|
+
module Jasmine
|
4
|
+
class SpecBuilder
|
5
|
+
attr_accessor :suites
|
6
|
+
|
7
|
+
def initialize(config)
|
8
|
+
@config = config
|
9
|
+
@spec_files = config.spec_files
|
10
|
+
@runner = config
|
11
|
+
@spec_ids = []
|
12
|
+
end
|
13
|
+
|
14
|
+
def start
|
15
|
+
guess_example_locations
|
16
|
+
|
17
|
+
@runner.start
|
18
|
+
load_suite_info
|
19
|
+
wait_for_suites_to_finish_running
|
20
|
+
end
|
21
|
+
|
22
|
+
def stop
|
23
|
+
@runner.stop
|
24
|
+
end
|
25
|
+
|
26
|
+
def script_path
|
27
|
+
File.expand_path(__FILE__)
|
28
|
+
end
|
29
|
+
|
30
|
+
def guess_example_locations
|
31
|
+
@example_locations = {}
|
32
|
+
|
33
|
+
example_name_parts = []
|
34
|
+
previous_indent_level = 0
|
35
|
+
@config.spec_files_full_paths.each do |filename|
|
36
|
+
line_number = 1
|
37
|
+
File.open(filename, "r") do |file|
|
38
|
+
file.readlines.each do |line|
|
39
|
+
match = /^(\s*)(describe|it)\s*\(\s*["'](.*)["']\s*,\s*function/.match(line)
|
40
|
+
if (match)
|
41
|
+
indent_level = match[1].length / 2
|
42
|
+
example_name = match[3]
|
43
|
+
example_name_parts[indent_level] = example_name
|
44
|
+
|
45
|
+
full_example_name = example_name_parts.slice(0, indent_level + 1).join(" ")
|
46
|
+
@example_locations[full_example_name] = "#{filename}:#{line_number}: in `it'"
|
47
|
+
end
|
48
|
+
line_number += 1
|
49
|
+
end
|
50
|
+
end
|
51
|
+
end
|
52
|
+
end
|
53
|
+
|
54
|
+
def load_suite_info
|
55
|
+
started = Time.now
|
56
|
+
while !eval_js('jsApiReporter && jsApiReporter.started') do
|
57
|
+
raise "couldn't connect to Jasmine after 60 seconds" if (started + 60 < Time.now)
|
58
|
+
sleep 0.1
|
59
|
+
end
|
60
|
+
|
61
|
+
@suites = eval_js("var result = jsApiReporter.suites(); if (window.Prototype && Object.toJSON) { Object.toJSON(result) } else { JSON.stringify(result) }")
|
62
|
+
end
|
63
|
+
|
64
|
+
def results_for(spec_id)
|
65
|
+
@spec_results ||= load_results
|
66
|
+
@spec_results[spec_id.to_s]
|
67
|
+
end
|
68
|
+
|
69
|
+
def load_results
|
70
|
+
@spec_results = {}
|
71
|
+
@spec_ids.each_slice(50) do |slice|
|
72
|
+
@spec_results.merge!(eval_js("var result = jsApiReporter.resultsForSpecs(#{MultiJson.encode(slice)}); if (window.Prototype && Object.toJSON) { Object.toJSON(result) } else { JSON.stringify(result) }"))
|
73
|
+
end
|
74
|
+
@spec_results
|
75
|
+
end
|
76
|
+
|
77
|
+
def wait_for_suites_to_finish_running
|
78
|
+
puts "Waiting for suite to finish in browser ..."
|
79
|
+
while !eval_js('jsApiReporter.finished') do
|
80
|
+
sleep 0.1
|
81
|
+
end
|
82
|
+
end
|
83
|
+
|
84
|
+
def declare_suites
|
85
|
+
me = self
|
86
|
+
suites.each do |suite|
|
87
|
+
declare_suite(self, suite)
|
88
|
+
end
|
89
|
+
end
|
90
|
+
|
91
|
+
def declare_suite(parent, suite)
|
92
|
+
me = self
|
93
|
+
parent.describe suite["name"] do
|
94
|
+
suite["children"].each do |suite_or_spec|
|
95
|
+
type = suite_or_spec["type"]
|
96
|
+
if type == "suite"
|
97
|
+
me.declare_suite(self, suite_or_spec)
|
98
|
+
elsif type == "spec"
|
99
|
+
me.declare_spec(self, suite_or_spec)
|
100
|
+
else
|
101
|
+
raise "unknown type #{type} for #{suite_or_spec.inspect}"
|
102
|
+
end
|
103
|
+
end
|
104
|
+
end
|
105
|
+
end
|
106
|
+
|
107
|
+
def declare_spec(parent, spec)
|
108
|
+
me = self
|
109
|
+
example_name = spec["name"]
|
110
|
+
@spec_ids << spec["id"]
|
111
|
+
backtrace = @example_locations[parent.description + " " + example_name]
|
112
|
+
parent.it example_name, {}, backtrace do
|
113
|
+
me.report_spec(spec["id"])
|
114
|
+
end
|
115
|
+
end
|
116
|
+
|
117
|
+
def report_spec(spec_id)
|
118
|
+
spec_results = results_for(spec_id)
|
119
|
+
out = ""
|
120
|
+
messages = spec_results['messages'].each do |message|
|
121
|
+
case
|
122
|
+
when message["type"] == "log"
|
123
|
+
puts message["text"]
|
124
|
+
puts "\n"
|
125
|
+
else
|
126
|
+
unless message["message"] =~ /^Passed.$/
|
127
|
+
STDERR << message["message"]
|
128
|
+
STDERR << "\n"
|
129
|
+
|
130
|
+
out << message["message"]
|
131
|
+
out << "\n"
|
132
|
+
end
|
133
|
+
|
134
|
+
if !message["passed"] && message["trace"]["stack"]
|
135
|
+
stack_trace = message["trace"]["stack"].gsub(/<br \/>/, "\n").gsub(/<\/?b>/, " ")
|
136
|
+
STDERR << stack_trace.gsub(/\(.*\)@http:\/\/localhost:[0-9]+\/specs\//, "/spec/")
|
137
|
+
STDERR << "\n"
|
138
|
+
end
|
139
|
+
end
|
140
|
+
|
141
|
+
end
|
142
|
+
fail out unless spec_results['result'] == 'passed'
|
143
|
+
puts out unless out.empty?
|
144
|
+
end
|
145
|
+
|
146
|
+
private
|
147
|
+
|
148
|
+
def eval_js(js)
|
149
|
+
@runner.eval_js(js)
|
150
|
+
end
|
151
|
+
end
|
152
|
+
end
|
@@ -0,0 +1,31 @@
|
|
1
|
+
namespace :jasmine do
|
2
|
+
task :require do
|
3
|
+
require 'jasmine'
|
4
|
+
end
|
5
|
+
|
6
|
+
desc "Run continuous integration tests"
|
7
|
+
task :ci => "jasmine:require" do
|
8
|
+
require "spec"
|
9
|
+
require 'spec/rake/spectask'
|
10
|
+
|
11
|
+
Spec::Rake::SpecTask.new(:jasmine_continuous_integration_runner) do |t|
|
12
|
+
t.spec_opts = ["--color", "--format", "specdoc"]
|
13
|
+
t.verbose = true
|
14
|
+
t.spec_files = ['spec/javascripts/support/jasmine_runner.rb']
|
15
|
+
end
|
16
|
+
Rake::Task["jasmine_continuous_integration_runner"].invoke
|
17
|
+
end
|
18
|
+
|
19
|
+
task :server => "jasmine:require" do
|
20
|
+
jasmine_config_overrides = 'spec/javascripts/support/jasmine_config.rb'
|
21
|
+
require jasmine_config_overrides if File.exists?(jasmine_config_overrides)
|
22
|
+
|
23
|
+
puts "your tests are here:"
|
24
|
+
puts " http://localhost:8888/"
|
25
|
+
|
26
|
+
Jasmine::Config.new.start_server
|
27
|
+
end
|
28
|
+
end
|
29
|
+
|
30
|
+
desc "Run specs via server"
|
31
|
+
task :jasmine => ['jasmine:server']
|
data/spec/config_spec.rb
ADDED
@@ -0,0 +1,259 @@
|
|
1
|
+
require File.expand_path(File.join(File.dirname(__FILE__), "spec_helper"))
|
2
|
+
|
3
|
+
describe Jasmine::Config do
|
4
|
+
|
5
|
+
describe "configuration" do
|
6
|
+
|
7
|
+
before(:all) do
|
8
|
+
temp_dir_before
|
9
|
+
|
10
|
+
Dir::chdir @tmp
|
11
|
+
`rails rails-project`
|
12
|
+
Dir::chdir 'rails-project'
|
13
|
+
|
14
|
+
FileUtils.cp_r(File.join(@root, 'generators'), 'vendor')
|
15
|
+
|
16
|
+
`./script/generate jasmine`
|
17
|
+
|
18
|
+
Dir::chdir @old_dir
|
19
|
+
|
20
|
+
@rails_dir = "#{@tmp}/rails-project"
|
21
|
+
end
|
22
|
+
|
23
|
+
after(:all) do
|
24
|
+
temp_dir_after
|
25
|
+
end
|
26
|
+
|
27
|
+
before(:each) do
|
28
|
+
@template_dir = File.expand_path(File.join(File.dirname(__FILE__), "../generators/jasmine/templates"))
|
29
|
+
@config = Jasmine::Config.new
|
30
|
+
end
|
31
|
+
|
32
|
+
describe "defaults" do
|
33
|
+
|
34
|
+
it "src_dir uses root when src dir is blank" do
|
35
|
+
@config.stub!(:project_root).and_return('some_project_root')
|
36
|
+
@config.stub!(:simple_config_file).and_return(File.join(@template_dir, 'spec/javascripts/support/jasmine.yml'))
|
37
|
+
YAML.stub!(:load).and_return({'src_dir' => nil})
|
38
|
+
@config.src_dir.should == 'some_project_root'
|
39
|
+
end
|
40
|
+
|
41
|
+
it "should use correct default yaml config" do
|
42
|
+
@config.stub!(:project_root).and_return('some_project_root')
|
43
|
+
@config.simple_config_file.should == (File.join('some_project_root', 'spec/javascripts/support/jasmine.yml'))
|
44
|
+
end
|
45
|
+
|
46
|
+
end
|
47
|
+
|
48
|
+
|
49
|
+
describe "simple_config" do
|
50
|
+
before(:each) do
|
51
|
+
@config.stub!(:src_dir).and_return(File.join(@rails_dir, "."))
|
52
|
+
@config.stub!(:spec_dir).and_return(File.join(@rails_dir, "spec/javascripts"))
|
53
|
+
end
|
54
|
+
|
55
|
+
shared_examples_for "simple_config defaults" do
|
56
|
+
it "should return the correct files and mappings" do
|
57
|
+
@config.src_files.should == []
|
58
|
+
@config.stylesheets.should == []
|
59
|
+
@config.spec_files.should == ['PlayerSpec.js']
|
60
|
+
@config.helpers.should == ['helpers/SpecHelper.js']
|
61
|
+
@config.js_files.should == [
|
62
|
+
'/__spec__/helpers/SpecHelper.js',
|
63
|
+
'/__spec__/PlayerSpec.js',
|
64
|
+
]
|
65
|
+
@config.js_files("PlayerSpec.js").should ==
|
66
|
+
['/__spec__/helpers/SpecHelper.js',
|
67
|
+
'/__spec__/PlayerSpec.js']
|
68
|
+
@config.spec_files_full_paths.should == [
|
69
|
+
File.join(@rails_dir, 'spec/javascripts/PlayerSpec.js'),
|
70
|
+
]
|
71
|
+
end
|
72
|
+
end
|
73
|
+
|
74
|
+
it "should parse ERB" do
|
75
|
+
@config.stub!(:simple_config_file).and_return(File.expand_path(File.join(File.dirname(__FILE__), 'fixture/jasmine.erb.yml')))
|
76
|
+
Dir.stub!(:glob).and_return do |glob_string|
|
77
|
+
glob_string
|
78
|
+
end
|
79
|
+
@config.src_files.should == [
|
80
|
+
'file0.js',
|
81
|
+
'file1.js',
|
82
|
+
'file2.js',
|
83
|
+
]
|
84
|
+
end
|
85
|
+
|
86
|
+
|
87
|
+
describe "if sources.yaml not found" do
|
88
|
+
before(:each) do
|
89
|
+
File.stub!(:exist?).and_return(false)
|
90
|
+
end
|
91
|
+
it_should_behave_like "simple_config defaults"
|
92
|
+
end
|
93
|
+
|
94
|
+
describe "if jasmine.yml is empty" do
|
95
|
+
before(:each) do
|
96
|
+
@config.stub!(:simple_config_file).and_return(File.join(@template_dir, 'spec/javascripts/support/jasmine.yml'))
|
97
|
+
YAML.stub!(:load).and_return(false)
|
98
|
+
end
|
99
|
+
it_should_behave_like "simple_config defaults"
|
100
|
+
|
101
|
+
end
|
102
|
+
|
103
|
+
# describe "using default jasmine.yml" do
|
104
|
+
# before(:each) do
|
105
|
+
# @config.stub!(:simple_config_file).and_return(File.join(@template_dir, 'spec/javascripts/support/jasmine.yml'))
|
106
|
+
# end
|
107
|
+
# it_should_behave_like "simple_config defaults"
|
108
|
+
#
|
109
|
+
# end
|
110
|
+
|
111
|
+
describe "should use the first appearance of duplicate filenames" do
|
112
|
+
before(:each) do
|
113
|
+
Dir.stub!(:glob).and_return do |glob_string|
|
114
|
+
glob_string
|
115
|
+
end
|
116
|
+
fake_config = Hash.new.stub!(:[]).and_return(["file1.ext", "file2.ext", "file1.ext"])
|
117
|
+
@config.stub!(:simple_config).and_return(fake_config)
|
118
|
+
end
|
119
|
+
|
120
|
+
it "src_files" do
|
121
|
+
@config.src_files.should == ['file1.ext', 'file2.ext']
|
122
|
+
end
|
123
|
+
|
124
|
+
it "stylesheets" do
|
125
|
+
@config.stylesheets.should == ['file1.ext', 'file2.ext']
|
126
|
+
end
|
127
|
+
|
128
|
+
it "spec_files" do
|
129
|
+
@config.spec_files.should == ['file1.ext', 'file2.ext']
|
130
|
+
end
|
131
|
+
|
132
|
+
it "helpers" do
|
133
|
+
@config.spec_files.should == ['file1.ext', 'file2.ext']
|
134
|
+
end
|
135
|
+
|
136
|
+
it "js_files" do
|
137
|
+
@config.js_files.should == ["/file1.ext",
|
138
|
+
"/file2.ext",
|
139
|
+
"/__spec__/file1.ext",
|
140
|
+
"/__spec__/file2.ext",
|
141
|
+
"/__spec__/file1.ext",
|
142
|
+
"/__spec__/file2.ext"]
|
143
|
+
end
|
144
|
+
|
145
|
+
it "spec_files_full_paths" do
|
146
|
+
@config.spec_files_full_paths.should == [
|
147
|
+
File.expand_path("spec/javascripts/file1.ext", @rails_dir),
|
148
|
+
File.expand_path("spec/javascripts/file2.ext", @rails_dir)
|
149
|
+
]
|
150
|
+
end
|
151
|
+
|
152
|
+
end
|
153
|
+
|
154
|
+
it "simple_config stylesheets" do
|
155
|
+
@config.stub!(:simple_config_file).and_return(File.join(@template_dir, 'spec/javascripts/support/jasmine.yml'))
|
156
|
+
YAML.stub!(:load).and_return({'stylesheets' => ['foo.css', 'bar.css']})
|
157
|
+
Dir.stub!(:glob).and_return do |glob_string|
|
158
|
+
glob_string
|
159
|
+
end
|
160
|
+
@config.stylesheets.should == ['foo.css', 'bar.css']
|
161
|
+
end
|
162
|
+
|
163
|
+
|
164
|
+
it "using rails jasmine.yml" do
|
165
|
+
@config.stub!(:simple_config_file).and_return(File.join(@template_dir, 'spec/javascripts/support/jasmine-rails.yml'))
|
166
|
+
@config.spec_files.should == ['PlayerSpec.js']
|
167
|
+
@config.helpers.should == ['helpers/SpecHelper.js']
|
168
|
+
@config.src_files.should == ['public/javascripts/prototype.js',
|
169
|
+
'public/javascripts/effects.js',
|
170
|
+
'public/javascripts/controls.js',
|
171
|
+
'public/javascripts/dragdrop.js',
|
172
|
+
'public/javascripts/application.js',
|
173
|
+
'public/javascripts/Player.js',
|
174
|
+
'public/javascripts/Song.js']
|
175
|
+
@config.js_files.should == [
|
176
|
+
'/public/javascripts/prototype.js',
|
177
|
+
'/public/javascripts/effects.js',
|
178
|
+
'/public/javascripts/controls.js',
|
179
|
+
'/public/javascripts/dragdrop.js',
|
180
|
+
'/public/javascripts/application.js',
|
181
|
+
'/public/javascripts/Player.js',
|
182
|
+
'/public/javascripts/Song.js',
|
183
|
+
'/__spec__/helpers/SpecHelper.js',
|
184
|
+
'/__spec__/PlayerSpec.js',
|
185
|
+
]
|
186
|
+
@config.js_files("PlayerSpec.js").should == [
|
187
|
+
'/public/javascripts/prototype.js',
|
188
|
+
'/public/javascripts/effects.js',
|
189
|
+
'/public/javascripts/controls.js',
|
190
|
+
'/public/javascripts/dragdrop.js',
|
191
|
+
'/public/javascripts/application.js',
|
192
|
+
'/public/javascripts/Player.js',
|
193
|
+
'/public/javascripts/Song.js',
|
194
|
+
'/__spec__/helpers/SpecHelper.js',
|
195
|
+
'/__spec__/PlayerSpec.js'
|
196
|
+
]
|
197
|
+
|
198
|
+
end
|
199
|
+
|
200
|
+
end
|
201
|
+
|
202
|
+
end
|
203
|
+
|
204
|
+
describe "browser configuration" do
|
205
|
+
it "should use firefox by default" do
|
206
|
+
ENV.stub!(:[], "JASMINE_BROWSER").and_return(nil)
|
207
|
+
config = Jasmine::Config.new
|
208
|
+
config.stub!(:start_servers)
|
209
|
+
Jasmine::SeleniumDriver.should_receive(:new).
|
210
|
+
with(anything(), anything(), "*firefox", anything()).
|
211
|
+
and_return(mock(Jasmine::SeleniumDriver, :connect => true))
|
212
|
+
config.start
|
213
|
+
end
|
214
|
+
|
215
|
+
it "should use ENV['JASMINE_BROWSER'] if set" do
|
216
|
+
ENV.stub!(:[], "JASMINE_BROWSER").and_return("mosaic")
|
217
|
+
config = Jasmine::Config.new
|
218
|
+
config.stub!(:start_servers)
|
219
|
+
Jasmine::SeleniumDriver.should_receive(:new).
|
220
|
+
with(anything(), anything(), "*mosaic", anything()).
|
221
|
+
and_return(mock(Jasmine::SeleniumDriver, :connect => true))
|
222
|
+
config.start
|
223
|
+
end
|
224
|
+
end
|
225
|
+
|
226
|
+
describe "jasmine host" do
|
227
|
+
it "should use http://localhost by default" do
|
228
|
+
config = Jasmine::Config.new
|
229
|
+
config.instance_variable_set(:@jasmine_server_port, '1234')
|
230
|
+
config.stub!(:start_servers)
|
231
|
+
|
232
|
+
Jasmine::SeleniumDriver.should_receive(:new).
|
233
|
+
with(anything(), anything(), anything(), "http://localhost:1234/").
|
234
|
+
and_return(mock(Jasmine::SeleniumDriver, :connect => true))
|
235
|
+
config.start
|
236
|
+
end
|
237
|
+
|
238
|
+
it "should use ENV['JASMINE_HOST'] if set" do
|
239
|
+
ENV.stub!(:[], "JASMINE_HOST").and_return("http://some_host")
|
240
|
+
config = Jasmine::Config.new
|
241
|
+
config.instance_variable_set(:@jasmine_server_port, '1234')
|
242
|
+
config.stub!(:start_servers)
|
243
|
+
|
244
|
+
Jasmine::SeleniumDriver.should_receive(:new).
|
245
|
+
with(anything(), anything(), anything(), "http://some_host:1234/").
|
246
|
+
and_return(mock(Jasmine::SeleniumDriver, :connect => true))
|
247
|
+
config.start
|
248
|
+
end
|
249
|
+
end
|
250
|
+
|
251
|
+
describe "#start_selenium_server" do
|
252
|
+
it "should use an existing selenium server if SELENIUM_SERVER_PORT is set" do
|
253
|
+
config = Jasmine::Config.new
|
254
|
+
ENV.stub!(:[], "SELENIUM_SERVER_PORT").and_return(1234)
|
255
|
+
Jasmine.should_receive(:wait_for_listener).with(1234, "selenium server")
|
256
|
+
config.start_selenium_server
|
257
|
+
end
|
258
|
+
end
|
259
|
+
end
|
@@ -0,0 +1,26 @@
|
|
1
|
+
require File.expand_path(File.join(File.dirname(__FILE__), "spec_helper"))
|
2
|
+
|
3
|
+
describe "Jasmine command line tool" do
|
4
|
+
before :each do
|
5
|
+
temp_dir_before
|
6
|
+
Dir::chdir @tmp
|
7
|
+
end
|
8
|
+
|
9
|
+
after :each do
|
10
|
+
temp_dir_after
|
11
|
+
end
|
12
|
+
|
13
|
+
it "should create files on init" do
|
14
|
+
output = capture_stdout do
|
15
|
+
Jasmine::CommandLineTool.new.process ["init"]
|
16
|
+
end
|
17
|
+
output.should =~ /Jasmine has been installed with example specs./
|
18
|
+
|
19
|
+
my_jasmine_lib = File.expand_path(File.join(@root, "lib"))
|
20
|
+
bootstrap = "$:.unshift('#{my_jasmine_lib}')"
|
21
|
+
|
22
|
+
ENV['JASMINE_GEM_PATH'] = "#{@root}/lib"
|
23
|
+
ci_output = `rake -E "#{bootstrap}" --trace jasmine:ci`
|
24
|
+
ci_output.should =~ (/[1-9][0-9]* examples, 0 failures/)
|
25
|
+
end
|
26
|
+
end
|