apitizer 0.0.1 → 0.0.2
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- checksums.yaml +4 -4
- data/.gitignore +3 -1
- data/.travis.yml +6 -0
- data/.yardopts +6 -0
- data/CHANGELOG.md +10 -0
- data/Guardfile +11 -4
- data/README.md +74 -7
- data/apitizer.gemspec +1 -2
- data/lib/apitizer.rb +0 -1
- data/lib/apitizer/base.rb +16 -27
- data/lib/apitizer/connection.rb +3 -1
- data/lib/apitizer/connection/adaptor.rb +1 -1
- data/lib/apitizer/connection/adaptor/standard.rb +24 -7
- data/lib/apitizer/connection/dispatcher.rb +5 -12
- data/lib/apitizer/connection/format.rb +14 -0
- data/lib/apitizer/{processing/parser → connection/format}/json.rb +6 -2
- data/lib/apitizer/{processing/parser → connection/format}/yaml.rb +6 -2
- data/lib/apitizer/connection/request.rb +3 -3
- data/lib/apitizer/connection/response.rb +3 -3
- data/lib/apitizer/core.rb +4 -4
- data/lib/apitizer/helper.rb +38 -14
- data/lib/apitizer/result.rb +2 -2
- data/lib/apitizer/routing.rb +1 -1
- data/lib/apitizer/routing/{mapper.rb → map.rb} +3 -10
- data/lib/apitizer/routing/node.rb +0 -1
- data/lib/apitizer/routing/node/base.rb +15 -17
- data/lib/apitizer/routing/node/collection.rb +17 -16
- data/lib/apitizer/routing/node/operation.rb +14 -15
- data/lib/apitizer/routing/node/root.rb +8 -2
- data/lib/apitizer/routing/path.rb +16 -8
- data/lib/apitizer/version.rb +1 -1
- data/spec/apitizer/base_spec.rb +36 -28
- data/spec/apitizer/connection/adaptor_spec.rb +87 -11
- data/spec/apitizer/connection/dispatcher_spec.rb +21 -23
- data/spec/apitizer/connection/format_spec.rb +15 -0
- data/spec/apitizer/helper_spec.rb +53 -24
- data/spec/apitizer/result_spec.rb +5 -7
- data/spec/apitizer/routing/map_spec.rb +71 -0
- data/spec/apitizer/routing/node_spec.rb +108 -36
- data/spec/apitizer/routing/path_spec.rb +12 -92
- data/spec/spec_helper.rb +4 -6
- data/spec/support/factory_helper.rb +25 -5
- data/spec/support/resource_helper.rb +8 -0
- metadata +14 -15
- data/lib/apitizer/processing.rb +0 -8
- data/lib/apitizer/processing/parser.rb +0 -14
- data/lib/apitizer/processing/translator.rb +0 -13
- data/lib/apitizer/routing/node/scope.rb +0 -19
- data/spec/apitizer/processing/parser_spec.rb +0 -23
- data/spec/apitizer/routing/mapper_spec.rb +0 -80
@@ -1,21 +1,97 @@
|
|
1
1
|
require 'spec_helper'
|
2
2
|
|
3
|
-
describe Apitizer::Connection::Adaptor do
|
3
|
+
RSpec.describe Apitizer::Connection::Adaptor do
|
4
4
|
let(:parent_module) { Apitizer::Connection }
|
5
|
-
let(:address) { 'https://service.com/api/
|
5
|
+
let(:address) { 'https://service.com/api/articles' }
|
6
6
|
|
7
|
-
|
8
|
-
|
7
|
+
shared_examples 'a proper postman' do |method:|
|
8
|
+
it 'takes into account headers' do
|
9
|
+
headers = { 'Secret-Token' => 'arbitrary' }
|
10
|
+
stub = stub_http_request(method, address).with(headers: headers)
|
11
|
+
subject.process(method, address, {}, headers)
|
12
|
+
expect(stub).to have_been_requested
|
13
|
+
end
|
14
|
+
end
|
15
|
+
|
16
|
+
shared_examples '#call of a Rack app' do |method:|
|
17
|
+
let(:code) { 200 }
|
18
|
+
let(:headers) { { 'a' => [ 'b' ] } }
|
19
|
+
let(:body) { 'Hej!' }
|
20
|
+
|
21
|
+
before(:each) do
|
22
|
+
stub_http_request(method, address).to_return(
|
23
|
+
code: code, headers: headers, body: body)
|
24
|
+
end
|
25
|
+
|
26
|
+
let(:response) { subject.process(method, address) }
|
27
|
+
|
28
|
+
it 'returns an array with three elements' do
|
29
|
+
expect(response.length).to eq(3)
|
30
|
+
end
|
31
|
+
|
32
|
+
it 'returns the code as the first element' do
|
33
|
+
expect(response[0]).to eq(code)
|
34
|
+
end
|
35
|
+
|
36
|
+
it 'returns the code as an integer' do
|
37
|
+
expect(response[0]).to be_kind_of(Integer)
|
38
|
+
end
|
39
|
+
|
40
|
+
it 'returns the headers as the second element' do
|
41
|
+
expect(response[1]).to eq(headers)
|
42
|
+
end
|
43
|
+
|
44
|
+
it 'returns the headers as a hash' do
|
45
|
+
expect(response[1]).to be_kind_of(Hash)
|
46
|
+
end
|
47
|
+
|
48
|
+
it 'returns the body as the third element' do
|
49
|
+
expect(response[2]).to eq([ body ])
|
50
|
+
end
|
51
|
+
|
52
|
+
it 'returns the body as an object responding to #each' do
|
53
|
+
expect(response[2]).to respond_to(:each)
|
54
|
+
end
|
55
|
+
end
|
56
|
+
|
57
|
+
describe '::Standard' do
|
58
|
+
subject { parent_module::Adaptor::Standard.new }
|
59
|
+
|
60
|
+
describe '#process' do
|
61
|
+
[ :get ].each do |method|
|
62
|
+
context "when sending #{ method } requests" do
|
63
|
+
it_behaves_like '#call of a Rack app', method: method
|
64
|
+
it_behaves_like 'a proper postman', method: method
|
65
|
+
|
66
|
+
it 'encodes parameters into the URI' do
|
67
|
+
stub = stub_http_request(method, address).with(query: { life: 42 })
|
68
|
+
subject.process(method, address, life: 42)
|
69
|
+
expect(stub).to have_been_requested
|
70
|
+
end
|
71
|
+
end
|
72
|
+
end
|
73
|
+
|
74
|
+
[ :post, :put, :patch, :delete ].each do |method|
|
75
|
+
context "when sending #{ method } requests" do
|
76
|
+
it_behaves_like '#call of a Rack app', method: method
|
77
|
+
it_behaves_like 'a proper postman', method: method
|
78
|
+
|
79
|
+
it 'encodes parameters into the body' do
|
80
|
+
stub = stub_http_request(method, address).with(body: 'life=42')
|
81
|
+
response = subject.process(method, address, life: 42)
|
82
|
+
expect(stub).to have_been_requested
|
83
|
+
end
|
9
84
|
|
10
|
-
|
11
|
-
|
12
|
-
|
13
|
-
|
14
|
-
|
15
|
-
|
85
|
+
it 'sets the charset parameter to UTF-8' do
|
86
|
+
stub = stub_http_request(method, address).with(
|
87
|
+
headers: { 'Content-Type' => /charset=UTF-8/ })
|
88
|
+
response = subject.process(method, address, life: 42)
|
89
|
+
expect(stub).to have_been_requested
|
90
|
+
end
|
91
|
+
end
|
16
92
|
end
|
17
93
|
|
18
|
-
it 'raises exceptions
|
94
|
+
it 'raises exceptions for unknown methods' do
|
19
95
|
expect { subject.process(:smile, address) }.to \
|
20
96
|
raise_error(parent_module::Error, /Invalid method/i)
|
21
97
|
end
|
@@ -1,37 +1,35 @@
|
|
1
1
|
require 'spec_helper'
|
2
2
|
|
3
|
-
describe Apitizer::Connection::Dispatcher do
|
3
|
+
RSpec.describe Apitizer::Connection::Dispatcher do
|
4
4
|
extend ResourceHelper
|
5
5
|
include ResourceHelper
|
6
6
|
|
7
|
-
let(:
|
8
|
-
let(:address) { 'https://service.com/api/v1/json/articles' }
|
9
|
-
let(:subject) do
|
10
|
-
Apitizer::Connection::Dispatcher.new(
|
11
|
-
dictionary: rest_http_dictionary, headers: headers)
|
12
|
-
end
|
7
|
+
let(:address) { 'https://service.com/api/articles' }
|
13
8
|
|
14
|
-
def create_request(
|
15
|
-
double(
|
9
|
+
def create_request(method)
|
10
|
+
double(method: method, address: address, parameters: {})
|
16
11
|
end
|
17
12
|
|
18
13
|
describe '#process' do
|
19
|
-
|
20
|
-
|
14
|
+
{ :json => '{}', :yaml => '---' }.each do |format, sample|
|
15
|
+
context "when interacting in #{ format }" do
|
16
|
+
let(:subject) { Apitizer::Connection::Dispatcher.new(format: format) }
|
21
17
|
|
22
|
-
|
23
|
-
|
24
|
-
|
25
|
-
|
26
|
-
|
27
|
-
|
28
|
-
|
18
|
+
http_methods.each do |method|
|
19
|
+
context "when performing #{ method } operations" do
|
20
|
+
it 'uses propoer HTTP methods' do
|
21
|
+
stub = stub_http_request(method, address).to_return(body: sample)
|
22
|
+
response = subject.process(create_request(method))
|
23
|
+
expect(stub).to have_been_requested
|
24
|
+
end
|
29
25
|
|
30
|
-
|
31
|
-
|
32
|
-
|
33
|
-
|
34
|
-
|
26
|
+
it 'sets proper headers' do
|
27
|
+
stub = stub_http_request(method, address).to_return(body: sample).
|
28
|
+
with(headers: { 'Accept' => mime_type_dictionary[format] })
|
29
|
+
response = subject.process(create_request(method))
|
30
|
+
expect(stub).to have_been_requested
|
31
|
+
end
|
32
|
+
end
|
35
33
|
end
|
36
34
|
end
|
37
35
|
end
|
@@ -0,0 +1,15 @@
|
|
1
|
+
require 'spec_helper'
|
2
|
+
|
3
|
+
RSpec.describe Apitizer::Connection::Format do
|
4
|
+
let(:subject_class) { Apitizer::Connection::Format }
|
5
|
+
|
6
|
+
{ :json => '{ "articles": [] }',
|
7
|
+
:yaml => "---\narticles: []" }.each do |format, sample|
|
8
|
+
|
9
|
+
it "supports #{ format }" do
|
10
|
+
subject = subject_class.build(format)
|
11
|
+
result = subject.process(sample)
|
12
|
+
expect(result).to eq('articles' => [])
|
13
|
+
end
|
14
|
+
end
|
15
|
+
end
|
@@ -1,6 +1,6 @@
|
|
1
1
|
require 'spec_helper'
|
2
2
|
|
3
|
-
describe Apitizer::Helper do
|
3
|
+
RSpec.describe Apitizer::Helper do
|
4
4
|
extend ResourceHelper
|
5
5
|
|
6
6
|
let(:subject_module) { Apitizer::Helper }
|
@@ -8,13 +8,13 @@ describe Apitizer::Helper do
|
|
8
8
|
describe '.member_action?' do
|
9
9
|
restful_member_actions.each do |action|
|
10
10
|
it "returns true for the #{ action } member action" do
|
11
|
-
expect(subject_module.member_action?(action)).to
|
11
|
+
expect(subject_module.member_action?(action)).to be true
|
12
12
|
end
|
13
13
|
end
|
14
14
|
|
15
15
|
restful_collection_actions.each do |action|
|
16
16
|
it "returns false for the #{ action } collection action" do
|
17
|
-
expect(subject_module.member_action?(action)).to
|
17
|
+
expect(subject_module.member_action?(action)).to be false
|
18
18
|
end
|
19
19
|
end
|
20
20
|
|
@@ -34,29 +34,39 @@ describe Apitizer::Helper do
|
|
34
34
|
end
|
35
35
|
|
36
36
|
describe '.build_query' do
|
37
|
-
it '
|
38
|
-
queries = [
|
39
|
-
'title=Meaning+of+Life&author=Random+Number+Generator',
|
40
|
-
'author=Random+Number+Generator&title=Meaning+of+Life'
|
41
|
-
]
|
37
|
+
it 'handles ordinary parameters' do
|
42
38
|
query = subject_module.build_query(
|
43
39
|
title: 'Meaning of Life', author: 'Random Number Generator')
|
44
|
-
expect(
|
40
|
+
expect(query).to \
|
41
|
+
eq('title=Meaning+of+Life&author=Random+Number+Generator')
|
45
42
|
end
|
46
43
|
|
47
|
-
it 'handles parameters whose values are ordinary
|
44
|
+
it 'handles parameters whose values are ordinary arrays' do
|
48
45
|
query = subject_module.build_query(keywords: [ 'hitchhiker', 'galaxy' ])
|
49
46
|
expect(query).to eq('keywords[]=hitchhiker&keywords[]=galaxy')
|
50
47
|
end
|
51
48
|
|
52
|
-
it 'handles parameters whose values are object
|
53
|
-
queries = [
|
54
|
-
'genres[0][name]=Comedy&genres[1][name]=Fiction',
|
55
|
-
'genres[1][name]=Fiction&genres[0][name]=Comedy'
|
56
|
-
]
|
49
|
+
it 'handles parameters whose values are object arrays' do
|
57
50
|
query = subject_module.build_query(
|
58
|
-
genres:
|
59
|
-
expect(
|
51
|
+
genres: [ { name: 'Comedy' }, { name: 'Fiction' } ])
|
52
|
+
expect(query).to \
|
53
|
+
eq('genres[0][name]=Comedy&genres[1][name]=Fiction')
|
54
|
+
end
|
55
|
+
|
56
|
+
it 'ignores parameters whose values are empty ordinary arrays' do
|
57
|
+
query = subject_module.build_query(title: 'Pulp Fiction', keywords: [])
|
58
|
+
expect(query).to eq('title=Pulp+Fiction')
|
59
|
+
end
|
60
|
+
|
61
|
+
it 'ignores parameters whose values are empty object arrays' do
|
62
|
+
query = subject_module.build_query(title: 'Pulp Fiction', genres: {})
|
63
|
+
expect(query).to eq('title=Pulp+Fiction')
|
64
|
+
end
|
65
|
+
|
66
|
+
it 'ignores deeply nested empty structures' do
|
67
|
+
query = subject_module.build_query(title: 'Pulp Fiction',
|
68
|
+
genres: [ { :name => { :language => [ nil, nil, [], {} ] } } ])
|
69
|
+
expect(query).to eq('title=Pulp+Fiction')
|
60
70
|
end
|
61
71
|
|
62
72
|
it 'converts integers to decimal strings' do
|
@@ -64,14 +74,11 @@ describe Apitizer::Helper do
|
|
64
74
|
expect(query).to eq('page=42')
|
65
75
|
end
|
66
76
|
|
67
|
-
it 'converts integers in object
|
68
|
-
queries = [
|
69
|
-
'primes[0][value]=2&primes[1][value]=3',
|
70
|
-
'primes[1][value]=3&primes[0][value]=2'
|
71
|
-
]
|
77
|
+
it 'converts integers in object arrays to decimal strings' do
|
72
78
|
query = subject_module.build_query(
|
73
|
-
primes:
|
74
|
-
expect(
|
79
|
+
primes: [ { value: 2 }, { value: 3 } ])
|
80
|
+
expect(query).to \
|
81
|
+
eq('primes[0][value]=2&primes[1][value]=3')
|
75
82
|
end
|
76
83
|
|
77
84
|
it 'converts the logical true to the string true' do
|
@@ -83,5 +90,27 @@ describe Apitizer::Helper do
|
|
83
90
|
query = subject_module.build_query(published: false)
|
84
91
|
expect(query).to eq('published=false')
|
85
92
|
end
|
93
|
+
|
94
|
+
it 'handles an arbitrary object that responds to #to_a' do
|
95
|
+
object = double(to_a: [ 'one', 'two' ])
|
96
|
+
query = subject_module.build_query(digits: object)
|
97
|
+
expect(query).to eq('digits[]=one&digits[]=two')
|
98
|
+
end
|
99
|
+
|
100
|
+
it 'handles an arbitrary object that responds to #to_h' do
|
101
|
+
object = double(to_h: { one: 1, two: 2 })
|
102
|
+
query = subject_module.build_query(digits: object)
|
103
|
+
expect(query).to eq('digits[one]=1&digits[two]=2')
|
104
|
+
end
|
105
|
+
|
106
|
+
it 'raises an exception for an unknown objects without #to_a and #to_h' do
|
107
|
+
expect { subject_module.build_query(a: { b: Class.new.new }) }.to \
|
108
|
+
raise_error(ArgumentError)
|
109
|
+
end
|
110
|
+
|
111
|
+
it 'returns a string encoded in UTF-8' do
|
112
|
+
query = subject_module.build_query(alpha: 'omega')
|
113
|
+
expect(query.encoding.to_s).to match(/^UTF-8$/i)
|
114
|
+
end
|
86
115
|
end
|
87
116
|
end
|
@@ -1,19 +1,17 @@
|
|
1
1
|
require 'spec_helper'
|
2
2
|
|
3
|
-
describe Apitizer::Result do
|
3
|
+
RSpec.describe Apitizer::Result do
|
4
4
|
let(:path) { double('Path') }
|
5
5
|
let(:request) { double('Request', path: path) }
|
6
|
-
let(:response) { double('Response', code: 200) }
|
7
6
|
let(:content) { double('Content') }
|
7
|
+
let(:response) { double('Response', code: 200, content: content) }
|
8
8
|
|
9
|
-
subject
|
10
|
-
Apitizer::Result.new(request: request, response: response, content: content)
|
11
|
-
end
|
9
|
+
subject { Apitizer::Result.new(request: request, response: response) }
|
12
10
|
|
13
11
|
it { should == content }
|
14
12
|
it { should be_a(content.class) }
|
15
13
|
it { should be_kind_of(content.class) }
|
16
14
|
it { should be_instance_of(content.class) }
|
17
|
-
|
18
|
-
|
15
|
+
it { expect(subject.path).to eq(path) }
|
16
|
+
it { expect(subject.code).to eq(200) }
|
19
17
|
end
|
@@ -0,0 +1,71 @@
|
|
1
|
+
require 'spec_helper'
|
2
|
+
|
3
|
+
RSpec.describe Apitizer::Routing::Map do
|
4
|
+
extend ResourceHelper
|
5
|
+
|
6
|
+
describe '#define' do
|
7
|
+
it 'declares plain resources' do
|
8
|
+
subject.define { resources(:articles) }
|
9
|
+
path = subject.trace(:index, [ :articles ])
|
10
|
+
expect(path.address).to eq('articles')
|
11
|
+
end
|
12
|
+
|
13
|
+
it 'declares nested resources' do
|
14
|
+
subject.define { resources(:articles) { resources(:sections) } }
|
15
|
+
path = subject.trace(:show, [ :articles, 'xxx', :sections, 'yyy' ])
|
16
|
+
expect(path.address).to eq('articles/xxx/sections/yyy')
|
17
|
+
end
|
18
|
+
|
19
|
+
it 'declares the root address' do
|
20
|
+
subject.define do
|
21
|
+
address('https://service.com/api')
|
22
|
+
resources(:articles)
|
23
|
+
end
|
24
|
+
path = subject.trace(:show, [ :articles, 'xxx' ])
|
25
|
+
expect(path.address).to eq('https://service.com/api/articles/xxx')
|
26
|
+
end
|
27
|
+
|
28
|
+
restful_actions.each do |action|
|
29
|
+
it "declares #{ action } operations on members" do
|
30
|
+
subject.define do
|
31
|
+
resources(:articles) { send(action, :shred, on: :member) }
|
32
|
+
end
|
33
|
+
path = subject.trace(action, [ :articles, 'xxx', :shred ])
|
34
|
+
expect(path.address).to eq('articles/xxx/shred')
|
35
|
+
end
|
36
|
+
|
37
|
+
it "declares #{ action } operations on members with variable names" do
|
38
|
+
subject.define do
|
39
|
+
resources(:articles) { send(action, ':paragraph', on: :member) }
|
40
|
+
end
|
41
|
+
path = subject.trace(action, [ :articles, 'xxx', 'zzz' ])
|
42
|
+
expect(path.address).to eq('articles/xxx/zzz')
|
43
|
+
end
|
44
|
+
|
45
|
+
it "declares #{ action } operations on collections" do
|
46
|
+
subject.define do
|
47
|
+
resources(:articles) { send(action, :shred, on: :collection) }
|
48
|
+
end
|
49
|
+
path = subject.trace(action, [ :articles, :shred ])
|
50
|
+
expect(path.address).to eq('articles/shred')
|
51
|
+
end
|
52
|
+
|
53
|
+
it "declares #{ action } operations on collections with variable names" do
|
54
|
+
subject.define do
|
55
|
+
resources(:articles) { send(action, ':paragraph', on: :collection) }
|
56
|
+
end
|
57
|
+
path = subject.trace(action, [ :articles, 'zzz' ])
|
58
|
+
expect(path.address).to eq('articles/zzz')
|
59
|
+
end
|
60
|
+
end
|
61
|
+
|
62
|
+
it 'supports reopening of resource declarations' do
|
63
|
+
subject.define do
|
64
|
+
resources(:articles)
|
65
|
+
resources(:articles) { resources(:sections) }
|
66
|
+
end
|
67
|
+
path = subject.trace(:show, [ :articles, 'xxx', :sections, 'yyy' ])
|
68
|
+
expect(path.address).to eq('articles/xxx/sections/yyy')
|
69
|
+
end
|
70
|
+
end
|
71
|
+
end
|
@@ -1,63 +1,135 @@
|
|
1
1
|
require 'spec_helper'
|
2
2
|
|
3
|
-
describe Apitizer::Routing::Node do
|
3
|
+
RSpec.describe Apitizer::Routing::Node do
|
4
4
|
extend ResourceHelper
|
5
5
|
include FactoryHelper
|
6
6
|
|
7
7
|
shared_examples 'an adequate pathfinder' do
|
8
|
-
|
8
|
+
it 'finds final destinations' do
|
9
|
+
expect(root.trace(steps)).to be_kind_of(Apitizer::Routing::Path)
|
10
|
+
end
|
11
|
+
end
|
12
|
+
|
13
|
+
shared_examples 'an adequate collection guard' do |only: restful_actions|
|
14
|
+
(restful_collection_actions & only).each do |action|
|
15
|
+
it "permits #{ action } actions" do
|
16
|
+
path = root.trace(steps)
|
17
|
+
expect(path.permit?(action)).to be_truthy
|
18
|
+
end
|
19
|
+
end
|
9
20
|
|
10
|
-
|
11
|
-
|
12
|
-
|
21
|
+
(restful_collection_actions - only).each do |action|
|
22
|
+
it "does not permit #{ action } actions" do
|
23
|
+
path = root.trace(steps)
|
24
|
+
expect(path.permit?(action)).to be_falsy
|
13
25
|
end
|
14
|
-
root.trace(steps, path)
|
15
26
|
end
|
16
27
|
|
17
|
-
|
18
|
-
|
19
|
-
|
20
|
-
|
28
|
+
restful_member_actions.each do |action|
|
29
|
+
it "does not permit #{ action } actions" do
|
30
|
+
path = root.trace(steps)
|
31
|
+
expect(path.permit?(action)).to be_falsy
|
21
32
|
end
|
22
|
-
root.trace(steps, path)
|
23
33
|
end
|
24
34
|
end
|
25
35
|
|
26
|
-
|
27
|
-
|
28
|
-
|
36
|
+
shared_examples 'an adequate member guard' do |only: restful_actions|
|
37
|
+
(restful_member_actions & only).each do |action|
|
38
|
+
it "permites #{ action } actions" do
|
39
|
+
path = root.trace(steps)
|
40
|
+
expect(path.permit?(action)).to be_truthy
|
41
|
+
end
|
42
|
+
end
|
29
43
|
|
30
|
-
|
31
|
-
|
32
|
-
|
44
|
+
(restful_member_actions - only).each do |action|
|
45
|
+
it "does not permit #{ action } actions" do
|
46
|
+
path = root.trace(steps)
|
47
|
+
expect(path.permit?(action)).to be_falsy
|
33
48
|
end
|
49
|
+
end
|
34
50
|
|
35
|
-
|
36
|
-
|
37
|
-
|
51
|
+
restful_collection_actions.each do |action|
|
52
|
+
it "does not permit #{ action } actions" do
|
53
|
+
path = root.trace(steps)
|
54
|
+
expect(path.permit?(action)).to be_falsy
|
38
55
|
end
|
39
56
|
end
|
57
|
+
end
|
58
|
+
|
59
|
+
context 'when defining plain collections' do
|
60
|
+
let(:root) { create_tree(:articles) }
|
61
|
+
|
62
|
+
context 'when looking for collections' do
|
63
|
+
let(:steps) { [ :articles ] }
|
64
|
+
it_behaves_like 'an adequate pathfinder'
|
65
|
+
it_behaves_like 'an adequate collection guard'
|
66
|
+
end
|
40
67
|
|
41
|
-
context 'when
|
42
|
-
let(:
|
68
|
+
context 'when looking for members' do
|
69
|
+
let(:steps) { [ :articles, 'xxx' ] }
|
70
|
+
it_behaves_like 'an adequate pathfinder'
|
71
|
+
it_behaves_like 'an adequate member guard'
|
72
|
+
end
|
73
|
+
end
|
43
74
|
|
44
|
-
|
45
|
-
|
46
|
-
|
47
|
-
end
|
75
|
+
context 'when defining nested collections' do
|
76
|
+
let(:root) { create_tree(:articles, :sections) }
|
77
|
+
let(:steps) { [ :articles, 'yyy', :sections ] }
|
48
78
|
|
49
|
-
|
50
|
-
|
51
|
-
|
52
|
-
|
79
|
+
context 'when looking for collections' do
|
80
|
+
let(:steps) { [ :articles, 'xxx', :sections ] }
|
81
|
+
it_behaves_like 'an adequate pathfinder'
|
82
|
+
it_behaves_like 'an adequate collection guard'
|
53
83
|
end
|
54
84
|
|
55
|
-
|
56
|
-
|
57
|
-
|
58
|
-
|
59
|
-
|
60
|
-
|
85
|
+
context 'when looking for members' do
|
86
|
+
let(:steps) { [ :articles, 'xxx', :sections, 'yyy' ] }
|
87
|
+
it_behaves_like 'an adequate pathfinder'
|
88
|
+
it_behaves_like 'an adequate member guard'
|
89
|
+
end
|
90
|
+
end
|
91
|
+
|
92
|
+
only = [ :index, :show ]
|
93
|
+
context "when defining collections restricted to #{ only.join(', ') }" do
|
94
|
+
let(:root) { create_tree([ :articles, only ]) }
|
95
|
+
|
96
|
+
context 'when looking for collections' do
|
97
|
+
let(:steps) { [ :articles ] }
|
98
|
+
it_behaves_like 'an adequate pathfinder'
|
99
|
+
it_behaves_like 'an adequate collection guard', only: only
|
100
|
+
end
|
101
|
+
|
102
|
+
context 'when looking for members' do
|
103
|
+
let(:steps) { [ :articles, 'xxx' ] }
|
104
|
+
it_behaves_like 'an adequate pathfinder'
|
105
|
+
it_behaves_like 'an adequate member guard', only: only
|
106
|
+
end
|
107
|
+
end
|
108
|
+
|
109
|
+
restful_actions.each do |action|
|
110
|
+
context "when defining #{ action } operations" do
|
111
|
+
let(:root) { create_tree(:articles, shred: action) }
|
112
|
+
let(:steps) { [ :articles, 'xxx', :shred ] }
|
113
|
+
|
114
|
+
it_behaves_like 'an adequate pathfinder'
|
115
|
+
end
|
116
|
+
end
|
117
|
+
|
118
|
+
restful_collection_actions.each do |action|
|
119
|
+
context "when defining #{ action } operations with varible names" do
|
120
|
+
let(:root) { create_tree(:articles, ':paragraph' => action) }
|
121
|
+
let(:steps) { [ :articles, 'zzz' ] }
|
122
|
+
|
123
|
+
it_behaves_like 'an adequate pathfinder'
|
124
|
+
end
|
125
|
+
end
|
126
|
+
|
127
|
+
restful_member_actions.each do |action|
|
128
|
+
context "when defining #{ action } operations with varible names" do
|
129
|
+
let(:root) { create_tree(:articles, ':paragraph' => action) }
|
130
|
+
let(:steps) { [ :articles, 'xxx', 'zzz' ] }
|
131
|
+
|
132
|
+
it_behaves_like 'an adequate pathfinder'
|
61
133
|
end
|
62
134
|
end
|
63
135
|
end
|