rev-api 2.1.0 → 2.2.0

Sign up to get free protection for your applications and to get access to all the features.
Files changed (62) hide show
  1. checksums.yaml +4 -4
  2. data/.coveralls.yml +1 -1
  3. data/.gitignore +21 -21
  4. data/.ruby-gemset +1 -1
  5. data/.ruby-version +1 -1
  6. data/.travis.yml +8 -8
  7. data/Gemfile +3 -3
  8. data/LICENSE +191 -191
  9. data/README.md +132 -132
  10. data/Rakefile +13 -13
  11. data/examples/cli.rb +270 -270
  12. data/lib/rev-api.rb +25 -25
  13. data/lib/rev-api/api.rb +326 -326
  14. data/lib/rev-api/api_serializable.rb +30 -30
  15. data/lib/rev-api/exceptions.rb +100 -100
  16. data/lib/rev-api/http_client.rb +97 -97
  17. data/lib/rev-api/models/order.rb +138 -138
  18. data/lib/rev-api/models/order_request.rb +222 -228
  19. data/lib/rev-api/version.rb +3 -3
  20. data/rev-api.gemspec +34 -34
  21. data/spec/fixtures/api_cassettes/cancel_order.yml +38 -38
  22. data/spec/fixtures/api_cassettes/cancel_order_not_allowed.yml +40 -40
  23. data/spec/fixtures/api_cassettes/get_attachment_content.yml +399 -399
  24. data/spec/fixtures/api_cassettes/get_attachment_content_as_pdf.yml +399 -399
  25. data/spec/fixtures/api_cassettes/get_attachment_content_as_text.yml +65 -65
  26. data/spec/fixtures/api_cassettes/get_attachment_content_as_youtube_transcript.yml +66 -66
  27. data/spec/fixtures/api_cassettes/get_attachment_content_unacceptable_representation.yml +42 -42
  28. data/spec/fixtures/api_cassettes/get_attachment_content_with_invalid_id.yml +42 -42
  29. data/spec/fixtures/api_cassettes/get_attachment_metadata.yml +42 -42
  30. data/spec/fixtures/api_cassettes/get_attachment_with_invalid_id.yml +40 -40
  31. data/spec/fixtures/api_cassettes/get_orders.yml +122 -122
  32. data/spec/fixtures/api_cassettes/get_orders_with_clientRef.yml +41 -41
  33. data/spec/fixtures/api_cassettes/get_tc_order.yml +44 -44
  34. data/spec/fixtures/api_cassettes/get_third_page_of_orders.yml +58 -58
  35. data/spec/fixtures/api_cassettes/get_tr_order.yml +44 -44
  36. data/spec/fixtures/api_cassettes/link_input.yml +44 -44
  37. data/spec/fixtures/api_cassettes/link_input_with_all_attributes.yml +44 -44
  38. data/spec/fixtures/api_cassettes/link_input_with_spaces_in_filename.yml +45 -45
  39. data/spec/fixtures/api_cassettes/not_found_order.yml +42 -42
  40. data/spec/fixtures/api_cassettes/submit_cp_order.yml +45 -45
  41. data/spec/fixtures/api_cassettes/submit_su_order.yml +45 -45
  42. data/spec/fixtures/api_cassettes/submit_tc_order_with_account_balance.yml +45 -45
  43. data/spec/fixtures/api_cassettes/submit_tc_order_with_invalid_request.yml +45 -45
  44. data/spec/fixtures/api_cassettes/submit_tc_order_without_specifying_payment.yml +45 -45
  45. data/spec/fixtures/api_cassettes/submit_tr_order.yml +44 -44
  46. data/spec/fixtures/api_cassettes/unauthorized.yml +42 -42
  47. data/spec/fixtures/api_cassettes/upload_input.yml +90 -90
  48. data/spec/fixtures/api_cassettes/upload_input_with_invalid_content_type.yml +91 -91
  49. data/spec/lib/rev/api_spec.rb +24 -24
  50. data/spec/lib/rev/cancel_order_spec.rb +24 -24
  51. data/spec/lib/rev/exceptions_spec.rb +8 -8
  52. data/spec/lib/rev/get_attachment_content_spec.rb +79 -79
  53. data/spec/lib/rev/get_attachment_metadata_spec.rb +33 -33
  54. data/spec/lib/rev/get_order_spec.rb +67 -67
  55. data/spec/lib/rev/get_orders_spec.rb +61 -61
  56. data/spec/lib/rev/http_client_spec.rb +32 -32
  57. data/spec/lib/rev/models/order_request_spec.rb +6 -14
  58. data/spec/lib/rev/models/order_spec.rb +58 -58
  59. data/spec/lib/rev/post_inputs_spec.rb +94 -94
  60. data/spec/lib/rev/post_order_spec.rb +195 -195
  61. data/spec/spec_helper.rb +49 -49
  62. metadata +39 -82
@@ -1,195 +1,195 @@
1
- require_relative '../../spec_helper'
2
-
3
- describe 'POST /orders' do
4
- let(:client) { Rev.new('welcome', 'AAAAAu/YjZ3phXU5FsF35yIcgiA=', 'www.revtrunk.com') }
5
-
6
- # some defaults we use often
7
- let(:billing_address) { Rev::BillingAddress.new(
8
- :street => '123 Pine Lane',
9
- :street2 => 'Apt D',
10
- :city => 'MyTown',
11
- :state => 'MN',
12
- :zip => '12345',
13
- :country_alpha2 => 'US'
14
- )}
15
-
16
- let(:balance_payment) { Rev::Payment.new(Rev::Payment::TYPES[:account_balance]) }
17
- let(:transcription_inputs) {
18
- inputs = []
19
- inputs << Rev::Input.new(:external_link => 'http://www.youtube.com/watch?v=UF8uR6Z6KLc')
20
- inputs << Rev::Input.new(:audio_length_seconds => 900, :external_link => 'https://vimeo.com/7976699')
21
- }
22
- let(:translation_inputs) {
23
- inputs = []
24
- inputs << Rev::Input.new(:word_length => 1000, :uri => 'urn:rev:inputmedia:SnVwbG9hZHMvMjAxMy0wOS0xNy9lMzk4MWIzNS0wNzM1LTRlMDAtODY1NC1jNWY4ZjE4MzdlMTIvc291cmNlZG9jdW1lbnQucG5n')
25
- }
26
- let(:caption_inputs) {
27
- inputs = []
28
- inputs << Rev::Input.new(:video_length_seconds => 900, :external_link => 'http://www.youtube.com/watch?v=UF8uR6Z6KLc')
29
- }
30
- let(:transcription_options) { Rev::TranscriptionOptions.new(transcription_inputs,
31
- :verbatim => true, :timestamps => true) }
32
- let(:translation_options) { Rev::TranslationOptions.new(translation_inputs,
33
- :source_language_code => 'es', :destination_language_code => 'en') }
34
- let(:caption_options) {
35
- Rev::CaptionOptions.new(caption_inputs, :output_file_formats => ['SubRip'])
36
- }
37
- let(:subtitle_options) {
38
- Rev::CaptionOptions.new(caption_inputs, :subtitle_languages => ['es','it'],
39
- :output_file_formats => ['SubRip'])
40
- }
41
-
42
- it 'must place order using account balance' do
43
- VCR.insert_cassette 'submit_tc_order_with_account_balance'
44
-
45
- request = Rev::OrderRequest.new(
46
- :transcription_options => transcription_options
47
- )
48
-
49
- new_order_num = client.submit_order(request)
50
-
51
- new_order_num.must_equal 'TC0406615008'
52
- expected_body = {
53
- 'payment' => {
54
- 'type' => 'AccountBalance'
55
- },
56
- 'priority' => Rev::OrderRequest::PRIORITY[:normal],
57
- 'transcription_options' => {
58
- 'inputs' => [
59
- { 'external_link' => 'http://www.youtube.com/watch?v=UF8uR6Z6KLc' },
60
- { 'external_link' => 'https://vimeo.com/7976699', 'audio_length_seconds' => 900 }
61
- ],
62
- 'verbatim' => true,
63
- 'timestamps' => true
64
- }
65
- }
66
- assert_order_placement_success(expected_body)
67
- end
68
-
69
- it 'must default to account balance if payment property not set' do
70
- VCR.insert_cassette 'submit_tc_order_without_specifying_payment'
71
-
72
- request = Rev::OrderRequest.new(
73
- :transcription_options => transcription_options
74
- )
75
-
76
- new_order_num = client.submit_order(request)
77
-
78
- new_order_num.must_equal 'TC0406615008'
79
- expected_body = {
80
- 'payment' => {
81
- 'type' => 'AccountBalance'
82
- },
83
- 'priority' => Rev::OrderRequest::PRIORITY[:normal],
84
- 'transcription_options' => {
85
- 'inputs' => [
86
- { 'external_link' => 'http://www.youtube.com/watch?v=UF8uR6Z6KLc' },
87
- { 'external_link' => 'https://vimeo.com/7976699', 'audio_length_seconds' => 900 }
88
- ],
89
- 'verbatim' => true,
90
- 'timestamps' => true
91
- }
92
- }
93
- assert_order_placement_success(expected_body)
94
- end
95
-
96
- it 'must raise BadRequest error in case of request validation failure' do
97
- VCR.insert_cassette 'submit_tc_order_with_invalid_request'
98
-
99
- # example - missing transcription options
100
- request = Rev::OrderRequest.new
101
-
102
- action = lambda { client.submit_order(request) }
103
- exception = action.must_raise Rev::BadRequestError
104
- exception.message.must_match '10004: You must specify either translation or transcription options in an order'
105
- exception.code.must_equal Rev::OrderRequestErrorCodes::TC_OR_TR_OPTIONS_NOT_SPECIFIED
106
- end
107
-
108
- it 'must submit translation order with options' do
109
- VCR.insert_cassette 'submit_tr_order'
110
-
111
- request = Rev::OrderRequest.new(
112
- :translation_options => translation_options
113
- )
114
-
115
- new_order_num = client.submit_order(request)
116
-
117
- new_order_num.must_equal 'TR0235803277'
118
- expected_body = {
119
- 'payment' => {
120
- 'type' => 'AccountBalance'
121
- },
122
- 'priority' => Rev::OrderRequest::PRIORITY[:normal],
123
- 'translation_options' => {
124
- 'inputs'=> [
125
- { 'word_length' => 1000, 'uri' => 'urn:rev:inputmedia:SnVwbG9hZHMvMjAxMy0wOS0xNy9lMzk4MWIzNS0wNzM1LTRlMDAtODY1NC1jNWY4ZjE4MzdlMTIvc291cmNlZG9jdW1lbnQucG5n' },
126
- ],
127
- 'source_language_code' => 'es',
128
- 'destination_language_code' => 'en'
129
- }
130
- }
131
- assert_order_placement_success(expected_body)
132
- end
133
-
134
- it 'must submit caption order with options' do
135
- VCR.insert_cassette 'submit_cp_order'
136
-
137
- request = Rev::OrderRequest.new(:caption_options => caption_options)
138
-
139
- new_order_num = client.submit_order(request)
140
-
141
- new_order_num.must_equal 'CP12345'
142
- expected_body = {
143
- 'payment' => {
144
- 'type' => 'AccountBalance'
145
- },
146
- 'priority' => Rev::OrderRequest::PRIORITY[:normal],
147
- 'caption_options' => {
148
- 'inputs'=> [
149
- { 'video_length_seconds' => 900, 'external_link' => 'http://www.youtube.com/watch?v=UF8uR6Z6KLc' }
150
- ],
151
- 'output_file_formats' => [Rev::CaptionOptions::OUTPUT_FILE_FORMATS[:subrip]]
152
- }
153
- }
154
- assert_order_placement_success(expected_body)
155
- end
156
-
157
- it 'must submit subtitle order with options' do
158
- VCR.insert_cassette 'submit_su_order'
159
-
160
- request = Rev::OrderRequest.new(:caption_options => subtitle_options)
161
-
162
- new_order_num = client.submit_order(request)
163
-
164
- new_order_num.must_equal 'CP56789'
165
- expected_body = {
166
- 'payment' => {
167
- 'type' => 'AccountBalance'
168
- },
169
- 'priority' => Rev::OrderRequest::PRIORITY[:normal],
170
- 'caption_options' => {
171
- 'inputs'=> [
172
- { 'video_length_seconds' => 900, 'external_link' => 'http://www.youtube.com/watch?v=UF8uR6Z6KLc' }
173
- ],
174
- 'subtitle_languages' => ['es','it'],
175
- 'output_file_formats' => [Rev::CaptionOptions::OUTPUT_FILE_FORMATS[:subrip]]
176
- }
177
- }
178
- assert_order_placement_success(expected_body)
179
- end
180
-
181
- after do
182
- VCR.eject_cassette
183
- end
184
-
185
- private
186
-
187
- def assert_order_placement_success(expected_body)
188
- assert_requested(:post, /.*\/orders/, :times => 1) do |req|
189
- req.headers['Content-Type'].must_equal 'application/json'
190
- actual_body = JSON.load req.body
191
- actual_body.must_equal expected_body
192
- end
193
- end
194
-
195
- end
1
+ require_relative '../../spec_helper'
2
+
3
+ describe 'POST /orders' do
4
+ let(:client) { Rev.new('welcome', 'AAAAAu/YjZ3phXU5FsF35yIcgiA=', 'www.revtrunk.com') }
5
+
6
+ # some defaults we use often
7
+ let(:billing_address) { Rev::BillingAddress.new(
8
+ :street => '123 Pine Lane',
9
+ :street2 => 'Apt D',
10
+ :city => 'MyTown',
11
+ :state => 'MN',
12
+ :zip => '12345',
13
+ :country_alpha2 => 'US'
14
+ )}
15
+
16
+ let(:balance_payment) { Rev::Payment.new(Rev::Payment::TYPES[:account_balance]) }
17
+ let(:transcription_inputs) {
18
+ inputs = []
19
+ inputs << Rev::Input.new(:external_link => 'http://www.youtube.com/watch?v=UF8uR6Z6KLc')
20
+ inputs << Rev::Input.new(:audio_length_seconds => 900, :external_link => 'https://vimeo.com/7976699')
21
+ }
22
+ let(:translation_inputs) {
23
+ inputs = []
24
+ inputs << Rev::Input.new(:word_length => 1000, :uri => 'urn:rev:inputmedia:SnVwbG9hZHMvMjAxMy0wOS0xNy9lMzk4MWIzNS0wNzM1LTRlMDAtODY1NC1jNWY4ZjE4MzdlMTIvc291cmNlZG9jdW1lbnQucG5n')
25
+ }
26
+ let(:caption_inputs) {
27
+ inputs = []
28
+ inputs << Rev::Input.new(:video_length_seconds => 900, :external_link => 'http://www.youtube.com/watch?v=UF8uR6Z6KLc')
29
+ }
30
+ let(:transcription_options) { Rev::TranscriptionOptions.new(transcription_inputs,
31
+ :verbatim => true, :timestamps => true) }
32
+ let(:translation_options) { Rev::TranslationOptions.new(translation_inputs,
33
+ :source_language_code => 'es', :destination_language_code => 'en') }
34
+ let(:caption_options) {
35
+ Rev::CaptionOptions.new(caption_inputs, :output_file_formats => ['SubRip'])
36
+ }
37
+ let(:subtitle_options) {
38
+ Rev::CaptionOptions.new(caption_inputs, :subtitle_languages => ['es','it'],
39
+ :output_file_formats => ['SubRip'])
40
+ }
41
+
42
+ it 'must place order using account balance' do
43
+ VCR.insert_cassette 'submit_tc_order_with_account_balance'
44
+
45
+ request = Rev::OrderRequest.new(
46
+ :transcription_options => transcription_options
47
+ )
48
+
49
+ new_order_num = client.submit_order(request)
50
+
51
+ new_order_num.must_equal 'TC0406615008'
52
+ expected_body = {
53
+ 'payment' => {
54
+ 'type' => 'AccountBalance'
55
+ },
56
+ 'non_standard_tat_guarantee' => false,
57
+ 'transcription_options' => {
58
+ 'inputs' => [
59
+ { 'external_link' => 'http://www.youtube.com/watch?v=UF8uR6Z6KLc' },
60
+ { 'external_link' => 'https://vimeo.com/7976699', 'audio_length_seconds' => 900 }
61
+ ],
62
+ 'verbatim' => true,
63
+ 'timestamps' => true
64
+ }
65
+ }
66
+ assert_order_placement_success(expected_body)
67
+ end
68
+
69
+ it 'must default to account balance if payment property not set' do
70
+ VCR.insert_cassette 'submit_tc_order_without_specifying_payment'
71
+
72
+ request = Rev::OrderRequest.new(
73
+ :transcription_options => transcription_options
74
+ )
75
+
76
+ new_order_num = client.submit_order(request)
77
+
78
+ new_order_num.must_equal 'TC0406615008'
79
+ expected_body = {
80
+ 'payment' => {
81
+ 'type' => 'AccountBalance'
82
+ },
83
+ 'non_standard_tat_guarantee' => false,
84
+ 'transcription_options' => {
85
+ 'inputs' => [
86
+ { 'external_link' => 'http://www.youtube.com/watch?v=UF8uR6Z6KLc' },
87
+ { 'external_link' => 'https://vimeo.com/7976699', 'audio_length_seconds' => 900 }
88
+ ],
89
+ 'verbatim' => true,
90
+ 'timestamps' => true
91
+ }
92
+ }
93
+ assert_order_placement_success(expected_body)
94
+ end
95
+
96
+ it 'must raise BadRequest error in case of request validation failure' do
97
+ VCR.insert_cassette 'submit_tc_order_with_invalid_request'
98
+
99
+ # example - missing transcription options
100
+ request = Rev::OrderRequest.new
101
+
102
+ action = lambda { client.submit_order(request) }
103
+ exception = action.must_raise Rev::BadRequestError
104
+ exception.message.must_match '10004: You must specify either translation or transcription options in an order'
105
+ exception.code.must_equal Rev::OrderRequestErrorCodes::TC_OR_TR_OPTIONS_NOT_SPECIFIED
106
+ end
107
+
108
+ it 'must submit translation order with options' do
109
+ VCR.insert_cassette 'submit_tr_order'
110
+
111
+ request = Rev::OrderRequest.new(
112
+ :translation_options => translation_options
113
+ )
114
+
115
+ new_order_num = client.submit_order(request)
116
+
117
+ new_order_num.must_equal 'TR0235803277'
118
+ expected_body = {
119
+ 'payment' => {
120
+ 'type' => 'AccountBalance'
121
+ },
122
+ 'non_standard_tat_guarantee' => false,
123
+ 'translation_options' => {
124
+ 'inputs'=> [
125
+ { 'word_length' => 1000, 'uri' => 'urn:rev:inputmedia:SnVwbG9hZHMvMjAxMy0wOS0xNy9lMzk4MWIzNS0wNzM1LTRlMDAtODY1NC1jNWY4ZjE4MzdlMTIvc291cmNlZG9jdW1lbnQucG5n' },
126
+ ],
127
+ 'source_language_code' => 'es',
128
+ 'destination_language_code' => 'en'
129
+ }
130
+ }
131
+ assert_order_placement_success(expected_body)
132
+ end
133
+
134
+ it 'must submit caption order with options' do
135
+ VCR.insert_cassette 'submit_cp_order'
136
+
137
+ request = Rev::OrderRequest.new(:caption_options => caption_options)
138
+
139
+ new_order_num = client.submit_order(request)
140
+
141
+ new_order_num.must_equal 'CP12345'
142
+ expected_body = {
143
+ 'payment' => {
144
+ 'type' => 'AccountBalance'
145
+ },
146
+ 'non_standard_tat_guarantee' => false,
147
+ 'caption_options' => {
148
+ 'inputs'=> [
149
+ { 'video_length_seconds' => 900, 'external_link' => 'http://www.youtube.com/watch?v=UF8uR6Z6KLc' }
150
+ ],
151
+ 'output_file_formats' => [Rev::CaptionOptions::OUTPUT_FILE_FORMATS[:subrip]]
152
+ }
153
+ }
154
+ assert_order_placement_success(expected_body)
155
+ end
156
+
157
+ it 'must submit subtitle order with options' do
158
+ VCR.insert_cassette 'submit_su_order'
159
+
160
+ request = Rev::OrderRequest.new(:caption_options => subtitle_options)
161
+
162
+ new_order_num = client.submit_order(request)
163
+
164
+ new_order_num.must_equal 'CP56789'
165
+ expected_body = {
166
+ 'payment' => {
167
+ 'type' => 'AccountBalance'
168
+ },
169
+ 'non_standard_tat_guarantee' => false,
170
+ 'caption_options' => {
171
+ 'inputs'=> [
172
+ { 'video_length_seconds' => 900, 'external_link' => 'http://www.youtube.com/watch?v=UF8uR6Z6KLc' }
173
+ ],
174
+ 'subtitle_languages' => ['es','it'],
175
+ 'output_file_formats' => [Rev::CaptionOptions::OUTPUT_FILE_FORMATS[:subrip]]
176
+ }
177
+ }
178
+ assert_order_placement_success(expected_body)
179
+ end
180
+
181
+ after do
182
+ VCR.eject_cassette
183
+ end
184
+
185
+ private
186
+
187
+ def assert_order_placement_success(expected_body)
188
+ assert_requested(:post, /.*\/orders/, :times => 1) do |req|
189
+ req.headers['Content-Type'].must_equal 'application/json'
190
+ actual_body = JSON.load req.body
191
+ actual_body.must_equal expected_body
192
+ end
193
+ end
194
+
195
+ end
@@ -1,49 +1,49 @@
1
- require 'coveralls'
2
- Coveralls.wear!
3
-
4
- require_relative '../lib/rev-api'
5
-
6
- #dependencies
7
- require 'minitest/autorun'
8
- require 'webmock/minitest'
9
- require 'vcr'
10
- require 'turn'
11
-
12
- module MiniTest
13
- class Spec
14
- class << self
15
- def xit(desc='anonymous')
16
- it(name) { skip 'DISABLED' }
17
- end
18
- end
19
- end
20
- end
21
-
22
- Turn.config do |c|
23
- c.format = :outline
24
- c.trace = false
25
- c.natural = true
26
- end
27
-
28
-
29
- VCR.configure do |c|
30
- c.cassette_library_dir = 'spec/fixtures/api_cassettes'
31
- c.default_cassette_options = { :record => :once, :allow_unused_http_interactions => false,
32
- :match_requests_on => [:method, :uri, :rev_headers] }
33
- c.hook_into :webmock
34
- c.ignore_hosts 'www.example.com' # used to stub requests manually, see http_client_spec
35
-
36
- # http://ruby-doc.org/stdlib-2.0.0/libdoc/net/http/rdoc/Net/HTTP.html#label-Compression - we ignore 'Accept-Encoding'
37
- c.register_request_matcher :rev_headers do |actual_request, expected_request|
38
- actual_request.headers.delete 'Accept-Encoding'
39
-
40
- # ignore specific version of a client recorded
41
- actual_user_agent = actual_request.headers['User-Agent'].to_s.split('/').first
42
- expected_user_agent = actual_request.headers['User-Agent'].to_s.split('/').first
43
-
44
- actual_request.headers.delete 'User-Agent'
45
- expected_request.headers.delete 'User-Agent'
46
-
47
- actual_request.headers == expected_request.headers# && actual_user_agent == expected_user_agent
48
- end
49
- end
1
+ require 'coveralls'
2
+ Coveralls.wear!
3
+
4
+ require_relative '../lib/rev-api'
5
+
6
+ #dependencies
7
+ require 'minitest/autorun'
8
+ require 'webmock/minitest'
9
+ require 'vcr'
10
+ require 'turn'
11
+
12
+ module MiniTest
13
+ class Spec
14
+ class << self
15
+ def xit(desc='anonymous')
16
+ it(name) { skip 'DISABLED' }
17
+ end
18
+ end
19
+ end
20
+ end
21
+
22
+ Turn.config do |c|
23
+ c.format = :outline
24
+ c.trace = false
25
+ c.natural = true
26
+ end
27
+
28
+
29
+ VCR.configure do |c|
30
+ c.cassette_library_dir = 'spec/fixtures/api_cassettes'
31
+ c.default_cassette_options = { :record => :once, :allow_unused_http_interactions => false,
32
+ :match_requests_on => [:method, :uri, :rev_headers] }
33
+ c.hook_into :webmock
34
+ c.ignore_hosts 'www.example.com' # used to stub requests manually, see http_client_spec
35
+
36
+ # http://ruby-doc.org/stdlib-2.0.0/libdoc/net/http/rdoc/Net/HTTP.html#label-Compression - we ignore 'Accept-Encoding'
37
+ c.register_request_matcher :rev_headers do |actual_request, expected_request|
38
+ actual_request.headers.delete 'Accept-Encoding'
39
+
40
+ # ignore specific version of a client recorded
41
+ actual_user_agent = actual_request.headers['User-Agent'].to_s.split('/').first
42
+ expected_user_agent = actual_request.headers['User-Agent'].to_s.split('/').first
43
+
44
+ actual_request.headers.delete 'User-Agent'
45
+ expected_request.headers.delete 'User-Agent'
46
+
47
+ actual_request.headers == expected_request.headers# && actual_user_agent == expected_user_agent
48
+ end
49
+ end