butternut 0.0.1 → 0.1.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/Rakefile +9 -1
- data/VERSION +1 -1
- data/butternut.gemspec +2 -1
- data/lib/butternut/formatter.rb +40 -28
- data/spec/butternut/formatter_spec.rb +36 -7
- data/spec/fixtures/facepalm.jpg +0 -0
- data/spec/fixtures/foo.css +6 -0
- data/spec/fixtures/foo.html +6 -1
- data/spec/spec.opts +1 -0
- metadata +2 -1
data/Rakefile
CHANGED
@@ -33,7 +33,7 @@ Spec::Rake::SpecTask.new(:rcov) do |spec|
|
|
33
33
|
spec.rcov = true
|
34
34
|
end
|
35
35
|
|
36
|
-
task :spec => :check_dependencies
|
36
|
+
task :spec => [:check_dependencies, "tmp:clear"]
|
37
37
|
|
38
38
|
task :default => :spec
|
39
39
|
|
@@ -51,3 +51,11 @@ desc 'Generate the css for the html formatter from sass'
|
|
51
51
|
task :sass do
|
52
52
|
sh 'sass -t expanded lib/butternut/cucumber.sass > lib/butternut/cucumber.css'
|
53
53
|
end
|
54
|
+
|
55
|
+
namespace :tmp do
|
56
|
+
desc 'Delete temporary files'
|
57
|
+
task :clear do
|
58
|
+
require 'fileutils'
|
59
|
+
FileUtils.rm_rf(Dir.glob(File.dirname(__FILE__) + "/tmp/features/*"), :verbose => true)
|
60
|
+
end
|
61
|
+
end
|
data/VERSION
CHANGED
@@ -1 +1 @@
|
|
1
|
-
0.0
|
1
|
+
0.1.0
|
data/butternut.gemspec
CHANGED
@@ -5,7 +5,7 @@
|
|
5
5
|
|
6
6
|
Gem::Specification.new do |s|
|
7
7
|
s.name = %q{butternut}
|
8
|
-
s.version = "0.0
|
8
|
+
s.version = "0.1.0"
|
9
9
|
|
10
10
|
s.required_rubygems_version = Gem::Requirement.new(">= 0") if s.respond_to? :required_rubygems_version=
|
11
11
|
s.authors = ["Jeremy Stephens"]
|
@@ -34,6 +34,7 @@ Gem::Specification.new do |s|
|
|
34
34
|
"spec/butternut/helpers_spec.rb",
|
35
35
|
"spec/butternut_spec.rb",
|
36
36
|
"spec/fixtures/css/bar.css",
|
37
|
+
"spec/fixtures/facepalm.jpg",
|
37
38
|
"spec/fixtures/foo.css",
|
38
39
|
"spec/fixtures/foo.html",
|
39
40
|
"spec/fixtures/foo.js",
|
data/lib/butternut/formatter.rb
CHANGED
@@ -1,10 +1,12 @@
|
|
1
1
|
require 'cucumber/formatter/ordered_xml_markup'
|
2
2
|
require 'cucumber/formatter/duration'
|
3
|
+
|
3
4
|
require 'tmpdir'
|
4
5
|
require 'fileutils'
|
5
6
|
require 'nokogiri'
|
6
7
|
require 'uri'
|
7
8
|
require 'open-uri'
|
9
|
+
require 'net/ftp' # For Net::FTPPermError
|
8
10
|
|
9
11
|
module Butternut
|
10
12
|
class Formatter
|
@@ -414,42 +416,25 @@ module Butternut
|
|
414
416
|
end
|
415
417
|
|
416
418
|
def transform_page_source(page_source, page_url)
|
417
|
-
|
418
|
-
|
419
|
-
|
419
|
+
base_uri = URI.parse(page_url)
|
420
|
+
base_uri.query = nil
|
421
|
+
@already_collected = []
|
420
422
|
|
421
423
|
doc = Nokogiri.HTML(page_source)
|
422
|
-
{ 'img'
|
423
|
-
'link[rel=stylesheet]'
|
424
|
-
}.each_pair do |selector, attr|
|
424
|
+
{ :image => ['img', 'src'],
|
425
|
+
:stylesheet => ['link[rel=stylesheet]', 'href']
|
426
|
+
}.each_pair do |type, (selector, attr)|
|
425
427
|
doc.css(selector).each do |elt|
|
426
428
|
elt_url = elt[attr]
|
427
|
-
next if elt_url.nil?
|
428
|
-
|
429
|
-
|
430
|
-
|
431
|
-
next if collected_files.index(elt_url)
|
432
|
-
|
433
|
-
basename = File.basename(elt_url)
|
434
|
-
local_file = File.join(@source_output_dir, basename)
|
435
|
-
remote_file = case elt_url
|
436
|
-
when %r{^\w+://} then elt_url
|
437
|
-
when %r{^/} then
|
438
|
-
"#{page_uri.scheme}://#{page_uri.host}:#{page_uri.port}#{elt_url}"
|
439
|
-
else
|
440
|
-
page_url.to_s + "/" + elt_url
|
441
|
-
end
|
442
|
-
File.open(local_file, "w") { |f| f.write open(remote_file).read }
|
443
|
-
collected_files << elt_url
|
444
|
-
|
445
|
-
elt[attr] = basename
|
429
|
+
next if elt_url.nil? || elt_url.empty?
|
430
|
+
|
431
|
+
result = save_remote_file(base_uri, type, elt_url)
|
432
|
+
elt[attr] = result if result
|
446
433
|
end
|
447
434
|
end
|
448
435
|
|
449
436
|
# disable links
|
450
|
-
doc.css('a').each
|
451
|
-
link['href'] = "#"
|
452
|
-
end
|
437
|
+
doc.css('a').each { |link| link['href'] = "#" }
|
453
438
|
|
454
439
|
# turn off scripts
|
455
440
|
doc.css('script').each { |s| s.unlink }
|
@@ -459,5 +444,32 @@ module Butternut
|
|
459
444
|
|
460
445
|
doc.to_s
|
461
446
|
end
|
447
|
+
|
448
|
+
def transform_stylesheet(stylesheet_uri, content)
|
449
|
+
content.gsub(%r{url\(([^\)]+)\)}) do |_|
|
450
|
+
result = save_remote_file(stylesheet_uri, :image, $1)
|
451
|
+
"url(#{result || $1})"
|
452
|
+
end
|
453
|
+
end
|
454
|
+
|
455
|
+
def save_remote_file(base_uri, type, url)
|
456
|
+
# FIXME: two different files could have the same basename :)
|
457
|
+
uri = URI.parse(url)
|
458
|
+
remote_uri = uri.absolute? ? uri : base_uri.merge(uri)
|
459
|
+
basename = File.basename(uri.path)
|
460
|
+
|
461
|
+
unless @already_collected.include?(remote_uri)
|
462
|
+
begin
|
463
|
+
content = open(remote_uri.to_s).read
|
464
|
+
content = transform_stylesheet(remote_uri, content) if type == :stylesheet
|
465
|
+
local_path = File.join(@source_output_dir, basename)
|
466
|
+
File.open(local_path, "w") { |f| f.write(content) }
|
467
|
+
@already_collected << remote_uri
|
468
|
+
rescue Errno::ENOENT, OpenURI::HTTPError, Net::FTPPermError
|
469
|
+
return nil
|
470
|
+
end
|
471
|
+
end
|
472
|
+
basename
|
473
|
+
end
|
462
474
|
end
|
463
475
|
end
|
@@ -12,6 +12,12 @@ module Butternut
|
|
12
12
|
end
|
13
13
|
end
|
14
14
|
|
15
|
+
Spec::Matchers.define :be_an_existing_file do
|
16
|
+
match do |filename|
|
17
|
+
File.exist?(filename)
|
18
|
+
end
|
19
|
+
end
|
20
|
+
|
15
21
|
def setup_formatter(options = {})
|
16
22
|
@out = StringIO.new
|
17
23
|
@formatter = Butternut::Formatter.new(step_mother, @out, options)
|
@@ -232,15 +238,15 @@ module Butternut
|
|
232
238
|
|
233
239
|
describe "displaying page source to file" do
|
234
240
|
before(:each) do
|
235
|
-
|
241
|
+
dir = File.join(File.dirname(__FILE__), "..", "..", "tmp")
|
236
242
|
setup_formatter({:formats => [
|
237
|
-
['Butternut::Formatter', File.join(
|
243
|
+
['Butternut::Formatter', File.join(dir, "main", "huge.html")]
|
238
244
|
]})
|
239
245
|
run_defined_feature
|
240
246
|
@doc = Nokogiri.HTML(@out.string)
|
241
247
|
|
242
|
-
|
243
|
-
file = most_recent_html_file(
|
248
|
+
@tmp_dir = File.join(dir, "features", Date.today.to_s)
|
249
|
+
file = most_recent_html_file(@tmp_dir)
|
244
250
|
@page_doc = Nokogiri.HTML(open(file).read)
|
245
251
|
end
|
246
252
|
|
@@ -264,9 +270,20 @@ module Butternut
|
|
264
270
|
end
|
265
271
|
|
266
272
|
it "saves images and stylesheets and rewrites urls in page source" do
|
267
|
-
@page_doc.at('img')['src'].should == "picard.jpg"
|
268
|
-
|
269
|
-
|
273
|
+
@page_doc.at('img:nth(1)')['src'].should == "picard.jpg"
|
274
|
+
File.join(@tmp_dir, "picard.jpg").should be_an_existing_file
|
275
|
+
|
276
|
+
@page_doc.at('link:nth(1)[rel="stylesheet"]')['href'].should == "foo.css"
|
277
|
+
File.join(@tmp_dir, "foo.css").should be_an_existing_file
|
278
|
+
|
279
|
+
@page_doc.at('link:nth(2)[rel="stylesheet"]')['href'].should == "bar.css"
|
280
|
+
File.join(@tmp_dir, "bar.css").should be_an_existing_file
|
281
|
+
end
|
282
|
+
|
283
|
+
it "saves assets and rewrites urls referred to by stylesheets" do
|
284
|
+
foo = open(File.join(@tmp_dir, "foo.css")).read
|
285
|
+
foo.should include("url(facepalm.jpg)")
|
286
|
+
File.join(@tmp_dir, "facepalm.jpg").should be_an_existing_file
|
270
287
|
end
|
271
288
|
|
272
289
|
it "turns off links" do
|
@@ -284,6 +301,18 @@ module Butternut
|
|
284
301
|
elt['disabled'].should == "disabled"
|
285
302
|
end
|
286
303
|
end
|
304
|
+
|
305
|
+
it "handles Errno::ENOENT" do
|
306
|
+
@page_doc.at('img:nth(2)')['src'].should == "/roflpwnage/missing_file_omg.gif"
|
307
|
+
end
|
308
|
+
|
309
|
+
it "handles OpenURI::HTTPError" do
|
310
|
+
@page_doc.at('img:nth(3)')['src'].should == "http://google.com/missing_file_omg.gif"
|
311
|
+
end
|
312
|
+
|
313
|
+
it "handles Net::FTPPermError" do
|
314
|
+
@page_doc.at('img:nth(4)')['src'].should == "ftp://mirror.anl.gov/missing_file_omg.gif"
|
315
|
+
end
|
287
316
|
end
|
288
317
|
end
|
289
318
|
end
|
Binary file
|
data/spec/fixtures/foo.css
CHANGED
data/spec/fixtures/foo.html
CHANGED
@@ -2,7 +2,7 @@
|
|
2
2
|
<head>
|
3
3
|
<title>Foo</title>
|
4
4
|
<link rel="stylesheet" href="foo.css" type="text/css"/>
|
5
|
-
<link rel="stylesheet" href="
|
5
|
+
<link rel="stylesheet" href="css/bar.css" type="text/css"/>
|
6
6
|
<script type="text/javascript" src="foo.js"></script>
|
7
7
|
</head>
|
8
8
|
<body>
|
@@ -17,5 +17,10 @@
|
|
17
17
|
<textarea name="yar"></textarea>
|
18
18
|
<input type="submit" value="Submit" />
|
19
19
|
</form>
|
20
|
+
<img src="/roflpwnage/missing_file_omg.gif"/>
|
21
|
+
<img src="http://google.com/missing_file_omg.gif"/>
|
22
|
+
<img src="ftp://mirror.anl.gov/missing_file_omg.gif"/>
|
23
|
+
|
24
|
+
<div class="facepalm"> </div>
|
20
25
|
</body>
|
21
26
|
</html>
|
data/spec/spec.opts
CHANGED
metadata
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: butternut
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 0.0
|
4
|
+
version: 0.1.0
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- Jeremy Stephens
|
@@ -79,6 +79,7 @@ files:
|
|
79
79
|
- spec/butternut/helpers_spec.rb
|
80
80
|
- spec/butternut_spec.rb
|
81
81
|
- spec/fixtures/css/bar.css
|
82
|
+
- spec/fixtures/facepalm.jpg
|
82
83
|
- spec/fixtures/foo.css
|
83
84
|
- spec/fixtures/foo.html
|
84
85
|
- spec/fixtures/foo.js
|