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 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
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.1"
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",
@@ -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
- page_uri = URI.parse(page_url)
418
- page_uri.query = nil
419
- collected_files = []
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' => 'src',
423
- 'link[rel=stylesheet]' => 'href'
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
- elt_url.gsub!('\\"', "")
430
- next if elt_url.empty?
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 do |link|
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
- @tmpdir = File.join(File.dirname(__FILE__), "..", "..", "tmp")
241
+ dir = File.join(File.dirname(__FILE__), "..", "..", "tmp")
236
242
  setup_formatter({:formats => [
237
- ['Butternut::Formatter', File.join(@tmpdir, "main", "huge.html")]
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
- dir = File.join(@tmpdir, "features", Date.today.to_s)
243
- file = most_recent_html_file(dir)
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
- @page_doc.at('link:first[rel="stylesheet"]')['href'].should == "foo.css"
269
- @page_doc.at('link:last[rel="stylesheet"]')['href'].should == "bar.css"
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
@@ -1,3 +1,9 @@
1
1
  body {
2
2
  font-family: Verdana;
3
3
  }
4
+
5
+ .facepalm {
6
+ width: 750px;
7
+ height: 600px;
8
+ background: url(../fixtures/facepalm.jpg);
9
+ }
@@ -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="/css/bar.css" type="text/css"/>
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">&nbsp;</div>
20
25
  </body>
21
26
  </html>
data/spec/spec.opts CHANGED
@@ -1 +1,2 @@
1
1
  --color
2
+ --backtrace
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.1
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