cathode 0.0.1 → 0.1.0
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/README.md +346 -125
- data/Rakefile +1 -0
- data/app/controllers/cathode/base_controller.rb +28 -45
- data/app/models/cathode/token.rb +21 -0
- data/config/routes.rb +16 -0
- data/db/migrate/20140425164100_create_cathode_tokens.rb +11 -0
- data/lib/cathode.rb +0 -13
- data/lib/cathode/_version.rb +2 -1
- data/lib/cathode/action.rb +197 -39
- data/lib/cathode/action_dsl.rb +60 -0
- data/lib/cathode/base.rb +81 -12
- data/lib/cathode/create_request.rb +21 -0
- data/lib/cathode/custom_request.rb +5 -0
- data/lib/cathode/debug.rb +25 -0
- data/lib/cathode/destroy_request.rb +13 -0
- data/lib/cathode/engine.rb +9 -0
- data/lib/cathode/exceptions.rb +20 -0
- data/lib/cathode/index_request.rb +40 -0
- data/lib/cathode/object_collection.rb +49 -0
- data/lib/cathode/query.rb +24 -0
- data/lib/cathode/railtie.rb +21 -0
- data/lib/cathode/request.rb +139 -7
- data/lib/cathode/resource.rb +50 -19
- data/lib/cathode/resource_dsl.rb +46 -0
- data/lib/cathode/show_request.rb +13 -0
- data/lib/cathode/update_request.rb +26 -0
- data/lib/cathode/version.rb +112 -23
- data/lib/tasks/cathode_tasks.rake +5 -4
- data/spec/dummy/app/api/api.rb +0 -0
- data/spec/dummy/app/models/payment.rb +3 -0
- data/spec/dummy/app/models/product.rb +1 -0
- data/spec/dummy/app/models/sale.rb +5 -0
- data/spec/dummy/app/models/salesperson.rb +3 -0
- data/spec/dummy/db/development.sqlite3 +0 -0
- data/spec/dummy/db/migrate/20140409183635_create_sales.rb +11 -0
- data/spec/dummy/db/migrate/20140423172419_create_salespeople.rb +11 -0
- data/spec/dummy/db/migrate/20140424181343_create_payments.rb +10 -0
- data/spec/dummy/db/schema.rb +31 -1
- data/spec/dummy/db/test.sqlite3 +0 -0
- data/spec/dummy/log/development.log +1167 -0
- data/spec/dummy/log/test.log +180602 -0
- data/spec/dummy/spec/factories/payments.rb +8 -0
- data/spec/dummy/spec/factories/products.rb +1 -1
- data/spec/dummy/spec/factories/sales.rb +9 -0
- data/spec/dummy/spec/factories/salespeople.rb +7 -0
- data/spec/dummy/spec/requests/requests_spec.rb +434 -0
- data/spec/lib/cathode/action_spec.rb +136 -0
- data/spec/lib/cathode/base_spec.rb +34 -0
- data/spec/lib/cathode/create_request_spec.rb +40 -0
- data/spec/lib/cathode/custom_request_spec.rb +31 -0
- data/spec/lib/cathode/debug_spec.rb +25 -0
- data/spec/lib/cathode/destroy_request_spec.rb +28 -0
- data/spec/lib/cathode/index_request_spec.rb +62 -0
- data/spec/lib/cathode/object_collection_spec.rb +66 -0
- data/spec/lib/cathode/query_spec.rb +28 -0
- data/spec/lib/cathode/request_spec.rb +58 -0
- data/spec/lib/cathode/resource_spec.rb +482 -0
- data/spec/lib/cathode/show_request_spec.rb +23 -0
- data/spec/lib/cathode/update_request_spec.rb +41 -0
- data/spec/lib/cathode/version_spec.rb +416 -0
- data/spec/models/cathode/token_spec.rb +62 -0
- data/spec/spec_helper.rb +8 -2
- data/spec/support/factories/payments.rb +3 -0
- data/spec/support/factories/sale.rb +3 -0
- data/spec/support/factories/salespeople.rb +3 -0
- data/spec/support/factories/token.rb +3 -0
- data/spec/support/helpers.rb +13 -2
- metadata +192 -47
- data/app/helpers/cathode/application_helper.rb +0 -4
- data/spec/dummy/app/api/dummy_api.rb +0 -4
- data/spec/integration/api_spec.rb +0 -88
- data/spec/lib/action_spec.rb +0 -140
- data/spec/lib/base_spec.rb +0 -28
- data/spec/lib/request_spec.rb +0 -5
- data/spec/lib/resources_spec.rb +0 -78
- data/spec/lib/versioning_spec.rb +0 -104
@@ -0,0 +1,23 @@
|
|
1
|
+
require 'spec_helper'
|
2
|
+
|
3
|
+
describe Cathode::ShowRequest do
|
4
|
+
subject do
|
5
|
+
Cathode::ShowRequest.new(context_stub(params: ActionController::Parameters.new(params.merge(controller: 'products', action: 'show'))))
|
6
|
+
end
|
7
|
+
before do
|
8
|
+
use_api do
|
9
|
+
resources :products, actions: [:show]
|
10
|
+
end
|
11
|
+
end
|
12
|
+
|
13
|
+
let(:params) { { id: 3 } }
|
14
|
+
let!(:products) { create_list(:product, 3) }
|
15
|
+
|
16
|
+
it 'sets status as ok' do
|
17
|
+
expect(subject._status).to eq(:ok)
|
18
|
+
end
|
19
|
+
|
20
|
+
it 'sets body as the resource' do
|
21
|
+
expect(subject._body).to eq(products[2])
|
22
|
+
end
|
23
|
+
end
|
@@ -0,0 +1,41 @@
|
|
1
|
+
require 'spec_helper'
|
2
|
+
|
3
|
+
describe Cathode::UpdateRequest do
|
4
|
+
subject do
|
5
|
+
Cathode::UpdateRequest.new(context_stub(params: ActionController::Parameters.new(params.merge(controller: 'products', action: 'update'))))
|
6
|
+
end
|
7
|
+
before do
|
8
|
+
use_api do
|
9
|
+
resources :products, actions: [:update] do
|
10
|
+
attributes do
|
11
|
+
params.require(:product).permit(:title)
|
12
|
+
end
|
13
|
+
end
|
14
|
+
end
|
15
|
+
end
|
16
|
+
let!(:product) { create(:product, title: 'cool product') }
|
17
|
+
|
18
|
+
context 'with valid attributes' do
|
19
|
+
let(:params) { { id: product.id, product: { title: 'cooler product' } } }
|
20
|
+
|
21
|
+
it 'sets status as ok' do
|
22
|
+
expect(subject._status).to eq(:ok)
|
23
|
+
end
|
24
|
+
|
25
|
+
it 'sets body as the updated record' do
|
26
|
+
expect(subject._body.title).to eq('cooler product')
|
27
|
+
end
|
28
|
+
end
|
29
|
+
|
30
|
+
context 'with invalid attributes' do
|
31
|
+
let(:params) { { id: product.id, title: 'cooler product' } }
|
32
|
+
|
33
|
+
it 'sets status as bad request' do
|
34
|
+
expect(subject._status).to eq(:bad_request)
|
35
|
+
end
|
36
|
+
|
37
|
+
it 'sets body as error message' do
|
38
|
+
expect(subject._body).to eq('param is missing or the value is empty: product')
|
39
|
+
end
|
40
|
+
end
|
41
|
+
end
|
@@ -0,0 +1,416 @@
|
|
1
|
+
require 'spec_helper'
|
2
|
+
|
3
|
+
describe Cathode::Version do
|
4
|
+
describe '.standardize' do
|
5
|
+
subject { Cathode::Version.standardize(version) }
|
6
|
+
|
7
|
+
context 'with integer' do
|
8
|
+
let(:version) { 1 }
|
9
|
+
|
10
|
+
it 'sets the semantic version' do
|
11
|
+
expect(subject).to eq('1.0.0')
|
12
|
+
end
|
13
|
+
end
|
14
|
+
|
15
|
+
context 'with float' do
|
16
|
+
let(:version) { 1.5 }
|
17
|
+
|
18
|
+
it 'sets the semantic version' do
|
19
|
+
expect(subject).to eq('1.5.0')
|
20
|
+
end
|
21
|
+
end
|
22
|
+
|
23
|
+
context 'with string' do
|
24
|
+
let(:version) { '1.5.1' }
|
25
|
+
|
26
|
+
it 'sets the semantic version' do
|
27
|
+
expect(subject).to eq('1.5.1')
|
28
|
+
end
|
29
|
+
end
|
30
|
+
|
31
|
+
context 'with prerelease' do
|
32
|
+
let(:version) { '1.6.0-pre' }
|
33
|
+
|
34
|
+
it 'sets the semantic version' do
|
35
|
+
expect(subject).to eq('1.6.0-pre')
|
36
|
+
end
|
37
|
+
end
|
38
|
+
end
|
39
|
+
|
40
|
+
describe '.define' do
|
41
|
+
subject { Cathode::Version.define('1.0.0') { resources :sales } }
|
42
|
+
|
43
|
+
context 'when version already exists' do
|
44
|
+
before do
|
45
|
+
use_api do
|
46
|
+
resources :products, actions: [:index]
|
47
|
+
end
|
48
|
+
end
|
49
|
+
|
50
|
+
it 'adds to the version' do
|
51
|
+
expect(subject._resources.names).to match_array([:products, :sales])
|
52
|
+
end
|
53
|
+
end
|
54
|
+
|
55
|
+
context 'when version does not exist' do
|
56
|
+
it 'creates a new version' do
|
57
|
+
expect(subject._resources.names).to match_array([:sales])
|
58
|
+
end
|
59
|
+
end
|
60
|
+
end
|
61
|
+
|
62
|
+
describe '.new' do
|
63
|
+
subject { Cathode::Version.new(version, &block) }
|
64
|
+
let(:version) { 1 }
|
65
|
+
before(:each) do
|
66
|
+
Cathode::Version.all.clear
|
67
|
+
end
|
68
|
+
|
69
|
+
context 'with bad version number' do
|
70
|
+
let(:version) { 'a' }
|
71
|
+
let(:block) { nil }
|
72
|
+
|
73
|
+
it 'raises an error' do
|
74
|
+
expect { subject }.to raise_error(ArgumentError)
|
75
|
+
end
|
76
|
+
end
|
77
|
+
|
78
|
+
context 'with no params or block' do
|
79
|
+
let(:block) do
|
80
|
+
proc do
|
81
|
+
resources :products
|
82
|
+
end
|
83
|
+
end
|
84
|
+
|
85
|
+
it 'creates the resource' do
|
86
|
+
expect(Cathode::Resource).to receive(:new) do |resource, params, &block|
|
87
|
+
expect(resource).to eq(:products)
|
88
|
+
expect(params).to eq(singular: false)
|
89
|
+
expect(block).to be_nil
|
90
|
+
end
|
91
|
+
subject
|
92
|
+
end
|
93
|
+
end
|
94
|
+
|
95
|
+
context 'with params' do
|
96
|
+
let(:block) do
|
97
|
+
proc do
|
98
|
+
resources :sales, actions: [:index, :create]
|
99
|
+
end
|
100
|
+
end
|
101
|
+
|
102
|
+
it 'creates the resource' do
|
103
|
+
expect(Cathode::Resource).to receive(:new) do |resource, params, &block|
|
104
|
+
expect(resource).to eq(:sales)
|
105
|
+
expect(params).to eq(actions: [:index, :create], singular: false)
|
106
|
+
expect(block).to be_nil
|
107
|
+
end
|
108
|
+
subject
|
109
|
+
end
|
110
|
+
end
|
111
|
+
|
112
|
+
context 'with params and block' do
|
113
|
+
let(:block) do
|
114
|
+
proc do
|
115
|
+
get :custom
|
116
|
+
resources :sales, actions: [:index] do
|
117
|
+
action :show
|
118
|
+
end
|
119
|
+
end
|
120
|
+
end
|
121
|
+
|
122
|
+
it 'creates the resource' do
|
123
|
+
expect(subject._resources.names).to match_array([:sales])
|
124
|
+
end
|
125
|
+
|
126
|
+
it 'creates the action' do
|
127
|
+
expect(subject.actions.names).to match_array([:custom])
|
128
|
+
end
|
129
|
+
end
|
130
|
+
|
131
|
+
context 'with duplicate resource' do
|
132
|
+
let(:block) do
|
133
|
+
proc do
|
134
|
+
resources :products, actions: [:index]
|
135
|
+
resources :products, actions: [:show]
|
136
|
+
end
|
137
|
+
end
|
138
|
+
|
139
|
+
it 'combines the actions' do
|
140
|
+
expect(subject._resources.names).to match_array([:products])
|
141
|
+
expect(subject._resources.find(:products).actions.names).to match_array([:index, :show])
|
142
|
+
end
|
143
|
+
end
|
144
|
+
|
145
|
+
context 'with inherited version' do
|
146
|
+
before do
|
147
|
+
Cathode::Version.new 1 do
|
148
|
+
resources :sales, actions: [:index, :show]
|
149
|
+
get :status
|
150
|
+
end
|
151
|
+
end
|
152
|
+
let(:version) { 1.5 }
|
153
|
+
|
154
|
+
context 'with a new action' do
|
155
|
+
let(:block) do
|
156
|
+
proc do
|
157
|
+
resources :sales do
|
158
|
+
action :destroy
|
159
|
+
end
|
160
|
+
end
|
161
|
+
end
|
162
|
+
|
163
|
+
it 'inherits the actions from the previous version' do
|
164
|
+
expect(subject._resources.names).to match_array([:sales])
|
165
|
+
expect(subject._resources.find(:sales).actions.names).to match_array([:index, :show, :destroy])
|
166
|
+
expect(subject.actions.names).to eq([:status])
|
167
|
+
end
|
168
|
+
|
169
|
+
it 'leaves the previous version intact' do
|
170
|
+
subject
|
171
|
+
previous_version = Cathode::Version.find('1.0.0')
|
172
|
+
expect(previous_version._resources.find(:sales).actions.names).to match_array([:index, :show])
|
173
|
+
end
|
174
|
+
end
|
175
|
+
|
176
|
+
context 'with a new resource' do
|
177
|
+
let(:block) { proc { resources :products, actions: [:index] } }
|
178
|
+
|
179
|
+
it 'inherits the resources from the previous version' do
|
180
|
+
expect(subject._resources.names).to match_array([:products, :sales])
|
181
|
+
expect(subject._resources.find(:sales).actions.names).to match_array([:index, :show])
|
182
|
+
expect(subject._resources.find(:products).actions.names).to match_array([:index])
|
183
|
+
end
|
184
|
+
end
|
185
|
+
|
186
|
+
context 'with a removed resource' do
|
187
|
+
context 'with an unkown resource' do
|
188
|
+
let(:block) { proc { remove_resources :factories } }
|
189
|
+
|
190
|
+
it 'raises an error' do
|
191
|
+
expect { subject }.to raise_error(Cathode::UnknownResourceError)
|
192
|
+
end
|
193
|
+
end
|
194
|
+
|
195
|
+
context 'with a single resource' do
|
196
|
+
let(:block) do
|
197
|
+
proc do
|
198
|
+
resources :products, actions: [:index]
|
199
|
+
remove_resources :sales
|
200
|
+
end
|
201
|
+
end
|
202
|
+
|
203
|
+
it 'does not use the resource' do
|
204
|
+
expect(subject._resources.names).to match_array([:products])
|
205
|
+
end
|
206
|
+
end
|
207
|
+
|
208
|
+
context 'with an array of resources' do
|
209
|
+
before do
|
210
|
+
Cathode::Version.new 1.2 do
|
211
|
+
resources :products, actions: [:index]
|
212
|
+
end
|
213
|
+
end
|
214
|
+
|
215
|
+
let(:block) { proc { remove_resources [:sales, :products] } }
|
216
|
+
|
217
|
+
it 'does not use the resource' do
|
218
|
+
expect(subject._resources.names).to be_empty
|
219
|
+
end
|
220
|
+
end
|
221
|
+
end
|
222
|
+
|
223
|
+
context 'with a removed action' do
|
224
|
+
context 'within a resource' do
|
225
|
+
context 'with an unknown resource' do
|
226
|
+
let(:block) { proc { remove_action :destroy, from: :unknown } }
|
227
|
+
|
228
|
+
it 'raises an error' do
|
229
|
+
expect { subject }.to raise_error(
|
230
|
+
Cathode::UnknownResourceError,
|
231
|
+
"Unknown resource `unknown' on ancestor version 1.0.0"
|
232
|
+
)
|
233
|
+
end
|
234
|
+
end
|
235
|
+
|
236
|
+
context 'with an unkown action' do
|
237
|
+
let(:block) { proc { remove_action :destroy, from: :sales } }
|
238
|
+
|
239
|
+
it 'raises an error' do
|
240
|
+
expect { subject }.to raise_error(
|
241
|
+
Cathode::UnknownActionError,
|
242
|
+
"Unknown action `destroy' on resource `sales'"
|
243
|
+
)
|
244
|
+
end
|
245
|
+
end
|
246
|
+
|
247
|
+
context 'with a single action' do
|
248
|
+
let(:block) do
|
249
|
+
proc do
|
250
|
+
resources :products, actions: [:index]
|
251
|
+
remove_action :index, from: :sales
|
252
|
+
end
|
253
|
+
end
|
254
|
+
|
255
|
+
it 'does not use the action' do
|
256
|
+
subject
|
257
|
+
expect(subject._resources.find(:sales).actions.names).to match_array([:show])
|
258
|
+
expect(subject._resources.find(:products).actions.names).to match_array([:index])
|
259
|
+
end
|
260
|
+
end
|
261
|
+
|
262
|
+
context 'with multiple actions' do
|
263
|
+
let(:block) do
|
264
|
+
proc do
|
265
|
+
resources :products, actions: [:index]
|
266
|
+
remove_actions :index, :show, from: :sales
|
267
|
+
end
|
268
|
+
end
|
269
|
+
|
270
|
+
it 'does not use the actions' do
|
271
|
+
subject
|
272
|
+
expect(subject._resources.find(:sales).actions.names).to match_array([])
|
273
|
+
expect(subject._resources.find(:products).actions.names).to match_array([:index])
|
274
|
+
end
|
275
|
+
end
|
276
|
+
end
|
277
|
+
|
278
|
+
context 'outside of a resource' do
|
279
|
+
before do
|
280
|
+
Cathode::Version.new 1.5 do
|
281
|
+
get :custom
|
282
|
+
delete :custom2
|
283
|
+
end
|
284
|
+
end
|
285
|
+
let(:version) { 2 }
|
286
|
+
|
287
|
+
context 'with an unkown action' do
|
288
|
+
let(:block) { proc { remove_action :unknown } }
|
289
|
+
|
290
|
+
it 'raises an error' do
|
291
|
+
expect { subject }.to raise_error(
|
292
|
+
Cathode::UnknownActionError,
|
293
|
+
"Unknown action `unknown' on ancestor version 1.5.0"
|
294
|
+
)
|
295
|
+
end
|
296
|
+
end
|
297
|
+
|
298
|
+
context 'with a single action' do
|
299
|
+
let(:block) { proc { remove_action :custom } }
|
300
|
+
|
301
|
+
it 'removes the action' do
|
302
|
+
expect(subject.actions.names).to match_array([:status, :custom2])
|
303
|
+
end
|
304
|
+
end
|
305
|
+
|
306
|
+
context 'with multiple actions' do
|
307
|
+
let(:block) { proc { remove_actions :custom, :custom2 } }
|
308
|
+
|
309
|
+
it 'removes the action' do
|
310
|
+
expect(subject.actions.names).to eq([:status])
|
311
|
+
end
|
312
|
+
end
|
313
|
+
end
|
314
|
+
end
|
315
|
+
end
|
316
|
+
end
|
317
|
+
|
318
|
+
describe '.find' do
|
319
|
+
subject { Cathode::Version.find(version_number) }
|
320
|
+
before do
|
321
|
+
use_api do
|
322
|
+
resources :products
|
323
|
+
version 1.5 do
|
324
|
+
resources :sales
|
325
|
+
end
|
326
|
+
end
|
327
|
+
end
|
328
|
+
|
329
|
+
context 'with a valid SemVer number' do
|
330
|
+
let(:version_number) { '1.5.0' }
|
331
|
+
|
332
|
+
it 'returns the version matching the version number' do
|
333
|
+
expect(subject.version).to eq('1.5.0')
|
334
|
+
end
|
335
|
+
end
|
336
|
+
|
337
|
+
context 'with a non-standard SemVer number' do
|
338
|
+
let(:version_number) { '1.5' }
|
339
|
+
|
340
|
+
it 'returns the version matching the standardized number' do
|
341
|
+
expect(subject.version).to eq('1.5.0')
|
342
|
+
end
|
343
|
+
end
|
344
|
+
|
345
|
+
context 'with an invalid SemVer number' do
|
346
|
+
let(:version_number) { '1.x' }
|
347
|
+
|
348
|
+
it 'returns nil' do
|
349
|
+
expect(subject).to be_nil
|
350
|
+
end
|
351
|
+
end
|
352
|
+
end
|
353
|
+
|
354
|
+
describe '#resource?' do
|
355
|
+
subject { Cathode::Version.find('1.0.0').resource?(resource) }
|
356
|
+
before do
|
357
|
+
use_api do
|
358
|
+
resources :products
|
359
|
+
end
|
360
|
+
end
|
361
|
+
|
362
|
+
context 'when the resource is present' do
|
363
|
+
let(:resource) { 'products' }
|
364
|
+
|
365
|
+
it 'is true' do
|
366
|
+
expect(subject).to be_true
|
367
|
+
end
|
368
|
+
end
|
369
|
+
|
370
|
+
context 'when the resource is not present' do
|
371
|
+
let(:resource) { 'sales' }
|
372
|
+
|
373
|
+
it 'is false' do
|
374
|
+
expect(subject).to be_false
|
375
|
+
end
|
376
|
+
end
|
377
|
+
end
|
378
|
+
|
379
|
+
describe '#action?' do
|
380
|
+
subject { Cathode::Version.find('1.0.0').action?(resource, action) }
|
381
|
+
before do
|
382
|
+
use_api do
|
383
|
+
resources :products, actions: [:index]
|
384
|
+
end
|
385
|
+
end
|
386
|
+
|
387
|
+
context 'when the resource is not present' do
|
388
|
+
let(:resource) { 'sales' }
|
389
|
+
let(:action) { 'index' }
|
390
|
+
|
391
|
+
it 'is false' do
|
392
|
+
expect(subject).to be_false
|
393
|
+
end
|
394
|
+
end
|
395
|
+
|
396
|
+
context 'when the resource is present' do
|
397
|
+
let(:resource) { 'products' }
|
398
|
+
|
399
|
+
context 'when the action is present' do
|
400
|
+
let(:action) { 'index' }
|
401
|
+
|
402
|
+
it 'is true' do
|
403
|
+
expect(subject).to be_true
|
404
|
+
end
|
405
|
+
end
|
406
|
+
|
407
|
+
context 'when the action is not present' do
|
408
|
+
let(:action) { 'show' }
|
409
|
+
|
410
|
+
it 'is false' do
|
411
|
+
expect(subject).to be_false
|
412
|
+
end
|
413
|
+
end
|
414
|
+
end
|
415
|
+
end
|
416
|
+
end
|