raml_ruby 0.1.1

Sign up to get free protection for your applications and to get access to all the features.
Files changed (88) hide show
  1. checksums.yaml +7 -0
  2. data/.gitignore +19 -0
  3. data/.travis.yml +6 -0
  4. data/Gemfile +4 -0
  5. data/LICENSE.txt +22 -0
  6. data/README.md +71 -0
  7. data/Rakefile +1 -0
  8. data/fixtures/include_1.raml +7 -0
  9. data/fixtures/schemas/canonicalSchemas.raml +3 -0
  10. data/fixtures/schemas/filesystem/file.json +1 -0
  11. data/fixtures/schemas/filesystem/files.json +1 -0
  12. data/fixtures/schemas/filesystem/fileupdate.json +1 -0
  13. data/fixtures/schemas/filesystem/relative/test.json +1 -0
  14. data/lib/raml.rb +104 -0
  15. data/lib/raml/exceptions.rb +27 -0
  16. data/lib/raml/mixin/bodies.rb +32 -0
  17. data/lib/raml/mixin/documentable.rb +32 -0
  18. data/lib/raml/mixin/global.rb +20 -0
  19. data/lib/raml/mixin/headers.rb +22 -0
  20. data/lib/raml/mixin/merge.rb +24 -0
  21. data/lib/raml/mixin/parent.rb +54 -0
  22. data/lib/raml/mixin/validation.rb +49 -0
  23. data/lib/raml/node.rb +219 -0
  24. data/lib/raml/node/abstract_method.rb +61 -0
  25. data/lib/raml/node/abstract_resource.rb +165 -0
  26. data/lib/raml/node/abstract_resource_circular.rb +5 -0
  27. data/lib/raml/node/body.rb +94 -0
  28. data/lib/raml/node/documentation.rb +28 -0
  29. data/lib/raml/node/header.rb +4 -0
  30. data/lib/raml/node/method.rb +106 -0
  31. data/lib/raml/node/parameter/abstract_parameter.rb +251 -0
  32. data/lib/raml/node/parameter/base_uri_parameter.rb +6 -0
  33. data/lib/raml/node/parameter/form_parameter.rb +6 -0
  34. data/lib/raml/node/parameter/query_parameter.rb +6 -0
  35. data/lib/raml/node/parameter/uri_parameter.rb +7 -0
  36. data/lib/raml/node/parametized_reference.rb +15 -0
  37. data/lib/raml/node/reference.rb +4 -0
  38. data/lib/raml/node/resource.rb +26 -0
  39. data/lib/raml/node/resource_type.rb +20 -0
  40. data/lib/raml/node/resource_type_reference.rb +5 -0
  41. data/lib/raml/node/response.rb +32 -0
  42. data/lib/raml/node/root.rb +246 -0
  43. data/lib/raml/node/schema.rb +41 -0
  44. data/lib/raml/node/schema_reference.rb +5 -0
  45. data/lib/raml/node/template.rb +55 -0
  46. data/lib/raml/node/trait.rb +18 -0
  47. data/lib/raml/node/trait_reference.rb +5 -0
  48. data/lib/raml/parser.rb +57 -0
  49. data/lib/raml/parser/include.rb +25 -0
  50. data/lib/raml/patch/hash.rb +6 -0
  51. data/lib/raml/patch/module.rb +12 -0
  52. data/lib/raml/version.rb +3 -0
  53. data/raml_ruby.gemspec +35 -0
  54. data/raml_spec_reqs.md +276 -0
  55. data/templates/abstract_parameter.slim +68 -0
  56. data/templates/body.slim +15 -0
  57. data/templates/collapse.slim +10 -0
  58. data/templates/documentation.slim +2 -0
  59. data/templates/method.slim +38 -0
  60. data/templates/resource.slim +33 -0
  61. data/templates/response.slim +13 -0
  62. data/templates/root.slim +39 -0
  63. data/templates/style.sass +119 -0
  64. data/test/apis/box-api.raml +4224 -0
  65. data/test/apis/instagram-api.raml +3378 -0
  66. data/test/apis/stripe-api.raml +12227 -0
  67. data/test/apis/twilio-rest-api.raml +6618 -0
  68. data/test/apis/twitter-rest-api.raml +34284 -0
  69. data/test/raml/body_spec.rb +268 -0
  70. data/test/raml/documentation_spec.rb +49 -0
  71. data/test/raml/header_spec.rb +17 -0
  72. data/test/raml/include_spec.rb +40 -0
  73. data/test/raml/method_spec.rb +701 -0
  74. data/test/raml/parameter/abstract_parameter_spec.rb +564 -0
  75. data/test/raml/parameter/form_parameter_spec.rb +17 -0
  76. data/test/raml/parameter/query_parameter_spec.rb +33 -0
  77. data/test/raml/parameter/uri_parameter_spec.rb +44 -0
  78. data/test/raml/parser_spec.rb +53 -0
  79. data/test/raml/raml_spec.rb +32 -0
  80. data/test/raml/resource_spec.rb +440 -0
  81. data/test/raml/resource_type_spec.rb +51 -0
  82. data/test/raml/response_spec.rb +251 -0
  83. data/test/raml/root_spec.rb +655 -0
  84. data/test/raml/schema_spec.rb +110 -0
  85. data/test/raml/spec_helper.rb +11 -0
  86. data/test/raml/template_spec.rb +98 -0
  87. data/test/raml/trait_spec.rb +31 -0
  88. metadata +337 -0
@@ -0,0 +1,17 @@
1
+ require_relative '../spec_helper'
2
+
3
+ describe Raml::Parameter::FormParameter do
4
+ let(:root_data) { {'title' => 'x', 'baseUri' => 'http://foo.com'} }
5
+ let(:root) { Raml::Root.new root_data }
6
+ let(:name) { 'AWSAccessKeyId' }
7
+ let (:data) {
8
+ YAML.load(%q(
9
+ description: The AWS Access Key ID of the owner of the bucket who grants ...
10
+ type: string
11
+ ))
12
+ }
13
+
14
+ it "should instanciate Form parameter" do
15
+ Raml::Parameter::FormParameter.new(name, data, root)
16
+ end
17
+ end
@@ -0,0 +1,33 @@
1
+ require_relative '../spec_helper'
2
+
3
+ describe Raml::Parameter::QueryParameter do
4
+ let(:root_data) { {'title' => 'x', 'baseUri' => 'http://foo.com'} }
5
+ let(:root) { Raml::Root.new root_data }
6
+ let(:name) { 'page' }
7
+ let(:data) {
8
+ YAML.load(%q(
9
+ type: integer
10
+ ))
11
+ }
12
+
13
+ subject { Raml::Parameter::QueryParameter.new(name, data, root) }
14
+
15
+ it "should instanciate Query parameter" do
16
+ Raml::Parameter::QueryParameter.new(name, data, root)
17
+ end
18
+
19
+ describe "#document" do
20
+ let(:data) {
21
+ YAML.load(%q(
22
+ description: Specify the page that you want to retrieve
23
+ type: integer
24
+ required: true
25
+ example: 1
26
+ ))
27
+ }
28
+
29
+ it "prints out documentation" do
30
+ subject.document
31
+ end
32
+ end
33
+ end
@@ -0,0 +1,44 @@
1
+ require_relative '../spec_helper'
2
+
3
+ describe Raml::Parameter::UriParameter do
4
+ let(:root_data) { {'title' => 'x', 'baseUri' => 'http://foo.com'} }
5
+ let(:root) { Raml::Root.new root_data }
6
+ let(:name) { 'AccountSid' }
7
+ let(:data) {
8
+ YAML.load(%q(
9
+ description: |
10
+ An Account instance resource represents a single Twilio account.
11
+ type: string
12
+ ))
13
+ }
14
+
15
+ subject { Raml::Parameter::UriParameter.new(name, data, root) }
16
+
17
+ describe '#new' do
18
+ it "should instanciate Uri parameter" do
19
+ Raml::Parameter::UriParameter.new(name, data, root)
20
+ end
21
+
22
+ context 'when no required attribute is given' do
23
+ let(:data) { { } }
24
+ it 'defaults to true' do
25
+ subject.required.should == true
26
+ end
27
+ end
28
+ end
29
+
30
+ describe "#document" do
31
+ let(:data) {
32
+ YAML.load(%q(
33
+ description: Specify the page that you want to retrieve
34
+ type: integer
35
+ required: true
36
+ example: 1
37
+ ))
38
+ }
39
+
40
+ it "prints out documentation" do
41
+ subject.document
42
+ end
43
+ end
44
+ end
@@ -0,0 +1,53 @@
1
+ require_relative 'spec_helper'
2
+
3
+ describe Raml::Parser do
4
+ let (:data) {
5
+ %q(
6
+ #%RAML 0.8
7
+ baseUri: https://api.example.com
8
+ title: Filesystem API
9
+ version: 0.1
10
+ /files:
11
+ get:
12
+ responses:
13
+ 200:
14
+ body:
15
+ application/xml:
16
+ schema: Files
17
+ )
18
+ }
19
+
20
+ describe '.parse' do
21
+ it "should parse the data" do
22
+ root = Raml::Parser.parse(data)
23
+ root.should be_a Raml::Root
24
+ root.title.should eq 'Filesystem API'
25
+ end
26
+
27
+ context 'when the RAML file has !include directives' do
28
+ it 'inserts the data into the right location and parses RAML included files' do
29
+ file = File.new 'fixtures/include_1.raml'
30
+ root = Raml::Parser.parse file.read, 'fixtures'
31
+ root.schemas.should be_a Hash
32
+ root.schemas.size.should be 4
33
+ root.schemas.keys.should contain_exactly('FileUpdate', 'Files', 'Test', 'File')
34
+ root.schemas['FileUpdate'].value.should eq 'file_update_schema'
35
+ root.schemas['Files' ].value.should eq 'files_schema'
36
+ root.schemas['Test' ].value.should eq 'test_schema'
37
+ root.schemas['File' ].value.should eq 'file_schema'
38
+ end
39
+
40
+ context 'when the included file is not redable' do
41
+ it do
42
+ expect { Raml::Parser.parse('- !include does_not_exit') }.to raise_error Raml::CantIncludeFile
43
+ end
44
+ end
45
+
46
+ context 'when the !include directive is not given a file path' do
47
+ it do
48
+ expect { Raml::Parser.parse('- !include') }.to raise_error Raml::CantIncludeFile
49
+ end
50
+ end
51
+ end
52
+ end
53
+ end
@@ -0,0 +1,32 @@
1
+ require_relative 'spec_helper'
2
+
3
+ describe Raml do
4
+ describe '#parse_file' do
5
+ let(:rest_of_doc) { "title: Some API\nbaseUri: https://app.zencoder.com/api" }
6
+ before do
7
+ stub(File).new('file.raml').stub! do |stub|
8
+ stub.readline { comment }
9
+ stub.read { rest_of_doc }
10
+ end
11
+ end
12
+ context 'when given a valid RAML 0.8 file with a valid version comment' do
13
+ let(:comment ) { '#%RAML 0.8' }
14
+ it do
15
+ expect { Raml.parse_file 'file.raml' }.to_not raise_error
16
+ end
17
+ end
18
+ context 'when given a valid RAML 0.8 file with an invalid version comment' do
19
+ let(:comment ) { '#%RAML 0.7' }
20
+ it do
21
+ expect { Raml.parse_file 'file.raml' }.to raise_error Raml::UnsupportedRamlVersion
22
+ end
23
+ end
24
+ context 'when given a valid RAML 0.8 file with no version comment' do
25
+ let(:comment ) { 'title: Some API' }
26
+ let(:rest_of_doc) { 'version: v2' }
27
+ it do
28
+ expect { Raml.parse_file 'file.raml' }.to raise_error Raml::UnsupportedRamlVersion
29
+ end
30
+ end
31
+ end
32
+ end
@@ -0,0 +1,440 @@
1
+ # encoding: UTF-8
2
+ require_relative 'spec_helper'
3
+
4
+ describe Raml::Resource do
5
+ let(:name) { '/{id}' }
6
+ let(:data) {
7
+ YAML.load(%q(
8
+ uriParameters:
9
+ id:
10
+ type: integer
11
+ required: true
12
+ example: 277102
13
+ /processing_status:
14
+ get:
15
+ displayName: Processing status
16
+ description: Получить статус загрузки
17
+ responses:
18
+ 200:
19
+ body:
20
+ application/json:
21
+ example: |
22
+ {
23
+ "percent": 0,
24
+ "type": "download",
25
+ "status":"initial"
26
+ }
27
+ ))
28
+ }
29
+ let(:root_data) { {'title' => 'x', 'baseUri' => 'http://foo.com'} }
30
+ let(:root) { Raml::Root.new root_data }
31
+
32
+ subject { Raml::Resource.new(name, data, root) }
33
+
34
+ describe '#new' do
35
+ it "should instanciate Resource" do
36
+ subject
37
+ end
38
+
39
+ context 'when displayName is given' do
40
+ let(:data) { { 'displayName' => 'My Name', 'description' => 'foo' } }
41
+ it { expect { subject }.to_not raise_error }
42
+ it 'should store the value' do
43
+ subject.display_name.should eq data['displayName']
44
+ end
45
+ it 'uses the displayName in the documentation' do
46
+ subject.document.should include data['displayName']
47
+ end
48
+ end
49
+
50
+ context 'when description is not given' do
51
+ let(:data) { {} }
52
+ it { expect { subject }.to_not raise_error }
53
+ end
54
+ context 'when description is given' do
55
+ context 'when the description property is not a string' do
56
+ let(:data) { { 'description' => 1 } }
57
+ it { expect { subject }.to raise_error Raml::InvalidProperty, /description/ }
58
+ end
59
+ context 'when the description property is a string' do
60
+ let(:data) { { 'description' => 'My Description'} }
61
+ it { expect { subject }.to_not raise_error }
62
+ it 'should store the value' do
63
+ subject.description.should eq data['description']
64
+ end
65
+ it 'uses the description in the documentation' do
66
+ subject.document.should include data['description']
67
+ end
68
+ end
69
+ end
70
+
71
+ context 'when the uriParameters parameter is given with valid parameters' do
72
+ context 'when the uriParameters property is well formed' do
73
+ it { expect { subject }.to_not raise_error }
74
+ it 'stores all as Raml::Parameter::UriParameter instances' do
75
+ expect( subject.uri_parameters.values ).to all( be_a Raml::Parameter::UriParameter )
76
+ end
77
+ end
78
+ context 'when the uriParameters property is not a map' do
79
+ let(:data) { { 'uriParameters' => 1 } }
80
+ it { expect { subject }.to raise_error Raml::InvalidProperty, /uriParameters/ }
81
+ end
82
+ context 'when the uriParameters property is not a map with non-string keys' do
83
+ let(:data) { { 'uriParameters' => { 1 => {}} } }
84
+ it { expect { subject }.to raise_error Raml::InvalidProperty, /uriParameters/ }
85
+ end
86
+ context 'when the uriParameters property is not a map with non-string keys' do
87
+ let(:data) { { 'uriParameters' => { '1' => 'x'} } }
88
+ it { expect { subject }.to raise_error Raml::InvalidProperty, /uriParameters/ }
89
+ end
90
+ end
91
+
92
+ context 'when nested resources are defined' do
93
+ let(:name) { '/{userId}' }
94
+ let(:data) {
95
+ YAML.load(
96
+ %q(
97
+ uriParameters:
98
+ userId:
99
+ type: integer
100
+ /followers:
101
+ displayName: Followers
102
+ /following:
103
+ displayName: Following
104
+ /keys:
105
+ /{keyId}:
106
+ uriParameters:
107
+ keyId:
108
+ type: integer
109
+ )
110
+ )
111
+ }
112
+ it { expect { subject }.to_not raise_error }
113
+ it 'stores all as Raml::Resource instances' do
114
+ expect( subject.resources.values ).to all( be_a Raml::Resource )
115
+ expect( subject.resources.keys ).to contain_exactly('/followers','/following', '/keys')
116
+ end
117
+ end
118
+
119
+ context 'when a baseUriParameters property is given' do
120
+ context 'when the baseUriParameters property is well formed' do
121
+ let(:name) { '/files' }
122
+ let(:data) {
123
+ YAML.load(
124
+ %q(
125
+ displayName: Download files
126
+ baseUriParameters:
127
+ apiDomain:
128
+ enum: [ "api-content" ]
129
+ )
130
+ )
131
+ }
132
+
133
+ it { expect { subject }.to_not raise_error }
134
+ it 'stores all as Raml::Parameter::UriParameter instances' do
135
+ expect( subject.base_uri_parameters.values ).to all( be_a Raml::Parameter::BaseUriParameter )
136
+ subject.base_uri_parameters.keys.should contain_exactly('apiDomain')
137
+ end
138
+ end
139
+ context 'when the baseUriParameters property is not a map' do
140
+ before { data['baseUriParameters'] = 1 }
141
+ it { expect { subject }.to raise_error Raml::InvalidProperty, /baseUriParameters/ }
142
+ end
143
+ context 'when the baseUriParameters property is not a map with non-string keys' do
144
+ before { data['baseUriParameters'] = { 1 => {}} }
145
+ it { expect { subject }.to raise_error Raml::InvalidProperty, /baseUriParameters/ }
146
+ end
147
+ context 'when the baseUriParameters property is not a map with non-string keys' do
148
+ before { data['baseUriParameters'] = { '1' => 'x'} }
149
+ it { expect { subject }.to raise_error Raml::InvalidProperty, /baseUriParameters/ }
150
+ end
151
+ context 'when the baseUriParameters property has a key for the reserved "version" parameter' do
152
+ before { data['baseUriParameters'] = { 'version' => {}} }
153
+ it { expect { subject }.to raise_error Raml::InvalidProperty, /baseUriParameters/ }
154
+ end
155
+ end
156
+
157
+ context 'when an type property is given' do
158
+ let(:root) {
159
+ Raml::Root.new 'title' => 'x', 'baseUri' => 'http://foo.com', 'resourceTypes' => [
160
+ { 'collection' => {} },
161
+ { 'member' => {} },
162
+ { 'auditableResource' => {} }
163
+ ]
164
+ }
165
+ context 'when the property is valid' do
166
+ context 'when the property is a resource type reference' do
167
+ before { data['type'] = 'collection' }
168
+ it { expect { subject }.to_not raise_error }
169
+ it 'should store the resource type reference' do
170
+ subject.type.should be_a Raml::ResourceTypeReference
171
+ subject.type.name.should == 'collection'
172
+ end
173
+ end
174
+ context 'when the property is a resource type reference with parameters' do
175
+ before { data['type'] = {'collection' => {'maxSize' => 10}} }
176
+ it { expect { subject }.to_not raise_error }
177
+ it 'should store the resource type reference' do
178
+ subject.type.should be_a Raml::ResourceTypeReference
179
+ subject.type.name.should == 'collection'
180
+ end
181
+ end
182
+ context 'when the property is a resource type definitions' do
183
+ let(:definition) {
184
+ YAML.load(%q(
185
+ usage: This resourceType should be used for any collection of items
186
+ description: The collection of <<resourcePathName>>
187
+ get:
188
+ description: Get all <<resourcePathName>>, optionally filtered
189
+ ))
190
+ }
191
+ before { data['type'] = definition }
192
+
193
+ it { expect { subject }.to_not raise_error }
194
+ it 'should store the resource type' do
195
+ subject.type.should be_a Raml::ResourceType
196
+ subject.send(:instantiate_resource_type).usage.should == definition['usage']
197
+ end
198
+ end
199
+ end
200
+ context 'when the property is invalid' do
201
+ context 'when the type property is not a string or a map' do
202
+ before { data['type'] = 1 }
203
+ it { expect { subject }.to raise_error Raml::InvalidProperty, /type/ }
204
+ end
205
+ context 'when the property is a resource type name with parameters, but the params are not a map' do
206
+ before { data['type'] = { 'collection' => 1 } }
207
+ it { expect { subject }.to raise_error Raml::InvalidProperty, /type/ }
208
+ end
209
+ end
210
+ end
211
+
212
+ context 'when an is property is given' do
213
+ let(:root) {
214
+ Raml::Root.new 'title' => 'x', 'baseUri' => 'http://foo.com', 'traits' => [
215
+ { 'secured' => {} },
216
+ { 'paged' => {} },
217
+ { 'rateLimited' => {} }
218
+ ]
219
+ }
220
+ context 'when the property is valid' do
221
+ context 'when the property is an array of trait references' do
222
+ let(:data) { { 'is' => [ 'secured', 'paged' ] } }
223
+ it { expect { subject }.to_not raise_error }
224
+ it 'should store the trait references' do
225
+ subject.traits.should all( be_a Raml::TraitReference )
226
+ subject.traits.map(&:name).should contain_exactly('secured', 'paged')
227
+ end
228
+ end
229
+ context 'when the property is an array of trait references with parameters' do
230
+ let(:data) { {
231
+ 'is' => [
232
+ {'secured' => {'tokenName' => 'access_token'}},
233
+ {'paged' => {'maxPages' => 10 }}
234
+ ]
235
+ } }
236
+ it { expect { subject }.to_not raise_error }
237
+ it 'should store the trait references' do
238
+ subject.traits.should all( be_a Raml::TraitReference )
239
+ subject.traits.map(&:name).should contain_exactly('secured', 'paged')
240
+ end
241
+ end
242
+ context 'when the property is an array of trait definitions' do
243
+ let(:data) { {
244
+ 'is' => [
245
+ {'queryParameters' => {'tokenName' => {'description'=>'foo'}}},
246
+ {'queryParameters' => {'numPages' => {'description'=>'bar'}}}
247
+ ]
248
+ } }
249
+ it { expect { subject }.to_not raise_error }
250
+ it 'should store the traits' do
251
+ subject.traits.should all( be_a Raml::Trait )
252
+ subject.traits[0].value.should eq ({'queryParameters' => {'tokenName' => {'description'=>'foo'}}})
253
+ subject.traits[1].value.should eq ({'queryParameters' => {'numPages' => {'description'=>'bar'}}})
254
+ end
255
+ end
256
+ context 'when the property is an array of mixed trait refrences, trait refrences with parameters, and trait definitions' do
257
+ let(:data) { {
258
+ 'is' => [
259
+ {'secured' => {'tokenName' => 'access_token'}},
260
+ {'queryParameters' => {'numPages' => {'description'=>'bar'}}},
261
+ 'rateLimited'
262
+ ]
263
+ } }
264
+ it { expect { subject }.to_not raise_error }
265
+ it 'should store the traits' do
266
+ subject.traits.select {|t| t.is_a? Raml::TraitReference }.map(&:name).should contain_exactly('secured', 'rateLimited')
267
+ subject.traits.select {|t| t.is_a? Raml::Trait }[0].value.should eq ({'queryParameters' => {'numPages' => {'description'=>'bar'}}})
268
+ end
269
+ end
270
+ end
271
+ context 'when the property is invalid' do
272
+ context 'when the property is not an array' do
273
+ let(:data) { { 'is' => 1 } }
274
+ it { expect { subject }.to raise_error Raml::InvalidProperty, /is/ }
275
+ end
276
+ context 'when the property is an array with elements other than a string or map' do
277
+ let(:data) { { 'is' => [1] } }
278
+ it { expect { subject }.to raise_error Raml::InvalidProperty, /is/ }
279
+ end
280
+ context 'when the property is an array an element that appears to be a trait name with parameters, but the params are not a map' do
281
+ let(:data) { { 'is' => [ { 'secured' => 1 } ] } }
282
+ it { expect { subject }.to raise_error Raml::InvalidProperty, /is/ }
283
+ end
284
+ end
285
+ end
286
+
287
+ context 'when the syntax tree contains optional properties' do
288
+ let(:data) {
289
+ YAML.load(%q(
290
+ uriParameters:
291
+ id:
292
+ type: integer
293
+ required: true
294
+ example: 277102
295
+ /processing_status:
296
+ get:
297
+ displayName: Processing status
298
+ description: Получить статус загрузки
299
+ responses:
300
+ 200?:
301
+ body:
302
+ application/json:
303
+ example: |
304
+ {
305
+ "percent": 0,
306
+ "type": "download",
307
+ "status":"initial"
308
+ }
309
+ ))
310
+ }
311
+ it { expect { subject }.to raise_error Raml::InvalidProperty, /Optional properties/ }
312
+ end
313
+ end
314
+
315
+ describe '#apply_resource_type' do
316
+ let(:resource_data) { {
317
+ 'type' => {
318
+ 'get' => { 'description' => 'resource type description', 'displayName' => 'resource type displayName' }
319
+ },
320
+ 'get' => {'description' => 'method description'},
321
+ 'post' => {},
322
+ '/foo' => {},
323
+ '/bar' => {}
324
+ } }
325
+ let(:resource) { Raml::Resource.new('/foo', resource_data, root) }
326
+ context 'when it has a resource type' do
327
+ it 'merges the resource type to the resource' do
328
+ resource.type.should be_a Raml::ResourceType
329
+ mock.proxy(resource).instantiate_resource_type { |instantiated_type|
330
+ mock(resource).merge(instantiated_type)
331
+ mock(resource).merge(is_a(Raml::Resource))
332
+ instantiated_type
333
+ }
334
+ resource.apply_resource_type
335
+ end
336
+ it 'applies the resource type correctly' do
337
+ resource.apply_resource_type
338
+ resource.methods['get'].description.should eq 'method description'
339
+ resource.methods['get'].display_name.should eq 'resource type displayName'
340
+ end
341
+ end
342
+ context 'when it has nested resources' do
343
+ it 'calls #apply_resource_type on the nested resources' do
344
+ resource.resources.size.should eq 2
345
+ resource.resources.values.each { |resource| mock(resource).apply_resource_type {} }
346
+ resource.apply_resource_type
347
+ end
348
+ end
349
+ end
350
+
351
+ describe '#apply_traits' do
352
+ let(:resource_data) { {
353
+ 'is' => [
354
+ { 'description' => 'trait1 description' },
355
+ { 'description' => 'trait2 description' }
356
+ ],
357
+ 'get' => {},
358
+ 'post' => {},
359
+ '/foo' => {},
360
+ '/bar' => {}
361
+ } }
362
+ let(:resource) { Raml::Resource.new('/foo', resource_data, root) }
363
+ it 'calls apply_traits on all its methods' do
364
+ resource.traits.size.should eq 2
365
+ resource.methods.size.should eq 2
366
+ resource.methods.values.each { |method| mock(method).apply_traits {} }
367
+ resource.apply_traits
368
+ end
369
+ it 'should call apply_trait on child resources without the resource traits' do
370
+ resource.traits.size.should eq 2
371
+ resource.resources.size.should eq 2
372
+ resource.resources.values.each { |resource| mock(resource).apply_traits {} }
373
+ resource.apply_traits
374
+ end
375
+ end
376
+
377
+ describe '#merge' do
378
+ let(:resource) { Raml::Resource.new('/foo', resource_data, root) }
379
+ context 'when called with something other than a ResourceType' do
380
+ let(:resource_data) { {} }
381
+ it do
382
+ expect { resource.merge(Raml::ResourceTypeReference.new('bar', root)) }.to raise_error Raml::MergeError
383
+ end
384
+ end
385
+ context 'when called with a ResourceType::Instance' do
386
+ let(:root_data) { {
387
+ 'title' => 'x',
388
+ 'baseUri' => 'http://foo.com',
389
+ 'traits' => [ {
390
+ 'secured' => { 'usage' => 'requires authentication' },
391
+ 'paged' => { 'usage' => 'allows for paging' }
392
+ } ]
393
+ } }
394
+ let(:resource_type) { Raml::ResourceType.new('bar', resource_type_data, root).instantiate({}) }
395
+ let(:resource_data) { {
396
+ 'is' => [ 'secured' ],
397
+ 'baseUriParameters' => { 'apiDomain' => { 'enum' => ['api'] } },
398
+ 'uriParameters' => { 'userId' => { 'type' => 'integer' } },
399
+ 'get' => {
400
+ 'queryParameters' => { 'id' => { 'type' => 'integer' } }
401
+ }
402
+ } }
403
+ let(:resource_type_data) { {
404
+ 'usage' => 'resource usage',
405
+ 'is' => [ 'paged' ],
406
+ 'baseUriParameters' => { 'apiDomain' => { 'enum' => ['static'] } },
407
+ 'uriParameters' => { 'language' => { 'default' => 'en' } },
408
+ 'get' => {
409
+ 'queryParameters' => { 'query' => { 'maxLength' => 100 } }
410
+ },
411
+ 'post' => {
412
+ 'description' => 'create a new one'
413
+ }
414
+ } }
415
+ it 'merges the resource type into the resource' do
416
+ resource.merge resource_type
417
+ resource.traits.map { |trait_ref| trait_ref.name }.should eq [ 'paged', 'secured' ]
418
+ resource.base_uri_parameters.keys.should contain_exactly('apiDomain')
419
+ resource.base_uri_parameters['apiDomain'].enum.should eq ['static']
420
+ resource.uri_parameters.keys.should contain_exactly('userId', 'language')
421
+ resource.methods.keys.should contain_exactly('get', 'post')
422
+ resource.methods['get'].query_parameters.keys.should contain_exactly('id', 'query')
423
+ end
424
+ it 'does not add the usage property to the resource' do
425
+ resource.merge resource_type
426
+ expect { resource.usage }.to raise_error NoMethodError
427
+ end
428
+ end
429
+ end
430
+
431
+ describe '#document' do
432
+ it 'returns a String' do
433
+ subject.document.should be_a String
434
+ end
435
+ it 'should render the template' do
436
+ mock(Slim::Template).new(/templates\/resource.slim\z/, is_a(Hash)).mock!.render(is_a(Raml::Node)) { '' }
437
+ subject.document
438
+ end
439
+ end
440
+ end