From 18d3c8714fe1b440a219873995fdf3347dbf5676 Mon Sep 17 00:00:00 2001 From: Blake Mizerany Date: Tue, 27 Nov 2007 21:55:05 -0800 Subject: [PATCH] more tests --- lib/sinatra.rb | 102 ++++++++++++++++++++++++++++++++++++++++++----- test/application_test.rb | 38 ++++++++++++++++++ test/events_test.rb | 44 ++++++++++++++------ test/helper.rb | 11 +++++ 4 files changed, 173 insertions(+), 22 deletions(-) create mode 100644 test/application_test.rb create mode 100644 test/helper.rb diff --git a/lib/sinatra.rb b/lib/sinatra.rb index 100093b..bf47c1d 100644 --- a/lib/sinatra.rb +++ b/lib/sinatra.rb @@ -1,19 +1,32 @@ +require 'rubygems' +require 'rack' module Sinatra - Result = Struct.new(:body) + Result = Struct.new(:body, :params) class Event + + URI_CHAR = '[^/?:,&#]'.freeze unless defined?(URI_CHAR) + PARAM = /:(#{URI_CHAR}+)/.freeze unless defined?(PARAM) - attr_reader :path, :block + attr_reader :path, :block, :param_keys, :pattern def initialize(path, &b) @path = path @block = b + @param_keys = [] + regex = @path.to_s.gsub(PARAM) do + @param_keys << $1.intern + "(#{URI_CHAR}+)" + end + @pattern = /^#{regex}$/ end - - def invoke - Result.new(block.call) + + def invoke(env) + return unless pattern =~ env['PATH_INFO'].squeeze('/') + params = param_keys.zip($~.captures.map(&:from_param)).to_hash + Result.new(block.call, params) end end @@ -31,12 +44,81 @@ module Sinatra event end - def lookup(method, path) - events[method].find do |e| - result = e.invoke and break result - end + def lookup(env) + events[env['REQUEST_METHOD'].downcase.to_sym].eject(&[:invoke, env]) end end -end \ No newline at end of file +end + +module Kernel + + def silence_warnings + old_verbose, $VERBOSE = $VERBOSE, nil + yield + ensure + $VERBOSE = old_verbose + end + +end + +class String + + # Converts +self+ to an escaped URI parameter value + # 'Foo Bar'.to_param # => 'Foo%20Bar' + def to_param + URI.escape(self) + end + + # Converts +self+ from an escaped URI parameter value + # 'Foo%20Bar'.from_param # => 'Foo Bar' + def from_param + URI.unescape(self) + end + +end + +class Hash + + def to_params + map { |k,v| "#{k}=#{URI.escape(v)}" }.join('&') + end + + def symbolize_keys + self.inject({}) { |h,(k,v)| h[k.to_sym] = v; h } + end + + def pass(*keys) + reject { |k,v| !keys.include?(k) } + end + +end + +class Symbol + + def to_proc + Proc.new { |*args| args.shift.__send__(self, *args) } + end + +end + +class Array + + def to_hash + self.inject({}) { |h, (k, v)| h[k] = v; h } + end + + def to_proc + Proc.new { |*args| args.shift.__send__(self[0], *(args + self[1..-1])) } + end + +end + +module Enumerable + + def eject(&block) + find { |e| result = block[e] and break result } + end + +end diff --git a/test/application_test.rb b/test/application_test.rb new file mode 100644 index 0000000..599a5a2 --- /dev/null +++ b/test/application_test.rb @@ -0,0 +1,38 @@ +require File.dirname(__FILE__) + '/helper' + +context "Simple Events" do + + setup do + @app = Sinatra::Application.new + end + + specify "return what's at the end" do + @app.define_event(:get, '/') do + 'Hello' + end + + result = @app.lookup( + 'REQUEST_METHOD' => 'GET', + 'PATH_INFO' => '/' + ) + + result.should.not.be.nil + result.body.should.equal 'Hello' + end + + specify "takes params in path" do + @app.define_event(:get, '/:foo') do + 'World' + end + + result = @app.lookup( + 'REQUEST_METHOD' => 'GET', + 'PATH_INFO' => '/bar' + ) + + result.should.not.be.nil + result.body.should.equal 'World' + result.params.should.equal :foo => 'bar' + end + +end diff --git a/test/events_test.rb b/test/events_test.rb index d6da833..d8f0a72 100644 --- a/test/events_test.rb +++ b/test/events_test.rb @@ -5,19 +5,39 @@ require 'test/spec' context "Simple Events" do - specify "return what's at the end" do - - application = Sinatra::Application.new - - route = application.define_event(:get, '/') do - 'Hello' - end - - result = application.lookup(:get, '/') - + def simple_request_hash(method, path) + { + 'REQUEST_METHOD' => method.to_s.upcase, + 'PATH_INFO' => path + } + end + + def invoke_simple(path, request_path) + event = Sinatra::Event.new(path) { 'Simple' } + event.invoke(simple_request_hash(:get, request_path)) + end + + specify "return last value" do + result = invoke_simple('/', '/') result.should.not.be.nil - result.body.should.equal 'Hello' + result.body.should.equal 'Simple' + result.params.should.equal Hash.new + end + + specify "takes params in path" do + result = invoke_simple('/:foo/:bar', '/a/b') + result.should.not.be.nil + result.params.should.equal :foo => 'a', :bar => 'b' + # unscapes + result = invoke_simple('/:foo/:bar', '/a/blake%20mizerany') + result.should.not.be.nil + result.params.should.equal :foo => 'a', :bar => 'blake mizerany' end - + + specify "ignores to many /'s" do + result = invoke_simple('/x/y', '/x//y') + result.should.not.be.nil + end + end diff --git a/test/helper.rb b/test/helper.rb new file mode 100644 index 0000000..cd7a39f --- /dev/null +++ b/test/helper.rb @@ -0,0 +1,11 @@ +require File.dirname(__FILE__) + '/../lib/sinatra' + +require 'rubygems' +require 'test/spec' + +module Sinatra::TestHelper + +end + +Test::Unit::TestCase.send :include, Sinatra::TestHelper + -- 2.11.4.GIT