raml_ruby 0.1.1
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +7 -0
- data/.gitignore +19 -0
- data/.travis.yml +6 -0
- data/Gemfile +4 -0
- data/LICENSE.txt +22 -0
- data/README.md +71 -0
- data/Rakefile +1 -0
- data/fixtures/include_1.raml +7 -0
- data/fixtures/schemas/canonicalSchemas.raml +3 -0
- data/fixtures/schemas/filesystem/file.json +1 -0
- data/fixtures/schemas/filesystem/files.json +1 -0
- data/fixtures/schemas/filesystem/fileupdate.json +1 -0
- data/fixtures/schemas/filesystem/relative/test.json +1 -0
- data/lib/raml.rb +104 -0
- data/lib/raml/exceptions.rb +27 -0
- data/lib/raml/mixin/bodies.rb +32 -0
- data/lib/raml/mixin/documentable.rb +32 -0
- data/lib/raml/mixin/global.rb +20 -0
- data/lib/raml/mixin/headers.rb +22 -0
- data/lib/raml/mixin/merge.rb +24 -0
- data/lib/raml/mixin/parent.rb +54 -0
- data/lib/raml/mixin/validation.rb +49 -0
- data/lib/raml/node.rb +219 -0
- data/lib/raml/node/abstract_method.rb +61 -0
- data/lib/raml/node/abstract_resource.rb +165 -0
- data/lib/raml/node/abstract_resource_circular.rb +5 -0
- data/lib/raml/node/body.rb +94 -0
- data/lib/raml/node/documentation.rb +28 -0
- data/lib/raml/node/header.rb +4 -0
- data/lib/raml/node/method.rb +106 -0
- data/lib/raml/node/parameter/abstract_parameter.rb +251 -0
- data/lib/raml/node/parameter/base_uri_parameter.rb +6 -0
- data/lib/raml/node/parameter/form_parameter.rb +6 -0
- data/lib/raml/node/parameter/query_parameter.rb +6 -0
- data/lib/raml/node/parameter/uri_parameter.rb +7 -0
- data/lib/raml/node/parametized_reference.rb +15 -0
- data/lib/raml/node/reference.rb +4 -0
- data/lib/raml/node/resource.rb +26 -0
- data/lib/raml/node/resource_type.rb +20 -0
- data/lib/raml/node/resource_type_reference.rb +5 -0
- data/lib/raml/node/response.rb +32 -0
- data/lib/raml/node/root.rb +246 -0
- data/lib/raml/node/schema.rb +41 -0
- data/lib/raml/node/schema_reference.rb +5 -0
- data/lib/raml/node/template.rb +55 -0
- data/lib/raml/node/trait.rb +18 -0
- data/lib/raml/node/trait_reference.rb +5 -0
- data/lib/raml/parser.rb +57 -0
- data/lib/raml/parser/include.rb +25 -0
- data/lib/raml/patch/hash.rb +6 -0
- data/lib/raml/patch/module.rb +12 -0
- data/lib/raml/version.rb +3 -0
- data/raml_ruby.gemspec +35 -0
- data/raml_spec_reqs.md +276 -0
- data/templates/abstract_parameter.slim +68 -0
- data/templates/body.slim +15 -0
- data/templates/collapse.slim +10 -0
- data/templates/documentation.slim +2 -0
- data/templates/method.slim +38 -0
- data/templates/resource.slim +33 -0
- data/templates/response.slim +13 -0
- data/templates/root.slim +39 -0
- data/templates/style.sass +119 -0
- data/test/apis/box-api.raml +4224 -0
- data/test/apis/instagram-api.raml +3378 -0
- data/test/apis/stripe-api.raml +12227 -0
- data/test/apis/twilio-rest-api.raml +6618 -0
- data/test/apis/twitter-rest-api.raml +34284 -0
- data/test/raml/body_spec.rb +268 -0
- data/test/raml/documentation_spec.rb +49 -0
- data/test/raml/header_spec.rb +17 -0
- data/test/raml/include_spec.rb +40 -0
- data/test/raml/method_spec.rb +701 -0
- data/test/raml/parameter/abstract_parameter_spec.rb +564 -0
- data/test/raml/parameter/form_parameter_spec.rb +17 -0
- data/test/raml/parameter/query_parameter_spec.rb +33 -0
- data/test/raml/parameter/uri_parameter_spec.rb +44 -0
- data/test/raml/parser_spec.rb +53 -0
- data/test/raml/raml_spec.rb +32 -0
- data/test/raml/resource_spec.rb +440 -0
- data/test/raml/resource_type_spec.rb +51 -0
- data/test/raml/response_spec.rb +251 -0
- data/test/raml/root_spec.rb +655 -0
- data/test/raml/schema_spec.rb +110 -0
- data/test/raml/spec_helper.rb +11 -0
- data/test/raml/template_spec.rb +98 -0
- data/test/raml/trait_spec.rb +31 -0
- metadata +337 -0
@@ -0,0 +1,51 @@
|
|
1
|
+
# encoding: UTF-8
|
2
|
+
require_relative 'spec_helper'
|
3
|
+
|
4
|
+
describe Raml::ResourceType do
|
5
|
+
let(:name) { 'auditableResource' }
|
6
|
+
let(:data) {
|
7
|
+
YAML.load(%q(
|
8
|
+
post:
|
9
|
+
body:
|
10
|
+
application/x-www-form-urlencoded:
|
11
|
+
formParameters:
|
12
|
+
createAuthority:
|
13
|
+
description: |
|
14
|
+
If the resource has a post method defined, expect a createAuthority
|
15
|
+
property in its body
|
16
|
+
delete:
|
17
|
+
body:
|
18
|
+
multipart/form-data:
|
19
|
+
formParameters:
|
20
|
+
deleteAuthority:
|
21
|
+
description: |
|
22
|
+
If the resource has a delete method defined, expect a deleteAuthority
|
23
|
+
property in its body
|
24
|
+
))
|
25
|
+
}
|
26
|
+
let(:root) { Raml::Root.new 'title' => 'x', 'baseUri' => 'http://foo.com' }
|
27
|
+
|
28
|
+
subject { Raml::ResourceType.new(name, data, root) }
|
29
|
+
|
30
|
+
describe '#new' do
|
31
|
+
context 'with valid arguments' do
|
32
|
+
it { expect { subject }.to_not raise_error }
|
33
|
+
it { should be_a Raml::ResourceType }
|
34
|
+
end
|
35
|
+
end
|
36
|
+
|
37
|
+
describe '#instantiate' do
|
38
|
+
context 'when the usage property is given' do
|
39
|
+
before { data['usage'] = 'Some text' }
|
40
|
+
it 'stores the usage property' do
|
41
|
+
subject.instantiate({}).usage.should eq data['usage']
|
42
|
+
end
|
43
|
+
end
|
44
|
+
context 'with invalid arguments' do
|
45
|
+
context 'when the resource type has nested resources' do
|
46
|
+
before { data['/foo'] = {} }
|
47
|
+
it { expect { subject.instantiate({}) }.to raise_error Raml::UnknownProperty, /\/foo/ }
|
48
|
+
end
|
49
|
+
end
|
50
|
+
end
|
51
|
+
end
|
@@ -0,0 +1,251 @@
|
|
1
|
+
require_relative 'spec_helper'
|
2
|
+
|
3
|
+
describe Raml::Response do
|
4
|
+
let (:name) { 200 }
|
5
|
+
let (:response_data) {
|
6
|
+
YAML.load(%q(
|
7
|
+
displayName: Success
|
8
|
+
description: Successful response
|
9
|
+
body:
|
10
|
+
text/xml:
|
11
|
+
schema: some xml schema
|
12
|
+
example: |
|
13
|
+
<api-request>
|
14
|
+
<input>s3://zencodertesting/test.mov</input>
|
15
|
+
</api-request>
|
16
|
+
application/json:
|
17
|
+
schema: some json schema
|
18
|
+
example: |
|
19
|
+
{
|
20
|
+
"input": "s3://zencodertesting/test.mov"
|
21
|
+
}
|
22
|
+
headers:
|
23
|
+
Zencoder-Api-Key:
|
24
|
+
displayName: ZEncoder API Key
|
25
|
+
x-Zencoder-job-metadata-{*}:
|
26
|
+
displayName: Job Metadata
|
27
|
+
))
|
28
|
+
}
|
29
|
+
let(:root) { Raml::Root.new 'title' => 'x', 'baseUri' => 'http://foo.com' }
|
30
|
+
|
31
|
+
subject { Raml::Response.new name, response_data, root }
|
32
|
+
|
33
|
+
describe '#new' do
|
34
|
+
it "inits with name" do
|
35
|
+
expect( subject.name ).to eq(name)
|
36
|
+
end
|
37
|
+
|
38
|
+
it "inits with headers" do
|
39
|
+
expect( subject.headers.size ).to eq(2)
|
40
|
+
end
|
41
|
+
|
42
|
+
context 'when a body property is given' do
|
43
|
+
context 'when the body property is well formed' do
|
44
|
+
it { expect { subject }.to_not raise_error }
|
45
|
+
it 'stores all as Raml::Body instances' do
|
46
|
+
expect( subject.bodies.values ).to all( be_a Raml::Body )
|
47
|
+
expect( subject.bodies.size ).to eq(2)
|
48
|
+
subject.bodies.keys.should contain_exactly('text/xml', 'application/json')
|
49
|
+
end
|
50
|
+
end
|
51
|
+
context 'when the body property is not a map' do
|
52
|
+
before { response_data['body'] = 1 }
|
53
|
+
it { expect { subject }.to raise_error Raml::InvalidProperty, /body/ }
|
54
|
+
end
|
55
|
+
context 'when the body property is a map with non-string keys' do
|
56
|
+
before { response_data['body'] = { 1 => {}} }
|
57
|
+
it { expect { subject }.to raise_error Raml::InvalidProperty, /body/ }
|
58
|
+
end
|
59
|
+
context 'when the body property is a map with non-map values' do
|
60
|
+
before { response_data['body'] = { 'text/xml' => 1 } }
|
61
|
+
it { expect { subject }.to raise_error Raml::InvalidProperty, /body/ }
|
62
|
+
end
|
63
|
+
end
|
64
|
+
|
65
|
+
context 'when description property is not given' do
|
66
|
+
before { response_data.delete 'description' }
|
67
|
+
it { expect { subject }.to_not raise_error }
|
68
|
+
end
|
69
|
+
context 'when description property is given' do
|
70
|
+
context 'when the description property is not a string' do
|
71
|
+
before { response_data['description'] = 1 }
|
72
|
+
it { expect { subject }.to raise_error Raml::InvalidProperty, /description/ }
|
73
|
+
end
|
74
|
+
context 'when the description property is a string' do
|
75
|
+
before { response_data['description'] = 'My Description' }
|
76
|
+
it { expect { subject }.to_not raise_error }
|
77
|
+
it 'should store the value' do
|
78
|
+
subject.description.should eq response_data['description']
|
79
|
+
end
|
80
|
+
it 'uses the description in the documentation' do
|
81
|
+
subject.document.should include response_data['description']
|
82
|
+
end
|
83
|
+
end
|
84
|
+
end
|
85
|
+
|
86
|
+
context 'when the headers parameter is given' do
|
87
|
+
context 'when the headers property is well formed' do
|
88
|
+
it { expect { subject }.to_not raise_error }
|
89
|
+
it 'stores all as Raml::Header instances' do
|
90
|
+
expect( subject.headers.values ).to all( be_a Raml::Header )
|
91
|
+
expect( subject.headers.keys ).to contain_exactly('Zencoder-Api-Key','x-Zencoder-job-metadata-{*}')
|
92
|
+
end
|
93
|
+
end
|
94
|
+
context 'when the headers property is not a map' do
|
95
|
+
before { response_data['headers'] = 1 }
|
96
|
+
it { expect { subject }.to raise_error Raml::InvalidProperty, /headers/ }
|
97
|
+
end
|
98
|
+
context 'when the headers property is not a map with non-string keys' do
|
99
|
+
before { response_data['headers'] = { 1 => {}} }
|
100
|
+
it { expect { subject }.to raise_error Raml::InvalidProperty, /headers/ }
|
101
|
+
end
|
102
|
+
context 'when the headers property is not a map with non-string keys' do
|
103
|
+
before { response_data['headers'] = { '1' => 'x'} }
|
104
|
+
it { expect { subject }.to raise_error Raml::InvalidProperty, /headers/ }
|
105
|
+
end
|
106
|
+
end
|
107
|
+
end
|
108
|
+
|
109
|
+
describe '#merge' do
|
110
|
+
context 'when response and mixin have different status codes' do
|
111
|
+
let(:response) { Raml::Response.new 200, {}, root }
|
112
|
+
let(:mixin ) { Raml::Response.new 403, {}, root }
|
113
|
+
it { expect { response.merge mixin }.to raise_error Raml::MergeError }
|
114
|
+
end
|
115
|
+
|
116
|
+
context 'when response and mixin have different the same codes' do
|
117
|
+
let(:response) { Raml::Response.new 200, response_data, root }
|
118
|
+
let(:mixin ) { Raml::Response.new 200, mixin_data , root }
|
119
|
+
context 'when the mixin has a property set' do
|
120
|
+
context 'when the response does not have that property set' do
|
121
|
+
let(:response_data) { {} }
|
122
|
+
context 'displayName property' do
|
123
|
+
let(:mixin_data) { {displayName: 'mixin displayName'} }
|
124
|
+
it 'sets the property in the response' do
|
125
|
+
response.merge(mixin).display_name.should eq mixin.display_name
|
126
|
+
end
|
127
|
+
end
|
128
|
+
context 'description property' do
|
129
|
+
let(:mixin_data) { {description: 'mixin description'} }
|
130
|
+
it 'sets the property in the response' do
|
131
|
+
response.merge(mixin).description.should eq mixin.description
|
132
|
+
end
|
133
|
+
end
|
134
|
+
context 'headers properties' do
|
135
|
+
let(:mixin_data) { {
|
136
|
+
'headers' => {
|
137
|
+
'header1' => {'description' => 'foo'},
|
138
|
+
'header2' => {'description' => 'bar'}
|
139
|
+
}
|
140
|
+
} }
|
141
|
+
it 'adds the headers to the response' do
|
142
|
+
response.merge(mixin).headers.keys.should contain_exactly('header1', 'header2')
|
143
|
+
end
|
144
|
+
end
|
145
|
+
context 'body property' do
|
146
|
+
let(:mixin_data) { {
|
147
|
+
'body' => {
|
148
|
+
'text/mime1' => {'schema' => 'foo'},
|
149
|
+
'text/mime2' => {'schema' => 'bar'}
|
150
|
+
}
|
151
|
+
} }
|
152
|
+
it 'adds the body media types to the response' do
|
153
|
+
response.merge(mixin).bodies.keys.should contain_exactly('text/mime1', 'text/mime2')
|
154
|
+
end
|
155
|
+
end
|
156
|
+
end
|
157
|
+
context 'when the response has that property set' do
|
158
|
+
context 'displayName property' do
|
159
|
+
let(:response_data) { {displayName: 'response displayName'} }
|
160
|
+
let(:mixin_data ) { {displayName: 'mixin displayName' } }
|
161
|
+
it 'overrites the response property' do
|
162
|
+
response.merge(mixin).display_name.should eq 'mixin displayName'
|
163
|
+
end
|
164
|
+
end
|
165
|
+
context 'description property' do
|
166
|
+
let(:response_data) { {description: 'response description'} }
|
167
|
+
let(:mixin_data ) { {description: 'mixin description' } }
|
168
|
+
it 'overrites the response property' do
|
169
|
+
response.merge(mixin).description.should eq 'mixin description'
|
170
|
+
end
|
171
|
+
end
|
172
|
+
context 'headers properties' do
|
173
|
+
let(:response_data) { {
|
174
|
+
'headers' => {
|
175
|
+
'header1' => {'description' => 'foo'},
|
176
|
+
'header2' => {'description' => 'bar'}
|
177
|
+
}
|
178
|
+
} }
|
179
|
+
context 'when the mixin headers are different from the response headers' do
|
180
|
+
let(:mixin_data) { {
|
181
|
+
'headers' => {
|
182
|
+
'header3' => {'description' => 'foo2'},
|
183
|
+
'header4' => {'description' => 'bar2'}
|
184
|
+
}
|
185
|
+
} }
|
186
|
+
it 'adds the headers to the response' do
|
187
|
+
response.merge(mixin).headers.keys.should contain_exactly('header1', 'header2', 'header3', 'header4')
|
188
|
+
end
|
189
|
+
end
|
190
|
+
context 'when the mixin headers overlap the the response headers' do
|
191
|
+
let(:mixin_data) { {
|
192
|
+
'headers' => {
|
193
|
+
'header2' => {'description' => 'bar3', 'displayName' => 'Header 3'},
|
194
|
+
'header3' => {'description' => 'foo2'},
|
195
|
+
'header4' => {'description' => 'bar2'}
|
196
|
+
}
|
197
|
+
} }
|
198
|
+
it 'merges the matching headers and adds the non-matching headers to the response' do
|
199
|
+
response.merge(mixin).headers.keys.should contain_exactly('header1', 'header2', 'header3', 'header4')
|
200
|
+
response.headers['header2'].display_name.should eq mixin.headers['header2'].display_name
|
201
|
+
response.headers['header2'].description.should eq mixin.headers['header2'].description
|
202
|
+
end
|
203
|
+
end
|
204
|
+
end
|
205
|
+
context 'body property' do
|
206
|
+
let(:response_data) { {
|
207
|
+
'body' => {
|
208
|
+
'text/mime1' => {'schema' => 'foo'},
|
209
|
+
'text/mime2' => {'schema' => 'bar'}
|
210
|
+
}
|
211
|
+
} }
|
212
|
+
context 'when the mixin query parameters are different from the response headers' do
|
213
|
+
let(:mixin_data) { {
|
214
|
+
'body' => {
|
215
|
+
'text/mime3' => {'schema' => 'foo2'},
|
216
|
+
'text/mime4' => {'schema' => 'bar2'}
|
217
|
+
}
|
218
|
+
} }
|
219
|
+
it 'adds the body media types to the response' do
|
220
|
+
response.merge(mixin).bodies.keys.should contain_exactly('text/mime1', 'text/mime2', 'text/mime3', 'text/mime4')
|
221
|
+
end
|
222
|
+
end
|
223
|
+
context 'when the mixin query parameters overlap the the response query parameters' do
|
224
|
+
let(:mixin_data) { {
|
225
|
+
'body' => {
|
226
|
+
'text/mime2' => {'example' => 'Example 2'},
|
227
|
+
'text/mime3' => {'schema' => 'foo2'},
|
228
|
+
'text/mime4' => {'schema' => 'bar2'}
|
229
|
+
}
|
230
|
+
} }
|
231
|
+
it 'merges the matching media types and adds the non-matching media types to the response' do
|
232
|
+
response.merge(mixin).bodies.keys.should contain_exactly('text/mime1', 'text/mime2', 'text/mime3', 'text/mime4')
|
233
|
+
response.bodies['text/mime2'].example.should eq mixin.bodies['text/mime2'].example
|
234
|
+
end
|
235
|
+
end
|
236
|
+
end
|
237
|
+
end
|
238
|
+
end
|
239
|
+
end
|
240
|
+
end
|
241
|
+
|
242
|
+
describe '#document' do
|
243
|
+
it 'returns a String' do
|
244
|
+
subject.document.should be_a String
|
245
|
+
end
|
246
|
+
it 'should render the template' do
|
247
|
+
mock(Slim::Template).new(/templates\/response.slim\z/, is_a(Hash)).mock!.render(is_a(Raml::Node)) { '' }
|
248
|
+
subject.document
|
249
|
+
end
|
250
|
+
end
|
251
|
+
end
|
@@ -0,0 +1,655 @@
|
|
1
|
+
require_relative 'spec_helper'
|
2
|
+
|
3
|
+
describe Raml::Root do
|
4
|
+
let(:data) {
|
5
|
+
YAML.load(
|
6
|
+
%q(
|
7
|
+
#%RAML 0.8
|
8
|
+
title: ZEncoder API
|
9
|
+
baseUri: https://app.zencoder.com/api
|
10
|
+
version: v2.0
|
11
|
+
documentation:
|
12
|
+
- title: Home
|
13
|
+
content: Doc content
|
14
|
+
)
|
15
|
+
)
|
16
|
+
}
|
17
|
+
|
18
|
+
subject { Raml::Root.new data }
|
19
|
+
|
20
|
+
describe '#new' do
|
21
|
+
it "should init root" do
|
22
|
+
expect { subject }.to_not raise_error
|
23
|
+
end
|
24
|
+
|
25
|
+
context 'when the title property is missing' do
|
26
|
+
let(:data) { { 'baseUri' => 'x' } }
|
27
|
+
it { expect{ subject }.to raise_error Raml::RequiredPropertyMissing, /title/ }
|
28
|
+
end
|
29
|
+
context 'when the title property is not a string' do
|
30
|
+
let(:data) { { 'title' => 1, 'baseUri' => 'x' } }
|
31
|
+
it { expect{ subject }.to raise_error Raml::InvalidProperty, /title/ }
|
32
|
+
end
|
33
|
+
|
34
|
+
context 'when the baseUri property is missing' do
|
35
|
+
let(:data) { { 'title' => 'x' } }
|
36
|
+
it { expect{ subject }.to raise_error Raml::RequiredPropertyMissing, /baseUri/ }
|
37
|
+
end
|
38
|
+
context 'when the baseUri property is not a string' do
|
39
|
+
let(:data) { { 'title' => 'x', 'baseUri' => 1 } }
|
40
|
+
it { expect{ subject }.to raise_error Raml::InvalidProperty, /baseUri/ }
|
41
|
+
end
|
42
|
+
context 'when the baseUri property is a valid URL' do
|
43
|
+
it 'should not raise an error' do
|
44
|
+
[
|
45
|
+
'https://api.github.com',
|
46
|
+
'https://app.zencoder.com/api'
|
47
|
+
].each do |template|
|
48
|
+
expect { Raml::Root.new({ 'title' => 'x', 'baseUri' => template }) }.to_not raise_error
|
49
|
+
end
|
50
|
+
end
|
51
|
+
end
|
52
|
+
context 'when the baseUri property is an invalid URL template' do
|
53
|
+
let(:data) { { 'title' => 'x', 'baseUri' => '://app.zencoder.com/api' } }
|
54
|
+
it { expect{ subject }.to raise_error Raml::InvalidProperty, /baseUri/ }
|
55
|
+
end
|
56
|
+
context 'when the baseUri property is a URL template' do
|
57
|
+
it 'should not raise an error' do
|
58
|
+
[
|
59
|
+
'https://{destinationBucket}.s3.amazonaws.com',
|
60
|
+
'https://na1.salesforce.com/services/data/{version}/chatter',
|
61
|
+
'https://api.stormpath.com/{version}',
|
62
|
+
'https://{companyName}.freshbooks.com/api/{version}/xml-in',
|
63
|
+
'https://{communityDomain}.force.com/{communityPath}',
|
64
|
+
'https://app.zencoder.com/api/{version}',
|
65
|
+
'https://{apiDomain}.dropbox.com/{version}'
|
66
|
+
].each do |template|
|
67
|
+
expect { Raml::Root.new({ 'title' => 'x', 'baseUri' => template, 'version' => 'v1' }) }.to_not raise_error
|
68
|
+
end
|
69
|
+
end
|
70
|
+
end
|
71
|
+
context 'when the baseUri property is an invalid URL template' do
|
72
|
+
let(:data) { { 'title' => 'x', 'baseUri' => 'https://api.stormpath.com/}version}' } }
|
73
|
+
it { expect{ subject }.to raise_error Raml::InvalidProperty, /baseUri/ }
|
74
|
+
end
|
75
|
+
|
76
|
+
context 'when the protocols property is missing' do
|
77
|
+
let(:data) { { 'title' => 'x', 'baseUri' => 'http://foo.com' } }
|
78
|
+
it { expect{ subject }.to_not raise_error }
|
79
|
+
end
|
80
|
+
context 'when the protocol property is not an array' do
|
81
|
+
let(:data) { { 'title' => 'x', 'baseUri' => 'http://foo.com', 'protocols' => 'HTTP' } }
|
82
|
+
it { expect{ subject }.to raise_error Raml::InvalidProperty, /protocols/ }
|
83
|
+
end
|
84
|
+
context 'when the protocol property is an array but not all elements are strings' do
|
85
|
+
let(:data) { { 'title' => 'x', 'baseUri' => 'http://foo.com', 'protocols' => ['HTTP', 1] } }
|
86
|
+
it { expect{ subject }.to raise_error Raml::InvalidProperty, /protocols/ }
|
87
|
+
end
|
88
|
+
context 'when the protocol property is an array of strings with invalid values' do
|
89
|
+
let(:data) { { 'title' => 'x', 'baseUri' => 'http://foo.com', 'protocols' => ['HTTP', 'foo'] } }
|
90
|
+
it { expect{ subject }.to raise_error Raml::InvalidProperty, /protocols/ }
|
91
|
+
end
|
92
|
+
[
|
93
|
+
[ 'HTTP' ],
|
94
|
+
[ 'HTTPS' ],
|
95
|
+
[ 'HTTP', 'HTTPS' ]
|
96
|
+
].each do |protocols|
|
97
|
+
context "when the protocol property is #{protocols}" do
|
98
|
+
let(:data) { { 'title' => 'x', 'baseUri' => 'http://foo.com', 'protocols' => protocols } }
|
99
|
+
it { expect{ subject }.to_not raise_error }
|
100
|
+
it 'stores the values' do
|
101
|
+
subject.protocols.should eq protocols
|
102
|
+
end
|
103
|
+
end
|
104
|
+
end
|
105
|
+
context 'when the protocol property is an array of valid values in lowercase' do
|
106
|
+
let(:data) { { 'title' => 'x', 'baseUri' => 'http://foo.com', 'protocols' => ['http', 'https'] } }
|
107
|
+
it 'uppercases them' do
|
108
|
+
subject.protocols.should eq [ 'HTTP', 'HTTPS' ]
|
109
|
+
end
|
110
|
+
end
|
111
|
+
|
112
|
+
[
|
113
|
+
'application/json',
|
114
|
+
'application/x-yaml',
|
115
|
+
'application/foo+json',
|
116
|
+
'application/foo+xml'
|
117
|
+
].each do |type|
|
118
|
+
context 'when the mediaType property is a well formed media type' do
|
119
|
+
let(:data) { { 'title' => 'x', 'baseUri' => 'http://foo.com', 'media_type' => type} }
|
120
|
+
it { expect{ subject }.to_not raise_error }
|
121
|
+
end
|
122
|
+
end
|
123
|
+
context 'when the mediaType property is not a string' do
|
124
|
+
let(:data) { { 'title' => 'x', 'baseUri' => 'http://foo.com', 'media_type' => 1 } }
|
125
|
+
it { expect{ subject }.to raise_error Raml::InvalidProperty, /mediaType/ }
|
126
|
+
end
|
127
|
+
context 'when the mediaType property is a malformed media type' do
|
128
|
+
let(:data) { { 'title' => 'x', 'baseUri' => 'http://foo.com', 'media_type' => 'foo' } }
|
129
|
+
it { expect{ subject }.to raise_error Raml::InvalidProperty, /mediaType/ }
|
130
|
+
end
|
131
|
+
|
132
|
+
context 'when the schemas property is an array of maps with string keys and values' do
|
133
|
+
let(:data) { { 'title' => 'x', 'baseUri' => 'http://foo.com', 'schemas' => [{'foo'=>'bar'}] } }
|
134
|
+
it { expect{ subject }.to_not raise_error }
|
135
|
+
end
|
136
|
+
context 'when the schemas property is an array with a single map' do
|
137
|
+
let(:data) { { 'title' => 'x', 'baseUri' => 'http://foo.com', 'schemas' => [{'foo'=>'bar'}] } }
|
138
|
+
it 'returns that map in the #schema method' do
|
139
|
+
subject.schemas.should be_a Hash
|
140
|
+
subject.schemas.keys.should contain_exactly('foo')
|
141
|
+
subject.schemas['foo'].should be_a Raml::Schema
|
142
|
+
subject.schemas['foo'].value.should == 'bar'
|
143
|
+
end
|
144
|
+
end
|
145
|
+
context 'when the schemas property is an array with multiple maps' do
|
146
|
+
let(:data) { { 'title' => 'x', 'baseUri' => 'http://foo.com', 'schemas' => [{'foo'=>'bar', 'roo'=>'rar'},{'boo'=>'bar'}] } }
|
147
|
+
it 'returns the merged maps in the #schema method' do
|
148
|
+
subject.schemas.should be_a Hash
|
149
|
+
subject.schemas.keys.should contain_exactly('foo', 'roo', 'boo')
|
150
|
+
subject.schemas.values.should all(be_a Raml::Schema)
|
151
|
+
subject.schemas.values.map(&:value).should contain_exactly('bar', 'rar', 'bar')
|
152
|
+
end
|
153
|
+
end
|
154
|
+
context 'when the schemas property is not an array' do
|
155
|
+
let(:data) { { 'title' => 'x', 'baseUri' => 'http://foo.com', 'schemas' => 'x' } }
|
156
|
+
it { expect{ subject }.to raise_error Raml::InvalidProperty, /schemas/ }
|
157
|
+
end
|
158
|
+
context 'when the schemas property is an empty array' do
|
159
|
+
let(:data) { { 'title' => 'x', 'baseUri' => 'http://foo.com', 'schemas' => [] } }
|
160
|
+
it { expect{ subject }.to_not raise_error }
|
161
|
+
end
|
162
|
+
context 'when the schemas property is an array with some non-map elements' do
|
163
|
+
let(:data) { { 'title' => 'x', 'baseUri' => 'http://foo.com', 'schemas' => [{'foo'=>'bar'}, 1] } }
|
164
|
+
it { expect{ subject }.to raise_error Raml::InvalidProperty, /schemas/ }
|
165
|
+
end
|
166
|
+
context 'when the schemas property is an array of maps with non-string keys' do
|
167
|
+
let(:data) { { 'title' => 'x', 'baseUri' => 'http://foo.com', 'schemas' => [{1=>'bar'}] } }
|
168
|
+
it { expect{ subject }.to raise_error Raml::InvalidProperty, /schemas/ }
|
169
|
+
end
|
170
|
+
context 'when the schemas property is an array of maps with non-string values' do
|
171
|
+
let(:data) { { 'title' => 'x', 'baseUri' => 'http://foo.com', 'schemas' => [{'foo'=>1}] } }
|
172
|
+
it { expect{ subject }.to raise_error Raml::InvalidProperty, /schemas/ }
|
173
|
+
end
|
174
|
+
context 'when the schemas property has duplicate schema names' do
|
175
|
+
let(:data) { { 'title' => 'x', 'baseUri' => 'http://foo.com', 'schemas' => [{'foo'=>'bar'},{'foo'=>'boo'}] } }
|
176
|
+
it { expect{ subject }.to raise_error Raml::InvalidProperty, /schemas/ }
|
177
|
+
end
|
178
|
+
|
179
|
+
context 'when the baseUriParameter property is well formed' do
|
180
|
+
let(:data) {
|
181
|
+
YAML.load(
|
182
|
+
%q(
|
183
|
+
title: Salesforce Chatter Communities REST API
|
184
|
+
version: v28.0
|
185
|
+
baseUri: https://{communityDomain}.force.com/{communityPath}
|
186
|
+
baseUriParameters:
|
187
|
+
communityDomain:
|
188
|
+
displayName: Community Domain
|
189
|
+
type: string
|
190
|
+
communityPath:
|
191
|
+
displayName: Community Path
|
192
|
+
type: string
|
193
|
+
pattern: ^[a-zA-Z0-9][-a-zA-Z0-9]*$
|
194
|
+
minLength: 1
|
195
|
+
)
|
196
|
+
)
|
197
|
+
}
|
198
|
+
it { expect { subject }.to_not raise_error }
|
199
|
+
it 'stores all as Raml::Parameter::BaseUriParameter instances' do
|
200
|
+
expect( subject.base_uri_parameters.values ).to all( be_a Raml::Parameter::BaseUriParameter )
|
201
|
+
end
|
202
|
+
context 'when the baseUri template does not include a version parameter' do
|
203
|
+
context 'and a version property is not provided' do
|
204
|
+
before { data.delete 'version' }
|
205
|
+
it { expect { subject }.to_not raise_error }
|
206
|
+
end
|
207
|
+
end
|
208
|
+
context 'when the baseUri template includes a version parameter' do
|
209
|
+
context 'and a version property is not provided' do
|
210
|
+
before do
|
211
|
+
data.delete 'version'
|
212
|
+
data['baseUri'] = 'https://{communityDomain}.force.com/{version}/{communityPath}'
|
213
|
+
end
|
214
|
+
it { expect { subject }.to raise_error Raml::RequiredPropertyMissing, /version/ }
|
215
|
+
end
|
216
|
+
end
|
217
|
+
end
|
218
|
+
context 'when the baseUriParameter property is not a map' do
|
219
|
+
let(:data) { { 'title' => 'x', 'baseUri' => 'http://foo.com', 'baseUriParameters' => 1 } }
|
220
|
+
it { expect { subject }.to raise_error Raml::InvalidProperty, /baseUriParameters/ }
|
221
|
+
end
|
222
|
+
context 'when the baseUriParameter property is not a map with non-string keys' do
|
223
|
+
let(:data) { { 'title' => 'x', 'baseUri' => 'http://foo.com', 'baseUriParameters' => { 1 => {}} } }
|
224
|
+
it { expect { subject }.to raise_error Raml::InvalidProperty, /baseUriParameters/ }
|
225
|
+
end
|
226
|
+
context 'when the baseUriParameter property is not a map with non-string keys' do
|
227
|
+
let(:data) { { 'title' => 'x', 'baseUri' => 'http://foo.com', 'baseUriParameters' => { '1' => 'x'} } }
|
228
|
+
it { expect { subject }.to raise_error Raml::InvalidProperty, /baseUriParameters/ }
|
229
|
+
end
|
230
|
+
context 'when the baseUriParameter property has a key for the reserved "version" parameter' do
|
231
|
+
let(:data) { { 'title' => 'x', 'baseUri' => 'http://foo.com', 'baseUriParameters' => { 'version' => {}} } }
|
232
|
+
it { expect { subject }.to raise_error Raml::InvalidProperty, /baseUriParameters/ }
|
233
|
+
end
|
234
|
+
|
235
|
+
context 'when the documentation parameter is given and valid' do
|
236
|
+
let(:data) {
|
237
|
+
YAML.load(
|
238
|
+
%q(
|
239
|
+
#%RAML 0.8
|
240
|
+
title: ZEncoder API
|
241
|
+
baseUri: https://app.zencoder.com/api
|
242
|
+
documentation:
|
243
|
+
- title: Home
|
244
|
+
content: |
|
245
|
+
Welcome to the _Zencoder API_ Documentation.
|
246
|
+
)
|
247
|
+
)
|
248
|
+
}
|
249
|
+
it { expect { subject }.to_not raise_error }
|
250
|
+
it 'stores all as Raml::Documentation instances' do
|
251
|
+
expect( subject.documents ).to all( be_a Raml::Documentation )
|
252
|
+
end
|
253
|
+
end
|
254
|
+
context 'when the documentation property is not a array' do
|
255
|
+
let(:data) { { 'title' => 'x', 'baseUri' => 'http://foo.com', 'documentation' => 1 } }
|
256
|
+
it { expect { subject }.to raise_error Raml::InvalidProperty, /documentation/ }
|
257
|
+
end
|
258
|
+
context 'when the documentation property is an empty array' do
|
259
|
+
let(:data) { { 'title' => 'x', 'baseUri' => 'http://foo.com', 'documentation' => [] } }
|
260
|
+
it { expect { subject }.to raise_error Raml::InvalidProperty, /documentation/ }
|
261
|
+
end
|
262
|
+
context 'when an entry in the documentation property is missing the title' do
|
263
|
+
let(:data) { { 'title' => 'x', 'baseUri' => 'http://foo.com', 'documentation' => [{'content' => 'x'}] } }
|
264
|
+
it { expect { subject }.to raise_error Raml::InvalidProperty, /document/ }
|
265
|
+
end
|
266
|
+
context 'when an entry in the documentation property has an empty title' do
|
267
|
+
let(:data) { { 'title' => 'x', 'baseUri' => 'http://foo.com', 'documentation' => [{'title' => '', 'content' => 'x'}] } }
|
268
|
+
it { expect { subject }.to raise_error Raml::InvalidProperty, /document/ }
|
269
|
+
end
|
270
|
+
context 'when an entry in the documentation property is missing the content' do
|
271
|
+
let(:data) { { 'title' => 'x', 'baseUri' => 'http://foo.com', 'documentation' => [{'title' => 'x'}] } }
|
272
|
+
it { expect { subject }.to raise_error Raml::InvalidProperty, /document/ }
|
273
|
+
end
|
274
|
+
context 'when an entry in the documentation property has an empty content' do
|
275
|
+
let(:data) { { 'title' => 'x', 'baseUri' => 'http://foo.com', 'documentation' => [{'title' => 'x', 'content' => ''}] } }
|
276
|
+
it { expect { subject }.to raise_error Raml::InvalidProperty, /document/ }
|
277
|
+
end
|
278
|
+
|
279
|
+
context 'when top-level resources are defined' do
|
280
|
+
let(:data) {
|
281
|
+
YAML.load(
|
282
|
+
%q(
|
283
|
+
#%RAML 0.8
|
284
|
+
title: GitHub API
|
285
|
+
version: v3
|
286
|
+
baseUri: https://api.github.com
|
287
|
+
/user:
|
288
|
+
displayName: Authenticated User
|
289
|
+
/users:
|
290
|
+
displayName: Users
|
291
|
+
)
|
292
|
+
)
|
293
|
+
}
|
294
|
+
it { expect { subject }.to_not raise_error }
|
295
|
+
it 'stores all as Raml::Resource instances' do
|
296
|
+
expect( subject.resources.values ).to all( be_a Raml::Resource )
|
297
|
+
expect( subject.resources.keys ).to contain_exactly('/user','/users')
|
298
|
+
end
|
299
|
+
end
|
300
|
+
|
301
|
+
context 'when the resourceTypes property is defined' do
|
302
|
+
context 'when the resourceTypes property is an array of maps with string keys and and map values' do
|
303
|
+
let(:data) { { 'title' => 'x', 'baseUri' => 'http://foo.com', 'resourceTypes' => [{'foo'=>{},'boo'=>{}}] } }
|
304
|
+
it { expect{ subject }.to_not raise_error }
|
305
|
+
end
|
306
|
+
context 'when the resourceTypes property is an array with a single map' do
|
307
|
+
let(:data) { { 'title' => 'x', 'baseUri' => 'http://foo.com', 'resourceTypes' => [{'foo'=>{}}] } }
|
308
|
+
it 'returns the ResourceType in the #resource_types method' do
|
309
|
+
subject.resource_types.should be_a Hash
|
310
|
+
subject.resource_types.keys.should contain_exactly('foo')
|
311
|
+
subject.resource_types['foo'].should be_a Raml::ResourceType
|
312
|
+
subject.resource_types['foo'].name.should == 'foo'
|
313
|
+
end
|
314
|
+
context 'when the resourceTypes property is an array with a single map with multiple types' do
|
315
|
+
let(:data) { { 'title' => 'x', 'baseUri' => 'http://foo.com', 'resourceTypes' => [{'foo'=>{},'boo'=>{}}] } }
|
316
|
+
it 'returns the ResourceTypes in the #resource_types method' do
|
317
|
+
subject.resource_types.should be_a Hash
|
318
|
+
subject.resource_types.keys.should contain_exactly('foo', 'boo')
|
319
|
+
subject.resource_types.values.should all(be_a Raml::ResourceType)
|
320
|
+
subject.resource_types.values.map(&:name).should contain_exactly('foo', 'boo')
|
321
|
+
end
|
322
|
+
end
|
323
|
+
end
|
324
|
+
context 'when the resourceTypes property is an array with multiple maps' do
|
325
|
+
let(:data) { { 'title' => 'x', 'baseUri' => 'http://foo.com', 'resourceTypes' => [{'foo'=>{}},{'boo'=>{}}] } }
|
326
|
+
it 'returns the merged maps in the #resource_types method' do
|
327
|
+
subject.resource_types.should be_a Hash
|
328
|
+
subject.resource_types.keys.should contain_exactly('foo', 'boo')
|
329
|
+
subject.resource_types.values.should all(be_a Raml::ResourceType)
|
330
|
+
subject.resource_types.values.map(&:name).should contain_exactly('foo', 'boo')
|
331
|
+
end
|
332
|
+
end
|
333
|
+
context 'when the resourceTypes property is not an array' do
|
334
|
+
let(:data) { { 'title' => 'x', 'baseUri' => 'http://foo.com', 'resourceTypes' => 'x' } }
|
335
|
+
it { expect{ subject }.to raise_error Raml::InvalidProperty, /resourceTypes/ }
|
336
|
+
end
|
337
|
+
context 'when the resourceTypes property is an empty array' do
|
338
|
+
let(:data) { { 'title' => 'x', 'baseUri' => 'http://foo.com', 'resourceTypes' => [] } }
|
339
|
+
it { expect{ subject }.to_not raise_error }
|
340
|
+
end
|
341
|
+
context 'when the resourceTypes property is an array with some non-map elements' do
|
342
|
+
let(:data) { { 'title' => 'x', 'baseUri' => 'http://foo.com', 'resourceTypes' => [{'foo'=>{}}, 1] } }
|
343
|
+
it { expect{ subject }.to raise_error Raml::InvalidProperty, /resourceTypes/ }
|
344
|
+
end
|
345
|
+
context 'when the resourceTypes property is an array of maps with non-string keys' do
|
346
|
+
let(:data) { { 'title' => 'x', 'baseUri' => 'http://foo.com', 'resourceTypes' => [{1=>{}}] } }
|
347
|
+
it { expect{ subject }.to raise_error Raml::InvalidProperty, /resourceTypes/ }
|
348
|
+
end
|
349
|
+
context 'when the resourceTypes property is an array of maps with non-map values' do
|
350
|
+
let(:data) { { 'title' => 'x', 'baseUri' => 'http://foo.com', 'resourceTypes' => [{'foo'=>1}] } }
|
351
|
+
it { expect{ subject }.to raise_error Raml::InvalidProperty, /resourceTypes/ }
|
352
|
+
end
|
353
|
+
context 'when the resourceTypes property has duplicate type names' do
|
354
|
+
let(:data) { { 'title' => 'x', 'baseUri' => 'http://foo.com', 'resourceTypes' => [{'foo'=>{}},{'foo'=>{}}] } }
|
355
|
+
it { expect{ subject }.to raise_error Raml::InvalidProperty, /resourceTypes/ }
|
356
|
+
end
|
357
|
+
end
|
358
|
+
|
359
|
+
context 'when the traits property is defined' do
|
360
|
+
context 'when the traits property is an array of maps with string keys and and map values' do
|
361
|
+
let(:data) { { 'title' => 'x', 'baseUri' => 'http://foo.com', 'traits' => [{'foo'=>{},'boo'=>{}}] } }
|
362
|
+
it { expect{ subject }.to_not raise_error }
|
363
|
+
end
|
364
|
+
context 'when the traits property is an array with a single map' do
|
365
|
+
let(:data) { { 'title' => 'x', 'baseUri' => 'http://foo.com', 'traits' => [{'foo'=>{}}] } }
|
366
|
+
it 'returns the Trait in the #traits method' do
|
367
|
+
subject.traits.should be_a Hash
|
368
|
+
subject.traits.keys.should contain_exactly('foo')
|
369
|
+
subject.traits['foo'].should be_a Raml::Trait
|
370
|
+
subject.traits['foo'].name.should == 'foo'
|
371
|
+
end
|
372
|
+
context 'when the traits property is an array with a single map with multiple traits' do
|
373
|
+
let(:data) { { 'title' => 'x', 'baseUri' => 'http://foo.com', 'traits' => [{'foo'=>{},'boo'=>{}}] } }
|
374
|
+
it 'returns the Traits in the #traits method' do
|
375
|
+
subject.traits.should be_a Hash
|
376
|
+
subject.traits.keys.should contain_exactly('foo', 'boo')
|
377
|
+
subject.traits.values.should all(be_a Raml::Trait)
|
378
|
+
subject.traits.values.map(&:name).should contain_exactly('foo', 'boo')
|
379
|
+
end
|
380
|
+
end
|
381
|
+
end
|
382
|
+
context 'when the traits property is an array with multiple maps' do
|
383
|
+
let(:data) { { 'title' => 'x', 'baseUri' => 'http://foo.com', 'traits' => [{'foo'=>{}},{'boo'=>{}}] } }
|
384
|
+
it 'returns the merged maps in the #traits method' do
|
385
|
+
subject.traits.should be_a Hash
|
386
|
+
subject.traits.keys.should contain_exactly('foo', 'boo')
|
387
|
+
subject.traits.values.should all(be_a Raml::Trait)
|
388
|
+
subject.traits.values.map(&:name).should contain_exactly('foo', 'boo')
|
389
|
+
end
|
390
|
+
end
|
391
|
+
context 'when the traits property is not an array' do
|
392
|
+
let(:data) { { 'title' => 'x', 'baseUri' => 'http://foo.com', 'traits' => 'x' } }
|
393
|
+
it { expect{ subject }.to raise_error Raml::InvalidProperty, /traits/ }
|
394
|
+
end
|
395
|
+
context 'when the traits property is an empty array' do
|
396
|
+
let(:data) { { 'title' => 'x', 'baseUri' => 'http://foo.com', 'traits' => [] } }
|
397
|
+
it { expect{ subject }.to_not raise_error }
|
398
|
+
end
|
399
|
+
context 'when the traits property is an array with some non-map elements' do
|
400
|
+
let(:data) { { 'title' => 'x', 'baseUri' => 'http://foo.com', 'traits' => [{'foo'=>{}}, 1] } }
|
401
|
+
it { expect{ subject }.to raise_error Raml::InvalidProperty, /traits/ }
|
402
|
+
end
|
403
|
+
context 'when the traits property is an array of maps with non-string keys' do
|
404
|
+
let(:data) { { 'title' => 'x', 'baseUri' => 'http://foo.com', 'traits' => [{1=>{}}] } }
|
405
|
+
it { expect{ subject }.to raise_error Raml::InvalidProperty, /traits/ }
|
406
|
+
end
|
407
|
+
context 'when the traits property is an array of maps with non-map values' do
|
408
|
+
let(:data) { { 'title' => 'x', 'baseUri' => 'http://foo.com', 'traits' => [{'foo'=>1}] } }
|
409
|
+
it { expect{ subject }.to raise_error Raml::InvalidProperty, /traits/ }
|
410
|
+
end
|
411
|
+
context 'when the traits property has duplicate trait names' do
|
412
|
+
let(:data) { { 'title' => 'x', 'baseUri' => 'http://foo.com', 'traits' => [{'foo'=>{}},{'foo'=>{}}] } }
|
413
|
+
it { expect{ subject }.to raise_error Raml::InvalidProperty, /traits/ }
|
414
|
+
end
|
415
|
+
end
|
416
|
+
end
|
417
|
+
|
418
|
+
describe '#expand' do
|
419
|
+
context 'when the syntax trees contains SchemaReferences' do
|
420
|
+
let(:data) {
|
421
|
+
YAML.load(
|
422
|
+
%q(
|
423
|
+
#%RAML 0.8
|
424
|
+
title: ZEncoder API
|
425
|
+
baseUri: https://app.zencoder.com/api
|
426
|
+
schemas:
|
427
|
+
- XMLJob: |
|
428
|
+
<xs:schema attributeFormDefault="unqualified"
|
429
|
+
elementFormDefault="qualified"
|
430
|
+
xmlns:xs="http://www.w3.org/2001/XMLSchema">
|
431
|
+
<xs:element name="api-request">
|
432
|
+
<xs:complexType>
|
433
|
+
<xs:sequence>
|
434
|
+
<xs:element type="xs:string" name="input"/>
|
435
|
+
</xs:sequence>
|
436
|
+
</xs:complexType>
|
437
|
+
</xs:element>
|
438
|
+
</xs:schema>
|
439
|
+
JSONJob: |
|
440
|
+
{
|
441
|
+
"$schema": "http://json-schema.org/draft-03/schema#",
|
442
|
+
"properties": {
|
443
|
+
"input": {
|
444
|
+
"required": false,
|
445
|
+
"type": "string"
|
446
|
+
}
|
447
|
+
},
|
448
|
+
"required": false,
|
449
|
+
"type": "object"
|
450
|
+
}
|
451
|
+
/jobs:
|
452
|
+
displayName: Jobs
|
453
|
+
post:
|
454
|
+
description: Create a Job
|
455
|
+
body:
|
456
|
+
text/xml:
|
457
|
+
schema: XMLJob
|
458
|
+
application/json:
|
459
|
+
schema: JSONJob
|
460
|
+
responses:
|
461
|
+
200:
|
462
|
+
body:
|
463
|
+
text/xml:
|
464
|
+
schema: XMLJob
|
465
|
+
application/json:
|
466
|
+
schema: JSONJob
|
467
|
+
)
|
468
|
+
)
|
469
|
+
}
|
470
|
+
it 'replaces them with Schemas' do
|
471
|
+
subject.resources['/jobs'].methods['post'].bodies['text/xml' ].schema.should be_a Raml::SchemaReference
|
472
|
+
subject.resources['/jobs'].methods['post'].bodies['application/json'].schema.should be_a Raml::SchemaReference
|
473
|
+
subject.resources['/jobs'].methods['post'].responses[200].bodies['text/xml' ].schema.should be_a Raml::SchemaReference
|
474
|
+
subject.resources['/jobs'].methods['post'].responses[200].bodies['application/json'].schema.should be_a Raml::SchemaReference
|
475
|
+
subject.expand
|
476
|
+
subject.resources['/jobs'].methods['post'].bodies['text/xml' ].schema.should be_a Raml::Schema
|
477
|
+
subject.resources['/jobs'].methods['post'].bodies['application/json'].schema.should be_a Raml::Schema
|
478
|
+
subject.resources['/jobs'].methods['post'].responses[200].bodies['text/xml' ].schema.should be_a Raml::Schema
|
479
|
+
subject.resources['/jobs'].methods['post'].responses[200].bodies['application/json'].schema.should be_a Raml::Schema
|
480
|
+
end
|
481
|
+
end
|
482
|
+
|
483
|
+
context 'when the syntax tree contains Resources' do
|
484
|
+
let(:data) {
|
485
|
+
YAML.load(
|
486
|
+
%q(
|
487
|
+
#%RAML 0.8
|
488
|
+
title: Example API
|
489
|
+
version: v1
|
490
|
+
baseUri: https://app.zencoder.com/api
|
491
|
+
resourceTypes:
|
492
|
+
- collection:
|
493
|
+
description: The collection.
|
494
|
+
- member:
|
495
|
+
description: The member.
|
496
|
+
/jobs:
|
497
|
+
type: collection
|
498
|
+
/status:
|
499
|
+
type: member
|
500
|
+
/users:
|
501
|
+
type: collection
|
502
|
+
)
|
503
|
+
)
|
504
|
+
}
|
505
|
+
it 'applies traits to resources' do
|
506
|
+
subject.resources.size.should eq 2
|
507
|
+
subject.resources.values.each { |resource| mock(resource).apply_traits {} }
|
508
|
+
subject.expand
|
509
|
+
end
|
510
|
+
it 'applies resource types to the resources' do
|
511
|
+
subject.resources.size.should eq 2
|
512
|
+
subject.resources.values.each { |resource| mock(resource).apply_resource_type {} }
|
513
|
+
subject.expand
|
514
|
+
end
|
515
|
+
end
|
516
|
+
|
517
|
+
context 'when the syntax tree contains resource types and traits' do
|
518
|
+
let(:data) {
|
519
|
+
YAML.load(
|
520
|
+
%q(
|
521
|
+
#%RAML 0.8
|
522
|
+
title: Example API
|
523
|
+
version: v1
|
524
|
+
baseUri: https://app.zencoder.com/api
|
525
|
+
traits:
|
526
|
+
- trait1:
|
527
|
+
queryParameters:
|
528
|
+
param1:
|
529
|
+
description: <<methodName>> trait1 param1
|
530
|
+
param2:
|
531
|
+
description: trait1 param2
|
532
|
+
trait2:
|
533
|
+
queryParameters:
|
534
|
+
param2:
|
535
|
+
description: trait2 param2
|
536
|
+
param3:
|
537
|
+
description: trait2 param3 <<arg1 | !pluralize>>
|
538
|
+
trait3:
|
539
|
+
queryParameters:
|
540
|
+
param3:
|
541
|
+
description: trait3 param3
|
542
|
+
param4:
|
543
|
+
description: trait3 param4
|
544
|
+
trait4:
|
545
|
+
responses:
|
546
|
+
200?:
|
547
|
+
body:
|
548
|
+
application/xml:
|
549
|
+
schema: schema3
|
550
|
+
403?:
|
551
|
+
body:
|
552
|
+
application/xml:
|
553
|
+
schema: schema3
|
554
|
+
trait5:
|
555
|
+
responses:
|
556
|
+
403:
|
557
|
+
body:
|
558
|
+
plain/text?:
|
559
|
+
schema: schema4
|
560
|
+
resourceTypes:
|
561
|
+
- resource_type1:
|
562
|
+
description: resource_type1 description
|
563
|
+
get?:
|
564
|
+
body:
|
565
|
+
application/json:
|
566
|
+
schema: schema1
|
567
|
+
post?:
|
568
|
+
body:
|
569
|
+
application/json:
|
570
|
+
schema: schema2
|
571
|
+
resource_type2:
|
572
|
+
description: resource_type2 description
|
573
|
+
displayName: resource_type2 displayName
|
574
|
+
get:
|
575
|
+
is: [ trait1 ]
|
576
|
+
description: resource_type2 get description
|
577
|
+
/resource1:
|
578
|
+
type: resource_type1
|
579
|
+
description: resource1 description
|
580
|
+
get:
|
581
|
+
description: resource1 get
|
582
|
+
/resource1_1:
|
583
|
+
type: resource_type2
|
584
|
+
description: resource1_1 description
|
585
|
+
/resource2:
|
586
|
+
type: resource_type2
|
587
|
+
is: [ trait3, trait2: { arg1: dog }, trait4, trait5 ]
|
588
|
+
get:
|
589
|
+
responses:
|
590
|
+
403:
|
591
|
+
body:
|
592
|
+
application/json:
|
593
|
+
schema: schema4
|
594
|
+
)
|
595
|
+
)
|
596
|
+
}
|
597
|
+
|
598
|
+
it 'applies them correctly' do
|
599
|
+
subject.expand
|
600
|
+
subject.resources['/resource1'].description.should eq 'resource1 description'
|
601
|
+
subject.resources['/resource1'].methods.keys.should include 'get'
|
602
|
+
subject.resources['/resource1'].methods['get'].bodies['application/json'].schema.value.should eq 'schema1'
|
603
|
+
subject.resources['/resource1'].methods.keys.should_not include 'post'
|
604
|
+
subject.resources['/resource1'].resources['/resource1_1'].description.should eq 'resource1_1 description'
|
605
|
+
subject.resources['/resource1'].resources['/resource1_1'].display_name.should eq 'resource_type2 displayName'
|
606
|
+
subject.resources['/resource1'].resources['/resource1_1'].methods['get'].description.should eq 'resource_type2 get description'
|
607
|
+
subject.resources['/resource2'].description.should eq 'resource_type2 description'
|
608
|
+
subject.resources['/resource2'].display_name.should eq 'resource_type2 displayName'
|
609
|
+
subject.resources['/resource2'].methods['get'].description.should eq 'resource_type2 get description'
|
610
|
+
subject.resources['/resource2'].methods['get'].query_parameters['param1'].description.should eq 'get trait1 param1'
|
611
|
+
subject.resources['/resource2'].methods['get'].query_parameters['param2'].description.should eq 'trait1 param2'
|
612
|
+
subject.resources['/resource2'].methods['get'].query_parameters['param3'].description.should eq 'trait2 param3 dogs'
|
613
|
+
subject.resources['/resource2'].methods['get'].query_parameters['param4'].description.should eq 'trait3 param4'
|
614
|
+
subject.resources['/resource2'].methods['get'].responses.keys.should_not include '200'
|
615
|
+
subject.resources['/resource2'].methods['get'].responses.keys.should_not include 200
|
616
|
+
subject.resources['/resource2'].methods['get'].responses[403].bodies['application/xml'].schema.value.should eq 'schema3'
|
617
|
+
subject.resources['/resource2'].methods['get'].responses[403].bodies.keys.should_not include 'plain/text'
|
618
|
+
end
|
619
|
+
end
|
620
|
+
|
621
|
+
context 'when parsing large specs' do
|
622
|
+
subject { Raml::Parser.parse( File.open("test/apis/#{api_file}").read ) }
|
623
|
+
context 'when parsing the Twitter API' do
|
624
|
+
let(:api_file) { 'twitter-rest-api.raml' }
|
625
|
+
it { expect { subject.expand }.to_not raise_error }
|
626
|
+
end
|
627
|
+
context 'when parsing the Stripe API' do
|
628
|
+
let(:api_file) { 'stripe-api.raml' }
|
629
|
+
it { expect { subject.expand }.to_not raise_error }
|
630
|
+
end
|
631
|
+
context 'when parsing the Twilio API' do
|
632
|
+
let(:api_file) { 'twilio-rest-api.raml' }
|
633
|
+
it { expect { subject.expand }.to_not raise_error }
|
634
|
+
end
|
635
|
+
context 'when parsing the Box API' do
|
636
|
+
let(:api_file) { 'box-api.raml' }
|
637
|
+
it { expect { subject.expand }.to_not raise_error }
|
638
|
+
end
|
639
|
+
context 'when parsing the Instagram API' do
|
640
|
+
let(:api_file) { 'instagram-api.raml' }
|
641
|
+
it { expect { subject.expand }.to_not raise_error }
|
642
|
+
end
|
643
|
+
end
|
644
|
+
end
|
645
|
+
|
646
|
+
describe '#document' do
|
647
|
+
it 'returns a String' do
|
648
|
+
subject.document.should be_a String
|
649
|
+
end
|
650
|
+
it 'should render the template' do
|
651
|
+
mock(Slim::Template).new(/templates\/root.slim\z/, is_a(Hash)).mock!.render(is_a(Raml::Node)) { '' }
|
652
|
+
subject.document
|
653
|
+
end
|
654
|
+
end
|
655
|
+
end
|