skylab_studio 1.0.6 → 1.0.8

Sign up to get free protection for your applications and to get access to all the features.
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: f99a61b73fab6e35ba741ca1c841822634c163b1542e96008f4a6126c7fc7e1e
4
- data.tar.gz: 41cf785d1ff581766b3ba7fc05bd262648cbf0dde78daaabe3558c09e176dd9a
3
+ metadata.gz: 8dcea80a2765d6d89b736dbdaf420595a284c66b1c2319bdb537e6dce55d6c29
4
+ data.tar.gz: 26870d180ef19254df91ce67ffeb150564c6a144ccbc8965414c48938f687486
5
5
  SHA512:
6
- metadata.gz: 06ca0fa9eb3a14c85c463abfe59b275a612181ffbfe1db9c5f3b61fda266911372446ecdf1db3c0666376b972ca7dec5147dec1ea6e14fdf3862bbd4df0f4855
7
- data.tar.gz: 1aaaf67aeb7be27fd165a7b75d324db4408188b238d0b06eda13ff1f18dbd52969b09ee230ddac8b10422033f4da0b5c728d9687f82891fb578be087d15dec75
6
+ metadata.gz: b01781324fb9c33b8720b54d218ed0c60f346069b04ac646e720b641c85316ef140d96821d69f1054c73a997445a0c1cc4adbf56be3c2f3a765e42c7354ea6d4
7
+ data.tar.gz: e78732d764037a41fad813879db50e04defe51ac4eb2eadd1c437693f5e8e58489c5795d135f0c4e81a3d3a4c2d17b024d2897e6733603ec5d81d8a8f41cfef6
@@ -1,9 +1,13 @@
1
+ # frozen_string_literal: true
2
+
1
3
  require_relative 'error'
2
4
  require 'fileutils'
3
5
  require 'digest'
4
6
  require 'open-uri'
5
7
  require 'base64'
6
8
  require 'net/http'
9
+ require 'vips'
10
+ require 'concurrent'
7
11
 
8
12
  module SkylabStudio
9
13
  class ClientNilArgument < Error; end
@@ -30,8 +34,8 @@ module SkylabStudio
30
34
  @configuration = SkylabStudio::Config.new(settings)
31
35
  end
32
36
 
33
- def list_jobs(options = {})
34
- SkylabStudio::Request.new(@configuration).get(:jobs, options)
37
+ def list_jobs()
38
+ SkylabStudio::Request.new(@configuration).get(:jobs)
35
39
  end
36
40
 
37
41
  def create_job(options = {})
@@ -41,10 +45,10 @@ module SkylabStudio
41
45
  SkylabStudio::Request.new(@configuration).post(:jobs, options)
42
46
  end
43
47
 
44
- def get_job(options = {})
45
- validate_argument_presence options, :id
48
+ def get_job(job_id)
49
+ validate_argument_presence nil, :job_id
46
50
 
47
- SkylabStudio::Request.new(@configuration).get("jobs/#{options[:id]}", options)
51
+ SkylabStudio::Request.new(@configuration).get("jobs/#{job_id}")
48
52
  end
49
53
 
50
54
  def get_job_by_name(options = {})
@@ -53,11 +57,10 @@ module SkylabStudio
53
57
  SkylabStudio::Request.new(@configuration).get('jobs/find_by_name', options)
54
58
  end
55
59
 
56
- def update_job(options = {})
57
- validate_argument_presence options, :id
58
- validate_argument_presence options, :job
60
+ def update_job(job_id, options = {})
61
+ validate_argument_presence nil, :job_id
59
62
 
60
- SkylabStudio::Request.new(@configuration).patch("jobs/#{options[:id]}", options)
63
+ SkylabStudio::Request.new(@configuration).patch("jobs/#{job_id}", options)
61
64
  end
62
65
 
63
66
  def queue_job(options = {})
@@ -66,20 +69,20 @@ module SkylabStudio
66
69
  SkylabStudio::Request.new(@configuration).post("jobs/#{options[:id]}/queue", options)
67
70
  end
68
71
 
69
- def fetch_jobs_in_front(options = {})
70
- SkylabStudio::Request.new(@configuration).get("jobs/#{options[:id]}/jobs_in_front", options)
72
+ def fetch_jobs_in_front(job_id)
73
+ SkylabStudio::Request.new(@configuration).get("jobs/#{job_id}/jobs_in_front")
71
74
  end
72
75
 
73
- def delete_job(options = {})
74
- validate_argument_presence options, :id
76
+ def delete_job(job_id)
77
+ validate_argument_presence nil, :job_id
75
78
 
76
- SkylabStudio::Request.new(@configuration).delete("jobs/#{options[:id]}")
79
+ SkylabStudio::Request.new(@configuration).delete("jobs/#{job_id}")
77
80
  end
78
81
 
79
- def cancel_job(options = {})
80
- validate_argument_presence options, :id
82
+ def cancel_job(job_id)
83
+ validate_argument_presence nil, :job_id
81
84
 
82
- SkylabStudio::Request.new(@configuration).post("jobs/#{options[:id]}/cancel", options)
85
+ SkylabStudio::Request.new(@configuration).post("jobs/#{job_id}/cancel", nil)
83
86
  end
84
87
 
85
88
  def list_profiles(options = {})
@@ -92,17 +95,16 @@ module SkylabStudio
92
95
  SkylabStudio::Request.new(@configuration).post(:profiles, options)
93
96
  end
94
97
 
95
- def get_profile(options = {})
96
- validate_argument_presence options, :id
98
+ def get_profile(profile_id)
99
+ validate_argument_presence nil, :profile_id
97
100
 
98
- SkylabStudio::Request.new(@configuration).get("profiles/#{options[:id]}", options)
101
+ SkylabStudio::Request.new(@configuration).get("profiles/#{profile_id}")
99
102
  end
100
103
 
101
- def update_profile(options = {})
102
- validate_argument_presence options, :id
103
- validate_argument_presence options, :profile
104
+ def update_profile(profile_id, options = {})
105
+ validate_argument_presence nil, :profile_id
104
106
 
105
- SkylabStudio::Request.new(@configuration).patch("profiles/#{options[:id]}", options)
107
+ SkylabStudio::Request.new(@configuration).patch("profiles/#{profile_id}", options)
106
108
  end
107
109
 
108
110
  def upload_job_photo(photo_path = nil, job_id = nil)
@@ -119,31 +121,123 @@ module SkylabStudio
119
121
  upload_photo(photo_path, profile_id, 'profile')
120
122
  end
121
123
 
122
- def get_photo(options = {})
123
- validate_argument_presence options, :id
124
+ def get_photo(photo_id)
125
+ validate_argument_presence nil, :photo_id
124
126
 
125
- SkylabStudio::Request.new(@configuration).get("photos/#{options[:id]}", options)
127
+ SkylabStudio::Request.new(@configuration).get("photos/#{photo_id}")
126
128
  end
127
129
 
128
- def get_job_photos(job_identifier, value)
129
- {
130
- "job_#{job_identifier}".to_sym => value
131
- }
130
+ def get_job_photos(job_id)
131
+ SkylabStudio::Request.new(@configuration).get('photos/list_for_job', { job_id: job_id })
132
+ end
133
+
134
+ def delete_photo(photo_id)
135
+ validate_argument_presence nil, :photo_id
132
136
 
133
- SkylabStudio::Request.new(@configuration).get('phtos/list_for_job', options)
137
+ SkylabStudio::Request.new(@configuration).delete("photos/#{photo_id}")
134
138
  end
135
139
 
136
- def update_photo(options = {})
137
- validate_argument_presence options, :id
138
- validate_argument_presence options, :photo
140
+ def download_photo(photo_id, output_path, profile: nil, options: {})
141
+ file_name = ''
142
+
143
+ unless Dir.exist?(output_path)
144
+ # Must be a file path - separate output_path and file_name
145
+ file_name = File.basename(output_path)
146
+ output_path = File.dirname(output_path) || ''
147
+ end
139
148
 
140
- SkylabStudio::Request.new(@configuration).patch("photos/#{options[:id]}", options)
149
+ begin
150
+ photo = get_photo(photo_id)
151
+ profile_id = photo['job']['profileId']
152
+
153
+ file_name = photo['name'] if file_name.empty?
154
+
155
+ profile ||= get_profile(profile_id)
156
+
157
+ is_extract = profile['enableExtract'].to_s == 'true'
158
+ replace_background = profile['replaceBackground'].to_s == 'true'
159
+ is_dual_file_output = profile['dualFileOutput'].to_s == 'true'
160
+ profile['enableStripPngMetadata'].to_s
161
+ bgs = options[:bgs]
162
+
163
+ # Load output image
164
+ image_buffer = download_image_async(photo['retouchedUrl'])
165
+ image = Vips::Image.new_from_buffer(image_buffer, '')
166
+
167
+ if is_extract # Output extract image
168
+ png_file_name = "#{File.basename(file_name, '.*')}.png"
169
+
170
+ # Dual File Output will provide an image in the format specified in the outputFileType field
171
+ # and an extracted image as a PNG.
172
+ image.write_to_file(File.join(output_path, png_file_name)) if is_dual_file_output
173
+
174
+ download_replaced_background_image(file_name, image, output_path, profile: profile, bgs: bgs) if replace_background
175
+
176
+ # Regular Extract output
177
+ image.write_to_file(File.join(output_path, png_file_name)) unless is_dual_file_output || replace_background
178
+ else # Non-extracted regular image output
179
+ image.write_to_file(File.join(output_path, file_name))
180
+ end
181
+
182
+ puts "Successfully downloaded: #{file_name}"
183
+ [file_name, true]
184
+ rescue StandardError => e
185
+ error_msg = "Failed to download photo id: #{photo_id} - #{e}"
186
+ raise error_msg if options[:return_on_error].nil?
187
+
188
+ [file_name, false]
189
+ end
141
190
  end
142
191
 
143
- def delete_photo(options = {})
144
- validate_argument_presence options, :id
192
+ def download_all_photos(photos_list, profile, output_path)
193
+ raise 'Invalid output path' unless Dir.exist?(output_path)
194
+
195
+ success_photos = []
196
+ errored_photos = []
197
+ bgs = []
198
+
199
+ begin
200
+ profile = get_profile(profile['id'])
201
+ bgs = download_bg_images(profile) if profile && profile['photos']&.any?
202
+
203
+ photo_ids = photos_list.map { |photo| photo['id'].to_s }.compact
204
+
205
+ pool = Concurrent::FixedThreadPool.new(@configuration.settings[:max_download_concurrency])
206
+ download_tasks = []
207
+ photo_options = { return_on_error: true, bgs: bgs }
208
+ photo_ids.each do |photo_id|
209
+ download_tasks << Concurrent::Future.execute(executor: pool) do
210
+ download_photo(photo_id.to_i, output_path, profile: profile, options: photo_options)
211
+ end
212
+ end
145
213
 
146
- SkylabStudio::Request.new(@configuration).delete("photos/#{options[:id]}")
214
+ # Wait for all download tasks to complete
215
+ results = download_tasks.map(&:value)
216
+ results.each do |result|
217
+ if result[1]
218
+ success_photos << result[0]
219
+ else
220
+ errored_photos << result[0]
221
+ end
222
+ end
223
+
224
+ { success_photos: success_photos, errored_photos: errored_photos }
225
+ rescue StandardError => e
226
+ warn e
227
+
228
+ { success_photos: success_photos, errored_photos: errored_photos }
229
+ end
230
+ end
231
+
232
+ def validate_hmac_headers(secret_key, job_json_string, request_timestamp, signature)
233
+ message = "#{request_timestamp}:#{job_json_string}".encode('utf-8')
234
+
235
+ # Create the HMAC signature using SHA-256
236
+ hmac_digest = OpenSSL::HMAC.digest('sha256', secret_key.encode('utf-8'), message)
237
+ generated_sig = Base64.strict_encode64(hmac_digest).force_encoding('utf-8')
238
+
239
+ # Compare the provided signature with the generated signature
240
+ signature == generated_sig
147
241
  end
148
242
 
149
243
  private
@@ -157,7 +251,6 @@ module SkylabStudio
157
251
  end
158
252
 
159
253
  def upload_photo(photo_path, id, model = 'job')
160
- res = {}
161
254
  valid_exts_to_check = %w[.jpg .jpeg .png .webp]
162
255
 
163
256
  raise 'Invalid file type: must be of type jpg/jpeg/png/webp' unless valid_exts_to_check.any? { |ext| photo_path.downcase.end_with?(ext) }
@@ -167,6 +260,7 @@ module SkylabStudio
167
260
  raise 'Invalid file size: must be no larger than 27MB' if file_size > 27 * 1024 * 1024
168
261
 
169
262
  photo_name = File.basename(photo_path)
263
+ photo_ext = File.extname(photo_name)
170
264
  headers = {}
171
265
  md5hash = ''
172
266
 
@@ -178,10 +272,10 @@ module SkylabStudio
178
272
  end
179
273
 
180
274
  # model - either job or profile (job_id/profile_id)
181
- photo_data = { "#{model}_id" => id, name: photo_name, 'use_cache_upload' => false }
275
+ photo_data = { "#{model}_id": id, name: "#{photo_name}#{photo_ext}", path: photo_path, 'use_cache_upload': false }
182
276
 
183
277
  if model == 'job'
184
- job_type = get_job(id: id)['type']
278
+ job_type = get_job(id)['type']
185
279
 
186
280
  headers = { 'X-Amz-Tagging' => 'job=photo&api=true' } if job_type == 'regular'
187
281
  end
@@ -213,7 +307,7 @@ module SkylabStudio
213
307
  uri = URI(upload_url)
214
308
  request = Net::HTTP::Put.new(uri, headers)
215
309
  request.body = data
216
- upload_photo_resp = Net::HTTP.start(uri.hostname) {|http| http.request(request) }
310
+ upload_photo_resp = Net::HTTP.start(uri.hostname) { |http| http.request(request) }
217
311
 
218
312
  unless upload_photo_resp
219
313
  puts 'First upload attempt failed, retrying...'
@@ -221,7 +315,7 @@ module SkylabStudio
221
315
  # Retry upload
222
316
 
223
317
  while retry_count < 3
224
- upload_photo_resp = Net::HTTP.start(uri.hostname) {|http| http.request(request) }
318
+ upload_photo_resp = Net::HTTP.start(uri.hostname) { |http| http.request(request) }
225
319
  if upload_photo_resp
226
320
  break # Upload was successful, exit the loop
227
321
  elsif retry_count == 2 # Check if retry count is 2 (0-based indexing)
@@ -241,6 +335,70 @@ module SkylabStudio
241
335
  photo_response_json
242
336
  end
243
337
 
338
+ def download_image_async(image_url)
339
+ raise "Invalid retouchedUrl: \"#{image_url}\" - Please ensure the job is complete" unless image_url.start_with?('http', 'https')
340
+
341
+ begin
342
+ uri = URI(image_url)
343
+ response = Net::HTTP.get_response(uri)
344
+
345
+ if response.is_a?(Net::HTTPSuccess)
346
+ response.body
347
+
348
+ else
349
+ puts "Error downloading image: #{response.message}"
350
+ nil
351
+ end
352
+ rescue StandardError => e
353
+ puts "Error downloading image: #{e.message}"
354
+ nil
355
+ end
356
+ end
357
+
358
+ def download_bg_images(profile)
359
+ temp_bgs = []
360
+
361
+ bg_photos = profile['photos'].select { |photo| photo['jobId'].nil? }
362
+
363
+ bg_photos.each do |bg|
364
+ bg_buffer = download_image_async(bg['originalUrl'])
365
+ bg_image = Vips::Image.new_from_buffer(bg_buffer, '')
366
+ temp_bgs << bg_image
367
+ end
368
+
369
+ temp_bgs
370
+ end
371
+
372
+ def download_replaced_background_image(file_name, input_image, output_path, profile: nil, bgs: nil)
373
+ output_file_type = profile&.[]('outputFileType') || 'png'
374
+
375
+ bgs = download_bg_images(profile) if bgs.nil? && !profile.nil? && profile&.[]('photos')&.any?
376
+
377
+ alpha_channel = input_image[3]
378
+ rgb_channel = input_image[0..2]
379
+ rgb_cutout = rgb_channel.bandjoin(alpha_channel)
380
+
381
+ if bgs&.any?
382
+ bgs.each_with_index do |bg_image, i|
383
+ new_file_name = if i.zero?
384
+ "#{File.basename(file_name,
385
+ '.*')}.#{output_file_type}"
386
+ else
387
+ "#{File.basename(file_name,
388
+ '.*')} (#{i + 1}).#{output_file_type}"
389
+ end
390
+ resized_bg_image = bg_image.thumbnail_image(input_image.width, height: input_image.height, crop: :centre)
391
+ result_image = resized_bg_image.composite2(rgb_cutout, :over)
392
+ result_image.write_to_file(File.join(output_path, new_file_name))
393
+ end
394
+ end
395
+
396
+ true
397
+ rescue StandardError => e
398
+ error_msg = "Error downloading background image: #{e.message}"
399
+ raise error_msg
400
+ end
401
+
244
402
  def validate_argument_presence(options, key)
245
403
  raise SkylabStudio::ClientNilArgument, "#{key} cannot be nil" if options.is_a?(Hash) && options[key].nil?
246
404
 
@@ -1,10 +1,12 @@
1
+ # frozen_string_literal: true
2
+
1
3
  require_relative 'version'
2
4
 
3
5
  module SkylabStudio
4
6
  class Config
5
7
  attr_accessor :settings
6
8
 
7
- DEFAULT_URL = 'https://studio.skylabtech.ai'.freeze
9
+ DEFAULT_URL = 'https://studio.skylabtech.ai'
8
10
 
9
11
  def self.defaults
10
12
  source = URI.parse(DEFAULT_URL)
@@ -17,7 +19,8 @@ module SkylabStudio
17
19
  port: source.port,
18
20
  api_version: 'v1',
19
21
  debug: true,
20
- client_stub: "ruby-#{VERSION}"
22
+ client_stub: "ruby-#{VERSION}",
23
+ max_download_concurrency: 5
21
24
  }
22
25
  end
23
26
 
@@ -1,5 +1,5 @@
1
1
  # frozen_string_literal: true
2
2
 
3
3
  module SkylabStudio
4
- VERSION = '1.0.6'
4
+ VERSION = '1.0.8'
5
5
  end
@@ -48,13 +48,13 @@ RSpec.describe SkylabStudio::Client do
48
48
 
49
49
  describe '#get_job' do
50
50
  it 'should raise error with no id' do
51
- expect { subject.get_job }.to raise_error(SkylabStudio::ClientNilArgument)
51
+ expect { subject.get_job }.to raise_error(ArgumentError)
52
52
  end
53
53
 
54
54
  it 'should return response' do
55
55
  SkylabStudio::Request.any_instance.stub(:get).and_return(true)
56
56
 
57
- subject.get_job(id: 123).should eq(true)
57
+ subject.get_job(123).should eq(true)
58
58
  end
59
59
  end
60
60
 
@@ -62,12 +62,7 @@ RSpec.describe SkylabStudio::Client do
62
62
  it 'should return response' do
63
63
  SkylabStudio::Request.any_instance.stub(:patch).and_return(true)
64
64
 
65
- subject.update_job(
66
- id: 1,
67
- job: {
68
- profile_id: 2
69
- }
70
- ).should eq(true)
65
+ subject.update_job(1, { profile_id: 2 }).should eq(true)
71
66
  end
72
67
  end
73
68
 
@@ -75,9 +70,7 @@ RSpec.describe SkylabStudio::Client do
75
70
  it 'should return response' do
76
71
  SkylabStudio::Request.any_instance.stub(:delete).and_return(true)
77
72
 
78
- subject.delete_job(
79
- id: 1
80
- ).should eq(true)
73
+ subject.delete_job(1).should eq(true)
81
74
  end
82
75
  end
83
76
 
@@ -95,9 +88,7 @@ RSpec.describe SkylabStudio::Client do
95
88
  it 'should return response' do
96
89
  SkylabStudio::Request.any_instance.stub(:post).and_return(true)
97
90
 
98
- subject.cancel_job(
99
- id: 1
100
- ).should eq(true)
91
+ subject.cancel_job(1).should eq(true)
101
92
  end
102
93
  end
103
94
 
@@ -123,13 +114,13 @@ RSpec.describe SkylabStudio::Client do
123
114
 
124
115
  describe '#get_profile' do
125
116
  it 'should raise error with no id' do
126
- expect { subject.get_profile }.to raise_error(SkylabStudio::ClientNilArgument)
117
+ expect { subject.get_profile }.to raise_error(ArgumentError)
127
118
  end
128
119
 
129
120
  it 'should return response' do
130
121
  SkylabStudio::Request.any_instance.stub(:get).and_return(true)
131
122
 
132
- subject.get_profile(id: 123).should eq(true)
123
+ subject.get_profile(123).should eq(true)
133
124
  end
134
125
  end
135
126
 
@@ -137,12 +128,7 @@ RSpec.describe SkylabStudio::Client do
137
128
  it 'should return response' do
138
129
  SkylabStudio::Request.any_instance.stub(:patch).and_return(true)
139
130
 
140
- subject.update_profile(
141
- id: 1,
142
- profile: {
143
- name: 'Bar'
144
- }
145
- ).should eq(true)
131
+ subject.update_profile(1, { name: 'Bar' } ).should eq(true)
146
132
  end
147
133
  end
148
134
 
@@ -152,24 +138,27 @@ RSpec.describe SkylabStudio::Client do
152
138
  .to_return(status: 200, body: { id: 1, photo: {} }.to_json, headers: {})
153
139
 
154
140
  stub_request(:get, 'https://studio.skylabtech.ai/api/public/v1/photos/upload_url')
155
- .to_return(status: 200, body: '', headers: {})
141
+ .to_return(status: 200, body: { url: 'http://test.test/' }.to_json, headers: {})
156
142
 
157
143
  stub_request(:get, 'https://studio.skylabtech.ai/api/public/v1/jobs/1')
158
- .to_return(status: 200, body: '', headers: {})
144
+ .to_return(status: 200, body: {}.to_json, headers: {})
159
145
 
160
146
  stub_request(:delete, 'https://studio.skylabtech.ai/api/public/v1/photos/1')
161
147
  .to_return(status: 200, body: { id: 1 }.to_json, headers: {})
162
148
 
163
- allow_any_instance_of(Net::HTTPSuccess).to receive(:body) { { id: 1 }.to_json }
149
+ stub_request(:put, /.*/)
150
+ .to_return(status: 200, body: {}.to_json, headers: {})
151
+
152
+ # allow_any_instance_of(Net::HTTPSuccess).to receive(:body) { { id: 1 }.to_json }
164
153
  end
165
154
 
166
155
  it 'should return response' do
167
156
  photo_path = "#{File.expand_path('../../', File.dirname(__FILE__))}/test-portrait-1.JPG"
168
157
  id = 1
169
158
 
170
- expected_response = { "id" => id }
159
+ expected_response = { id: id, photo: {} }.to_json
171
160
 
172
- subject.upload_job_photo(photo_path, id).should eq(expected_response)
161
+ expect(subject.upload_job_photo(photo_path, id).to_json).to eq(expected_response)
173
162
  end
174
163
  end
175
164
 
@@ -179,49 +168,40 @@ RSpec.describe SkylabStudio::Client do
179
168
  .to_return(status: 200, body: { id: 1, photo: {} }.to_json, headers: {})
180
169
 
181
170
  stub_request(:get, 'https://studio.skylabtech.ai/api/public/v1/photos/upload_url')
182
- .to_return(status: 200, body: '', headers: {})
171
+ .to_return(status: 200, body: { url: 'http://test.test/' }.to_json, headers: {})
172
+
173
+ stub_request(:get, 'https://studio.skylabtech.ai/api/public/v1/profiles/upload_url')
174
+ .to_return(status: 200, body: { url: 'http://test.test/' }.to_json, headers: {})
183
175
 
184
176
  stub_request(:get, 'https://studio.skylabtech.ai/api/public/v1/jobs/1')
185
- .to_return(status: 200, body: '', headers: {})
177
+ .to_return(status: 200, body: {}.to_json, headers: {})
186
178
 
187
179
  stub_request(:delete, 'https://studio.skylabtech.ai/api/public/v1/photos/1')
188
180
  .to_return(status: 200, body: { id: 1 }.to_json, headers: {})
189
181
 
190
- allow_any_instance_of(Net::HTTPSuccess).to receive(:body) { { id: 1 }.to_json }
182
+ stub_request(:put, /.*/)
183
+ .to_return(status: 200, body: {}.to_json, headers: {})
191
184
  end
192
185
 
193
186
  it 'should return response' do
194
187
  photo_path = "#{File.expand_path('../../', File.dirname(__FILE__))}/test-portrait-1.JPG"
195
188
  id = 1
196
189
 
197
- expected_response = { "id" => id }
190
+ expected_response = { id: id, photo: {} }.to_json
198
191
 
199
- subject.upload_profile_photo(photo_path, 1).should eq(expected_response)
192
+ expect(subject.upload_profile_photo(photo_path, 1).to_json).to eq(expected_response)
200
193
  end
201
194
  end
202
195
 
203
196
  describe '#get_photo' do
204
197
  it 'should raise error with no id' do
205
- expect { subject.get_photo }.to raise_error(SkylabStudio::ClientNilArgument)
198
+ expect { subject.get_photo }.to raise_error(ArgumentError)
206
199
  end
207
200
 
208
201
  it 'should return response' do
209
202
  SkylabStudio::Request.any_instance.stub(:get).and_return(true)
210
203
 
211
- subject.get_photo(id: 123).should eq(true)
212
- end
213
- end
214
-
215
- describe '#update_photo' do
216
- it 'should return response' do
217
- SkylabStudio::Request.any_instance.stub(:patch).and_return(true)
218
-
219
- subject.update_photo(
220
- id: 1,
221
- photo: {
222
- name: 'Bar'
223
- }
224
- ).should eq(true)
204
+ subject.get_photo(123).should eq(true)
225
205
  end
226
206
  end
227
207
 
@@ -229,9 +209,7 @@ RSpec.describe SkylabStudio::Client do
229
209
  it 'should return response' do
230
210
  SkylabStudio::Request.any_instance.stub(:delete).and_return(true)
231
211
 
232
- subject.delete_photo(
233
- id: 1
234
- ).should eq(true)
212
+ subject.delete_photo(1).should eq(true)
235
213
  end
236
214
  end
237
215
  end
metadata CHANGED
@@ -1,14 +1,14 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: skylab_studio
3
3
  version: !ruby/object:Gem::Version
4
- version: 1.0.6
4
+ version: 1.0.8
5
5
  platform: ruby
6
6
  authors:
7
7
  - Paul Lam
8
8
  autorequire:
9
9
  bindir: bin
10
10
  cert_chain: []
11
- date: 2024-03-20 00:00:00.000000000 Z
11
+ date: 2024-04-08 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: rspec