wcc-data 0.3.3 → 0.3.7
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 +4 -4
- data/lib/wcc/data/nucleus/campus.rb +25 -3
- data/lib/wcc/data/version.rb +1 -1
- data/wcc-data.gemspec +2 -3
- metadata +9 -49
- data/.env.example +0 -3
- data/.gitignore +0 -18
- data/.rspec +0 -2
- data/Gemfile +0 -6
- data/Rakefile +0 -36
- data/bin/rspec +0 -17
- data/circle.yml +0 -6
- data/spec/spec_helper.rb +0 -24
- data/spec/support/inheritable_class_attribute_examples.rb +0 -16
- data/spec/wcc/data/config_spec.rb +0 -113
- data/spec/wcc/data/enumerated_type_spec.rb +0 -176
- data/spec/wcc/data/faraday_client_app_token_auth_spec.rb +0 -237
- data/spec/wcc/data/mapper/attributes_spec.rb +0 -94
- data/spec/wcc/data/mapper/json_response_spec.rb +0 -57
- data/spec/wcc/data/mapper/rest_configuration_spec.rb +0 -43
- data/spec/wcc/data/mapper/rest_query_spec.rb +0 -50
- data/spec/wcc/data/model_spec.rb +0 -33
- data/spec/wcc/data/nucleus/campus_spec.rb +0 -34
- data/spec/wcc/data/rack_client_app_token_auth_spec.rb +0 -219
- data/spec/wcc/data/response_spec.rb +0 -57
- data/spec/wcc/data/rest_endpoint_spec.rb +0 -71
- data/spec/wcc/data/service_spec.rb +0 -128
- data/spec/wcc/data_spec.rb +0 -25
@@ -1,237 +0,0 @@
|
|
1
|
-
require 'spec_helper'
|
2
|
-
|
3
|
-
RSpec.describe WCC::Data::FaradayClientAppTokenAuth do
|
4
|
-
let(:app) { spy(:application) }
|
5
|
-
|
6
|
-
describe WCC::Data::FaradayClientAppTokenAuth::RedisCache do
|
7
|
-
let(:connection) { instance_spy(Redis) }
|
8
|
-
let(:connection_lambda) { -> (&blk) { blk.call(connection) } }
|
9
|
-
|
10
|
-
describe "#initialize" do
|
11
|
-
it "requires a callable for Redis connection" do
|
12
|
-
expect { described_class.new }.to raise_error(ArgumentError)
|
13
|
-
obj = described_class.new(connection_lambda)
|
14
|
-
expect(obj.connection).to eq(connection_lambda)
|
15
|
-
end
|
16
|
-
|
17
|
-
it "allows setting a :cache_key option to change the token store" do
|
18
|
-
obj = described_class.new(connection_lambda, cache_key: "store")
|
19
|
-
expect(obj.cache_key).to eq("store")
|
20
|
-
end
|
21
|
-
|
22
|
-
it "defaults to the value of the DEFAULT_CACHE_KEY constant" do
|
23
|
-
obj = described_class.new(connection_lambda)
|
24
|
-
expect(obj.cache_key).to eq(described_class::DEFAULT_CACHE_KEY)
|
25
|
-
end
|
26
|
-
end
|
27
|
-
|
28
|
-
describe "#[]" do
|
29
|
-
subject(:cache) { described_class.new(connection_lambda) }
|
30
|
-
|
31
|
-
it "returns HGET on the cache_key for the specified field" do
|
32
|
-
expect(connection)
|
33
|
-
.to receive(:hget).with(cache.cache_key, "example.com").and_return("123abc")
|
34
|
-
expect(cache["example.com"]).to eq("123abc")
|
35
|
-
end
|
36
|
-
end
|
37
|
-
|
38
|
-
describe "#[]=" do
|
39
|
-
subject(:cache) { described_class.new(connection_lambda) }
|
40
|
-
|
41
|
-
it "does HSET on the cache_key for the specified field and value" do
|
42
|
-
cache["example.com"] = "abc123"
|
43
|
-
expect(connection)
|
44
|
-
.to have_received(:hset).with(cache.cache_key, "example.com", "abc123")
|
45
|
-
end
|
46
|
-
|
47
|
-
context "with a nil value" do
|
48
|
-
it "does HDEL on the cache_key for the specified field" do
|
49
|
-
cache["example.com"] = nil
|
50
|
-
expect(connection)
|
51
|
-
.to have_received(:hdel).with(cache.cache_key, "example.com")
|
52
|
-
end
|
53
|
-
end
|
54
|
-
end
|
55
|
-
end
|
56
|
-
|
57
|
-
describe "#initialize" do
|
58
|
-
it "takes an app as param one and sets to @app" do
|
59
|
-
obj = described_class.new(:app)
|
60
|
-
expect(obj.send(:instance_variable_get, :@app)).to eq(:app)
|
61
|
-
end
|
62
|
-
|
63
|
-
it "takes a :cache option" do
|
64
|
-
obj = described_class.new(:app, cache: :cache)
|
65
|
-
expect(obj.cache).to eq(:cache)
|
66
|
-
end
|
67
|
-
|
68
|
-
it "takes a :token_factory option" do
|
69
|
-
obj = described_class.new(:app, token_factory: :factory)
|
70
|
-
expect(obj.token_factory).to eq(:factory)
|
71
|
-
end
|
72
|
-
|
73
|
-
it "defaults :cache option to an instance of RedisCache" do
|
74
|
-
obj = described_class.new(:app)
|
75
|
-
expect(obj.cache).to be_a(described_class::RedisCache)
|
76
|
-
expect(obj.cache.connection).to eq(Sidekiq.method(:redis))
|
77
|
-
end
|
78
|
-
|
79
|
-
it "defaults :token_factory option to a callable" do
|
80
|
-
obj = described_class.new(:app)
|
81
|
-
expect(obj.token_factory).to respond_to(:call)
|
82
|
-
end
|
83
|
-
|
84
|
-
describe "default token_factory" do
|
85
|
-
it "returns #token property from a Nucleus::ClientAppToken create" do
|
86
|
-
token = instance_spy(WCC::Data::Nucleus::ClientAppToken)
|
87
|
-
|
88
|
-
expect(WCC::Data::Nucleus::ClientAppToken)
|
89
|
-
.to receive(:create).with(hostname: "example.com").and_return(token)
|
90
|
-
expect(token).to receive(:token).and_return("abc123")
|
91
|
-
expect(described_class.new(:app).token_factory.("example.com"))
|
92
|
-
.to eq("abc123")
|
93
|
-
end
|
94
|
-
end
|
95
|
-
end
|
96
|
-
|
97
|
-
describe "#call" do
|
98
|
-
let(:app) { spy(:application) }
|
99
|
-
subject(:auth) { described_class.new(app) }
|
100
|
-
let(:env) {
|
101
|
-
{
|
102
|
-
url: URI("http://example.com"),
|
103
|
-
request_headers: {},
|
104
|
-
}
|
105
|
-
}
|
106
|
-
|
107
|
-
before do
|
108
|
-
allow(auth)
|
109
|
-
.to receive(:token_for).with("example.com").and_return("abc123")
|
110
|
-
end
|
111
|
-
|
112
|
-
it "sets env's Authorization header using value from #token_for" do
|
113
|
-
auth.call(env)
|
114
|
-
expect(env[:request_headers]["Authorization"])
|
115
|
-
.to eq("Bearer abc123")
|
116
|
-
end
|
117
|
-
|
118
|
-
it "calls @app with env" do
|
119
|
-
expect(app).to receive(:call).with(env)
|
120
|
-
auth.call(env)
|
121
|
-
end
|
122
|
-
|
123
|
-
it "adds an on_complete handler to @app" do
|
124
|
-
allow(app).to receive(:call).and_return(app).ordered
|
125
|
-
expect(app).to receive(:on_complete).ordered
|
126
|
-
auth.call(env)
|
127
|
-
end
|
128
|
-
|
129
|
-
describe "on_complete handler" do
|
130
|
-
subject(:auth) { described_class.new(app, cache: cache) }
|
131
|
-
let(:cache) { instance_spy(described_class::RedisCache) }
|
132
|
-
let(:handler) {
|
133
|
-
handler = nil
|
134
|
-
allow(app).to receive(:call).and_return(app)
|
135
|
-
allow(app).to receive(:on_complete) { |&block| handler = block }
|
136
|
-
|
137
|
-
auth.call(env)
|
138
|
-
|
139
|
-
handler
|
140
|
-
}
|
141
|
-
|
142
|
-
it "removes value from cache when response is unsuccessful" do
|
143
|
-
expect(cache).to receive(:[]=).with("example.com", nil).exactly(2).times
|
144
|
-
handler.(status: 200)
|
145
|
-
handler.(status: 400)
|
146
|
-
handler.(status: 500)
|
147
|
-
end
|
148
|
-
|
149
|
-
it "retries the request after clearing the cache on a 403 response" do
|
150
|
-
expect(app).to receive(:call).with(env).ordered
|
151
|
-
expect(cache).to receive(:[]=).with("example.com", nil).ordered
|
152
|
-
expect(app).to receive(:call).with(env).ordered
|
153
|
-
handler.(status: 403)
|
154
|
-
end
|
155
|
-
end
|
156
|
-
|
157
|
-
class FakeApp
|
158
|
-
attr_accessor :response
|
159
|
-
def initialize(response)
|
160
|
-
@response = response
|
161
|
-
end
|
162
|
-
def call(request)
|
163
|
-
@request = request
|
164
|
-
self
|
165
|
-
end
|
166
|
-
def on_complete
|
167
|
-
@request[:body] = "response"
|
168
|
-
yield(response)
|
169
|
-
end
|
170
|
-
end
|
171
|
-
|
172
|
-
describe "multiple 403 errors" do
|
173
|
-
subject(:auth) { described_class.new(app, cache: cache, token_factory: -> (_) { "value" }) }
|
174
|
-
let(:cache) { instance_spy(described_class::RedisCache) }
|
175
|
-
let(:app) { FakeApp.new(body: "response", status: 403) }
|
176
|
-
|
177
|
-
it "doesn't retry forever" do
|
178
|
-
auth.call(env)
|
179
|
-
end
|
180
|
-
|
181
|
-
it "resets the body to original request body" do
|
182
|
-
expect(app).to receive(:call).with(hash_including(body: "request")).twice.and_call_original
|
183
|
-
auth.call(env.merge(body: "request"))
|
184
|
-
end
|
185
|
-
end
|
186
|
-
end
|
187
|
-
|
188
|
-
describe "#token_for" do
|
189
|
-
let(:cache) { instance_spy(described_class::RedisCache) }
|
190
|
-
subject(:auth) { described_class.new(:app, cache: cache) }
|
191
|
-
|
192
|
-
context "when cache is non-nil" do
|
193
|
-
before do
|
194
|
-
allow(cache).to receive(:[]).with("example.com").and_return("abc123")
|
195
|
-
end
|
196
|
-
|
197
|
-
it "returns value from cache" do
|
198
|
-
expect(auth.token_for("example.com")).to eq("abc123")
|
199
|
-
end
|
200
|
-
|
201
|
-
it "does not call @token_factory" do
|
202
|
-
expect(auth.token_factory).to_not receive(:call)
|
203
|
-
auth.token_for("example.com")
|
204
|
-
end
|
205
|
-
end
|
206
|
-
|
207
|
-
context "when cache is empty" do
|
208
|
-
before do
|
209
|
-
allow(cache).to receive(:[]).and_return(nil)
|
210
|
-
allow(auth.token_factory)
|
211
|
-
.to receive(:call).with("example.com").and_return("abc123")
|
212
|
-
end
|
213
|
-
|
214
|
-
it "calls @token_factory with passed host" do
|
215
|
-
expect(auth.token_for("example.com")).to eq("abc123")
|
216
|
-
end
|
217
|
-
|
218
|
-
it "stores the value in the cache" do
|
219
|
-
expect(cache).to receive(:[]=).with("example.com", "abc123")
|
220
|
-
auth.token_for("example.com")
|
221
|
-
end
|
222
|
-
|
223
|
-
it "passes error up the chain when service unavailable" do
|
224
|
-
allow(auth.token_factory)
|
225
|
-
.to receive(:call)
|
226
|
-
.and_raise(WCC::Data::Mapper::ServiceUnavailable)
|
227
|
-
|
228
|
-
expect {
|
229
|
-
auth.call({
|
230
|
-
url: URI("http://example.com"),
|
231
|
-
request_headers: {},
|
232
|
-
})
|
233
|
-
}.to raise_error(WCC::Data::Mapper::ServiceUnavailable)
|
234
|
-
end
|
235
|
-
end
|
236
|
-
end
|
237
|
-
end
|
@@ -1,94 +0,0 @@
|
|
1
|
-
require 'spec_helper'
|
2
|
-
|
3
|
-
describe WCC::Data::Mapper::Attributes do
|
4
|
-
let(:klass) {
|
5
|
-
Class.new do
|
6
|
-
include WCC::Data::Mapper::Attributes
|
7
|
-
end
|
8
|
-
}
|
9
|
-
|
10
|
-
describe "::attribute" do
|
11
|
-
subject { klass }
|
12
|
-
it_behaves_like :inheritable_class_attributes, :attributes
|
13
|
-
|
14
|
-
it "takes a name and optional options and stores them in ::attributes" do
|
15
|
-
subject.attribute :name, foo: :bar
|
16
|
-
expect(subject.attributes).to eq("name" => { foo: :bar })
|
17
|
-
end
|
18
|
-
|
19
|
-
it "freezes the options hash" do
|
20
|
-
subject.attribute :name
|
21
|
-
expect { subject.attributes["name"][:foo] = "foo" }.to raise_error(RuntimeError)
|
22
|
-
end
|
23
|
-
|
24
|
-
it "defines an instance method by the same name" do
|
25
|
-
expect(subject.new).to_not respond_to(:name)
|
26
|
-
subject.attribute :name
|
27
|
-
expect(subject.new).to respond_to(:name)
|
28
|
-
end
|
29
|
-
|
30
|
-
context "defined instance method" do
|
31
|
-
it "returns the value set on the instance for this attribute" do
|
32
|
-
subject.attribute :name
|
33
|
-
obj = subject.new("name" => "foo")
|
34
|
-
expect(obj.name).to eq("foo")
|
35
|
-
end
|
36
|
-
end
|
37
|
-
|
38
|
-
context "with writer option" do
|
39
|
-
it "defines a writer instance method" do
|
40
|
-
subject.attribute :name, writer: true
|
41
|
-
obj = subject.new("name" => "foo")
|
42
|
-
obj.name = "bar"
|
43
|
-
expect(obj.name).to eq("bar")
|
44
|
-
end
|
45
|
-
end
|
46
|
-
end
|
47
|
-
|
48
|
-
describe "#initialize" do
|
49
|
-
subject { klass }
|
50
|
-
|
51
|
-
it "takes a hash of attributes and sets it to @attributes" do
|
52
|
-
obj = subject.new(foo: :bar)
|
53
|
-
expect(obj.attributes).to eq(foo: :bar)
|
54
|
-
end
|
55
|
-
end
|
56
|
-
|
57
|
-
describe "#[]" do
|
58
|
-
before(:each) do
|
59
|
-
klass.attribute :name
|
60
|
-
end
|
61
|
-
subject { klass.new("name" => "foo", "other" => :value) }
|
62
|
-
|
63
|
-
it "returns raw values of defined attributes" do
|
64
|
-
expect(subject[:name]).to eq("foo")
|
65
|
-
expect(subject["name"]).to eq("foo")
|
66
|
-
end
|
67
|
-
|
68
|
-
it "returns a key error for undefined attributes" do
|
69
|
-
expect { subject[:other] }.to raise_error(KeyError)
|
70
|
-
end
|
71
|
-
end
|
72
|
-
|
73
|
-
describe "#[]=" do
|
74
|
-
before(:each) do
|
75
|
-
klass.attribute :name
|
76
|
-
end
|
77
|
-
subject { klass.new("name" => "foo", "other" => :value) }
|
78
|
-
|
79
|
-
it "sets raw values of defined attributes" do
|
80
|
-
subject[:name] = "value1"
|
81
|
-
expect(subject[:name]).to eq("value1")
|
82
|
-
end
|
83
|
-
|
84
|
-
it "allows string values as key" do
|
85
|
-
subject["name"] = "value1"
|
86
|
-
expect(subject[:name]).to eq("value1")
|
87
|
-
end
|
88
|
-
|
89
|
-
it "returns a key error for undefined attributes" do
|
90
|
-
expect { subject[:other] = "value" }.to raise_error(KeyError)
|
91
|
-
end
|
92
|
-
end
|
93
|
-
|
94
|
-
end
|
@@ -1,57 +0,0 @@
|
|
1
|
-
require 'spec_helper'
|
2
|
-
|
3
|
-
describe WCC::Data::Mapper::JSONResponse do
|
4
|
-
let(:klass) {
|
5
|
-
Class.new do
|
6
|
-
extend WCC::Data::Mapper::JSONResponse
|
7
|
-
|
8
|
-
attr_accessor :val
|
9
|
-
def initialize(val=nil) @val = val end
|
10
|
-
end
|
11
|
-
}
|
12
|
-
|
13
|
-
describe "::new_from_response" do
|
14
|
-
let(:singular_response) {
|
15
|
-
double(json: { key: "value" }, status: 200)
|
16
|
-
}
|
17
|
-
let(:plural_response) {
|
18
|
-
double(json: [
|
19
|
-
{ name: "abc" },
|
20
|
-
{ name: "def" },
|
21
|
-
], status: 200)
|
22
|
-
}
|
23
|
-
|
24
|
-
it "returns a new instance from singular response" do
|
25
|
-
obj = klass.new_from_response(singular_response)
|
26
|
-
expect(obj).to be_a(klass)
|
27
|
-
expect(obj.val).to eq(singular_response.json)
|
28
|
-
end
|
29
|
-
|
30
|
-
it "returns array of instances from array response" do
|
31
|
-
obj = klass.new_from_response(plural_response)
|
32
|
-
expect(obj).to be_a(Array)
|
33
|
-
expect(obj[0].val).to eq(plural_response.json[0])
|
34
|
-
expect(obj[1].val).to eq(plural_response.json[1])
|
35
|
-
end
|
36
|
-
|
37
|
-
it "raises RecordNotFound when response status is 404" do
|
38
|
-
allow(singular_response).to receive(:status).and_return(404)
|
39
|
-
expect { klass.new_from_response(singular_response) }
|
40
|
-
.to raise_error(WCC::Data::Mapper::RecordNotFound)
|
41
|
-
|
42
|
-
end
|
43
|
-
|
44
|
-
it "raises ServiceUnavailable when response status is 503" do
|
45
|
-
allow(singular_response).to receive(:status).and_return(503)
|
46
|
-
expect { klass.new_from_response(singular_response) }
|
47
|
-
.to raise_error(WCC::Data::Mapper::ServiceUnavailable)
|
48
|
-
|
49
|
-
end
|
50
|
-
|
51
|
-
it "raises InvalidResponse error for non-json objects" do
|
52
|
-
expect { klass.new_from_response(double(json: 1, status: 200)) }
|
53
|
-
.to raise_error(WCC::Data::Mapper::InvalidResponse)
|
54
|
-
end
|
55
|
-
end
|
56
|
-
|
57
|
-
end
|
@@ -1,43 +0,0 @@
|
|
1
|
-
require 'spec_helper'
|
2
|
-
|
3
|
-
describe WCC::Data::Mapper::RESTConfiguration do
|
4
|
-
let(:klass) {
|
5
|
-
Class.new.tap do |klass|
|
6
|
-
klass.extend described_class
|
7
|
-
end
|
8
|
-
}
|
9
|
-
subject { klass }
|
10
|
-
before(:each) do
|
11
|
-
WCC::Data.config.applications[:rest_configuration_test].uri = "http://test.app/"
|
12
|
-
subject.set_endpoint(:rest_configuration_test, "bar/")
|
13
|
-
end
|
14
|
-
after(:each) do
|
15
|
-
WCC::Data.config.applications.delete(:rest_configuration_test)
|
16
|
-
end
|
17
|
-
|
18
|
-
describe "::set_endpoint" do
|
19
|
-
it_behaves_like :inheritable_class_attributes, :endpoint_config
|
20
|
-
|
21
|
-
it "sets @endpoint_config hash with values from args" do
|
22
|
-
expect(subject.endpoint_config).to eq(app: :rest_configuration_test, uri: "bar/")
|
23
|
-
end
|
24
|
-
end
|
25
|
-
|
26
|
-
describe "::endpoint" do
|
27
|
-
it "returns instance of RESTEndpoint" do
|
28
|
-
expect(subject.endpoint).to be_a(WCC::Data::RESTEndpoint)
|
29
|
-
end
|
30
|
-
|
31
|
-
it "sets service using appname and provided URI string" do
|
32
|
-
expect(subject.endpoint.service.uri).to eq(URI("http://test.app/bar/"))
|
33
|
-
end
|
34
|
-
end
|
35
|
-
|
36
|
-
context "lazy configuration" do
|
37
|
-
it "sets endpoint data only when endpoint is called" do
|
38
|
-
WCC::Data.config.applications[:rest_configuration_test].uri = "http://new.test.app/"
|
39
|
-
expect(subject.endpoint.service.uri).to eq(URI("http://new.test.app/bar/"))
|
40
|
-
end
|
41
|
-
end
|
42
|
-
|
43
|
-
end
|
@@ -1,50 +0,0 @@
|
|
1
|
-
require 'spec_helper'
|
2
|
-
|
3
|
-
describe WCC::Data::Mapper::RESTQuery do
|
4
|
-
let(:klass) {
|
5
|
-
Class.new.tap do |klass|
|
6
|
-
klass.extend described_class
|
7
|
-
end
|
8
|
-
}
|
9
|
-
|
10
|
-
let(:endpoint) { double(:endpoint) }
|
11
|
-
before(:each) do
|
12
|
-
allow(klass).to receive(:endpoint) { endpoint }
|
13
|
-
end
|
14
|
-
|
15
|
-
shared_examples_for :handles_undefined_endpoint do |method, args|
|
16
|
-
let(:endpoint) { nil }
|
17
|
-
it "raises an EndpointUndefined exception" do
|
18
|
-
expect { klass.send(method, *args) }.to raise_error(WCC::Data::Mapper::EndpointUndefined)
|
19
|
-
end
|
20
|
-
end
|
21
|
-
|
22
|
-
describe "::find" do
|
23
|
-
it_behaves_like :handles_undefined_endpoint, :find, :id_param
|
24
|
-
|
25
|
-
it "calls show(id) on defined endpoint and builds on response" do
|
26
|
-
expect(endpoint).to receive(:show).with(:id_param).and_return(:response)
|
27
|
-
expect(klass).to receive(:new_from_response).with(:response).and_return(:new_response)
|
28
|
-
expect(klass.find(:id_param)).to eq(:new_response)
|
29
|
-
end
|
30
|
-
end
|
31
|
-
|
32
|
-
describe "::list" do
|
33
|
-
it_behaves_like :handles_undefined_endpoint, :list, :params
|
34
|
-
|
35
|
-
it "calls index(params) on defined endpoint and builds on response" do
|
36
|
-
expect(endpoint).to receive(:index).with(params: :params).and_return(:response)
|
37
|
-
expect(klass).to receive(:new_from_response).with(:response).and_return(:new_response)
|
38
|
-
expect(klass.list(:params)).to eq(:new_response)
|
39
|
-
end
|
40
|
-
|
41
|
-
it "allows calling with no params" do
|
42
|
-
expect(endpoint).to receive(:index).with(params: {})
|
43
|
-
expect(klass).to receive(:new_from_response)
|
44
|
-
klass.list
|
45
|
-
end
|
46
|
-
|
47
|
-
end
|
48
|
-
|
49
|
-
end
|
50
|
-
|