raml_ruby 0.1.1
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- checksums.yaml +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
|