crystal_sdk 0.0.4 → 1.0.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: 5bacb9a91dadcdcc60eb24dd15eedcd61d25c5f3
4
- data.tar.gz: 33b610a788337ff076b128d651bf1a7150c8c2ef
3
+ metadata.gz: ed49b547a11579d80d9aa3c96dab61019d0dd47b
4
+ data.tar.gz: 49afdf1d21487a6d4def81f564feb3eec54dfc54
5
5
  SHA512:
6
- metadata.gz: 966cc07acc85cfd463c7f33b021294519c4d92f0d6cebe7bc1db209c036c1091c53b74cce502405c8e862295fe0db41385f822d7d1475373317227171f5d77e2
7
- data.tar.gz: c75662264040de042eca6e8034e054eb2da837c5be5f948aa4c4727e59be4551a206b5c65240d7f2d3b2f49eb415fd9802c78ea62f29595c35239f461109c704
6
+ metadata.gz: 55a5a0ca2e44a4df1cf4b3455703da564ffc32a39fd22e2d020c5c2a05ab9ef8b7f89e0f0559c371e64ae84bb2b5f5270ac5043efed0ea92ec7a05703519e68d
7
+ data.tar.gz: 13a84fc643b862bde2f5f3a7f7cf8cd3cf292379233d23e13324ba1a05c76ec00f919fe0b4d01a94e57bd4d8914abf1ce745b226de9d5652be19bcc5c4e2a8e7
data/Gemfile.lock CHANGED
@@ -1,7 +1,7 @@
1
1
  PATH
2
2
  remote: .
3
3
  specs:
4
- crystal_sdk (0.0.3)
4
+ crystal_sdk (1.0.0)
5
5
  nestful (~> 1.1)
6
6
  recursive-open-struct (~> 1.0)
7
7
 
@@ -0,0 +1,19 @@
1
+ module CrystalSDK
2
+ class Api
3
+ def self.make_request(type, endpoint, params: {}, headers: {})
4
+ headers = headers.merge(
5
+ 'X-Org-Token' => Base.key!,
6
+ 'X-Sdk-Version' => VERSION
7
+ )
8
+
9
+ opts = {
10
+ method: type,
11
+ headers: headers,
12
+ params: params,
13
+ format: :json
14
+ }
15
+
16
+ Nestful::Request.new("#{Base::API_URL}/#{endpoint}", opts).execute
17
+ end
18
+ end
19
+ end
@@ -1,7 +1,7 @@
1
1
  module CrystalSDK
2
2
  class Base
3
3
  class ApiKeyNotSet < StandardError; end
4
- API_URL = 'http://enterprise-api.crystalknows.com/v1'.freeze
4
+ API_URL = 'https://connect.crystalknows.com/v1'.freeze
5
5
 
6
6
  class << self
7
7
  attr_accessor :key
@@ -0,0 +1,60 @@
1
+ require 'recursive-open-struct'
2
+ require 'crystal_sdk/api'
3
+
4
+ module CrystalSDK
5
+ class Profile
6
+ class Request
7
+ attr_reader :id
8
+
9
+ def initialize(id)
10
+ @id = id
11
+ end
12
+
13
+ def self.from_search(query)
14
+ resp = Api.make_request(:post, 'profile_search/async', params: query)
15
+ body = JSON.parse(resp.body || '{}', symbolize_names: true)
16
+
17
+ Profile::Request.new(body[:request_id])
18
+ end
19
+
20
+ def fetch_request_info
21
+ return @cached_data if @cached_data
22
+
23
+ resp = Api.make_request(:get, "results/#{@id}")
24
+ body = resp.body ? JSON.parse(resp.body, symbolize_names: true) : nil
25
+
26
+ if body[:status] == 'complete' || body[:status] == 'error'
27
+ @cached_data = body
28
+ end
29
+
30
+ body
31
+ end
32
+
33
+ def fetch_status
34
+ fetch_request_info[:status]
35
+ end
36
+
37
+ def did_finish?
38
+ status = fetch_status
39
+ status == 'complete' || status == 'error'
40
+ end
41
+
42
+ def did_find_profile?
43
+ return false unless did_finish? && fetch_status == 'complete'
44
+
45
+ info = fetch_request_info
46
+ !info[:data][:info][:error]
47
+ end
48
+
49
+ def profile_info
50
+ return nil unless did_find_profile?
51
+
52
+ req_info = fetch_request_info
53
+ profile_info = RecursiveOpenStruct.new(req_info[:data][:info])
54
+ recommendations = RecursiveOpenStruct.new(req_info[:data][:recommendations])
55
+
56
+ { info: profile_info, recommendations: recommendations }
57
+ end
58
+ end
59
+ end
60
+ end
@@ -1,3 +1,3 @@
1
1
  module CrystalSDK
2
- VERSION = '0.0.4'.freeze
2
+ VERSION = '1.0.0'.freeze
3
3
  end
@@ -0,0 +1,95 @@
1
+ require 'spec_helper'
2
+
3
+ describe CrystalSDK::Api do
4
+ subject { CrystalSDK::Api }
5
+
6
+ describe '.make_request' do
7
+ context 'without api key' do
8
+ it 'should raise an error' do
9
+ expect { subject.make_request(:post, 'test') }
10
+ .to raise_error(CrystalSDK::Base::ApiKeyNotSet)
11
+ end
12
+ end
13
+
14
+ context 'with api key' do
15
+ subject { CrystalSDK::Api.make_request(:post, 'test_endpoint') }
16
+
17
+ let(:headers) do
18
+ {
19
+ 'X-Org-Token' => 'SomeToken',
20
+ 'X-Sdk-Version' => CrystalSDK::VERSION
21
+ }
22
+ end
23
+
24
+ let(:stubbed_req) do
25
+ stub_request(:post, "#{CrystalSDK::Base::API_URL}/test_endpoint")
26
+ .with(headers: headers)
27
+ end
28
+
29
+ before(:each) do
30
+ allow(CrystalSDK::Base).to receive(:key).and_return('SomeToken')
31
+ end
32
+
33
+ context 'got 4xx response code' do
34
+ it 'should raise an error' do
35
+ stubbed_req
36
+ .to_return(status: 404, body: '{}', headers: {})
37
+
38
+ expect { subject }.to raise_error
39
+ end
40
+ end
41
+
42
+ context 'got 5xx response code' do
43
+ it 'should raise error on 5xx responses' do
44
+ stubbed_req
45
+ .to_return(status: 500, body: '{}', headers: {})
46
+
47
+ expect { subject }.to raise_error
48
+ end
49
+ end
50
+
51
+ context 'got 2xx response code' do
52
+ it 'should return correct response' do
53
+ stubbed_req
54
+ .to_return(status: 200, body: 'stubbed', headers: {})
55
+
56
+ expect(subject.code).to eql(200)
57
+ expect(subject.body).to eql('stubbed')
58
+ end
59
+ end
60
+
61
+ context 'given params' do
62
+ subject do
63
+ CrystalSDK::Api
64
+ .make_request(:post, 'test_endpoint', params: params)
65
+ end
66
+ let(:params) { { some_param: '123'} }
67
+
68
+ it 'should turn params into json body' do
69
+ stubbed_req
70
+ .with(body: params.to_json)
71
+ .to_return(status: 200, body: 'stubbed', headers: {})
72
+
73
+ expect { subject }.to_not raise_error
74
+ end
75
+ end
76
+
77
+
78
+ context 'given headers' do
79
+ subject do
80
+ CrystalSDK::Api
81
+ .make_request(:post, 'test_endpoint', headers: headers)
82
+ end
83
+ let(:headers) { { 'X-Some-Header' => '123' } }
84
+
85
+ it 'should turn params into json body' do
86
+ stubbed_req
87
+ .with(headers: headers)
88
+ .to_return(status: 200, body: 'stubbed', headers: {})
89
+
90
+ expect { subject }.to_not raise_error
91
+ end
92
+ end
93
+ end
94
+ end
95
+ end
@@ -11,7 +11,7 @@ describe CrystalSDK::Base do
11
11
  subject { CrystalSDK::Base::API_URL }
12
12
 
13
13
  it { is_expected.to include '.crystalknows.com' }
14
- # it { is_expected.to start_with 'https://' }
14
+ it { is_expected.to start_with 'https://' }
15
15
  it { is_expected.to_not end_with '/' }
16
16
  end
17
17
 
@@ -0,0 +1,252 @@
1
+ require 'spec_helper'
2
+
3
+ describe CrystalSDK::Profile::Request do
4
+ subject { CrystalSDK::Profile::Request }
5
+
6
+ it 'should initialize properly' do
7
+ req = subject.new("an_id")
8
+ expect(req.id).to eql("an_id")
9
+ end
10
+
11
+ describe '.from_search' do
12
+ subject { CrystalSDK::Profile::Request.from_search(query) }
13
+ let(:query) { { first_name: 'Test', last_name: 'Test' } }
14
+ let(:request_type) { :post }
15
+ let(:endpoint) { 'profile_search/async' }
16
+
17
+ context 'CrystalSDK::Api raises exception' do
18
+ it 'should not suppress it' do
19
+ allow(CrystalSDK::Api).to receive(:make_request)
20
+ .with(request_type, endpoint, params: query)
21
+ .and_raise('SomeRandomError')
22
+
23
+ expect { subject }.to raise_error('SomeRandomError')
24
+ end
25
+ end
26
+
27
+ context 'CrystalSDK::Api returns invalid json body' do
28
+ it 'should raise error' do
29
+ allow(CrystalSDK::Api).to receive(:make_request)
30
+ .with(request_type, endpoint, params: query)
31
+ .and_return(double(body: 'pie'))
32
+
33
+ expect { subject }.to raise_error
34
+ end
35
+ end
36
+
37
+ context 'CrystalSDK::Api returns valid json body' do
38
+ it 'should return request object' do
39
+ allow(CrystalSDK::Api).to receive(:make_request)
40
+ .with(request_type, endpoint, params: query)
41
+ .and_return(double(body: '{}'))
42
+
43
+ expect(subject).to be_kind_of(CrystalSDK::Profile::Request)
44
+ end
45
+ end
46
+ end
47
+
48
+ describe '#fetch_request_info' do
49
+ subject { CrystalSDK::Profile::Request.new('my_id').fetch_request_info() }
50
+ let(:request_type) { :get }
51
+ let(:endpoint) { 'results/my_id' }
52
+
53
+ context 'CrystalSDK::Api raises exception' do
54
+ it 'should not suppress it' do
55
+ allow(CrystalSDK::Api).to receive(:make_request)
56
+ .with(request_type, endpoint)
57
+ .and_raise('SomeRandomError')
58
+
59
+ expect { subject }.to raise_error('SomeRandomError')
60
+ end
61
+ end
62
+
63
+ context 'CrystalSDK::Api returns invalid json body' do
64
+ it 'should raise error' do
65
+ allow(CrystalSDK::Api).to receive(:make_request)
66
+ .with(request_type, endpoint)
67
+ .and_return(double(body: 'pie'))
68
+
69
+ expect { subject }.to raise_error
70
+ end
71
+ end
72
+
73
+ context 'CrystalSDK::Api returns valid json body' do
74
+ it 'should return request object' do
75
+ allow(CrystalSDK::Api).to receive(:make_request)
76
+ .with(request_type, endpoint)
77
+ .and_return(double(body: '{"something": true}'))
78
+
79
+ expect(subject).to eql({ something: true })
80
+ end
81
+
82
+ context 'status is "complete"' do
83
+ it 'should cache' do
84
+ allow(CrystalSDK::Api).to receive(:make_request)
85
+ .with(request_type, endpoint)
86
+ .and_return(double(body: '{"status": "complete"}'))
87
+
88
+ expect(subject).to eql({ status: 'complete' })
89
+
90
+ allow(CrystalSDK::Api).to receive(:make_request)
91
+ .with(request_type, endpoint)
92
+ .and_return(double(body: '{"status": "failure"}'))
93
+
94
+ expect(subject).to eql({ status: 'complete' })
95
+ end
96
+ end
97
+
98
+ context 'status is "error"' do
99
+ it 'should cache' do
100
+ allow(CrystalSDK::Api).to receive(:make_request)
101
+ .with(request_type, endpoint)
102
+ .and_return(double(body: '{"status": "error"}'))
103
+
104
+ expect(subject).to eql({ status: 'error' })
105
+
106
+ allow(CrystalSDK::Api).to receive(:make_request)
107
+ .with(request_type, endpoint)
108
+ .and_return(double(body: '{"status": "failure"}'))
109
+
110
+ expect(subject).to eql({ status: 'error' })
111
+ end
112
+ end
113
+ end
114
+ end
115
+
116
+ describe '#fetch_status' do
117
+ let(:request) { CrystalSDK::Profile::Request.new('my_id') }
118
+ subject { request.fetch_status }
119
+
120
+ it 'should pull :status from #fetch_request_info' do
121
+ allow(request).to receive(:fetch_request_info)
122
+ .and_return({status: 'testing'})
123
+
124
+ expect(subject).to eql('testing')
125
+ end
126
+ end
127
+
128
+ describe '#did_finish?' do
129
+ let(:request) { CrystalSDK::Profile::Request.new('my_id') }
130
+ subject { request.did_finish? }
131
+
132
+ context '#fetch_status returns "complete"' do
133
+ before(:each) do
134
+ allow(request).to receive(:fetch_status).and_return('complete')
135
+ end
136
+
137
+ it { is_expected.to eql(true) }
138
+ end
139
+
140
+ context '#fetch_status returns "error"' do
141
+ before(:each) do
142
+ allow(request).to receive(:fetch_status).and_return('error')
143
+ end
144
+
145
+ it { is_expected.to eql(true) }
146
+ end
147
+
148
+ context '#fetch_status returns something else' do
149
+ before(:each) do
150
+ allow(request).to receive(:fetch_status).and_return('something')
151
+ end
152
+
153
+ it { is_expected.to eql(false) }
154
+ end
155
+ end
156
+
157
+ describe '#did_find_profile?' do
158
+ let(:request) { CrystalSDK::Profile::Request.new('my_id') }
159
+ subject { request.did_find_profile? }
160
+
161
+ context '#did_finish? is false' do
162
+ it 'should return false' do
163
+ allow(request).to receive(:did_finish?).and_return(false)
164
+
165
+ expect(subject).to eql(false)
166
+ end
167
+ end
168
+
169
+ context '#did_finish? is true' do
170
+ before(:each) do
171
+ allow(request).to receive(:did_finish?).and_return(true)
172
+ end
173
+
174
+ context '#fetch_status is not "complete"' do
175
+ before(:each) do
176
+ allow(request).to receive(:fetch_status).and_return('something')
177
+ end
178
+
179
+ it { is_expected.to eql(false) }
180
+ end
181
+
182
+ context '#fetch_status is "complete"' do
183
+ before(:each) do
184
+ allow(request).to receive(:fetch_status).and_return('complete')
185
+ end
186
+
187
+ context '#fetch_request_info error is not nil' do
188
+ before(:each) do
189
+ allow(request).to receive(:fetch_request_info).and_return({
190
+ data: { info: { error: 'error' } }
191
+ })
192
+ end
193
+
194
+ it { is_expected.to eql(false) }
195
+ end
196
+
197
+ context '#fetch_request_info error is nil' do
198
+ before(:each) do
199
+ allow(request).to receive(:fetch_request_info).and_return({
200
+ data: { info: { error: nil } }
201
+ })
202
+ end
203
+
204
+ it { is_expected.to eql(true) }
205
+ end
206
+ end
207
+ end
208
+ end
209
+
210
+ describe '#profile_info' do
211
+ let(:request) { CrystalSDK::Profile::Request.new('my_id') }
212
+ subject { request.profile_info }
213
+
214
+ context '#did_find_profile? is false' do
215
+ before(:each) do
216
+ allow(request).to receive(:did_find_profile?).and_return(false)
217
+ end
218
+
219
+ it { is_expected.to eql(nil) }
220
+ end
221
+
222
+ context '#did_find_profile? is true' do
223
+ before(:each) do
224
+ allow(request).to receive(:did_find_profile?).and_return(true)
225
+ allow(request).to receive(:fetch_request_info).and_return({
226
+ data: {
227
+ info: {
228
+ some_info: 'some_info',
229
+ deep_info: {
230
+ info: 'deep_info'
231
+ }
232
+ },
233
+
234
+ recommendations: {
235
+ some_recs: 'some_recs',
236
+ deep_recs: {
237
+ recs: 'deep_recs'
238
+ }
239
+ }
240
+ }
241
+ })
242
+ end
243
+
244
+ it 'should return hash with deep openstruct values' do
245
+ expect(subject[:info].some_info).to eql('some_info')
246
+ expect(subject[:info].deep_info.info).to eql('deep_info')
247
+ expect(subject[:recommendations].some_recs).to eql('some_recs')
248
+ expect(subject[:recommendations].deep_recs.recs).to eql('deep_recs')
249
+ end
250
+ end
251
+ end
252
+ end
metadata CHANGED
@@ -1,7 +1,7 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: crystal_sdk
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.0.4
4
+ version: 1.0.0
5
5
  platform: ruby
6
6
  authors:
7
7
  - Cory Finger
@@ -83,10 +83,14 @@ files:
83
83
  - Rakefile
84
84
  - crystal_sdk.gemspec
85
85
  - lib/crystal_sdk.rb
86
+ - lib/crystal_sdk/api.rb
86
87
  - lib/crystal_sdk/base.rb
87
88
  - lib/crystal_sdk/profile.rb
89
+ - lib/crystal_sdk/profile/request.rb
88
90
  - lib/crystal_sdk/version.rb
91
+ - spec/crystal_sdk/api_spec.rb
89
92
  - spec/crystal_sdk/base_spec.rb
93
+ - spec/crystal_sdk/profile/request_spec.rb
90
94
  - spec/crystal_sdk/profile_spec.rb
91
95
  - spec/crystal_sdk/version_spec.rb
92
96
  - spec/crystal_sdk_spec.rb
@@ -116,7 +120,9 @@ signing_key:
116
120
  specification_version: 4
117
121
  summary: Access the largest and most accurate personality database!
118
122
  test_files:
123
+ - spec/crystal_sdk/api_spec.rb
119
124
  - spec/crystal_sdk/base_spec.rb
125
+ - spec/crystal_sdk/profile/request_spec.rb
120
126
  - spec/crystal_sdk/profile_spec.rb
121
127
  - spec/crystal_sdk/version_spec.rb
122
128
  - spec/crystal_sdk_spec.rb