butternut 0.2.2-java
Sign up to get free protection for your applications and to get access to all the features.
- 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
|