shenandoah 0.1.3 → 0.2.0
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.
- data/.gitignore +1 -0
- data/ChangeLog.markdown +9 -0
- data/Rakefile +21 -2
- data/VERSION.yml +3 -2
- data/features/buildr.feature +29 -0
- data/features/example_projects/base/Rakefile +7 -0
- data/features/example_projects/base/lib/cells.js +105 -0
- data/features/example_projects/base/lib/life.js +30 -0
- data/features/example_projects/base/spec/cells.html +13 -0
- data/features/example_projects/base/spec/cells_spec.js +234 -0
- data/features/example_projects/base/spec/life.html +13 -0
- data/features/example_projects/base/spec/life_spec.js +28 -0
- data/features/plain-rake.feature +30 -0
- data/features/rails.feature +39 -0
- data/features/step_definitions/buildr_steps.rb +26 -0
- data/features/step_definitions/rails_steps.rb +38 -0
- data/features/step_definitions/rake_steps.rb +45 -0
- data/features/support/env.rb +48 -0
- data/lib/shenandoah/css/shenandoah.sass +138 -0
- data/lib/shenandoah/javascript/browser/index.js +18 -0
- data/lib/shenandoah/javascript/browser/multirunner-single.js +32 -0
- data/lib/shenandoah/javascript/browser/multirunner.js +87 -0
- data/lib/shenandoah/javascript/common/jquery.parsequery.js +19 -0
- data/lib/shenandoah/server.rb +81 -16
- data/lib/shenandoah/server/views/index.haml +18 -8
- data/lib/shenandoah/server/views/multirunner.haml +6 -0
- data/rails_generators/shen_spec/templates/fixture.html.erb +1 -1
- data/rails_generators/shenandoah/templates/application.html +1 -1
- data/spec/rails_generators/shen_spec_generator_spec.rb +2 -2
- data/spec/rails_generators/shenandoah_generator_spec.rb +3 -3
- data/spec/shenandoah/server_spec.rb +156 -15
- metadata +32 -3
- data/lib/shenandoah/css/screw.css +0 -90
@@ -0,0 +1,87 @@
|
|
1
|
+
if (!window.shenandoah) { var shenandoah = {}; }
|
2
|
+
|
3
|
+
(function ($) {
|
4
|
+
shenandoah.Multirunner = function (container_id, spec_urls) {
|
5
|
+
////// PRIVATE
|
6
|
+
|
7
|
+
var runner = this;
|
8
|
+
|
9
|
+
function container(subselector) {
|
10
|
+
var sel = "#" + runner.container_id;
|
11
|
+
if (subselector) sel += ' ' + subselector;
|
12
|
+
return jQuery(sel);
|
13
|
+
}
|
14
|
+
|
15
|
+
////// PUBLIC
|
16
|
+
|
17
|
+
this.container_id = container_id;
|
18
|
+
this.spec_urls = spec_urls;
|
19
|
+
|
20
|
+
this.run = function () {
|
21
|
+
this.frames = container("#frames iframe").get();
|
22
|
+
this.next();
|
23
|
+
}
|
24
|
+
|
25
|
+
this.next = function () {
|
26
|
+
if (this.frames && this.frames.length > 0) {
|
27
|
+
setTimeout(function () { jQuery(runner.frames.shift()).trigger('begin') }, 0);
|
28
|
+
} else {
|
29
|
+
var show = container('#specs li.failed').get(0) || container('#specs li').get(0);
|
30
|
+
jQuery(show).trigger('activate');
|
31
|
+
}
|
32
|
+
}
|
33
|
+
|
34
|
+
this.reset = function () {
|
35
|
+
container().empty();
|
36
|
+
this.frames = null;
|
37
|
+
}
|
38
|
+
|
39
|
+
////// INITIALIZATION
|
40
|
+
|
41
|
+
if (!this.spec_urls || this.spec_urls.length === 0) {
|
42
|
+
container().append("<p>No specs selected to run</p>")
|
43
|
+
} else {
|
44
|
+
container().append("<ul id='specs'></ul>").append("<div id='frames'></div>");
|
45
|
+
jQuery(this.spec_urls).each(function (idx) {
|
46
|
+
container("#specs").append('<li class="spec inactive"><span class="name">' + this.replace(/\/spec\//, "") + '</span> <span class="count"></span></li>');
|
47
|
+
container("#frames").append('<iframe class="inactive" spec-url="' + this + '" src="about:blank"></iframe>');
|
48
|
+
var newLi = container("#specs li:last-child");
|
49
|
+
var newFrame = container("#frames iframe:last-child");
|
50
|
+
var both = jQuery(newLi.selector + ", " + newFrame.selector);
|
51
|
+
|
52
|
+
both.bind('activate', function () {
|
53
|
+
both.removeClass('inactive').addClass('active');
|
54
|
+
}).bind('deactivate', function () {
|
55
|
+
both.addClass('inactive').removeClass('active');
|
56
|
+
});
|
57
|
+
|
58
|
+
newFrame.bind("begin", null, function (evt, data) {
|
59
|
+
newLi.find('.count').empty().end().trigger('activate');
|
60
|
+
newFrame.attr('src', newFrame.attr('spec-url'));
|
61
|
+
});
|
62
|
+
|
63
|
+
newFrame.bind("complete", null, function (evt, data) {
|
64
|
+
newLi.find('.count').text(data.passed_count + " of " + data.total_count).end().
|
65
|
+
removeClass('passed').removeClass('failed').addClass(data.passed_count === data.total_count ? 'passed' : 'failed').
|
66
|
+
trigger('deactivate');
|
67
|
+
runner.next();
|
68
|
+
});
|
69
|
+
|
70
|
+
newLi.bind('click', function () {
|
71
|
+
container('#frames iframe').trigger('deactivate');
|
72
|
+
newFrame.trigger('activate');
|
73
|
+
return false;
|
74
|
+
});
|
75
|
+
});
|
76
|
+
}
|
77
|
+
};
|
78
|
+
|
79
|
+
$(document).ready(function () {
|
80
|
+
var specs = jQuery.parseQuery().spec;
|
81
|
+
if (specs && specs.constructor !== Array) {
|
82
|
+
specs = [specs];
|
83
|
+
}
|
84
|
+
new shenandoah.Multirunner('runner', specs).run();
|
85
|
+
});
|
86
|
+
|
87
|
+
}(jQuery));
|
@@ -0,0 +1,19 @@
|
|
1
|
+
/**
|
2
|
+
* A simple querystring parser.
|
3
|
+
* Example usage: var q = $.parseQuery(); q.fooreturns "bar" if query contains "?foo=bar"; multiple values are added to an array.
|
4
|
+
* Values are unescaped by default and plus signs replaced with spaces, or an alternate processing function can be passed in the params object .
|
5
|
+
* http://actingthemaggot.com/jquery
|
6
|
+
*
|
7
|
+
* Copyright (c) 2008 Michael Manning (http://actingthemaggot.com)
|
8
|
+
* Dual licensed under the MIT (MIT-LICENSE.txt)
|
9
|
+
* and GPL (GPL-LICENSE.txt) licenses.
|
10
|
+
**/
|
11
|
+
jQuery.parseQuery = function(qs,options) {
|
12
|
+
var q = (typeof qs === 'string'?qs:window.location.search), o = {'f':function(v){return unescape(v).replace(/\+/g,' ');}}, options = (typeof qs === 'object' && typeof options === 'undefined')?qs:options, o = jQuery.extend({}, o, options), params = {};
|
13
|
+
jQuery.each(q.match(/^\??(.*)$/)[1].split('&'),function(i,p){
|
14
|
+
p = p.split('=');
|
15
|
+
p[1] = o.f(p[1]);
|
16
|
+
params[p[0]] = params[p[0]]?((params[p[0]] instanceof Array)?(params[p[0]].push(p[1]),params[p[0]]):[params[p[0]],p[1]]):p[1];
|
17
|
+
});
|
18
|
+
return params;
|
19
|
+
}
|
data/lib/shenandoah/server.rb
CHANGED
@@ -1,5 +1,7 @@
|
|
1
1
|
require 'sinatra'
|
2
2
|
require 'haml'
|
3
|
+
require 'sass'
|
4
|
+
require 'compass'
|
3
5
|
|
4
6
|
module Shenandoah
|
5
7
|
# The server which enables in-browser execution of Screw.Unit specs in
|
@@ -12,18 +14,23 @@ module Shenandoah
|
|
12
14
|
class Server < Sinatra::Base
|
13
15
|
set :root, File.dirname(__FILE__) + "/server"
|
14
16
|
set :port, 4410
|
17
|
+
set :sass, Compass.sass_engine_options
|
15
18
|
enable :logging
|
16
19
|
|
17
20
|
get '/' do
|
18
21
|
section_map = options.locator.spec_files.
|
19
22
|
collect { |t| t.sub(%r{^#{options.locator.spec_path}/?}, '') }.
|
20
23
|
collect { |t| [File.dirname(t), File.basename(t).sub(/_spec.js$/, '.html')] }.
|
21
|
-
inject({}) { |h, (dir, file)| h[dir] ||= []; h[dir] << file; h }
|
24
|
+
inject({}) { |h, (dir, file)| h[dir] ||= []; h[dir] << IndexEntry.new(dir, file); h }
|
22
25
|
@sections = section_map.collect { |dir, files| [dir, files.sort] }.sort
|
23
26
|
|
24
27
|
haml :index
|
25
28
|
end
|
26
29
|
|
30
|
+
get '/multirunner' do
|
31
|
+
haml :multirunner
|
32
|
+
end
|
33
|
+
|
27
34
|
get '/main/*' do
|
28
35
|
map_file(options.locator.main_path, params[:splat].first, "Main")
|
29
36
|
end
|
@@ -32,27 +39,47 @@ module Shenandoah
|
|
32
39
|
map_file(options.locator.spec_path, params[:splat].first, "Spec")
|
33
40
|
end
|
34
41
|
|
35
|
-
get '/
|
36
|
-
|
37
|
-
|
38
|
-
|
42
|
+
get '/shenandoah.css' do
|
43
|
+
shenandoah_css = File.join(options.locator.spec_path, 'shenandoah.css')
|
44
|
+
if File.exist?(shenandoah_css)
|
45
|
+
send_file shenandoah_css
|
46
|
+
else
|
47
|
+
shenandoah_sass = File.join(options.locator.spec_path, 'shenandoah.sass')
|
48
|
+
unless File.exist?(shenandoah_sass)
|
49
|
+
shenandoah_sass = File.join(File.dirname(__FILE__), "css/shenandoah.sass")
|
50
|
+
end
|
51
|
+
content_type 'text/css'
|
52
|
+
last_modified File.stat(shenandoah_sass).mtime
|
53
|
+
sass File.read(shenandoah_sass)
|
39
54
|
end
|
40
|
-
|
55
|
+
end
|
56
|
+
|
57
|
+
get '/screw.css' do
|
58
|
+
uri = '/shenandoah.css'
|
59
|
+
$stderr.puts "DEPRECATION NOTICE: Use #{uri} instead of /screw.css."
|
60
|
+
status 301
|
61
|
+
response['Location'] = uri
|
62
|
+
"This URI is deprecated. Use <a href='#{uri}'>#{uri}</a>."
|
41
63
|
end
|
42
64
|
|
43
65
|
get '/shenandoah/browser-runner.js' do
|
66
|
+
maxtime, content = concatenate_files(runner_files)
|
67
|
+
|
44
68
|
content_type 'text/javascript'
|
69
|
+
last_modified maxtime
|
70
|
+
content
|
71
|
+
end
|
45
72
|
|
46
|
-
|
47
|
-
|
48
|
-
}.max
|
73
|
+
get '/shenandoah/multirunner.js' do
|
74
|
+
maxtime, content = concatenate_files(multirunner_files)
|
49
75
|
|
50
|
-
|
51
|
-
|
52
|
-
|
53
|
-
|
54
|
-
|
55
|
-
|
76
|
+
content_type 'text/javascript'
|
77
|
+
last_modified maxtime
|
78
|
+
content
|
79
|
+
end
|
80
|
+
|
81
|
+
get '/js/*' do
|
82
|
+
send_file File.join(File.dirname(__FILE__), "javascript/#{params[:splat].first}")
|
56
83
|
end
|
57
84
|
|
58
85
|
protected
|
@@ -67,6 +94,21 @@ module Shenandoah
|
|
67
94
|
end
|
68
95
|
end
|
69
96
|
|
97
|
+
def concatenate_files(files)
|
98
|
+
maxtime = files.collect { |filename|
|
99
|
+
File.stat("#{File.dirname(__FILE__)}/#{filename}").mtime
|
100
|
+
}.max
|
101
|
+
|
102
|
+
content = files.collect { |filename|
|
103
|
+
[
|
104
|
+
"\n//////\n////// #{filename}\n//////\n",
|
105
|
+
File.read("#{File.dirname(__FILE__)}/#{filename}")
|
106
|
+
]
|
107
|
+
}.flatten
|
108
|
+
|
109
|
+
[maxtime, content]
|
110
|
+
end
|
111
|
+
|
70
112
|
def runner_files # :nodoc:
|
71
113
|
# Can't just use Dir[] because order is important
|
72
114
|
[
|
@@ -81,8 +123,31 @@ module Shenandoah
|
|
81
123
|
"javascript/common/smoke.mock.js",
|
82
124
|
"javascript/common/smoke.stub.js",
|
83
125
|
"javascript/common/screw.mocking.js",
|
84
|
-
"javascript/browser/runner.js"
|
126
|
+
"javascript/browser/runner.js",
|
127
|
+
"javascript/browser/multirunner-single.js"
|
85
128
|
]
|
86
129
|
end
|
130
|
+
|
131
|
+
def multirunner_files # :nodoc
|
132
|
+
[
|
133
|
+
"javascript/common/jquery-1.3.2.js",
|
134
|
+
"javascript/common/jquery.parsequery.js",
|
135
|
+
"javascript/browser/multirunner.js"
|
136
|
+
]
|
137
|
+
end
|
138
|
+
|
139
|
+
class IndexEntry < Struct.new(:section, :test_html)
|
140
|
+
def href
|
141
|
+
'/' + ["spec", section, test_html].reject { |s| s == '.' }.join('/')
|
142
|
+
end
|
143
|
+
|
144
|
+
def name
|
145
|
+
test_html.sub(/.html$/, '')
|
146
|
+
end
|
147
|
+
|
148
|
+
def <=>(other)
|
149
|
+
self.test_html <=> other.test_html
|
150
|
+
end
|
151
|
+
end
|
87
152
|
end
|
88
153
|
end
|
@@ -1,12 +1,22 @@
|
|
1
1
|
%html
|
2
2
|
%head
|
3
|
-
%
|
4
|
-
|
3
|
+
%script{ :src => '/js/common/jquery-1.3.2.js' }
|
4
|
+
%script{ :src => '/js/browser/index.js' }
|
5
|
+
%link{ :rel => "stylesheet", :href => "/shenandoah.css", :type => "text/css", :charset => "utf-8" }
|
6
|
+
%body#index
|
5
7
|
- if options.respond_to?(:project_name) && options.project_name
|
6
8
|
%h1= "Specs for #{options.project_name}"
|
7
|
-
-
|
8
|
-
%
|
9
|
-
|
10
|
-
|
11
|
-
|
12
|
-
|
9
|
+
%label#select-all
|
10
|
+
%input{ :type => 'checkbox', :name => 'select-all' }
|
11
|
+
%a select all
|
12
|
+
%form{ :method => 'GET', :action => '/multirunner' }
|
13
|
+
- @sections.each do |section, tests|
|
14
|
+
%h2= section == '.' ? '[root]' : section
|
15
|
+
%ul
|
16
|
+
- tests.each do |test|
|
17
|
+
%li
|
18
|
+
%label
|
19
|
+
%input{ :type => 'checkbox', :name => 'spec', :value => test.href }
|
20
|
+
%a{ :href => test.href }= test.name
|
21
|
+
#controls
|
22
|
+
%input{ :type => 'submit', :value => 'Run selected' }
|
@@ -3,7 +3,7 @@
|
|
3
3
|
|
4
4
|
<head>
|
5
5
|
<title><%= file_name %>.js | JavaScript Testing Results</title>
|
6
|
-
<link rel="stylesheet" href="/
|
6
|
+
<link rel="stylesheet" href="/shenandoah.css" type="text/css" charset="utf-8" />
|
7
7
|
<script type="text/javascript" src="/shenandoah/browser-runner.js"></script>
|
8
8
|
</head>
|
9
9
|
|
@@ -3,7 +3,7 @@
|
|
3
3
|
|
4
4
|
<head>
|
5
5
|
<title>Application | JavaScript Testing Results</title>
|
6
|
-
<link rel="stylesheet" href="/
|
6
|
+
<link rel="stylesheet" href="/shenandoah.css" type="text/css" charset="utf-8" />
|
7
7
|
<script type="text/javascript" src="/shenandoah/browser-runner.js"></script>
|
8
8
|
</head>
|
9
9
|
|
@@ -50,8 +50,8 @@ describe "shen_spec generator" do
|
|
50
50
|
@html.should =~ %r{src="/shenandoah/browser-runner.js"}
|
51
51
|
end
|
52
52
|
|
53
|
-
it "includes
|
54
|
-
@html.should =~ %r{href="/
|
53
|
+
it "includes shenandoah.css" do
|
54
|
+
@html.should =~ %r{href="/shenandoah.css"}
|
55
55
|
end
|
56
56
|
end
|
57
57
|
|
@@ -70,11 +70,11 @@ describe "shenandoah generator" do
|
|
70
70
|
File.read(@path).should =~ %r{src="/shenandoah/browser-runner.js"}
|
71
71
|
end
|
72
72
|
|
73
|
-
it "links to the served
|
74
|
-
File.read(@path).should =~ %r{href="/
|
73
|
+
it "links to the served shenandoah.css" do
|
74
|
+
File.read(@path).should =~ %r{href="/shenandoah.css"}
|
75
75
|
end
|
76
76
|
end
|
77
77
|
end
|
78
78
|
end
|
79
79
|
end
|
80
|
-
end
|
80
|
+
end
|
@@ -59,8 +59,13 @@ describe Shenandoah::Server do
|
|
59
59
|
last_response.body.should =~ %r{function require_main\(}
|
60
60
|
end
|
61
61
|
|
62
|
+
it "includes the multirunner code for a single test" do
|
63
|
+
last_response.body.should =~ %r{window.parent.jQuery\('iframe'\)}
|
64
|
+
end
|
65
|
+
|
62
66
|
it "was last modified at the latest date of the combined files" do
|
63
67
|
maxTime = Dir["#{File.dirname(__FILE__)}/../../lib/shenandoah/javascript/{browser,common}/*.js"].
|
68
|
+
reject { |filename| filename =~ /multirunner.js$/ || filename =~ /parsequery/i || filename =~ /index.js$/ }.
|
64
69
|
collect { |filename| File.stat(filename).mtime }.max
|
65
70
|
Time.httpdate(last_response.headers['Last-Modified']).should == maxTime
|
66
71
|
end
|
@@ -114,37 +119,44 @@ describe Shenandoah::Server do
|
|
114
119
|
end
|
115
120
|
end
|
116
121
|
|
117
|
-
describe "/
|
122
|
+
describe "/shenandoah.css" do
|
118
123
|
describe "by default" do
|
119
124
|
before do
|
120
|
-
get '/
|
121
|
-
@
|
125
|
+
get '/shenandoah.css'
|
126
|
+
@sass = File.expand_path(
|
127
|
+
"lib/shenandoah/css/shenandoah.sass", File.dirname(__FILE__) + "/../..")
|
122
128
|
end
|
123
129
|
|
124
130
|
it "is available" do
|
125
131
|
last_response.should be_ok
|
126
132
|
end
|
127
133
|
|
128
|
-
it "is the included
|
129
|
-
last_response.body.should
|
134
|
+
it "is the CSS version of the included shenandoah.sass" do
|
135
|
+
last_response.body.should include('#frames iframe {')
|
136
|
+
last_response.body.should include('.describes .describe {')
|
137
|
+
end
|
138
|
+
|
139
|
+
it "includes the compass reset styles directly" do
|
140
|
+
last_response.body.should_not include("@import url(compass/reset.css)")
|
141
|
+
last_response.body.should include("table, caption, tbody, tfoot, thead, tr, th, td")
|
130
142
|
end
|
131
143
|
|
132
144
|
it "has the correct last modified version" do
|
133
145
|
Time.httpdate(last_response.headers['Last-Modified']).should ==
|
134
|
-
File.stat(@
|
146
|
+
File.stat(@sass).mtime
|
135
147
|
end
|
136
148
|
|
137
149
|
it "is CSS" do
|
138
|
-
last_response.
|
150
|
+
last_response.content_type.should == 'text/css'
|
139
151
|
end
|
140
152
|
end
|
141
153
|
|
142
|
-
describe "when overridden" do
|
154
|
+
describe "when overridden with CSS" do
|
143
155
|
before do
|
144
156
|
app.set :locator,
|
145
157
|
Shenandoah::DefaultLocator.new(:spec_path => self.tmpdir)
|
146
|
-
tmpfile "
|
147
|
-
get '/
|
158
|
+
tmpfile "shenandoah.css", ".passed { color: blue }"
|
159
|
+
get '/shenandoah.css'
|
148
160
|
end
|
149
161
|
|
150
162
|
it "is available" do
|
@@ -157,13 +169,57 @@ describe Shenandoah::Server do
|
|
157
169
|
|
158
170
|
it "has the correct last modified version" do
|
159
171
|
Time.httpdate(last_response.headers['Last-Modified']).should ==
|
160
|
-
File.stat("#{self.tmpdir}/
|
172
|
+
File.stat("#{self.tmpdir}/shenandoah.css").mtime
|
161
173
|
end
|
162
174
|
|
163
175
|
it "is CSS" do
|
164
|
-
last_response.
|
176
|
+
last_response.content_type.should == 'text/css'
|
165
177
|
end
|
166
178
|
end
|
179
|
+
|
180
|
+
describe "when overridden with Sass" do
|
181
|
+
before do
|
182
|
+
app.set :locator,
|
183
|
+
Shenandoah::DefaultLocator.new(:spec_path => self.tmpdir)
|
184
|
+
tmpfile "shenandoah.sass", ".passed\n color: blue"
|
185
|
+
get '/shenandoah.css'
|
186
|
+
end
|
187
|
+
|
188
|
+
it "is available" do
|
189
|
+
last_response.should be_ok
|
190
|
+
end
|
191
|
+
|
192
|
+
it "is the version from the spec dir" do
|
193
|
+
last_response.body.should == ".passed {\n color: blue; }\n"
|
194
|
+
end
|
195
|
+
|
196
|
+
it "has the correct last modified version" do
|
197
|
+
Time.httpdate(last_response.headers['Last-Modified']).should ==
|
198
|
+
File.stat("#{self.tmpdir}/shenandoah.sass").mtime
|
199
|
+
end
|
200
|
+
|
201
|
+
it "is CSS" do
|
202
|
+
last_response.content_type.should == 'text/css'
|
203
|
+
end
|
204
|
+
end
|
205
|
+
end
|
206
|
+
|
207
|
+
describe "/screw.css" do
|
208
|
+
before do
|
209
|
+
get '/screw.css'
|
210
|
+
end
|
211
|
+
|
212
|
+
it "redirects" do
|
213
|
+
last_response.status.should == 301
|
214
|
+
end
|
215
|
+
|
216
|
+
it "points to /shenandoah.css" do
|
217
|
+
last_response['Location'].should == '/shenandoah.css'
|
218
|
+
end
|
219
|
+
|
220
|
+
it "includes a deprecation note" do
|
221
|
+
last_response.body.should == "This URI is deprecated. Use <a href='/shenandoah.css'>/shenandoah.css</a>."
|
222
|
+
end
|
167
223
|
end
|
168
224
|
|
169
225
|
describe "/" do
|
@@ -173,6 +229,7 @@ describe Shenandoah::Server do
|
|
173
229
|
app.set :locator,
|
174
230
|
Shenandoah::DefaultLocator.new(:spec_path => File.join(self.tmpdir, 'spec'))
|
175
231
|
tmpfile "spec/common_spec.js", "DC"
|
232
|
+
tmpfile "spec/application_spec.js", "DC"
|
176
233
|
tmpfile "spec/some/thing_spec.js", "DC"
|
177
234
|
get "/"
|
178
235
|
end
|
@@ -202,15 +259,99 @@ describe Shenandoah::Server do
|
|
202
259
|
end
|
203
260
|
|
204
261
|
it "includes lists of links" do
|
205
|
-
last_response.body.should have_tag("ul a", :count =>
|
262
|
+
last_response.body.should have_tag("ul a", :count => 3)
|
206
263
|
end
|
207
264
|
|
208
265
|
it "includes a link to a spec in the root" do
|
209
|
-
last_response.body.should have_tag("a[@href='spec/common.html']", "common")
|
266
|
+
last_response.body.should have_tag("a[@href='/spec/common.html']", "common")
|
210
267
|
end
|
211
268
|
|
212
269
|
it "includes link to a spec in a subdirectory" do
|
213
|
-
last_response.body.should have_tag("a[@href='spec/some/thing.html']", "thing")
|
270
|
+
last_response.body.should have_tag("a[@href='/spec/some/thing.html']", "thing")
|
271
|
+
end
|
272
|
+
|
273
|
+
it "includes a checkbox for a spec in the root" do
|
274
|
+
last_response.body.should have_tag("input[@value='/spec/common.html']")
|
275
|
+
end
|
276
|
+
|
277
|
+
it "includes a checkbox for a spec in a subdirectory" do
|
278
|
+
last_response.body.should have_tag("input[@value='/spec/some/thing.html']")
|
279
|
+
end
|
280
|
+
|
281
|
+
it "includes a form to run the multirunner" do
|
282
|
+
last_response.body.should have_tag("form[@action='/multirunner']")
|
283
|
+
end
|
284
|
+
|
285
|
+
it "includes a submit button for the multirunner form" do
|
286
|
+
last_response.body.should have_tag("input[@type='submit']")
|
287
|
+
end
|
288
|
+
end
|
289
|
+
|
290
|
+
describe "/multirunner" do
|
291
|
+
include RspecHpricotMatchers
|
292
|
+
|
293
|
+
before do
|
294
|
+
get "/multirunner?spec=/spec/common.html"
|
295
|
+
end
|
296
|
+
|
297
|
+
it "is available" do
|
298
|
+
last_response.should be_ok
|
299
|
+
end
|
300
|
+
|
301
|
+
it "is html" do
|
302
|
+
last_response.content_type.should == 'text/html'
|
303
|
+
end
|
304
|
+
|
305
|
+
it "includes the multirunner script" do
|
306
|
+
last_response.body.should have_tag("script[@src='/shenandoah/multirunner.js']")
|
307
|
+
end
|
308
|
+
|
309
|
+
it "includes the container" do
|
310
|
+
last_response.body.should have_tag("div#runner")
|
311
|
+
end
|
312
|
+
end
|
313
|
+
|
314
|
+
describe "/shenandoah/multirunner.js" do
|
315
|
+
before do
|
316
|
+
get '/shenandoah/multirunner.js'
|
317
|
+
end
|
318
|
+
|
319
|
+
it "is available" do
|
320
|
+
last_response.should be_ok
|
321
|
+
end
|
322
|
+
|
323
|
+
it "is javascript" do
|
324
|
+
last_response.content_type.should == 'text/javascript'
|
325
|
+
end
|
326
|
+
|
327
|
+
it "contains the multirunner script" do
|
328
|
+
last_response.body.should =~ /shenandoah.Multirunner/
|
329
|
+
end
|
330
|
+
|
331
|
+
it "includes jQuery" do
|
332
|
+
last_response.body.should =~ %r{\* jQuery JavaScript Library v1\.3\.2}
|
333
|
+
end
|
334
|
+
|
335
|
+
it "includes parseQuery" do
|
336
|
+
last_response.body.should =~ %r{jQuery.parseQuery =}
|
337
|
+
end
|
338
|
+
end
|
339
|
+
|
340
|
+
describe "/js/common/jquery-1.3.2.js" do
|
341
|
+
before do
|
342
|
+
get '/js/common/jquery-1.3.2.js'
|
343
|
+
end
|
344
|
+
|
345
|
+
it "is available" do
|
346
|
+
last_response.should be_ok
|
347
|
+
end
|
348
|
+
|
349
|
+
it "is javascript" do
|
350
|
+
last_response.content_type.should == 'application/javascript'
|
351
|
+
end
|
352
|
+
|
353
|
+
it "includes jQuery" do
|
354
|
+
last_response.body.should =~ %r{\* jQuery JavaScript Library v1\.3\.2}
|
214
355
|
end
|
215
356
|
end
|
216
357
|
end
|