rdstation-ruby-client 1.0.1 → 1.1.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
checksums.yaml 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