zero 0.1.0
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.
- data/.gitignore +2 -0
- data/.rspec +3 -0
- data/.travis.yml +8 -0
- data/Gemfile +14 -0
- data/Gemfile.lock +59 -0
- data/Guardfile +15 -0
- data/README.md +60 -0
- data/Thorfile +6 -0
- data/lib/zero.rb +7 -0
- data/lib/zero/controller.rb +46 -0
- data/lib/zero/rack_request.rb +44 -0
- data/lib/zero/renderer.rb +139 -0
- data/lib/zero/request.rb +100 -0
- data/lib/zero/request/accept.rb +28 -0
- data/lib/zero/request/accept_type.rb +58 -0
- data/lib/zero/request/client.rb +31 -0
- data/lib/zero/request/parameter.rb +101 -0
- data/lib/zero/request/server.rb +41 -0
- data/lib/zero/response.rb +80 -0
- data/lib/zero/router.rb +63 -0
- data/lib/zero/version.rb +3 -0
- data/spec/fixtures/templates/index.html.erb +1 -0
- data/spec/fixtures/templates/index.json.erb +1 -0
- data/spec/spec_helper.rb +65 -0
- data/spec/unit/controller/call_spec.rb +22 -0
- data/spec/unit/controller/renderer_spec.rb +11 -0
- data/spec/unit/renderer/read_template_path_spec.rb +53 -0
- data/spec/unit/renderer/render_spec.rb +50 -0
- data/spec/unit/renderer/template_path.rb +8 -0
- data/spec/unit/renderer/type_map_spec.rb +9 -0
- data/spec/unit/request/accept/encoding_spec.rb +9 -0
- data/spec/unit/request/accept/language_spec.rb +9 -0
- data/spec/unit/request/accept/types_spec.rb +9 -0
- data/spec/unit/request/accept_spec.rb +7 -0
- data/spec/unit/request/accepttype/each_spec.rb +10 -0
- data/spec/unit/request/accepttype/preferred_spec.rb +35 -0
- data/spec/unit/request/client/address_spec.rb +9 -0
- data/spec/unit/request/client/hostname_spec.rb +9 -0
- data/spec/unit/request/client/user_agent_spec.rb +9 -0
- data/spec/unit/request/client_spec.rb +8 -0
- data/spec/unit/request/content_type_spec.rb +16 -0
- data/spec/unit/request/create_spec.rb +21 -0
- data/spec/unit/request/delete_spec.rb +15 -0
- data/spec/unit/request/get_spec.rb +15 -0
- data/spec/unit/request/head_spec.rb +15 -0
- data/spec/unit/request/method_spec.rb +8 -0
- data/spec/unit/request/parameter/[]_spec.rb +56 -0
- data/spec/unit/request/parameter/custom_spec.rb +18 -0
- data/spec/unit/request/parameter/initialize_spec.rb +12 -0
- data/spec/unit/request/parameter/payload_spec.rb +33 -0
- data/spec/unit/request/parameter/query_spec.rb +25 -0
- data/spec/unit/request/params_spec.rb +8 -0
- data/spec/unit/request/patch_spec.rb +15 -0
- data/spec/unit/request/path_spec.rb +9 -0
- data/spec/unit/request/post_spec.rb +15 -0
- data/spec/unit/request/put_spec.rb +15 -0
- data/spec/unit/request/server/hostname_spec.rb +9 -0
- data/spec/unit/request/server/port_spec.rb +7 -0
- data/spec/unit/request/server/protocol_spec.rb +9 -0
- data/spec/unit/request/server/software_spec.rb +9 -0
- data/spec/unit/request/server_spec.rb +8 -0
- data/spec/unit/response/response_spec.rb +146 -0
- data/spec/unit/router/call_spec.rb +55 -0
- data/zero.gemspec +27 -0
- metadata +345 -0
@@ -0,0 +1,22 @@
|
|
1
|
+
require 'spec_helper'
|
2
|
+
|
3
|
+
describe Zero::Controller, '.call' do
|
4
|
+
subject { SpecController.call(env) }
|
5
|
+
let(:env) { EnvGenerator.get('/foo') }
|
6
|
+
|
7
|
+
it "returns a response" do
|
8
|
+
subject.should be_respond_to(:to_a)
|
9
|
+
end
|
10
|
+
|
11
|
+
it "returns an object with the first element being a status" do
|
12
|
+
subject[0].should be_kind_of(Numeric)
|
13
|
+
end
|
14
|
+
|
15
|
+
it "does not modify an existing request" do
|
16
|
+
r = Zero::Request.new(env)
|
17
|
+
r.params['foo'] = 'bar'
|
18
|
+
subject
|
19
|
+
r = Zero::Request.create(env)
|
20
|
+
expect(r.params['foo']).to eq('bar')
|
21
|
+
end
|
22
|
+
end
|
@@ -0,0 +1,11 @@
|
|
1
|
+
require 'spec_helper'
|
2
|
+
|
3
|
+
describe Zero::Controller, '#renderer' do
|
4
|
+
subject { Zero::Controller }
|
5
|
+
let(:renderer) { Object.new }
|
6
|
+
|
7
|
+
it 'returns the set renderer' do
|
8
|
+
subject.renderer = renderer
|
9
|
+
expect(subject.new(Object.new).renderer).to be(renderer)
|
10
|
+
end
|
11
|
+
end
|
@@ -0,0 +1,53 @@
|
|
1
|
+
require 'spec_helper'
|
2
|
+
|
3
|
+
describe Zero::Renderer, 'read_template_path!' do
|
4
|
+
subject { Zero::Renderer.new(template_path, type_map) }
|
5
|
+
let(:template_path) { 'foo' }
|
6
|
+
let(:file_list) { ['foo/welcome/index.html.erb'] }
|
7
|
+
|
8
|
+
before :each do
|
9
|
+
subject.stub(:search_files).and_return(file_list)
|
10
|
+
end
|
11
|
+
|
12
|
+
shared_examples_for 'a template loader' do
|
13
|
+
it 'creates a template tree' do
|
14
|
+
subject.read_template_path!
|
15
|
+
subject.templates['welcome/index'].should eq(result)
|
16
|
+
end
|
17
|
+
end
|
18
|
+
|
19
|
+
context 'without mapping' do
|
20
|
+
let(:type_map) { {} }
|
21
|
+
let(:result) { { 'html' => 'foo/welcome/index.html.erb' } }
|
22
|
+
|
23
|
+
it_behaves_like 'a template loader'
|
24
|
+
end
|
25
|
+
|
26
|
+
context 'with a single mapping' do
|
27
|
+
let(:type_map) { {'html' => 'text/html' } }
|
28
|
+
let(:result) { { 'text/html' => 'foo/welcome/index.html.erb' } }
|
29
|
+
|
30
|
+
it_behaves_like 'a template loader'
|
31
|
+
end
|
32
|
+
|
33
|
+
context 'with multiple mappings' do
|
34
|
+
let(:type_map) { {'html' => ['text/html', 'text/xml'] } }
|
35
|
+
let(:result) { {
|
36
|
+
'text/html' => 'foo/welcome/index.html.erb',
|
37
|
+
'text/xml' => 'foo/welcome/index.html.erb'
|
38
|
+
} }
|
39
|
+
|
40
|
+
it_behaves_like 'a template loader'
|
41
|
+
end
|
42
|
+
|
43
|
+
context 'with default template' do
|
44
|
+
let(:file_list) {['foo/welcome/index.erb']}
|
45
|
+
let(:type_map) { {'default' => ['text/html', 'text/xml'] } }
|
46
|
+
let(:result) { {
|
47
|
+
'text/html' => 'foo/welcome/index.erb',
|
48
|
+
'text/xml' => 'foo/welcome/index.erb'
|
49
|
+
} }
|
50
|
+
|
51
|
+
it_behaves_like 'a template loader'
|
52
|
+
end
|
53
|
+
end
|
@@ -0,0 +1,50 @@
|
|
1
|
+
require 'spec_helper'
|
2
|
+
|
3
|
+
describe Zero::Renderer, '#render' do
|
4
|
+
subject { Zero::Renderer.new(template_path, type_map) }
|
5
|
+
let(:template_path) { 'spec/fixtures/templates' }
|
6
|
+
let(:file_list) { ['./foo/welcome/index.html.erb'] }
|
7
|
+
let(:type_map) {{
|
8
|
+
'html' => ['text/html', 'text/xml', '*/*'],
|
9
|
+
'json' => ['application/json', 'plain/text']
|
10
|
+
}}
|
11
|
+
let(:html_types) { ['text/html'] }
|
12
|
+
let(:json_types) { ['application/json'] }
|
13
|
+
let(:foo_types) { ['foo/bar', 'bar/foo'] }
|
14
|
+
let(:binding) { SpecTemplateContext.new('foo') }
|
15
|
+
|
16
|
+
before :each do
|
17
|
+
subject.read_template_path!
|
18
|
+
end
|
19
|
+
|
20
|
+
it 'returns a tilt template' do
|
21
|
+
subject.render('index', html_types, binding).should be_kind_of(String)
|
22
|
+
end
|
23
|
+
|
24
|
+
it 'renders html content' do
|
25
|
+
subject.render('index', html_types, binding).should match('success')
|
26
|
+
end
|
27
|
+
|
28
|
+
it 'returns a tilt template for different types' do
|
29
|
+
subject.render('index', json_types, binding).should be_kind_of(String)
|
30
|
+
end
|
31
|
+
|
32
|
+
it 'renders json content' do
|
33
|
+
subject.render('index', json_types, binding).should match("{text: 'success'}")
|
34
|
+
end
|
35
|
+
|
36
|
+
it 'returns an ArgumentError, if given template does not exist' do
|
37
|
+
expect {
|
38
|
+
subject.render('foobar', html_types, binding)
|
39
|
+
}.to raise_error(ArgumentError, "No template found for 'foobar'!")
|
40
|
+
end
|
41
|
+
|
42
|
+
it 'returns an ArgumentError, if no template fits types' do
|
43
|
+
expect {
|
44
|
+
subject.render('index', foo_types, binding)
|
45
|
+
}.to raise_error(
|
46
|
+
ArgumentError,
|
47
|
+
"No template found for any of this types #{foo_types.join ', '}!"
|
48
|
+
)
|
49
|
+
end
|
50
|
+
end
|
@@ -0,0 +1,9 @@
|
|
1
|
+
require 'spec_helper'
|
2
|
+
|
3
|
+
describe Zero::Request::Accept, '#encoding' do
|
4
|
+
subject { Zero::Request::Accept.new(env) }
|
5
|
+
let(:encoding) { 'en_US' }
|
6
|
+
let(:env) { EnvGenerator.get('/foo', {'HTTP_ACCEPT_ENCODING' => encoding}) }
|
7
|
+
|
8
|
+
its(:encoding) { should be_an_instance_of(Zero::Request::AcceptType) }
|
9
|
+
end
|
@@ -0,0 +1,9 @@
|
|
1
|
+
require 'spec_helper'
|
2
|
+
|
3
|
+
describe Zero::Request::Accept, '#language' do
|
4
|
+
subject { Zero::Request::Accept.new(env) }
|
5
|
+
let(:language) { 'en_US' }
|
6
|
+
let(:env) { EnvGenerator.get('/foo', {'HTTP_ACCEPT_LANGUAGE' => language}) }
|
7
|
+
|
8
|
+
its(:language) { should be_an_instance_of(Zero::Request::AcceptType) }
|
9
|
+
end
|
@@ -0,0 +1,9 @@
|
|
1
|
+
require 'spec_helper'
|
2
|
+
|
3
|
+
describe Zero::Request::Accept, '#types' do
|
4
|
+
subject { Zero::Request::Accept.new(env) }
|
5
|
+
let(:media_types) { 'text/html' }
|
6
|
+
let(:env) { EnvGenerator.get('/foo', {'HTTP_ACCEPT' => media_types}) }
|
7
|
+
|
8
|
+
its(:types) { should be_an_instance_of(Zero::Request::AcceptType) }
|
9
|
+
end
|
@@ -0,0 +1,10 @@
|
|
1
|
+
require 'spec_helper'
|
2
|
+
|
3
|
+
describe Zero::Request::AcceptType, '#each' do
|
4
|
+
subject { Zero::Request::AcceptType.new(types) }
|
5
|
+
let(:html) { 'text/html' }
|
6
|
+
let(:json) { 'application/json' }
|
7
|
+
let(:types) { [html, json].join(',') }
|
8
|
+
|
9
|
+
specify { expect {|b| subject.each(&b) }.to yield_successive_args(html, json) }
|
10
|
+
end
|
@@ -0,0 +1,35 @@
|
|
1
|
+
require 'spec_helper'
|
2
|
+
|
3
|
+
describe Zero::Request::AcceptType, '#preferred' do
|
4
|
+
subject { Zero::Request::AcceptType }
|
5
|
+
let(:html) { 'text/html' }
|
6
|
+
let(:json) { 'application/json' }
|
7
|
+
let(:foo) { 'text/foo' }
|
8
|
+
let(:lower_quality) { foo + ';q=0.5' }
|
9
|
+
let(:default) { '*/*;q=0.1' }
|
10
|
+
let(:simple_accept) { [html, json].join(',') }
|
11
|
+
let(:quality_accept) { [html, lower_quality, default].join(',') }
|
12
|
+
let(:random_accept) { [lower_quality, default, html].join(',') }
|
13
|
+
let(:lower_accept) { [lower_quality, default].join(',') }
|
14
|
+
|
15
|
+
context 'without mapping' do
|
16
|
+
it { subject.new(html).preferred.should == html }
|
17
|
+
it { subject.new(json).preferred.should == json }
|
18
|
+
it { subject.new(simple_accept).preferred.should == html }
|
19
|
+
it { subject.new(quality_accept).preferred.should == html }
|
20
|
+
it { subject.new(random_accept).preferred.should == html }
|
21
|
+
it { subject.new(lower_accept).preferred.should == foo }
|
22
|
+
end
|
23
|
+
|
24
|
+
# context 'with mapping' do
|
25
|
+
# before :all do
|
26
|
+
# Zero::Request::Accept.map = {'text/html' => 'html'}
|
27
|
+
# end
|
28
|
+
#
|
29
|
+
# after :all do
|
30
|
+
# Zero::Request::Accept.map = {}
|
31
|
+
# end
|
32
|
+
#
|
33
|
+
# it { subject.new(html).preferred.should == 'html' }
|
34
|
+
# end
|
35
|
+
end
|
@@ -0,0 +1,9 @@
|
|
1
|
+
require 'spec_helper'
|
2
|
+
|
3
|
+
describe Zero::Request::Client, '#user_agent' do
|
4
|
+
subject { Zero::Request::Client.new(env) }
|
5
|
+
let(:user_agent) { 'Mozilla (dummy agent)' }
|
6
|
+
let(:env) { {'HTTP_USER_AGENT' => user_agent} }
|
7
|
+
|
8
|
+
its(:user_agent) { should == user_agent }
|
9
|
+
end
|
@@ -0,0 +1,16 @@
|
|
1
|
+
require 'spec_helper'
|
2
|
+
|
3
|
+
describe Zero::Request, '#content_type' do
|
4
|
+
subject { Zero::Request.new(env) }
|
5
|
+
|
6
|
+
context 'returns nil with no content type' do
|
7
|
+
let(:env) { EnvGenerator.get('/foo') }
|
8
|
+
its('content_type') { should be(nil) }
|
9
|
+
end
|
10
|
+
|
11
|
+
context 'returns the set content type' do
|
12
|
+
let(:content_type) { 'bogus/type' }
|
13
|
+
let(:env) { EnvGenerator.post('/foo', {'CONTENT_TYPE' => content_type}) }
|
14
|
+
its('content_type') { should be(content_type) }
|
15
|
+
end
|
16
|
+
end
|
@@ -0,0 +1,21 @@
|
|
1
|
+
require 'spec_helper'
|
2
|
+
|
3
|
+
describe Zero::Request, '.create' do
|
4
|
+
subject { Zero::Request.new(env) }
|
5
|
+
|
6
|
+
context "with a fresh environment" do
|
7
|
+
let(:env) { EnvGenerator.get('/foo') }
|
8
|
+
it "creates an instance of Zero::Request" do
|
9
|
+
Zero::Request.create(env).should be_an_instance_of(Zero::Request)
|
10
|
+
end
|
11
|
+
end
|
12
|
+
|
13
|
+
context "with an already used environment" do
|
14
|
+
let(:env) { EnvGenerator.get('/foo') }
|
15
|
+
let(:new_env) { subject.env }
|
16
|
+
|
17
|
+
it "returns an already build request" do
|
18
|
+
Zero::Request.create(new_env).should be(subject)
|
19
|
+
end
|
20
|
+
end
|
21
|
+
end
|
@@ -0,0 +1,15 @@
|
|
1
|
+
require 'spec_helper'
|
2
|
+
|
3
|
+
describe Zero::Request, '#delete?' do
|
4
|
+
subject { Zero::Request.new(env) }
|
5
|
+
|
6
|
+
context "with a delete request" do
|
7
|
+
let(:env) { EnvGenerator.delete('/foo') }
|
8
|
+
its(:delete?) { should be(true) }
|
9
|
+
end
|
10
|
+
|
11
|
+
context "with a get request" do
|
12
|
+
let(:env) { EnvGenerator.get('/foo') }
|
13
|
+
its(:delete?) { should be(false) }
|
14
|
+
end
|
15
|
+
end
|
@@ -0,0 +1,15 @@
|
|
1
|
+
require 'spec_helper'
|
2
|
+
|
3
|
+
describe Zero::Request, '#get?' do
|
4
|
+
subject { Zero::Request.new(env) }
|
5
|
+
|
6
|
+
context "with a get request" do
|
7
|
+
let(:env) { EnvGenerator.get('/foo') }
|
8
|
+
its(:get?) { should be(true) }
|
9
|
+
end
|
10
|
+
|
11
|
+
context "with a post request" do
|
12
|
+
let(:env) { EnvGenerator.post('/foo') }
|
13
|
+
its(:get?) { should be(false) }
|
14
|
+
end
|
15
|
+
end
|
@@ -0,0 +1,15 @@
|
|
1
|
+
require 'spec_helper'
|
2
|
+
|
3
|
+
describe Zero::Request, '#head?' do
|
4
|
+
subject { Zero::Request.new(env) }
|
5
|
+
|
6
|
+
context "with a head request" do
|
7
|
+
let(:env) { EnvGenerator.head('/foo') }
|
8
|
+
its(:head?) { should be(true) }
|
9
|
+
end
|
10
|
+
|
11
|
+
context "with a get request" do
|
12
|
+
let(:env) { EnvGenerator.get('/foo') }
|
13
|
+
its(:head?) { should be(false) }
|
14
|
+
end
|
15
|
+
end
|
@@ -0,0 +1,56 @@
|
|
1
|
+
require 'spec_helper'
|
2
|
+
|
3
|
+
describe Zero::Request::Parameter, '#[]' do
|
4
|
+
subject { Zero::Request::Parameter.new(env) }
|
5
|
+
|
6
|
+
context 'without parameters' do
|
7
|
+
let(:env) { EnvGenerator.get('/foo') }
|
8
|
+
|
9
|
+
it 'returns the custom parameter' do
|
10
|
+
subject['foo'] = 'bar'
|
11
|
+
expect(subject['foo']).to eq('bar')
|
12
|
+
end
|
13
|
+
end
|
14
|
+
|
15
|
+
context 'with query parameters' do
|
16
|
+
let(:env) { EnvGenerator.get('/foo?foo=bar') }
|
17
|
+
|
18
|
+
it 'returns the query parameter' do
|
19
|
+
expect(subject['foo']).to eq('bar')
|
20
|
+
end
|
21
|
+
|
22
|
+
it 'returns the custom parameter' do
|
23
|
+
subject['foo'] = 'baz'
|
24
|
+
expect(subject['foo']).to eq('baz')
|
25
|
+
end
|
26
|
+
end
|
27
|
+
|
28
|
+
context 'with payload parameters' do
|
29
|
+
let(:env) do
|
30
|
+
EnvGenerator.post('/foo', {
|
31
|
+
:input => 'foo=bar', 'CONTENT_TYPE' => 'multipart/form-data'
|
32
|
+
})
|
33
|
+
end
|
34
|
+
|
35
|
+
it 'returns the payload value' do
|
36
|
+
expect(subject['foo']).to eq('bar')
|
37
|
+
end
|
38
|
+
|
39
|
+
it 'returns the custom parameter' do
|
40
|
+
subject['foo'] = 'baz'
|
41
|
+
expect(subject['foo']).to eq('baz')
|
42
|
+
end
|
43
|
+
end
|
44
|
+
|
45
|
+
context 'with query and payload parameters' do
|
46
|
+
let(:env) do
|
47
|
+
EnvGenerator.post('/foo?foo=baz', {
|
48
|
+
:input => 'foo=bar', 'CONTENT_TYPE' => 'multipart/form-data'
|
49
|
+
})
|
50
|
+
end
|
51
|
+
|
52
|
+
it 'returns the payload parameter' do
|
53
|
+
expect(subject['foo']).to eq('bar')
|
54
|
+
end
|
55
|
+
end
|
56
|
+
end
|