sinatra-unit 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/.gemtest ADDED
File without changes
data/History.txt ADDED
@@ -0,0 +1,6 @@
1
+ === 0.1.0 / 2013-01-14
2
+
3
+ * 1 major enhancement
4
+
5
+ * Birthday!
6
+
data/Manifest.txt ADDED
@@ -0,0 +1,5 @@
1
+ History.txt
2
+ Manifest.txt
3
+ README.txt
4
+ Rakefile
5
+ lib/sinatra/unit.rb
data/README.txt ADDED
@@ -0,0 +1,84 @@
1
+ # sinatra-unit
2
+
3
+ * http://github.com/snarfmason/sinatra-unit
4
+
5
+ Testing harness for Sinatra to make proper unit tests/specs for actions.
6
+
7
+ Description
8
+ -----------
9
+
10
+ The idea is to instantiate your Sintra class and then execute the web request blocks on the instance
11
+ that you have created. It uses the `test_request` method (and shortcuts like `test_get`, `test_put`, etc)
12
+ to look up the block using the same route matching logic that Sinatra would use when receiving a request
13
+ from Rack.
14
+
15
+ Usage
16
+ -----
17
+
18
+ Basic usage:
19
+
20
+ @app = WebApp.new
21
+ response_body = @app.test_request(:get, '/')
22
+
23
+ of course you can do, params:
24
+
25
+ response_body = @app.test_request(:get, '/hi', :qsname => 'jon')
26
+
27
+ you can set the environment or session (if enabled) with a hash, before a request
28
+
29
+ @app.env = { :test => 'hello' }
30
+ @app.session = { :test => 'hello' }
31
+ response_body = @app.test_get '/showsession'
32
+
33
+ Currently the text of the response is returned from the `test_request` method. If you need access to headers or HTTP status you use the `response` object.
34
+
35
+ @app.response.status
36
+ @app.response.header['Content-Type']
37
+
38
+
39
+ Writing Tests
40
+ -------------
41
+
42
+ basic good route:
43
+
44
+ response_body = @app.test_request(:get, '/')
45
+ assert_equal "hello world", response_body
46
+ assert_equal 200, @app.response.status
47
+ assert_equal 'text/html', @app.response.header['Content-Type']
48
+
49
+ basic bad route:
50
+
51
+ assert_raise Sinatra::Unit::UnknownRouteError do
52
+ @app.test_get '/wrongroute'
53
+ end
54
+
55
+ basic redirect:
56
+
57
+ @app.test_get '/redirect'
58
+ assert @app.redirect?
59
+ assert_equal 302, @app.response.status
60
+
61
+ you can retrieve instance variables set in request blocks
62
+
63
+ # app
64
+ get '/showobject' do
65
+ @object = OpenStruct.new :foo => 1, :bar => 2, :baz => 3
66
+ "foo=#{@object.foo}&bar=#{@object.bar}&baz=#{@object.baz}"
67
+ end
68
+
69
+ # test
70
+ response_body = @app.test_get '/showobject'
71
+ assert_equal 'foo=1&bar=2&baz=3', response_body
72
+ assert_equal 1, @app.variables("object").foo
73
+
74
+ you can assert against session values
75
+
76
+ # app
77
+ post '/setsession' do
78
+ session[:test] = params[:test]
79
+ end
80
+
81
+ # test
82
+ assert_nil @app.session[:test]
83
+ @app.test_post '/setsession', :test => 'goodbye'
84
+ assert_equal 'goodbye', @app.session[:test]
data/Rakefile ADDED
@@ -0,0 +1,17 @@
1
+ # -*- ruby -*-
2
+
3
+ require "rubygems"
4
+ require "hoe"
5
+
6
+ Hoe.plugin :isolate
7
+ # Hoe.plugin :rubyforge
8
+
9
+ Hoe.spec "sinatra-unit" do
10
+ dependency 'sinatra', '~> 1.3.3'
11
+
12
+ developer "Jonathan Mason", "jonathan.e.mason@gmail.com"
13
+
14
+ license "MIT"
15
+ end
16
+
17
+ # vim: syntax=ruby
@@ -0,0 +1,104 @@
1
+ require 'ostruct'
2
+
3
+ module Sinatra
4
+ class Unit
5
+ VERSION = '0.1.0'
6
+
7
+ class UnknownRouteError < StandardError
8
+ attr_accessor :method, :path, :params
9
+ def initialize(method, path, params)
10
+ self.method, self.path, self.params = method, path, params
11
+ message = "Could not resovle route #{method} #{path} with params #{params.inspect}"
12
+ super message
13
+ end
14
+ end
15
+
16
+ class SessionsDisabledError < StandardError ; end
17
+ end
18
+
19
+ class Base
20
+ def test_sessions_enabled?
21
+ return true if self.class.sessions?
22
+
23
+ used_middleware = self.class.instance_variable_get "@middleware"
24
+ used_middleware.each do |middleware|
25
+ return true if middleware.first == Rack::Session::Cookie
26
+ end
27
+
28
+ return false
29
+ end
30
+
31
+ # Normal sinatra session method just returns request.session which passes
32
+ # through to env['rack.session'] but I don't initialize the request object
33
+ # until just before the route lookkup, so I need to skip directly to env.
34
+ def session
35
+ raise Sinatra::Unit::SessionsDisabledError unless test_sessions_enabled?
36
+ env['rack.session'] ||= {}
37
+ end
38
+
39
+ # This doesn't exist in regular sinatra, but it's convenient for some tests
40
+ def session=(session)
41
+ raise Sinatra::Unit::SessionsDisabledError unless test_sessions_enabled?
42
+ env['rack.session'] = session
43
+ end
44
+
45
+ # test_request comes mostly from the guts of route! in Sinatra::Base
46
+ def test_request(method, path, params={})
47
+ @params = indifferent_params(params)
48
+
49
+ @request = Sinatra::Request.new(env)
50
+ @request.path_info = path # sinatra 1.3.3
51
+
52
+ @__protected_ivars = instance_variables + ["@__protected_ivars"]
53
+
54
+ # routes are stored by uppercase method, but I wanted the test interface
55
+ # to accept :get or 'get' as well as 'GET'
56
+ test_request_internal self.class, method.to_s.upcase
57
+ end
58
+
59
+ def variables(name)
60
+ name = "@#{name.to_s}"
61
+ instance_variable_get(name) unless @__protected_ivars.include?(name)
62
+ end
63
+
64
+ # expects @request and @params to be set
65
+ # Don't call this directly, but I don't believe in private methods
66
+ def test_request_internal(route_holder, method)
67
+ raise Sinatra::Unit::UnknownRouteError.new(method,@request.path_info,@params) unless route_holder.respond_to?(:routes)
68
+
69
+ if route_holder.routes.has_key? method
70
+ routes = route_holder.routes[method]
71
+ routes.each do |pattern, keys, conditions, block|
72
+ process_route(pattern, keys, conditions) do |*args|
73
+ return catch(:halt) { block[*args] }
74
+ end
75
+ end
76
+ end
77
+
78
+ test_request_internal(route_holder.superclass, method)
79
+ end
80
+
81
+ %w(get post put delete head).each do |method|
82
+ eval <<-CODE
83
+ def test_#{method}(path, params={})
84
+ test_request('#{method}', path, params)
85
+ end
86
+ CODE
87
+ end
88
+
89
+ # Sinatra makes new do a bunch of stuff with rack middleware wrappers
90
+ # that are useful if you're actually running the app, but provides
91
+ # new! for regular instantiation. I'm just re-standardizing names
92
+ class << self
93
+ alias new_with_rack_wrappers new
94
+ end
95
+
96
+ def self.new
97
+ app = new!
98
+ app.env ||= {}
99
+ app.response = Sinatra::Response.new
100
+ app
101
+ end
102
+
103
+ end
104
+ end
@@ -0,0 +1,26 @@
1
+ require 'no_sessions_app'
2
+ require 'sinatra/unit'
3
+
4
+ require 'test/unit'
5
+
6
+ class TestNoSessionsApp < Test::Unit::TestCase
7
+ def setup
8
+ @app = NoSessionsApp.new
9
+ end
10
+
11
+ def test_session_show
12
+ assert_raises Sinatra::Unit::SessionsDisabledError do
13
+ @app.session = { :test => 'hello' }
14
+ response_body = @app.test_get '/showsession'
15
+ assert_equal 'session[test] hello', response_body
16
+ end
17
+ end
18
+
19
+ def test_session_set
20
+ assert_raises Sinatra::Unit::SessionsDisabledError do
21
+ assert_nil @app.session[:test]
22
+ @app.test_post '/setsession', :test => 'goodbye'
23
+ assert_equal 'goodbye', @app.session[:test]
24
+ end
25
+ end
26
+ end
@@ -0,0 +1,22 @@
1
+ require 'rack_sessions_app'
2
+ require 'sinatra/unit'
3
+
4
+ require 'test/unit'
5
+
6
+ class TestRackSessionsApp < Test::Unit::TestCase
7
+ def setup
8
+ @app = RackSessionsApp.new
9
+ end
10
+
11
+ def test_session_show
12
+ @app.session = { :test => 'hello' }
13
+ response_body = @app.test_get '/showsession'
14
+ assert_equal 'session[test] hello', response_body
15
+ end
16
+
17
+ def test_session_set
18
+ assert_nil @app.session[:test]
19
+ @app.test_post '/setsession', :test => 'goodbye'
20
+ assert_equal 'goodbye', @app.session[:test]
21
+ end
22
+ end
@@ -0,0 +1,21 @@
1
+ require 'web_app'
2
+ require 'sinatra/unit'
3
+ require 'test/unit'
4
+
5
+ class TestUnknownRouteError < Test::Unit::TestCase
6
+ def test_unknown_route_exception_details
7
+ error = nil
8
+ begin
9
+ WebApp.new.test_get '/wrongroute', :wrong_param => 'foobar'
10
+ rescue => e
11
+ error = e
12
+ end
13
+
14
+ assert_not_nil error
15
+ assert_equal 'GET', error.method
16
+ assert_equal '/wrongroute', error.path
17
+ assert_equal 'foobar', error.params[:wrong_param]
18
+ assert_match %r{GET.*/wrongroute.*wrong_param.*foobar}, error.message
19
+ end
20
+ end
21
+
@@ -0,0 +1,105 @@
1
+ require 'web_app'
2
+ require 'sinatra/unit'
3
+
4
+ require 'test/unit'
5
+
6
+ class TestWebApp < Test::Unit::TestCase
7
+ def setup
8
+ @app = WebApp.new
9
+ end
10
+
11
+ def test_returns_hello_world_on_index
12
+ response_body = @app.test_request(:get, '/')
13
+ assert_equal "hello world", response_body
14
+ assert_equal 200, @app.response.status
15
+ assert_equal 'text/html', @app.response.header['Content-Type']
16
+ end
17
+
18
+ def test_returns_goodbye_on_bye
19
+ response_body = @app.test_request(:get, '/bye')
20
+ assert_equal "goodbye", response_body
21
+ end
22
+
23
+ def test_has_hello_name
24
+ response_body = @app.test_request(:get, '/hello/jon')
25
+ assert_equal "hello jon", response_body
26
+ end
27
+
28
+ def test_returns_for_hi_with_param
29
+ response_body = @app.test_request(:get, '/hi', :qsname => 'jon')
30
+ assert_equal "hi jon", response_body
31
+ end
32
+
33
+ def test_work_with_get_wrapped_method
34
+ response_body = @app.test_get '/'
35
+ assert_equal "hello world", response_body
36
+ end
37
+
38
+ def test_raises_an_exception_for_unknown_route
39
+ assert_raise Sinatra::Unit::UnknownRouteError do
40
+ @app.test_get '/wrongroute'
41
+ end
42
+ end
43
+
44
+ def test_works_with_post_data
45
+ response_body = @app.test_post '/goodnight', :name => 'jon'
46
+ assert_equal 'post goodnight jon', response_body
47
+ end
48
+
49
+ def test_works_with_pu
50
+ response_body = @app.test_put '/goodnight', :name => 'jon'
51
+ assert_equal 'put goodnight jon', response_body
52
+ end
53
+
54
+ def test_works_with_env
55
+ @app.env = { :test => 'hello' }
56
+ response_body = @app.test_post '/showenv'
57
+ assert_equal 'env[test] hello', response_body
58
+ end
59
+
60
+ def test_session_show
61
+ @app.session = { :test => 'hello' }
62
+ response_body = @app.test_get '/showsession'
63
+ assert_equal 'session[test] hello', response_body
64
+ end
65
+
66
+ def test_session_set
67
+ assert_nil @app.session[:test]
68
+ @app.test_post '/setsession', :test => 'goodbye'
69
+ assert_equal 'goodbye', @app.session[:test]
70
+ end
71
+
72
+ def test_instance_variable_retrieval
73
+ response_body = @app.test_get '/showobject'
74
+ assert_equal 'foo=1&bar=2&baz=3', response_body
75
+ assert_equal 1, @app.variables("object").foo
76
+ end
77
+
78
+ def test_only_retrieve_instance_variables_set_in_the_block
79
+ response_body = @app.test_get '/showobject'
80
+ assert_nil @app.variables("template_cache")
81
+ end
82
+
83
+ def test_do_not_retrieve_protected_instance_variables
84
+ response_body = @app.test_get '/showobject'
85
+ assert_nil @app.variables("__protected_ivars")
86
+ end
87
+
88
+ def test_redirect_to_index
89
+ @app.test_get '/redirect'
90
+ assert @app.redirect?
91
+ assert_equal 302, @app.response.status
92
+ end
93
+
94
+ def test_two_requests
95
+ response_body = @app.test_request(:get, '/')
96
+ assert_equal "hello world", response_body
97
+ assert_equal 200, @app.response.status
98
+ assert_equal 'text/html', @app.response.header['Content-Type']
99
+
100
+ @app.test_get '/redirect'
101
+ assert @app.redirect?
102
+ assert_equal 302, @app.response.status
103
+ end
104
+
105
+ end
metadata ADDED
@@ -0,0 +1,126 @@
1
+ --- !ruby/object:Gem::Specification
2
+ name: sinatra-unit
3
+ version: !ruby/object:Gem::Version
4
+ hash: 27
5
+ prerelease:
6
+ segments:
7
+ - 0
8
+ - 1
9
+ - 0
10
+ version: 0.1.0
11
+ platform: ruby
12
+ authors:
13
+ - Jonathan Mason
14
+ autorequire:
15
+ bindir: bin
16
+ cert_chain: []
17
+
18
+ date: 2013-04-26 00:00:00 Z
19
+ dependencies:
20
+ - !ruby/object:Gem::Dependency
21
+ name: sinatra
22
+ prerelease: false
23
+ requirement: &id001 !ruby/object:Gem::Requirement
24
+ none: false
25
+ requirements:
26
+ - - ~>
27
+ - !ruby/object:Gem::Version
28
+ hash: 29
29
+ segments:
30
+ - 1
31
+ - 3
32
+ - 3
33
+ version: 1.3.3
34
+ type: :runtime
35
+ version_requirements: *id001
36
+ - !ruby/object:Gem::Dependency
37
+ name: rdoc
38
+ prerelease: false
39
+ requirement: &id002 !ruby/object:Gem::Requirement
40
+ none: false
41
+ requirements:
42
+ - - ~>
43
+ - !ruby/object:Gem::Version
44
+ hash: 19
45
+ segments:
46
+ - 3
47
+ - 10
48
+ version: "3.10"
49
+ type: :development
50
+ version_requirements: *id002
51
+ - !ruby/object:Gem::Dependency
52
+ name: hoe
53
+ prerelease: false
54
+ requirement: &id003 !ruby/object:Gem::Requirement
55
+ none: false
56
+ requirements:
57
+ - - ~>
58
+ - !ruby/object:Gem::Version
59
+ hash: 13
60
+ segments:
61
+ - 3
62
+ - 5
63
+ version: "3.5"
64
+ type: :development
65
+ version_requirements: *id003
66
+ description: ""
67
+ email:
68
+ - jonathan.e.mason@gmail.com
69
+ executables: []
70
+
71
+ extensions: []
72
+
73
+ extra_rdoc_files:
74
+ - History.txt
75
+ - Manifest.txt
76
+ - README.txt
77
+ files:
78
+ - History.txt
79
+ - Manifest.txt
80
+ - README.txt
81
+ - Rakefile
82
+ - lib/sinatra/unit.rb
83
+ - test/unit/test_no_sessions_app.rb
84
+ - test/unit/test_rack_session_app.rb
85
+ - test/unit/test_unknown_route_error.rb
86
+ - test/unit/test_web_app.rb
87
+ - .gemtest
88
+ homepage: http://github.com/snarfmason/sinatra-unit
89
+ licenses:
90
+ - MIT
91
+ post_install_message:
92
+ rdoc_options:
93
+ - --main
94
+ - README.txt
95
+ require_paths:
96
+ - lib
97
+ required_ruby_version: !ruby/object:Gem::Requirement
98
+ none: false
99
+ requirements:
100
+ - - ">="
101
+ - !ruby/object:Gem::Version
102
+ hash: 3
103
+ segments:
104
+ - 0
105
+ version: "0"
106
+ required_rubygems_version: !ruby/object:Gem::Requirement
107
+ none: false
108
+ requirements:
109
+ - - ">="
110
+ - !ruby/object:Gem::Version
111
+ hash: 3
112
+ segments:
113
+ - 0
114
+ version: "0"
115
+ requirements: []
116
+
117
+ rubyforge_project: sinatra-unit
118
+ rubygems_version: 1.8.25
119
+ signing_key:
120
+ specification_version: 3
121
+ summary: ""
122
+ test_files:
123
+ - test/unit/test_no_sessions_app.rb
124
+ - test/unit/test_rack_session_app.rb
125
+ - test/unit/test_unknown_route_error.rb
126
+ - test/unit/test_web_app.rb