webmachine-test 0.1.0

Sign up to get free protection for your applications and to get access to all the features.
data/Gemfile ADDED
@@ -0,0 +1,6 @@
1
+ source :rubygems
2
+
3
+ gem 'rake'
4
+ gem 'rspec'
5
+ gem 'ZenTest'
6
+ gem 'webmachine', :git => 'https://github.com/seancribbs/webmachine-ruby'
data/README.md ADDED
@@ -0,0 +1,100 @@
1
+ # Webmachine::Test
2
+
3
+ [![travis](https://secure.travis-ci.org/bernd/webmachine-test.png)](http://travis-ci.org/bernd/webmachine-test)
4
+
5
+ ## WARNING
6
+
7
+ This library is still under development and incomplete!
8
+
9
+ It will be merged into [webmachine-ruby](https://github.com/seancribbs/webmachine-ruby)
10
+ when it's ready.
11
+
12
+ ## Description
13
+
14
+ Webmachine::Test provides a testing API for
15
+ [webmachine-ruby](https://github.com/seancribbs/webmachine-ruby) inspired by
16
+ [rack-test](https://github.com/brynary/rack-test).
17
+
18
+ ## Example Usage
19
+
20
+ ### Application
21
+
22
+ ```ruby
23
+ require 'webmachine'
24
+
25
+ class MyResource < Webmachine::Resource
26
+ def content_types_provided
27
+ [['text/plain', :to_text]]
28
+ end
29
+
30
+ def to_text
31
+ 'OK'
32
+ end
33
+ end
34
+
35
+ MyApp = Webmachine::Application.new.tap do |app|
36
+ app.add_route(['*'], MyResource)
37
+ end
38
+
39
+ # decouple runner from application so that adapter
40
+ # does not start and block test thread
41
+ #
42
+ # MyApp.run
43
+ ```
44
+
45
+ ### Test with Test::Unit
46
+
47
+ ```ruby
48
+ class MyAppTest < Test::Unit::TestCase
49
+ include Webmachine::Test
50
+
51
+ def test_get_root_succeeds
52
+ get '/'
53
+ assert_equal 200, response.code
54
+ end
55
+
56
+ def test_get_root_replies_with_string_ok
57
+ get '/'
58
+ assert_equal 'OK', response.body
59
+ end
60
+
61
+ def test_get_root_replies_with_content_type_of_text_plain
62
+ get '/'
63
+ assert_equal 'text/plain', response.headers['Content-Type']
64
+ end
65
+
66
+ def app
67
+ MyApp
68
+ end
69
+ end
70
+ ```
71
+
72
+ ### Test with RSpec
73
+
74
+ ```ruby
75
+ require 'webmachine/test'
76
+ require 'myapp'
77
+
78
+ describe MyApp do
79
+ include Webmachine::Test
80
+
81
+ let(:app) { MyApp }
82
+
83
+ describe 'GET /' do
84
+ it 'succeeds' do
85
+ get '/'
86
+ response.code.should == 200
87
+ end
88
+
89
+ it 'replies with the string OK' do
90
+ get '/'
91
+ response.body.should == 'OK'
92
+ end
93
+
94
+ it 'replies with a content type of text/plain' do
95
+ get '/'
96
+ response.headers['Content-Type'].should == 'text/plain'
97
+ end
98
+ end
99
+ end
100
+ ```
data/Rakefile ADDED
@@ -0,0 +1,7 @@
1
+ require 'bundler/gem_tasks'
2
+ require 'rspec/core/rake_task'
3
+
4
+ desc 'Run specs'
5
+ RSpec::Core::RakeTask.new(:spec)
6
+
7
+ task :default => :spec
@@ -0,0 +1,46 @@
1
+ # :stopdoc:
2
+
3
+ # Stolen from ruby core's uri/common.rb, with modifications to support 1.8.x
4
+ #
5
+ # https://github.com/ruby/ruby/blob/trunk/lib/uri/common.rb
6
+ #
7
+ # (via rack)
8
+
9
+ module URI
10
+ TBLENCWWWCOMP_ = {} # :nodoc:
11
+ 256.times do |i|
12
+ TBLENCWWWCOMP_[i.chr] = '%%%02X' % i
13
+ end
14
+ TBLENCWWWCOMP_[' '] = '+'
15
+ TBLENCWWWCOMP_.freeze
16
+ TBLDECWWWCOMP_ = {} # :nodoc:
17
+ 256.times do |i|
18
+ h, l = i>>4, i&15
19
+ TBLDECWWWCOMP_['%%%X%X' % [h, l]] = i.chr
20
+ TBLDECWWWCOMP_['%%%x%X' % [h, l]] = i.chr
21
+ TBLDECWWWCOMP_['%%%X%x' % [h, l]] = i.chr
22
+ TBLDECWWWCOMP_['%%%x%x' % [h, l]] = i.chr
23
+ end
24
+ TBLDECWWWCOMP_['+'] = ' '
25
+ TBLDECWWWCOMP_.freeze
26
+
27
+ # Encode given +s+ to URL-encoded form data.
28
+ #
29
+ # This method doesn't convert *, -, ., 0-9, A-Z, _, a-z, but does convert SP
30
+ # (ASCII space) to + and converts others to %XX.
31
+ #
32
+ # This is an implementation of
33
+ # http://www.w3.org/TR/html5/forms.html#url-encoded-form-data
34
+ #
35
+ # See URI.decode_www_form_component, URI.encode_www_form
36
+ def self.encode_www_form_component(s)
37
+ str = s.to_s
38
+ if RUBY_VERSION < "1.9" && $KCODE =~ /u/i
39
+ str.gsub(/([^ a-zA-Z0-9_.-]+)/) do
40
+ '%' + $1.unpack('H2' * Rack::Utils.bytesize($1)).join('%').upcase
41
+ end.tr(' ', '+')
42
+ else
43
+ str.gsub(/[^*\-.0-9A-Z_a-z]/) {|m| TBLENCWWWCOMP_[m]}
44
+ end
45
+ end
46
+ end
@@ -0,0 +1,90 @@
1
+ require 'stringio'
2
+ require 'uri'
3
+
4
+ # Ruby 1.8 does not have URI.encode_www_form_component.
5
+ unless URI.respond_to?(:encode_www_form_component)
6
+ require 'webmachine/test/backports/uri'
7
+ end
8
+
9
+ module Webmachine
10
+ module Test
11
+ class Session
12
+ HTTP_METHODS = %W(HEAD GET PUT POST PATCH DELETE OPTIONS)
13
+
14
+ def initialize(app)
15
+ @headers = Webmachine::Headers.new
16
+ @body = nil
17
+ @req = nil
18
+ @res = nil
19
+ @app = app
20
+ end
21
+
22
+ # Returns the request object.
23
+ def request
24
+ @req || webmachine_test_error('No request object yet. Issue a request first.')
25
+ end
26
+
27
+ # Returns the response object after a request has been made.
28
+ def response
29
+ @res || webmachine_test_error('No response yet. Issue a request first!')
30
+ end
31
+
32
+ # Set a single header for the next request.
33
+ def header(name, value)
34
+ @headers[name] = value
35
+ end
36
+
37
+ # Set the request body.
38
+ def body(value)
39
+ @body = value.respond_to?(:read) ? value : StringIO.new(value.to_s)
40
+ end
41
+
42
+ HTTP_METHODS.each do |method|
43
+ class_eval <<-__RUBY
44
+ def #{method.downcase}(uri, options = {})
45
+ do_request('#{method.upcase}', uri, options)
46
+ end
47
+ __RUBY
48
+ end
49
+
50
+ private
51
+ def webmachine_test_error(msg)
52
+ raise Webmachine::Test::Error.new(msg)
53
+ end
54
+
55
+ def do_request(method, uri, options)
56
+ uri = URI.parse(uri)
57
+ uri.scheme ||= 'http'
58
+ uri.host ||= 'localhost'
59
+
60
+ add_query_params(uri, options[:params])
61
+
62
+ # Set some default headers and merge the provided ones.
63
+ @headers['Host'] = [uri.host, uri.port].compact.join(':') unless @headers['Host']
64
+ @headers['Accept'] = '*/*' unless @headers['Accept']
65
+
66
+ options[:headers] ||= {}
67
+ options[:headers].each { |k, v| @headers[k] = v }
68
+
69
+ @body ||= options[:body] || StringIO.new
70
+
71
+ @req = Webmachine::Request.new(method, uri, @headers, @body)
72
+ @res = Webmachine::Response.new
73
+
74
+ @app.dispatcher.dispatch(@req, @res)
75
+ return @res
76
+ end
77
+
78
+ def add_query_params(uri, params)
79
+ if params
80
+ q = params.map do |k, v|
81
+ k, v = URI.encode_www_form_component(k), URI.encode_www_form_component(v)
82
+ "#{k}=#{v}"
83
+ end.join('&')
84
+
85
+ uri.query = uri.query ? [uri.query, q].join('&') : q
86
+ end
87
+ end
88
+ end
89
+ end
90
+ end
@@ -0,0 +1,5 @@
1
+ module Webmachine
2
+ module Test
3
+ VERSION = '0.1.0'
4
+ end
5
+ end
@@ -0,0 +1,22 @@
1
+ require 'forwardable'
2
+ require 'webmachine'
3
+ require 'webmachine/test/session'
4
+
5
+ module Webmachine
6
+ module Test
7
+ extend Forwardable
8
+
9
+ # Exception class for Test errors.
10
+ class Error < StandardError
11
+ end
12
+
13
+ def current_session
14
+ @session ||= Webmachine::Test::Session.new(app)
15
+ end
16
+
17
+ def_delegators :current_session, :request, :header, :headers, :body, :response,
18
+ :get, :post, :put, :patch, :delete,
19
+ :options, :head
20
+ end
21
+ end
22
+
@@ -0,0 +1,11 @@
1
+ require 'webmachine'
2
+
3
+ class TestResource < Webmachine::Resource
4
+ def content_types_provided
5
+ [['text/plain', :to_text]]
6
+ end
7
+
8
+ def to_text
9
+ 'OK'
10
+ end
11
+ end
@@ -0,0 +1,19 @@
1
+ require 'rubygems'
2
+ require 'bundler/setup'
3
+
4
+ require 'webmachine/application'
5
+ require 'webmachine/test'
6
+ require 'fixtures/test_resource'
7
+
8
+ module WebmachineTestApplication
9
+ def app
10
+ @app ||= Webmachine::Application.new.tap do |test_app|
11
+ test_app.add_route(['*'], TestResource)
12
+ end
13
+ end
14
+ end
15
+
16
+ RSpec.configure do |c|
17
+ c.include WebmachineTestApplication
18
+ end
19
+
@@ -0,0 +1,145 @@
1
+ require 'spec_helper'
2
+
3
+ describe Webmachine::Test::Session do
4
+ include Webmachine::Test
5
+
6
+ describe "#request" do
7
+ it "returns the Webmachine::Request object" do
8
+ get '/'
9
+ request.should be_a(Webmachine::Request)
10
+ end
11
+
12
+ context "without a request" do
13
+ it "raises an exception" do
14
+ expect { request }.to raise_error(Webmachine::Test::Error)
15
+ end
16
+ end
17
+ end
18
+
19
+ describe "#response" do
20
+ it "returns the Webmachine::Response object" do
21
+ get '/'
22
+ response.should be_a(Webmachine::Response)
23
+ end
24
+
25
+ context "without a request" do
26
+ it "raises an exception" do
27
+ expect { response }.to raise_error(Webmachine::Test::Error)
28
+ end
29
+ end
30
+ end
31
+
32
+ shared_examples_for "a HTTP verb" do
33
+ it "executes a GET request" do
34
+ send verb, '/'
35
+ request.method.should == verb.upcase
36
+ end
37
+
38
+ it "sets the provided header" do
39
+ send verb, '/', :headers => {'Accept' => 'application/x-gunzip'}
40
+ request.headers['Accept'].should == 'application/x-gunzip'
41
+ end
42
+
43
+ context "with a complete URI" do
44
+ it "sets the correct host header" do
45
+ send verb, 'http://example.com:3000/foo'
46
+ request.headers['Host'].should == 'example.com:3000'
47
+ end
48
+ end
49
+
50
+ context "with an incomplete URI" do
51
+ it "sets the correct host header" do
52
+ send verb, '/foo'
53
+ request.headers['Host'].should == 'localhost'
54
+ end
55
+ end
56
+
57
+ it "accepts query parameters in the path" do
58
+ send verb,'/?lang=en&foo=bar'
59
+ request.query['lang'].should == 'en'
60
+ request.query['foo'].should == 'bar'
61
+ end
62
+
63
+ it "accepts query parameters in the options hash" do
64
+ send verb, '/?foo=bar', :params => {'lang' => 'en'}
65
+ request.query['lang'].should == 'en'
66
+ request.query['foo'].should == 'bar'
67
+ end
68
+
69
+ it "escapes the query parameters" do
70
+ expect {
71
+ send verb, '/', :params => {'test' => 'foo bar'}
72
+ }.to_not raise_error(URI::InvalidComponentError)
73
+ end
74
+
75
+ it "encodes the query key and value." do
76
+ send verb, '/', :params => { "foo=" => "bar=" }
77
+ request.uri.query.should == "foo%3D=bar%3D"
78
+ end
79
+
80
+ it "returns the Webmachine::Request object" do
81
+ send(verb, '/').should be_a(Webmachine::Response)
82
+ end
83
+ end
84
+
85
+ describe "#get" do
86
+ let(:verb) { 'get' }
87
+ it_should_behave_like "a HTTP verb"
88
+ end
89
+
90
+ describe "#post" do
91
+ let(:verb) { 'post' }
92
+ it_should_behave_like "a HTTP verb"
93
+ end
94
+
95
+ describe "#put" do
96
+ let(:verb) { 'put' }
97
+ it_should_behave_like "a HTTP verb"
98
+ end
99
+
100
+ describe "#patch" do
101
+ let(:verb) { 'patch' }
102
+ it_should_behave_like "a HTTP verb"
103
+ end
104
+
105
+ describe "#delete" do
106
+ let(:verb) { 'delete' }
107
+ it_should_behave_like "a HTTP verb"
108
+ end
109
+
110
+ describe "#head" do
111
+ let(:verb) { 'head' }
112
+ it_should_behave_like "a HTTP verb"
113
+ end
114
+
115
+ describe "#options" do
116
+ let(:verb) { 'options' }
117
+ it_should_behave_like "a HTTP verb"
118
+ end
119
+
120
+ describe "#header" do
121
+ it "sets the given header value" do
122
+ header('Foo', 'bar-baz')
123
+ get '/'
124
+ request.headers['Foo'].should == 'bar-baz'
125
+ end
126
+ end
127
+
128
+ describe "#body" do
129
+ context "given a string" do
130
+ it "sets the body" do
131
+ body('test body')
132
+ get '/'
133
+ request.body.read.should == 'test body'
134
+ end
135
+ end
136
+
137
+ context "given an IO object" do
138
+ it "sets the body" do
139
+ body(StringIO.new('foo'))
140
+ get '/'
141
+ request.body.read.should == 'foo'
142
+ end
143
+ end
144
+ end
145
+ end
@@ -0,0 +1,25 @@
1
+ # -*- encoding: utf-8 -*-
2
+ $:.push File.expand_path("../lib", __FILE__)
3
+ require "webmachine/test/version"
4
+
5
+ Gem::Specification.new do |s|
6
+ s.name = "webmachine-test"
7
+ s.version = Webmachine::Test::VERSION
8
+ s.authors = ["Bernd Ahlers"]
9
+ s.email = ["bernd@tuneafish.de"]
10
+ s.homepage = ""
11
+ s.summary = %q{Test API for webmachine-ruby}
12
+ s.description = <<-DESC.gsub(/\s+/, ' ')
13
+ Webmachine::Test provides a testing API for webmachine-ruby inspired
14
+ by rack-test.
15
+ DESC
16
+
17
+ s.rubyforge_project = "webmachine-test"
18
+
19
+ s.files = `git ls-files`.split("\n").reject {|f| f =~ /^\./ }
20
+ s.test_files = `git ls-files -- {test,spec,features}/*`.split("\n")
21
+ s.executables = `git ls-files -- bin/*`.split("\n").map{ |f| File.basename(f) }
22
+ s.require_paths = ["lib"]
23
+
24
+ s.add_runtime_dependency(%q<webmachine>)
25
+ end
metadata ADDED
@@ -0,0 +1,73 @@
1
+ --- !ruby/object:Gem::Specification
2
+ name: webmachine-test
3
+ version: !ruby/object:Gem::Version
4
+ version: 0.1.0
5
+ prerelease:
6
+ platform: ruby
7
+ authors:
8
+ - Bernd Ahlers
9
+ autorequire:
10
+ bindir: bin
11
+ cert_chain: []
12
+ date: 2012-07-07 00:00:00.000000000 Z
13
+ dependencies:
14
+ - !ruby/object:Gem::Dependency
15
+ name: webmachine
16
+ requirement: !ruby/object:Gem::Requirement
17
+ none: false
18
+ requirements:
19
+ - - ! '>='
20
+ - !ruby/object:Gem::Version
21
+ version: '0'
22
+ type: :runtime
23
+ prerelease: false
24
+ version_requirements: !ruby/object:Gem::Requirement
25
+ none: false
26
+ requirements:
27
+ - - ! '>='
28
+ - !ruby/object:Gem::Version
29
+ version: '0'
30
+ description: ! ' Webmachine::Test provides a testing API for webmachine-ruby inspired
31
+ by rack-test. '
32
+ email:
33
+ - bernd@tuneafish.de
34
+ executables: []
35
+ extensions: []
36
+ extra_rdoc_files: []
37
+ files:
38
+ - Gemfile
39
+ - README.md
40
+ - Rakefile
41
+ - lib/webmachine/test.rb
42
+ - lib/webmachine/test/backports/uri.rb
43
+ - lib/webmachine/test/session.rb
44
+ - lib/webmachine/test/version.rb
45
+ - spec/fixtures/test_resource.rb
46
+ - spec/spec_helper.rb
47
+ - spec/webmachine/test/session_spec.rb
48
+ - webmachine-test.gemspec
49
+ homepage: ''
50
+ licenses: []
51
+ post_install_message:
52
+ rdoc_options: []
53
+ require_paths:
54
+ - lib
55
+ required_ruby_version: !ruby/object:Gem::Requirement
56
+ none: false
57
+ requirements:
58
+ - - ! '>='
59
+ - !ruby/object:Gem::Version
60
+ version: '0'
61
+ required_rubygems_version: !ruby/object:Gem::Requirement
62
+ none: false
63
+ requirements:
64
+ - - ! '>='
65
+ - !ruby/object:Gem::Version
66
+ version: '0'
67
+ requirements: []
68
+ rubyforge_project: webmachine-test
69
+ rubygems_version: 1.8.24
70
+ signing_key:
71
+ specification_version: 3
72
+ summary: Test API for webmachine-ruby
73
+ test_files: []