butternut 0.2.2-java
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/.document +5 -0
- data/.gitignore +22 -0
- data/LICENSE +20 -0
- data/README.rdoc +18 -0
- data/Rakefile +63 -0
- data/VERSION +1 -0
- data/butternut.gemspec +82 -0
- data/lib/butternut/cucumber.css +112 -0
- data/lib/butternut/cucumber.sass +152 -0
- data/lib/butternut/formatter.rb +144 -0
- data/lib/butternut/helpers.rb +103 -0
- data/lib/butternut/scenario_extensions.rb +7 -0
- data/lib/butternut.rb +27 -0
- data/spec/butternut/formatter_spec.rb +146 -0
- data/spec/butternut/helpers_spec.rb +132 -0
- data/spec/butternut_spec.rb +53 -0
- data/spec/fixtures/blargh.html +9 -0
- data/spec/fixtures/css/bar.css +3 -0
- data/spec/fixtures/facepalm.jpg +0 -0
- data/spec/fixtures/foo.css +9 -0
- data/spec/fixtures/foo.html +27 -0
- data/spec/fixtures/foo.js +3 -0
- data/spec/fixtures/picard.jpg +0 -0
- data/spec/spec.opts +1 -0
- data/spec/spec_helper.rb +97 -0
- data/tmp/.gitignore +2 -0
- metadata +123 -0
data/.document
ADDED
data/.gitignore
ADDED
data/LICENSE
ADDED
@@ -0,0 +1,20 @@
|
|
1
|
+
Copyright (c) 2009 Jeremy Stephens
|
2
|
+
|
3
|
+
Permission is hereby granted, free of charge, to any person obtaining
|
4
|
+
a copy of this software and associated documentation files (the
|
5
|
+
"Software"), to deal in the Software without restriction, including
|
6
|
+
without limitation the rights to use, copy, modify, merge, publish,
|
7
|
+
distribute, sublicense, and/or sell copies of the Software, and to
|
8
|
+
permit persons to whom the Software is furnished to do so, subject to
|
9
|
+
the following conditions:
|
10
|
+
|
11
|
+
The above copyright notice and this permission notice shall be
|
12
|
+
included in all copies or substantial portions of the Software.
|
13
|
+
|
14
|
+
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
|
15
|
+
EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
|
16
|
+
MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
|
17
|
+
NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
|
18
|
+
LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
|
19
|
+
OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
|
20
|
+
WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
|
data/README.rdoc
ADDED
@@ -0,0 +1,18 @@
|
|
1
|
+
= butternut
|
2
|
+
|
3
|
+
Description goes here.
|
4
|
+
|
5
|
+
== Note on Patches/Pull Requests
|
6
|
+
|
7
|
+
* Fork the project.
|
8
|
+
* Make your feature addition or bug fix.
|
9
|
+
* Add tests for it. This is important so I don't break it in a
|
10
|
+
future version unintentionally.
|
11
|
+
* Commit, do not mess with rakefile, version, or history.
|
12
|
+
(if you want to have your own version, that is fine but
|
13
|
+
bump version in a commit by itself I can ignore when I pull)
|
14
|
+
* Send me a pull request. Bonus points for topic branches.
|
15
|
+
|
16
|
+
== Copyright
|
17
|
+
|
18
|
+
Copyright (c) 2009 Jeremy Stephens. See LICENSE for details.
|
data/Rakefile
ADDED
@@ -0,0 +1,63 @@
|
|
1
|
+
require 'rubygems'
|
2
|
+
require 'rake'
|
3
|
+
|
4
|
+
begin
|
5
|
+
require 'jeweler'
|
6
|
+
Jeweler::Tasks.new do |gem|
|
7
|
+
gem.name = "butternut"
|
8
|
+
gem.summary = %Q{A Cucumber formatter that uses Celerity to capture HTML sources (JRuby)}
|
9
|
+
gem.description = %Q{Based on Cucumber's HTML formatter, Butternut uses Celerity to capture page sources after each step.}
|
10
|
+
gem.email = "viking415@gmail.com"
|
11
|
+
gem.homepage = "http://github.com/viking/butternut"
|
12
|
+
gem.authors = ["Jeremy Stephens"]
|
13
|
+
gem.platform = "java"
|
14
|
+
gem.add_dependency "cucumber", ">= 0.6.0"
|
15
|
+
gem.add_dependency "celerity"
|
16
|
+
gem.add_dependency "nokogiri"
|
17
|
+
gem.add_development_dependency "rspec", ">= 1.2.9"
|
18
|
+
# gem is a Gem::Specification... see http://www.rubygems.org/read/chapter/20 for additional settings
|
19
|
+
end
|
20
|
+
Jeweler::GemcutterTasks.new
|
21
|
+
rescue LoadError
|
22
|
+
puts "Jeweler (or a dependency) not available. Install it with: sudo gem install jeweler"
|
23
|
+
end
|
24
|
+
|
25
|
+
require 'spec/rake/spectask'
|
26
|
+
Spec::Rake::SpecTask.new(:spec) do |spec|
|
27
|
+
spec.ruby_opts = %w{-X+O}
|
28
|
+
spec.libs << 'lib' << 'spec'
|
29
|
+
spec.spec_files = FileList['spec/**/*_spec.rb']
|
30
|
+
end
|
31
|
+
|
32
|
+
Spec::Rake::SpecTask.new(:rcov) do |spec|
|
33
|
+
spec.libs << 'lib' << 'spec'
|
34
|
+
spec.pattern = 'spec/**/*_spec.rb'
|
35
|
+
spec.rcov = true
|
36
|
+
end
|
37
|
+
|
38
|
+
task :spec => [:check_dependencies, "tmp:clear"]
|
39
|
+
|
40
|
+
task :default => :spec
|
41
|
+
|
42
|
+
require 'rake/rdoctask'
|
43
|
+
Rake::RDocTask.new do |rdoc|
|
44
|
+
version = File.exist?('VERSION') ? File.read('VERSION') : ""
|
45
|
+
|
46
|
+
rdoc.rdoc_dir = 'rdoc'
|
47
|
+
rdoc.title = "butternut #{version}"
|
48
|
+
rdoc.rdoc_files.include('README*')
|
49
|
+
rdoc.rdoc_files.include('lib/**/*.rb')
|
50
|
+
end
|
51
|
+
|
52
|
+
desc 'Generate the css for the html formatter from sass'
|
53
|
+
task :sass do
|
54
|
+
sh 'sass -t expanded lib/butternut/cucumber.sass > lib/butternut/cucumber.css'
|
55
|
+
end
|
56
|
+
|
57
|
+
namespace :tmp do
|
58
|
+
desc 'Delete temporary files'
|
59
|
+
task :clear do
|
60
|
+
require 'fileutils'
|
61
|
+
FileUtils.rm_rf(Dir.glob(File.dirname(__FILE__) + "/tmp/*"))
|
62
|
+
end
|
63
|
+
end
|
data/VERSION
ADDED
@@ -0,0 +1 @@
|
|
1
|
+
0.2.2
|
data/butternut.gemspec
ADDED
@@ -0,0 +1,82 @@
|
|
1
|
+
# Generated by jeweler
|
2
|
+
# DO NOT EDIT THIS FILE DIRECTLY
|
3
|
+
# Instead, edit Jeweler::Tasks in Rakefile, and run the gemspec command
|
4
|
+
# -*- encoding: utf-8 -*-
|
5
|
+
|
6
|
+
Gem::Specification.new do |s|
|
7
|
+
s.name = %q{butternut}
|
8
|
+
s.version = "0.2.2"
|
9
|
+
s.platform = %q{java}
|
10
|
+
|
11
|
+
s.required_rubygems_version = Gem::Requirement.new(">= 0") if s.respond_to? :required_rubygems_version=
|
12
|
+
s.authors = ["Jeremy Stephens"]
|
13
|
+
s.date = %q{2010-02-10}
|
14
|
+
s.description = %q{Based on Cucumber's HTML formatter, Butternut uses Celerity to capture page sources after each step.}
|
15
|
+
s.email = %q{viking415@gmail.com}
|
16
|
+
s.extra_rdoc_files = [
|
17
|
+
"LICENSE",
|
18
|
+
"README.rdoc"
|
19
|
+
]
|
20
|
+
s.files = [
|
21
|
+
".document",
|
22
|
+
".gitignore",
|
23
|
+
"LICENSE",
|
24
|
+
"README.rdoc",
|
25
|
+
"Rakefile",
|
26
|
+
"VERSION",
|
27
|
+
"butternut.gemspec",
|
28
|
+
"lib/butternut.rb",
|
29
|
+
"lib/butternut/cucumber.css",
|
30
|
+
"lib/butternut/cucumber.sass",
|
31
|
+
"lib/butternut/formatter.rb",
|
32
|
+
"lib/butternut/helpers.rb",
|
33
|
+
"lib/butternut/scenario_extensions.rb",
|
34
|
+
"spec/butternut/formatter_spec.rb",
|
35
|
+
"spec/butternut/helpers_spec.rb",
|
36
|
+
"spec/butternut_spec.rb",
|
37
|
+
"spec/fixtures/blargh.html",
|
38
|
+
"spec/fixtures/css/bar.css",
|
39
|
+
"spec/fixtures/facepalm.jpg",
|
40
|
+
"spec/fixtures/foo.css",
|
41
|
+
"spec/fixtures/foo.html",
|
42
|
+
"spec/fixtures/foo.js",
|
43
|
+
"spec/fixtures/picard.jpg",
|
44
|
+
"spec/spec.opts",
|
45
|
+
"spec/spec_helper.rb",
|
46
|
+
"tmp/.gitignore"
|
47
|
+
]
|
48
|
+
s.homepage = %q{http://github.com/viking/butternut}
|
49
|
+
s.rdoc_options = ["--charset=UTF-8"]
|
50
|
+
s.require_paths = ["lib"]
|
51
|
+
s.rubygems_version = %q{1.3.5}
|
52
|
+
s.summary = %q{A Cucumber formatter that uses Celerity to capture HTML sources (JRuby)}
|
53
|
+
s.test_files = [
|
54
|
+
"spec/butternut_spec.rb",
|
55
|
+
"spec/spec_helper.rb",
|
56
|
+
"spec/butternut/formatter_spec.rb",
|
57
|
+
"spec/butternut/helpers_spec.rb"
|
58
|
+
]
|
59
|
+
|
60
|
+
if s.respond_to? :specification_version then
|
61
|
+
current_version = Gem::Specification::CURRENT_SPECIFICATION_VERSION
|
62
|
+
s.specification_version = 3
|
63
|
+
|
64
|
+
if Gem::Version.new(Gem::RubyGemsVersion) >= Gem::Version.new('1.2.0') then
|
65
|
+
s.add_runtime_dependency(%q<cucumber>, [">= 0.6.0"])
|
66
|
+
s.add_runtime_dependency(%q<celerity>, [">= 0"])
|
67
|
+
s.add_runtime_dependency(%q<nokogiri>, [">= 0"])
|
68
|
+
s.add_development_dependency(%q<rspec>, [">= 1.2.9"])
|
69
|
+
else
|
70
|
+
s.add_dependency(%q<cucumber>, [">= 0.6.0"])
|
71
|
+
s.add_dependency(%q<celerity>, [">= 0"])
|
72
|
+
s.add_dependency(%q<nokogiri>, [">= 0"])
|
73
|
+
s.add_dependency(%q<rspec>, [">= 1.2.9"])
|
74
|
+
end
|
75
|
+
else
|
76
|
+
s.add_dependency(%q<cucumber>, [">= 0.6.0"])
|
77
|
+
s.add_dependency(%q<celerity>, [">= 0"])
|
78
|
+
s.add_dependency(%q<nokogiri>, [">= 0"])
|
79
|
+
s.add_dependency(%q<rspec>, [">= 1.2.9"])
|
80
|
+
end
|
81
|
+
end
|
82
|
+
|
@@ -0,0 +1,112 @@
|
|
1
|
+
|
2
|
+
|
3
|
+
.cucumber {
|
4
|
+
font-family: Verdana, Arial, sans-serif;
|
5
|
+
font-size: 15px;
|
6
|
+
background: white;
|
7
|
+
padding: 1em; }
|
8
|
+
.cucumber h1, .cucumber h2, .cucumber h3, .cucumber h4, .cucumber ol, .cucumber li, .cucumber pre, .cucumber p {
|
9
|
+
font-size: 1em;
|
10
|
+
padding: 0px;
|
11
|
+
margin: 0px; }
|
12
|
+
.cucumber div.feature {
|
13
|
+
border: 1px solid;
|
14
|
+
padding: 2px;
|
15
|
+
margin: 4px; }
|
16
|
+
.cucumber div.feature div.background, .cucumber div.feature div.scenario, .cucumber div.feature p {
|
17
|
+
padding: 0em 0em 0em 1em; }
|
18
|
+
.cucumber div.feature div.background div.examples, .cucumber div.feature div.scenario div.examples, .cucumber div.feature p div.examples {
|
19
|
+
padding: 0em 0em 0em 1em; }
|
20
|
+
.cucumber .stats {
|
21
|
+
margin: 2em; }
|
22
|
+
.cucumber .summary ul.features li {
|
23
|
+
display: inline; }
|
24
|
+
.cucumber .backtrace {
|
25
|
+
margin-top: 0;
|
26
|
+
margin-bottom: 0;
|
27
|
+
margin-left: 1em; }
|
28
|
+
.cucumber a {
|
29
|
+
text-decoration: none;
|
30
|
+
color: inherit; }
|
31
|
+
.cucumber a:hover {
|
32
|
+
text-decoration: underline; }
|
33
|
+
.cucumber a:visited {
|
34
|
+
font-weight: normal; }
|
35
|
+
.cucumber a div.examples {
|
36
|
+
border: 1px solid;
|
37
|
+
padding: 2px;
|
38
|
+
margin: 4px; }
|
39
|
+
.cucumber table {
|
40
|
+
border-collapse: collapse; }
|
41
|
+
.cucumber table td, .cucumber table th {
|
42
|
+
font-size: 1em;
|
43
|
+
border: 1px solid #AAAAAA; }
|
44
|
+
.cucumber table td.failed {
|
45
|
+
background: #FFC0CB;
|
46
|
+
color: #8B0000; }
|
47
|
+
.cucumber table td.passed {
|
48
|
+
background: #98FB98;
|
49
|
+
color: #001111; }
|
50
|
+
.cucumber table td.skipped {
|
51
|
+
background: #e0ffff;
|
52
|
+
color: #001111; }
|
53
|
+
.cucumber table td.pending {
|
54
|
+
background: #FFFFE0;
|
55
|
+
color: #111100; }
|
56
|
+
.cucumber table td.undefined {
|
57
|
+
background: #FFFFE0;
|
58
|
+
color: #111100; }
|
59
|
+
.cucumber ol {
|
60
|
+
list-style: none; }
|
61
|
+
.cucumber ol li {
|
62
|
+
margin: 0em 0em 0em 1em;
|
63
|
+
padding: 0em 0em 0em 0.2em;
|
64
|
+
position: relative; }
|
65
|
+
.cucumber ol li span.param {
|
66
|
+
font-weight: bold; }
|
67
|
+
.cucumber ol li div.page {
|
68
|
+
position: absolute;
|
69
|
+
right: 0;
|
70
|
+
top: 0; }
|
71
|
+
.cucumber ol li.failed {
|
72
|
+
border-left: 5px solid red;
|
73
|
+
border-bottom: 1px solid red;
|
74
|
+
background: #ffc0cb;
|
75
|
+
color: #8b0000; }
|
76
|
+
.cucumber ol li.failed span.param {
|
77
|
+
background: !failed_dark; }
|
78
|
+
.cucumber ol li.passed {
|
79
|
+
border-left: 5px solid lime;
|
80
|
+
border-bottom: 1px solid lime;
|
81
|
+
background: #98fb98;
|
82
|
+
color: #001111; }
|
83
|
+
.cucumber ol li.passed span.param {
|
84
|
+
background: lime; }
|
85
|
+
.cucumber ol li.skipped {
|
86
|
+
border-left: 5px solid aqua;
|
87
|
+
border-bottom: 1px solid aqua;
|
88
|
+
background: #e0ffff;
|
89
|
+
color: #001111; }
|
90
|
+
.cucumber ol li.skipped span.param {
|
91
|
+
background: aqua; }
|
92
|
+
.cucumber ol li.pending {
|
93
|
+
border-left: 5px solid #ff8000;
|
94
|
+
border-bottom: 1px solid #ff8000;
|
95
|
+
background: yellow;
|
96
|
+
color: #2a1b0a; }
|
97
|
+
.cucumber ol li.pending span.param {
|
98
|
+
background: #ff8000; }
|
99
|
+
.cucumber ol li.undefined {
|
100
|
+
border-left: 5px solid #ff8000;
|
101
|
+
border-bottom: 1px solid #ff8000;
|
102
|
+
background: yellow;
|
103
|
+
color: #2a1b0a; }
|
104
|
+
.cucumber ol li.undefined span.param {
|
105
|
+
background: #ff8000; }
|
106
|
+
.cucumber .icon-show {
|
107
|
+
background-image: url(data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAABAAAAAQCAYAAAAf8/9hAAAABmJLR0QA/wD/AP+gvaeTAAAACXBIWXMAAAsTAAALEwEAmpwYAAAAB3RJTUUH1gkWFgcEIFayvAAAAB10RVh0Q29tbWVudABDcmVhdGVkIHdpdGggVGhlIEdJTVDvZCVuAAABsElEQVQ4y6WSS2sTURzFf3c6giWktRql7roLqIv5CA1FtBtdpC+6cVGQItFvIz6w0l1F+gG6qa0WxFUIgQhu0hJd9arptJ1mHr33uhgbcjsJFjybC//nOf97xJPK8q6UcoJzKBQKX188f3Wbf8CVUk5UKo9wnKFu8CTo8GZl7RYXgAsQxyG7e00wBmMMN67fBGB2vmwGNY6NXdl+/XKl5AKEYUQQnKQZA99/tJgp3yOKIwQOCGE1x3HCxsanyS6DXjQae/h+ANT7bh4fv4rn3bEl9ML3A96/Wx+oeW5hJnsDpRRJEluHbLd/9dF9DYAkSewBWmvSV3UTtVotM6BUmiK9WcceEEUhnU5oFXuex4W/ceiSSxwlVmJn5yNvV1dRSmWaNje/kMvlWFicWxOz82WTz+eRUlpFDx/cpVgsMjKS50zmqTrFGDBa8WHrM9VqPWXw7OkSxmQ9c3zs02w2EOd8ADB9f4pqtS7d1DuGVutbX42O42RiWmsODnyAIxeg/fsno6MFi8XZVpuY+RsTHB76AL54vLy0tb8vJ9PJA62P44geBobh4ctHWutF/hd/AExBukCW3MYjAAAAAElFTkSuQmCC);
|
108
|
+
background-repeat: no-repeat;
|
109
|
+
float: left;
|
110
|
+
width: 16px;
|
111
|
+
height: 16px;
|
112
|
+
display: block; }
|
@@ -0,0 +1,152 @@
|
|
1
|
+
# cucumber.css is generated from cucumber.sass
|
2
|
+
# Regenerate with rake sass
|
3
|
+
|
4
|
+
!step_left = 5px solid
|
5
|
+
!step_bottom = 1px solid
|
6
|
+
|
7
|
+
!failed = #FFC0CB
|
8
|
+
!failed_dark = #FF0000
|
9
|
+
!failed_text = #8B0000
|
10
|
+
|
11
|
+
!passed = #98FB98
|
12
|
+
!passed_dark = #00FF00
|
13
|
+
!passed_text = #001111
|
14
|
+
|
15
|
+
!skipped = #E0FFFF
|
16
|
+
!skipped_dark = #00FFFF
|
17
|
+
!skipped_text = #001111
|
18
|
+
|
19
|
+
!pending = #FFFF00
|
20
|
+
!pending_dark = #FF8000
|
21
|
+
!pending_text = #2A1B0A
|
22
|
+
|
23
|
+
!undefined = #FFFF00
|
24
|
+
!undefined_dark = #FF8000
|
25
|
+
!undefined_text = #2A1B0A
|
26
|
+
|
27
|
+
.cucumber
|
28
|
+
:font-family Verdana, Arial, sans-serif
|
29
|
+
:font-size 15px
|
30
|
+
:background white
|
31
|
+
:padding 1em
|
32
|
+
|
33
|
+
h1, h2, h3, h4, ol, li, pre, p
|
34
|
+
:font-size 1em
|
35
|
+
:padding 0px
|
36
|
+
:margin 0px
|
37
|
+
|
38
|
+
div.feature
|
39
|
+
:border 1px solid
|
40
|
+
:padding 2px
|
41
|
+
:margin 4px
|
42
|
+
|
43
|
+
div.background, div.scenario, p
|
44
|
+
:padding 0em 0em 0em 1em
|
45
|
+
div.examples
|
46
|
+
:padding 0em 0em 0em 1em
|
47
|
+
|
48
|
+
.stats
|
49
|
+
:margin 2em
|
50
|
+
|
51
|
+
.summary
|
52
|
+
ul.features
|
53
|
+
li
|
54
|
+
:display inline
|
55
|
+
|
56
|
+
.backtrace
|
57
|
+
:margin-top 0
|
58
|
+
:margin-bottom 0
|
59
|
+
:margin-left 1em
|
60
|
+
|
61
|
+
a
|
62
|
+
:text-decoration none
|
63
|
+
:color inherit
|
64
|
+
|
65
|
+
&:hover
|
66
|
+
:text-decoration underline
|
67
|
+
&:visited
|
68
|
+
:font-weight normal
|
69
|
+
|
70
|
+
div.examples
|
71
|
+
:border 1px solid
|
72
|
+
:padding 2px
|
73
|
+
:margin 4px
|
74
|
+
|
75
|
+
table
|
76
|
+
:border-collapse collapse
|
77
|
+
|
78
|
+
td, th
|
79
|
+
:font-size 1em
|
80
|
+
:border 1px solid #AAAAAA
|
81
|
+
td.failed
|
82
|
+
:background #FFC0CB
|
83
|
+
:color #8B0000
|
84
|
+
td.passed
|
85
|
+
:background #98FB98
|
86
|
+
:color= !passed_text
|
87
|
+
td.skipped
|
88
|
+
:background= !skipped
|
89
|
+
:color= !skipped_text
|
90
|
+
td.pending
|
91
|
+
:background #FFFFE0
|
92
|
+
:color #111100
|
93
|
+
td.undefined
|
94
|
+
:background #FFFFE0
|
95
|
+
:color #111100
|
96
|
+
|
97
|
+
ol
|
98
|
+
:list-style none
|
99
|
+
|
100
|
+
li
|
101
|
+
:margin 0em 0em 0em 1em
|
102
|
+
:padding 0em 0em 0em 0.2em
|
103
|
+
:position relative
|
104
|
+
span.param
|
105
|
+
:font-weight bold
|
106
|
+
div.page
|
107
|
+
:position absolute
|
108
|
+
:right 0
|
109
|
+
:top 0
|
110
|
+
li.failed
|
111
|
+
:border-left= !step_left !failed_dark
|
112
|
+
:border-bottom= !step_bottom !failed_dark
|
113
|
+
:background= !failed
|
114
|
+
:color= !failed_text
|
115
|
+
span.param
|
116
|
+
:background !failed_dark
|
117
|
+
li.passed
|
118
|
+
:border-left= !step_left !passed_dark
|
119
|
+
:border-bottom= !step_bottom !passed_dark
|
120
|
+
:background= !passed
|
121
|
+
:color= !passed_text
|
122
|
+
span.param
|
123
|
+
:background= !passed_dark
|
124
|
+
li.skipped
|
125
|
+
:border-left= !step_left !skipped_dark
|
126
|
+
:border-bottom= !step_bottom !skipped_dark
|
127
|
+
:background= !skipped
|
128
|
+
:color= !skipped_text
|
129
|
+
span.param
|
130
|
+
:background= !skipped_dark
|
131
|
+
li.pending
|
132
|
+
:border-left= !step_left !pending_dark
|
133
|
+
:border-bottom= !step_bottom !pending_dark
|
134
|
+
:background= !pending
|
135
|
+
:color= !pending_text
|
136
|
+
span.param
|
137
|
+
:background= !pending_dark
|
138
|
+
li.undefined
|
139
|
+
:border-left= !step_left !undefined_dark
|
140
|
+
:border-bottom= !step_bottom !undefined_dark
|
141
|
+
:background= !undefined
|
142
|
+
:color= !undefined_text
|
143
|
+
span.param
|
144
|
+
:background= !undefined_dark
|
145
|
+
|
146
|
+
.icon-show
|
147
|
+
:background-image url(data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAABAAAAAQCAYAAAAf8/9hAAAABmJLR0QA/wD/AP+gvaeTAAAACXBIWXMAAAsTAAALEwEAmpwYAAAAB3RJTUUH1gkWFgcEIFayvAAAAB10RVh0Q29tbWVudABDcmVhdGVkIHdpdGggVGhlIEdJTVDvZCVuAAABsElEQVQ4y6WSS2sTURzFf3c6giWktRql7roLqIv5CA1FtBtdpC+6cVGQItFvIz6w0l1F+gG6qa0WxFUIgQhu0hJd9arptJ1mHr33uhgbcjsJFjybC//nOf97xJPK8q6UcoJzKBQKX188f3Wbf8CVUk5UKo9wnKFu8CTo8GZl7RYXgAsQxyG7e00wBmMMN67fBGB2vmwGNY6NXdl+/XKl5AKEYUQQnKQZA99/tJgp3yOKIwQOCGE1x3HCxsanyS6DXjQae/h+ANT7bh4fv4rn3bEl9ML3A96/Wx+oeW5hJnsDpRRJEluHbLd/9dF9DYAkSewBWmvSV3UTtVotM6BUmiK9WcceEEUhnU5oFXuex4W/ceiSSxwlVmJn5yNvV1dRSmWaNje/kMvlWFicWxOz82WTz+eRUlpFDx/cpVgsMjKS50zmqTrFGDBa8WHrM9VqPWXw7OkSxmQ9c3zs02w2EOd8ADB9f4pqtS7d1DuGVutbX42O42RiWmsODnyAIxeg/fsno6MFi8XZVpuY+RsTHB76AL54vLy0tb8vJ9PJA62P44geBobh4ctHWutF/hd/AExBukCW3MYjAAAAAElFTkSuQmCC)
|
148
|
+
:background-repeat no-repeat
|
149
|
+
:float left
|
150
|
+
:width 16px
|
151
|
+
:height 16px
|
152
|
+
:display block
|
@@ -0,0 +1,144 @@
|
|
1
|
+
require 'cucumber/formatter/html'
|
2
|
+
|
3
|
+
require 'fileutils'
|
4
|
+
require 'nokogiri'
|
5
|
+
require 'uri'
|
6
|
+
require 'open-uri'
|
7
|
+
require 'net/ftp' # For Net::FTPPermError
|
8
|
+
|
9
|
+
module Butternut
|
10
|
+
class Formatter < Cucumber::Formatter::Html
|
11
|
+
|
12
|
+
def initialize(step_mother, io, options)
|
13
|
+
# find the format options
|
14
|
+
format = options[:formats].detect { |(name, _)| name == "Butternut::Formatter" }
|
15
|
+
if !format || !format[1].is_a?(String)
|
16
|
+
raise "Butternut::Formatter cannot output to STDOUT"
|
17
|
+
end
|
18
|
+
out = format[1]
|
19
|
+
|
20
|
+
super
|
21
|
+
if File.directory?(out)
|
22
|
+
#@assets_dir = out
|
23
|
+
#@assets_url = "."
|
24
|
+
else
|
25
|
+
basename = File.basename(out).sub(/\..*$/, "")
|
26
|
+
@assets_dir = File.join(File.dirname(out), basename)
|
27
|
+
@assets_url = basename
|
28
|
+
if !File.exist?(@assets_dir)
|
29
|
+
FileUtils.mkdir(@assets_dir)
|
30
|
+
end
|
31
|
+
end
|
32
|
+
end
|
33
|
+
|
34
|
+
def before_feature_element(feature_element)
|
35
|
+
super
|
36
|
+
@feature_element = feature_element
|
37
|
+
end
|
38
|
+
|
39
|
+
def after_step_result(keyword, step_match, multiline_arg, status, exception, source_indent, background)
|
40
|
+
return if @hide_this_step
|
41
|
+
# print snippet for undefined steps
|
42
|
+
if status == :undefined
|
43
|
+
step_multiline_class = @step.multiline_arg ? @step.multiline_arg.class : nil
|
44
|
+
@builder.pre do |pre|
|
45
|
+
pre << @step_mother.snippet_text(@step.actual_keyword,step_match.instance_variable_get("@name") || '',step_multiline_class)
|
46
|
+
end
|
47
|
+
end
|
48
|
+
add_page_source_link(@builder)
|
49
|
+
@builder << '</li>'
|
50
|
+
end
|
51
|
+
|
52
|
+
private
|
53
|
+
def add_page_source_link(builder)
|
54
|
+
if !@feature_element.respond_to?(:last_page_source) || @feature_element.last_page_source.nil?
|
55
|
+
# don't add a link of we haven't interacted with a webpage
|
56
|
+
return
|
57
|
+
end
|
58
|
+
|
59
|
+
page_source = @feature_element.last_page_source
|
60
|
+
page_url = @feature_element.last_page_url
|
61
|
+
@feature_element.last_page_source = nil
|
62
|
+
@feature_element.last_page_url = nil
|
63
|
+
|
64
|
+
page_source = transform_page_source(page_source, page_url)
|
65
|
+
path = source_file_name
|
66
|
+
File.open(path, "w") { |f| f.print(page_source) }
|
67
|
+
|
68
|
+
builder.a({:target => "_blank", :href => "#{@assets_url}/#{File.basename(path)}"}) do
|
69
|
+
builder << "Source"
|
70
|
+
end
|
71
|
+
end
|
72
|
+
|
73
|
+
def source_file_name
|
74
|
+
t = Time.now.strftime("%Y%m%d")
|
75
|
+
path = nil
|
76
|
+
while path.nil?
|
77
|
+
path = File.join(@assets_dir, "butternut#{t}-#{$$}-#{rand(0x100000000).to_s(36)}.html")
|
78
|
+
path = nil if File.exist?(path)
|
79
|
+
end
|
80
|
+
path
|
81
|
+
end
|
82
|
+
|
83
|
+
def transform_page_source(page_source, page_url)
|
84
|
+
base_uri = URI.parse(page_url)
|
85
|
+
base_uri.query = nil
|
86
|
+
@already_collected = []
|
87
|
+
|
88
|
+
doc = Nokogiri.HTML(page_source)
|
89
|
+
{ :image => ['img', 'src'],
|
90
|
+
:stylesheet => ['link[rel=stylesheet]', 'href']
|
91
|
+
}.each_pair do |type, (selector, attr)|
|
92
|
+
doc.css(selector).each do |elt|
|
93
|
+
elt_url = elt[attr]
|
94
|
+
next if elt_url.nil? || elt_url.empty?
|
95
|
+
|
96
|
+
result = save_remote_file(base_uri, type, elt_url)
|
97
|
+
elt[attr] = result if result
|
98
|
+
end
|
99
|
+
end
|
100
|
+
|
101
|
+
# disable links
|
102
|
+
doc.css('a').each { |link| link['href'] = "#" }
|
103
|
+
|
104
|
+
# turn off scripts
|
105
|
+
doc.css('script').each { |s| s.unlink }
|
106
|
+
|
107
|
+
# disable form elements
|
108
|
+
doc.css('input, select, textarea').each { |x| x['disabled'] = 'disabled' }
|
109
|
+
|
110
|
+
doc.to_s
|
111
|
+
end
|
112
|
+
|
113
|
+
def transform_stylesheet(stylesheet_uri, content)
|
114
|
+
content.gsub(%r{url\(([^\)]+)\)}) do |_|
|
115
|
+
result = save_remote_file(stylesheet_uri, :image, $1)
|
116
|
+
"url(#{result || $1})"
|
117
|
+
end
|
118
|
+
end
|
119
|
+
|
120
|
+
def save_remote_file(base_uri, type, url)
|
121
|
+
# FIXME: two different files could have the same basename :)
|
122
|
+
begin
|
123
|
+
uri = URI.parse(url)
|
124
|
+
rescue URI::InvalidURIError
|
125
|
+
return nil
|
126
|
+
end
|
127
|
+
remote_uri = uri.absolute? ? uri : base_uri.merge(uri)
|
128
|
+
basename = File.basename(uri.path)
|
129
|
+
|
130
|
+
unless @already_collected.include?(remote_uri)
|
131
|
+
begin
|
132
|
+
content = open(remote_uri.to_s).read
|
133
|
+
content = transform_stylesheet(remote_uri, content) if type == :stylesheet
|
134
|
+
local_path = File.join(@assets_dir, basename)
|
135
|
+
File.open(local_path, "w") { |f| f.write(content) }
|
136
|
+
@already_collected << remote_uri
|
137
|
+
rescue IOError, Errno::ENOENT, OpenURI::HTTPError, Net::FTPPermError
|
138
|
+
return nil
|
139
|
+
end
|
140
|
+
end
|
141
|
+
basename
|
142
|
+
end
|
143
|
+
end
|
144
|
+
end
|