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.
@@ -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
-