rdstation-ruby-client 1.0.1 → 1.1.0

Sign up to get free protection for your applications and to get access to all the features.
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA1:
3
- metadata.gz: ea20e4d5e37030b98d697da5b71892ff892a3204
4
- data.tar.gz: 027a431a05b01d94279b40d194d334d8a5235cf4
3
+ metadata.gz: e3abd8cbbff8541804f9098ccf8076025404e9fd
4
+ data.tar.gz: 303aed653c2a72f186bdbfc2b1dea8f56c7ff55d
5
5
  SHA512:
6
- metadata.gz: 7a1bedc3f94bd5f532ab9073d0abc9651ef1a9159e0b339b13b9061e8c476967683b5a66bb659a12a6848fc7396a854be6153655acab97bef9f205ad50ada11b
7
- data.tar.gz: ebbf843ae9cc9293850070b0b40cf638a8e1a7e61655f2022def1d01e3987b78dd2a4227e43ccb403a28d3e941f3813238595b542b6978433ecc86e1462fdd20
6
+ metadata.gz: 752ad7a2b479d064dfc176f2299f31035a51bfff11dbf71f3bf96fd813ac840524125789a035880a613b1c77b79ca8698b0b40687afb9ef28eee4ab4da1f6807
7
+ data.tar.gz: 1494b26e7d0867b640e8ea4deab9e57b8fb716417a194c821a9e77f7a9ebc8bce1057910be8e10908afde16b1ab347b28add6feacbb1f8b49818adb76019aace
@@ -4,6 +4,7 @@ require 'httparty'
4
4
  require 'rdstation/authentication'
5
5
  require 'rdstation/client'
6
6
  require 'rdstation/contacts'
7
+ require 'rdstation/events'
7
8
  require 'rdstation/fields'
8
9
 
9
10
  # Error handling
@@ -23,6 +23,7 @@ module RDStation
23
23
  class ExpiredAccessToken < Error; end
24
24
  class ExpiredCodeGrant < Error; end
25
25
  class InvalidCredentials < Error; end
26
+ class InvalidEventType < Error; end
26
27
  class ResourceNotFound < Error; end
27
28
  class Unauthorized < Error; end
28
29
  end
@@ -3,27 +3,29 @@ require_relative './format'
3
3
  module RDStation
4
4
  class Error
5
5
  class Formatter
6
- def initialize(errors)
7
- @errors = errors
6
+ def initialize(error_response)
7
+ @error_response = error_response
8
8
  end
9
9
 
10
10
  def to_array
11
+ return @error_response unless @error_response.is_a?(Hash)
12
+
11
13
  case error_format.format
12
14
  when RDStation::Error::Format::FLAT_HASH
13
- from_flat_hash
15
+ return from_flat_hash
14
16
  when RDStation::Error::Format::HASH_OF_ARRAYS
15
- from_hash_of_arrays
16
- else
17
- @errors
17
+ return from_hash_of_arrays
18
18
  end
19
+
20
+ errors
19
21
  end
20
22
 
21
23
  def from_flat_hash
22
- [@errors]
24
+ [errors]
23
25
  end
24
26
 
25
27
  def from_hash_of_arrays
26
- @errors.each_with_object([]) do |errors, array_of_errors|
28
+ errors.each_with_object([]) do |errors, array_of_errors|
27
29
  attribute_name = errors.first
28
30
  attribute_errors = errors.last
29
31
  path = { 'path' => "body.#{attribute_name}" }
@@ -33,7 +35,11 @@ module RDStation
33
35
  end
34
36
 
35
37
  def error_format
36
- @error_format ||= RDStation::Error::Format.new(@errors)
38
+ @error_format ||= RDStation::Error::Format.new(errors)
39
+ end
40
+
41
+ def errors
42
+ @errors ||= @error_response['errors']
37
43
  end
38
44
  end
39
45
  end
@@ -4,6 +4,7 @@ require_relative 'error_handler/default'
4
4
  require_relative 'error_handler/expired_access_token'
5
5
  require_relative 'error_handler/expired_code_grant'
6
6
  require_relative 'error_handler/invalid_credentials'
7
+ require_relative 'error_handler/invalid_event_type'
7
8
  require_relative 'error_handler/resource_not_found'
8
9
  require_relative 'error_handler/unauthorized'
9
10
 
@@ -14,6 +15,7 @@ module RDStation
14
15
  ErrorHandler::ExpiredAccessToken,
15
16
  ErrorHandler::ExpiredCodeGrant,
16
17
  ErrorHandler::InvalidCredentials,
18
+ ErrorHandler::InvalidEventType,
17
19
  ErrorHandler::ResourceNotFound,
18
20
  ErrorHandler::Unauthorized,
19
21
  ErrorHandler::Default
@@ -42,7 +44,7 @@ module RDStation
42
44
  end
43
45
 
44
46
  def response_errors
45
- JSON.parse(response.body)['errors']
47
+ JSON.parse(response.body)
46
48
  end
47
49
 
48
50
  def error_formatter
@@ -0,0 +1,27 @@
1
+ module RDStation
2
+ class ErrorHandler
3
+ class InvalidEventType
4
+ attr_reader :errors
5
+
6
+ ERROR_CODE = 'INVALID_OPTION'.freeze
7
+ PATH = '$.event_type'.freeze
8
+
9
+ def initialize(errors)
10
+ @errors = errors
11
+ end
12
+
13
+ def raise_error
14
+ return if invalid_event_type_error.empty?
15
+ raise RDStation::Error::InvalidEventType, invalid_event_type_error.first
16
+ end
17
+
18
+ private
19
+
20
+ def invalid_event_type_error
21
+ errors.select do |error|
22
+ error.values_at('error_type', 'path') == [ERROR_CODE, PATH]
23
+ end
24
+ end
25
+ end
26
+ end
27
+ end
@@ -0,0 +1,33 @@
1
+ # encoding: utf-8
2
+ module RDStation
3
+ # More info: https://developers.rdstation.com/pt-BR/reference/contacts
4
+ class Events
5
+ include HTTParty
6
+
7
+ EVENTS_ENDPOINT = 'https://api.rd.services/platform/events'.freeze
8
+
9
+ def initialize(auth_token)
10
+ @auth_token = auth_token
11
+ end
12
+
13
+ def create(payload)
14
+ response = self.class.post(EVENTS_ENDPOINT, headers: required_headers, body: payload.to_json)
15
+ response_body = JSON.parse(response.body)
16
+ return response_body unless errors?(response_body)
17
+ RDStation::ErrorHandler.new(response).raise_errors
18
+ end
19
+
20
+ private
21
+
22
+ def errors?(response_body)
23
+ response_body.is_a?(Array) || response_body['errors']
24
+ end
25
+
26
+ def required_headers
27
+ {
28
+ 'Authorization' => "Bearer #{@auth_token}",
29
+ 'Content-Type' => 'application/json'
30
+ }
31
+ end
32
+ end
33
+ end
@@ -1,3 +1,3 @@
1
1
  module RDStation
2
- VERSION = '1.0.1'.freeze
2
+ VERSION = '1.1.0'.freeze
3
3
  end
@@ -9,14 +9,16 @@ RSpec.describe RDStation::Error::Formatter do
9
9
  context 'when receives a flat hash of errors' do
10
10
  let(:error_format) { instance_double(RDStation::Error::Format, format: RDStation::Error::Format::FLAT_HASH) }
11
11
 
12
- let(:errors) do
12
+ let(:error_response) do
13
13
  {
14
- 'error_type' => 'CONFLICTING_FIELD',
15
- 'error_message' => 'The payload contains an attribute that was used to identify the lead'
14
+ 'errors' => {
15
+ 'error_type' => 'CONFLICTING_FIELD',
16
+ 'error_message' => 'The payload contains an attribute that was used to identify the lead'
17
+ }
16
18
  }
17
19
  end
18
20
 
19
- let(:error_formatter) { described_class.new(errors) }
21
+ let(:error_formatter) { described_class.new(error_response) }
20
22
 
21
23
  let(:expected_result) do
22
24
  [
@@ -27,7 +29,7 @@ RSpec.describe RDStation::Error::Formatter do
27
29
  ]
28
30
  end
29
31
 
30
- it 'returns an array of errors including the status code and headers' do
32
+ it 'returns an array of errors' do
31
33
  result = error_formatter.to_array
32
34
  expect(result).to eq(expected_result)
33
35
  end
@@ -36,18 +38,20 @@ RSpec.describe RDStation::Error::Formatter do
36
38
  context 'when receives a hash of arrays of errors' do
37
39
  let(:error_format) { instance_double(RDStation::Error::Format, format: RDStation::Error::Format::HASH_OF_ARRAYS) }
38
40
 
39
- let(:errors) do
41
+ let(:error_response) do
40
42
  {
41
- 'name' => [
42
- {
43
- 'error_type' => 'MUST_BE_STRING',
44
- 'error_message' => 'Name must be string.'
45
- }
46
- ]
43
+ 'errors' => {
44
+ 'name' => [
45
+ {
46
+ 'error_type' => 'MUST_BE_STRING',
47
+ 'error_message' => 'Name must be string.'
48
+ }
49
+ ]
50
+ }
47
51
  }
48
52
  end
49
53
 
50
- let(:error_formatter) { described_class.new(errors) }
54
+ let(:error_formatter) { described_class.new(error_response) }
51
55
 
52
56
  let(:expected_result) do
53
57
  [
@@ -59,16 +63,49 @@ RSpec.describe RDStation::Error::Formatter do
59
63
  ]
60
64
  end
61
65
 
62
- it 'returns an array of errors including the status code and headers' do
66
+ it 'returns an array of errors' do
63
67
  result = error_formatter.to_array
64
68
  expect(result).to eq(expected_result)
65
69
  end
66
70
  end
67
71
 
68
- context 'when receives an array of errors' do
72
+ context 'when receives an array of errors inside the "errors" key' do
69
73
  let(:error_format) { instance_double(RDStation::Error::Format, format: RDStation::Error::Format::ARRAY_OF_HASHES) }
70
74
 
71
- let(:errors) do
75
+ let(:error_response) do
76
+ {
77
+ 'errors' => [
78
+ {
79
+ 'error_type' => 'CANNOT_BE_NULL',
80
+ 'error_message' => 'Cannot be null.',
81
+ 'path' => 'body.client_secret'
82
+ }
83
+ ]
84
+ }
85
+ end
86
+
87
+ let(:error_formatter) { described_class.new(error_response) }
88
+
89
+ let(:expected_result) do
90
+ [
91
+ {
92
+ 'error_type' => 'CANNOT_BE_NULL',
93
+ 'error_message' => 'Cannot be null.',
94
+ 'path' => 'body.client_secret'
95
+ }
96
+ ]
97
+ end
98
+
99
+ it 'returns an array of errors' do
100
+ result = error_formatter.to_array
101
+ expect(result).to eq(expected_result)
102
+ end
103
+ end
104
+
105
+ context 'when receives a pure array of errors' do
106
+ let(:error_format) { '' }
107
+
108
+ let(:error_response) do
72
109
  [
73
110
  {
74
111
  'error_type' => 'CANNOT_BE_NULL',
@@ -78,7 +115,7 @@ RSpec.describe RDStation::Error::Formatter do
78
115
  ]
79
116
  end
80
117
 
81
- let(:error_formatter) { described_class.new(errors) }
118
+ let(:error_formatter) { described_class.new(error_response) }
82
119
 
83
120
  let(:expected_result) do
84
121
  [
@@ -90,7 +127,7 @@ RSpec.describe RDStation::Error::Formatter do
90
127
  ]
91
128
  end
92
129
 
93
- it 'returns an array of errors including the status code and headers' do
130
+ it 'returns an array of errors' do
94
131
  result = error_formatter.to_array
95
132
  expect(result).to eq(expected_result)
96
133
  end
@@ -0,0 +1,54 @@
1
+ require 'spec_helper'
2
+
3
+ RSpec.describe RDStation::ErrorHandler::InvalidEventType do
4
+ describe '#raise_error' do
5
+ subject(:invalid_event_type_error) { described_class.new(errors) }
6
+
7
+ context 'when there is a invalid event type error' do
8
+ let(:errors) do
9
+ [
10
+ {
11
+ 'error_message' => 'Error Message',
12
+ 'error_type' => 'INVALID_OPTION',
13
+ 'path' => '$.event_type'
14
+ }
15
+ ]
16
+ end
17
+
18
+ it 'raises an InvalidEventType error' do
19
+ expect do
20
+ invalid_event_type_error.raise_error
21
+ end.to raise_error(RDStation::Error::InvalidEventType, 'Error Message')
22
+ end
23
+ end
24
+
25
+ context 'when none of the errors are invalid event type errors' do
26
+ let(:errors) do
27
+ [
28
+ {
29
+ 'error_message' => 'Error Message',
30
+ 'error_type' => 'RANDOM_ERROR_TYPE'
31
+ },
32
+ {
33
+ 'error_message' => 'Another Error Message',
34
+ 'error_type' => 'ANOTHER_RANDOM_ERROR_TYPE'
35
+ }
36
+ ]
37
+ end
38
+
39
+ it 'does not raise an InvalidEventType error' do
40
+ result = invalid_event_type_error.raise_error
41
+ expect(result).to be_nil
42
+ end
43
+ end
44
+
45
+ context 'when there are no errors' do
46
+ let(:errors) { [] }
47
+
48
+ it 'does not raise an InvalidEventType error' do
49
+ result = invalid_event_type_error.raise_error
50
+ expect(result).to be_nil
51
+ end
52
+ end
53
+ end
54
+ end
@@ -0,0 +1,175 @@
1
+ require 'spec_helper'
2
+
3
+ RSpec.describe RDStation::Events do
4
+ let(:valid_auth_token) { 'valid_auth_token' }
5
+ let(:invalid_auth_token) { 'invalid_auth_token' }
6
+ let(:expired_auth_token) { 'expired_auth_token' }
7
+
8
+ let(:event_with_valid_token) { described_class.new(valid_auth_token) }
9
+ let(:event_with_expired_token) { described_class.new(expired_auth_token) }
10
+ let(:event_with_invalid_token) { described_class.new(invalid_auth_token) }
11
+
12
+ let(:events_endpoint) { 'https://api.rd.services/platform/events' }
13
+
14
+ let(:valid_event_types) do
15
+ %w[
16
+ OPPORTUNITY_LOST
17
+ EMAIL_DELIVERED
18
+ DOUBLE_OPT_IN_EMAIL_CONFIRMED
19
+ OPPORTUNITY
20
+ CART_ABANDONED_ITEM
21
+ FUNNEL_STAGE_CHANGED
22
+ MEDIA_PLAYBACK_STOPPED
23
+ CONVERSION
24
+ MEDIA_PLAYBACK_STARTED
25
+ SALE
26
+ WORKFLOW_STARTED
27
+ EMAIL_SPAM_REPORTED
28
+ ORDER_PLACED
29
+ EMAIL_SOFT_BOUNCED
30
+ CART_ABANDONED
31
+ EMAIL_OPENED
32
+ EMAIL_DROPPED
33
+ EMAIL_HARD_BOUNCED
34
+ WORKFLOW_FINISHED
35
+ WORKFLOW_CANCELED
36
+ EMAIL_CLICKED
37
+ ORDER_PLACED_ITEM
38
+ CHAT_STARTED
39
+ CHAT_FINISHED
40
+ EMAIL_UNSUBSCRIBED
41
+ PAGE_VISITED
42
+ CALL_FINISHED
43
+ ]
44
+ end
45
+
46
+ let(:valid_headers) do
47
+ {
48
+ 'Authorization' => "Bearer #{valid_auth_token}",
49
+ 'Content-Type' => 'application/json'
50
+ }
51
+ end
52
+
53
+ let(:invalid_token_headers) do
54
+ {
55
+ 'Authorization' => "Bearer #{invalid_auth_token}",
56
+ 'Content-Type' => 'application/json'
57
+ }
58
+ end
59
+
60
+ let(:expired_token_headers) do
61
+ {
62
+ 'Authorization' => "Bearer #{expired_auth_token}",
63
+ 'Content-Type' => 'application/json'
64
+ }
65
+ end
66
+
67
+ let(:invalid_token_response) do
68
+ {
69
+ status: 401,
70
+ body: {
71
+ errors: {
72
+ error_type: 'UNAUTHORIZED',
73
+ error_message: 'Invalid token.'
74
+ }
75
+ }.to_json
76
+ }
77
+ end
78
+
79
+ let(:expired_token_response) do
80
+ {
81
+ status: 401,
82
+ headers: { 'WWW-Authenticate' => 'Bearer realm="https://api.rd.services/", error="expired_token", error_description="The access token expired"' },
83
+ body: {
84
+ errors: {
85
+ error_type: 'UNAUTHORIZED',
86
+ error_message: 'Invalid token.'
87
+ }
88
+ }.to_json
89
+ }
90
+ end
91
+
92
+ describe '#create' do
93
+ let(:event) do
94
+ {
95
+ 'event_type' => 'OPPORTUNITY_LOST',
96
+ 'event_family' => 'CDP',
97
+ 'payload' => {
98
+ 'email' => 'email@email.com',
99
+ 'funnel_name' => 'default',
100
+ 'reason' => 'Lost reason'
101
+ }
102
+ }
103
+ end
104
+
105
+ context 'with a valid auth token' do
106
+ before do
107
+ stub_request(:post, events_endpoint)
108
+ .with(headers: valid_headers)
109
+ .to_return(status: 200, body: event.to_json)
110
+ end
111
+
112
+ it 'returns the event uuid' do
113
+ # {"event_uuid":"830eacd4-6859-43b5-82ef-d2989db38604"}
114
+ response = event_with_valid_token.create(event)
115
+ expect(response).to eq(event)
116
+ end
117
+ end
118
+
119
+ context 'with an invalid auth token' do
120
+ before do
121
+ stub_request(:post, events_endpoint)
122
+ .with(headers: invalid_token_headers)
123
+ .to_return(invalid_token_response)
124
+ end
125
+
126
+ it 'raises an invalid token error' do
127
+ expect do
128
+ event_with_invalid_token.create(event)
129
+ end.to raise_error(RDStation::Error::Unauthorized)
130
+ end
131
+ end
132
+
133
+ context 'with an expired auth token' do
134
+ before do
135
+ stub_request(:post, events_endpoint)
136
+ .with(headers: expired_token_headers)
137
+ .to_return(expired_token_response)
138
+ end
139
+
140
+ it 'raises a expired token error' do
141
+ expect do
142
+ event_with_expired_token.create(event)
143
+ end.to raise_error(RDStation::Error::ExpiredAccessToken)
144
+ end
145
+ end
146
+
147
+ context 'when the event type is incorrect' do
148
+ let(:invalid_event_type_response) do
149
+ {
150
+ status: 400,
151
+ body: [
152
+ {
153
+ 'error_type' => 'INVALID_OPTION',
154
+ 'error_message' => 'Must be one of the valid options.',
155
+ 'validation_rules' => { 'valid_options' => valid_event_types },
156
+ 'path' => '$.event_type'
157
+ }
158
+ ].to_json
159
+ }
160
+ end
161
+
162
+ before do
163
+ stub_request(:post, events_endpoint)
164
+ .with(headers: valid_headers)
165
+ .to_return(invalid_event_type_response)
166
+ end
167
+
168
+ it 'raises an invalid event type error' do
169
+ expect do
170
+ event_with_valid_token.create(event)
171
+ end.to raise_error(RDStation::Error::InvalidEventType)
172
+ end
173
+ end
174
+ end
175
+ end
metadata CHANGED
@@ -1,14 +1,14 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: rdstation-ruby-client
3
3
  version: !ruby/object:Gem::Version
4
- version: 1.0.1
4
+ version: 1.1.0
5
5
  platform: ruby
6
6
  authors:
7
7
  - Paulo L F Casaretto
8
8
  autorequire:
9
9
  bindir: bin
10
10
  cert_chain: []
11
- date: 2018-11-29 00:00:00.000000000 Z
11
+ date: 2018-12-05 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: bundler
@@ -120,8 +120,10 @@ files:
120
120
  - lib/rdstation/error_handler/expired_access_token.rb
121
121
  - lib/rdstation/error_handler/expired_code_grant.rb
122
122
  - lib/rdstation/error_handler/invalid_credentials.rb
123
+ - lib/rdstation/error_handler/invalid_event_type.rb
123
124
  - lib/rdstation/error_handler/resource_not_found.rb
124
125
  - lib/rdstation/error_handler/unauthorized.rb
126
+ - lib/rdstation/events.rb
125
127
  - lib/rdstation/fields.rb
126
128
  - lib/rdstation/version.rb
127
129
  - rdstation-ruby-client.gemspec
@@ -135,10 +137,12 @@ files:
135
137
  - spec/lib/rdstation/error_handler/expired_access_token_spec.rb
136
138
  - spec/lib/rdstation/error_handler/expired_code_grant_spec.rb
137
139
  - spec/lib/rdstation/error_handler/invalid_credentials_spec.rb
140
+ - spec/lib/rdstation/error_handler/invalid_event_type_spec.rb
138
141
  - spec/lib/rdstation/error_handler/resource_not_found_spec.rb
139
142
  - spec/lib/rdstation/error_handler/unauthorized_spec.rb
140
143
  - spec/lib/rdstation/error_handler_spec.rb
141
144
  - spec/lib/rdstation/error_spec.rb
145
+ - spec/lib/rdstation/events_spec.rb
142
146
  - spec/lib/rdstation/fields_spec.rb
143
147
  - spec/spec_helper.rb
144
148
  homepage: http://resultadosdigitais.com.br
@@ -176,9 +180,11 @@ test_files:
176
180
  - spec/lib/rdstation/error_handler/expired_access_token_spec.rb
177
181
  - spec/lib/rdstation/error_handler/expired_code_grant_spec.rb
178
182
  - spec/lib/rdstation/error_handler/invalid_credentials_spec.rb
183
+ - spec/lib/rdstation/error_handler/invalid_event_type_spec.rb
179
184
  - spec/lib/rdstation/error_handler/resource_not_found_spec.rb
180
185
  - spec/lib/rdstation/error_handler/unauthorized_spec.rb
181
186
  - spec/lib/rdstation/error_handler_spec.rb
182
187
  - spec/lib/rdstation/error_spec.rb
188
+ - spec/lib/rdstation/events_spec.rb
183
189
  - spec/lib/rdstation/fields_spec.rb
184
190
  - spec/spec_helper.rb