wcc-data 0.3.9 → 0.4.0.pre

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.
@@ -0,0 +1,219 @@
1
+ require 'spec_helper'
2
+
3
+ RSpec.describe WCC::Data::RackClientAppTokenAuth do
4
+
5
+ describe WCC::Data::RackClientAppTokenAuth::RedisCache do
6
+ let(:connection) { instance_spy(Redis) }
7
+ let(:connection_lambda) { -> (&blk) { blk.call(connection) } }
8
+
9
+ describe "#initialize" do
10
+ it "requires a callable for Redis connection" do
11
+ expect { described_class.new }.to raise_error(ArgumentError)
12
+ obj = described_class.new(connection_lambda)
13
+ expect(obj.connection).to eq(connection_lambda)
14
+ end
15
+
16
+ it "allows setting a :cache_key option to change the token store" do
17
+ obj = described_class.new(connection_lambda, cache_key: "store")
18
+ expect(obj.cache_key).to eq("store")
19
+ end
20
+
21
+ it "allows setting the :cache_length" do
22
+ obj = described_class.new(connection_lambda, cache_length: 5)
23
+ expect(obj.cache_length).to eq(5)
24
+ end
25
+
26
+ it "defaults :cache_key to the value of the DEFAULT_CACHE_KEY constant" do
27
+ obj = described_class.new(connection_lambda)
28
+ expect(obj.cache_key).to eq(described_class::DEFAULT_CACHE_KEY)
29
+ end
30
+
31
+ it "defaults :cache_length to the value of DEFAULT_CACHE_LENGTH constant" do
32
+ obj = described_class.new(connection_lambda)
33
+ expect(obj.cache_length).to eq(described_class::DEFAULT_CACHE_LENGTH)
34
+ end
35
+ end
36
+
37
+ describe "#<<" do
38
+ subject(:auth) { described_class.new(connection_lambda, cache_key: "test", cache_length: 123) }
39
+
40
+ it "calls SET with @cache_key joined to token by a dot and set to '1'" do
41
+ auth << "token"
42
+ expect(connection).to have_received(:set).with("test.token", "1")
43
+ end
44
+
45
+ it "calls EXPIRE with the configured cache length" do
46
+ auth << "token"
47
+ expect(connection).to have_received(:expire).with("test.token", 123)
48
+ end
49
+ end
50
+
51
+ describe "#find" do
52
+ subject(:auth) { described_class.new(connection_lambda, cache_key: "test") }
53
+
54
+ it "returns the value from GET on the joined token key" do
55
+ expect(connection).to receive(:get).with("test.token").and_return("1")
56
+ expect(auth.find("token")).to eq("1")
57
+ end
58
+ end
59
+ end
60
+
61
+ describe "#initialize" do
62
+ it "takes an app argument and sets to @app" do
63
+ obj = described_class.new(:app)
64
+ expect(obj.app).to eq(:app)
65
+ end
66
+
67
+ it "takes a :cache option and sets to @cache" do
68
+ obj = described_class.new(:app, cache: :cache)
69
+ expect(obj.cache).to eq(:cache)
70
+ end
71
+
72
+ it "takes a :lookup_token and sets to @lookup_token" do
73
+ obj = described_class.new(:app, lookup_token: :lookup)
74
+ expect(obj.lookup_token).to eq(:lookup)
75
+ end
76
+
77
+ it "defaults :cache option to an instance of RedisCache" do
78
+ obj = described_class.new(:app)
79
+ expect(obj.cache).to be_a(described_class::RedisCache)
80
+ expect(obj.cache.connection).to eq(Sidekiq.method(:redis))
81
+ end
82
+
83
+ describe "default :lookup_token value" do
84
+ it "tries to fetch a token with the given value" do
85
+ expect(WCC::Data::Nucleus::ClientAppToken)
86
+ .to receive(:find).with("abc123").and_return(:val)
87
+ expect(described_class.new(:app).lookup_token.("abc123"))
88
+ .to eq(:val)
89
+ end
90
+
91
+ it "returns nil when InvalidResponse raised" do
92
+ allow(WCC::Data::Nucleus::ClientAppToken)
93
+ .to receive(:find).and_raise(WCC::Data::Mapper::InvalidResponse)
94
+ expect(described_class.new(:app).lookup_token.("abc123"))
95
+ .to be_nil
96
+ end
97
+
98
+ it "returns nil when RecordNotFound raised" do
99
+ allow(WCC::Data::Nucleus::ClientAppToken)
100
+ .to receive(:find).and_raise(WCC::Data::Mapper::RecordNotFound)
101
+ expect(described_class.new(:app).lookup_token.("abc123"))
102
+ .to be_nil
103
+ end
104
+ end
105
+
106
+ end
107
+
108
+ describe "#find" do
109
+ let(:cache) { instance_spy(described_class::RedisCache) }
110
+ subject(:auth) { described_class.new(:app, cache: cache) }
111
+
112
+ context "with token in the cache" do
113
+ before do
114
+ allow(auth.cache).to receive(:find).with("abc123").and_return("1")
115
+ end
116
+
117
+ it "calls find with token on the cache and then returns cached value" do
118
+ expect(auth.find("abc123"))
119
+ .to eq("1")
120
+ end
121
+
122
+ it "does not call lookup_token" do
123
+ expect(auth.lookup_token).to_not receive(:call)
124
+ auth.find("abc123")
125
+ end
126
+ end
127
+
128
+ context "with an empty cache" do
129
+ before do
130
+ allow(cache).to receive(:find).and_return(nil)
131
+ end
132
+
133
+ it "calls lookup_token with the token" do
134
+ expect(auth.lookup_token)
135
+ .to receive(:call).with("abc123").and_return(true)
136
+ expect(auth.find("abc123")).to eq(true)
137
+ end
138
+
139
+ context "with a valid token" do
140
+ before do
141
+ allow(auth.lookup_token).to receive(:call).and_return(true)
142
+ end
143
+
144
+ it "shovels the value into the cache" do
145
+ expect(cache).to receive(:<<).with("abc123")
146
+ auth.find("abc123")
147
+ end
148
+
149
+ it "returns a truthy value" do
150
+ expect(auth.find("abc123")).to be_truthy
151
+ end
152
+ end
153
+
154
+ context "with an invalid token" do
155
+ before do
156
+ allow(auth.lookup_token).to receive(:call).and_return(false)
157
+ end
158
+
159
+ it "does not shovel value into the cache" do
160
+ expect(auth.cache).to_not receive(:<<)
161
+ auth.find("abc123")
162
+ end
163
+
164
+ it "returns a falsey value" do
165
+ expect(auth.find("abc123")).to be_falsey
166
+ end
167
+ end
168
+ end
169
+ end
170
+
171
+ describe "#call" do
172
+ subject(:auth) { described_class.new(-> (env) {}, cache: cache) }
173
+ let(:cache) { instance_spy(described_class::RedisCache) }
174
+ let(:env) {
175
+ {
176
+ "HTTP_AUTHORIZATION" => "Bearer abc123",
177
+ }
178
+ }
179
+
180
+
181
+ it "passes the bearer token onto the find method" do
182
+ expect(auth).to receive(:find).with("abc123")
183
+ auth.call(env)
184
+ end
185
+
186
+ context "truthy find result" do
187
+ before do
188
+ allow(auth).to receive(:find).and_return(true)
189
+ end
190
+
191
+ it "passes the request on to the app" do
192
+ expect(auth.app).to receive(:call).with(env)
193
+ auth.call(env)
194
+ end
195
+
196
+ it "returns the value of app" do
197
+ allow(auth.app).to receive(:call).and_return(:value)
198
+ expect(auth.call(env)).to eq(:value)
199
+ end
200
+ end
201
+
202
+ context "falsey find result" do
203
+ before do
204
+ allow(auth).to receive(:find).and_return(false)
205
+ end
206
+
207
+ it "does not call app" do
208
+ expect(auth.app).to_not receive(:call)
209
+ auth.call(env)
210
+ end
211
+
212
+ it "returns a 403 response" do
213
+ response = auth.call(env)
214
+
215
+ expect(response).to eq([403, {}, ['{"error":"Invalid Bearer Token"}']])
216
+ end
217
+ end
218
+ end
219
+ end
@@ -0,0 +1,57 @@
1
+ require 'spec_helper'
2
+
3
+ describe WCC::Data::Response do
4
+ let(:unit) { WCC::Data::Response }
5
+ let(:raw) { double(:faraday_response) }
6
+ subject { unit.new(raw) }
7
+
8
+ describe "#initialize" do
9
+ it "takes a Faraday response object and sets it to @raw" do
10
+ expect(subject.raw).to eq(raw)
11
+ end
12
+ end
13
+
14
+ describe "method delegation" do
15
+ it "delegates `body` to @raw" do
16
+ expect(raw).to receive(:body).and_return(:value)
17
+ expect(subject.body).to eq(:value)
18
+ expect(subject.respond_to?(:body)).to be_truthy
19
+ end
20
+
21
+ it "delegates `headers` to @raw" do
22
+ expect(raw).to receive(:headers).and_return(:value)
23
+ expect(subject.headers).to eq(:value)
24
+ expect(subject.respond_to?(:headers)).to be_truthy
25
+ end
26
+
27
+ it "delegates `status` to @raw" do
28
+ expect(raw).to receive(:status).and_return(:value)
29
+ expect(subject.status).to eq(:value)
30
+ expect(subject.respond_to?(:status)).to be_truthy
31
+ end
32
+
33
+ it "delegates `success?` to @raw" do
34
+ expect(raw).to receive(:success?).and_return(:value)
35
+ expect(subject.success?).to eq(:value)
36
+ expect(subject.respond_to?(:success?)).to be_truthy
37
+ end
38
+ end
39
+
40
+ describe "#json" do
41
+ it "returns JSON deserialized body" do
42
+ expect(raw).to receive(:body) {
43
+ %[{"name":"Bob","interests":["Fishing","Rowing","Golfing"]}]
44
+ }
45
+ expect(subject.json).to eq({
46
+ "name" => "Bob",
47
+ "interests" => ["Fishing", "Rowing", "Golfing"],
48
+ })
49
+ end
50
+
51
+ it "returns nil if body is not valid JSON" do
52
+ expect(raw).to receive(:body) { "" }
53
+ expect(subject.json).to be_nil
54
+ end
55
+ end
56
+
57
+ end
@@ -0,0 +1,71 @@
1
+ require 'spec_helper'
2
+
3
+ describe WCC::Data::RESTEndpoint do
4
+ let(:service) { WCC::Data::Service.new }
5
+ subject { described_class.new(service: service) }
6
+
7
+ describe "#initialize" do
8
+ subject { described_class }
9
+ it "sets @service from :service option" do
10
+ obj = subject.new(service: service)
11
+ expect(obj.service).to eq(service)
12
+ end
13
+ end
14
+
15
+ shared_examples_for :rest_method_general_options do |method, verb, args|
16
+ let(:test_args) {
17
+ { foo: "bar", baz: "bing" }
18
+ }
19
+ it "takes a hash as last argument and passes to underlying service" do
20
+ args = Array(args)
21
+ expect(service).to receive(verb).with(hash_including(test_args))
22
+ subject.public_send(method, *args, test_args)
23
+ end
24
+ end
25
+
26
+ describe "#index" do
27
+ it_behaves_like :rest_method_general_options, :index, :get
28
+
29
+ it "calls #get directly on service" do
30
+ expect(service).to receive(:get).and_return("hi there")
31
+ expect(subject.index).to eq("hi there")
32
+ end
33
+ end
34
+
35
+ describe "#show" do
36
+ it_behaves_like :rest_method_general_options, :show, :get, 1
37
+
38
+ it "calls #get on service adding the id param to the URI" do
39
+ expect(service).to receive(:get).with(uri: "123").and_return("yo")
40
+ expect(subject.show(123)).to eq("yo")
41
+ end
42
+ end
43
+
44
+ describe "#create" do
45
+ it_behaves_like :rest_method_general_options, :create, :post, { test: 1 }
46
+
47
+ it "calls #post on service with attrs hash as body" do
48
+ expect(service).to receive(:post).with(body: { foo: "bar" }).and_return("hey bra")
49
+ expect(subject.create(foo: "bar")).to eq("hey bra")
50
+ end
51
+ end
52
+
53
+ describe "#update" do
54
+ it_behaves_like :rest_method_general_options, :update, :patch, [1, { test: 1 }]
55
+
56
+ it "calls #patch on service with id as URI and attrs as body" do
57
+ expect(service).to receive(:patch).with(uri: "123", body: {}).and_return("sup")
58
+ expect(subject.update(123, {})).to eq("sup")
59
+ end
60
+ end
61
+
62
+ describe "#destroy" do
63
+ it_behaves_like :rest_method_general_options, :destroy, :delete, 1
64
+
65
+ it "calls #delete on service with id as URI" do
66
+ expect(service).to receive(:delete).with(uri: "123").and_return("oh noes!")
67
+ expect(subject.destroy(123)).to eq("oh noes!")
68
+ end
69
+ end
70
+
71
+ end
@@ -0,0 +1,128 @@
1
+ require 'spec_helper'
2
+
3
+ describe WCC::Data::Service do
4
+ let(:unit) { WCC::Data::Service }
5
+ let(:connection) { double() }
6
+ let(:default_args) {
7
+ {
8
+ uri: "http://test.com/foo/",
9
+ connection: connection,
10
+ }
11
+ }
12
+ subject { unit.new(default_args) }
13
+
14
+ describe "#initialize" do
15
+ it "sets :uri to @uri" do
16
+ expect(subject.uri).to eq(URI(default_args[:uri]))
17
+ end
18
+
19
+ it "sets :connection to @connection" do
20
+ expect(subject.connection).to eq(default_args[:connection])
21
+ end
22
+ end
23
+
24
+ describe "#merge" do
25
+ it "returns a new instance" do
26
+ merged = subject.merge
27
+ expect(merged).to be_a(unit)
28
+ expect(merged.object_id).to_not eq(subject.object_id)
29
+ end
30
+
31
+ it "merges the URI params" do
32
+ merged = subject.merge(uri: "bar/baz?query")
33
+ expect(merged.uri.path).to eq("/foo/bar/baz")
34
+ expect(merged.uri.query).to eq("query")
35
+ end
36
+
37
+ it "sets to the right instance's @connection" do
38
+ connection = :bar
39
+ merged = subject.merge(connection: connection)
40
+ expect(merged.connection).to eq(connection)
41
+ end
42
+
43
+ it "accepts a hash of arguments as well as an instance" do
44
+ right = unit.new(uri: "bar", connection: double())
45
+ merged = subject.merge(right)
46
+ expect(merged.uri).to eq(URI("http://test.com/foo/bar"))
47
+ expect(merged.connection).to eq(right.connection)
48
+ end
49
+
50
+ end
51
+
52
+ shared_examples_for :http_verb_methods do
53
+ it "request verb matches the method name" do
54
+ expect(connection).to receive(:run_request) do |verb, _, _, _|
55
+ expect(verb).to eq(method)
56
+ end
57
+ subject.send(method, {})
58
+ end
59
+
60
+ it "returns a WCC::Data::Response instance" do
61
+ expect(connection).to receive(:run_request) {}
62
+ expect(subject.send(method, {})).to be_a(WCC::Data::Response)
63
+ end
64
+
65
+ it "merges :uri arg onto @uri" do
66
+ expect(connection).to receive(:run_request) do |_, url, _, _|
67
+ expect(url).to eq(URI("http://test.com/foo/bar"))
68
+ end
69
+ subject.send(method, uri: "bar")
70
+ end
71
+
72
+ it "sets the request body with :body arg" do
73
+ expect(connection).to receive(:run_request) do |_, _, body, _|
74
+ expect(body).to eq("a string")
75
+ end
76
+ subject.send(method, body: "a string")
77
+ end
78
+
79
+ it "provides request headers with :headers arg" do
80
+ expect(connection).to receive(:run_request) do |_, _, _, headers|
81
+ expect(headers).to eq(:foo)
82
+ end
83
+ subject.send(method, headers: :foo)
84
+ end
85
+
86
+ it "updates the params on the request if :params argument provided" do
87
+ params = { foo: "bar" }
88
+ request = double(params: double(:params))
89
+ expect(connection).to receive(:run_request).and_yield(request)
90
+
91
+ expect(request.params).to receive(:update).with(params)
92
+ subject.send(method, params: params)
93
+ end
94
+
95
+ it "does not update the params on the request if :params is nil" do
96
+ request = double(params: double(:params))
97
+ expect(connection).to receive(:run_request).and_yield(request)
98
+ expect(request.params).to_not receive(:update)
99
+ subject.send(method, {})
100
+ end
101
+ end
102
+
103
+ describe "#get" do
104
+ let(:method) { :get }
105
+ it_behaves_like :http_verb_methods
106
+ end
107
+
108
+ describe "#post" do
109
+ let(:method) { :post }
110
+ it_behaves_like :http_verb_methods
111
+ end
112
+
113
+ describe "#put" do
114
+ let(:method) { :put }
115
+ it_behaves_like :http_verb_methods
116
+ end
117
+
118
+ describe "#patch" do
119
+ let(:method) { :patch }
120
+ it_behaves_like :http_verb_methods
121
+ end
122
+
123
+ describe "#delete" do
124
+ let(:method) { :delete }
125
+ it_behaves_like :http_verb_methods
126
+ end
127
+
128
+ end
@@ -0,0 +1,25 @@
1
+ require 'spec_helper'
2
+
3
+ describe WCC::Data do
4
+
5
+ describe "::config" do
6
+ it "returns a cached instance of Config" do
7
+ config = WCC::Data.config
8
+ expect(config).to be_a(WCC::Data::Config)
9
+ expect(WCC::Data.config).to eq(config)
10
+ end
11
+ end
12
+
13
+ describe "::setup" do
14
+ it "yields to the provided block with config" do
15
+ config = WCC::Data.config
16
+ called = false
17
+ WCC::Data.setup do |passed_config|
18
+ called = true
19
+ expect(passed_config).to eq(config)
20
+ end
21
+ expect(called).to be_truthy
22
+ end
23
+ end
24
+
25
+ end
data/wcc-data.gemspec CHANGED
@@ -13,13 +13,15 @@ Gem::Specification.new do |spec|
13
13
  spec.homepage = ""
14
14
  spec.license = "MIT"
15
15
 
16
- spec.files = Dir['lib/**/*'] + %w[LICENSE.txt README.md wcc-data.gemspec]
16
+ spec.files = `git ls-files`.split($/)
17
+ spec.executables = spec.files.grep(%r{^bin/}) { |f| File.basename(f) }
17
18
  spec.test_files = spec.files.grep(%r{^(test|spec|features)/})
18
- spec.require_paths = ['lib']
19
+ spec.require_paths = ["lib"]
19
20
 
20
21
  spec.required_ruby_version = '~> 2.2'
21
22
 
22
- spec.add_dependency "faraday", "~> 0.8"
23
+ # Required if you use faraday_client_app_token_auth but must be included separately
24
+ spec.add_development_dependency "faraday", "~> 0.8"
23
25
 
24
26
  spec.add_development_dependency "bundler", "~> 1.3"
25
27
  spec.add_development_dependency "dotenv", "~> 0.10.0"
metadata CHANGED
@@ -1,14 +1,14 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: wcc-data
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.3.9
4
+ version: 0.4.0.pre
5
5
  platform: ruby
6
6
  authors:
7
7
  - Watermark Dev
8
8
  autorequire:
9
9
  bindir: bin
10
10
  cert_chain: []
11
- date: 2022-01-03 00:00:00.000000000 Z
11
+ date: 2021-05-21 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: faraday
@@ -17,7 +17,7 @@ dependencies:
17
17
  - - "~>"
18
18
  - !ruby/object:Gem::Version
19
19
  version: '0.8'
20
- type: :runtime
20
+ type: :development
21
21
  prerelease: false
22
22
  version_requirements: !ruby/object:Gem::Requirement
23
23
  requirements:
@@ -97,12 +97,20 @@ dependencies:
97
97
  description: Watermark's library for interapp communication via APIs
98
98
  email:
99
99
  - dev@watermark.org
100
- executables: []
100
+ executables:
101
+ - rspec
101
102
  extensions: []
102
103
  extra_rdoc_files: []
103
104
  files:
105
+ - ".env.example"
106
+ - ".gitignore"
107
+ - ".rspec"
108
+ - Gemfile
104
109
  - LICENSE.txt
105
110
  - README.md
111
+ - Rakefile
112
+ - bin/rspec
113
+ - circle.yml
106
114
  - lib/wcc/data.rb
107
115
  - lib/wcc/data/config.rb
108
116
  - lib/wcc/data/enumerated_type.rb
@@ -128,6 +136,22 @@ files:
128
136
  - lib/wcc/data/rest_endpoint.rb
129
137
  - lib/wcc/data/service.rb
130
138
  - lib/wcc/data/version.rb
139
+ - spec/spec_helper.rb
140
+ - spec/support/inheritable_class_attribute_examples.rb
141
+ - spec/wcc/data/config_spec.rb
142
+ - spec/wcc/data/enumerated_type_spec.rb
143
+ - spec/wcc/data/faraday_client_app_token_auth_spec.rb
144
+ - spec/wcc/data/mapper/attributes_spec.rb
145
+ - spec/wcc/data/mapper/json_response_spec.rb
146
+ - spec/wcc/data/mapper/rest_configuration_spec.rb
147
+ - spec/wcc/data/mapper/rest_query_spec.rb
148
+ - spec/wcc/data/model_spec.rb
149
+ - spec/wcc/data/nucleus/campus_spec.rb
150
+ - spec/wcc/data/rack_client_app_token_auth_spec.rb
151
+ - spec/wcc/data/response_spec.rb
152
+ - spec/wcc/data/rest_endpoint_spec.rb
153
+ - spec/wcc/data/service_spec.rb
154
+ - spec/wcc/data_spec.rb
131
155
  - wcc-data.gemspec
132
156
  homepage: ''
133
157
  licenses:
@@ -144,13 +168,29 @@ required_ruby_version: !ruby/object:Gem::Requirement
144
168
  version: '2.2'
145
169
  required_rubygems_version: !ruby/object:Gem::Requirement
146
170
  requirements:
147
- - - ">="
171
+ - - ">"
148
172
  - !ruby/object:Gem::Version
149
- version: '0'
173
+ version: 1.3.1
150
174
  requirements: []
151
175
  rubyforge_project:
152
176
  rubygems_version: 2.5.2.3
153
177
  signing_key:
154
178
  specification_version: 4
155
179
  summary: Watermark's library for interapp communication via APIs
156
- test_files: []
180
+ test_files:
181
+ - spec/spec_helper.rb
182
+ - spec/support/inheritable_class_attribute_examples.rb
183
+ - spec/wcc/data/config_spec.rb
184
+ - spec/wcc/data/enumerated_type_spec.rb
185
+ - spec/wcc/data/faraday_client_app_token_auth_spec.rb
186
+ - spec/wcc/data/mapper/attributes_spec.rb
187
+ - spec/wcc/data/mapper/json_response_spec.rb
188
+ - spec/wcc/data/mapper/rest_configuration_spec.rb
189
+ - spec/wcc/data/mapper/rest_query_spec.rb
190
+ - spec/wcc/data/model_spec.rb
191
+ - spec/wcc/data/nucleus/campus_spec.rb
192
+ - spec/wcc/data/rack_client_app_token_auth_spec.rb
193
+ - spec/wcc/data/response_spec.rb
194
+ - spec/wcc/data/rest_endpoint_spec.rb
195
+ - spec/wcc/data/service_spec.rb
196
+ - spec/wcc/data_spec.rb