dragonfly 1.3.0 → 1.4.1

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.
Files changed (49) hide show
  1. checksums.yaml +4 -4
  2. data/.travis.yml +1 -0
  3. data/History.md +16 -0
  4. data/README.md +5 -1
  5. data/dev/test.ru +1 -1
  6. data/dragonfly.gemspec +2 -1
  7. data/lib/dragonfly/content.rb +17 -18
  8. data/lib/dragonfly/image_magick/commands.rb +35 -0
  9. data/lib/dragonfly/image_magick/generators/plain.rb +13 -7
  10. data/lib/dragonfly/image_magick/generators/plasma.rb +10 -6
  11. data/lib/dragonfly/image_magick/generators/text.rb +67 -58
  12. data/lib/dragonfly/image_magick/plugin.rb +26 -25
  13. data/lib/dragonfly/image_magick/processors/encode.rb +16 -5
  14. data/lib/dragonfly/image_magick/processors/thumb.rb +37 -31
  15. data/lib/dragonfly/middleware.rb +2 -1
  16. data/lib/dragonfly/param_validators.rb +37 -0
  17. data/lib/dragonfly/response.rb +11 -11
  18. data/lib/dragonfly/routed_endpoint.rb +1 -1
  19. data/lib/dragonfly/server.rb +7 -7
  20. data/lib/dragonfly/version.rb +1 -1
  21. data/spec/dragonfly/app_spec.rb +1 -1
  22. data/spec/dragonfly/configurable_spec.rb +4 -4
  23. data/spec/dragonfly/content_spec.rb +1 -1
  24. data/spec/dragonfly/file_data_store_spec.rb +2 -2
  25. data/spec/dragonfly/image_magick/commands_spec.rb +98 -0
  26. data/spec/dragonfly/image_magick/generators/plain_spec.rb +39 -13
  27. data/spec/dragonfly/image_magick/generators/plasma_spec.rb +28 -9
  28. data/spec/dragonfly/image_magick/generators/text_spec.rb +51 -20
  29. data/spec/dragonfly/image_magick/plugin_spec.rb +45 -28
  30. data/spec/dragonfly/image_magick/processors/encode_spec.rb +30 -0
  31. data/spec/dragonfly/image_magick/processors/thumb_spec.rb +46 -45
  32. data/spec/dragonfly/job/fetch_url_spec.rb +1 -1
  33. data/spec/dragonfly/job_endpoint_spec.rb +26 -26
  34. data/spec/dragonfly/middleware_spec.rb +15 -6
  35. data/spec/dragonfly/model/active_record_spec.rb +2 -2
  36. data/spec/dragonfly/model/model_spec.rb +1 -1
  37. data/spec/dragonfly/param_validators_spec.rb +89 -0
  38. data/spec/dragonfly/server_spec.rb +4 -4
  39. data/spec/dragonfly/temp_object_spec.rb +5 -5
  40. data/spec/functional/shell_commands_spec.rb +6 -9
  41. data/spec/functional/to_response_spec.rb +2 -2
  42. data/spec/functional/urls_spec.rb +1 -1
  43. data/spec/spec_helper.rb +18 -14
  44. data/spec/support/image_matchers.rb +1 -1
  45. metadata +27 -12
  46. data/lib/dragonfly/image_magick/generators/convert.rb +0 -19
  47. data/lib/dragonfly/image_magick/processors/convert.rb +0 -33
  48. data/spec/dragonfly/image_magick/generators/convert_spec.rb +0 -19
  49. data/spec/dragonfly/image_magick/processors/convert_spec.rb +0 -88
@@ -1,32 +1,40 @@
1
+ require "dragonfly/image_magick/commands"
2
+
1
3
  module Dragonfly
2
4
  module ImageMagick
3
5
  module Processors
4
6
  class Thumb
7
+ include ParamValidators
5
8
 
6
9
  GRAVITIES = {
7
- 'nw' => 'NorthWest',
8
- 'n' => 'North',
9
- 'ne' => 'NorthEast',
10
- 'w' => 'West',
11
- 'c' => 'Center',
12
- 'e' => 'East',
13
- 'sw' => 'SouthWest',
14
- 's' => 'South',
15
- 'se' => 'SouthEast'
10
+ "nw" => "NorthWest",
11
+ "n" => "North",
12
+ "ne" => "NorthEast",
13
+ "w" => "West",
14
+ "c" => "Center",
15
+ "e" => "East",
16
+ "sw" => "SouthWest",
17
+ "s" => "South",
18
+ "se" => "SouthEast",
16
19
  }
17
20
 
18
21
  # Geometry string patterns
19
- RESIZE_GEOMETRY = /\A\d*x\d*[><%^!]?\z|\A\d+@\z/ # e.g. '300x200!'
22
+ RESIZE_GEOMETRY = /\A\d*x\d*[><%^!]?\z|\A\d+@\z/ # e.g. '300x200!'
20
23
  CROPPED_RESIZE_GEOMETRY = /\A(\d+)x(\d+)#(\w{1,2})?\z/ # e.g. '20x50#ne'
21
- CROP_GEOMETRY = /\A(\d+)x(\d+)([+-]\d+)?([+-]\d+)?(\w{1,2})?\z/ # e.g. '30x30+10+10'
24
+ CROP_GEOMETRY = /\A(\d+)x(\d+)([+-]\d+)?([+-]\d+)?(\w{1,2})?\z/ # e.g. '30x30+10+10'
22
25
 
23
- def update_url(url_attributes, geometry, opts={})
24
- format = opts['format']
26
+ def update_url(url_attributes, geometry, opts = {})
27
+ format = opts["format"]
25
28
  url_attributes.ext = format if format
26
29
  end
27
30
 
28
- def call(content, geometry, opts={})
29
- content.process!(:convert, args_for_geometry(geometry), opts)
31
+ def call(content, geometry, opts = {})
32
+ validate!(opts["format"], &is_word)
33
+ validate!(opts["frame"], &is_number)
34
+ Commands.convert(content, args_for_geometry(geometry), {
35
+ "format" => opts["format"],
36
+ "frame" => opts["frame"],
37
+ })
30
38
  end
31
39
 
32
40
  def args_for_geometry(geometry)
@@ -37,11 +45,11 @@ module Dragonfly
37
45
  resize_and_crop_args($1, $2, $3)
38
46
  when CROP_GEOMETRY
39
47
  crop_args(
40
- 'width' => $1,
41
- 'height' => $2,
42
- 'x' => $3,
43
- 'y' => $4,
44
- 'gravity' => $5
48
+ "width" => $1,
49
+ "height" => $2,
50
+ "x" => $3,
51
+ "y" => $4,
52
+ "gravity" => $5,
45
53
  )
46
54
  else raise ArgumentError, "Didn't recognise the geometry string #{geometry}"
47
55
  end
@@ -54,26 +62,24 @@ module Dragonfly
54
62
  end
55
63
 
56
64
  def crop_args(opts)
57
- raise ArgumentError, "you can't give a crop offset and gravity at the same time" if opts['x'] && opts['gravity']
65
+ raise ArgumentError, "you can't give a crop offset and gravity at the same time" if opts["x"] && opts["gravity"]
58
66
 
59
- width = opts['width']
60
- height = opts['height']
61
- gravity = GRAVITIES[opts['gravity']]
62
- x = "#{opts['x'] || 0}"
63
- x = '+' + x unless x[/\A[+-]/]
64
- y = "#{opts['y'] || 0}"
65
- y = '+' + y unless y[/\A[+-]/]
67
+ width = opts["width"]
68
+ height = opts["height"]
69
+ gravity = GRAVITIES[opts["gravity"]]
70
+ x = "#{opts["x"] || 0}"
71
+ x = "+" + x unless x[/\A[+-]/]
72
+ y = "#{opts["y"] || 0}"
73
+ y = "+" + y unless y[/\A[+-]/]
66
74
 
67
75
  "#{"-gravity #{gravity} " if gravity}-crop #{width}x#{height}#{x}#{y} +repage"
68
76
  end
69
77
 
70
78
  def resize_and_crop_args(width, height, gravity)
71
- gravity = GRAVITIES[gravity || 'c']
79
+ gravity = GRAVITIES[gravity || "c"]
72
80
  "-resize #{width}x#{height}^^ -gravity #{gravity} -crop #{width}x#{height}+0+0 +repage"
73
81
  end
74
-
75
82
  end
76
83
  end
77
84
  end
78
85
  end
79
-
@@ -10,7 +10,8 @@ module Dragonfly
10
10
 
11
11
  def call(env)
12
12
  response = Dragonfly.app(@dragonfly_app_name).call(env)
13
- if response[1]['X-Cascade'] == 'pass'
13
+ headers = response[1].transform_keys(&:downcase)
14
+ if headers['x-cascade'] == 'pass'
14
15
  @app.call(env)
15
16
  else
16
17
  response
@@ -0,0 +1,37 @@
1
+ module Dragonfly
2
+ module ParamValidators
3
+ class InvalidParameter < RuntimeError; end
4
+
5
+ module_function
6
+
7
+ IS_NUMBER = ->(param) {
8
+ param.is_a?(Numeric) || /\A[\d\.]+\z/ === param
9
+ }
10
+
11
+ IS_WORD = ->(param) {
12
+ /\A\w+\z/ === param
13
+ }
14
+
15
+ IS_WORDS = ->(param) {
16
+ /\A[\w ]+\z/ === param
17
+ }
18
+
19
+ def is_number; IS_NUMBER; end
20
+ def is_word; IS_WORD; end
21
+ def is_words; IS_WORDS; end
22
+
23
+ def validate!(parameter, &validator)
24
+ return if parameter.nil?
25
+ raise InvalidParameter unless validator.(parameter)
26
+ end
27
+
28
+ def validate_all!(parameters, &validator)
29
+ parameters.each { |p| validate!(p, &validator) }
30
+ end
31
+
32
+ def validate_all_keys!(obj, keys, &validator)
33
+ parameters = keys.map { |key| obj[key] }
34
+ validate_all!(parameters, &validator)
35
+ end
36
+ end
37
+ end
@@ -1,4 +1,4 @@
1
- require 'uri'
1
+ require 'cgi'
2
2
  require 'rack'
3
3
 
4
4
  module Dragonfly
@@ -26,10 +26,10 @@ module Dragonfly
26
26
  end
27
27
  rescue Job::Fetch::NotFound => e
28
28
  Dragonfly.warn(e.message)
29
- [404, {"Content-Type" => "text/plain"}, ["Not found"]]
29
+ [404, {"content-type" => "text/plain"}, ["Not found"]]
30
30
  rescue RuntimeError => e
31
31
  Dragonfly.warn("caught error - #{e.message}")
32
- [500, {"Content-Type" => "text/plain"}, ["Internal Server Error"]]
32
+ [500, {"content-type" => "text/plain"}, ["Internal Server Error"]]
33
33
  end
34
34
  log_response(response)
35
35
  response
@@ -65,8 +65,8 @@ module Dragonfly
65
65
 
66
66
  def method_not_allowed_headers
67
67
  {
68
- 'Content-Type' => 'text/plain',
69
- 'Allow' => 'GET, HEAD'
68
+ 'content-type' => 'text/plain',
69
+ 'allow' => 'GET, HEAD'
70
70
  }
71
71
  end
72
72
 
@@ -78,16 +78,16 @@ module Dragonfly
78
78
 
79
79
  def standard_headers
80
80
  {
81
- "Content-Type" => job.mime_type,
82
- "Content-Length" => job.size.to_s,
83
- "Content-Disposition" => filename_string
81
+ "content-type" => job.mime_type,
82
+ "content-length" => job.size.to_s,
83
+ "content-disposition" => filename_string
84
84
  }
85
85
  end
86
86
 
87
87
  def cache_headers
88
88
  {
89
- "Cache-Control" => "public, max-age=31536000", # (1 year)
90
- "ETag" => %("#{job.signature}")
89
+ "cache-control" => "public, max-age=31536000", # (1 year)
90
+ "etag" => %("#{job.signature}")
91
91
  }
92
92
  end
93
93
 
@@ -99,7 +99,7 @@ module Dragonfly
99
99
 
100
100
  def filename_string
101
101
  return unless job.name
102
- filename = request_from_msie? ? URI.encode(job.name) : job.name
102
+ filename = request_from_msie? ? CGI.escape(job.name) : job.name
103
103
  %(filename="#{filename}")
104
104
  end
105
105
 
@@ -45,7 +45,7 @@ module Dragonfly
45
45
  end
46
46
 
47
47
  def plain_response(status, message)
48
- [status, {"Content-Type" => "text/plain"}, [message]]
48
+ [status, {"content-type" => "text/plain"}, [message]]
49
49
  end
50
50
  end
51
51
  end
@@ -59,18 +59,18 @@ module Dragonfly
59
59
  response.to_response
60
60
  end
61
61
  else
62
- [404, {'Content-Type' => 'text/plain', 'X-Cascade' => 'pass'}, ['Not found']]
62
+ [404, {'content-type' => 'text/plain', 'x-cascade' => 'pass'}, ['Not found']]
63
63
  end
64
64
  rescue Job::NoSHAGiven => e
65
- [400, {"Content-Type" => 'text/plain'}, ["You need to give a SHA parameter"]]
65
+ [400, {"content-type" => 'text/plain'}, ["You need to give a SHA parameter"]]
66
66
  rescue Job::IncorrectSHA => e
67
- [400, {"Content-Type" => 'text/plain'}, ["The SHA parameter you gave is incorrect"]]
67
+ [400, {"content-type" => 'text/plain'}, ["The SHA parameter you gave is incorrect"]]
68
68
  rescue JobNotAllowed => e
69
69
  Dragonfly.warn(e.message)
70
- [403, {"Content-Type" => 'text/plain'}, ["Forbidden"]]
70
+ [403, {"content-type" => 'text/plain'}, ["Forbidden"]]
71
71
  rescue Serializer::BadString, Serializer::MaliciousString, Job::InvalidArray => e
72
72
  Dragonfly.warn(e.message)
73
- [404, {'Content-Type' => 'text/plain'}, ['Not found']]
73
+ [404, {'content-type' => 'text/plain'}, ['Not found']]
74
74
  end
75
75
 
76
76
  def url_for(job, opts={})
@@ -111,8 +111,8 @@ module Dragonfly
111
111
  V
112
112
  DRAGONFLY
113
113
  [200, {
114
- 'Content-Type' => 'text/plain',
115
- 'Content-Size' => body.bytesize.to_s
114
+ 'content-type' => 'text/plain',
115
+ 'content-size' => body.bytesize.to_s
116
116
  },
117
117
  [body]
118
118
  ]
@@ -1,3 +1,3 @@
1
1
  module Dragonfly
2
- VERSION = "1.3.0"
2
+ VERSION = "1.4.1"
3
3
  end
@@ -138,7 +138,7 @@ describe Dragonfly::App do
138
138
  }.should raise_error(NotImplementedError)
139
139
  end
140
140
  it "should correctly call it if the datastore provides it" do
141
- @app.datastore.should_receive(:url_for).with('some_uid', :some => :opts).and_return 'http://egg.head'
141
+ @app.datastore.should_receive(:url_for).with('some_uid', {:some => :opts}).and_return 'http://egg.head'
142
142
  @app.remote_url_for('some_uid', :some => :opts).should == 'http://egg.head'
143
143
  end
144
144
  end
@@ -65,7 +65,7 @@ describe Dragonfly::Configurable do
65
65
  configurer = Dragonfly::Configurable::Configurer.new do
66
66
  meth :jobby, :nobby
67
67
  end
68
- obj.should_receive(:jobby).with('beans', :make => 5)
68
+ obj.should_receive(:jobby).with('beans', {:make => 5})
69
69
  obj.should_receive(:nobby).with(['nuts'])
70
70
  configurer.configure(obj) do
71
71
  jobby 'beans', :make => 5
@@ -79,7 +79,7 @@ describe Dragonfly::Configurable do
79
79
  end
80
80
  egg = double('egg')
81
81
  obj.should_receive(:egg).and_return(egg)
82
- egg.should_receive(:jobby).with('beans', :make => 5)
82
+ egg.should_receive(:jobby).with('beans', {:make => 5})
83
83
  configurer.configure(obj) do
84
84
  jobby 'beans', :make => 5
85
85
  end
@@ -93,7 +93,7 @@ describe Dragonfly::Configurable do
93
93
 
94
94
  it "provides 'plugin' for using plugins" do
95
95
  pluggy = double('plugin')
96
- pluggy.should_receive(:call).with(obj, :a, 'few' => ['args'])
96
+ pluggy.should_receive(:call).with(obj, :a, {'few' => ['args']})
97
97
  configurer.configure(obj) do
98
98
  plugin pluggy, :a, 'few' => ['args']
99
99
  end
@@ -101,7 +101,7 @@ describe Dragonfly::Configurable do
101
101
 
102
102
  it "allows using 'plugin' with symbols" do
103
103
  pluggy = double('plugin')
104
- pluggy.should_receive(:call).with(obj, :a, 'few' => ['args'])
104
+ pluggy.should_receive(:call).with(obj, :a, {'few' => ['args']})
105
105
  configurer.register_plugin(:pluggy){ pluggy }
106
106
  configurer.configure(obj) do
107
107
  plugin :pluggy, :a, 'few' => ['args']
@@ -320,7 +320,7 @@ describe Dragonfly::Content do
320
320
  end
321
321
 
322
322
  it "allows passing options" do
323
- app.datastore.should_receive(:write).with(content, :hello => 'there')
323
+ app.datastore.should_receive(:write).with(content, {:hello => 'there'})
324
324
  content.store(:hello => 'there')
325
325
  end
326
326
  end
@@ -9,11 +9,11 @@ describe Dragonfly::FileDataStore do
9
9
  end
10
10
 
11
11
  def assert_exists(path)
12
- File.exists?(path).should be_truthy
12
+ File.exist?(path).should be_truthy
13
13
  end
14
14
 
15
15
  def assert_does_not_exist(path)
16
- File.exists?(path).should be_falsey
16
+ File.exist?(path).should be_falsey
17
17
  end
18
18
 
19
19
  def assert_contains(dir, filepattern)
@@ -0,0 +1,98 @@
1
+ require "spec_helper"
2
+ require "dragonfly/image_magick/commands"
3
+
4
+ describe Dragonfly::ImageMagick::Commands do
5
+ include Dragonfly::ImageMagick::Commands
6
+
7
+ let(:app) { test_app }
8
+
9
+ def sample_content(name)
10
+ Dragonfly::Content.new(app, SAMPLES_DIR.join(name))
11
+ end
12
+
13
+ describe "convert" do
14
+ let(:image) { sample_content("beach.png") } # 280x355
15
+
16
+ it "should allow for general convert commands" do
17
+ convert(image, "-scale 56x71")
18
+ image.should have_width(56)
19
+ image.should have_height(71)
20
+ end
21
+
22
+ it "should allow for general convert commands with added format" do
23
+ convert(image, "-scale 56x71", "format" => "gif")
24
+ image.should have_width(56)
25
+ image.should have_height(71)
26
+ image.should have_format("gif")
27
+ image.meta["format"].should == "gif"
28
+ end
29
+
30
+ it "should work for commands with parenthesis" do
31
+ convert(image, "\\( +clone -sparse-color Barycentric '0,0 black 0,%[fx:h-1] white' -function polynomial 2,-2,0.5 \\) -compose Blur -set option:compose:args 15 -composite")
32
+ image.should have_width(280)
33
+ end
34
+
35
+ it "should work for files with spaces/apostrophes in the name" do
36
+ image = Dragonfly::Content.new(app, SAMPLES_DIR.join("mevs' white pixel.png"))
37
+ convert(image, "-resize 2x2!")
38
+ image.should have_width(2)
39
+ end
40
+
41
+ it "allows converting specific frames" do
42
+ gif = sample_content("gif.gif")
43
+ convert(gif, "-resize 50x50")
44
+ all_frames_size = gif.size
45
+
46
+ gif = sample_content("gif.gif")
47
+ convert(gif, "-resize 50x50", "frame" => 0)
48
+ one_frame_size = gif.size
49
+
50
+ one_frame_size.should < all_frames_size
51
+ end
52
+
53
+ it "accepts input arguments for convert commands" do
54
+ image2 = image.clone
55
+ convert(image, "")
56
+ convert(image2, "", "input_args" => "-extract 50x50+10+10")
57
+
58
+ image.should_not equal_image(image2)
59
+ image2.should have_width(50)
60
+ end
61
+
62
+ it "allows converting using specific delegates" do
63
+ expect {
64
+ convert(image, "", "format" => "jpg", "delegate" => "png")
65
+ }.to call_command(app.shell, %r{convert png:/[^']+?/beach\.png /[^']+?\.jpg})
66
+ end
67
+
68
+ it "maintains the mime_type meta if it exists already" do
69
+ convert(image, "-resize 10x")
70
+ image.meta["mime_type"].should be_nil
71
+
72
+ image.add_meta("mime_type" => "image/png")
73
+ convert(image, "-resize 5x")
74
+ image.meta["mime_type"].should == "image/png"
75
+ image.mime_type.should == "image/png" # sanity check
76
+ end
77
+
78
+ it "doesn't maintain the mime_type meta on format change" do
79
+ image.add_meta("mime_type" => "image/png")
80
+ convert(image, "", "format" => "gif")
81
+ image.meta["mime_type"].should be_nil
82
+ image.mime_type.should == "image/gif" # sanity check
83
+ end
84
+ end
85
+
86
+ describe "generate" do
87
+ let (:image) { Dragonfly::Content.new(app) }
88
+
89
+ before(:each) do
90
+ generate(image, "-size 1x1 xc:white", "png")
91
+ end
92
+
93
+ it { image.should have_width(1) }
94
+ it { image.should have_height(1) }
95
+ it { image.should have_format("png") }
96
+ it { image.meta.should == { "format" => "png" } }
97
+ end
98
+ end
@@ -1,4 +1,5 @@
1
- require 'spec_helper'
1
+ require "spec_helper"
2
+ require "dragonfly/param_validators"
2
3
 
3
4
  describe Dragonfly::ImageMagick::Generators::Plain do
4
5
  let (:generator) { Dragonfly::ImageMagick::Generators::Plain.new }
@@ -9,32 +10,32 @@ describe Dragonfly::ImageMagick::Generators::Plain do
9
10
  before(:each) do
10
11
  generator.call(image, 3, 2)
11
12
  end
12
- it {image.should have_width(3)}
13
- it {image.should have_height(2)}
14
- it {image.should have_format('png')}
15
- it {image.meta.should == {'format' => 'png', 'name' => 'plain.png'}}
13
+ it { image.should have_width(3) }
14
+ it { image.should have_height(2) }
15
+ it { image.should have_format("png") }
16
+ it { image.meta.should == { "format" => "png", "name" => "plain.png" } }
16
17
  end
17
18
 
18
19
  describe "specifying the format" do
19
20
  before(:each) do
20
- generator.call(image, 1, 1, 'format'=> 'gif')
21
+ generator.call(image, 1, 1, "format" => "gif")
21
22
  end
22
- it {image.should have_format('gif')}
23
- it {image.meta.should == {'format' => 'gif', 'name' => 'plain.gif'}}
23
+ it { image.should have_format("gif") }
24
+ it { image.meta.should == { "format" => "gif", "name" => "plain.gif" } }
24
25
  end
25
26
 
26
27
  describe "specifying the colour" do
27
28
  it "works with English spelling" do
28
- generator.call(image, 1, 1, 'colour' => 'red')
29
+ generator.call(image, 1, 1, "colour" => "red")
29
30
  end
30
31
 
31
32
  it "works with American spelling" do
32
- generator.call(image, 1, 1, 'color' => 'red')
33
+ generator.call(image, 1, 1, "color" => "red")
33
34
  end
34
35
 
35
36
  it "blows up with a bad colour" do
36
37
  expect {
37
- generator.call(image, 1, 1, 'colour' => 'lardoin')
38
+ generator.call(image, 1, 1, "colour" => "lardoin")
38
39
  }.to raise_error(Dragonfly::Shell::CommandFailed)
39
40
  end
40
41
  end
@@ -42,9 +43,34 @@ describe Dragonfly::ImageMagick::Generators::Plain do
42
43
  describe "urls" do
43
44
  it "updates the url" do
44
45
  url_attributes = Dragonfly::UrlAttributes.new
45
- generator.update_url(url_attributes, 1, 1, 'format' => 'gif')
46
- url_attributes.name.should == 'plain.gif'
46
+ generator.update_url(url_attributes, 1, 1, "format" => "gif")
47
+ url_attributes.name.should == "plain.gif"
47
48
  end
48
49
  end
49
50
 
51
+ describe "param validations" do
52
+ {
53
+ "color" => "white -write bad.png",
54
+ "colour" => "white -write bad.png",
55
+ "format" => "png -write bad.png",
56
+ }.each do |opt, value|
57
+ it "validates bad opts like #{opt} = '#{value}'" do
58
+ expect {
59
+ generator.call(image, 1, 1, opt => value)
60
+ }.to raise_error(Dragonfly::ParamValidators::InvalidParameter)
61
+ end
62
+ end
63
+
64
+ it "validates width" do
65
+ expect {
66
+ generator.call(image, "1 -write bad.png", 1)
67
+ }.to raise_error(Dragonfly::ParamValidators::InvalidParameter)
68
+ end
69
+
70
+ it "validates height" do
71
+ expect {
72
+ generator.call(image, 1, "1 -write bad.png")
73
+ }.to raise_error(Dragonfly::ParamValidators::InvalidParameter)
74
+ end
75
+ end
50
76
  end
@@ -1,4 +1,4 @@
1
- require 'spec_helper'
1
+ require "spec_helper"
2
2
 
3
3
  describe Dragonfly::ImageMagick::Generators::Plasma do
4
4
  let (:generator) { Dragonfly::ImageMagick::Generators::Plasma.new }
@@ -10,23 +10,42 @@ describe Dragonfly::ImageMagick::Generators::Plasma do
10
10
  generator.call(image, 5, 3)
11
11
  image.should have_width(5)
12
12
  image.should have_height(3)
13
- image.should have_format('png')
14
- image.meta.should == {'format' => 'png', 'name' => 'plasma.png'}
13
+ image.should have_format("png")
14
+ image.meta.should == { "format" => "png", "name" => "plasma.png" }
15
15
  end
16
16
 
17
17
  it "allows changing the format" do
18
- generator.call(image, 1, 1, 'format' => 'jpg')
19
- image.should have_format('jpeg')
20
- image.meta.should == {'format' => 'jpg', 'name' => 'plasma.jpg'}
18
+ generator.call(image, 1, 1, "format" => "jpg")
19
+ image.should have_format("jpeg")
20
+ image.meta.should == { "format" => "jpg", "name" => "plasma.jpg" }
21
21
  end
22
22
  end
23
23
 
24
24
  describe "urls" do
25
25
  it "updates the url" do
26
26
  url_attributes = Dragonfly::UrlAttributes.new
27
- generator.update_url(url_attributes, 1, 1, 'format' => 'jpg')
28
- url_attributes.name.should == 'plasma.jpg'
27
+ generator.update_url(url_attributes, 1, 1, "format" => "jpg")
28
+ url_attributes.name.should == "plasma.jpg"
29
29
  end
30
30
  end
31
- end
32
31
 
32
+ describe "param validations" do
33
+ it "validates format" do
34
+ expect {
35
+ generator.call(image, 1, 1, "format" => "png -write bad.png")
36
+ }.to raise_error(Dragonfly::ParamValidators::InvalidParameter)
37
+ end
38
+
39
+ it "validates width" do
40
+ expect {
41
+ generator.call(image, "1 -write bad.png", 1)
42
+ }.to raise_error(Dragonfly::ParamValidators::InvalidParameter)
43
+ end
44
+
45
+ it "validates height" do
46
+ expect {
47
+ generator.call(image, 1, "1 -write bad.png")
48
+ }.to raise_error(Dragonfly::ParamValidators::InvalidParameter)
49
+ end
50
+ end
51
+ end