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,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));
|