tinify 1.2.0 → 1.5.1

Sign up to get free protection for your applications and to get access to all the features.
data/lib/tinify/client.rb CHANGED
@@ -4,11 +4,21 @@ require "json"
4
4
  module Tinify
5
5
  class Client
6
6
  API_ENDPOINT = "https://api.tinify.com".freeze
7
+
8
+ RETRY_COUNT = 1
9
+ RETRY_DELAY = 500
10
+
7
11
  USER_AGENT = "Tinify/#{VERSION} Ruby/#{RUBY_VERSION}p#{RUBY_PATCHLEVEL} (#{defined?(RUBY_ENGINE) ? RUBY_ENGINE : "unknown"})".freeze
12
+
8
13
  CA_BUNDLE = File.expand_path("../../data/cacert.pem", __FILE__).freeze
9
14
 
10
- def initialize(key, app_identifier = nil)
11
- @client = HTTPClient.new
15
+ def initialize(key, app_identifier = nil, proxy = nil)
16
+ begin
17
+ @client = HTTPClient.new(proxy)
18
+ rescue ArgumentError => err
19
+ raise ConnectionError.new("Invalid proxy: #{err.message}")
20
+ end
21
+
12
22
  @client.base_url = API_ENDPOINT
13
23
  @client.default_header = { "User-Agent" => [USER_AGENT, app_identifier].compact.join(" ") }
14
24
 
@@ -19,7 +29,8 @@ module Tinify
19
29
  @client.ssl_config.add_trust_ca(CA_BUNDLE)
20
30
  end
21
31
 
22
- def request(method, url, body = nil, header = {})
32
+ def request(method, url, body = nil)
33
+ header = {}
23
34
  if Hash === body
24
35
  if body.empty?
25
36
  body = nil
@@ -29,26 +40,31 @@ module Tinify
29
40
  end
30
41
  end
31
42
 
32
- begin
33
- response = @client.request(method, url, body: body, header: header)
34
- rescue HTTPClient::TimeoutError => err
35
- raise ConnectionError.new("Timeout while connecting")
36
- rescue StandardError => err
37
- raise ConnectionError.new("Error while connecting: #{err.message}")
38
- end
43
+ RETRY_COUNT.downto(0) do |retries|
44
+ sleep RETRY_DELAY / 1000.0 if retries < RETRY_COUNT
39
45
 
40
- if count = response.headers["Compression-Count"]
41
- Tinify.compression_count = count.to_i
42
- end
46
+ begin
47
+ response = @client.request(method, url, body: body, header: header)
48
+ rescue HTTPClient::TimeoutError => err
49
+ next if retries > 0
50
+ raise ConnectionError.new("Timeout while connecting")
51
+ rescue StandardError => err
52
+ next if retries > 0
53
+ raise ConnectionError.new("Error while connecting: #{err.message}")
54
+ end
55
+
56
+ if count = response.headers["Compression-Count"]
57
+ Tinify.compression_count = count.to_i
58
+ end
59
+
60
+ return response if response.ok?
43
61
 
44
- if response.ok?
45
- response
46
- else
47
62
  details = begin
48
63
  JSON.parse(response.body)
49
64
  rescue StandardError => err
50
- { "message" => "Error while parsing response: #{err.message}", "error" => "ParseError" }
65
+ {"message" => "Error while parsing response: #{err.message}", "error" => "ParseError"}
51
66
  end
67
+ next if retries > 0 and response.status >= 500
52
68
  raise Error.create(details["message"], details["error"], response.status)
53
69
  end
54
70
  end
data/lib/tinify/error.rb CHANGED
@@ -14,12 +14,14 @@ module Tinify
14
14
  end
15
15
  end
16
16
 
17
+ attr_reader :status
18
+
17
19
  def initialize(message, type = self.class.name.split("::").last, status = nil)
18
20
  @message, @type, @status = message, type, status
19
21
  end
20
22
 
21
23
  def message
22
- if @status
24
+ if status
23
25
  "#{@message} (HTTP #{@status}/#{@type})"
24
26
  else
25
27
  "#{@message}"
data/lib/tinify/source.rb CHANGED
@@ -20,6 +20,11 @@ module Tinify
20
20
  @url, @commands = url.freeze, commands.freeze
21
21
  end
22
22
 
23
+ def preserve(*options)
24
+ options = Array(options).flatten
25
+ self.class.new(@url, @commands.merge(preserve: options))
26
+ end
27
+
23
28
  def resize(options)
24
29
  self.class.new(@url, @commands.merge(resize: options))
25
30
  end
@@ -1,3 +1,3 @@
1
1
  module Tinify
2
- VERSION = "1.2.0"
2
+ VERSION = "1.5.1"
3
3
  end
data/lib/tinify.rb CHANGED
@@ -10,8 +10,9 @@ require "thread"
10
10
 
11
11
  module Tinify
12
12
  class << self
13
- attr_accessor :key
14
- attr_accessor :app_identifier
13
+ attr_reader :key
14
+ attr_reader :app_identifier
15
+ attr_reader :proxy
15
16
  attr_accessor :compression_count
16
17
 
17
18
  def key=(key)
@@ -24,6 +25,11 @@ module Tinify
24
25
  @client = nil
25
26
  end
26
27
 
28
+ def proxy=(proxy)
29
+ @proxy = proxy
30
+ @client = nil
31
+ end
32
+
27
33
  def from_file(path)
28
34
  Source.from_file(path)
29
35
  end
@@ -38,6 +44,9 @@ module Tinify
38
44
 
39
45
  def validate!
40
46
  client.request(:post, "/shrink")
47
+ rescue AccountError => err
48
+ return true if err.status == 429
49
+ raise err
41
50
  rescue ClientError
42
51
  true
43
52
  end
@@ -45,10 +54,10 @@ module Tinify
45
54
  @@mutex = Mutex.new
46
55
 
47
56
  def client
48
- raise AccountError.new("Provide an API key with Tinify.key = ...") unless @key
57
+ raise AccountError.new("Provide an API key with Tinify.key = ...") unless key
49
58
  return @client if @client
50
59
  @@mutex.synchronize do
51
- @client ||= Client.new(@key, @app_identifier).freeze
60
+ @client ||= Client.new(key, app_identifier, proxy).freeze
52
61
  end
53
62
  end
54
63
  end
Binary file
data/test/helper.rb CHANGED
@@ -6,6 +6,7 @@ require "tinify"
6
6
  module TestHelpers
7
7
  def before_setup
8
8
  Tinify.key = nil
9
+ Tinify.proxy = nil
9
10
  super
10
11
  end
11
12
 
data/test/integration.rb CHANGED
@@ -7,32 +7,73 @@ require "minitest/autorun"
7
7
 
8
8
  describe "client integration" do
9
9
  Tinify.key = ENV["TINIFY_KEY"]
10
+ Tinify.proxy = ENV["TINIFY_PROXY"]
10
11
 
11
12
  unoptimized_path = File.expand_path("../examples/voormedia.png", __FILE__)
12
13
  optimized = Tinify.from_file(unoptimized_path)
13
14
 
14
15
  it "should compress from file" do
15
- Tempfile.open("optimized.png") do |file|
16
+ Tempfile.open("optimized.png", encoding: "binary") do |file|
16
17
  optimized.to_file(file.path)
17
- assert_operator file.size, :>, 0
18
- assert_operator file.size, :<, 1500
18
+
19
+ size = file.size
20
+ contents = file.read
21
+
22
+ assert_operator size, :>, 1000
23
+ assert_operator size, :<, 1500
24
+
25
+ # width == 137
26
+ assert_includes contents, "\0\0\0\x89".force_encoding("binary")
27
+ refute_includes contents, "Copyright Voormedia".force_encoding("binary")
19
28
  end
20
29
  end
21
30
 
22
31
  it "should compress from url" do
23
32
  source = Tinify.from_url("https://raw.githubusercontent.com/tinify/tinify-ruby/master/test/examples/voormedia.png")
24
- Tempfile.open("optimized.png") do |file|
33
+ Tempfile.open("optimized.png", encoding: "binary") do |file|
25
34
  source.to_file(file.path)
26
- assert_operator file.size, :>, 0
27
- assert_operator file.size, :<, 1500
35
+
36
+ size = file.size
37
+ contents = file.read
38
+
39
+ assert_operator size, :>, 1000
40
+ assert_operator size, :<, 1500
41
+
42
+ # width == 137
43
+ assert_includes contents, "\0\0\0\x89".force_encoding("binary")
44
+ refute_includes contents, "Copyright Voormedia".force_encoding("binary")
28
45
  end
29
46
  end
30
47
 
31
48
  it "should resize" do
32
- Tempfile.open("resized.png") do |file|
49
+ Tempfile.open("optimized.png", encoding: "binary") do |file|
33
50
  optimized.resize(method: "fit", width: 50, height: 20).to_file(file.path)
34
- assert_operator file.size, :>, 0
35
- assert_operator file.size, :<, 800
51
+
52
+ size = file.size
53
+ contents = file.read
54
+
55
+ assert_operator size, :>, 500
56
+ assert_operator size, :<, 1000
57
+
58
+ # width == 50
59
+ assert_includes contents, "\0\0\0\x32".force_encoding("binary")
60
+ refute_includes contents, "Copyright Voormedia".force_encoding("binary")
61
+ end
62
+ end
63
+
64
+ it "should preserve metadata" do
65
+ Tempfile.open("optimized.png", encoding: "binary") do |file|
66
+ optimized.preserve(:copyright, :creation).to_file(file.path)
67
+
68
+ size = file.size
69
+ contents = file.read
70
+
71
+ assert_operator size, :>, 1000
72
+ assert_operator size, :<, 2000
73
+
74
+ # width == 137
75
+ assert_includes contents, "\0\0\0\x89".force_encoding("binary")
76
+ assert_includes contents, "Copyright Voormedia".force_encoding("binary")
36
77
  end
37
78
  end
38
79
  end
@@ -1,6 +1,9 @@
1
1
  require File.expand_path("../helper", __FILE__)
2
2
 
3
3
  describe Tinify::Client do
4
+ Tinify::Client.send(:remove_const, :RETRY_DELAY)
5
+ Tinify::Client.const_set(:RETRY_DELAY, 10)
6
+
4
7
  subject do
5
8
  Tinify::Client.new("key")
6
9
  end
@@ -82,9 +85,33 @@ describe Tinify::Client do
82
85
  headers: { "User-Agent" => "#{Tinify::Client::USER_AGENT} TestApp/0.1" }
83
86
  end
84
87
  end
88
+
89
+ describe "with proxy" do
90
+ subject do
91
+ Tinify::Client.new("key", nil, "http://user:pass@localhost:8080")
92
+ end
93
+
94
+ it "should issue request with proxy authorization" do
95
+ subject.request(:get, "/")
96
+ assert_requested :get, "https://api:key@api.tinify.com",
97
+ headers: { "Proxy-Authorization" => "Basic dXNlcjpwYXNz" }
98
+ end
99
+ end
85
100
  end
86
101
 
87
- describe "with timeout" do
102
+ describe "with timeout once" do
103
+ before do
104
+ stub_request(:get, "https://api:key@api.tinify.com").to_timeout
105
+ .then.to_return(status: 201)
106
+ end
107
+
108
+ it "should return response" do
109
+ response = subject.request(:get, "/")
110
+ assert_equal "", response.body
111
+ end
112
+ end
113
+
114
+ describe "with timeout repeatedly" do
88
115
  before do
89
116
  stub_request(:get, "https://api:key@api.tinify.com").to_timeout
90
117
  end
@@ -102,7 +129,20 @@ describe Tinify::Client do
102
129
  end
103
130
  end
104
131
 
105
- describe "with socket error" do
132
+ describe "with socket error once" do
133
+ before do
134
+ stub_request(:get, "https://api:key@api.tinify.com")
135
+ .to_raise(SocketError.new("nodename nor servname provided"))
136
+ .then.to_return(status: 201)
137
+ end
138
+
139
+ it "should return response" do
140
+ response = subject.request(:get, "/")
141
+ assert_equal "", response.body
142
+ end
143
+ end
144
+
145
+ describe "with socket error repeatedly" do
106
146
  before do
107
147
  stub_request(:get, "https://api:key@api.tinify.com").to_raise(SocketError.new("nodename nor servname provided"))
108
148
  end
@@ -120,7 +160,20 @@ describe Tinify::Client do
120
160
  end
121
161
  end
122
162
 
123
- describe "with unexpected error" do
163
+ describe "with unexpected error once" do
164
+ before do
165
+ stub_request(:get, "https://api:key@api.tinify.com")
166
+ .to_raise("some error")
167
+ .then.to_return(status: 201)
168
+ end
169
+
170
+ it "should return response" do
171
+ response = subject.request(:get, "/")
172
+ assert_equal "", response.body
173
+ end
174
+ end
175
+
176
+ describe "with unexpected error repeatedly" do
124
177
  before do
125
178
  stub_request(:get, "https://api:key@api.tinify.com").to_raise("some error")
126
179
  end
@@ -138,7 +191,21 @@ describe Tinify::Client do
138
191
  end
139
192
  end
140
193
 
141
- describe "with server error" do
194
+ describe "with server error once" do
195
+ before do
196
+ stub_request(:get, "https://api:key@api.tinify.com").to_return(
197
+ status: 584,
198
+ body: '{"error":"InternalServerError","message":"Oops!"}'
199
+ ).then.to_return(status: 201)
200
+ end
201
+
202
+ it "should return response" do
203
+ response = subject.request(:get, "/")
204
+ assert_equal "", response.body
205
+ end
206
+ end
207
+
208
+ describe "with server error repeatedly" do
142
209
  before do
143
210
  stub_request(:get, "https://api:key@api.tinify.com").to_return(
144
211
  status: 584,
@@ -159,8 +226,21 @@ describe Tinify::Client do
159
226
  end
160
227
  end
161
228
 
229
+ describe "with bad server response once" do
230
+ before do
231
+ stub_request(:get, "https://api:key@api.tinify.com").to_return(
232
+ status: 543,
233
+ body: '<!-- this is not json -->'
234
+ ).then.to_return(status: 201)
235
+ end
162
236
 
163
- describe "with bad server response" do
237
+ it "should return response" do
238
+ response = subject.request(:get, "/")
239
+ assert_equal "", response.body
240
+ end
241
+ end
242
+
243
+ describe "with bad server response repeatedly" do
164
244
  before do
165
245
  stub_request(:get, "https://api:key@api.tinify.com").to_return(
166
246
  status: 543,
@@ -186,7 +266,7 @@ describe Tinify::Client do
186
266
  stub_request(:get, "https://api:key@api.tinify.com").to_return(
187
267
  status: 492,
188
268
  body: '{"error":"BadRequest","message":"Oops!"}'
189
- )
269
+ ).then.to_return(status: 201)
190
270
  end
191
271
 
192
272
  it "should raise client error" do
@@ -202,12 +282,13 @@ describe Tinify::Client do
202
282
  end
203
283
  end
204
284
 
285
+
205
286
  describe "with bad credentials" do
206
287
  before do
207
288
  stub_request(:get, "https://api:key@api.tinify.com").to_return(
208
289
  status: 401,
209
290
  body: '{"error":"Unauthorized","message":"Oops!"}'
210
- )
291
+ ).then.to_return(status: 201)
211
292
  end
212
293
 
213
294
  it "should raise account error" do
@@ -7,10 +7,10 @@ describe Tinify::Source do
7
7
  before do
8
8
  Tinify.key = "invalid"
9
9
 
10
- stub_request(:post, "https://api:invalid@api.tinify.com/shrink").to_return(
11
- status: 401,
12
- body: '{"error":"Unauthorized","message":"Credentials are invalid"}'
13
- )
10
+ stub_request(:post, "https://api:invalid@api.tinify.com/shrink")
11
+ .to_return(
12
+ status: 401,
13
+ body: '{"error":"Unauthorized","message":"Credentials are invalid"}')
14
14
  end
15
15
 
16
16
  describe "from_file" do
@@ -41,42 +41,22 @@ describe Tinify::Source do
41
41
  describe "with valid api key" do
42
42
  before do
43
43
  Tinify.key = "valid"
44
-
45
- stub_request(:post, "https://api:valid@api.tinify.com/shrink")
46
- .to_return(
47
- status: 201,
48
- headers: { Location: "https://api.tinify.com/some/location" },
49
- body: '{}'
50
- )
51
-
52
- stub_request(:get, "https://api:valid@api.tinify.com/some/location").to_return(
53
- status: 200,
54
- body: "compressed file"
55
- )
56
-
57
- stub_request(:get, "https://api:valid@api.tinify.com/some/location").with(
58
- body: '{"resize":{"width":400}}'
59
- ).to_return(
60
- status: 200,
61
- body: "small file"
62
- )
63
-
64
- stub_request(:post, "https://api:valid@api.tinify.com/some/location").with(
65
- body: '{"store":{"service":"s3"}}'
66
- ).to_return(
67
- status: 200,
68
- headers: { Location: "https://bucket.s3.amazonaws.com/example" }
69
- )
70
-
71
- stub_request(:post, "https://api:valid@api.tinify.com/some/location").with(
72
- body: '{"resize":{"width":400},"store":{"service":"s3"}}'
73
- ).to_return(
74
- status: 200,
75
- headers: { Location: "https://bucket.s3.amazonaws.com/example" }
76
- )
77
44
  end
78
45
 
79
46
  describe "from_file" do
47
+ before do
48
+ stub_request(:post, "https://api:valid@api.tinify.com/shrink")
49
+ .to_return(
50
+ status: 201,
51
+ headers: { Location: "https://api.tinify.com/some/location" },
52
+ body: '{}')
53
+
54
+ stub_request(:get, "https://api:valid@api.tinify.com/some/location")
55
+ .to_return(
56
+ status: 200,
57
+ body: "compressed file")
58
+ end
59
+
80
60
  it "should return source" do
81
61
  assert_kind_of Tinify::Source, Tinify::Source.from_file(dummy_file)
82
62
  end
@@ -87,6 +67,19 @@ describe Tinify::Source do
87
67
  end
88
68
 
89
69
  describe "from_buffer" do
70
+ before do
71
+ stub_request(:post, "https://api:valid@api.tinify.com/shrink")
72
+ .to_return(
73
+ status: 201,
74
+ headers: { Location: "https://api.tinify.com/some/location" },
75
+ body: '{}')
76
+
77
+ stub_request(:get, "https://api:valid@api.tinify.com/some/location")
78
+ .to_return(
79
+ status: 200,
80
+ body: "compressed file")
81
+ end
82
+
90
83
  it "should return source" do
91
84
  assert_kind_of Tinify::Source, Tinify::Source.from_buffer("png file")
92
85
  end
@@ -103,20 +96,18 @@ describe Tinify::Source do
103
96
  .to_return(
104
97
  status: 201,
105
98
  headers: { Location: "https://api.tinify.com/some/location" },
106
- body: '{}'
107
- )
99
+ body: '{}')
108
100
 
109
101
  stub_request(:post, "https://api:valid@api.tinify.com/shrink")
110
102
  .with(body: '{"source":{"url":"file://wrong"}}')
111
103
  .to_return(
112
104
  status: 400,
113
- body: '{"error":"Source not found","message":"Cannot parse URL"}'
114
- )
105
+ body: '{"error":"Source not found","message":"Cannot parse URL"}')
115
106
 
116
- stub_request(:get, "https://api:valid@api.tinify.com/some/location").to_return(
117
- status: 200,
118
- body: "compressed file"
119
- )
107
+ stub_request(:get, "https://api:valid@api.tinify.com/some/location")
108
+ .to_return(
109
+ status: 200,
110
+ body: "compressed file")
120
111
  end
121
112
 
122
113
  it "should return source" do
@@ -135,12 +126,84 @@ describe Tinify::Source do
135
126
  end
136
127
 
137
128
  describe "result" do
129
+ before do
130
+ stub_request(:post, "https://api:valid@api.tinify.com/shrink")
131
+ .to_return(
132
+ status: 201,
133
+ headers: { Location: "https://api.tinify.com/some/location" },
134
+ body: '{}')
135
+
136
+ stub_request(:get, "https://api:valid@api.tinify.com/some/location")
137
+ .to_return(
138
+ status: 200,
139
+ body: "compressed file")
140
+ end
141
+
138
142
  it "should return result" do
139
143
  assert_kind_of Tinify::Result, Tinify::Source.from_buffer("png file").result
140
144
  end
141
145
  end
142
146
 
147
+ describe "preserve" do
148
+ before do
149
+ stub_request(:post, "https://api:valid@api.tinify.com/shrink")
150
+ .to_return(
151
+ status: 201,
152
+ headers: { Location: "https://api.tinify.com/some/location" },
153
+ body: '{}')
154
+
155
+ stub_request(:get, "https://api:valid@api.tinify.com/some/location")
156
+ .with(
157
+ body: '{"preserve":["copyright","location"]}')
158
+ .to_return(
159
+ status: 200,
160
+ body: "copyrighted file")
161
+ end
162
+
163
+ it "should return source" do
164
+ source = Tinify::Source.from_buffer("png file").preserve(:copyright, :location)
165
+ assert_kind_of Tinify::Source, source
166
+ end
167
+
168
+ it "should return source with data" do
169
+ source = Tinify::Source.from_buffer("png file").preserve(:copyright, :location)
170
+ assert_equal "copyrighted file", source.to_buffer
171
+ end
172
+
173
+ it "should return source with data for array" do
174
+ source = Tinify::Source.from_buffer("png file").preserve([:copyright, :location])
175
+ assert_equal "copyrighted file", source.to_buffer
176
+ end
177
+
178
+ it "should include other options if set" do
179
+ stub_request(:get, "https://api:valid@api.tinify.com/some/location")
180
+ .with(
181
+ body: '{"resize":{"width":400},"preserve":["copyright","location"]}')
182
+ .to_return(
183
+ status: 200,
184
+ body: "copyrighted resized file")
185
+
186
+ source = Tinify::Source.from_buffer("png file").resize(width: 400).preserve(:copyright, :location)
187
+ assert_equal "copyrighted resized file", source.to_buffer
188
+ end
189
+ end
190
+
143
191
  describe "resize" do
192
+ before do
193
+ stub_request(:post, "https://api:valid@api.tinify.com/shrink")
194
+ .to_return(
195
+ status: 201,
196
+ headers: { Location: "https://api.tinify.com/some/location" },
197
+ body: '{}')
198
+
199
+ stub_request(:get, "https://api:valid@api.tinify.com/some/location")
200
+ .with(
201
+ body: '{"resize":{"width":400}}')
202
+ .to_return(
203
+ status: 200,
204
+ body: "small file")
205
+ end
206
+
144
207
  it "should return source" do
145
208
  assert_kind_of Tinify::Source, Tinify::Source.from_buffer("png file").resize(width: 400)
146
209
  end
@@ -151,6 +214,22 @@ describe Tinify::Source do
151
214
  end
152
215
 
153
216
  describe "store" do
217
+ before do
218
+ stub_request(:post, "https://api:valid@api.tinify.com/shrink")
219
+ .to_return(
220
+ status: 201,
221
+ headers: { Location: "https://api.tinify.com/some/location" },
222
+ body: '{}'
223
+ )
224
+
225
+ stub_request(:post, "https://api:valid@api.tinify.com/some/location")
226
+ .with(
227
+ body: '{"store":{"service":"s3"}}')
228
+ .to_return(
229
+ status: 200,
230
+ headers: { Location: "https://bucket.s3.amazonaws.com/example" })
231
+ end
232
+
154
233
  it "should return result meta" do
155
234
  assert_kind_of Tinify::ResultMeta, Tinify::Source.from_buffer("png file").store(service: "s3")
156
235
  end
@@ -160,19 +239,52 @@ describe Tinify::Source do
160
239
  assert_equal "https://bucket.s3.amazonaws.com/example", result.location
161
240
  end
162
241
 
163
- it "should include resize options if set" do
242
+ it "should include other options if set" do
243
+ stub_request(:post, "https://api:valid@api.tinify.com/some/location")
244
+ .with(
245
+ body: '{"resize":{"width":400},"store":{"service":"s3"}}')
246
+ .to_return(
247
+ status: 200,
248
+ headers: { Location: "https://bucket.s3.amazonaws.com/example" })
249
+
164
250
  result = Tinify::Source.from_buffer("png file").resize(width: 400).store(service: "s3")
165
251
  assert_equal "https://bucket.s3.amazonaws.com/example", result.location
166
252
  end
167
253
  end
168
254
 
169
255
  describe "to_buffer" do
256
+ before do
257
+ stub_request(:post, "https://api:valid@api.tinify.com/shrink")
258
+ .to_return(
259
+ status: 201,
260
+ headers: { Location: "https://api.tinify.com/some/location" },
261
+ body: '{}')
262
+
263
+ stub_request(:get, "https://api:valid@api.tinify.com/some/location").to_return(
264
+ status: 200,
265
+ body: "compressed file"
266
+ )
267
+ end
268
+
170
269
  it "should return image data" do
171
270
  assert_equal "compressed file", Tinify::Source.from_buffer("png file").to_buffer
172
271
  end
173
272
  end
174
273
 
175
274
  describe "to_file" do
275
+ before do
276
+ stub_request(:post, "https://api:valid@api.tinify.com/shrink")
277
+ .to_return(
278
+ status: 201,
279
+ headers: { Location: "https://api.tinify.com/some/location" },
280
+ body: '{}')
281
+
282
+ stub_request(:get, "https://api:valid@api.tinify.com/some/location").to_return(
283
+ status: 200,
284
+ body: "compressed file"
285
+ )
286
+ end
287
+
176
288
  it "should store image data" do
177
289
  begin
178
290
  tmp = Tempfile.open("foo")