dragonfly 0.1.0
Sign up to get free protection for your applications and to get access to all the features.
Potentially problematic release.
This version of dragonfly might be problematic. Click here for more details.
- data/.gitignore +7 -0
- data/LICENSE +20 -0
- data/README.markdown +95 -0
- data/Rakefile +60 -0
- data/VERSION +1 -0
- data/config.rb +7 -0
- data/config.ru +10 -0
- data/dragonfly-rails.gemspec +41 -0
- data/dragonfly.gemspec +137 -0
- data/features/dragonfly.feature +38 -0
- data/features/steps/common_steps.rb +8 -0
- data/features/steps/dragonfly_steps.rb +39 -0
- data/features/support/env.rb +25 -0
- data/features/support/image_helpers.rb +9 -0
- data/generators/dragonfly_app/USAGE +16 -0
- data/generators/dragonfly_app/dragonfly_app_generator.rb +54 -0
- data/generators/dragonfly_app/templates/custom_processing.erb +13 -0
- data/generators/dragonfly_app/templates/initializer.erb +7 -0
- data/generators/dragonfly_app/templates/metal_file.erb +32 -0
- data/irbrc.rb +20 -0
- data/lib/dragonfly/active_record_extensions/attachment.rb +117 -0
- data/lib/dragonfly/active_record_extensions/class_methods.rb +41 -0
- data/lib/dragonfly/active_record_extensions/instance_methods.rb +28 -0
- data/lib/dragonfly/active_record_extensions/validations.rb +19 -0
- data/lib/dragonfly/active_record_extensions.rb +12 -0
- data/lib/dragonfly/analysis/analyser.rb +45 -0
- data/lib/dragonfly/analysis/base.rb +10 -0
- data/lib/dragonfly/analysis/r_magick_analyser.rb +40 -0
- data/lib/dragonfly/app.rb +85 -0
- data/lib/dragonfly/app_configuration.rb +9 -0
- data/lib/dragonfly/configurable.rb +113 -0
- data/lib/dragonfly/core_ext/object.rb +8 -0
- data/lib/dragonfly/data_storage/base.rb +19 -0
- data/lib/dragonfly/data_storage/file_data_store.rb +72 -0
- data/lib/dragonfly/data_storage.rb +9 -0
- data/lib/dragonfly/encoding/base.rb +13 -0
- data/lib/dragonfly/encoding/r_magick_encoder.rb +17 -0
- data/lib/dragonfly/extended_temp_object.rb +94 -0
- data/lib/dragonfly/middleware.rb +27 -0
- data/lib/dragonfly/parameters.rb +152 -0
- data/lib/dragonfly/processing/processor.rb +14 -0
- data/lib/dragonfly/processing/r_magick_processor.rb +71 -0
- data/lib/dragonfly/r_magick_configuration.rb +47 -0
- data/lib/dragonfly/rails/images.rb +20 -0
- data/lib/dragonfly/temp_object.rb +118 -0
- data/lib/dragonfly/url_handler.rb +148 -0
- data/lib/dragonfly.rb +33 -0
- data/samples/beach.png +0 -0
- data/samples/egg.png +0 -0
- data/samples/round.gif +0 -0
- data/samples/taj.jpg +0 -0
- data/spec/argument_matchers.rb +29 -0
- data/spec/dragonfly/active_record_extensions/attachment_spec.rb +8 -0
- data/spec/dragonfly/active_record_extensions/initializer.rb +1 -0
- data/spec/dragonfly/active_record_extensions/migration.rb +21 -0
- data/spec/dragonfly/active_record_extensions/model_spec.rb +400 -0
- data/spec/dragonfly/active_record_extensions/models.rb +2 -0
- data/spec/dragonfly/active_record_extensions/spec_helper.rb +23 -0
- data/spec/dragonfly/analysis/analyser_spec.rb +85 -0
- data/spec/dragonfly/analysis/r_magick_analyser_spec.rb +35 -0
- data/spec/dragonfly/app_spec.rb +69 -0
- data/spec/dragonfly/configurable_spec.rb +193 -0
- data/spec/dragonfly/data_storage/data_store_spec.rb +47 -0
- data/spec/dragonfly/data_storage/file_data_store_spec.rb +93 -0
- data/spec/dragonfly/extended_temp_object_spec.rb +67 -0
- data/spec/dragonfly/middleware_spec.rb +44 -0
- data/spec/dragonfly/parameters_spec.rb +293 -0
- data/spec/dragonfly/processing/rmagick_processor_spec.rb +148 -0
- data/spec/dragonfly/temp_object_spec.rb +233 -0
- data/spec/dragonfly/url_handler_spec.rb +246 -0
- data/spec/dragonfly_spec.rb +4 -0
- data/spec/image_matchers.rb +31 -0
- data/spec/simple_matchers.rb +14 -0
- data/spec/spec_helper.rb +19 -0
- metadata +160 -0
@@ -0,0 +1,69 @@
|
|
1
|
+
require File.dirname(__FILE__) + '/../spec_helper'
|
2
|
+
require 'rack/mock'
|
3
|
+
|
4
|
+
describe Dragonfly::App do
|
5
|
+
|
6
|
+
def make_request(app, url)
|
7
|
+
Rack::MockRequest.new(app).get(url)
|
8
|
+
end
|
9
|
+
|
10
|
+
describe ".instance" do
|
11
|
+
|
12
|
+
it "should create a new instance if it didn't already exist" do
|
13
|
+
app = Dragonfly::App.instance(:images)
|
14
|
+
app.should be_a(Dragonfly::App)
|
15
|
+
end
|
16
|
+
|
17
|
+
it "should return an existing instance if called by name" do
|
18
|
+
app = Dragonfly::App.instance(:images)
|
19
|
+
Dragonfly::App.instance(:images).should == app
|
20
|
+
end
|
21
|
+
|
22
|
+
it "should also work using square brackets" do
|
23
|
+
Dragonfly::App[:images].should == Dragonfly::App.instance(:images)
|
24
|
+
end
|
25
|
+
|
26
|
+
end
|
27
|
+
|
28
|
+
describe ".new" do
|
29
|
+
it "should not be callable" do
|
30
|
+
lambda{
|
31
|
+
Dragonfly::App.new
|
32
|
+
}.should raise_error(NoMethodError)
|
33
|
+
end
|
34
|
+
end
|
35
|
+
|
36
|
+
describe "errors" do
|
37
|
+
|
38
|
+
before(:each) do
|
39
|
+
@app = Dragonfly::App[:images]
|
40
|
+
end
|
41
|
+
|
42
|
+
it "should return 400 if UrlHandler::IncorrectSHA is raised" do
|
43
|
+
@app.url_handler.should_receive(:url_to_parameters).and_raise(Dragonfly::UrlHandler::IncorrectSHA)
|
44
|
+
response = make_request(@app, '/some_uid.png?s=sadfas')
|
45
|
+
response.status.should == 400
|
46
|
+
end
|
47
|
+
|
48
|
+
it "should return 400 if UrlHandler::SHANotGiven is raised" do
|
49
|
+
@app.url_handler.should_receive(:url_to_parameters).and_raise(Dragonfly::UrlHandler::SHANotGiven)
|
50
|
+
response = make_request(@app, '/some_uid.png?s=asdfghsg')
|
51
|
+
response.status.should == 400
|
52
|
+
end
|
53
|
+
|
54
|
+
it "should return 404 if url handler raises an unknown url exception" do
|
55
|
+
@app.url_handler.should_receive(:url_to_parameters).and_raise(Dragonfly::UrlHandler::UnknownUrl)
|
56
|
+
response = make_request(@app, '/')
|
57
|
+
response.status.should == 404
|
58
|
+
end
|
59
|
+
|
60
|
+
it "should return 404 if the datastore raises data not found" do
|
61
|
+
@app.url_handler.protect_from_dos_attacks = false
|
62
|
+
@app.should_receive(:fetch).and_raise(Dragonfly::DataStorage::DataNotFound)
|
63
|
+
response = make_request(@app, 'hello.png')
|
64
|
+
response.status.should == 404
|
65
|
+
end
|
66
|
+
|
67
|
+
end
|
68
|
+
|
69
|
+
end
|
@@ -0,0 +1,193 @@
|
|
1
|
+
require File.dirname(__FILE__) + '/../spec_helper'
|
2
|
+
|
3
|
+
describe Dragonfly::Configurable do
|
4
|
+
|
5
|
+
before(:each) do
|
6
|
+
class Car
|
7
|
+
include Dragonfly::Configurable
|
8
|
+
configurable_attr :colour
|
9
|
+
configurable_attr :top_speed, 216
|
10
|
+
def self.other_thing=(thing); end
|
11
|
+
end
|
12
|
+
@car = Car.new
|
13
|
+
end
|
14
|
+
|
15
|
+
describe "setup" do
|
16
|
+
it "should provide attr_readers for configurable attributes" do
|
17
|
+
@car.should respond_to(:colour)
|
18
|
+
end
|
19
|
+
|
20
|
+
it "should provide attr_writers for configurable attributes" do
|
21
|
+
@car.colour = 'verde'
|
22
|
+
@car.colour.should == 'verde'
|
23
|
+
end
|
24
|
+
|
25
|
+
it "should set default values for configurable attributes" do
|
26
|
+
@car.top_speed.should == 216
|
27
|
+
end
|
28
|
+
|
29
|
+
it "should set the default as nil if not specified" do
|
30
|
+
@car.colour.should be_nil
|
31
|
+
end
|
32
|
+
|
33
|
+
it "should allow specifying configurable attrs as strings" do
|
34
|
+
class Bike
|
35
|
+
include Dragonfly::Configurable
|
36
|
+
configurable_attr 'colour', 'rude'
|
37
|
+
end
|
38
|
+
Bike.new.colour.should == 'rude'
|
39
|
+
end
|
40
|
+
end
|
41
|
+
|
42
|
+
describe "configuring" do
|
43
|
+
it "should allow you to change values" do
|
44
|
+
@car.configure do |c|
|
45
|
+
c.colour = 'red'
|
46
|
+
end
|
47
|
+
@car.colour.should == 'red'
|
48
|
+
end
|
49
|
+
|
50
|
+
it "should not allow you to call other methods on the object via the configuration" do
|
51
|
+
lambda{
|
52
|
+
@car.configure do |c|
|
53
|
+
c.other_thing = 5
|
54
|
+
end
|
55
|
+
}.should raise_error(Dragonfly::Configurable::BadConfigAttribute)
|
56
|
+
end
|
57
|
+
end
|
58
|
+
|
59
|
+
describe "getting configuration" do
|
60
|
+
it "should return the configuration as a hash" do
|
61
|
+
@car.configuration.should == {:colour => nil, :top_speed => 216}
|
62
|
+
end
|
63
|
+
it "should not allow you to change the configuration via the hash" do
|
64
|
+
@car.configuration[:top_speed] = 555
|
65
|
+
@car.top_speed.should == 216
|
66
|
+
end
|
67
|
+
end
|
68
|
+
|
69
|
+
describe "multiple objects" do
|
70
|
+
it "should return the default configuration" do
|
71
|
+
Car.default_configuration.should == {:colour => nil, :top_speed => 216}
|
72
|
+
end
|
73
|
+
it "should allow instances to be configured differently" do
|
74
|
+
car1 = Car.new
|
75
|
+
car1.configure{|c| c.colour = 'green'}
|
76
|
+
car2 = Car.new
|
77
|
+
car2.configure{|c| c.colour = 'yellow'}
|
78
|
+
car1.configuration.should == {:colour => 'green', :top_speed => 216}
|
79
|
+
car2.configuration.should == {:colour => 'yellow', :top_speed => 216}
|
80
|
+
end
|
81
|
+
end
|
82
|
+
|
83
|
+
describe "lazy attributes" do
|
84
|
+
before(:each) do
|
85
|
+
cow = @cow = mock('cow')
|
86
|
+
class Lazy; end
|
87
|
+
Lazy.class_eval do
|
88
|
+
include Dragonfly::Configurable
|
89
|
+
configurable_attr(:sound){ cow.moo }
|
90
|
+
end
|
91
|
+
@lazy = Lazy.new
|
92
|
+
end
|
93
|
+
it "should not call the block if the configurable attribute is set to something else" do
|
94
|
+
@cow.should_not_receive(:moo)
|
95
|
+
@lazy.configure{|c| c.sound = 'baa' }
|
96
|
+
@lazy.sound.should == 'baa'
|
97
|
+
end
|
98
|
+
it "should call the block if it's not been changed, once it's accessed" do
|
99
|
+
@cow.should_receive(:moo).and_return('mooo!')
|
100
|
+
@lazy.sound.should == 'mooo!'
|
101
|
+
end
|
102
|
+
it "should not call the block when accessed again" do
|
103
|
+
@cow.should_receive(:moo).exactly(:once).and_return('mooo!')
|
104
|
+
@lazy.sound.should == 'mooo!'
|
105
|
+
@lazy.sound.should == 'mooo!'
|
106
|
+
end
|
107
|
+
it "should also call a block which has been set as part of the configuration" do
|
108
|
+
@cow.should_receive(:fart).exactly(:once).and_return('paaarrp!')
|
109
|
+
@lazy.configure{|c| c.sound = lambda{ @cow.fart }}
|
110
|
+
@lazy.sound.should == 'paaarrp!'
|
111
|
+
@lazy.sound.should == 'paaarrp!'
|
112
|
+
end
|
113
|
+
end
|
114
|
+
|
115
|
+
describe "using in the singleton class" do
|
116
|
+
it "should work" do
|
117
|
+
class OneOff
|
118
|
+
class << self
|
119
|
+
include Dragonfly::Configurable
|
120
|
+
configurable_attr :food, 'bread'
|
121
|
+
end
|
122
|
+
end
|
123
|
+
OneOff.food.should == 'bread'
|
124
|
+
end
|
125
|
+
end
|
126
|
+
|
127
|
+
describe "configuration method" do
|
128
|
+
|
129
|
+
before(:each) do
|
130
|
+
class ClassWithMethod
|
131
|
+
include Dragonfly::Configurable
|
132
|
+
def add_thing(thing)
|
133
|
+
'poo'
|
134
|
+
end
|
135
|
+
def remove_thing(thing)
|
136
|
+
'bum'
|
137
|
+
end
|
138
|
+
configuration_method :add_thing, :remove_thing
|
139
|
+
end
|
140
|
+
@thing = ClassWithMethod.new
|
141
|
+
end
|
142
|
+
|
143
|
+
it "should allow calling the method through 'configure'" do
|
144
|
+
@thing.configure do |c|
|
145
|
+
c.add_thing('duck')
|
146
|
+
c.remove_thing('dog')
|
147
|
+
end
|
148
|
+
end
|
149
|
+
|
150
|
+
end
|
151
|
+
|
152
|
+
describe "nested configurable objects" do
|
153
|
+
|
154
|
+
it "should allow configuring nested configurable objects" do
|
155
|
+
|
156
|
+
class NestedThing
|
157
|
+
include Dragonfly::Configurable
|
158
|
+
configurable_attr :age, 29
|
159
|
+
end
|
160
|
+
|
161
|
+
class Car
|
162
|
+
def nested_thing
|
163
|
+
@nested_thing ||= NestedThing.new
|
164
|
+
end
|
165
|
+
end
|
166
|
+
|
167
|
+
@car.configure do |c|
|
168
|
+
c.nested_thing do |nt|
|
169
|
+
nt.age = 50
|
170
|
+
end
|
171
|
+
end
|
172
|
+
|
173
|
+
@car.nested_thing.age.should == 50
|
174
|
+
|
175
|
+
end
|
176
|
+
|
177
|
+
end
|
178
|
+
|
179
|
+
describe "configuring with a configurer" do
|
180
|
+
it "should allow configuration by a configurer" do
|
181
|
+
cool_configuration = Object.new
|
182
|
+
def cool_configuration.apply_configuration(car)
|
183
|
+
car.configure do |c|
|
184
|
+
c.colour = 'vermelho'
|
185
|
+
end
|
186
|
+
end
|
187
|
+
@car.configure_with(cool_configuration)
|
188
|
+
@car.colour.should == 'vermelho'
|
189
|
+
@car.top_speed.should == 216
|
190
|
+
end
|
191
|
+
end
|
192
|
+
|
193
|
+
end
|
@@ -0,0 +1,47 @@
|
|
1
|
+
require File.dirname(__FILE__) + '/../../spec_helper'
|
2
|
+
|
3
|
+
describe "data_store", :shared => true do
|
4
|
+
|
5
|
+
# Using these shared spec requires you to set the inst var @data_store
|
6
|
+
|
7
|
+
before(:each) do
|
8
|
+
@temp_object = Dragonfly::TempObject.new('gollum')
|
9
|
+
end
|
10
|
+
|
11
|
+
describe "store" do
|
12
|
+
it "should return a unique identifier for each storage" do
|
13
|
+
@data_store.store(@temp_object).should_not == @data_store.store(@temp_object)
|
14
|
+
end
|
15
|
+
end
|
16
|
+
|
17
|
+
describe "retrieve" do
|
18
|
+
it "should retrieve the stored data" do
|
19
|
+
uid = @data_store.store(@temp_object)
|
20
|
+
Dragonfly::TempObject.new(@data_store.retrieve(uid)).data.should == @temp_object.data
|
21
|
+
end
|
22
|
+
|
23
|
+
it "should raise an exception if the data doesn't exist" do
|
24
|
+
lambda{
|
25
|
+
@data_store.retrieve('gooble/gubbub')
|
26
|
+
}.should raise_error(Dragonfly::DataStorage::DataNotFound)
|
27
|
+
end
|
28
|
+
end
|
29
|
+
|
30
|
+
describe "destroy" do
|
31
|
+
|
32
|
+
it "should destroy the stored data" do
|
33
|
+
uid = @data_store.store(@temp_object)
|
34
|
+
@data_store.destroy(uid)
|
35
|
+
lambda{
|
36
|
+
@data_store.retrieve(uid)
|
37
|
+
}.should raise_error(Dragonfly::DataStorage::DataNotFound)
|
38
|
+
end
|
39
|
+
|
40
|
+
it "should raise an error if the data doesn't exist" do
|
41
|
+
lambda{
|
42
|
+
@data_store.destroy('gooble/gubbub')
|
43
|
+
}.should raise_error(Dragonfly::DataStorage::DataNotFound)
|
44
|
+
end
|
45
|
+
end
|
46
|
+
|
47
|
+
end
|
@@ -0,0 +1,93 @@
|
|
1
|
+
require File.dirname(__FILE__) + '/../../spec_helper'
|
2
|
+
require File.dirname(__FILE__) + '/data_store_spec'
|
3
|
+
|
4
|
+
describe Dragonfly::DataStorage::FileDataStore do
|
5
|
+
|
6
|
+
before(:each) do
|
7
|
+
@data_store = Dragonfly::DataStorage::FileDataStore.new
|
8
|
+
@data_store.root_path = '/var/tmp/dragonfly_test'
|
9
|
+
|
10
|
+
# Set 'now' to a date in the past
|
11
|
+
Time.stub!(:now).and_return Time.mktime(1984,"may",4,14,28,1)
|
12
|
+
@file_pattern_prefix_without_root = '1984/05/04/142801'
|
13
|
+
@file_pattern_prefix = "#{@data_store.root_path}/#{@file_pattern_prefix_without_root}"
|
14
|
+
end
|
15
|
+
|
16
|
+
after(:each) do
|
17
|
+
# Clean up created files
|
18
|
+
FileUtils.rm_rf("#{@data_store.root_path}/1984")
|
19
|
+
end
|
20
|
+
|
21
|
+
it_should_behave_like 'data_store'
|
22
|
+
|
23
|
+
describe "store" do
|
24
|
+
|
25
|
+
before(:each) do
|
26
|
+
@temp_object = Dragonfly::TempObject.new('goobydoo')
|
27
|
+
end
|
28
|
+
|
29
|
+
def it_should_write_to_file(storage_path, temp_object)
|
30
|
+
FileUtils.should_receive(:cp).with(temp_object.path, storage_path)
|
31
|
+
end
|
32
|
+
|
33
|
+
it "should store the file in a folder based on date, with default filename" do
|
34
|
+
it_should_write_to_file("#{@file_pattern_prefix}_file", @temp_object)
|
35
|
+
@data_store.store(@temp_object)
|
36
|
+
end
|
37
|
+
|
38
|
+
it "should store the file with a numbered suffix if the filename already exists" do
|
39
|
+
FileUtils.mkdir_p(@file_pattern_prefix)
|
40
|
+
FileUtils.touch("#{@file_pattern_prefix}_file")
|
41
|
+
it_should_write_to_file("#{@file_pattern_prefix}_file_2", @temp_object)
|
42
|
+
@data_store.store(@temp_object)
|
43
|
+
end
|
44
|
+
|
45
|
+
it "should store the file with an incremented number suffix if the filename already exists" do
|
46
|
+
FileUtils.mkdir_p(@file_pattern_prefix)
|
47
|
+
FileUtils.touch("#{@file_pattern_prefix}_file")
|
48
|
+
FileUtils.touch("#{@file_pattern_prefix}_file_2")
|
49
|
+
it_should_write_to_file("#{@file_pattern_prefix}_file_3", @temp_object)
|
50
|
+
@data_store.store(@temp_object)
|
51
|
+
end
|
52
|
+
|
53
|
+
it "should use the temp_object name if it exists" do
|
54
|
+
@temp_object.name = 'hello'
|
55
|
+
it_should_write_to_file("#{@file_pattern_prefix}_hello", @temp_object)
|
56
|
+
@data_store.store(@temp_object)
|
57
|
+
end
|
58
|
+
|
59
|
+
it "should use the basename (all but part after last dot) of the temp_object name if it exists" do
|
60
|
+
@temp_object.name = 'hello.you.png'
|
61
|
+
it_should_write_to_file("#{@file_pattern_prefix}_hello.you", @temp_object)
|
62
|
+
@data_store.store(@temp_object)
|
63
|
+
end
|
64
|
+
|
65
|
+
it "should use the default file suffix if the temp_object name is blank" do
|
66
|
+
@temp_object.name = ''
|
67
|
+
it_should_write_to_file("#{@file_pattern_prefix}_file", @temp_object)
|
68
|
+
@data_store.store(@temp_object)
|
69
|
+
end
|
70
|
+
|
71
|
+
it "should return the filepath without the root of the stored file" do
|
72
|
+
@data_store.store(@temp_object).should == "#{@file_pattern_prefix_without_root}_file"
|
73
|
+
end
|
74
|
+
|
75
|
+
it "should raise an error if it can't create a directory" do
|
76
|
+
FileUtils.should_receive(:mkdir_p).and_raise(Errno::EACCES)
|
77
|
+
lambda{ @data_store.store(@temp_object) }.should raise_error(Dragonfly::DataStorage::UnableToStore)
|
78
|
+
end
|
79
|
+
|
80
|
+
it "should raise an error if it can't create a file" do
|
81
|
+
FileUtils.should_receive(:cp).and_raise(Errno::EACCES)
|
82
|
+
lambda{ @data_store.store(@temp_object) }.should raise_error(Dragonfly::DataStorage::UnableToStore)
|
83
|
+
end
|
84
|
+
|
85
|
+
it "should prune empty directories when destroying" do
|
86
|
+
uid = @data_store.store(@temp_object)
|
87
|
+
@data_store.destroy(uid)
|
88
|
+
@data_store.root_path.should be_an_empty_directory
|
89
|
+
end
|
90
|
+
|
91
|
+
end
|
92
|
+
|
93
|
+
end
|
@@ -0,0 +1,67 @@
|
|
1
|
+
require File.dirname(__FILE__) + '/../spec_helper'
|
2
|
+
|
3
|
+
describe Dragonfly::ExtendedTempObject do
|
4
|
+
|
5
|
+
it "should raise an error if not configured with an app" do
|
6
|
+
temp_object = Dragonfly::ExtendedTempObject.new('asdf')
|
7
|
+
lambda{
|
8
|
+
temp_object.process(:dummy)
|
9
|
+
}.should raise_error(Dragonfly::ExtendedTempObject::NotConfiguredError)
|
10
|
+
end
|
11
|
+
|
12
|
+
describe "when configured correctly" do
|
13
|
+
|
14
|
+
before(:each) do
|
15
|
+
@analyser = mock('analyser', :has_analysis_method? => false)
|
16
|
+
@analyser.stub!(:has_analysis_method?).with(:width).and_return(true)
|
17
|
+
@processor = mock('processor')
|
18
|
+
@encoder = mock('encoder')
|
19
|
+
@app = mock('app', :analyser => @analyser, :processor => @processor, :encoder => @encoder)
|
20
|
+
@klass = Class.new(Dragonfly::ExtendedTempObject)
|
21
|
+
@klass.app = @app
|
22
|
+
@object = @klass.new('asdf')
|
23
|
+
end
|
24
|
+
|
25
|
+
describe "analysis" do
|
26
|
+
|
27
|
+
it "should respond to something that the analyser responds to" do
|
28
|
+
@analyser.should_receive(:has_analysis_method?).with(:some_method).and_return(true)
|
29
|
+
@object.should respond_to(:some_method)
|
30
|
+
end
|
31
|
+
|
32
|
+
it "should not respond to something that the analyser doesn't respond to" do
|
33
|
+
@analyser.should_receive(:has_analysis_method?).with(:some_method).and_return(false)
|
34
|
+
@object.should_not respond_to(:some_method)
|
35
|
+
end
|
36
|
+
|
37
|
+
it "should delegate the analysis to the analyser" do
|
38
|
+
@analyser.should_receive(:width).with(@object).and_return(4)
|
39
|
+
@object.width.should == 4
|
40
|
+
end
|
41
|
+
|
42
|
+
it "should cache the result so that it doesn't call it a second time" do
|
43
|
+
@analyser.should_receive(:width).with(@object).and_return(4)
|
44
|
+
@object.width.should == 4
|
45
|
+
|
46
|
+
@analyser.should_not_receive(:width)
|
47
|
+
@object.width.should == 4
|
48
|
+
end
|
49
|
+
|
50
|
+
it "should do the analysis again when it has been modified" do
|
51
|
+
@analyser.should_receive(:width).with(@object).and_return(4)
|
52
|
+
@object.width.should == 4
|
53
|
+
|
54
|
+
@object.modify_self!('hellothisisnew')
|
55
|
+
|
56
|
+
@analyser.should_receive(:width).with(@object).and_return(17)
|
57
|
+
@object.width.should == 17
|
58
|
+
|
59
|
+
@analyser.should_not_receive(:width)
|
60
|
+
@object.width.should == 17
|
61
|
+
end
|
62
|
+
|
63
|
+
end
|
64
|
+
|
65
|
+
end
|
66
|
+
|
67
|
+
end
|
@@ -0,0 +1,44 @@
|
|
1
|
+
require File.dirname(__FILE__) + '/../spec_helper'
|
2
|
+
require 'rack'
|
3
|
+
|
4
|
+
describe Dragonfly::Middleware do
|
5
|
+
|
6
|
+
def make_request(app, url)
|
7
|
+
Rack::MockRequest.new(app).get(url)
|
8
|
+
end
|
9
|
+
|
10
|
+
before(:each) do
|
11
|
+
@stack = Rack::Builder.new do
|
12
|
+
use Dragonfly::Middleware, :images
|
13
|
+
run lambda{|env| [200, {"Content-Type" => "text/html"}, ["#{env['PATH_INFO']}, #{env['QUERY_STRING']}"]] }
|
14
|
+
end
|
15
|
+
end
|
16
|
+
|
17
|
+
it "should continue the calling chain if the app returns a 404 for that url" do
|
18
|
+
Dragonfly::App[:images].should_receive(:call).and_return(
|
19
|
+
[404, {"Content-Type" => 'text/plain'}, ['Not found']]
|
20
|
+
)
|
21
|
+
response = make_request(@stack, 'hello.png?howare=you')
|
22
|
+
response.status.should == 200
|
23
|
+
response.body.should == 'hello.png, howare=you'
|
24
|
+
end
|
25
|
+
|
26
|
+
it "should return as per the dragonfly app if the app returns a 200" do
|
27
|
+
Dragonfly::App[:images].should_receive(:call).and_return(
|
28
|
+
[200, {"Content-Type" => 'text/plain'}, ['ABCD']]
|
29
|
+
)
|
30
|
+
response = make_request(@stack, 'hello.png?howare=you')
|
31
|
+
response.status.should == 200
|
32
|
+
response.body.should == 'ABCD'
|
33
|
+
end
|
34
|
+
|
35
|
+
it "should return as per the dragonfly app if the app returns a 400" do
|
36
|
+
Dragonfly::App[:images].should_receive(:call).and_return(
|
37
|
+
[400, {"Content-Type" => 'text/plain'}, ['ABCD']]
|
38
|
+
)
|
39
|
+
response = make_request(@stack, 'hello.png?howare=you')
|
40
|
+
response.status.should == 400
|
41
|
+
response.body.should == 'ABCD'
|
42
|
+
end
|
43
|
+
|
44
|
+
end
|