azeroth 0.7.2 → 0.8.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.
- checksums.yaml +4 -4
- data/.circleci/config.yml +2 -2
- data/Dockerfile +1 -1
- data/README.md +4 -1
- data/azeroth.gemspec +28 -26
- data/config/yardstick.yml +1 -0
- data/lib/azeroth.rb +9 -8
- data/lib/azeroth/controller_interface.rb +87 -0
- data/lib/azeroth/decorator.rb +2 -3
- data/lib/azeroth/decorator/method_builder.rb +26 -0
- data/lib/azeroth/options.rb +38 -2
- data/lib/azeroth/request_handler.rb +16 -7
- data/lib/azeroth/request_handler/create.rb +1 -1
- data/lib/azeroth/request_handler/index.rb +78 -0
- data/lib/azeroth/version.rb +1 -1
- data/spec/controllers/documents_controller_spec.rb +1 -1
- data/spec/controllers/documents_with_error_controller_spec.rb +1 -1
- data/spec/controllers/index_documents_controller_spec.rb +12 -1
- data/spec/controllers/paginated_documents_controller_spec.rb +146 -0
- data/spec/dummy/app/controllers/paginated_documents_controller.rb +7 -0
- data/spec/dummy/config/routes.rb +1 -0
- data/spec/lib/azeroth/controller_interface_spec.rb +82 -0
- data/spec/lib/azeroth/decorator/method_builder_spec.rb +23 -0
- data/spec/lib/azeroth/request_handler/create_spec.rb +106 -0
- data/spec/lib/azeroth/request_handler/index_spec.rb +118 -0
- data/spec/lib/azeroth/request_handler_spec.rb +1 -1
- data/spec/spec_helper.rb +2 -0
- data/spec/support/app/controllers/request_handler_controller.rb +5 -0
- data/spec/support/app/workers/worker.rb +5 -0
- data/spec/support/shared_examples/request_handler.rb +6 -1
- metadata +74 -34
data/lib/azeroth/version.rb
CHANGED
@@ -10,7 +10,7 @@ describe IndexDocumentsController do
|
|
10
10
|
describe 'GET index' do
|
11
11
|
let(:documents_count) { 0 }
|
12
12
|
let!(:documents) do
|
13
|
-
|
13
|
+
create_list(:document, documents_count)
|
14
14
|
end
|
15
15
|
|
16
16
|
let(:expected_json) do
|
@@ -37,6 +37,17 @@ describe IndexDocumentsController do
|
|
37
37
|
expect(parsed_response).to eq(expected_json)
|
38
38
|
end
|
39
39
|
end
|
40
|
+
|
41
|
+
context 'when there are more documents than expected pagination' do
|
42
|
+
let(:documents_count) { Random.rand(21..30) }
|
43
|
+
|
44
|
+
it { expect(response).to be_successful }
|
45
|
+
|
46
|
+
it 'returns all documents' do
|
47
|
+
expect(parsed_response)
|
48
|
+
.to have(documents_count).elements
|
49
|
+
end
|
50
|
+
end
|
40
51
|
end
|
41
52
|
end
|
42
53
|
|
@@ -0,0 +1,146 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
require 'spec_helper'
|
4
|
+
|
5
|
+
describe PaginatedDocumentsController do
|
6
|
+
let(:parsed_response) do
|
7
|
+
JSON.parse(response.body)
|
8
|
+
end
|
9
|
+
|
10
|
+
describe 'GET index' do
|
11
|
+
let(:documents_count) { 0 }
|
12
|
+
let!(:documents) do
|
13
|
+
create_list(:document, documents_count)
|
14
|
+
end
|
15
|
+
|
16
|
+
let(:expected_json) do
|
17
|
+
Document::Decorator.new(documents).as_json
|
18
|
+
end
|
19
|
+
|
20
|
+
context 'when calling on format json' do
|
21
|
+
let(:parameters) { {} }
|
22
|
+
|
23
|
+
before do
|
24
|
+
get :index, params: parameters.merge(format: :json)
|
25
|
+
end
|
26
|
+
|
27
|
+
it { expect(response).to be_successful }
|
28
|
+
|
29
|
+
it 'returns empty array' do
|
30
|
+
expect(parsed_response).to eq(expected_json)
|
31
|
+
end
|
32
|
+
|
33
|
+
context 'when there is a document' do
|
34
|
+
let(:documents_count) { 1 }
|
35
|
+
|
36
|
+
it { expect(response).to be_successful }
|
37
|
+
|
38
|
+
it 'renders documents json' do
|
39
|
+
expect(parsed_response).to eq(expected_json)
|
40
|
+
end
|
41
|
+
|
42
|
+
it 'adds total pages header' do
|
43
|
+
expect(response.headers['pages']).to eq(1)
|
44
|
+
end
|
45
|
+
|
46
|
+
it 'adds current page header' do
|
47
|
+
expect(response.headers['page']).to eq(1)
|
48
|
+
end
|
49
|
+
|
50
|
+
it 'adds per page header' do
|
51
|
+
expect(response.headers['per_page']).to eq(20)
|
52
|
+
end
|
53
|
+
end
|
54
|
+
|
55
|
+
context 'when there are more documents than expected pagination' do
|
56
|
+
let(:documents_count) { Random.rand(21..30) }
|
57
|
+
|
58
|
+
it { expect(response).to be_successful }
|
59
|
+
|
60
|
+
it 'returns paginated documents' do
|
61
|
+
expect(parsed_response)
|
62
|
+
.not_to have(documents_count).elements
|
63
|
+
end
|
64
|
+
|
65
|
+
it 'returns full page of documents' do
|
66
|
+
expect(parsed_response)
|
67
|
+
.to have(20).elements
|
68
|
+
end
|
69
|
+
|
70
|
+
it 'adds total pages header' do
|
71
|
+
expect(response.headers['pages']).to eq(2)
|
72
|
+
end
|
73
|
+
|
74
|
+
it 'adds current page header' do
|
75
|
+
expect(response.headers['page']).to eq(1)
|
76
|
+
end
|
77
|
+
|
78
|
+
it 'adds per page header' do
|
79
|
+
expect(response.headers['per_page']).to eq(20)
|
80
|
+
end
|
81
|
+
end
|
82
|
+
|
83
|
+
context 'when page is given' do
|
84
|
+
let(:documents_count) { Random.rand(21..30) }
|
85
|
+
let(:parameters) { { page: 2 } }
|
86
|
+
|
87
|
+
it { expect(response).to be_successful }
|
88
|
+
|
89
|
+
it 'returns paginated documents' do
|
90
|
+
expect(parsed_response)
|
91
|
+
.not_to have(documents_count).elements
|
92
|
+
end
|
93
|
+
|
94
|
+
it 'returns full page of documents' do
|
95
|
+
expect(parsed_response)
|
96
|
+
.to have(documents_count - 20)
|
97
|
+
.elements
|
98
|
+
end
|
99
|
+
|
100
|
+
it 'adds total pages header' do
|
101
|
+
expect(response.headers['pages']).to eq(2)
|
102
|
+
end
|
103
|
+
|
104
|
+
it 'adds current page header' do
|
105
|
+
expect(response.headers['page']).to eq(2)
|
106
|
+
end
|
107
|
+
|
108
|
+
it 'adds per page header' do
|
109
|
+
expect(response.headers['per_page']).to eq(20)
|
110
|
+
end
|
111
|
+
end
|
112
|
+
|
113
|
+
context 'when per_page is given' do
|
114
|
+
let(:documents_count) { Random.rand(21..30) }
|
115
|
+
let(:per_page) { Random.rand(5..15) }
|
116
|
+
let(:parameters) { { per_page: per_page } }
|
117
|
+
|
118
|
+
it { expect(response).to be_successful }
|
119
|
+
|
120
|
+
it 'returns paginated documents' do
|
121
|
+
expect(parsed_response)
|
122
|
+
.not_to have(documents_count).elements
|
123
|
+
end
|
124
|
+
|
125
|
+
it 'returns full page of documents' do
|
126
|
+
expect(parsed_response)
|
127
|
+
.to have(per_page)
|
128
|
+
.elements
|
129
|
+
end
|
130
|
+
|
131
|
+
it 'adds total pages header' do
|
132
|
+
expect(response.headers['pages'])
|
133
|
+
.to eq((documents_count.to_f / per_page).ceil)
|
134
|
+
end
|
135
|
+
|
136
|
+
it 'adds current page header' do
|
137
|
+
expect(response.headers['page']).to eq(1)
|
138
|
+
end
|
139
|
+
|
140
|
+
it 'adds per page header' do
|
141
|
+
expect(response.headers['per_page']).to eq(per_page)
|
142
|
+
end
|
143
|
+
end
|
144
|
+
end
|
145
|
+
end
|
146
|
+
end
|
data/spec/dummy/config/routes.rb
CHANGED
@@ -4,6 +4,7 @@ Rails.application.routes.draw do
|
|
4
4
|
resources :documents
|
5
5
|
resources :public_documents, controller: :index_documents
|
6
6
|
resources :create_documents, controller: :documents_with_error
|
7
|
+
resources :paginated_documents
|
7
8
|
|
8
9
|
resources :publishers, only: %i[create index] do
|
9
10
|
resources :games, except: :delete
|
@@ -0,0 +1,82 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
require 'spec_helper'
|
4
|
+
|
5
|
+
describe Azeroth::ControllerInterface do
|
6
|
+
subject(:interface) { described_class.new(controller) }
|
7
|
+
|
8
|
+
let(:controller) { controller_class.new }
|
9
|
+
let(:controller_class) { RequestHandlerController }
|
10
|
+
|
11
|
+
describe '#add_headers' do
|
12
|
+
let(:controller_headers) do
|
13
|
+
{
|
14
|
+
'old_key': 100
|
15
|
+
}
|
16
|
+
end
|
17
|
+
|
18
|
+
let(:headers) do
|
19
|
+
{
|
20
|
+
key1: 10,
|
21
|
+
key2: 20
|
22
|
+
}
|
23
|
+
end
|
24
|
+
|
25
|
+
before do
|
26
|
+
allow(controller)
|
27
|
+
.to receive(:headers)
|
28
|
+
.and_return(controller_headers)
|
29
|
+
end
|
30
|
+
|
31
|
+
it 'sets controller headers' do
|
32
|
+
expect { interface.add_headers(headers) }
|
33
|
+
.to change { controller_headers }
|
34
|
+
.from(controller_headers)
|
35
|
+
.to(controller_headers.merge(headers.stringify_keys))
|
36
|
+
end
|
37
|
+
end
|
38
|
+
|
39
|
+
describe '#render_json' do
|
40
|
+
let(:json) { { key: 'value' } }
|
41
|
+
let(:status) { 200 }
|
42
|
+
|
43
|
+
before do
|
44
|
+
allow(controller)
|
45
|
+
.to receive(:render)
|
46
|
+
.with(json: json, status: status)
|
47
|
+
end
|
48
|
+
|
49
|
+
it 'renders json' do
|
50
|
+
interface.render_json(json, status)
|
51
|
+
|
52
|
+
expect(controller).to have_received(:render)
|
53
|
+
end
|
54
|
+
end
|
55
|
+
|
56
|
+
describe '#set' do
|
57
|
+
it 'sets instance variable' do
|
58
|
+
expect { interface.set(:name, 20) }
|
59
|
+
.to change { controller.instance_variable_get('@name') }
|
60
|
+
.from(nil)
|
61
|
+
.to(20)
|
62
|
+
end
|
63
|
+
end
|
64
|
+
|
65
|
+
describe 'method missing' do
|
66
|
+
before do
|
67
|
+
create(:document)
|
68
|
+
end
|
69
|
+
|
70
|
+
it 'delegates call to controller' do
|
71
|
+
expect(interface.documents)
|
72
|
+
.to eq(Document.all)
|
73
|
+
end
|
74
|
+
|
75
|
+
context 'when method is not defined' do
|
76
|
+
it do
|
77
|
+
expect { interface.pokemons }
|
78
|
+
.to raise_error(NoMethodError)
|
79
|
+
end
|
80
|
+
end
|
81
|
+
end
|
82
|
+
end
|
@@ -0,0 +1,23 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
require 'spec_helper'
|
4
|
+
|
5
|
+
describe Azeroth::Decorator::MethodBuilder do
|
6
|
+
let(:decorator_class) { Class.new(Azeroth::Decorator) }
|
7
|
+
let(:decorator) { decorator_class.new(object) }
|
8
|
+
let(:model) { build(:dummy_model) }
|
9
|
+
let(:object) { model }
|
10
|
+
|
11
|
+
describe '.build_reader' do
|
12
|
+
it do
|
13
|
+
expect { described_class.build_reader(decorator_class, :age) }
|
14
|
+
.to add_method(:age).to(decorator)
|
15
|
+
end
|
16
|
+
|
17
|
+
it do
|
18
|
+
described_class.build_reader(decorator_class, :age)
|
19
|
+
|
20
|
+
expect(decorator.age).to eq(model.age)
|
21
|
+
end
|
22
|
+
end
|
23
|
+
end
|
@@ -106,6 +106,112 @@ describe Azeroth::RequestHandler::Create do
|
|
106
106
|
end
|
107
107
|
end
|
108
108
|
end
|
109
|
+
|
110
|
+
context 'with after_save block option' do
|
111
|
+
it_behaves_like 'a request handler', status: :created do
|
112
|
+
let(:block) do
|
113
|
+
value = 10
|
114
|
+
proc do
|
115
|
+
document.update(reference: "X-MAGIC-#{value}")
|
116
|
+
Worker.perform(document.id)
|
117
|
+
end
|
118
|
+
end
|
119
|
+
|
120
|
+
let(:options_hash) do
|
121
|
+
{
|
122
|
+
after_save: block
|
123
|
+
}
|
124
|
+
end
|
125
|
+
|
126
|
+
let(:extra_params) do
|
127
|
+
{
|
128
|
+
document: {
|
129
|
+
name: 'My Document'
|
130
|
+
}
|
131
|
+
}
|
132
|
+
end
|
133
|
+
|
134
|
+
let(:expected_json) do
|
135
|
+
{
|
136
|
+
'name' => 'My Document',
|
137
|
+
'reference' => 'X-MAGIC-10'
|
138
|
+
}
|
139
|
+
end
|
140
|
+
|
141
|
+
before do
|
142
|
+
allow(Worker).to receive(:perform)
|
143
|
+
end
|
144
|
+
|
145
|
+
it 'creates entry' do
|
146
|
+
expect { handler.process }
|
147
|
+
.to change(Document, :count)
|
148
|
+
.by(1)
|
149
|
+
end
|
150
|
+
|
151
|
+
it 'trigger workers after saving' do
|
152
|
+
handler.process
|
153
|
+
|
154
|
+
expect(Worker).to have_received(:perform)
|
155
|
+
.with(Document.last.id)
|
156
|
+
end
|
157
|
+
|
158
|
+
it 'changes entry after saving' do
|
159
|
+
handler.process
|
160
|
+
|
161
|
+
expect(Document.last.reference)
|
162
|
+
.to eq('X-MAGIC-10')
|
163
|
+
end
|
164
|
+
end
|
165
|
+
end
|
166
|
+
|
167
|
+
context 'with after_save symbol option' do
|
168
|
+
it_behaves_like 'a request handler', status: :created do
|
169
|
+
let(:options_hash) do
|
170
|
+
{
|
171
|
+
after_save: :add_magic_reference_and_trigger
|
172
|
+
}
|
173
|
+
end
|
174
|
+
|
175
|
+
let(:extra_params) do
|
176
|
+
{
|
177
|
+
document: {
|
178
|
+
name: 'My Document'
|
179
|
+
}
|
180
|
+
}
|
181
|
+
end
|
182
|
+
|
183
|
+
let(:expected_json) do
|
184
|
+
{
|
185
|
+
'name' => 'My Document',
|
186
|
+
'reference' => 'X-MAGIC-15'
|
187
|
+
}
|
188
|
+
end
|
189
|
+
|
190
|
+
before do
|
191
|
+
allow(Worker).to receive(:perform)
|
192
|
+
end
|
193
|
+
|
194
|
+
it 'creates entry' do
|
195
|
+
expect { handler.process }
|
196
|
+
.to change(Document, :count)
|
197
|
+
.by(1)
|
198
|
+
end
|
199
|
+
|
200
|
+
it 'trigger workers after saving' do
|
201
|
+
handler.process
|
202
|
+
|
203
|
+
expect(Worker).to have_received(:perform)
|
204
|
+
.with(Document.last.id)
|
205
|
+
end
|
206
|
+
|
207
|
+
it 'changes entry after saving' do
|
208
|
+
handler.process
|
209
|
+
|
210
|
+
expect(Document.last.reference)
|
211
|
+
.to eq('X-MAGIC-15')
|
212
|
+
end
|
213
|
+
end
|
214
|
+
end
|
109
215
|
end
|
110
216
|
|
111
217
|
context 'with build_with as symbol' do
|
@@ -8,5 +8,123 @@ describe Azeroth::RequestHandler::Index do
|
|
8
8
|
let(:documents_count) { 3 }
|
9
9
|
let(:expected_resource) { Document.all }
|
10
10
|
end
|
11
|
+
|
12
|
+
context 'when pagination is active' do
|
13
|
+
it_behaves_like 'a request handler' do
|
14
|
+
let(:documents_count) { Random.rand(21..30) }
|
15
|
+
let(:expected_resource) { Document.all.limit(20) }
|
16
|
+
let(:options_hash) { { paginated: true } }
|
17
|
+
|
18
|
+
it 'adds total pages header' do
|
19
|
+
handler.process
|
20
|
+
expect(controller_headers['pages']).to eq(2)
|
21
|
+
end
|
22
|
+
|
23
|
+
it 'adds current page header' do
|
24
|
+
handler.process
|
25
|
+
expect(controller_headers['page']).to eq(1)
|
26
|
+
end
|
27
|
+
|
28
|
+
it 'adds per page header' do
|
29
|
+
handler.process
|
30
|
+
expect(controller_headers['per_page']).to eq(20)
|
31
|
+
end
|
32
|
+
end
|
33
|
+
|
34
|
+
context 'when page is given' do
|
35
|
+
it_behaves_like 'a request handler' do
|
36
|
+
let(:documents_count) { Random.rand(41..50) }
|
37
|
+
let(:expected_resource) { Document.all.offset(20).limit(20) }
|
38
|
+
let(:options_hash) { { paginated: true } }
|
39
|
+
let(:extra_params) { { page: '2' } }
|
40
|
+
|
41
|
+
it 'adds total pages header' do
|
42
|
+
handler.process
|
43
|
+
expect(controller_headers['pages']).to eq(3)
|
44
|
+
end
|
45
|
+
|
46
|
+
it 'adds current page header' do
|
47
|
+
handler.process
|
48
|
+
expect(controller_headers['page']).to eq(2)
|
49
|
+
end
|
50
|
+
|
51
|
+
it 'adds per page header' do
|
52
|
+
handler.process
|
53
|
+
expect(controller_headers['per_page']).to eq(20)
|
54
|
+
end
|
55
|
+
end
|
56
|
+
end
|
57
|
+
|
58
|
+
context 'when third page is given' do
|
59
|
+
it_behaves_like 'a request handler' do
|
60
|
+
let(:documents_count) { Random.rand(41..50) }
|
61
|
+
let(:expected_resource) { Document.all.offset(40) }
|
62
|
+
let(:options_hash) { { paginated: true } }
|
63
|
+
let(:extra_params) { { page: '3' } }
|
64
|
+
|
65
|
+
it 'adds total pages header' do
|
66
|
+
handler.process
|
67
|
+
expect(controller_headers['pages']).to eq(3)
|
68
|
+
end
|
69
|
+
|
70
|
+
it 'adds current page header' do
|
71
|
+
handler.process
|
72
|
+
expect(controller_headers['page']).to eq(3)
|
73
|
+
end
|
74
|
+
|
75
|
+
it 'adds per page header' do
|
76
|
+
handler.process
|
77
|
+
expect(controller_headers['per_page']).to eq(20)
|
78
|
+
end
|
79
|
+
end
|
80
|
+
end
|
81
|
+
|
82
|
+
context 'when per_page is not default' do
|
83
|
+
it_behaves_like 'a request handler' do
|
84
|
+
let(:documents_count) { Random.rand(21..30) }
|
85
|
+
let(:expected_resource) { Document.all.limit(10) }
|
86
|
+
let(:options_hash) { { paginated: true, per_page: 10 } }
|
87
|
+
|
88
|
+
it 'adds total pages header' do
|
89
|
+
handler.process
|
90
|
+
expect(controller_headers['pages']).to eq(3)
|
91
|
+
end
|
92
|
+
|
93
|
+
it 'adds current page header' do
|
94
|
+
handler.process
|
95
|
+
expect(controller_headers['page']).to eq(1)
|
96
|
+
end
|
97
|
+
|
98
|
+
it 'adds per page header' do
|
99
|
+
handler.process
|
100
|
+
expect(controller_headers['per_page']).to eq(10)
|
101
|
+
end
|
102
|
+
end
|
103
|
+
end
|
104
|
+
|
105
|
+
context 'when per page is given in params' do
|
106
|
+
it_behaves_like 'a request handler' do
|
107
|
+
let(:documents_count) { Random.rand(41..50) }
|
108
|
+
let(:expected_resource) { Document.all.offset(10).limit(10) }
|
109
|
+
let(:options_hash) { { paginated: true, per_page: 15 } }
|
110
|
+
let(:extra_params) { { page: '2', per_page: '10' } }
|
111
|
+
|
112
|
+
it 'adds total pages header' do
|
113
|
+
handler.process
|
114
|
+
expect(controller_headers['pages']).to eq(5)
|
115
|
+
end
|
116
|
+
|
117
|
+
it 'adds current page header' do
|
118
|
+
handler.process
|
119
|
+
expect(controller_headers['page']).to eq(2)
|
120
|
+
end
|
121
|
+
|
122
|
+
it 'adds per page header' do
|
123
|
+
handler.process
|
124
|
+
expect(controller_headers['per_page']).to eq(10)
|
125
|
+
end
|
126
|
+
end
|
127
|
+
end
|
128
|
+
end
|
11
129
|
end
|
12
130
|
end
|