praxis 0.13.0 → 0.14.0
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +4 -4
- data/.ruby-version +1 -1
- data/.travis.yml +15 -2
- data/CHANGELOG.md +54 -1
- data/bin/praxis +49 -2
- data/lib/api_browser/Gruntfile.js +247 -90
- data/lib/api_browser/app/bower_components/angular-mocks/.bower.json +19 -0
- data/lib/api_browser/app/bower_components/angular-mocks/README.md +57 -0
- data/lib/api_browser/app/bower_components/angular-mocks/angular-mocks.js +2193 -0
- data/lib/api_browser/app/bower_components/angular-mocks/bower.json +9 -0
- data/lib/api_browser/app/bower_components/angular-mocks/package.json +27 -0
- data/lib/api_browser/app/bower_components/angular/.bower.json +6 -5
- data/lib/api_browser/app/bower_components/angular/README.md +23 -4
- data/lib/api_browser/app/bower_components/angular/angular-csp.css +6 -0
- data/lib/api_browser/app/bower_components/angular/angular.js +2287 -1597
- data/lib/api_browser/app/bower_components/angular/angular.min.js +212 -205
- data/lib/api_browser/app/bower_components/angular/angular.min.js.gzip +0 -0
- data/lib/api_browser/app/bower_components/angular/angular.min.js.map +3 -3
- data/lib/api_browser/app/bower_components/angular/bower.json +2 -1
- data/lib/api_browser/app/bower_components/angular/package.json +25 -0
- data/lib/api_browser/app/bower_components/showdown/.bower.json +39 -0
- data/lib/api_browser/app/bower_components/showdown/.jshintignore +2 -0
- data/lib/api_browser/app/bower_components/showdown/.travis.yml +8 -0
- data/lib/api_browser/app/bower_components/showdown/Gruntfile.js +100 -0
- data/lib/api_browser/app/bower_components/showdown/README.md +317 -0
- data/lib/api_browser/app/bower_components/showdown/bower.json +26 -0
- data/lib/api_browser/app/bower_components/showdown/compressed/Showdown.js +1606 -0
- data/lib/api_browser/app/bower_components/showdown/compressed/Showdown.js.map +1 -0
- data/lib/api_browser/app/bower_components/showdown/compressed/Showdown.min.js +2 -0
- data/lib/api_browser/app/bower_components/showdown/compressed/extensions/github.min.js +2 -0
- data/lib/api_browser/app/bower_components/showdown/compressed/extensions/github.min.js.map +1 -0
- data/lib/api_browser/app/bower_components/showdown/compressed/extensions/prettify.min.js +2 -0
- data/lib/api_browser/app/bower_components/showdown/compressed/extensions/prettify.min.js.map +1 -0
- data/lib/api_browser/app/bower_components/showdown/compressed/extensions/table.min.js +2 -0
- data/lib/api_browser/app/bower_components/showdown/compressed/extensions/table.min.js.map +1 -0
- data/lib/api_browser/app/bower_components/showdown/compressed/extensions/twitter.min.js +2 -0
- data/lib/api_browser/app/bower_components/showdown/compressed/extensions/twitter.min.js.map +1 -0
- data/lib/api_browser/app/bower_components/showdown/license.txt +34 -0
- data/lib/api_browser/app/bower_components/showdown/package.json +47 -0
- data/lib/api_browser/app/bower_components/showdown/src/extensions/github.js +25 -0
- data/lib/api_browser/app/bower_components/showdown/src/extensions/prettify.js +29 -0
- data/lib/api_browser/app/bower_components/showdown/src/extensions/table.js +106 -0
- data/lib/api_browser/app/bower_components/showdown/src/extensions/twitter.js +42 -0
- data/lib/api_browser/app/bower_components/showdown/src/ng-showdown.js +150 -0
- data/lib/api_browser/app/bower_components/showdown/src/showdown.js +1454 -0
- data/lib/api_browser/app/index.html +6 -4
- data/lib/api_browser/app/js/app.js +1 -2
- data/lib/api_browser/app/js/controllers/action.js +4 -4
- data/lib/api_browser/app/js/controllers/controller.js +1 -1
- data/lib/api_browser/app/js/controllers/menu.js +5 -3
- data/lib/api_browser/app/js/controllers/type.js +5 -5
- data/lib/api_browser/app/js/directives/attribute_description.js +5 -5
- data/lib/api_browser/app/js/directives/attribute_table.js +1 -1
- data/lib/api_browser/app/js/directives/attribute_table_row.js +2 -2
- data/lib/api_browser/app/js/directives/no_container.js +1 -1
- data/lib/api_browser/app/js/directives/request_body.js +5 -5
- data/lib/api_browser/app/js/directives/request_headers.js +3 -6
- data/lib/api_browser/app/js/directives/request_parameters.js +3 -6
- data/lib/api_browser/app/js/directives/type_label.js +4 -5
- data/lib/api_browser/app/js/factories/Documentation.js +4 -4
- data/lib/api_browser/app/js/factories/PayloadTemplates.js +2 -2
- data/lib/api_browser/app/js/factories/TypeTemplates.js +3 -3
- data/lib/api_browser/app/js/filters/markdown.js +6 -0
- data/lib/api_browser/app/js/filters/resource_name.js +2 -2
- data/lib/api_browser/app/sass/modules/_header.scss +2 -7
- data/lib/api_browser/app/sass/{main.scss → praxis.scss} +0 -0
- data/lib/api_browser/app/sass/variables/_bootstrap-variables.scss +370 -367
- data/lib/api_browser/app/views/action.html +2 -2
- data/lib/api_browser/app/views/controller.html +2 -2
- data/lib/api_browser/app/views/directives/attribute_description.html +1 -1
- data/lib/api_browser/app/views/layout.html +2 -11
- data/lib/api_browser/app/views/navbar.html +9 -0
- data/lib/api_browser/app/views/resource/_actions.html +1 -1
- data/lib/api_browser/app/views/type.html +2 -2
- data/lib/api_browser/app/views/type/_details.html +2 -1
- data/lib/api_browser/bower.json +5 -0
- data/lib/api_browser/package.json +18 -7
- data/lib/praxis.rb +8 -3
- data/lib/praxis/action_definition.rb +28 -6
- data/lib/praxis/api_definition.rb +30 -2
- data/lib/praxis/api_general_info.rb +36 -0
- data/lib/praxis/bootloader.rb +1 -0
- data/lib/praxis/collection.rb +34 -0
- data/lib/praxis/controller.rb +7 -0
- data/lib/praxis/dispatcher.rb +3 -0
- data/lib/praxis/links.rb +2 -8
- data/lib/praxis/media_type.rb +6 -24
- data/lib/praxis/media_type_collection.rb +6 -2
- data/lib/praxis/plugin_concern.rb +2 -1
- data/lib/praxis/request.rb +24 -15
- data/lib/praxis/request_stages/request_stage.rb +19 -4
- data/lib/praxis/request_stages/validate_params_and_headers.rb +1 -1
- data/lib/praxis/request_stages/validate_payload.rb +1 -1
- data/lib/praxis/resource_definition.rb +45 -10
- data/lib/praxis/response_definition.rb +46 -27
- data/lib/praxis/restful_doc_generator.rb +94 -7
- data/lib/praxis/simple_media_type.rb +2 -9
- data/lib/praxis/stage.rb +1 -4
- data/lib/praxis/tasks/api_docs.rb +51 -19
- data/lib/praxis/tasks/routes.rb +19 -15
- data/lib/praxis/types/media_type_common.rb +31 -0
- data/lib/praxis/types/multipart.rb +4 -4
- data/lib/praxis/version.rb +1 -1
- data/praxis.gemspec +2 -2
- data/spec/api_browser/factories/documentation_spec.js +50 -0
- data/spec/api_browser/filters/attribute_name_spec.js +23 -0
- data/spec/functional_spec.rb +62 -10
- data/spec/praxis/action_definition_spec.rb +12 -4
- data/spec/praxis/api_definition_spec.rb +159 -0
- data/spec/praxis/api_general_info_spec.rb +36 -0
- data/spec/praxis/bootloader_spec.rb +10 -1
- data/spec/praxis/media_type_collection_spec.rb +46 -53
- data/spec/praxis/media_type_spec.rb +6 -6
- data/spec/praxis/request_stage_spec.rb +7 -2
- data/spec/praxis/request_stages_validate_spec.rb +12 -7
- data/spec/praxis/resource_definition_spec.rb +62 -0
- data/spec/praxis/response_definition_spec.rb +26 -16
- data/spec/praxis/stage_spec.rb +4 -8
- data/spec/praxis/types/collection_spec.rb +144 -0
- data/spec/spec_app/app/controllers/instances.rb +8 -2
- data/spec/spec_app/design/api.rb +11 -0
- data/spec/spec_app/design/media_types/instance.rb +12 -0
- data/spec/spec_app/design/media_types/volume.rb +9 -2
- data/spec/spec_app/design/media_types/volume_snapshot.rb +9 -6
- data/spec/spec_app/design/resources/instances.rb +25 -10
- data/spec/support/spec_media_types.rb +1 -1
- data/spec/support/spec_resource_definitions.rb +2 -0
- data/tasks/thor/app.rb +15 -10
- data/tasks/thor/example.rb +115 -115
- data/tasks/thor/templates/generator/empty_app/.gitignore +2 -0
- data/tasks/thor/templates/generator/empty_app/docs/app.js +1 -0
- data/tasks/thor/templates/generator/empty_app/docs/styles.scss +3 -0
- metadata +50 -9
- data/lib/api_browser/app/css/main.css +0 -4511
- data/lib/praxis/types/collection.rb +0 -17
@@ -0,0 +1,23 @@
|
|
1
|
+
describe('attributeName filter', function() {
|
2
|
+
var filter;
|
3
|
+
beforeEach(angular.mock.module('PraxisDocBrowser'));
|
4
|
+
|
5
|
+
beforeEach(inject(function(attributeNameFilter, $sce) {
|
6
|
+
filter = function(input) {
|
7
|
+
return $sce.getTrusted('html', attributeNameFilter(input));
|
8
|
+
};
|
9
|
+
}));
|
10
|
+
|
11
|
+
it('only modifies input with one dot', function() {
|
12
|
+
expect(function(str) {
|
13
|
+
var dotsCount = str.split('.').length - 1;
|
14
|
+
if (dotsCount !== 1) {
|
15
|
+
return str === filter(str);
|
16
|
+
}
|
17
|
+
}).forAll(qc.string);
|
18
|
+
});
|
19
|
+
|
20
|
+
it('adds a tag to the prefix', function() {
|
21
|
+
expect(filter('ns.test')).toEqual('<span class="attribute-prefix">ns.</span>test');
|
22
|
+
});
|
23
|
+
});
|
data/spec/functional_spec.rb
CHANGED
@@ -10,6 +10,14 @@ describe 'Functional specs' do
|
|
10
10
|
|
11
11
|
context 'index' do
|
12
12
|
|
13
|
+
context 'with a valid request' do
|
14
|
+
it 'is successful' do
|
15
|
+
get '/clouds/1/instances?api_version=1.0', nil, 'global_session' => session
|
16
|
+
expect(last_response.headers['Content-Type']).to(
|
17
|
+
eq("application/vnd.acme.instance;type=collection"))
|
18
|
+
end
|
19
|
+
end
|
20
|
+
|
13
21
|
context 'with an incorrect response_content_type param' do
|
14
22
|
around do |example|
|
15
23
|
logger = app.logger
|
@@ -52,15 +60,25 @@ describe 'Functional specs' do
|
|
52
60
|
it 'works' do
|
53
61
|
get '/clouds/1/instances/2?junk=foo&api_version=1.0', nil, 'global_session' => session
|
54
62
|
expect(last_response.status).to eq(200)
|
55
|
-
|
56
|
-
|
57
|
-
|
58
|
-
|
59
|
-
|
60
|
-
|
61
|
-
|
62
|
-
|
63
|
-
|
63
|
+
expected = {
|
64
|
+
"cloud_id" => 1,
|
65
|
+
"id"=>2,
|
66
|
+
"junk"=>"foo",
|
67
|
+
"other_params"=>{
|
68
|
+
"some_date"=>"2012-12-21T00:00:00+00:00",
|
69
|
+
"fail_filter"=>false
|
70
|
+
},
|
71
|
+
"payload"=>{
|
72
|
+
"optional"=>"not given"}
|
73
|
+
}
|
74
|
+
|
75
|
+
expect(JSON.parse(last_response.body)).to eq(expected)
|
76
|
+
|
77
|
+
headers = last_response.headers
|
78
|
+
expect(headers['Content-Type']).to eq('application/vnd.acme.instance')
|
79
|
+
expect(headers['Spec-Middleware']).to eq('used')
|
80
|
+
expect(headers['Content-Length']).to eq(last_response.body.size.to_s)
|
81
|
+
end
|
64
82
|
|
65
83
|
it 'returns early when making the before filter break' do
|
66
84
|
get '/clouds/1/instances/2?junk=foo&api_version=1.0&fail_filter=true', nil, 'global_session' => session
|
@@ -267,7 +285,7 @@ describe 'Functional specs' do
|
|
267
285
|
end
|
268
286
|
|
269
287
|
end
|
270
|
-
|
288
|
+
|
271
289
|
context 'auth_plugin' do
|
272
290
|
it 'can terminate' do
|
273
291
|
post '/clouds/23/instances/1/terminate?api_version=1.0', nil, 'global_session' => session
|
@@ -295,4 +313,38 @@ describe 'Functional specs' do
|
|
295
313
|
end
|
296
314
|
end
|
297
315
|
|
316
|
+
context 'update' do
|
317
|
+
|
318
|
+
|
319
|
+
let(:body) { JSON.pretty_generate(request_payload) }
|
320
|
+
let(:content_type) { 'application/json' }
|
321
|
+
|
322
|
+
before do
|
323
|
+
patch '/clouds/1/instances/3?api_version=1.0', body, 'CONTENT_TYPE' => content_type, 'global_session' => session
|
324
|
+
end
|
325
|
+
|
326
|
+
subject(:response_body) { JSON.parse(last_response.body) }
|
327
|
+
|
328
|
+
context 'with an empty payload' do
|
329
|
+
let(:request_payload) { {} }
|
330
|
+
it { should be_empty }
|
331
|
+
it { should_not have_key('name') }
|
332
|
+
it { should_not have_key('root_volume') }
|
333
|
+
end
|
334
|
+
|
335
|
+
context 'with a provided name' do
|
336
|
+
let(:request_payload) { {name: 'My Instance'} }
|
337
|
+
its(['name']) { should eq('My Instance') }
|
338
|
+
it { should_not have_key('root_volume') }
|
339
|
+
end
|
340
|
+
|
341
|
+
context 'with an explicitly-nil root_volme' do
|
342
|
+
let(:request_payload) { {name: 'My Instance', root_volume: nil} }
|
343
|
+
its(['name']) { should eq('My Instance') }
|
344
|
+
its(['root_volume']) { should be(nil) }
|
345
|
+
end
|
346
|
+
|
347
|
+
|
348
|
+
end
|
349
|
+
|
298
350
|
end
|
@@ -21,7 +21,7 @@ describe Praxis::ActionDefinition do
|
|
21
21
|
end
|
22
22
|
|
23
23
|
subject(:action) do
|
24
|
-
Praxis::ActionDefinition.new(
|
24
|
+
Praxis::ActionDefinition.new(:foo, resource_definition) do
|
25
25
|
routing { get '/:one' }
|
26
26
|
payload { attribute :two, String }
|
27
27
|
headers { header "X_REQUESTED_WITH", 'XMLHttpRequest' }
|
@@ -30,7 +30,7 @@ describe Praxis::ActionDefinition do
|
|
30
30
|
end
|
31
31
|
|
32
32
|
context '#initialize' do
|
33
|
-
its('name') { should eq
|
33
|
+
its('name') { should eq :foo }
|
34
34
|
its('resource_definition') { should be resource_definition }
|
35
35
|
its('params.attributes') { should have_key :one }
|
36
36
|
its('params.attributes') { should have_key :inherited }
|
@@ -116,7 +116,16 @@ describe Praxis::ActionDefinition do
|
|
116
116
|
end
|
117
117
|
|
118
118
|
context '#describe' do
|
119
|
-
|
119
|
+
subject(:describe) { action.describe }
|
120
|
+
|
121
|
+
context 'params' do
|
122
|
+
subject(:param_description) { describe[:params] }
|
123
|
+
it 'includes attribute sources' do
|
124
|
+
attributes = param_description[:type][:attributes]
|
125
|
+
expect(attributes[:inherited][:source]).to eq('query')
|
126
|
+
expect(attributes[:one][:source]).to eq('url')
|
127
|
+
end
|
128
|
+
end
|
120
129
|
end
|
121
130
|
|
122
131
|
context 'href generation' do
|
@@ -156,5 +165,4 @@ describe Praxis::ActionDefinition do
|
|
156
165
|
end
|
157
166
|
|
158
167
|
end
|
159
|
-
|
160
168
|
end
|
@@ -0,0 +1,159 @@
|
|
1
|
+
require 'spec_helper'
|
2
|
+
|
3
|
+
describe Praxis::ApiDefinition do
|
4
|
+
|
5
|
+
subject(:api){ Praxis::ApiDefinition.instance }
|
6
|
+
|
7
|
+
# Without getting a fresh new ApiDefinition it is very difficult to test stuff using the Singleton
|
8
|
+
# So for some tests we're gonna create a new instance and work with it to avoid the singleton issues
|
9
|
+
let(:non_singleton_api) do
|
10
|
+
api_def=Praxis::ApiDefinition.__send__(:new)
|
11
|
+
api_def.instance_eval do |api|
|
12
|
+
api.response_template :template1, &Proc.new {}
|
13
|
+
api.trait :trait1, &Proc.new {}
|
14
|
+
end
|
15
|
+
api_def
|
16
|
+
end
|
17
|
+
|
18
|
+
let(:info_block) do
|
19
|
+
Proc.new do
|
20
|
+
name "Name"
|
21
|
+
title "Title"
|
22
|
+
end
|
23
|
+
end
|
24
|
+
|
25
|
+
context 'singleton' do
|
26
|
+
it 'should be a Singleton' do
|
27
|
+
expect(Praxis::ApiDefinition.ancestors).to include( Singleton )
|
28
|
+
expect(subject).to eq(Praxis::ApiDefinition.instance )
|
29
|
+
end
|
30
|
+
|
31
|
+
it 'has the :ok and :created response templates registered' do
|
32
|
+
expect(api.responses.keys).to include(:ok)
|
33
|
+
expect(api.responses.keys).to include(:created)
|
34
|
+
end
|
35
|
+
end
|
36
|
+
|
37
|
+
context '.response_template' do
|
38
|
+
let(:response_template){ Proc.new {} }
|
39
|
+
let(:api){ non_singleton_api }
|
40
|
+
|
41
|
+
it 'has the defined template1 response_template' do
|
42
|
+
expect(api.responses.keys).to include(:template1)
|
43
|
+
expect(api.response(:template1)).to be_kind_of(Praxis::ResponseTemplate)
|
44
|
+
end
|
45
|
+
it 'also works outside a .define block' do
|
46
|
+
api.response_template :foobar, &response_template
|
47
|
+
expect(api.responses.keys).to include(:foobar)
|
48
|
+
expect(api.response(:foobar)).to be_kind_of(Praxis::ResponseTemplate)
|
49
|
+
end
|
50
|
+
end
|
51
|
+
|
52
|
+
context '.response' do
|
53
|
+
let(:api){ non_singleton_api }
|
54
|
+
|
55
|
+
it 'returns a registered response by name' do
|
56
|
+
expect(api.response(:template1)).to be_kind_of(Praxis::ResponseTemplate)
|
57
|
+
end
|
58
|
+
end
|
59
|
+
|
60
|
+
context '.trait' do
|
61
|
+
let(:api){ non_singleton_api }
|
62
|
+
|
63
|
+
let(:trait2){ Proc.new{} }
|
64
|
+
it 'has the defined trait1 ' do
|
65
|
+
expect(api.traits.keys).to include(:trait1)
|
66
|
+
expect(api.traits[:trait1]).to be_kind_of(Proc)
|
67
|
+
end
|
68
|
+
|
69
|
+
it 'saves it verbatim' do
|
70
|
+
api.trait :trait2, &trait2
|
71
|
+
expect(api.traits[:trait2]).to be(trait2)
|
72
|
+
end
|
73
|
+
|
74
|
+
it 'complains trying to register traits with same name' do
|
75
|
+
api.trait :trait2, &trait2
|
76
|
+
expect{
|
77
|
+
api.trait :trait2, &trait2
|
78
|
+
}.to raise_error(Praxis::Exceptions::InvalidTrait, /Overwriting a previous trait with the same name/)
|
79
|
+
end
|
80
|
+
end
|
81
|
+
|
82
|
+
context '.info' do
|
83
|
+
|
84
|
+
let(:api){ non_singleton_api }
|
85
|
+
|
86
|
+
context 'with a version' do
|
87
|
+
it 'saves the data into the correct version hash' do
|
88
|
+
expect(api.infos.keys).to_not include("9.0")
|
89
|
+
api.info("9.0", &info_block)
|
90
|
+
expect(api.infos.keys).to include("9.0")
|
91
|
+
end
|
92
|
+
it 'immediate invokes the block' do
|
93
|
+
expect(api.infos["9.0"]).to receive(:instance_eval)
|
94
|
+
api.info("9.0", &info_block)
|
95
|
+
end
|
96
|
+
end
|
97
|
+
context 'without a version' do
|
98
|
+
it 'saves it into nil if no version is passed' do
|
99
|
+
expect(api.infos.keys).to_not include(nil)
|
100
|
+
api.info do
|
101
|
+
description "Global Description"
|
102
|
+
end
|
103
|
+
expect(api.infos.keys).to include(nil)
|
104
|
+
end
|
105
|
+
end
|
106
|
+
end
|
107
|
+
|
108
|
+
context '.describe' do
|
109
|
+
subject(:output){ api.describe }
|
110
|
+
|
111
|
+
context 'using the spec_app definitions' do
|
112
|
+
subject(:version_output){ output["1.0"][:info] }
|
113
|
+
it 'saves the data into the correct version hash' do
|
114
|
+
expect(api.infos.keys).to include(nil)
|
115
|
+
expect(api.infos.keys).to include("1.0")
|
116
|
+
end
|
117
|
+
|
118
|
+
it 'outputs data for 1.0 info' do
|
119
|
+
expect(output.keys).to include("1.0")
|
120
|
+
expect(output["1.0"]).to include(:info)
|
121
|
+
end
|
122
|
+
it 'describes 1.0 Api info properly' do
|
123
|
+
info = output["1.0"][:info]
|
124
|
+
expect(info).to include(:schema_version, :name, :title, :description, :base_path)
|
125
|
+
expect(info[:schema_version]).to eq("1.0")
|
126
|
+
expect(info[:name]).to eq("Spec App")
|
127
|
+
expect(info[:title]).to eq("A simple App to do some simple integration testing")
|
128
|
+
expect(info[:description]).to eq("A simple 1.0 App")
|
129
|
+
expect(info[:base_path]).to eq("/")
|
130
|
+
end
|
131
|
+
end
|
132
|
+
|
133
|
+
context 'using a non-singleton object' do
|
134
|
+
let(:api){ non_singleton_api }
|
135
|
+
|
136
|
+
before do
|
137
|
+
api.info("9.0", &info_block)
|
138
|
+
api.info do
|
139
|
+
description "Global Description"
|
140
|
+
end
|
141
|
+
end
|
142
|
+
its(:keys){ should include("9.0") }
|
143
|
+
|
144
|
+
context 'for v9.0 info' do
|
145
|
+
subject(:v9_info){ output["9.0"][:info] }
|
146
|
+
|
147
|
+
it 'has the info it was set in the call' do
|
148
|
+
expect(v9_info).to include({schema_version: "1.0"})
|
149
|
+
expect(v9_info).to include({name: "Name"})
|
150
|
+
expect(v9_info).to include({title: "Title"})
|
151
|
+
end
|
152
|
+
it 'inherited the description from the nil(global) one' do
|
153
|
+
expect(v9_info).to include({description: "Global Description"})
|
154
|
+
end
|
155
|
+
|
156
|
+
end
|
157
|
+
end
|
158
|
+
end
|
159
|
+
end
|
@@ -0,0 +1,36 @@
|
|
1
|
+
require 'spec_helper'
|
2
|
+
|
3
|
+
describe Praxis::ApiGeneralInfo do
|
4
|
+
|
5
|
+
subject(:info){ Praxis::ApiGeneralInfo.new }
|
6
|
+
|
7
|
+
let(:info_block) do
|
8
|
+
Proc.new do
|
9
|
+
name "Name"
|
10
|
+
title "Title"
|
11
|
+
description "Description"
|
12
|
+
base_path "/base"
|
13
|
+
end
|
14
|
+
end
|
15
|
+
|
16
|
+
context 'DSLs' do
|
17
|
+
it 'accepts the appropriate DSLs' do
|
18
|
+
expect{
|
19
|
+
info.instance_exec &info_block
|
20
|
+
}.to_not raise_error
|
21
|
+
end
|
22
|
+
|
23
|
+
end
|
24
|
+
|
25
|
+
context '.describe' do
|
26
|
+
subject(:output){ info.describe }
|
27
|
+
it 'works' do
|
28
|
+
info.instance_exec &info_block
|
29
|
+
expect(output).to eq(
|
30
|
+
{:schema_version=>"1.0", :name=>"Name", :title=>"Title",
|
31
|
+
:description=>"Description", :base_path=>"/base"
|
32
|
+
})
|
33
|
+
end
|
34
|
+
|
35
|
+
end
|
36
|
+
end
|
@@ -2,7 +2,7 @@ require 'spec_helper'
|
|
2
2
|
|
3
3
|
describe Praxis::Bootloader do
|
4
4
|
let(:application) do
|
5
|
-
instance_double("Praxis::Application", config: "config", root: "root", plugins: {})
|
5
|
+
instance_double("Praxis::Application", config: "config", root: "root", plugins: {}, file_layout: {} )
|
6
6
|
end
|
7
7
|
|
8
8
|
subject(:bootloader) {Praxis::Bootloader.new(application)}
|
@@ -17,6 +17,15 @@ describe Praxis::Bootloader do
|
|
17
17
|
its(:root) {should be(application.root)}
|
18
18
|
end
|
19
19
|
|
20
|
+
context ".run" do
|
21
|
+
it "should call setup and run for all the stages" do
|
22
|
+
bootloader.stages.each do |s|
|
23
|
+
expect(s).to receive(:setup!).once
|
24
|
+
expect(s).to receive(:run).once
|
25
|
+
end
|
26
|
+
bootloader.run
|
27
|
+
end
|
28
|
+
end
|
20
29
|
context ".delete_stage" do
|
21
30
|
it "delete valid stage" do
|
22
31
|
bootloader.delete_stage(:app)
|
@@ -2,49 +2,49 @@ require "spec_helper"
|
|
2
2
|
|
3
3
|
describe Praxis::MediaTypeCollection do
|
4
4
|
|
5
|
-
|
6
|
-
|
5
|
+
subject!(:media_type_collection) do
|
6
|
+
silence_warnings do
|
7
|
+
klass = Class.new(Praxis::MediaTypeCollection) do
|
8
|
+
member_type VolumeSnapshot
|
9
|
+
|
10
|
+
attributes do
|
11
|
+
attribute :name, String, regexp: /snapshots-(\w+)/
|
12
|
+
attribute :size, Integer
|
13
|
+
attribute :href, String
|
14
|
+
end
|
15
|
+
|
16
|
+
view :link do
|
17
|
+
attribute :name
|
18
|
+
attribute :size
|
19
|
+
attribute :href
|
20
|
+
end
|
7
21
|
|
8
|
-
|
22
|
+
member_view :default, using: :default
|
23
|
+
end
|
9
24
|
|
10
|
-
|
11
|
-
|
12
|
-
member_type Volume
|
25
|
+
klass.finalize!
|
26
|
+
klass
|
13
27
|
end
|
14
28
|
end
|
15
29
|
|
16
30
|
context '.member_type' do
|
17
|
-
its(:member_type){ should be(
|
31
|
+
its(:member_type){ should be(VolumeSnapshot) }
|
18
32
|
its(:member_attribute){ should be_kind_of(Attributor::Attribute) }
|
19
|
-
its('member_attribute.type'){ should be(
|
33
|
+
its('member_attribute.type'){ should be(VolumeSnapshot) }
|
20
34
|
end
|
21
35
|
|
22
36
|
context '.load' do
|
23
|
-
let(:volume_data) do
|
24
|
-
{
|
25
|
-
id: 1,
|
26
|
-
name: 'bob',
|
27
|
-
snapshots: snapshots_data
|
28
|
-
}
|
29
|
-
end
|
30
|
-
|
31
|
-
let(:snapshots_data) {
|
32
|
-
nil
|
33
|
-
}
|
34
|
-
|
35
37
|
context 'with a hash' do
|
36
38
|
let(:snapshots_data) { {name: 'snapshots', href: '/bob/snapshots' } }
|
39
|
+
subject(:snapshots) { media_type_collection.load(snapshots_data) }
|
37
40
|
|
38
|
-
|
39
|
-
|
41
|
+
its(:name) { should eq(snapshots_data[:name]) }
|
42
|
+
its(:href) { should eq(snapshots_data[:href]) }
|
40
43
|
|
41
|
-
|
42
|
-
|
43
|
-
|
44
|
-
|
45
|
-
expect(snapshots.to_a).to eq([])
|
46
|
-
end
|
47
|
-
end
|
44
|
+
it 'has no members set' do
|
45
|
+
expect(snapshots.to_a).to eq([])
|
46
|
+
end
|
47
|
+
end
|
48
48
|
|
49
49
|
|
50
50
|
context 'loading an array' do
|
@@ -52,9 +52,8 @@ describe Praxis::MediaTypeCollection do
|
|
52
52
|
[{id: 1, name: 'snapshot-1'},
|
53
53
|
{id: 2, name: 'snapshot-2'}]
|
54
54
|
end
|
55
|
-
|
56
|
-
let(:
|
57
|
-
let(:snapshots) { volume.snapshots }
|
55
|
+
|
56
|
+
let(:snapshots) { media_type_collection.load(snapshots_data) }
|
58
57
|
subject(:members) { snapshots.to_a }
|
59
58
|
|
60
59
|
it 'sets the collection members' do
|
@@ -75,10 +74,10 @@ describe Praxis::MediaTypeCollection do
|
|
75
74
|
end
|
76
75
|
end
|
77
76
|
|
78
|
-
|
79
77
|
context '#render' do
|
80
|
-
|
81
78
|
context 'for standard views' do
|
79
|
+
let(:snapshots_data) { {name: 'snapshots', href: '/bob/snapshots' } }
|
80
|
+
let(:snapshots) { media_type_collection.load(snapshots_data) }
|
82
81
|
subject(:output) { snapshots.render(:link) }
|
83
82
|
|
84
83
|
its([:name]) { should eq(snapshots.name)}
|
@@ -86,8 +85,15 @@ describe Praxis::MediaTypeCollection do
|
|
86
85
|
its([:href]) { should eq(snapshots.href)}
|
87
86
|
end
|
88
87
|
|
89
|
-
context 'for
|
90
|
-
|
88
|
+
context 'for members' do
|
89
|
+
let(:snapshots_data) do
|
90
|
+
[{id: 1, name: 'snapshot-1'},
|
91
|
+
{id: 2, name: 'snapshot-2'}]
|
92
|
+
end
|
93
|
+
|
94
|
+
let(:snapshots) { media_type_collection.load(snapshots_data) }
|
95
|
+
|
96
|
+
subject(:output) { media_type_collection.dump(snapshots, view: :default) }
|
91
97
|
|
92
98
|
it { should eq(snapshots.collect(&:render)) }
|
93
99
|
end
|
@@ -96,23 +102,12 @@ describe Praxis::MediaTypeCollection do
|
|
96
102
|
end
|
97
103
|
|
98
104
|
context '#validate' do
|
99
|
-
|
100
|
-
{
|
101
|
-
id: 1,
|
102
|
-
name: 'bob',
|
103
|
-
snapshots: snapshots_data
|
104
|
-
}
|
105
|
-
end
|
106
|
-
|
107
|
-
let(:snapshots_data) {
|
108
|
-
nil
|
109
|
-
}
|
105
|
+
|
110
106
|
|
111
107
|
context 'with a hash' do
|
112
108
|
let(:snapshots_data) { {name: 'snapshots-1', href: '/bob/snapshots' } }
|
109
|
+
subject(:snapshots) { media_type_collection.load(snapshots_data) }
|
113
110
|
|
114
|
-
let(:volume) { Volume.load(volume_data) }
|
115
|
-
subject(:snapshots) { volume.snapshots }
|
116
111
|
|
117
112
|
it 'validates' do
|
118
113
|
expect(snapshots.validate).to be_empty
|
@@ -133,10 +128,8 @@ describe Praxis::MediaTypeCollection do
|
|
133
128
|
{id: 2, name: 'snapshot-2'}]
|
134
129
|
end
|
135
130
|
|
136
|
-
|
137
|
-
|
138
|
-
subject(:members) { snapshots.to_a }
|
139
|
-
|
131
|
+
subject(:snapshots) { media_type_collection.load(snapshots_data) }
|
132
|
+
|
140
133
|
it 'validates' do
|
141
134
|
expect(snapshots.validate).to be_empty
|
142
135
|
end
|