praxis 0.15.0 → 0.16.0

Sign up to get free protection for your applications and to get access to all the features.
@@ -11,7 +11,7 @@ describe Praxis::ActionDefinition do
11
11
 
12
12
  media_type 'application/json'
13
13
  version '1.0'
14
- routing { prefix '/api/hello_world' }
14
+ prefix '/api/hello_world'
15
15
  action_defaults do
16
16
  payload { attribute :inherited, String }
17
17
  headers { header "Inherited", String }
@@ -61,6 +61,44 @@ describe Praxis::ActionDefinition do
61
61
  it 'has some tests after we stop using ApiDefinition.instance'
62
62
  end
63
63
 
64
+ describe 'when a trait is used' do
65
+ subject(:action) do
66
+ Praxis::ActionDefinition.new(:bar, resource_definition) do
67
+ trait :test
68
+ routing { get '/:one' }
69
+ params { attribute :one, String }
70
+ end
71
+ end
72
+
73
+ let(:trait) do
74
+ Praxis::Trait.new do
75
+ routing do
76
+ prefix '/test_trait/:app_name'
77
+ end
78
+
79
+ params do
80
+ attribute :app_name, String
81
+ attribute :name, String
82
+ end
83
+
84
+ end
85
+ end
86
+ let(:traits) { {test: trait} }
87
+
88
+ before do
89
+ allow(Praxis::ApiDefinition.instance).to receive(:traits).and_return(traits)
90
+ end
91
+
92
+ its('params.attributes.keys') { should eq [:inherited, :app_name, :name, :one]}
93
+ its('routes.first.path.to_s') { should eq '/api/hello_world/test_trait/:app_name/:one' }
94
+ its(:traits) { should eq [:test] }
95
+
96
+ it 'is reflected in the describe output' do
97
+ expect(action.describe[:traits]).to eq [:test]
98
+ end
99
+
100
+ end
101
+
64
102
  describe '#params' do
65
103
  it 'merges in more params' do
66
104
  subject.params do
@@ -98,9 +136,8 @@ describe Praxis::ActionDefinition do
98
136
  header "more"
99
137
  end
100
138
 
101
- expect(subject.headers.attributes.keys).to match_array([
102
- "X_REQUESTED_WITH", "Inherited", "more"
103
- ])
139
+ expected_array = ["X_REQUESTED_WITH", "Inherited", "more"]
140
+ expect(subject.headers.attributes.keys).to match_array(expected_array)
104
141
  end
105
142
  end
106
143
 
@@ -153,7 +190,7 @@ describe Praxis::ActionDefinition do
153
190
 
154
191
  context 'with nodoc!' do
155
192
  before do
156
- action.nodoc!
193
+ action.nodoc!
157
194
  end
158
195
 
159
196
  it 'has :doc_visibility set in metadata' do
@@ -165,4 +202,69 @@ describe Praxis::ActionDefinition do
165
202
  end
166
203
 
167
204
  end
205
+
206
+ context 'with a base_path and base_params on ApiDefinition' do
207
+ # Without getting a fresh new ApiDefinition it is very difficult to test stuff using the Singleton
208
+ # So for some tests we're gonna create a new instance and work with it to avoid the singleton issues
209
+ let(:non_singleton_api) do
210
+ api_def=Praxis::ApiDefinition.__send__(:new)
211
+ api_def.instance_eval do |api|
212
+
213
+ api.info do
214
+ base_path '/apps/:app_name'
215
+ end
216
+
217
+ api.info '1.0' do
218
+ base_params do
219
+ attribute :app_name, String
220
+ end
221
+ end
222
+
223
+ end
224
+ api_def
225
+ end
226
+
227
+ before do
228
+ allow(Praxis::ApiDefinition).to receive(:instance).and_return(non_singleton_api)
229
+ end
230
+
231
+ its('routes.first.path.to_s') { should eq '/apps/:app_name/api/hello_world/:one' }
232
+ its('params.attributes.keys') { should eq [:inherited, :app_name, :one]}
233
+
234
+ context 'where the action overrides a base_param' do
235
+
236
+ let(:resource_definition) do
237
+ Class.new do
238
+ include Praxis::ResourceDefinition
239
+
240
+ def self.name
241
+ 'FooBar'
242
+ end
243
+ version '1.0'
244
+ prefix '/api/hello_world'
245
+ action_defaults do
246
+ payload { attribute :inherited, String }
247
+ headers { header "Inherited", String }
248
+ end
249
+ end
250
+ end
251
+
252
+ let(:action) do
253
+ Praxis::ActionDefinition.new(:foo, resource_definition) do
254
+ routing { get '' }
255
+ params { attribute :app_name, Integer }
256
+ end
257
+ end
258
+
259
+ subject(:attributes) { action.params.attributes }
260
+
261
+ its(:keys) { should eq [:app_name]}
262
+
263
+ it 'overrides the base param' do
264
+ expect(attributes[:app_name].type).to eq(Attributor::Integer)
265
+ end
266
+
267
+ end
268
+
269
+ end
168
270
  end
@@ -1,43 +1,54 @@
1
1
  require 'spec_helper'
2
2
 
3
3
  describe Praxis::ApiDefinition do
4
-
5
- subject(:api){ Praxis::ApiDefinition.instance }
6
-
4
+
5
+ subject(:api){ Praxis::ApiDefinition.instance }
6
+
7
7
  # Without getting a fresh new ApiDefinition it is very difficult to test stuff using the Singleton
8
8
  # So for some tests we're gonna create a new instance and work with it to avoid the singleton issues
9
9
  let(:non_singleton_api) do
10
10
  api_def=Praxis::ApiDefinition.__send__(:new)
11
11
  api_def.instance_eval do |api|
12
- api.response_template :template1, &Proc.new {}
13
- api.trait :trait1, &Proc.new {}
12
+ api.response_template :template1, &Proc.new {}
13
+ api.trait :trait1, &Proc.new {}
14
+ api.trait :trait_2 do
15
+ description 'the second testing trait'
16
+ end
17
+
18
+ api.info '1.0' do
19
+ base_path '/apps/:app_name'
20
+ base_params do
21
+ attribute :app_name, String
22
+ end
23
+ end
14
24
  end
15
25
  api_def
16
26
  end
17
-
27
+
18
28
  let(:info_block) do
19
29
  Proc.new do
20
30
  name "Name"
21
31
  title "Title"
22
32
  end
23
- end
24
-
33
+ end
34
+
25
35
  context 'singleton' do
26
36
  it 'should be a Singleton' do
27
37
  expect(Praxis::ApiDefinition.ancestors).to include( Singleton )
28
38
  expect(subject).to eq(Praxis::ApiDefinition.instance )
29
39
  end
30
-
40
+
31
41
  it 'has the :ok and :created response templates registered' do
32
42
  expect(api.responses.keys).to include(:ok)
33
43
  expect(api.responses.keys).to include(:created)
34
- end
44
+ end
35
45
  end
36
-
46
+
47
+
37
48
  context '.response_template' do
38
49
  let(:response_template){ Proc.new {} }
39
50
  let(:api){ non_singleton_api }
40
-
51
+
41
52
  it 'has the defined template1 response_template' do
42
53
  expect(api.responses.keys).to include(:template1)
43
54
  expect(api.response(:template1)).to be_kind_of(Praxis::ResponseTemplate)
@@ -48,7 +59,7 @@ describe Praxis::ApiDefinition do
48
59
  expect(api.response(:foobar)).to be_kind_of(Praxis::ResponseTemplate)
49
60
  end
50
61
  end
51
-
62
+
52
63
  context '.response' do
53
64
  let(:api){ non_singleton_api }
54
65
 
@@ -56,32 +67,39 @@ describe Praxis::ApiDefinition do
56
67
  expect(api.response(:template1)).to be_kind_of(Praxis::ResponseTemplate)
57
68
  end
58
69
  end
59
-
70
+
60
71
  context '.trait' do
61
72
  let(:api){ non_singleton_api }
62
-
73
+
63
74
  let(:trait2){ Proc.new{} }
75
+
64
76
  it 'has the defined trait1 ' do
65
77
  expect(api.traits.keys).to include(:trait1)
66
- expect(api.traits[:trait1]).to be_kind_of(Proc)
78
+ expect(api.traits[:trait1]).to be_kind_of(Praxis::Trait)
67
79
  end
68
-
69
- it 'saves it verbatim' do
70
- api.trait :trait2, &trait2
71
- expect(api.traits[:trait2]).to be(trait2)
72
- end
73
-
80
+
74
81
  it 'complains trying to register traits with same name' do
75
82
  api.trait :trait2, &trait2
76
- expect{
83
+ expect{
77
84
  api.trait :trait2, &trait2
78
85
  }.to raise_error(Praxis::Exceptions::InvalidTrait, /Overwriting a previous trait with the same name/)
79
86
  end
80
87
  end
81
-
88
+
82
89
  context '.info' do
83
-
90
+
84
91
  let(:api){ non_singleton_api }
92
+ subject(:info) { api.info('1.0') }
93
+
94
+ context '.base_path' do
95
+ its(:base_path) { should eq '/apps/:app_name'}
96
+ end
97
+
98
+ context '.base_params' do
99
+ subject(:base_params) { info.base_params }
100
+ it { should be_kind_of(Attributor::Attribute) }
101
+ its(:attributes) { should include :app_name }
102
+ end
85
103
 
86
104
  context 'with a version' do
87
105
  it 'saves the data into the correct version hash' do
@@ -89,36 +107,39 @@ describe Praxis::ApiDefinition do
89
107
  api.info("9.0", &info_block)
90
108
  expect(api.infos.keys).to include("9.0")
91
109
  end
92
- it 'immediate invokes the block' do
93
- expect(api.infos["9.0"]).to receive(:instance_eval)
94
- api.info("9.0", &info_block)
95
- end
96
- end
110
+ end
111
+
97
112
  context 'without a version' do
98
- it 'saves it into nil if no version is passed' do
113
+ it 'saves it into global_info' do
99
114
  expect(api.infos.keys).to_not include(nil)
100
115
  api.info do
101
116
  description "Global Description"
102
117
  end
103
- expect(api.infos.keys).to include(nil)
118
+ expect(api.infos.keys).to_not include(nil)
119
+ expect(api.global_info.description).to eq 'Global Description'
104
120
  end
105
121
  end
106
122
  end
107
-
123
+
108
124
  context '.describe' do
109
125
  subject(:output){ api.describe }
110
126
 
111
127
  context 'using the spec_app definitions' do
112
128
  subject(:version_output){ output["1.0"][:info] }
113
- it 'saves the data into the correct version hash' do
114
- expect(api.infos.keys).to include(nil)
115
- expect(api.infos.keys).to include("1.0")
116
- end
117
129
 
130
+ context 'for the global_info data' do
131
+ subject(:info) { output[:global][:info] }
132
+ it { should include(:name, :title, :description) }
133
+ its([:name]) { should eq 'Spec App' }
134
+ its([:title]) { should eq 'A simple App to do some simple integration testing' }
135
+ its([:description]) { should eq 'This example API should really be replaced by a set of more full-fledged example apps in the future' }
136
+ end
137
+
118
138
  it 'outputs data for 1.0 info' do
119
139
  expect(output.keys).to include("1.0")
120
140
  expect(output["1.0"]).to include(:info)
121
141
  end
142
+
122
143
  it 'describes 1.0 Api info properly' do
123
144
  info = output["1.0"][:info]
124
145
  expect(info).to include(:schema_version, :name, :title, :description, :base_path)
@@ -129,21 +150,23 @@ describe Praxis::ApiDefinition do
129
150
  expect(info[:base_path]).to eq("/")
130
151
  end
131
152
  end
132
-
153
+
133
154
  context 'using a non-singleton object' do
134
155
  let(:api){ non_singleton_api }
135
-
156
+
136
157
  before do
137
158
  api.info("9.0", &info_block)
138
159
  api.info do
139
160
  description "Global Description"
140
161
  end
141
162
  end
142
- its(:keys){ should include("9.0") }
143
-
163
+ its(:keys) { should include("9.0") }
164
+ its(:keys) { should include :traits }
165
+ its([:traits, :trait_2]) { should eq api.traits[:trait_2].describe }
166
+
144
167
  context 'for v9.0 info' do
145
168
  subject(:v9_info){ output["9.0"][:info] }
146
-
169
+
147
170
  it 'has the info it was set in the call' do
148
171
  expect(v9_info).to include({schema_version: "1.0"})
149
172
  expect(v9_info).to include({name: "Name"})
@@ -152,8 +175,8 @@ describe Praxis::ApiDefinition do
152
175
  it 'inherited the description from the nil(global) one' do
153
176
  expect(v9_info).to include({description: "Global Description"})
154
177
  end
155
-
178
+
156
179
  end
157
180
  end
158
181
  end
159
- end
182
+ end
@@ -1,36 +1,50 @@
1
1
  require 'spec_helper'
2
2
 
3
3
  describe Praxis::ApiGeneralInfo do
4
-
4
+
5
5
  subject(:info){ Praxis::ApiGeneralInfo.new }
6
-
6
+
7
7
  let(:info_block) do
8
8
  Proc.new do
9
9
  name "Name"
10
10
  title "Title"
11
11
  description "Description"
12
12
  base_path "/base"
13
+ base_params do
14
+ attribute :name, String
15
+ end
13
16
  end
14
17
  end
15
-
16
- context 'DSLs' do
18
+
19
+ context 'setting' do
17
20
  it 'accepts the appropriate DSLs' do
18
- expect{
21
+ expect{
19
22
  info.instance_exec &info_block
20
23
  }.to_not raise_error
21
24
  end
22
-
23
25
  end
24
26
 
27
+ context 'getting values' do
28
+ before do
29
+ info.instance_exec &info_block
30
+ end
31
+
32
+ its(:name) { should eq 'Name' }
33
+
34
+ end
25
35
  context '.describe' do
26
- subject(:output){ info.describe }
27
- it 'works' do
36
+ before do
28
37
  info.instance_exec &info_block
29
- expect(output).to eq(
30
- {:schema_version=>"1.0", :name=>"Name", :title=>"Title",
31
- :description=>"Description", :base_path=>"/base"
32
- })
33
38
  end
34
-
39
+
40
+ subject(:output){ info.describe }
41
+ its([:schema_version]) {should eq '1.0' }
42
+ its([:name]) {should eq 'Name' }
43
+ its([:title]) {should eq 'Title' }
44
+ its([:description]) {should eq 'Description' }
45
+ its([:base_path]) {should eq '/base' }
46
+ its([:base_params]) { should have_key :name }
47
+ its([:base_params, :name, :type, :name]) { should eq 'String' }
48
+
35
49
  end
36
- end
50
+ end
@@ -9,8 +9,8 @@ describe Praxis::MediaType do
9
9
  end
10
10
 
11
11
  let(:resource) do
12
- double('address',
13
- id: 1,
12
+ double('address',
13
+ id: 1,
14
14
  name: 'Home',
15
15
  owner: owner_resource,
16
16
  manager: manager_resource,
@@ -38,7 +38,7 @@ describe Praxis::MediaType do
38
38
  end
39
39
 
40
40
 
41
-
41
+
42
42
  context 'accessor methods' do
43
43
  subject(:address_klass) { address.class }
44
44
 
@@ -62,7 +62,7 @@ describe Praxis::MediaType do
62
62
  end
63
63
 
64
64
  its(:description) { should be_kind_of(String) }
65
-
65
+
66
66
  context 'links' do
67
67
  context 'with a custom links attribute' do
68
68
  subject(:person) { Person.new(owner_resource) }
@@ -70,7 +70,7 @@ describe Praxis::MediaType do
70
70
  its(:links) { should be_kind_of(Array) }
71
71
  its(:links) { should eq(owner_resource.links) }
72
72
  end
73
-
73
+
74
74
  context 'using the links DSL' do
75
75
  subject(:address) { Address.new(resource) }
76
76
  its(:links) { should be_kind_of(Address::Links) }
@@ -114,7 +114,7 @@ describe Praxis::MediaType do
114
114
  let(:snapshots_summary) { volume.snapshots_summary }
115
115
  let(:output) { volume.render(:default) }
116
116
  subject { links[:snapshots] }
117
-
117
+
118
118
  its([:name]) { should eq(snapshots_summary.name) }
119
119
  its([:size]) { should eq(snapshots_summary.size) }
120
120
  its([:href]) { should eq(snapshots_summary.href) }
@@ -140,6 +140,33 @@ describe Praxis::MediaType do
140
140
  end
141
141
 
142
142
 
143
+ context 'describing' do
144
+
145
+ subject(:described){ Address.describe }
146
+
147
+ its(:keys) { should match_array( [:attributes, :description, :family, :id, :identifier, :key, :name, :views] ) }
148
+ its([:attributes]) { should be_kind_of(::Hash) }
149
+ its([:description]) { should be_kind_of(::String) }
150
+ its([:family]) { should be_kind_of(::String) }
151
+ its([:id]) { should be_kind_of(::String) }
152
+ its([:name]) { should be_kind_of(::String) }
153
+ its([:identifier]) { should be_kind_of(::String) }
154
+ its([:key]) { should be_kind_of(::Hash) }
155
+ its([:views]) { should be_kind_of(::Hash) }
156
+
157
+ its([:description]) { should eq(Address.description) }
158
+ its([:family]) { should eq(Address.family) }
159
+ its([:id]) { should eq(Address.id) }
160
+ its([:name]) { should eq(Address.name) }
161
+ its([:identifier]) { should eq(Address.identifier.to_s) }
162
+ it 'should include the defined views' do
163
+ expect( subject[:views].keys ).to match( [:default, :master] )
164
+ end
165
+ it 'should include the defined attributes' do
166
+ expect( subject[:attributes].keys ).to match( [:id, :name, :owner, :custodian, :residents, :residents_summary, :links] )
167
+ end
168
+ end
169
+
143
170
  context 'using blueprint caching' do
144
171
  it 'has specs'
145
172
  end