endpoint-flux 1.1.1

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.
Files changed (59) hide show
  1. checksums.yaml +7 -0
  2. data/.gitignore +36 -0
  3. data/CONTRIBUTING.md +18 -0
  4. data/Gemfile +6 -0
  5. data/Gemfile.lock +37 -0
  6. data/README.md +607 -0
  7. data/circle.yml +14 -0
  8. data/endpoint_flux.gemspec +17 -0
  9. data/lib/endpoint_flux.rb +20 -0
  10. data/lib/endpoint_flux/class_loader.rb +58 -0
  11. data/lib/endpoint_flux/config.rb +85 -0
  12. data/lib/endpoint_flux/config/interceptor.rb +23 -0
  13. data/lib/endpoint_flux/config/middleware.rb +38 -0
  14. data/lib/endpoint_flux/config/rescue_from.rb +28 -0
  15. data/lib/endpoint_flux/endpoint.rb +81 -0
  16. data/lib/endpoint_flux/exceptions.rb +10 -0
  17. data/lib/endpoint_flux/exceptions/base.rb +21 -0
  18. data/lib/endpoint_flux/exceptions/forbidden.rb +12 -0
  19. data/lib/endpoint_flux/exceptions/not_found.rb +12 -0
  20. data/lib/endpoint_flux/exceptions/service_unavailable.rb +12 -0
  21. data/lib/endpoint_flux/exceptions/unauthorized.rb +12 -0
  22. data/lib/endpoint_flux/exceptions/validation.rb +13 -0
  23. data/lib/endpoint_flux/middlewares.rb +8 -0
  24. data/lib/endpoint_flux/middlewares/authenticator/skip.rb +11 -0
  25. data/lib/endpoint_flux/middlewares/authorizator/skip.rb +11 -0
  26. data/lib/endpoint_flux/middlewares/decorator/add_status.rb +12 -0
  27. data/lib/endpoint_flux/middlewares/decorator/skip.rb +11 -0
  28. data/lib/endpoint_flux/middlewares/policy/skip.rb +11 -0
  29. data/lib/endpoint_flux/middlewares/validator/empty.rb +12 -0
  30. data/lib/endpoint_flux/rails/concerns/endpoint_controller.rb +32 -0
  31. data/lib/endpoint_flux/request.rb +15 -0
  32. data/lib/endpoint_flux/response.rb +30 -0
  33. data/lib/endpoint_flux/version.rb +3 -0
  34. data/spec/lib/class_loader_spec.rb +31 -0
  35. data/spec/lib/config/default_middlewares_spec.rb +21 -0
  36. data/spec/lib/config/endpoints_namespace_spec.rb +13 -0
  37. data/spec/lib/config/flow_spec.rb +8 -0
  38. data/spec/lib/config/interceptor_spec.rb +34 -0
  39. data/spec/lib/config/middleware_spec.rb +62 -0
  40. data/spec/lib/config/rescue_from_spec.rb +45 -0
  41. data/spec/lib/endpoint/flow_spec.rb +43 -0
  42. data/spec/lib/endpoint/middlewares_spec.rb +110 -0
  43. data/spec/lib/endpoint/perform_spec.rb +61 -0
  44. data/spec/lib/endpoint/rescue_from_spec.rb +61 -0
  45. data/spec/lib/exceptions/forbidden_spec.rb +12 -0
  46. data/spec/lib/exceptions/not_found_spec.rb +12 -0
  47. data/spec/lib/exceptions/service_unavailable_spec.rb +12 -0
  48. data/spec/lib/exceptions/unauthorized_spec.rb +12 -0
  49. data/spec/lib/exceptions/validation_spec.rb +14 -0
  50. data/spec/lib/middlewares/authenticator/skip_spec.rb +5 -0
  51. data/spec/lib/middlewares/authorizator/skip_spec.rb +5 -0
  52. data/spec/lib/middlewares/decorator/add_status_spec.rb +17 -0
  53. data/spec/lib/middlewares/decorator/skip_spec.rb +5 -0
  54. data/spec/lib/middlewares/policy/skip_spec.rb +5 -0
  55. data/spec/lib/middlewares/shared_examples.rb +19 -0
  56. data/spec/lib/middlewares/validator/empty_spec.rb +15 -0
  57. data/spec/lib/response_spec.rb +131 -0
  58. data/spec/spec_helper.rb +52 -0
  59. metadata +153 -0
@@ -0,0 +1,110 @@
1
+ require 'spec_helper'
2
+
3
+ RSpec.describe EndpointFlux::Endpoint do
4
+ let(:klass) { class_double('Sample') }
5
+
6
+ before do
7
+ EndpointFlux.config EndpointFlux::Config.new
8
+
9
+ klass.include EndpointFlux::Endpoint
10
+ end
11
+
12
+ context 'with exceptions' do
13
+ it 'fails with wrong string' do
14
+ klass.flow [:validator]
15
+
16
+ expect do
17
+ klass.validator 'some_not_existing_class'
18
+ end.to raise_error('You must provide block or existing klass')
19
+ end
20
+
21
+ it 'fails whit wrong class passed' do
22
+ stub_const 'EndpointFlux::Middlewares::Validator::SampleMiddleware', Class.new
23
+
24
+ klass.flow [:validator]
25
+
26
+ expect { klass.validator 'sample_middleware' }.to raise_error(
27
+ 'The [EndpointFlux::Middlewares::Validator::SampleMiddleware] '\
28
+ 'class should define perform class method'
29
+ )
30
+ end
31
+
32
+ context 'when wrong param passed' do
33
+ it do
34
+ klass.flow [:validator]
35
+
36
+ expect { klass.validator 1334 }.to raise_error(
37
+ 'You must provide block or existing klass'
38
+ )
39
+ end
40
+
41
+ it do
42
+ stub_const 'SampleMiddleware', Class.new
43
+
44
+ klass.flow [:validator]
45
+
46
+ expect { klass.validator SampleMiddleware }.to raise_error(
47
+ 'You must provide block or existing klass'
48
+ )
49
+ end
50
+ end
51
+ end
52
+
53
+ describe 'middlewares' do
54
+ before do
55
+ stub_const 'SomeNamespace::MiddlewareName::SampleMiddleware', Class.new
56
+ SomeNamespace::MiddlewareName::SampleMiddleware.class_eval do
57
+ def self.perform(*args)
58
+ args
59
+ end
60
+ end
61
+
62
+ EndpointFlux.config.middlewares_namespaces << 'some_namespace'
63
+ end
64
+
65
+ before do
66
+ klass.flow [:middleware_name]
67
+ end
68
+
69
+ let(:middleware) { klass.middleware_name.first }
70
+
71
+ it 'sets middleware with options' do
72
+ klass.middleware_name 'sample_middleware', some: :option
73
+
74
+ expect(middleware.klass).to be(SomeNamespace::MiddlewareName::SampleMiddleware)
75
+ expect(middleware.options).to eq(some: :option)
76
+ end
77
+
78
+ it 'sets middleware' do
79
+ klass.middleware_name 'sample_middleware'
80
+
81
+ expect(middleware.klass).to be(SomeNamespace::MiddlewareName::SampleMiddleware)
82
+ end
83
+
84
+ it 'does not add twice' do
85
+ klass.middleware_name 'sample_middleware'
86
+ klass.middleware_name 'sample_middleware'
87
+
88
+ middleware = klass.middleware_name.first
89
+
90
+ expect(middleware.klass).to be(SomeNamespace::MiddlewareName::SampleMiddleware)
91
+ end
92
+
93
+ context 'block' do
94
+ let(:block) { proc {} }
95
+
96
+ it 'sets middleware' do
97
+ klass.middleware_name(&block)
98
+
99
+ expect(middleware.handler).to be == block
100
+ end
101
+
102
+ it 'does not adds twice' do
103
+ klass.middleware_name(&block)
104
+ klass.middleware_name(&block)
105
+
106
+ expect(middleware.handler).to be == block
107
+ end
108
+ end
109
+ end
110
+ end
@@ -0,0 +1,61 @@
1
+ require 'spec_helper'
2
+
3
+ RSpec.describe EndpointFlux::Endpoint do
4
+ let(:klass) { stub_const 'Sample', Class.new }
5
+ let(:middleware_request) { EndpointFlux::Request.new(headers: {}, params: params) }
6
+ let(:middleware_response) { EndpointFlux::Response.new }
7
+
8
+ before do
9
+ EndpointFlux.config EndpointFlux::Config.new
10
+
11
+ klass.include EndpointFlux::Endpoint
12
+ end
13
+
14
+ describe '#perform' do
15
+ before do
16
+ stub_const 'EndpointFlux::Middlewares::Validator::SampleValidator', Class.new
17
+ EndpointFlux::Middlewares::Validator::SampleValidator.class_eval do
18
+ def self.perform(request, response, _)
19
+ request.params = {}
20
+ [request, response, {}]
21
+ end
22
+ end
23
+ end
24
+
25
+ let(:params) { { some: :val } }
26
+
27
+ it 'checks if middleware exists' do
28
+ klass.flow [:validator]
29
+
30
+ expect { klass.perform(middleware_request) }
31
+ .to raise_error('No middleware registred for [:validator]')
32
+ end
33
+
34
+ context 'middleware passed as string' do
35
+ it 'runs middleware passed as string' do
36
+ klass.flow [:validator]
37
+ klass.validator 'sample_validator'
38
+
39
+ request, response = klass.perform(middleware_request)
40
+
41
+ expect(request.params).to eq({})
42
+ expect(response.body).to eq({})
43
+ end
44
+ end
45
+
46
+ context 'default middleware' do
47
+ before do
48
+ klass.flow [:validator]
49
+
50
+ EndpointFlux.config.default_middlewares :validator, 'sample_validator'
51
+ end
52
+
53
+ it 'uses default if not defined' do
54
+ request, response = klass.perform(middleware_request)
55
+
56
+ expect(request.params).to eq({})
57
+ expect(response.body).to eq({})
58
+ end
59
+ end
60
+ end
61
+ end
@@ -0,0 +1,61 @@
1
+ require 'spec_helper'
2
+
3
+ RSpec.describe EndpointFlux::Endpoint do
4
+ let(:klass) { stub_const 'Sample', Class.new }
5
+ let(:middleware_request) { EndpointFlux::Request.new(headers: {}, params: {}) }
6
+ let(:middleware_response) { EndpointFlux::Response.new }
7
+
8
+ before do
9
+ EndpointFlux.config EndpointFlux::Config.new
10
+
11
+ klass.include EndpointFlux::Endpoint
12
+ end
13
+
14
+ describe '#rescue_from' do
15
+ let(:sample_exception) { stub_const 'SampleException', Class.new(Exception) }
16
+ let!(:sample_validator) do
17
+ stub_const 'EndpointFlux::Middlewares::Validator::Sample', Class.new
18
+ EndpointFlux::Middlewares::Validator::Sample.class_eval do
19
+ def self.perform(*)
20
+ raise SampleException, 'bla bla'
21
+ end
22
+ end
23
+ EndpointFlux::Middlewares::Validator::Sample
24
+ end
25
+ let!(:sample_decorator) do
26
+ stub_const 'EndpointFlux::Middlewares::Decorator::Sample', Class.new
27
+ EndpointFlux::Middlewares::Decorator::Sample.class_eval do
28
+ def self.perform(request, response, options)
29
+ response.body[:decorator] = true
30
+ [request, response, options]
31
+ end
32
+ end
33
+ EndpointFlux::Middlewares::Decorator::Sample
34
+ end
35
+
36
+ it 'fails if exception not found' do
37
+ expect do
38
+ EndpointFlux.config.rescue_from 'NonExsistingClasss' do |_, attrs|
39
+ # code
40
+ end
41
+ end.to raise_error('The [NonExsistingClasss] should be a string representing a class')
42
+ end
43
+
44
+ context 'default middleware' do
45
+ before do
46
+ klass.flow %i[validator decorator]
47
+ klass.validator 'sample'
48
+ klass.decorator 'sample'
49
+
50
+ EndpointFlux.config.rescue_from sample_exception do |_, attrs|
51
+ [attrs[0], attrs[1], { status: false }]
52
+ end
53
+ end
54
+
55
+ it 'uses default if not defined' do
56
+ _, response = klass.perform(middleware_request)
57
+ expect(response.body[:status]).to be_falsey
58
+ end
59
+ end
60
+ end
61
+ end
@@ -0,0 +1,12 @@
1
+ require 'spec_helper'
2
+
3
+ RSpec.describe EndpointFlux::Exceptions::Forbidden do
4
+ describe '#to_hash' do
5
+ it 'returns correct hash' do
6
+ expect(subject.to_hash).to eq(
7
+ status: 403,
8
+ message: 'Forbidden'
9
+ )
10
+ end
11
+ end
12
+ end
@@ -0,0 +1,12 @@
1
+ require 'spec_helper'
2
+
3
+ RSpec.describe EndpointFlux::Exceptions::NotFound do
4
+ describe '#to_hash' do
5
+ it 'returns correct hash' do
6
+ expect(subject.to_hash).to eq(
7
+ status: 404,
8
+ message: 'not found'
9
+ )
10
+ end
11
+ end
12
+ end
@@ -0,0 +1,12 @@
1
+ require 'spec_helper'
2
+
3
+ RSpec.describe EndpointFlux::Exceptions::ServiceUnavailable do
4
+ describe '#to_hash' do
5
+ it 'returns correct hash' do
6
+ expect(subject.to_hash).to eq(
7
+ status: 503,
8
+ message: 'service unavailable'
9
+ )
10
+ end
11
+ end
12
+ end
@@ -0,0 +1,12 @@
1
+ require 'spec_helper'
2
+
3
+ RSpec.describe EndpointFlux::Exceptions::Unauthorized do
4
+ describe '#to_hash' do
5
+ it 'returns correct hash' do
6
+ expect(subject.to_hash).to eq(
7
+ status: 401,
8
+ message: 'Unauthorized'
9
+ )
10
+ end
11
+ end
12
+ end
@@ -0,0 +1,14 @@
1
+ require 'spec_helper'
2
+
3
+ RSpec.describe EndpointFlux::Exceptions::Validation do
4
+ describe '#to_hash' do
5
+ let(:messages) { {name: 'not valid'} }
6
+ it 'returns correct hash' do
7
+ expect(EndpointFlux::Exceptions::Validation.new(messages).to_hash).to eq(
8
+ status: 422,
9
+ message: 'validation errors',
10
+ errors: messages
11
+ )
12
+ end
13
+ end
14
+ end
@@ -0,0 +1,5 @@
1
+ require_relative '../../middlewares/shared_examples'
2
+
3
+ RSpec.describe EndpointFlux::Middlewares::Authenticator::Skip do
4
+ include_examples 'perform does not change the params'
5
+ end
@@ -0,0 +1,5 @@
1
+ require_relative '../../middlewares/shared_examples'
2
+
3
+ RSpec.describe EndpointFlux::Middlewares::Authorizator::Skip do
4
+ include_examples 'perform does not change the params'
5
+ end
@@ -0,0 +1,17 @@
1
+ RSpec.describe EndpointFlux::Middlewares::Decorator::AddStatus do
2
+ describe '#perform' do
3
+ let(:params) { { some: 'value' } }
4
+ let(:body) { { status: 200 } }
5
+ let(:request) { EndpointFlux::Request.new(headers: {}, params: params) }
6
+ let(:response) { EndpointFlux::Response.new(headers: {}, body: body) }
7
+
8
+ it 'returns response with status in body' do
9
+ middleware_request, middleware_response = subject.perform(request, response, {})
10
+
11
+ expect(middleware_request.headers).to eq({})
12
+ expect(middleware_request.params).to eq(params)
13
+ expect(middleware_response.headers).to eq({})
14
+ expect(middleware_response.body).to eq(body)
15
+ end
16
+ end
17
+ end
@@ -0,0 +1,5 @@
1
+ require_relative '../../middlewares/shared_examples'
2
+
3
+ RSpec.describe EndpointFlux::Middlewares::Decorator::Skip do
4
+ include_examples 'perform does not change the params'
5
+ end
@@ -0,0 +1,5 @@
1
+ require_relative '../../middlewares/shared_examples'
2
+
3
+ RSpec.describe EndpointFlux::Middlewares::Policy::Skip do
4
+ include_examples 'perform does not change the params'
5
+ end
@@ -0,0 +1,19 @@
1
+ require 'spec_helper'
2
+
3
+ RSpec.shared_context 'perform does not change the params', shared_context: :metadata do
4
+ describe '#perform' do
5
+ let(:params) { { some: 'value' } }
6
+ let(:headers) { { 'Authorization' => 'valid' } }
7
+ let(:request) { EndpointFlux::Request.new(headers: headers, params: params) }
8
+ let(:response) { EndpointFlux::Response.new(headers: {}, body: {}) }
9
+
10
+ it 'returns not changed params' do
11
+ middleware_request, middleware_response = subject.perform(request, response, {})
12
+
13
+ expect(middleware_request.params).to eq(params)
14
+ expect(middleware_request.headers).to eq(headers)
15
+ expect(middleware_response.headers).to eq({})
16
+ expect(middleware_response.body).to eq({})
17
+ end
18
+ end
19
+ end
@@ -0,0 +1,15 @@
1
+ RSpec.describe EndpointFlux::Middlewares::Validator::Empty do
2
+ describe '#perform' do
3
+ let(:params) { { some: 'value' } }
4
+ let(:request) { EndpointFlux::Request.new(headers: {}, params: params) }
5
+ let(:response) { EndpointFlux::Response.new }
6
+
7
+ it 'returns empty params' do
8
+ middleware_request, middleware_response = subject.perform(request, response, {})
9
+
10
+ expect(middleware_request.params).to eq({})
11
+ expect(middleware_response.headers).to eq({})
12
+ expect(middleware_response.body).to eq({})
13
+ end
14
+ end
15
+ end
@@ -0,0 +1,131 @@
1
+ require 'spec_helper'
2
+
3
+ RSpec.describe EndpointFlux::Response do
4
+ subject { EndpointFlux::Response.new(params) }
5
+ let(:empty_subject) { EndpointFlux::Response.new() }
6
+
7
+ describe '#success?' do
8
+ context 'when valid params given' do
9
+ Array(200..209).each do |status|
10
+ let(:params) { { headers: {}, body: {status: status} } }
11
+ it "returns true for status #{status}" do
12
+ expect(subject.success?).to be_truthy
13
+ end
14
+ end
15
+ end
16
+
17
+ context 'when wrong params given' do
18
+ let(:status) { 400 }
19
+ let(:params) { { headers: {}, body: {status: status} } }
20
+ it 'returns false for not a success status' do
21
+ expect(subject.success?).to be_falsey
22
+ end
23
+
24
+ describe 'when Response initialized without params' do
25
+ it 'returns false for not a success status' do
26
+ expect(empty_subject.success?).to be_falsey
27
+ end
28
+ end
29
+ end
30
+ end
31
+
32
+ describe '#invalid?' do
33
+ let(:params) { { headers: {}, body: {status: status} } }
34
+ context 'when valid params given' do
35
+ let(:status) { 422 }
36
+
37
+ it 'returns true for status 422' do
38
+ expect(subject.invalid?).to be_truthy
39
+ end
40
+ end
41
+
42
+ context 'when wrong params given' do
43
+ let(:status) { 400 }
44
+
45
+ it 'returns false for not an invalid status' do
46
+ expect(subject.invalid?).to be_falsey
47
+ end
48
+
49
+ describe 'when Response initialized without params' do
50
+ it 'returns false for not an invalid status' do
51
+ expect(empty_subject.invalid?).to be_falsey
52
+ end
53
+ end
54
+ end
55
+ end
56
+
57
+ describe '#forbidden?' do
58
+ let(:params) { { headers: {}, body: {status: status} } }
59
+ context 'when valid params given' do
60
+ let(:status) { 403 }
61
+
62
+ it 'returns true for status 403' do
63
+ expect(subject.forbidden?).to be_truthy
64
+ end
65
+ end
66
+
67
+ context 'when wrong params given' do
68
+ let(:status) { 400 }
69
+
70
+ it 'returns false for not a forbidden status' do
71
+ expect(subject.forbidden?).to be_falsey
72
+ end
73
+
74
+ describe 'when Response initialized without params' do
75
+ it 'returns false for not a forbidden status' do
76
+ expect(empty_subject.forbidden?).to be_falsey
77
+ end
78
+ end
79
+ end
80
+ end
81
+
82
+ describe '#unauthorized?' do
83
+ let(:params) { { headers: {}, body: {status: status} } }
84
+ context 'when valid params given' do
85
+ let(:status) { 401 }
86
+
87
+ it 'returns true for status 401' do
88
+ expect(subject.unauthorized?).to be_truthy
89
+ end
90
+ end
91
+
92
+ context 'when wrong params given' do
93
+ let(:status) { 400 }
94
+
95
+ it 'returns false for not a unauthorized status' do
96
+ expect(subject.unauthorized?).to be_falsey
97
+ end
98
+
99
+ describe 'when Response initialized without params' do
100
+ it 'returns false for not a unauthorized status' do
101
+ expect(empty_subject.unauthorized?).to be_falsey
102
+ end
103
+ end
104
+ end
105
+ end
106
+
107
+ describe '#unauthorized?' do
108
+ let(:params) { { headers: {}, body: {status: status} } }
109
+ context 'when valid params given' do
110
+ let(:status) { 404 }
111
+
112
+ it 'returns true for status 404' do
113
+ expect(subject.not_found?).to be_truthy
114
+ end
115
+ end
116
+
117
+ context 'when wrong params given' do
118
+ let(:status) { 400 }
119
+
120
+ it 'returns false for not a not_found status' do
121
+ expect(subject.not_found?).to be_falsey
122
+ end
123
+
124
+ describe 'when Response initialized without params' do
125
+ it 'returns false for not a not_found status' do
126
+ expect(empty_subject.not_found?).to be_falsey
127
+ end
128
+ end
129
+ end
130
+ end
131
+ end