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