gnawrnip 0.1.3 → 0.2.0

Sign up to get free protection for your applications and to get access to all the features.
data/.gitignore CHANGED
@@ -18,3 +18,5 @@ tmp
18
18
  vendor
19
19
  example/vendor
20
20
  example/report.html
21
+ .sass-cache
22
+ example/.sass-cache
data/README.md CHANGED
@@ -21,7 +21,6 @@ So it have potential for massive refactorings (that could be API breaking).
21
21
  * RubyGems
22
22
  * capybara `~> 2.1.0`
23
23
  * turnip_formatter
24
- * rmagick ( **optional** )
25
24
 
26
25
  ## Installation
27
26
 
@@ -50,25 +49,29 @@ You can do to customize a screenshot.
50
49
 
51
50
  ```ruby
52
51
  Gnawrnip.configure do |c|
53
- c.publisher_driver = :js
54
- c.make_animation = true
55
- c.frame_interval = 1000 # milliseconds
56
- c.frame_size = [640, 360] # width, height
52
+ c.frame_interval = 1000 # milliseconds
53
+ c.make_animation = true
54
+ c.max_frame_size = 1024 # pixel
57
55
  end
58
56
  ```
59
57
 
60
- * `publisher_driver` (Symbol) A driver that make screenshot like animation GIF.
61
- * `:js`: use jQuery and image files. **The size of the report file tends to be large this driver**
62
- * `:rmagick`: Make pure animation GIF using [RMagick](http://rmagick.rubyforge.org/). This driver is requires Gem `rmagick`. Add this line to your application's Gemfile:
63
-
64
- ```
65
- gem 'rmagick'
66
- ```
67
58
  * `make_animation` (Boolean) Whether to make animation GIF. (Default: true)
68
59
  * `frame_interval` (Integer) A time (millisecond) between each image in an animation. Default is `1000` (1sec)
69
60
  * This option is enabled only when the `make_animation = true`.
70
- * `frame_size` (Array) A size of screenshot (width, height). Default is `nil` (`nil` means that use `Capybara.current_driver.browser` size) .
71
- * This option is enabled only when the `publisher_driver = :rmagick`.
61
+ * `max_frame_size` (Integer) Maximum size that use to resize of image.
62
+ * If given, it resize the image to fit to this value.
63
+ * Ignored if this value is greater than original width and height.
64
+ * Example:
65
+
66
+ ```
67
+ original: 640x480
68
+ this value: 300
69
+ result : 300x225
70
+
71
+ original: 480x640
72
+ this value: 400
73
+ result : 300x400
74
+ ```
72
75
 
73
76
  As example, see [example/spec/spec_helper.rb](https://github.com/gongo/gnawrnip/tree/master/example/spec/spec_helper.rb) .
74
77
 
@@ -21,10 +21,7 @@ Capybara.default_driver = :poltergeist
21
21
  Capybara.javascript_driver = :selenium
22
22
 
23
23
  Gnawrnip.configure do |c|
24
- # c.publisher_driver = :js
25
- c.publisher_driver = :rmagick
26
24
  c.frame_interval = 1000 # milliseconds
27
- c.frame_size = [640, 360] # width, height
28
- c.make_animation = false
25
+ c.make_animation = true
26
+ c.max_frame_size = 1024 # pixel
29
27
  end
30
-
data/gnawrnip.gemspec CHANGED
@@ -19,10 +19,10 @@ Gem::Specification.new do |spec|
19
19
  spec.require_paths = ["lib"]
20
20
 
21
21
  spec.add_dependency 'capybara', "~> 2.1"
22
- spec.add_dependency 'turnip_formatter', '~> 0.2.2'
22
+ spec.add_dependency 'turnip_formatter', '~> 0.2.8'
23
+ spec.add_dependency 'oily_png'
23
24
  spec.add_development_dependency "bundler", "~> 1.3"
24
25
  spec.add_development_dependency "rake"
25
26
  spec.add_development_dependency 'rspec'
26
27
  spec.add_development_dependency 'coveralls'
27
- spec.add_development_dependency 'rmagick'
28
28
  end
@@ -1,21 +1,30 @@
1
1
  require 'base64'
2
2
 
3
3
  module Gnawrnip
4
- module Publisher
4
+ class Publisher
5
+
6
+ #
7
+ # @params [Array] paths Array of screenshot image filename
8
+ #
5
9
  def animation(paths)
6
- raise NotImplementedError
10
+ paths.map { |path| image_tag(path) }.join
7
11
  end
8
12
 
13
+ #
14
+ # @params [string] path Screenshot image filename
15
+ #
9
16
  def single(path)
10
- image_tag(image_base64(path))
17
+ image_tag(path)
11
18
  end
12
19
 
13
- def image_base64(path)
14
- Base64.strict_encode64(File.read(path))
15
- end
20
+ private
16
21
 
17
- def image_tag(data, format = :png)
18
- '<img src="data:image/' + format.to_s + ';base64,' + data + '"/>'
19
- end
22
+ def image_tag(path, format = :png)
23
+ %Q|<img src="data:image/#{format.to_s};base64,#{image_base64(path)}"/>|
24
+ end
25
+
26
+ def image_base64(path)
27
+ Base64.strict_encode64(File.read(path))
28
+ end
20
29
  end
21
30
  end
@@ -29,6 +29,7 @@ module Gnawrnip
29
29
  begin
30
30
  tempfile = Tempfile.new(['gnawrnip', '.png'])
31
31
  session.save_screenshot(tempfile.path)
32
+ resize(tempfile.path) if need_resize?
32
33
  tempfile
33
34
  rescue Capybara::NotSupportedByDriverError => e
34
35
  raise e
@@ -41,9 +42,46 @@ module Gnawrnip
41
42
 
42
43
  private
43
44
 
44
- def session
45
- Capybara.current_session
46
- end
45
+ def session
46
+ Capybara.current_session
47
+ end
48
+
49
+ def need_resize?
50
+ !Gnawrnip.max_frame_size.nil?
51
+ end
52
+
53
+ def resize(path)
54
+ require 'oily_png'
55
+
56
+ image = OilyPNG::Canvas.from_file(path)
57
+ new_width, new_height = calculate_new_size(image.width, image.height)
58
+
59
+ image.resample_bilinear!(new_width, new_height)
60
+ image.save(path)
61
+ end
62
+
63
+ #
64
+ # Return new frame size (width and height).
65
+ # This size is keeping original aspect ratio.
66
+ #
67
+ # @return [Array] New width and height size. [width, height]
68
+ #
69
+ def calculate_new_size(width, height)
70
+ ratio = width / height
71
+ target = Gnawrnip.max_frame_size
72
+
73
+ return [width, height] if target > [width, height].max
74
+
75
+ if ratio < 0
76
+ new_width = target * ratio
77
+ new_height = target
78
+ else
79
+ new_width = target
80
+ new_height = target / ratio
81
+ end
82
+
83
+ return [new_width, new_height]
84
+ end
47
85
  end
48
86
  end
49
87
  end
@@ -6,7 +6,7 @@ module Gnawrnip
6
6
  module StepScreenshot
7
7
  class << self
8
8
  #
9
- # @param [Array] png_base64_list array of base64 encoded image
9
+ # @param [Array] png_base64_list array of base64 encoded image
10
10
  #
11
11
  def build(png_base64_list)
12
12
  case png_base64_list.length
@@ -20,9 +20,22 @@ module Gnawrnip
20
20
  end
21
21
 
22
22
  def animation_image(paths)
23
- text = '<div class="screenshot animation">'
23
+ text = <<-EOS
24
+ <div class="screenshot animation">
25
+ <div class="nav">
26
+ <div class="pager"></div>
27
+ <div class="manipulate">
28
+ <span class="play selected">&#9654;</span>
29
+ <span class="stop">&#9632;</span>
30
+ </div>
31
+ </div>
32
+ <div class="slides">
33
+ EOS
24
34
  text += Gnawrnip.publisher.animation(paths)
25
- text + '</div>'
35
+ text + <<-EOS
36
+ </div>
37
+ </div>
38
+ EOS
26
39
  end
27
40
 
28
41
  def single_image(path)
@@ -35,16 +48,93 @@ module Gnawrnip
35
48
  end
36
49
 
37
50
  module TurnipFormatter
51
+ Template.add_js_file('http://cdnjs.cloudflare.com/ajax/libs/jquery.cycle2/20130801/jquery.cycle2.min.js')
52
+
53
+ Template.add_js(<<-EOS)
54
+ $(function() {
55
+ $('.screenshot.animation').each(function() {
56
+ var slide = $(this).find('.slides').cycle({
57
+ timeout: 1000,
58
+ autoHeight: "container",
59
+ pager: $(this).find('div.nav .pager')
60
+ });
61
+
62
+ var nav = $(this).find('div.nav');
63
+ var playButton = nav.find('.play');
64
+ var stopButton = nav.find('.stop');
65
+
66
+ var coloringOfStopped = function() {
67
+ playButton.removeClass("selected");
68
+ stopButton.addClass("selected");
69
+ };
70
+
71
+ var coloringOfPlaying = function() {
72
+ playButton.addClass("selected");
73
+ stopButton.removeClass("selected");
74
+ };
75
+
76
+ playButton.click(function() { slide.cycle('resume'); });
77
+ stopButton.click(function() { slide.cycle('pause'); });
78
+
79
+ slide.on('cycle-pager-activated', function(event, opts) {
80
+ slide.cycle('pause');
81
+ });
82
+
83
+ slide.on('cycle-paused', function(event, opts) {
84
+ coloringOfStopped();
85
+ });
86
+
87
+ slide.on('cycle-resumed', function(event, opts) {
88
+ coloringOfPlaying();
89
+ });
90
+ });
91
+ });
92
+ EOS
93
+
38
94
  Template.add_scss(<<-EOS)
39
95
  div#steps-statistics section.scenario {
40
96
  ul.steps {
41
97
  div.screenshot {
42
- > img {
98
+ img {
43
99
  max-width: 90%;
44
100
  border: 2px solid black;
45
101
  }
46
- }
47
- }
102
+ }
103
+
104
+ div.screenshot.animation {
105
+ > div.nav {
106
+ text-align: center;
107
+
108
+ .pager {
109
+ margin-left: auto;
110
+ margin-right: auto;
111
+
112
+ span {
113
+ font-size: 50px;
114
+ display: inline;
115
+ color: #999999;
116
+ cursor: pointer;
117
+
118
+ &.cycle-pager-active {
119
+ color: red;
120
+ }
121
+ }
122
+ }
123
+
124
+ .manipulate {
125
+ span {
126
+ color: black;
127
+ font-size: 30px;
128
+ cursor: pointer;
129
+
130
+ &.selected {
131
+ color: red;
132
+ }
133
+ }
134
+ }
135
+ }
136
+ }
137
+ }
48
138
  }
49
139
  EOS
50
140
 
@@ -1,3 +1,3 @@
1
1
  module Gnawrnip
2
- VERSION = "0.1.3"
2
+ VERSION = "0.2.0"
3
3
  end
data/lib/gnawrnip.rb CHANGED
@@ -1,22 +1,43 @@
1
1
  require "gnawrnip/version"
2
2
  require 'gnawrnip/rspec'
3
3
  require 'gnawrnip/photographer'
4
- require 'gnawrnip/step_screenshot'
4
+ require 'gnawrnip/publisher'
5
5
 
6
6
  module Gnawrnip
7
7
  class << self
8
- attr_accessor :publisher_driver
8
+ #
9
+ # [Integer] Time (millisecond) between each image in animation
10
+ #
9
11
  attr_accessor :frame_interval
10
- attr_accessor :frame_size
12
+
13
+ #
14
+ # [Boolean] Whether to make animation GIF
15
+ #
11
16
  attr_accessor :make_animation
12
17
 
18
+ #
19
+ # [Integer] Maximum size that use to resize of image.
20
+ # If given, it resize the image to fit to this value.
21
+ # Ignored if this value is greater than original width and height.
22
+ #
23
+ # Example:
24
+ # original: 640x480
25
+ # this value: 300
26
+ # result : 300x225
27
+ #
28
+ # original: 480x640
29
+ # this value: 400
30
+ # result : 300x400
31
+ #
32
+ attr_accessor :max_frame_size
33
+
13
34
  def configure
14
35
  yield self
15
36
  end
16
37
 
17
38
  def ready!
18
39
  require 'gnawrnip/ext/capybara/session' if animation?
19
- publisher
40
+ require 'gnawrnip/step_screenshot'
20
41
  end
21
42
 
22
43
  def animation?
@@ -24,25 +45,21 @@ module Gnawrnip
24
45
  end
25
46
 
26
47
  def photographer
27
- @photographer ||= Gnawrnip::Photographer.new
48
+ @photographer ||= Photographer.new
28
49
  end
29
50
 
30
51
  def publisher
31
- @publisher ||= case publisher_driver
32
- when :rmagick
33
- require 'gnawrnip/publisher/rmagick'
34
- @publisher = Publisher::RMagick.new
35
- else # :js
36
- require 'gnawrnip/publisher/js'
37
- @publisher = Publisher::JS.new
38
- end
52
+ @publisher ||= Publisher.new
53
+ end
54
+
55
+ def publisher_driver=(driver)
56
+ warn "DEPRECATED: `publisher_driver` option is deprecated (not used)."
39
57
  end
40
58
  end
41
59
  end
42
60
 
43
61
  Gnawrnip.configure do |c|
44
- c.publisher_driver = :js
45
- c.frame_interval = 1000
46
- c.frame_size = nil
47
- c.make_animation = true
62
+ c.frame_interval = 1000
63
+ c.make_animation = true
64
+ c.max_frame_size = nil
48
65
  end
@@ -6,8 +6,24 @@ module Gnawrnip
6
6
  describe '.take' do
7
7
  subject { Screenshot.take.read }
8
8
 
9
- # see GnawrnipTestSession::save_screenshot
10
- it { should == "screenshot" }
9
+ context 'No given max frame size' do
10
+ before do
11
+ Screenshot.stub(:need_resize?) { false }
12
+ Screenshot.should_not_receive(:resize)
13
+ end
14
+
15
+ # see GnawrnipTestSession::save_screenshot
16
+ it { should == "screenshot" }
17
+ end
18
+
19
+ context 'No given max frame size' do
20
+ before do
21
+ Screenshot.stub(:need_resize?) { true }
22
+ Screenshot.should_receive(:resize)
23
+ end
24
+
25
+ it { should == "screenshot" }
26
+ end
11
27
 
12
28
  context 'not support save_screenshot' do
13
29
  before do
@@ -28,7 +28,8 @@ module Gnawrnip
28
28
  should include '<div class="screenshot animation">'
29
29
  should include '<img src="data:image/png;base64,' + data1 + '"/>'
30
30
  should include '<img src="data:image/png;base64,' + data2 + '"/>'
31
- should include '<img src="data:image/png;base64,' + data3 + '"/></div>'
31
+ should include '<img src="data:image/png;base64,' + data3 + '"/>'
32
+ should include '<div class="nav">'
32
33
  end
33
34
  end
34
35
 
@@ -38,6 +39,7 @@ module Gnawrnip
38
39
  data = Base64.strict_encode64('aiueo')
39
40
  should include '<div class="screenshot">'
40
41
  should include '<img src="data:image/png;base64,' + data + '"/></div>'
42
+ should_not include '<div class="nav">'
41
43
  }
42
44
  end
43
45
 
metadata CHANGED
@@ -1,7 +1,7 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: gnawrnip
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.1.3
4
+ version: 0.2.0
5
5
  prerelease:
6
6
  platform: ruby
7
7
  authors:
@@ -9,7 +9,7 @@ authors:
9
9
  autorequire:
10
10
  bindir: bin
11
11
  cert_chain: []
12
- date: 2013-07-16 00:00:00.000000000 Z
12
+ date: 2013-11-15 00:00:00.000000000 Z
13
13
  dependencies:
14
14
  - !ruby/object:Gem::Dependency
15
15
  name: capybara
@@ -34,7 +34,7 @@ dependencies:
34
34
  requirements:
35
35
  - - ~>
36
36
  - !ruby/object:Gem::Version
37
- version: 0.2.2
37
+ version: 0.2.8
38
38
  type: :runtime
39
39
  prerelease: false
40
40
  version_requirements: !ruby/object:Gem::Requirement
@@ -42,41 +42,41 @@ dependencies:
42
42
  requirements:
43
43
  - - ~>
44
44
  - !ruby/object:Gem::Version
45
- version: 0.2.2
45
+ version: 0.2.8
46
46
  - !ruby/object:Gem::Dependency
47
- name: bundler
47
+ name: oily_png
48
48
  requirement: !ruby/object:Gem::Requirement
49
49
  none: false
50
50
  requirements:
51
- - - ~>
51
+ - - ! '>='
52
52
  - !ruby/object:Gem::Version
53
- version: '1.3'
54
- type: :development
53
+ version: '0'
54
+ type: :runtime
55
55
  prerelease: false
56
56
  version_requirements: !ruby/object:Gem::Requirement
57
57
  none: false
58
58
  requirements:
59
- - - ~>
59
+ - - ! '>='
60
60
  - !ruby/object:Gem::Version
61
- version: '1.3'
61
+ version: '0'
62
62
  - !ruby/object:Gem::Dependency
63
- name: rake
63
+ name: bundler
64
64
  requirement: !ruby/object:Gem::Requirement
65
65
  none: false
66
66
  requirements:
67
- - - ! '>='
67
+ - - ~>
68
68
  - !ruby/object:Gem::Version
69
- version: '0'
69
+ version: '1.3'
70
70
  type: :development
71
71
  prerelease: false
72
72
  version_requirements: !ruby/object:Gem::Requirement
73
73
  none: false
74
74
  requirements:
75
- - - ! '>='
75
+ - - ~>
76
76
  - !ruby/object:Gem::Version
77
- version: '0'
77
+ version: '1.3'
78
78
  - !ruby/object:Gem::Dependency
79
- name: rspec
79
+ name: rake
80
80
  requirement: !ruby/object:Gem::Requirement
81
81
  none: false
82
82
  requirements:
@@ -92,7 +92,7 @@ dependencies:
92
92
  - !ruby/object:Gem::Version
93
93
  version: '0'
94
94
  - !ruby/object:Gem::Dependency
95
- name: coveralls
95
+ name: rspec
96
96
  requirement: !ruby/object:Gem::Requirement
97
97
  none: false
98
98
  requirements:
@@ -108,7 +108,7 @@ dependencies:
108
108
  - !ruby/object:Gem::Version
109
109
  version: '0'
110
110
  - !ruby/object:Gem::Dependency
111
- name: rmagick
111
+ name: coveralls
112
112
  requirement: !ruby/object:Gem::Requirement
113
113
  none: false
114
114
  requirements:
@@ -149,14 +149,11 @@ files:
149
149
  - lib/gnawrnip/no_screenshot.png
150
150
  - lib/gnawrnip/photographer.rb
151
151
  - lib/gnawrnip/publisher.rb
152
- - lib/gnawrnip/publisher/js.rb
153
- - lib/gnawrnip/publisher/rmagick.rb
154
152
  - lib/gnawrnip/rspec.rb
155
153
  - lib/gnawrnip/screenshot.rb
156
154
  - lib/gnawrnip/step_screenshot.rb
157
155
  - lib/gnawrnip/version.rb
158
156
  - spec/gnawrnip/photographer_spec.rb
159
- - spec/gnawrnip/publisher/rmagick.rb
160
157
  - spec/gnawrnip/rspec_spec.rb
161
158
  - spec/gnawrnip/screenshot_spec.rb
162
159
  - spec/gnawrnip/step_screenshot_spec.rb
@@ -176,7 +173,7 @@ required_ruby_version: !ruby/object:Gem::Requirement
176
173
  version: '0'
177
174
  segments:
178
175
  - 0
179
- hash: 2586147401268872003
176
+ hash: 270195121
180
177
  required_rubygems_version: !ruby/object:Gem::Requirement
181
178
  none: false
182
179
  requirements:
@@ -185,7 +182,7 @@ required_rubygems_version: !ruby/object:Gem::Requirement
185
182
  version: '0'
186
183
  segments:
187
184
  - 0
188
- hash: 2586147401268872003
185
+ hash: 270195121
189
186
  requirements: []
190
187
  rubyforge_project:
191
188
  rubygems_version: 1.8.23
@@ -194,7 +191,6 @@ specification_version: 3
194
191
  summary: Add-on for TurnipFormatter with Capybara
195
192
  test_files:
196
193
  - spec/gnawrnip/photographer_spec.rb
197
- - spec/gnawrnip/publisher/rmagick.rb
198
194
  - spec/gnawrnip/rspec_spec.rb
199
195
  - spec/gnawrnip/screenshot_spec.rb
200
196
  - spec/gnawrnip/step_screenshot_spec.rb
@@ -1,30 +0,0 @@
1
- require 'gnawrnip/publisher'
2
- require 'turnip_formatter/template'
3
-
4
- module Gnawrnip
5
- module Publisher
6
- class JS
7
- include Gnawrnip::Publisher
8
-
9
- def animation(images)
10
- images.map { |img| single(img) }.join
11
- end
12
- end
13
- end
14
- end
15
-
16
- TurnipFormatter::Template.add_js(<<-EOS)
17
- $(function() {
18
- $('.screenshot.animation').each(function() {
19
- var imgs = $(this).children('img');
20
- var frame = 0;
21
-
22
- imgs.hide();
23
- setInterval(function() {
24
- imgs.hide();
25
- imgs.eq(frame).show();
26
- frame = (++frame % imgs.length);
27
- }, #{Gnawrnip.frame_interval.to_s});
28
- });
29
- });
30
- EOS
@@ -1,47 +0,0 @@
1
- require 'gnawrnip/publisher'
2
-
3
- module Gnawrnip
4
- module Publisher
5
- class RMagick
6
- include Gnawrnip::Publisher
7
-
8
- def initialize
9
- Kernel.require 'RMagick'
10
- rescue LoadError => e
11
- if e.message =~ /cannot load.*RMagick/
12
- raise LoadError, "Please install the gem and add `gem 'rmagick'` to your Gemfile if you are using bundler."
13
- else
14
- raise e
15
- end
16
- end
17
-
18
- def animation(images)
19
- creator = photo_creator(images)
20
- tempfile = Tempfile.new(['gnawrnip', '.gif'])
21
- creator.write(tempfile.path)
22
-
23
- image_tag(image_base64(tempfile.path), :gif)
24
- end
25
-
26
- def single(image)
27
- animation([image])
28
- end
29
-
30
- private
31
-
32
- def photo_creator(images)
33
- paths = images.map(&:path)
34
- photos = ::Magick::ImageList.new(*paths)
35
-
36
- photos.delay = Gnawrnip.frame_interval / 10.0
37
- unless Gnawrnip.frame_size.nil?
38
- photos.each do |p|
39
- p.scale!(*Gnawrnip.frame_size)
40
- end
41
- end
42
-
43
- photos
44
- end
45
- end
46
- end
47
- end
@@ -1,56 +0,0 @@
1
- require 'spec_helper'
2
- require 'gnawrnip/publisher/rmagick'
3
- require 'RMagick'
4
-
5
- module Gnawrnip
6
- module Publisher
7
- describe RMagick do
8
- let(:photographer) { RMagick.new }
9
-
10
- describe '.new' do
11
- subject { lambda { photographer } }
12
-
13
- context 'cannot load rmagick' do
14
- before do
15
- error = LoadError.new("LoadError: cannot load such file -- RMagick")
16
- Kernel.stub(:require).and_raise(error)
17
- end
18
-
19
- it { should raise_error LoadError, /gem 'rmagick'/ }
20
- end
21
-
22
- context 'cannot load other library' do
23
- before do
24
- error = LoadError.new("LoadError: cannot load such file -- samurai")
25
- Kernel.stub(:require).and_raise(error)
26
- end
27
-
28
- it { should raise_error LoadError, /such file -- samurai/ }
29
- end
30
- end
31
-
32
- describe '#animation' do
33
- let(:screenshot_list) {
34
- [GnawrnipTest.image('hoge'), GnawrnipTest.image('fuga')]
35
- }
36
-
37
- let(:creator) {
38
- d = double
39
- d.stub(:write) { |path| File.write(path, d.data) }
40
- d
41
- }
42
-
43
- context 'exists image files' do
44
- before do
45
- photographer.stub(:photo_creator) do |args|
46
- creator.stub(:data).and_return(args.map(&:read).join)
47
- end.and_return(creator)
48
- end
49
-
50
- subject { photographer.animation(screenshot_list) }
51
- it { should eq '<img src="data:image/gif;base64,aG9nZWZ1Z2E="/>' }
52
- end
53
- end
54
- end
55
- end
56
- end