shenandoah 0.1.3 → 0.2.0
Sign up to get free protection for your applications and to get access to all the features.
- 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,13 @@
|
|
1
|
+
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.1//EN" "http://www.w3.org/TR/xhtml11/DTD/xhtml11.dtd">
|
2
|
+
<html xmlns="http://www.w3.org/1999/xhtml">
|
3
|
+
|
4
|
+
<head>
|
5
|
+
<title>life.js | JavaScript Testing Results</title>
|
6
|
+
<link rel="stylesheet" href="/shenandoah.css" type="text/css" charset="utf-8" />
|
7
|
+
<script type="text/javascript" src="/shenandoah/browser-runner.js"></script>
|
8
|
+
</head>
|
9
|
+
|
10
|
+
<body>
|
11
|
+
<!-- Put any HTML fixture elements here. -->
|
12
|
+
</body>
|
13
|
+
</html>
|
@@ -0,0 +1,28 @@
|
|
1
|
+
require_main('cells.js');
|
2
|
+
require_main('life.js');
|
3
|
+
|
4
|
+
Screw.Unit(function () {
|
5
|
+
describe('Life', function () {
|
6
|
+
var game;
|
7
|
+
before(function () {
|
8
|
+
game = new Life(new Cells([
|
9
|
+
[0, 1, 0],
|
10
|
+
[0, 1, 0],
|
11
|
+
[0, 1, 0]
|
12
|
+
]));
|
13
|
+
});
|
14
|
+
|
15
|
+
it("steps", function () {
|
16
|
+
game.step();
|
17
|
+
expect(game.cells.get(0, 0).age).to(equal, 0);
|
18
|
+
expect(game.cells.get(0, 1).age).to(equal, 0);
|
19
|
+
expect(game.cells.get(0, 2).age).to(equal, 0);
|
20
|
+
expect(game.cells.get(1, 0).age).to(equal, 1);
|
21
|
+
expect(game.cells.get(1, 1).age).to(equal, 2);
|
22
|
+
expect(game.cells.get(1, 2).age).to(equal, 1);
|
23
|
+
expect(game.cells.get(2, 0).age).to(equal, 0);
|
24
|
+
expect(game.cells.get(2, 1).age).to(equal, 0);
|
25
|
+
expect(game.cells.get(2, 2).age).to(equal, 0);
|
26
|
+
});
|
27
|
+
});
|
28
|
+
});
|
@@ -0,0 +1,30 @@
|
|
1
|
+
Feature: Testing projects which just use rake
|
2
|
+
|
3
|
+
Scenario: Defined tasks
|
4
|
+
Given a plain-rake project
|
5
|
+
When I list the available rake tasks
|
6
|
+
Then the task list should include shen:serve
|
7
|
+
And the task list should include shen:generate[basename]
|
8
|
+
And the task list should include shen:spec[pattern]
|
9
|
+
And the task list should include shen:shell
|
10
|
+
|
11
|
+
Scenario: Running the server
|
12
|
+
Given a plain-rake project
|
13
|
+
When I execute `rake shen:serve`
|
14
|
+
Then the server should be running
|
15
|
+
|
16
|
+
Scenario: Running all specs
|
17
|
+
Given a plain-rake project
|
18
|
+
When I execute `rake shen:spec`
|
19
|
+
Then 49 specs should run
|
20
|
+
|
21
|
+
Scenario: Running one spec
|
22
|
+
Given a plain-rake project
|
23
|
+
When I execute `rake shen:spec[life_spec]`
|
24
|
+
Then 1 spec should run
|
25
|
+
|
26
|
+
Scenario: Generating a spec
|
27
|
+
Given an empty plain-rake project
|
28
|
+
When I execute `rake shen:generate[pre_view]`
|
29
|
+
Then the file "spec/pre_view_spec.js" should exist
|
30
|
+
And the file "spec/pre_view.html" should exist
|
@@ -0,0 +1,39 @@
|
|
1
|
+
Feature: Testing rails projects
|
2
|
+
|
3
|
+
Scenario: Defined tasks
|
4
|
+
Given a rails project
|
5
|
+
When I list the available rake tasks
|
6
|
+
Then the task list should include shen:serve
|
7
|
+
And the task list should not include shen:generate[basename]
|
8
|
+
And the task list should include shen:spec[pattern]
|
9
|
+
And the task list should include shen:shell
|
10
|
+
|
11
|
+
Scenario: Running the server
|
12
|
+
Given a rails project
|
13
|
+
When I execute `rake shen:serve`
|
14
|
+
Then the server should be running
|
15
|
+
|
16
|
+
Scenario: Running all specs
|
17
|
+
Given a rails project
|
18
|
+
When I execute `rake shen:spec`
|
19
|
+
Then 49 specs should run
|
20
|
+
|
21
|
+
Scenario: Running one spec
|
22
|
+
Given a rails project
|
23
|
+
When I execute `rake shen:spec[life_spec]`
|
24
|
+
Then 1 spec should run
|
25
|
+
|
26
|
+
Scenario: Integrating with a new rails project
|
27
|
+
Given an empty rails project
|
28
|
+
When I execute `script/generate shenandoah`
|
29
|
+
Then the file "lib/tasks/shenandoah.rake" should exist
|
30
|
+
And the directory "test/javascript" should exist
|
31
|
+
And the file "test/javascript/spec_helper.js" should exist
|
32
|
+
And the file "test/javascript/application.html" should exist
|
33
|
+
And the file "test/javascript/application_spec.js" should exist
|
34
|
+
|
35
|
+
Scenario: Generating a spec
|
36
|
+
Given a rails project
|
37
|
+
When I execute `script/generate shen_spec pre_view`
|
38
|
+
Then the file "test/javascript/pre_view_spec.js" should exist
|
39
|
+
And the file "test/javascript/pre_view.html" should exist
|
@@ -0,0 +1,26 @@
|
|
1
|
+
Given /a buildr project/ do
|
2
|
+
switch_to_project('buildr')
|
3
|
+
|
4
|
+
open("buildfile", 'w') do |f|
|
5
|
+
f.write <<-RUBY
|
6
|
+
$LOAD_PATH.unshift(File.join(#{root_path.inspect}, 'lib'))
|
7
|
+
require 'shenandoah/buildr'
|
8
|
+
|
9
|
+
define 'life' do
|
10
|
+
test.using :shenandoah
|
11
|
+
end
|
12
|
+
RUBY
|
13
|
+
end
|
14
|
+
|
15
|
+
mkdir_p 'src/main/javascript'
|
16
|
+
cp Dir["#{base_project}/lib/**/*"], 'src/main/javascript'
|
17
|
+
|
18
|
+
mkdir_p 'src/spec/javascript'
|
19
|
+
cp Dir["#{base_project}/spec/**/*"], 'src/spec/javascript'
|
20
|
+
end
|
21
|
+
|
22
|
+
When /^I list the available buildr tasks$/ do
|
23
|
+
@tasks = `buildr help:tasks`.scan(/\n\s*(\S+)\s*#/).collect { |m| m.first }
|
24
|
+
$?.should == 0
|
25
|
+
end
|
26
|
+
|
@@ -0,0 +1,38 @@
|
|
1
|
+
|
2
|
+
Given /an empty rails project/ do
|
3
|
+
switch_to_project('rails')
|
4
|
+
system("rails . > /dev/null")
|
5
|
+
|
6
|
+
File.open('config/initializers/shenandoh_dev.rb', 'w') do |f|
|
7
|
+
f.write <<-RUBY
|
8
|
+
require 'rails_generator'
|
9
|
+
|
10
|
+
begin
|
11
|
+
$LOAD_PATH.unshift(File.join(#{root_path.inspect}, 'lib'))
|
12
|
+
|
13
|
+
Rails::Generator::Base.prepend_sources(
|
14
|
+
Rails::Generator::PathSource.new(
|
15
|
+
:shenandoah_dev, File.join(#{root_path.inspect}, 'rails_generators')))
|
16
|
+
end
|
17
|
+
RUBY
|
18
|
+
end
|
19
|
+
end
|
20
|
+
|
21
|
+
Given /a rails project/ do
|
22
|
+
Given "an empty rails project"
|
23
|
+
|
24
|
+
File.open('lib/tasks/shenandoah.rake', 'w') do |f|
|
25
|
+
f.write <<-RUBY
|
26
|
+
begin
|
27
|
+
$LOAD_PATH.unshift(File.join(#{root_path.inspect}, 'lib'))
|
28
|
+
end
|
29
|
+
|
30
|
+
require 'shenandoah/rails/tasks'
|
31
|
+
Shenandoah::Rails::Tasks.new
|
32
|
+
RUBY
|
33
|
+
end
|
34
|
+
|
35
|
+
mkdir "test/javascript"
|
36
|
+
cp Dir["#{base_project}/lib/*"], "public/javascripts"
|
37
|
+
cp Dir["#{base_project}/spec/*"], "test/javascript"
|
38
|
+
end
|
@@ -0,0 +1,45 @@
|
|
1
|
+
require 'open-uri'
|
2
|
+
|
3
|
+
Given /^a plain-rake project$/ do
|
4
|
+
cd base_project
|
5
|
+
end
|
6
|
+
|
7
|
+
Given /^an empty plain-rake project$/ do
|
8
|
+
switch_to_project('starter')
|
9
|
+
cp "#{base_project}/Rakefile", "Rakefile"
|
10
|
+
end
|
11
|
+
|
12
|
+
When /^I list the available rake tasks$/ do
|
13
|
+
@tasks = `rake -T`.scan(/rake (\S+)/).collect { |m| m.first }
|
14
|
+
$?.should == 0
|
15
|
+
end
|
16
|
+
|
17
|
+
Then /^the task list should (not )?include (\S+)$/ do |no, task_name|
|
18
|
+
if no
|
19
|
+
@tasks.should_not include(task_name)
|
20
|
+
else
|
21
|
+
@tasks.should include(task_name)
|
22
|
+
end
|
23
|
+
end
|
24
|
+
|
25
|
+
When %r{^I execute \`([^`]+)\`$} do |command|
|
26
|
+
@pipe = IO.popen(command)
|
27
|
+
end
|
28
|
+
|
29
|
+
Then %r{^(\d+) specs? should run$} do |count|
|
30
|
+
@pipe.read.
|
31
|
+
scan(/(\d+) test\(s\)/).
|
32
|
+
collect { |matches| matches.first.to_i }.
|
33
|
+
inject(0) { |s, i| s + i }.
|
34
|
+
should == count.to_i
|
35
|
+
end
|
36
|
+
|
37
|
+
Then %r{^the server should be running$} do
|
38
|
+
sleep 10
|
39
|
+
open('http://localhost:4410/') { |f| f.read }.should_not be_nil
|
40
|
+
end
|
41
|
+
|
42
|
+
Then /^the (?:file|directory) "([^\"]*)" should exist$/ do |filename|
|
43
|
+
@pipe.read if @pipe
|
44
|
+
File.exist?(filename).should be_true
|
45
|
+
end
|
@@ -0,0 +1,48 @@
|
|
1
|
+
require 'spec/expectations'
|
2
|
+
|
3
|
+
Before do
|
4
|
+
@original_wd = FileUtils.pwd
|
5
|
+
end
|
6
|
+
|
7
|
+
After do
|
8
|
+
FileUtils.cd @original_wd
|
9
|
+
if @pipe
|
10
|
+
Process.kill 15, @pipe.pid
|
11
|
+
@pipe.close
|
12
|
+
end
|
13
|
+
cleanup
|
14
|
+
end
|
15
|
+
|
16
|
+
class ShenandoahWorld
|
17
|
+
include FileUtils
|
18
|
+
|
19
|
+
def root_path
|
20
|
+
@root ||= File.expand_path("../../..")
|
21
|
+
end
|
22
|
+
|
23
|
+
def base_project
|
24
|
+
@base_project ||= File.expand_path("../example_projects/base", File.dirname(__FILE__))
|
25
|
+
end
|
26
|
+
|
27
|
+
def switch_to_project(name)
|
28
|
+
path = File.expand_path("../#{name}", base_project);
|
29
|
+
self.temp_projects << path
|
30
|
+
mkdir_p path
|
31
|
+
cd path
|
32
|
+
path
|
33
|
+
end
|
34
|
+
|
35
|
+
def cleanup
|
36
|
+
self.temp_projects.each { |dir| rm_rf dir }
|
37
|
+
end
|
38
|
+
|
39
|
+
protected
|
40
|
+
|
41
|
+
def temp_projects
|
42
|
+
@temp_projects ||= []
|
43
|
+
end
|
44
|
+
end
|
45
|
+
|
46
|
+
World do
|
47
|
+
ShenandoahWorld.new
|
48
|
+
end
|
@@ -0,0 +1,138 @@
|
|
1
|
+
@import compass/reset
|
2
|
+
|
3
|
+
!running = #CC6600
|
4
|
+
!passed = #5A753D
|
5
|
+
!failed = #993300
|
6
|
+
!border_color = #6E6E6E
|
7
|
+
!background_color = #EDEBD5
|
8
|
+
|
9
|
+
body
|
10
|
+
padding: 0.5em
|
11
|
+
font-family: Helvetica, sans-serif
|
12
|
+
background= !background_color
|
13
|
+
|
14
|
+
li
|
15
|
+
list-style-type: none
|
16
|
+
|
17
|
+
.focused
|
18
|
+
background-color: #F4F2E4
|
19
|
+
*
|
20
|
+
opacity: 1.0
|
21
|
+
|
22
|
+
h3.status
|
23
|
+
font-style: italic
|
24
|
+
padding-bottom: 1em
|
25
|
+
|
26
|
+
h1, h2, p
|
27
|
+
opacity: 0.4
|
28
|
+
|
29
|
+
.describes
|
30
|
+
padding-left: 0
|
31
|
+
|
32
|
+
h1
|
33
|
+
font-size: 1.1em
|
34
|
+
color: #877C21
|
35
|
+
line-height: 1.8em
|
36
|
+
margin: 0pt 0pt 0.6em
|
37
|
+
border-bottom: 1px solid transparent
|
38
|
+
font-weight: bold
|
39
|
+
|
40
|
+
&:hover
|
41
|
+
cursor: pointer
|
42
|
+
color: #000
|
43
|
+
background-color: #F4F2E4
|
44
|
+
border-bottom: 1px solid #9A8E51
|
45
|
+
|
46
|
+
.describe
|
47
|
+
margin-left: 0.6em
|
48
|
+
padding-left: 0.6em
|
49
|
+
margin-bottom: 2px
|
50
|
+
margin-right: 2px
|
51
|
+
border= 1px "dotted" !border_color
|
52
|
+
|
53
|
+
.its .it
|
54
|
+
list-style-type: lower-roman
|
55
|
+
list-style-position: outside
|
56
|
+
margin-left: 2.0em
|
57
|
+
|
58
|
+
h2
|
59
|
+
font-weight: normal
|
60
|
+
font-style: normal
|
61
|
+
padding-left: 0.5em
|
62
|
+
font-size: 1.0em
|
63
|
+
color: #877C21
|
64
|
+
line-height: 1.8em
|
65
|
+
margin: 0 0 0.5em
|
66
|
+
border-bottom: 1px solid transparent
|
67
|
+
|
68
|
+
&.enqueued h2
|
69
|
+
background-color= !running
|
70
|
+
color: white !important
|
71
|
+
|
72
|
+
&.passed h2
|
73
|
+
background-color= !passed
|
74
|
+
color: white !important
|
75
|
+
|
76
|
+
&.failed
|
77
|
+
h2
|
78
|
+
background-color= !failed
|
79
|
+
color: white !important
|
80
|
+
|
81
|
+
p
|
82
|
+
margin-left: 1em
|
83
|
+
color= !failed
|
84
|
+
|
85
|
+
h2:hover
|
86
|
+
cursor: pointer
|
87
|
+
color: #000 !important
|
88
|
+
border-bottom: 1px solid #9A8E51
|
89
|
+
|
90
|
+
// Index styles
|
91
|
+
|
92
|
+
body#index
|
93
|
+
padding: 3em
|
94
|
+
ul li
|
95
|
+
margin-left: 1.2em
|
96
|
+
list-style-type: disc
|
97
|
+
line-height: 1.2em
|
98
|
+
h2
|
99
|
+
font-size: 1.2em
|
100
|
+
margin: 0.5em 0
|
101
|
+
#controls
|
102
|
+
margin-top: 1em
|
103
|
+
#select-all
|
104
|
+
margin-left: 1.2em
|
105
|
+
|
106
|
+
// Multirunner styles
|
107
|
+
|
108
|
+
#frames
|
109
|
+
clear: both
|
110
|
+
|
111
|
+
#frames iframe
|
112
|
+
width: 94%
|
113
|
+
height: 90%
|
114
|
+
display: none
|
115
|
+
border= 2px "solid" !border_color
|
116
|
+
margin: 1em 2%
|
117
|
+
clear: both
|
118
|
+
&.active
|
119
|
+
display: block
|
120
|
+
|
121
|
+
#specs li
|
122
|
+
display: block
|
123
|
+
padding: 4px
|
124
|
+
margin: 2px
|
125
|
+
background-color= !background_color - #333
|
126
|
+
float: left
|
127
|
+
border= 2px "solid" !background_color
|
128
|
+
cursor: pointer
|
129
|
+
&.active
|
130
|
+
border-color= !border_color
|
131
|
+
&.passed
|
132
|
+
background-color= !passed
|
133
|
+
color: #ddd
|
134
|
+
&.failed
|
135
|
+
background-color= !failed
|
136
|
+
color: #ddd
|
137
|
+
span.name
|
138
|
+
color: #fff
|
@@ -0,0 +1,18 @@
|
|
1
|
+
(function ($) {
|
2
|
+
$(document).ready(function () {
|
3
|
+
var checkboxes_selector = "form input";
|
4
|
+
|
5
|
+
$('#select-all input').click(function () {
|
6
|
+
if ($(this).is(':checked')) {
|
7
|
+
$(checkboxes_selector).attr('checked', true);
|
8
|
+
} else {
|
9
|
+
$(checkboxes_selector).attr('checked', false);
|
10
|
+
}
|
11
|
+
});
|
12
|
+
|
13
|
+
$(checkboxes_selector).click(function () {
|
14
|
+
$('#select-all input').attr('checked',
|
15
|
+
$(checkboxes_selector).filter(':checked').size() == $(checkboxes_selector).size());
|
16
|
+
});
|
17
|
+
});
|
18
|
+
}(jQuery));
|
@@ -0,0 +1,32 @@
|
|
1
|
+
if (!window.shenandoah) { shenandoah = { }; }
|
2
|
+
|
3
|
+
(function ($) {
|
4
|
+
shenandoah.MultirunnerFrame = function () {
|
5
|
+
// Finds the IFRAME which contains this window in the parent DOM
|
6
|
+
var containingFrame = $.grep(window.parent.jQuery('iframe'), function (iframe, idx) {
|
7
|
+
return iframe.contentWindow === window;
|
8
|
+
})[0];
|
9
|
+
|
10
|
+
function parentTrigger(name, data) {
|
11
|
+
if (containingFrame) {
|
12
|
+
window.parent.jQuery(containingFrame).trigger(name, data);
|
13
|
+
}
|
14
|
+
}
|
15
|
+
|
16
|
+
this.register = function () {
|
17
|
+
$(Screw).bind('after', function () {
|
18
|
+
parentTrigger('complete', {
|
19
|
+
passed_count: $('.passed').length,
|
20
|
+
failed_count: $('.failed').length,
|
21
|
+
total_count: $('.passed').length + $('.failed').length
|
22
|
+
});
|
23
|
+
});
|
24
|
+
};
|
25
|
+
};
|
26
|
+
|
27
|
+
|
28
|
+
$(document).ready(function () {
|
29
|
+
new shenandoah.MultirunnerFrame().register();
|
30
|
+
});
|
31
|
+
|
32
|
+
}(jQuery));
|