wetransfer 0.1.0
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.
- checksums.yaml +7 -0
- data/.gitignore +14 -0
- data/.rspec +3 -0
- data/.rubocop.yml +6 -0
- data/.travis.yml +15 -0
- data/CODE_OF_CONDUCT.md +74 -0
- data/CONTRIBUTING.md +152 -0
- data/Gemfile +6 -0
- data/LICENSE.txt +21 -0
- data/README.md +102 -0
- data/Rakefile +6 -0
- data/bin/console +14 -0
- data/bin/setup +8 -0
- data/lib/wetransfer.rb +16 -0
- data/lib/wetransfer/client.rb +126 -0
- data/lib/wetransfer/connection.rb +77 -0
- data/lib/wetransfer/item.rb +14 -0
- data/lib/wetransfer/item_builder.rb +59 -0
- data/lib/wetransfer/transfer.rb +30 -0
- data/lib/wetransfer/transfer_builder.rb +28 -0
- data/lib/wetransfer/version.rb +3 -0
- data/spec/client_spec.rb +82 -0
- data/spec/connection_spec.rb +74 -0
- data/spec/item_builder_spec.rb +104 -0
- data/spec/spec_helper.rb +24 -0
- data/spec/test_server.rb +208 -0
- data/spec/wetransfer_spec.rb +7 -0
- data/wetransfer.gemspec +44 -0
- metadata +201 -0
data/lib/wetransfer.rb
ADDED
@@ -0,0 +1,16 @@
|
|
1
|
+
require 'faraday'
|
2
|
+
require 'json'
|
3
|
+
require 'dotenv'
|
4
|
+
Dotenv.load
|
5
|
+
|
6
|
+
require 'wetransfer/version'
|
7
|
+
require 'wetransfer/client'
|
8
|
+
require 'wetransfer/transfer'
|
9
|
+
require 'wetransfer/transfer_builder'
|
10
|
+
require 'wetransfer/item'
|
11
|
+
require 'wetransfer/item_builder'
|
12
|
+
require 'wetransfer/connection'
|
13
|
+
|
14
|
+
module WeTransfer
|
15
|
+
|
16
|
+
end
|
@@ -0,0 +1,126 @@
|
|
1
|
+
module WeTransfer
|
2
|
+
class Client
|
3
|
+
attr_accessor :api_key
|
4
|
+
attr_reader :api_connection
|
5
|
+
CHUNK_SIZE = 6_291_456
|
6
|
+
|
7
|
+
# Initializes a new Client object
|
8
|
+
def initialize(api_key:)
|
9
|
+
@api_path = ENV.fetch('WT_API_CONNECTION_PATH') { '' }
|
10
|
+
@api_key = api_key
|
11
|
+
@api_bearer_token ||= request_jwt
|
12
|
+
@api_connection ||= WeTransfer::Connection.new(client: self, api_bearer_token: @api_bearer_token)
|
13
|
+
end
|
14
|
+
|
15
|
+
def request_jwt
|
16
|
+
# Create a connection request without a bearer token for authorization
|
17
|
+
# since authorization is what you need to do to retrieve the token.
|
18
|
+
auth_connection = WeTransfer::Connection.new(client: self)
|
19
|
+
auth_connection.authorization_request
|
20
|
+
end
|
21
|
+
|
22
|
+
# If you pass in items to the transfer it'll create the transfer with them,
|
23
|
+
# otherwise it creates a "blank" transfer object. You can also leave off the
|
24
|
+
# name and description, and it will be auto-generated.
|
25
|
+
def create_transfer(name: nil, description: nil, items: [])
|
26
|
+
raise ArgumentError, 'The items field must be an array' unless items.is_a?(Array)
|
27
|
+
@transfer = build_transfer_object(name, description).transfer
|
28
|
+
items.any? ? create_transfer_with_items(items: items) : create_initial_transfer
|
29
|
+
@transfer
|
30
|
+
end
|
31
|
+
|
32
|
+
# Once you've created a "blank" transfer you can use this to add items to it.
|
33
|
+
# Items must have the structure defined in the README, otherwise information will be auto-generated for them.
|
34
|
+
def add_items(transfer:, items:)
|
35
|
+
@transfer ||= transfer
|
36
|
+
create_transfer_items(items: items)
|
37
|
+
send_items_to_transfer
|
38
|
+
upload_and_complete_items
|
39
|
+
@transfer
|
40
|
+
end
|
41
|
+
|
42
|
+
def create_transfer_with_items(items: [])
|
43
|
+
raise ArgumentError, 'Items array cannot be empty' if items.empty?
|
44
|
+
create_transfer_items(items: items)
|
45
|
+
create_initial_transfer
|
46
|
+
upload_and_complete_items
|
47
|
+
end
|
48
|
+
|
49
|
+
private
|
50
|
+
|
51
|
+
def build_transfer_object(name, description)
|
52
|
+
transfer_builder = TransferBuilder.new
|
53
|
+
transfer_builder.name_description(name: name, description: description)
|
54
|
+
transfer_builder
|
55
|
+
end
|
56
|
+
|
57
|
+
def create_transfer_items(items:)
|
58
|
+
items.each do |item|
|
59
|
+
item_builder = ItemBuilder.new
|
60
|
+
item_builder.path(path: item)
|
61
|
+
item_builder.content_identifier
|
62
|
+
item_builder.local_identifier
|
63
|
+
item_builder.name
|
64
|
+
item_builder.size
|
65
|
+
@transfer.items.push(item_builder.item)
|
66
|
+
end
|
67
|
+
end
|
68
|
+
|
69
|
+
def create_initial_transfer
|
70
|
+
response = @api_connection.post_request(path: '/transfers', body: @transfer.transfer_params)
|
71
|
+
TransferBuilder.id(transfer: @transfer, id: response['id'])
|
72
|
+
TransferBuilder.shortened_url(transfer: @transfer, url: response['shortened_url'])
|
73
|
+
update_item_objects(response_items: response['items']) if response['items'].any?
|
74
|
+
end
|
75
|
+
|
76
|
+
def send_items_to_transfer
|
77
|
+
response = @api_connection.post_request(path: "/transfers/#{@transfer.id}/items", body: {items: @transfer.items_params})
|
78
|
+
update_item_objects(response_items: response)
|
79
|
+
end
|
80
|
+
|
81
|
+
def update_item_objects(response_items:)
|
82
|
+
response_items.each do |item|
|
83
|
+
item_object = @transfer.items.select { |t| t.name == item['name'] }.first
|
84
|
+
item_builder = ItemBuilder.new(item: item_object)
|
85
|
+
item_builder.id(item: item_object, id: item['id'])
|
86
|
+
item_builder.upload_url(item: item_object, url: item['upload_url'])
|
87
|
+
item_builder.multipart_parts(item: item_object, part_count: item['meta']['multipart_parts'])
|
88
|
+
item_builder.multipart_id(item: item_object, multi_id: item['meta']['multipart_upload_id'])
|
89
|
+
item_builder.upload_id(item: item_object, upload_id: item['upload_id'])
|
90
|
+
add_item_upload_url(item: item_builder.item) if item_builder.item.multipart_parts > 1
|
91
|
+
end
|
92
|
+
end
|
93
|
+
|
94
|
+
def add_item_upload_url(item:)
|
95
|
+
upload_urls = []
|
96
|
+
item.multipart_parts.times do |part|
|
97
|
+
part += 1
|
98
|
+
response = @api_connection.get_request(path: "/files/#{item.id}/uploads/#{part}/#{item.multipart_id}")
|
99
|
+
upload_urls << response['upload_url']
|
100
|
+
end
|
101
|
+
item.upload_url = upload_urls
|
102
|
+
end
|
103
|
+
|
104
|
+
def upload_and_complete_items
|
105
|
+
upload_files
|
106
|
+
complete_transfer
|
107
|
+
end
|
108
|
+
|
109
|
+
def upload_files
|
110
|
+
@transfer.items.each do |item|
|
111
|
+
file_object = File.open(item.path)
|
112
|
+
item.upload_url.each do |url|
|
113
|
+
chunk = file_object.read(CHUNK_SIZE)
|
114
|
+
@api_connection.upload(file: chunk, url: url)
|
115
|
+
end
|
116
|
+
file_object.close
|
117
|
+
end
|
118
|
+
end
|
119
|
+
|
120
|
+
def complete_transfer
|
121
|
+
@transfer.items.each do |item|
|
122
|
+
@api_connection.post_request(path: "/files/#{item.id}/uploads/complete")
|
123
|
+
end
|
124
|
+
end
|
125
|
+
end
|
126
|
+
end
|
@@ -0,0 +1,77 @@
|
|
1
|
+
module WeTransfer
|
2
|
+
class Connection
|
3
|
+
class ApiRequestError < StandardError; end
|
4
|
+
|
5
|
+
attr_reader :api_connection, :api_bearer_token, :api_key, :api_path
|
6
|
+
|
7
|
+
def initialize(client:, api_bearer_token: '')
|
8
|
+
@api_url = ENV.fetch('WT_API_URL') { 'https://dev.wetransfer.com' }
|
9
|
+
@api_key = client.api_key
|
10
|
+
@api_connection ||= create_api_connection_object!
|
11
|
+
@api_bearer_token = api_bearer_token
|
12
|
+
@api_path = ENV.fetch('WT_API_CONNECTION_PATH') { '' }
|
13
|
+
end
|
14
|
+
|
15
|
+
def authorization_request
|
16
|
+
response = @api_connection.post do |req|
|
17
|
+
req.url("#{@api_path}/authorize")
|
18
|
+
request_header_params(req: req)
|
19
|
+
end
|
20
|
+
response_validation!(response: response)
|
21
|
+
response['token']
|
22
|
+
end
|
23
|
+
|
24
|
+
def post_request(path:, body: nil)
|
25
|
+
response = @api_connection.post do |req|
|
26
|
+
req.url(@api_path + path)
|
27
|
+
request_header_params(req: req)
|
28
|
+
req.body = body.to_json unless body.nil?
|
29
|
+
end
|
30
|
+
response_validation!(response: response)
|
31
|
+
JSON.parse(response.body)
|
32
|
+
end
|
33
|
+
|
34
|
+
def get_request(path:)
|
35
|
+
response = @api_connection.get do |req|
|
36
|
+
req.url(@api_path + path)
|
37
|
+
request_header_params(req: req)
|
38
|
+
end
|
39
|
+
response_validation!(response: response)
|
40
|
+
JSON.parse(response.body)
|
41
|
+
end
|
42
|
+
|
43
|
+
def upload(file:, url:)
|
44
|
+
conn = Faraday.new(url: url) do |faraday|
|
45
|
+
faraday.request :multipart
|
46
|
+
faraday.adapter :net_http
|
47
|
+
end
|
48
|
+
resp = conn.put do |req|
|
49
|
+
req.headers['Content-Length'] = file.size.to_s
|
50
|
+
req.body = file
|
51
|
+
end
|
52
|
+
response_validation!(response: resp)
|
53
|
+
end
|
54
|
+
|
55
|
+
private
|
56
|
+
|
57
|
+
def request_header_params(req:)
|
58
|
+
req.headers['X-API-Key'] = @api_key
|
59
|
+
req.headers['Authorization'] = 'Bearer ' + @api_bearer_token unless @api_bearer_token.nil?
|
60
|
+
req.headers['Content-Type'] = 'application/json'
|
61
|
+
end
|
62
|
+
|
63
|
+
# If you need extra logging for your requests, switch it on by setting WT_API_LOGGING_ON in your .env file.
|
64
|
+
def create_api_connection_object!
|
65
|
+
conn = Faraday.new(url: @api_url) do |faraday|
|
66
|
+
faraday.response :logger if ENV.fetch('WT_API_LOGGING_ON') { nil } # log requests to STDOUT if ENVVAR is present
|
67
|
+
faraday.adapter Faraday.default_adapter # make requests with Net::HTTP
|
68
|
+
end
|
69
|
+
conn
|
70
|
+
end
|
71
|
+
|
72
|
+
def response_validation!(response:)
|
73
|
+
raise ApiRequestError, response.reason_phrase if response.status == 401
|
74
|
+
raise ApiRequestError, response.reason_phrase if response.status == 403
|
75
|
+
end
|
76
|
+
end
|
77
|
+
end
|
@@ -0,0 +1,59 @@
|
|
1
|
+
module WeTransfer
|
2
|
+
class ItemBuilder
|
3
|
+
class FileDoesNotExistError < ArgumentError; end
|
4
|
+
attr_reader :item
|
5
|
+
|
6
|
+
def initialize(item: nil)
|
7
|
+
@item = if item.nil?
|
8
|
+
Item.new
|
9
|
+
else
|
10
|
+
item
|
11
|
+
end
|
12
|
+
end
|
13
|
+
|
14
|
+
def path(path:)
|
15
|
+
@item.path = path
|
16
|
+
end
|
17
|
+
|
18
|
+
def content_identifier
|
19
|
+
@item.content_identifier = 'file'
|
20
|
+
end
|
21
|
+
|
22
|
+
def local_identifier
|
23
|
+
# only take the file name and shorten it to 36 characters if it's longer
|
24
|
+
@item.local_identifier = @item.path.split('/').last.gsub(' ', '')[0..35]
|
25
|
+
end
|
26
|
+
|
27
|
+
def name
|
28
|
+
@item.name = @item.path.split('/').last
|
29
|
+
end
|
30
|
+
|
31
|
+
def size
|
32
|
+
@item.size = File.size(@item.path)
|
33
|
+
end
|
34
|
+
|
35
|
+
def id(item:, id:)
|
36
|
+
item.id = id
|
37
|
+
end
|
38
|
+
|
39
|
+
def upload_url(item:, url:)
|
40
|
+
item.upload_url = [url]
|
41
|
+
end
|
42
|
+
|
43
|
+
def multipart_parts(item:, part_count:)
|
44
|
+
item.multipart_parts = part_count
|
45
|
+
end
|
46
|
+
|
47
|
+
def multipart_id(item:, multi_id:)
|
48
|
+
item.multipart_id = multi_id
|
49
|
+
end
|
50
|
+
|
51
|
+
def upload_id(item:, upload_id:)
|
52
|
+
item.upload_id = upload_id
|
53
|
+
end
|
54
|
+
|
55
|
+
def validate_file
|
56
|
+
raise FileDoesNotExistError, "#{@item} does not exist" unless File.exist?(@item.path)
|
57
|
+
end
|
58
|
+
end
|
59
|
+
end
|
@@ -0,0 +1,30 @@
|
|
1
|
+
module WeTransfer
|
2
|
+
class Transfer
|
3
|
+
attr_accessor :id, :name, :description, :shortened_url, :items
|
4
|
+
|
5
|
+
def initialize
|
6
|
+
@items = []
|
7
|
+
end
|
8
|
+
|
9
|
+
def transfer_params
|
10
|
+
{
|
11
|
+
name: name,
|
12
|
+
description: description,
|
13
|
+
items: items_params
|
14
|
+
}
|
15
|
+
end
|
16
|
+
|
17
|
+
def items_params
|
18
|
+
transfer_items = []
|
19
|
+
items.each do |item|
|
20
|
+
transfer_items << {
|
21
|
+
local_identifier: item.local_identifier,
|
22
|
+
content_identifier: item.content_identifier,
|
23
|
+
filename: item.name,
|
24
|
+
filesize: item.size
|
25
|
+
}
|
26
|
+
end
|
27
|
+
transfer_items
|
28
|
+
end
|
29
|
+
end
|
30
|
+
end
|
@@ -0,0 +1,28 @@
|
|
1
|
+
module WeTransfer
|
2
|
+
class TransferBuilder
|
3
|
+
def initialize(transfer: nil)
|
4
|
+
@transfer = if transfer.nil?
|
5
|
+
Transfer.new
|
6
|
+
else
|
7
|
+
transfer
|
8
|
+
end
|
9
|
+
end
|
10
|
+
|
11
|
+
def name_description(name: nil, description: nil)
|
12
|
+
@transfer.name = name || "File Transfer: #{Time.now.strftime('%d-%m-%Y')}"
|
13
|
+
@transfer.description = description || 'Transfer generated with WeTransfer Ruby SDK'
|
14
|
+
end
|
15
|
+
|
16
|
+
def self.id(transfer:, id:)
|
17
|
+
transfer.id = id
|
18
|
+
end
|
19
|
+
|
20
|
+
def self.shortened_url(transfer:, url:)
|
21
|
+
transfer.shortened_url = url
|
22
|
+
end
|
23
|
+
|
24
|
+
def transfer
|
25
|
+
@transfer
|
26
|
+
end
|
27
|
+
end
|
28
|
+
end
|
data/spec/client_spec.rb
ADDED
@@ -0,0 +1,82 @@
|
|
1
|
+
require 'spec_helper'
|
2
|
+
|
3
|
+
describe WeTransfer::Client do
|
4
|
+
describe 'Client#new' do
|
5
|
+
it 'returns a error when no api_key is given' do
|
6
|
+
expect {
|
7
|
+
described_class.new
|
8
|
+
}.to raise_error(ArgumentError, /missing keyword: api_key/)
|
9
|
+
end
|
10
|
+
|
11
|
+
it 'on initialization a active connection object is created' do
|
12
|
+
client = described_class.new(api_key: 'api-key')
|
13
|
+
expect(client.api_connection).to be_kind_of WeTransfer::Connection
|
14
|
+
end
|
15
|
+
end
|
16
|
+
|
17
|
+
describe 'Client#create_transfer' do
|
18
|
+
let(:client) { described_class.new(api_key: 'api-key') }
|
19
|
+
|
20
|
+
it 'create transfer should return a transfer object' do
|
21
|
+
transfer = client.create_transfer
|
22
|
+
expect(transfer.shortened_url).to start_with('http://we.tl/s-')
|
23
|
+
expect(transfer).to be_kind_of WeTransfer::Transfer
|
24
|
+
end
|
25
|
+
|
26
|
+
it 'when no name/description is send, a default name/description is generated' do
|
27
|
+
transfer = client.create_transfer
|
28
|
+
expect(transfer.name).to eq("File Transfer: #{Time.now.strftime('%d-%m-%Y')}")
|
29
|
+
expect(transfer.description).to eq('Transfer generated with WeTransfer Ruby SDK')
|
30
|
+
end
|
31
|
+
|
32
|
+
it 'when a name/description is send, transfer has that name/description' do
|
33
|
+
transfer = client.create_transfer(
|
34
|
+
name: 'WeTransfer Test Transfer',
|
35
|
+
description: "Moving along… Good news, everyone! I've
|
36
|
+
taught the toaster to feel love! Humans dating robots is
|
37
|
+
sick. You people wonder why I'm still single? It's 'cause
|
38
|
+
all the fine robot sisters are dating humans!")
|
39
|
+
expect(transfer.name).to eq('WeTransfer Test Transfer')
|
40
|
+
expect(transfer.description).to start_with('Moving along… Good news, everyone!')
|
41
|
+
end
|
42
|
+
|
43
|
+
it 'when no items are send, a itemless transfer is created' do
|
44
|
+
transfer = client.create_transfer
|
45
|
+
expect(transfer.items).to be_empty
|
46
|
+
end
|
47
|
+
|
48
|
+
it 'when items are sended, the transfer has items' do
|
49
|
+
transfer = client.create_transfer(items: ["#{__dir__}/fixtures/war-and-peace.txt"])
|
50
|
+
expect(transfer).to be_kind_of WeTransfer::Transfer
|
51
|
+
expect(transfer.items.count).to eq(1)
|
52
|
+
end
|
53
|
+
|
54
|
+
it 'returns an error when items are not sended inside an array' do
|
55
|
+
expect {
|
56
|
+
client.create_transfer(items: "#{__dir__}/war-end-peace.txt")
|
57
|
+
}.to raise_error(StandardError, 'The items field must be an array')
|
58
|
+
end
|
59
|
+
|
60
|
+
it 'completes a item after item upload' do
|
61
|
+
transfer = client.create_transfer(items: ["#{__dir__}/fixtures/war-and-peace.txt"])
|
62
|
+
expect(transfer).to be_kind_of WeTransfer::Transfer
|
63
|
+
end
|
64
|
+
end
|
65
|
+
|
66
|
+
describe 'Client#add_item' do
|
67
|
+
let(:client) { described_class.new(api_key: 'api-key') }
|
68
|
+
|
69
|
+
it 'add items to an already created transfer' do
|
70
|
+
transfer = client.create_transfer
|
71
|
+
expect(transfer.items.count).to eq(0)
|
72
|
+
transfer = client.add_items(transfer: transfer, items: ["#{__dir__}/fixtures/war-and-peace.txt"])
|
73
|
+
expect(transfer.items.count).to eq(1)
|
74
|
+
end
|
75
|
+
|
76
|
+
it 'raises an error when no transfer is being send to add_items_to_transfer method' do
|
77
|
+
expect {
|
78
|
+
client.add_items(items: ["#{__dir__}/fixtures/war-and-peace.txt"])
|
79
|
+
}.to raise_error(ArgumentError, 'missing keyword: transfer')
|
80
|
+
end
|
81
|
+
end
|
82
|
+
end
|
@@ -0,0 +1,74 @@
|
|
1
|
+
require 'spec_helper'
|
2
|
+
|
3
|
+
describe WeTransfer::Connection do
|
4
|
+
describe 'Connection#new' do
|
5
|
+
it 'creates a new connection when the client is passed' do
|
6
|
+
client = OpenStruct.new(api_key: 'api-key-12345')
|
7
|
+
connection = described_class.new(client: client)
|
8
|
+
expect(connection.api_connection).to be_kind_of Faraday::Connection
|
9
|
+
end
|
10
|
+
|
11
|
+
it 'contains the api_key inside the connection' do
|
12
|
+
client = OpenStruct.new(api_key: 'api-key-12345')
|
13
|
+
connection = described_class.new(client: client)
|
14
|
+
expect(connection.api_key).to eq(client.api_key)
|
15
|
+
end
|
16
|
+
|
17
|
+
it 'correctly handles the connection path variable' do
|
18
|
+
ENV['WT_API_CONNECTION_PATH'] = '/this_path_does_not_exist'
|
19
|
+
client = OpenStruct.new(api_key: 'api-key-12345')
|
20
|
+
connection = described_class.new(client: client)
|
21
|
+
expect(connection.api_path).to eq('/this_path_does_not_exist')
|
22
|
+
ENV['WT_API_CONNECTION_PATH'] = '/v1'
|
23
|
+
connection = described_class.new(client: client)
|
24
|
+
expect(connection.api_path).to eq('/v1')
|
25
|
+
end
|
26
|
+
end
|
27
|
+
|
28
|
+
describe 'Connection#post_request' do
|
29
|
+
it 'returns with a response body when a post request is made' do
|
30
|
+
client = OpenStruct.new(api_key: 'api-key-12345')
|
31
|
+
connection = described_class.new(client: client)
|
32
|
+
response = connection.post_request(path: '/authorize')
|
33
|
+
expect(response['status']).to eq('success')
|
34
|
+
end
|
35
|
+
|
36
|
+
it 'returns with a response body when a post request is made' do
|
37
|
+
client = OpenStruct.new(api_key: 'api-key-12345')
|
38
|
+
connection = described_class.new(client: client)
|
39
|
+
response = connection.post_request(path: '/transfers', body: {name: 'test_transfer', description: 'this is a test transfer', items: []})
|
40
|
+
expect(response['shortened_url']).to start_with('http://we.tl/s-')
|
41
|
+
expect(response['name']).to eq('test_transfer')
|
42
|
+
expect(response['description']).to eq('this is a test transfer')
|
43
|
+
expect(response['items'].count).to eq(0)
|
44
|
+
end
|
45
|
+
|
46
|
+
it 'returns with a ApiRequestError when request is forbidden' do
|
47
|
+
client = OpenStruct.new(api_key: 'api-key-12345')
|
48
|
+
connection = described_class.new(client: client)
|
49
|
+
expect {
|
50
|
+
connection.post_request(path: '/forbidden')
|
51
|
+
}.to raise_error(WeTransfer::Connection::ApiRequestError, 'Forbidden')
|
52
|
+
end
|
53
|
+
end
|
54
|
+
|
55
|
+
describe 'Connection#get_request' do
|
56
|
+
it 'returns with a response body when a get request is made for upload urls' do
|
57
|
+
client = OpenStruct.new(api_key: 'api-key-12345')
|
58
|
+
connection = described_class.new(client: client)
|
59
|
+
response = connection.get_request(path: '/files/1337/uploads/1/7331')
|
60
|
+
expect(response['upload_url']).to include('upload')
|
61
|
+
expect(response['part_number']).to eq(1)
|
62
|
+
expect(response['upload_id']).to_not be_nil
|
63
|
+
expect(response['upload_expires_at']).to_not be_nil
|
64
|
+
end
|
65
|
+
|
66
|
+
it 'returns with a ApiRequestError when request is forbidden' do
|
67
|
+
client = OpenStruct.new(api_key: 'api-key-12345')
|
68
|
+
connection = described_class.new(client: client)
|
69
|
+
expect {
|
70
|
+
connection.get_request(path: '/forbidden')
|
71
|
+
}.to raise_error(WeTransfer::Connection::ApiRequestError, 'Forbidden')
|
72
|
+
end
|
73
|
+
end
|
74
|
+
end
|