praxis 0.13.0 → 0.14.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/.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
|