itrp-client 1.1.2 → 1.1.3

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 CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA1:
3
- metadata.gz: a3f55cdbfd736e209d4e107fd750fecb819d34bb
4
- data.tar.gz: 4b883ab29f9afb6b1fa055c95645fe43384d3c9f
3
+ metadata.gz: de6fdad59c1fdf0bc47384448260e98b2434f323
4
+ data.tar.gz: 976f89ddc9f004e7c716c0e3bbe7eea7fc8df4b9
5
5
  SHA512:
6
- metadata.gz: c53088678d9bdb63533a8380a83440adc2e10231719539af9415fd8944a882fb53e6ce0d4909b2cba7cc95b10ef7a95aab91a1fc3d64aafa76c33b83b8b4ed0f
7
- data.tar.gz: ea7aa517b1cf619bc4e6118e16b8e7a2949cc95b78109f5972c799be79127601ad4a230a47362803536c7aa6b544c395c73a3bcb28e64ca34b2c9b01a5a12cf1
6
+ metadata.gz: d4a0ca0784ddb94126cfc2bd76b8ca86c85933d3eecb7603ab177141827345771541d44014c9a78df293a0f3903e83ab2a76ca4ba576b43c24431dc65c38a88f
7
+ data.tar.gz: 806497d4dda808649e0d99d239c8eed4896367668465f5eec71b7a87d3a5aa51201cc4061379395b87e326351d5e53739a76be19d18c6abe468457af6acbe2b3
@@ -1,7 +1,7 @@
1
1
  PATH
2
2
  remote: .
3
3
  specs:
4
- itrp-client (1.1.1)
4
+ itrp-client (1.0.13)
5
5
  activesupport
6
6
  gem_config
7
7
  mime-types
@@ -9,28 +9,26 @@ PATH
9
9
  GEM
10
10
  remote: https://rubygems.org/
11
11
  specs:
12
- activesupport (4.2.7.1)
12
+ activesupport (4.2.5.1)
13
13
  i18n (~> 0.7)
14
14
  json (~> 1.7, >= 1.7.7)
15
15
  minitest (~> 5.1)
16
16
  thread_safe (~> 0.3, >= 0.3.4)
17
17
  tzinfo (~> 1.1)
18
- addressable (2.5.0)
19
- public_suffix (~> 2.0, >= 2.0.2)
18
+ addressable (2.4.0)
20
19
  crack (0.4.3)
21
20
  safe_yaml (~> 1.0.0)
22
21
  diff-lcs (1.2.5)
23
22
  docile (1.1.5)
24
23
  gem_config (0.3.1)
25
- hashdiff (0.3.1)
24
+ hashdiff (0.2.3)
26
25
  i18n (0.7.0)
27
26
  json (1.8.3)
28
- mime-types (3.1)
27
+ mime-types (3.0)
29
28
  mime-types-data (~> 3.2015)
30
- mime-types-data (3.2016.0521)
31
- minitest (5.9.1)
32
- public_suffix (2.0.4)
33
- rake (11.3.0)
29
+ mime-types-data (3.2015.1120)
30
+ minitest (5.8.4)
31
+ rake (10.5.0)
34
32
  rspec (3.3.0)
35
33
  rspec-core (~> 3.3.0)
36
34
  rspec-expectations (~> 3.3.0)
@@ -45,15 +43,15 @@ GEM
45
43
  rspec-support (~> 3.3.0)
46
44
  rspec-support (3.3.0)
47
45
  safe_yaml (1.0.4)
48
- simplecov (0.12.0)
46
+ simplecov (0.11.1)
49
47
  docile (~> 1.1.0)
50
- json (>= 1.8, < 3)
48
+ json (~> 1.8)
51
49
  simplecov-html (~> 0.10.0)
52
50
  simplecov-html (0.10.0)
53
51
  thread_safe (0.3.5)
54
52
  tzinfo (1.2.2)
55
53
  thread_safe (~> 0.1)
56
- webmock (2.1.0)
54
+ webmock (1.22.6)
57
55
  addressable (>= 2.3.6)
58
56
  crack (>= 0.3.2)
59
57
  hashdiff
@@ -67,7 +65,7 @@ DEPENDENCIES
67
65
  rake
68
66
  rspec (~> 3.3.0)
69
67
  simplecov
70
- webmock (~> 2)
68
+ webmock
71
69
 
72
70
  BUNDLED WITH
73
- 1.11.2
71
+ 1.10.6
@@ -14,12 +14,12 @@ module Itrp
14
14
  has :account, classes: String
15
15
  has :source, classes: String
16
16
 
17
- has :max_retry_time, classes: Fixnum, default: 5400
18
- has :read_timeout, classes: Fixnum, default: 25
17
+ has :max_retry_time, classes: Integer, default: 5400
18
+ has :read_timeout, classes: Integer, default: 25
19
19
  has :block_at_rate_limit, classes: [TrueClass, FalseClass], default: false
20
20
 
21
21
  has :proxy_host, classes: String
22
- has :proxy_port, classes: Fixnum, default: 8080
22
+ has :proxy_port, classes: Integer, default: 8080
23
23
  has :proxy_user, classes: String
24
24
  has :proxy_password, classes: String
25
25
 
@@ -34,4 +34,4 @@ module Itrp
34
34
 
35
35
  class UploadFailed < Exception; end # ::Itrp::UploadFailed class
36
36
 
37
- end
37
+ end
@@ -1,5 +1,5 @@
1
1
  module Itrp
2
2
  class Client
3
- VERSION = '1.1.2'
3
+ VERSION = '1.1.3'
4
4
  end
5
5
  end
metadata CHANGED
@@ -1,14 +1,14 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: itrp-client
3
3
  version: !ruby/object:Gem::Version
4
- version: 1.1.2
4
+ version: 1.1.3
5
5
  platform: ruby
6
6
  authors:
7
7
  - ITRP
8
8
  autorequire:
9
9
  bindir: bin
10
10
  cert_chain: []
11
- date: 2017-03-16 00:00:00.000000000 Z
11
+ date: 2018-02-19 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: gem_config
@@ -140,16 +140,6 @@ files:
140
140
  - lib/itrp/client/multipart.rb
141
141
  - lib/itrp/client/response.rb
142
142
  - lib/itrp/client/version.rb
143
- - spec/lib/itrp/attachments_spec.rb
144
- - spec/lib/itrp/certificate_spec.rb
145
- - spec/lib/itrp/client_spec.rb
146
- - spec/lib/itrp/response_spec.rb
147
- - spec/lib/itrp_spec.rb
148
- - spec/spec_helper.rb
149
- - spec/support/fixtures/people.csv
150
- - spec/support/fixtures/upload.txt
151
- - spec/support/matchers/never_raise.rb
152
- - spec/support/util.rb
153
143
  homepage: http://github.com/itrp/itrp-client
154
144
  licenses:
155
145
  - MIT
@@ -171,18 +161,9 @@ required_rubygems_version: !ruby/object:Gem::Requirement
171
161
  version: '0'
172
162
  requirements: []
173
163
  rubyforge_project:
174
- rubygems_version: 2.2.2
164
+ rubygems_version: 2.5.2.1
175
165
  signing_key:
176
166
  specification_version: 4
177
167
  summary: Client for accessing the ITRP REST API
178
- test_files:
179
- - spec/lib/itrp/attachments_spec.rb
180
- - spec/lib/itrp/certificate_spec.rb
181
- - spec/lib/itrp/client_spec.rb
182
- - spec/lib/itrp/response_spec.rb
183
- - spec/lib/itrp_spec.rb
184
- - spec/spec_helper.rb
185
- - spec/support/fixtures/people.csv
186
- - spec/support/fixtures/upload.txt
187
- - spec/support/matchers/never_raise.rb
188
- - spec/support/util.rb
168
+ test_files: []
169
+ has_rdoc:
@@ -1,178 +0,0 @@
1
- require 'spec_helper'
2
-
3
- describe Itrp::Attachments do
4
-
5
- before(:each) do
6
- @client = Itrp::Client.new(api_token: 'secret', max_retry_time: -1)
7
- @attachments = Itrp::Attachments.new(@client)
8
- end
9
-
10
- context 'upload_attachments!' do
11
- it 'should not do anything when no :attachments are present' do
12
- expect(@attachments.upload_attachments!('/requests', {status: :in_progress})).to be_nil
13
- end
14
-
15
- it 'should not do anything when :attachments is nil' do
16
- expect(@attachments.upload_attachments!('/requests', {attachments: nil})).to be_nil
17
- end
18
-
19
- it 'should not do anything when :attachments is empty' do
20
- expect(@attachments.upload_attachments!('/requests', {attachments: []})).to be_nil
21
- expect(@attachments.upload_attachments!('/requests', {attachments: [nil]})).to be_nil
22
- end
23
-
24
- it 'should show a error if no attachment may be uploaded' do
25
- stub_request(:get, 'https://api.itrp.com/v1/sites/1?attachment_upload_token=true').with(basic_auth: ['secret', 'x']).to_return(body: {name: 'site 1'}.to_json)
26
- expect_log('Attachments not allowed for /sites/1', :error)
27
- expect(@attachments.upload_attachments!('/sites/1', {attachments: ['file1.png']})).to be_nil
28
- end
29
-
30
- it 'should raise an exception if no attachment may be uploaded' do
31
- stub_request(:get, 'https://api.itrp.com/v1/sites/1?attachment_upload_token=true').with(basic_auth: ['secret', 'x']).to_return(body: {name: 'site 1'}.to_json)
32
- message = 'Attachments not allowed for /sites/1'
33
- expect{ @attachments.upload_attachments!('/sites/1', {attachments: ['file1.png'], attachments_exception: true}) }.to raise_error(::Itrp::UploadFailed, message)
34
- end
35
-
36
- it 'should add /new to the path for new records' do
37
- stub_request(:get, 'https://api.itrp.com/v1/sites/new?attachment_upload_token=true').with(basic_auth: ['secret', 'x']).to_return(body: {missing: 'storage'}.to_json)
38
- expect_log('Attachments not allowed for /sites', :error)
39
- expect(@attachments.upload_attachments!('/sites', {attachments: ['file1.png']})).to be_nil
40
- end
41
-
42
- [ [:requests, :note],
43
- [:problems, :note],
44
- [:contracts, :remarks],
45
- [:cis, :remarks],
46
- [:flsas, :remarks],
47
- [:slas, :remarks],
48
- [:service_instances, :remarks],
49
- [:service_offerings, :summary],
50
- [:any_other_model, :note]].each do |model, attribute|
51
-
52
- it "should replace :attachments with :#{attribute}_attachments after upload at /#{model}" do
53
- stub_request(:get, "https://api.itrp.com/v1/#{model}/new?attachment_upload_token=true").with(basic_auth: ['secret', 'x']).to_return(body: {storage_upload: 'conf'}.to_json)
54
- expect(@attachments).to receive(:upload_attachment).with('conf', 'file1.png', false).ordered{ 'uploaded file1.png' }
55
- expect(@attachments).to receive(:upload_attachment).with('conf', 'file2.zip', false).ordered{ 'uploaded file2.zip' }
56
- data = {leave: 'me alone', attachments: %w(file1.png file2.zip)}
57
- @attachments.upload_attachments!("/#{model}", data)
58
- expect(data[:attachments]).to be_nil
59
- expect(data[:leave]).to eq('me alone')
60
- expect(data[:"#{attribute}_attachments"]).to eq(['uploaded file1.png', 'uploaded file2.zip'].to_json)
61
- end
62
- end
63
-
64
- it 'should set raise_exception flag to true when :attachments_exception is set' do
65
- stub_request(:get, 'https://api.itrp.com/v1/requests/new?attachment_upload_token=true').with(basic_auth: ['secret', 'x']).to_return(body: {storage_upload: 'conf'}.to_json)
66
- expect(@attachments).to receive(:upload_attachment).with('conf', 'file1.png', true).ordered{ 'uploaded file1.png' }
67
- data = {leave: 'me alone', attachments: 'file1.png', attachments_exception: true}
68
- @attachments.upload_attachments!('/requests', data)
69
- expect(data[:attachments]).to be_nil
70
- expect(data[:attachments_exception]).to be_nil
71
- expect(data[:leave]).to eq('me alone')
72
- expect(data[:note_attachments]).to eq(['uploaded file1.png'].to_json)
73
- end
74
- end
75
-
76
- context 'upload_attachment' do
77
-
78
- it 'should log an exception when the file could not be found' do
79
- expect_log('Attachment upload failed: file does not exist: unknown_file', :error)
80
- expect(@attachments.send(:upload_attachment, nil, 'unknown_file', false)).to be_nil
81
- end
82
-
83
- it 'should raise an exception when the file could not be found' do
84
- message = 'Attachment upload failed: file does not exist: unknown_file'
85
- expect{ @attachments.send(:upload_attachment, nil, 'unknown_file', true) }.to raise_error(::Itrp::UploadFailed, message)
86
- end
87
-
88
- context 'aws' do
89
- before(:each) do
90
- @aws_conf = {
91
- provider: 'aws',
92
- upload_uri: 'https://itrp.s3.amazonaws.com/',
93
- access_key: "AKIA6RYQ",
94
- success_url: "https://mycompany.itrp.com/s3_success?sig=99e82e8a046",
95
- policy: "eydlgIH0=",
96
- signature: 'nbhdec4k=',
97
- upload_path: 'attachments/5/reqs/000/070/451/zxxb4ot60xfd6sjg/'
98
- }
99
- @key_template = 'attachments/5/reqs/000/070/451/zxxb4ot60xfd6sjg/${filename}'
100
- @key = 'attachments/5/reqs/000/070/451/zxxb4ot60xfd6sjg/upload.txt'
101
-
102
- @multi_part_body = "--0123456789ABLEWASIEREISAWELBA9876543210\r\nContent-Disposition: form-data; name=\"Content-Type\"\r\n\r\napplication/octet-stream\r\n--0123456789ABLEWASIEREISAWELBA9876543210\r\nContent-Disposition: form-data; name=\"x-amz-server-side-encryption\"\r\n\r\nAES256\r\n--0123456789ABLEWASIEREISAWELBA9876543210\r\nContent-Disposition: form-data; name=\"key\"\r\n\r\nattachments/5/reqs/000/070/451/zxxb4ot60xfd6sjg/${filename}\r\n--0123456789ABLEWASIEREISAWELBA9876543210\r\nContent-Disposition: form-data; name=\"AWSAccessKeyId\"\r\n\r\nAKIA6RYQ\r\n--0123456789ABLEWASIEREISAWELBA9876543210\r\nContent-Disposition: form-data; name=\"acl\"\r\n\r\nprivate\r\n--0123456789ABLEWASIEREISAWELBA9876543210\r\nContent-Disposition: form-data; name=\"signature\"\r\n\r\nnbhdec4k=\r\n--0123456789ABLEWASIEREISAWELBA9876543210\r\nContent-Disposition: form-data; name=\"success_action_status\"\r\n\r\n201\r\n--0123456789ABLEWASIEREISAWELBA9876543210\r\nContent-Disposition: form-data; name=\"policy\"\r\n\r\neydlgIH0=\r\n--0123456789ABLEWASIEREISAWELBA9876543210\r\nContent-Disposition: form-data; name=\"file\"; filename=\"#{@fixture_dir}/upload.txt\"\r\nContent-Type: text/plain\r\n\r\ncontent\r\n--0123456789ABLEWASIEREISAWELBA9876543210--"
103
- @multi_part_headers = {'Accept'=>'*/*', 'Content-Type'=>'multipart/form-data; boundary=0123456789ABLEWASIEREISAWELBA9876543210', 'User-Agent'=>'Mozilla/5.0 (Macintosh; U; PPC Mac OS X; en-us) AppleWebKit/523.10.6 (KHTML, like Gecko) Version/3.0.4 Safari/523.10.6'}
104
- end
105
-
106
- it 'should open a file from disk' do
107
- expect(@attachments).to receive(:aws_upload).with(@aws_conf, @key_template, @key, kind_of(File))
108
- expect(@attachments.send(:upload_attachment, @aws_conf, "#{@fixture_dir}/upload.txt", false)).to eq({key: @key, filesize: 7})
109
- end
110
-
111
- it 'should sent the upload to AWS' do
112
- stub_request(:post, 'https://itrp.s3.amazonaws.com/').with(body: @multi_part_body, headers: @multi_part_headers).to_return(body: 'OK', status: 303, headers: {'Location' => 'https://mycompany.itrp.com/s3_success?sig=99e82e8a046'})
113
- stub_request(:get, "https://api.itrp.com/v1/s3_success?sig=99e82e8a046&key=#{@key}").with(basic_auth: ['secret', 'x']).to_return(body: {}.to_json)
114
- expect(@attachments.send(:upload_attachment, @aws_conf, "#{@fixture_dir}/upload.txt", false)).to eq({key: @key, filesize: 7})
115
- end
116
-
117
- it 'should report an error when AWS upload fails' do
118
- stub_request(:post, 'https://itrp.s3.amazonaws.com/').with(body: @multi_part_body, headers: @multi_part_headers).to_return(body: %(<?xml version="1.0" encoding="UTF-8"?>\n<Error><Code>AccessDenied</Code><Message>Invalid according to Policy</Message><RequestId>1FECC4B719E426B1</RequestId><HostId>15+14lXt+HlF</HostId></Error>), status: 303, headers: {'Location' => 'https://mycompany.itrp.com/s3_success?sig=99e82e8a046'})
119
- expect_log("Attachment upload failed: AWS upload to https://itrp.s3.amazonaws.com/ for #{@key} failed: Invalid according to Policy", :error)
120
- expect(@attachments.send(:upload_attachment, @aws_conf, "#{@fixture_dir}/upload.txt", false)).to be_nil
121
- end
122
-
123
- it 'should report an error when ITRP confirmation fails' do
124
- stub_request(:post, 'https://itrp.s3.amazonaws.com/').with(body: @multi_part_body, headers: @multi_part_headers).to_return(body: 'OK', status: 303, headers: {'Location' => 'https://mycompany.itrp.com/s3_success?sig=99e82e8a046'})
125
- stub_request(:get, "https://api.itrp.com/v1/s3_success?sig=99e82e8a046&key=#{@key}").with(basic_auth: ['secret', 'x']).to_return(body: {message: 'oops!'}.to_json)
126
- expect_log('Request failed: oops!', :error)
127
- expect_log("Attachment upload failed: ITRP confirmation s3_success?sig=99e82e8a046 for #{@key} failed: oops!", :error)
128
- expect(@attachments.send(:upload_attachment, @aws_conf, "#{@fixture_dir}/upload.txt", false)).to be_nil
129
- end
130
-
131
- it 'should raise an exception when AWS upload fails' do
132
- stub_request(:post, 'https://itrp.s3.amazonaws.com/').with(body: @multi_part_body, headers: @multi_part_headers).to_return(body: %(<?xml version="1.0" encoding="UTF-8"?>\n<Error><Code>AccessDenied</Code><Message>Invalid according to Policy</Message><RequestId>1FECC4B719E426B1</RequestId><HostId>15+14lXt+HlF</HostId></Error>), status: 303, headers: {'Location' => 'https://mycompany.itrp.com/s3_success?sig=99e82e8a046'})
133
- message = "Attachment upload failed: AWS upload to https://itrp.s3.amazonaws.com/ for #{@key} failed: Invalid according to Policy"
134
- expect{ @attachments.send(:upload_attachment, @aws_conf, "#{@fixture_dir}/upload.txt", true) }.to raise_error(::Itrp::UploadFailed, message)
135
- end
136
- end
137
-
138
- context 'itrp' do
139
- before(:each) do
140
- @itrp_conf = {
141
- provider: 'local',
142
- upload_uri: 'https://api.itrp.com/attachments',
143
- upload_path: 'attachments/5/reqs/000/070/451/zxxb4ot60xfd6sjg/'
144
- }
145
- @key_template = 'attachments/5/reqs/000/070/451/zxxb4ot60xfd6sjg/${filename}'
146
- @key = 'attachments/5/reqs/000/070/451/zxxb4ot60xfd6sjg/upload.txt'
147
-
148
- @multi_part_body = "--0123456789ABLEWASIEREISAWELBA9876543210\r\nContent-Disposition: form-data; name=\"Content-Type\"\r\n\r\napplication/octet-stream\r\n--0123456789ABLEWASIEREISAWELBA9876543210\r\nContent-Disposition: form-data; name=\"file\"; filename=\"#{@spec_dir}/support/fixtures/upload.txt\"\r\nContent-Type: text/plain\r\n\r\ncontent\r\n--0123456789ABLEWASIEREISAWELBA9876543210\r\nContent-Disposition: form-data; name=\"key\"\r\n\r\nattachments/5/reqs/000/070/451/zxxb4ot60xfd6sjg/${filename}\r\n--0123456789ABLEWASIEREISAWELBA9876543210--"
149
- @multi_part_headers = {'Accept'=>'*/*', 'Content-Type'=>'multipart/form-data; boundary=0123456789ABLEWASIEREISAWELBA9876543210', 'User-Agent'=>'Mozilla/5.0 (Macintosh; U; PPC Mac OS X; en-us) AppleWebKit/523.10.6 (KHTML, like Gecko) Version/3.0.4 Safari/523.10.6'}
150
- end
151
-
152
- it 'should open a file from disk' do
153
- expect(@attachments).to receive(:itrp_upload).with(@itrp_conf, @key_template, @key, kind_of(File))
154
- expect(@attachments.send(:upload_attachment, @itrp_conf, "#{@fixture_dir}/upload.txt", false)).to eq({key: @key, filesize: 7})
155
- end
156
-
157
- it 'should sent the upload to ITRP' do
158
- stub_request(:post, 'https://api.itrp.com/v1/attachments').with(basic_auth: ['secret', 'x']).with(body: @multi_part_body, headers: @multi_part_headers).to_return(body: {}.to_json)
159
- expect(@attachments.send(:upload_attachment, @itrp_conf, "#{@fixture_dir}/upload.txt", false)).to eq({key: @key, filesize: 7})
160
- end
161
-
162
- it 'should report an error when ITRP upload fails' do
163
- stub_request(:post, 'https://api.itrp.com/v1/attachments').with(basic_auth: ['secret', 'x']).with(body: @multi_part_body, headers: @multi_part_headers).to_return(body: {message: 'oops!'}.to_json)
164
- expect_log('Request failed: oops!', :error)
165
- expect_log("Attachment upload failed: ITRP upload to https://api.itrp.com/attachments for #{@key} failed: oops!", :error)
166
- expect(@attachments.send(:upload_attachment, @itrp_conf, "#{@fixture_dir}/upload.txt", false)).to be_nil
167
- end
168
-
169
- it 'should raise an exception when ITRP upload fails' do
170
- stub_request(:post, 'https://api.itrp.com/v1/attachments').with(basic_auth: ['secret', 'x']).with(body: @multi_part_body, headers: @multi_part_headers).to_return(body: {message: 'oops!'}.to_json)
171
- expect_log('Request failed: oops!', :error)
172
- message = "Attachment upload failed: ITRP upload to https://api.itrp.com/attachments for #{@key} failed: oops!"
173
- expect{ @attachments.send(:upload_attachment, @itrp_conf, "#{@fixture_dir}/upload.txt", true) }.to raise_error(::Itrp::UploadFailed, message)
174
- end
175
- end
176
-
177
- end
178
- end
@@ -1,28 +0,0 @@
1
- require 'spec_helper'
2
-
3
- describe 'ca-bundle.crt' do
4
-
5
- it 'should be able to connect to the ITRP API' do
6
- WebMock.allow_net_connect!
7
- client = Itrp::Client.new(api_token: 'invalid', max_retry_time: -1)
8
- result = {}
9
-
10
- # no exception concerning the certificate
11
- expect { result[:response] = client.get('me') }.not_to raise_error
12
- response = result[:response]
13
- expect(response.valid?).to be_falsey
14
-
15
- # expecting 401 error
16
- expect(response.message).to eq('401: Access credentials required')
17
- end
18
-
19
- it 'should be able to connect to S3' do
20
- WebMock.allow_net_connect!
21
- http = Net::HTTP.new('itrp-eu.s3-eu-west-1.amazonaws.com', 443)
22
- http.read_timeout = 1
23
- http.use_ssl = true
24
-
25
- # no SSL error please
26
- expect{ http.start{ |_http| _http.request(Net::HTTP::Get.new('/exports/20141107/')) } }.to never_raise(OpenSSL::SSL::SSLError)
27
- end
28
- end
@@ -1,542 +0,0 @@
1
- require 'spec_helper'
2
-
3
- describe Itrp::Client do
4
-
5
- context 'Itrp.config' do
6
- before(:each) do
7
- Itrp.configure do |config|
8
- config.max_retry_time = 120 # override default value (5400)
9
- config.api_token = 'secret' # set value
10
- end
11
- end
12
-
13
- it 'should define the MAX_PAGE_SIZE' do
14
- expect(Itrp::Client::MAX_PAGE_SIZE).to eq(100)
15
- end
16
-
17
- it 'should use the Itrp configuration' do
18
- client = Itrp::Client.new
19
- expect(client.option(:host)).to eq('https://api.itrp.com') # default value
20
- expect(client.option(:api_token)).to eq('secret') # value set using Itrp.config
21
- expect(client.option(:max_retry_time)).to eq(120) # value overridden in Itrp.config
22
- end
23
-
24
- it 'should override the Itrp configuration' do
25
- client = Itrp::Client.new(host: 'https://demo.itrp.com', api_token: 'unknown', block_at_rate_limit: true)
26
- expect(client.option(:read_timeout)).to eq(25) # default value
27
- expect(client.option(:host)).to eq('https://demo.itrp.com') # default value overridden in Client.new
28
- expect(client.option(:api_token)).to eq('unknown') # value set using Itrp.config and overridden in Client.new
29
- expect(client.option(:max_retry_time)).to eq(120) # value overridden in Itrp.config
30
- expect(client.option(:block_at_rate_limit)).to eq(true) # value overridden in Client.new
31
- end
32
-
33
- [:host, :api_version, :api_token].each do |required_option|
34
- it "should require option #{required_option}" do
35
- expect { Itrp::Client.new(required_option => '') }.to raise_error("Missing required configuration option #{required_option}")
36
- end
37
- end
38
-
39
- [ ['https://api.itrp.com', true, 'api.itrp.com', 443],
40
- ['https://api.example.com:777', true, 'api.example.com', 777],
41
- ['http://itrp.example.com', false, 'itrp.example.com', 80],
42
- ['http://itrp.example.com:777', false, 'itrp.example.com', 777]
43
- ].each do |host, ssl, domain, port|
44
- it 'should parse ssl, host and port' do
45
- client = Itrp::Client.new(host: host)
46
- expect(client.instance_variable_get(:@ssl)).to eq(ssl)
47
- expect(client.instance_variable_get(:@domain)).to eq(domain)
48
- expect(client.instance_variable_get(:@port)).to eq(port)
49
- end
50
- end
51
- end
52
-
53
- it 'should set the ca-bundle.crt file' do
54
- http = Net::HTTP.new('https://api.itrp.com')
55
- http.use_ssl = true
56
-
57
- on_disk = `ls #{http.ca_file}`
58
- expect(on_disk).not_to match(/cannot access/)
59
- expect(on_disk).to match(/\/ca-bundle.crt$/)
60
- end
61
-
62
- describe 'headers' do
63
- before(:each) do
64
- @client = Itrp::Client.new(api_token: 'secret', max_retry_time: -1)
65
- end
66
-
67
- it 'should set the content type header' do
68
- stub = stub_request(:get, 'https://api.itrp.com/v1/me').with(basic_auth: ['secret', 'x']).with(headers: {'Content-Type' => 'application/json'}).to_return(body: {name: 'my name'}.to_json)
69
- @client.get('me')
70
- expect(stub).to have_been_requested
71
- end
72
-
73
- it 'should add the X-ITRP-Account header' do
74
- client = Itrp::Client.new(api_token: 'secret', max_retry_time: -1, account: 'test')
75
- stub = stub_request(:get, 'https://api.itrp.com/v1/me').with(basic_auth: ['secret', 'x']).with(headers: {'X-ITRP-Account' => 'test'}).to_return(body: {name: 'my name'}.to_json)
76
- client.get('me')
77
- expect(stub).to have_been_requested
78
- end
79
-
80
- it 'should add the X-ITRP-Source header' do
81
- client = Itrp::Client.new(api_token: 'secret', max_retry_time: -1, source: 'myapp')
82
- stub = stub_request(:get, 'https://api.itrp.com/v1/me').with(basic_auth: ['secret', 'x']).with(headers: {'X-ITRP-Source' => 'myapp'}).to_return(body: {name: 'my name'}.to_json)
83
- client.get('me')
84
- expect(stub).to have_been_requested
85
- end
86
-
87
- it 'should be able to override headers' do
88
- stub = stub_request(:get, 'https://api.itrp.com/v1/me').with(basic_auth: ['secret', 'x']).with(headers: {'Content-Type' => 'application/x-www-form-urlencoded'}).to_return(body: {name: 'my name'}.to_json)
89
- @client.get('me', {}, {'Content-Type' => 'application/x-www-form-urlencoded'})
90
- expect(stub).to have_been_requested
91
- end
92
-
93
- it 'should set the other headers' do
94
- stub = stub_request(:get, 'https://api.itrp.com/v1/me').with(basic_auth: ['secret', 'x']).with(headers: {'X-ITRP-Other' => 'value'}).to_return(body: {name: 'my name'}.to_json)
95
- @client.get('me', {}, {'X-ITRP-Other' => 'value'})
96
- expect(stub).to have_been_requested
97
- end
98
-
99
- it 'should accept headers in the each call' do
100
- stub = stub_request(:get, 'https://api.itrp.com/v1/requests?fields=subject&page=1&per_page=100').with(basic_auth: ['secret', 'x']).with(headers: {'X-ITRP-Secret' => 'special'}).to_return(body: [{id: 1, subject: 'Subject 1'}, {id: 2, subject: 'Subject 2'}, {id: 3, subject: 'Subject 3'}].to_json)
101
- @client.each('requests', {fields: 'subject'}, {'X-ITRP-Secret' => 'special'}) do |request|
102
- expect(request[:subject]).to eq("Subject #{request[:id]}")
103
- end
104
- expect(stub).to have_been_requested
105
- end
106
- end
107
-
108
- context 'each' do
109
- before(:each) do
110
- @client = Itrp::Client.new(api_token: 'secret', max_retry_time: -1)
111
- end
112
-
113
- it 'should yield each result' do
114
- stub_request(:get, 'https://api.itrp.com/v1/requests?fields=subject&page=1&per_page=100').with(basic_auth: ['secret', 'x']).to_return(body: [{id: 1, subject: 'Subject 1'}, {id: 2, subject: 'Subject 2'}, {id: 3, subject: 'Subject 3'}].to_json)
115
- nr_of_requests = @client.each('requests', {fields: 'subject'}) do |request|
116
- expect(request[:subject]).to eq("Subject #{request[:id]}")
117
- end
118
- expect(nr_of_requests).to eq(3)
119
- end
120
-
121
- it 'should retrieve multiple pages' do
122
- stub_page1 = stub_request(:get, 'https://api.itrp.com/v1/requests?page=1&per_page=2').with(basic_auth: ['secret', 'x']).to_return(body: [{id: 1, subject: 'Subject 1'}, {id: 2, subject: 'Subject 2'}].to_json, headers: {'Link' => '<https://api.itrp.com/v1/requests?page=1&per_page=2>; rel="first",<https://api.itrp.com/v1/requests?page=2&per_page=2>; rel="next",<https://api.itrp.com/v1/requests?page=2&per_page=2>; rel="last"'})
123
- stub_page2 = stub_request(:get, 'https://api.itrp.com/v1/requests?page=2&per_page=2').with(basic_auth: ['secret', 'x']).to_return(body: [{id: 3, subject: 'Subject 3'}].to_json, headers: {'Link' => '<https://api.itrp.com/v1/requests?page=1&per_page=2>; rel="first",<https://api.itrp.com/v1/requests?page=1&per_page=2>; rel="prev",<https://api.itrp.com/v1/requests?page=2&per_page=2>; rel="last"'})
124
- nr_of_requests = @client.each('requests', {per_page: 2}) do |request|
125
- expect(request[:subject]).to eq("Subject #{request[:id]}")
126
- end
127
- expect(nr_of_requests).to eq(3)
128
- expect(stub_page2).to have_been_requested
129
- end
130
- end
131
-
132
- context 'get' do
133
- before(:each) do
134
- @client = Itrp::Client.new(api_token: 'secret', max_retry_time: -1)
135
- end
136
-
137
- it 'should return a response' do
138
- stub_request(:get, 'https://api.itrp.com/v1/me').with(basic_auth: ['secret', 'x']).to_return(body: {name: 'my name'}.to_json)
139
- response = @client.get('me')
140
- expect(response[:name]).to eq('my name')
141
- end
142
-
143
- describe 'parameters' do
144
-
145
- [[nil, ''],
146
- [ 'normal', 'normal'],
147
- [ 'hello;<', 'hello%3B%3C'],
148
- [ true, 'true'],
149
- [ false, 'false'],
150
- [ DateTime.now, DateTime.now.new_offset(0).iso8601.gsub('+', '%2B')],
151
- [ Date.new, Date.new.strftime('%Y-%m-%d')],
152
- [ Time.now, Time.now.strftime('%H:%M')],
153
- [ ['first', 'second;<', true], 'first,second%3B%3C,true']
154
- ].each do |param_value, url_value|
155
- it "should cast #{param_value.class.name}: '#{param_value}' to '#{url_value}'" do
156
- stub = stub_request(:get, "https://api.itrp.com/v1/me?value=#{url_value}").with(basic_auth: ['secret', 'x']).to_return(body: {name: 'my name'}.to_json)
157
- @client.get('me', {value: param_value})
158
- expect(stub).to have_been_requested
159
- end
160
- end
161
-
162
- it 'should not cast arrays in post and put calls' do
163
- client = Itrp::Client.new(api_token: 'secret', max_retry_time: -1)
164
- stub = stub_request(:post, 'https://api.itrp.com/v1/people').with(basic_auth: ['secret', 'x']).with(body: {user_ids: [1, 2, 3]}, headers: {'X-ITRP-Custom' => 'custom'}).to_return(body: {id: 101}.to_json)
165
- client.post('people', {user_ids: [1, 2, 3]}, {'X-ITRP-Custom' => 'custom'})
166
- expect(stub).to have_been_requested
167
- end
168
-
169
- it 'should not cast hashes in post and put calls' do
170
- client = Itrp::Client.new(api_token: 'secret', max_retry_time: -1)
171
- stub = stub_request(:patch, 'https://api.itrp.com/v1/people/55').with(basic_auth: ['secret', 'x']).with(body: '{"contacts_attributes":{"0":{"protocol":"email","label":"work","uri":"work@example.com"}}}', headers: {'X-ITRP-Custom' => 'custom'}).to_return(body: {id: 101}.to_json)
172
- client.put('people/55', {contacts_attributes: {0 => {protocol: :email, label: :work, uri: 'work@example.com'}}}, {'X-ITRP-Custom' => 'custom'})
173
- expect(stub).to have_been_requested
174
- end
175
-
176
- it 'should not double escape symbols' do
177
- client = Itrp::Client.new(api_token: 'secret', max_retry_time: -1)
178
- stub = stub_request(:patch, 'https://api.itrp.com/v1/people/55').with(basic_auth: ['secret', 'x']).with(body: '{"status":"waiting_for"}').to_return(body: {id: 101}.to_json)
179
- client.put('people/55', {status: :waiting_for})
180
- expect(stub).to have_been_requested
181
- end
182
-
183
- it 'should handle fancy filter operations' do
184
- now = DateTime.now
185
- stub = stub_request(:get, "https://api.itrp.com/v1/people?created_at=>#{now.new_offset(0).iso8601.gsub('+', '%2B')}&id!=15").with(basic_auth: ['secret', 'x']).to_return(body: {name: 'my name'}.to_json)
186
- @client.get('people', {'created_at=>' => now, 'id!=' => 15})
187
- expect(stub).to have_been_requested
188
- end
189
-
190
- it 'should append parameters' do
191
- stub = stub_request(:get, 'https://api.itrp.com/v1/people?id!=15&primary_email=me@example.com').with(basic_auth: ['secret', 'x']).to_return(body: {name: 'my name'}.to_json)
192
- @client.get('people?id!=15', {primary_email: 'me@example.com'})
193
- expect(stub).to have_been_requested
194
- end
195
- end
196
- end
197
-
198
- context 'patch' do
199
- [:put, :patch].each do |method|
200
- it 'should send patch requests with parameters and headers for #{method} calls' do
201
- client = Itrp::Client.new(api_token: 'secret', max_retry_time: -1)
202
- stub = stub_request(:patch, 'https://api.itrp.com/v1/people/1').with(basic_auth: ['secret', 'x']).with(body: {name: 'New Name'}, headers: {'X-ITRP-Custom' => 'custom'}).to_return(body: {id: 1}.to_json)
203
- client.send(method, 'people/1', {name: 'New Name'}, {'X-ITRP-Custom' => 'custom'})
204
- expect(stub).to have_been_requested
205
- end
206
- end
207
- end
208
-
209
- context 'post' do
210
- it 'should send post requests with parameters and headers' do
211
- client = Itrp::Client.new(api_token: 'secret', max_retry_time: -1)
212
- stub = stub_request(:post, 'https://api.itrp.com/v1/people').with(basic_auth: ['secret', 'x']).with(body: {name: 'New Name'}, headers: {'X-ITRP-Custom' => 'custom'}).to_return(body: {id: 101}.to_json)
213
- client.post('people', {name: 'New Name'}, {'X-ITRP-Custom' => 'custom'})
214
- expect(stub).to have_been_requested
215
- end
216
- end
217
-
218
- context 'delete' do
219
- it 'should send delete requests with parameters and headers' do
220
- client = Itrp::Client.new(api_token: 'secret', max_retry_time: -1)
221
- stub = stub_request(:delete, 'https://api.itrp.com/v1/people?id=value').with(basic_auth: ['secret', 'x']).with(headers: {'X-ITRP-Custom' => 'custom'}).to_return(body: '', status: 204)
222
- response = client.delete('people', {id: 'value'}, {'X-ITRP-Custom' => 'custom'})
223
- expect(stub).to have_been_requested
224
- expect(response.valid?).to be_truthy
225
- expect(response.json).to eq({})
226
- end
227
- end
228
-
229
- context 'attachments' do
230
- before(:each) do
231
- @client = Itrp::Client.new(api_token: 'secret', max_retry_time: -1)
232
- end
233
-
234
- it 'should not log an error for XML responses' do
235
- xml = %(<?xml version="1.0" encoding="UTF-8"?>\n<details>some info</details>)
236
- stub_request(:get, 'https://api.itrp.com/v1/me').with(basic_auth: ['secret', 'x']).to_return(body: xml)
237
- expect_log('Sending GET request to api.itrp.com:443/v1/me', :debug)
238
- expect_log("XML response:\n#{xml}", :debug)
239
- response = @client.get('me')
240
- expect(response.valid?).to be_falsey
241
- expect(response.raw.body).to eq(xml)
242
- end
243
-
244
- it 'should not log an error for redirects' do
245
- stub_request(:get, 'https://api.itrp.com/v1/me').with(basic_auth: ['secret', 'x']).to_return(body: '', status: 303, headers: {'Location' => 'http://redirect.example.com/to/here'})
246
- expect_log('Sending GET request to api.itrp.com:443/v1/me', :debug)
247
- expect_log('Redirect: http://redirect.example.com/to/here', :debug)
248
- response = @client.get('me')
249
- expect(response.valid?).to be_falsey
250
- expect(response.raw.body).to be_nil
251
- end
252
-
253
- it "should not parse attachments for get requests" do
254
- expect(Itrp::Attachments).not_to receive(:new)
255
- stub_request(:get, 'https://api.itrp.com/v1/requests/777?attachments=/tmp/first.png,/tmp/second.zip&note=note').with(basic_auth: ['secret', 'x']).to_return(body: {id: 777, upload_called: false}.to_json)
256
-
257
- response = @client.get('/requests/777', {note: 'note', attachments: ['/tmp/first.png', '/tmp/second.zip'] })
258
- expect(response.valid?).to be_truthy
259
- expect(response[:upload_called]).to be_falsey
260
- end
261
-
262
- [:post, :patch].each do |method|
263
- it "should parse attachments for #{method} requests" do
264
- attachments = double('Itrp::Attachments')
265
- expect(attachments).to receive(:upload_attachments!) do |path, data|
266
- expect(path).to eq '/requests/777'
267
- expect(data[:attachments]).to eq ['/tmp/first.png', '/tmp/second.zip']
268
- data.delete(:attachments)
269
- data[:note_attachments] = 'processed'
270
- end
271
- expect(Itrp::Attachments).to receive(:new).with(@client){ attachments }
272
- stub_request(method, 'https://api.itrp.com/v1/requests/777').with(basic_auth: ['secret', 'x']).with(body: {note: 'note', note_attachments: 'processed' }).to_return(body: {id: 777, upload_called: true}.to_json)
273
-
274
- response = @client.send(method, '/requests/777', {note: 'note', attachments: ['/tmp/first.png', '/tmp/second.zip'] })
275
- expect(response.valid?).to be_truthy
276
- expect(response[:upload_called]).to be_truthy
277
- end
278
- end
279
-
280
- end
281
-
282
- context 'import' do
283
- before(:each) do
284
- @client = Itrp::Client.new(api_token: 'secret', max_retry_time: -1)
285
- @multi_part_body = "--0123456789ABLEWASIEREISAWELBA9876543210\r\nContent-Disposition: form-data; name=\"type\"\r\n\r\npeople\r\n--0123456789ABLEWASIEREISAWELBA9876543210\r\nContent-Disposition: form-data; name=\"file\"; filename=\"#{@fixture_dir}/people.csv\"\r\nContent-Type: text/comma-separated-values\r\n\r\nPrimary Email,Name\nchess.cole@example.com,Chess Cole\ned.turner@example.com,Ed Turner\r\n--0123456789ABLEWASIEREISAWELBA9876543210--"
286
- @multi_part_headers = {'Accept'=>'*/*', 'Content-Type'=>'multipart/form-data; boundary=0123456789ABLEWASIEREISAWELBA9876543210', 'User-Agent'=>'Mozilla/5.0 (Macintosh; U; PPC Mac OS X; en-us) AppleWebKit/523.10.6 (KHTML, like Gecko) Version/3.0.4 Safari/523.10.6'}
287
-
288
- @import_queued_response = {body: {state: 'queued'}.to_json}
289
- @import_processing_response = {body: {state: 'processing'}.to_json}
290
- @import_done_response = {body: {state: 'done', results: {errors: 0, updated: 1, created: 1, failures: 0, unchanged: 0, deleted: 0}}.to_json}
291
- @import_failed_response = {body: {state: 'error', message: 'Invalid byte sequence in UTF-8 on line 2', results: {errors: 1, updated: 1, created: 0, failures: 1, unchanged: 0, deleted: 0}}.to_json}
292
- allow(@client).to receive(:sleep)
293
- end
294
-
295
- it 'should import a CSV file' do
296
- stub_request(:post, 'https://api.itrp.com/v1/import').with(basic_auth: ['secret', 'x']).with(body: @multi_part_body, headers: @multi_part_headers).to_return(body: {token: '68ef5ef0f64c0'}.to_json)
297
- expect_log("Import file '#{@fixture_dir}/people.csv' successfully uploaded with token '68ef5ef0f64c0'.")
298
-
299
- response = @client.import(File.new("#{@fixture_dir}/people.csv"), 'people')
300
- expect(response[:token]).to eq('68ef5ef0f64c0')
301
- end
302
-
303
- it 'should import a CSV file by filename' do
304
- stub_request(:post, 'https://api.itrp.com/v1/import').with(basic_auth: ['secret', 'x']).with(body: @multi_part_body, headers: @multi_part_headers).to_return(body: {token: '68ef5ef0f64c0'}.to_json)
305
- response = @client.import("#{@fixture_dir}/people.csv", 'people')
306
- expect(response[:token]).to eq('68ef5ef0f64c0')
307
- end
308
-
309
- it 'should wait for the import to complete' do
310
- stub_request(:post, 'https://api.itrp.com/v1/import').with(basic_auth: ['secret', 'x']).with(body: @multi_part_body, headers: @multi_part_headers).to_return(body: {token: '68ef5ef0f64c0'}.to_json)
311
- progress_stub = stub_request(:get, 'https://api.itrp.com/v1/import/68ef5ef0f64c0').with(basic_auth: ['secret', 'x'])
312
- .to_return(@import_queued_response, @import_processing_response)
313
- .then.to_raise(StandardError.new('network error'))
314
- .then.to_return(@import_done_response)
315
-
316
- # verify the correct log statement are made
317
- expect_log('Sending POST request to api.itrp.com:443/v1/import', :debug)
318
- expect_log("Response:\n{\n \"token\": \"68ef5ef0f64c0\"\n}", :debug)
319
- expect_log("Import file '#{@fixture_dir}/people.csv' successfully uploaded with token '68ef5ef0f64c0'.")
320
- expect_log('Sending GET request to api.itrp.com:443/v1/import/68ef5ef0f64c0', :debug)
321
- expect_log("Response:\n{\n \"state\": \"queued\"\n}", :debug)
322
- expect_log("Import of '#{@fixture_dir}/people.csv' is queued. Checking again in 30 seconds.", :debug)
323
- expect_log('Sending GET request to api.itrp.com:443/v1/import/68ef5ef0f64c0', :debug)
324
- expect_log("Response:\n{\n \"state\": \"processing\"\n}", :debug)
325
- expect_log("Import of '#{@fixture_dir}/people.csv' is processing. Checking again in 30 seconds.", :debug)
326
- expect_log('Sending GET request to api.itrp.com:443/v1/import/68ef5ef0f64c0', :debug)
327
- expect_log("Request failed: 500: No Response from Server - network error for 'api.itrp.com:443/v1/import/68ef5ef0f64c0'", :error)
328
- expect_log('Sending GET request to api.itrp.com:443/v1/import/68ef5ef0f64c0', :debug)
329
- expect_log("Response:\n{\n \"state\": \"done\",\n \"results\": {\n \"errors\": 0,\n \"updated\": 1,\n \"created\": 1,\n \"failures\": 0,\n \"unchanged\": 0,\n \"deleted\": 0\n }\n}", :debug)
330
-
331
- response = @client.import("#{@fixture_dir}/people.csv", 'people', true)
332
- expect(response[:state]).to eq('done')
333
- expect(response[:results][:updated]).to eq(1)
334
- expect(progress_stub).to have_been_requested.times(4)
335
- end
336
-
337
- it 'should wait for the import to fail' do
338
- stub_request(:post, 'https://api.itrp.com/v1/import').with(basic_auth: ['secret', 'x']).with(body: @multi_part_body, headers: @multi_part_headers).to_return(body: {token: '68ef5ef0f64c0'}.to_json)
339
- progress_stub = stub_request(:get, 'https://api.itrp.com/v1/import/68ef5ef0f64c0').with(basic_auth: ['secret', 'x']).to_return(@import_queued_response, @import_processing_response, @import_failed_response)
340
-
341
- expect{ @client.import("#{@fixture_dir}/people.csv", 'people', true) }.to raise_error(Itrp::Exception, "Unable to monitor progress for people import. Invalid byte sequence in UTF-8 on line 2")
342
- expect(progress_stub).to have_been_requested.times(4)
343
- end
344
-
345
- it 'should not continue when there is an error connecting to ITRP' do
346
- stub_request(:post, 'https://api.itrp.com/v1/import').with(basic_auth: ['secret', 'x']).with(body: @multi_part_body, headers: @multi_part_headers).to_return(body: {token: '68ef5ef0f64c0'}.to_json)
347
- progress_stub = stub_request(:get, 'https://api.itrp.com/v1/import/68ef5ef0f64c0').with(basic_auth: ['secret', 'x'])
348
- .to_return(@import_queued_response, @import_processing_response)
349
- .then.to_raise(StandardError.new('network error')) # twice
350
-
351
- expect{ @client.import("#{@fixture_dir}/people.csv", 'people', true) }.to raise_error(Itrp::Exception, "Unable to monitor progress for people import. 500: No Response from Server - network error for 'api.itrp.com:443/v1/import/68ef5ef0f64c0'")
352
- expect(progress_stub).to have_been_requested.times(4)
353
- end
354
-
355
- it 'should return an invalid response in case waiting for progress is false' do
356
- stub_request(:post, 'https://api.itrp.com/v1/import').with(basic_auth: ['secret', 'x']).with(body: @multi_part_body, headers: @multi_part_headers).to_return(body: {message: 'oops!'}.to_json)
357
- response = @client.import("#{@fixture_dir}/people.csv", 'people', false)
358
- expect(response.valid?).to be_falsey
359
- expect(response.message).to eq('oops!')
360
- end
361
-
362
- it 'should raise an UploadFailed exception in case waiting for progress is true' do
363
- stub_request(:post, 'https://api.itrp.com/v1/import').with(basic_auth: ['secret', 'x']).with(body: @multi_part_body, headers: @multi_part_headers).to_return(body: {message: 'oops!'}.to_json)
364
- expect{ @client.import("#{@fixture_dir}/people.csv", 'people', true) }.to raise_error(Itrp::UploadFailed, 'Failed to queue people import. oops!')
365
- end
366
-
367
- end
368
-
369
-
370
- context 'export' do
371
- before(:each) do
372
- @client = Itrp::Client.new(api_token: 'secret', max_retry_time: -1)
373
-
374
- @export_queued_response = {body: {state: 'queued'}.to_json}
375
- @export_processing_response = {body: {state: 'processing'}.to_json}
376
- @export_done_response = {body: {state: 'done', url: 'https://download.example.com/export.zip?AWSAccessKeyId=12345'}.to_json}
377
- allow(@client).to receive(:sleep)
378
- end
379
-
380
- it 'should export multiple types' do
381
- stub_request(:post, 'https://api.itrp.com/v1/export').with(basic_auth: ['secret', 'x']).with(body: {type: 'people,people_contact_details'}).to_return(body: {token: '68ef5ef0f64c0'}.to_json)
382
- expect_log("Export for 'people,people_contact_details' successfully queued with token '68ef5ef0f64c0'.")
383
-
384
- response = @client.export(['people', 'people_contact_details'])
385
- expect(response[:token]).to eq('68ef5ef0f64c0')
386
- end
387
-
388
- it 'should indicate when nothing is exported' do
389
- stub_request(:post, 'https://api.itrp.com/v1/export').with(basic_auth: ['secret', 'x']).with(body: {type: 'people', from: '2012-03-30T23:00:00+00:00'}).to_return(status: 204)
390
- expect_log("No changed records for 'people' since 2012-03-30T23:00:00+00:00.")
391
-
392
- response = @client.export('people', DateTime.new(2012,03,30,23,00,00))
393
- expect(response[:token]).to be_nil
394
- end
395
-
396
- it 'should export since a certain time' do
397
- stub_request(:post, 'https://api.itrp.com/v1/export').with(basic_auth: ['secret', 'x']).with(body: {type: 'people', from: '2012-03-30T23:00:00+00:00'}).to_return(body: {token: '68ef5ef0f64c0'}.to_json)
398
- expect_log("Export for 'people' successfully queued with token '68ef5ef0f64c0'.")
399
-
400
- response = @client.export('people', DateTime.new(2012,03,30,23,00,00))
401
- expect(response[:token]).to eq('68ef5ef0f64c0')
402
- end
403
-
404
- it 'should wait for the export to complete' do
405
- stub_request(:post, 'https://api.itrp.com/v1/export').with(basic_auth: ['secret', 'x']).with(body: {type: 'people'}).to_return(body: {token: '68ef5ef0f64c0'}.to_json)
406
- progress_stub = stub_request(:get, 'https://api.itrp.com/v1/export/68ef5ef0f64c0').with(basic_auth: ['secret', 'x'])
407
- .to_return(@export_queued_response, @export_processing_response)
408
- .then.to_raise(StandardError.new('network error'))
409
- .then.to_return(@export_done_response)
410
-
411
- # verify the correct log statement are made
412
- expect_log('Sending POST request to api.itrp.com:443/v1/export', :debug)
413
- expect_log(%(Response:\n{\n "token": "68ef5ef0f64c0"\n}), :debug)
414
- expect_log("Export for 'people' successfully queued with token '68ef5ef0f64c0'.")
415
- expect_log('Sending GET request to api.itrp.com:443/v1/export/68ef5ef0f64c0', :debug)
416
- expect_log(%(Response:\n{\n "state": "queued"\n}), :debug)
417
- expect_log("Export of 'people' is queued. Checking again in 30 seconds.", :debug)
418
- expect_log('Sending GET request to api.itrp.com:443/v1/export/68ef5ef0f64c0', :debug)
419
- expect_log(%(Response:\n{\n "state": "processing"\n}), :debug)
420
- expect_log("Export of 'people' is processing. Checking again in 30 seconds.", :debug)
421
- expect_log('Sending GET request to api.itrp.com:443/v1/export/68ef5ef0f64c0', :debug)
422
- expect_log("Request failed: 500: No Response from Server - network error for 'api.itrp.com:443/v1/export/68ef5ef0f64c0'", :error)
423
- expect_log('Sending GET request to api.itrp.com:443/v1/export/68ef5ef0f64c0', :debug)
424
- expect_log(%(Response:\n{\n "state": "done",\n "url": "https://download.example.com/export.zip?AWSAccessKeyId=12345"\n}), :debug)
425
-
426
- response = @client.export('people', nil, true)
427
- expect(response[:state]).to eq('done')
428
- expect(response[:url]).to eq('https://download.example.com/export.zip?AWSAccessKeyId=12345')
429
- expect(progress_stub).to have_been_requested.times(4)
430
- end
431
-
432
- it 'should not continue when there is an error connecting to ITRP' do
433
- stub_request(:post, 'https://api.itrp.com/v1/export').with(basic_auth: ['secret', 'x']).with(body: {type: 'people'}).to_return(body: {token: '68ef5ef0f64c0'}.to_json)
434
- progress_stub = stub_request(:get, 'https://api.itrp.com/v1/export/68ef5ef0f64c0').with(basic_auth: ['secret', 'x'])
435
- .to_return(@export_queued_response, @export_processing_response)
436
- .then.to_raise(StandardError.new('network error')) # twice
437
-
438
- expect{ @client.export('people', nil, true) }.to raise_error(Itrp::Exception, "Unable to monitor progress for 'people' export. 500: No Response from Server - network error for 'api.itrp.com:443/v1/export/68ef5ef0f64c0'")
439
- expect(progress_stub).to have_been_requested.times(4)
440
- end
441
-
442
- it 'should return an invalid response in case waiting for progress is false' do
443
- stub_request(:post, 'https://api.itrp.com/v1/export').with(basic_auth: ['secret', 'x']).with(body: {type: 'people'}).to_return(body: {message: 'oops!'}.to_json)
444
- response = @client.export('people')
445
- expect(response.valid?).to be_falsey
446
- expect(response.message).to eq('oops!')
447
- end
448
-
449
- it 'should raise an UploadFailed exception in case waiting for progress is true' do
450
- stub_request(:post, 'https://api.itrp.com/v1/export').with(basic_auth: ['secret', 'x']).with(body: {type: 'people'}).to_return(body: {message: 'oops!'}.to_json)
451
- expect{ @client.export('people', nil, true) }.to raise_error(Itrp::UploadFailed, "Failed to queue 'people' export. oops!")
452
- end
453
-
454
- end
455
-
456
- context 'retry' do
457
- it 'should not retry when max_retry_time = -1' do
458
- stub = stub_request(:get, 'https://api.itrp.com/v1/me').with(basic_auth: ['secret', 'x']).to_raise(StandardError.new('network error'))
459
- expect_log('Sending GET request to api.itrp.com:443/v1/me', :debug )
460
- expect_log("Request failed: 500: No Response from Server - network error for 'api.itrp.com:443/v1/me'", :error)
461
-
462
- client = Itrp::Client.new(api_token: 'secret', max_retry_time: -1)
463
- response = client.get('me')
464
- expect(stub).to have_been_requested.times(1)
465
- expect(response.valid?).to be_falsey
466
- expect(response.message).to eq("500: No Response from Server - network error for 'api.itrp.com:443/v1/me'")
467
- end
468
-
469
- it 'should not retry 4 times when max_retry_time = 16' do
470
- stub = stub_request(:get, 'https://api.itrp.com/v1/me').with(basic_auth: ['secret', 'x']).to_raise(StandardError.new('network error'))
471
- [2,4,8,16].each_with_index do |secs, i|
472
- expect_log('Sending GET request to api.itrp.com:443/v1/me', :debug )
473
- expect_log("Request failed, retry ##{i+1} in #{secs} seconds: 500: No Response from Server - network error for 'api.itrp.com:443/v1/me'", :warn)
474
- end
475
-
476
- client = Itrp::Client.new(api_token: 'secret', max_retry_time: 16)
477
- allow(client).to receive(:sleep)
478
- response = client.get('me')
479
- expect(stub).to have_been_requested.times(4)
480
- expect(response.valid?).to be_falsey
481
- expect(response.message).to eq("500: No Response from Server - network error for 'api.itrp.com:443/v1/me'")
482
- end
483
-
484
- it 'should return the response after retry succeeds' do
485
- stub = stub_request(:get, 'https://api.itrp.com/v1/me').with(basic_auth: ['secret', 'x']).to_raise(StandardError.new('network error')).then.to_return(body: {name: 'my name'}.to_json)
486
- expect_log('Sending GET request to api.itrp.com:443/v1/me', :debug )
487
- expect_log("Request failed, retry #1 in 2 seconds: 500: No Response from Server - network error for 'api.itrp.com:443/v1/me'", :warn)
488
- expect_log('Sending GET request to api.itrp.com:443/v1/me', :debug )
489
- expect_log(%(Response:\n{\n "name": "my name"\n}), :debug )
490
-
491
- client = Itrp::Client.new(api_token: 'secret', max_retry_time: 16)
492
- allow(client).to receive(:sleep)
493
- response = client.get('me')
494
- expect(stub).to have_been_requested.times(2)
495
- expect(response.valid?).to be_truthy
496
- expect(response[:name]).to eq('my name')
497
- end
498
- end
499
-
500
- context 'rate limiting' do
501
- it 'should not block on rate limit when block_at_rate_limit is false' do
502
- stub = stub_request(:get, 'https://api.itrp.com/v1/me').with(basic_auth: ['secret', 'x']).to_return(status: 429, body: {message: 'Too Many Requests'}.to_json)
503
- expect_log('Sending GET request to api.itrp.com:443/v1/me', :debug )
504
- expect_log("Request failed: 429: Too Many Requests", :error)
505
-
506
- client = Itrp::Client.new(api_token: 'secret', block_at_rate_limit: false)
507
- response = client.get('me')
508
- expect(stub).to have_been_requested.times(1)
509
- expect(response.valid?).to be_falsey
510
- expect(response.message).to eq('429: Too Many Requests')
511
- end
512
-
513
- it 'should block on rate limit when block_at_rate_limit is true' do
514
- stub = stub_request(:get, 'https://api.itrp.com/v1/me').with(basic_auth: ['secret', 'x']).to_return(status: 429, body: {message: 'Too Many Requests'}.to_json).then.to_return(body: {name: 'my name'}.to_json)
515
- expect_log('Sending GET request to api.itrp.com:443/v1/me', :debug )
516
- expect_log('Request throttled, trying again in 5 minutes: 429: Too Many Requests', :warn)
517
- expect_log('Sending GET request to api.itrp.com:443/v1/me', :debug )
518
- expect_log(%(Response:\n{\n "name": "my name"\n}), :debug )
519
-
520
- client = Itrp::Client.new(api_token: 'secret', block_at_rate_limit: true)
521
- allow(client).to receive(:sleep)
522
- response = client.get('me')
523
- expect(stub).to have_been_requested.times(2)
524
- expect(response.valid?).to be_truthy
525
- expect(response[:name]).to eq('my name')
526
- end
527
- end
528
-
529
- context 'logger' do
530
- before(:each) do
531
- @logger = Logger.new(STDOUT)
532
- @client = Itrp::Client.new(api_token: 'secret', max_retry_time: -1, logger: @logger)
533
- end
534
-
535
- it 'should be possible to override the default logger' do
536
- stub_request(:get, 'https://api.itrp.com/v1/me').with(basic_auth: ['secret', 'x']).to_return(body: {name: 'my name'}.to_json)
537
- expect_log('Sending GET request to api.itrp.com:443/v1/me', :debug, @logger )
538
- expect_log(%(Response:\n{\n "name": "my name"\n}), :debug, @logger )
539
- @client.get('me')
540
- end
541
- end
542
- end