wetransfer 0.1.0
Sign up to get free protection for your applications and to get access to all the features.
- 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
|