From 59451d1e20cfa226c15d05abaddf9b0c097663f9 Mon Sep 17 00:00:00 2001 From: tdreyno Date: Wed, 12 Aug 2009 13:04:58 -0700 Subject: [PATCH] add vendor back --- vendor/rack-test/History.txt | 64 +++ vendor/rack-test/MIT-LICENSE.txt | 19 + vendor/rack-test/README.rdoc | 57 +++ vendor/rack-test/Rakefile | 62 +++ vendor/rack-test/lib/rack/mock_session.rb | 57 +++ vendor/rack-test/lib/rack/test.rb | 246 ++++++++++++ vendor/rack-test/lib/rack/test/cookie_jar.rb | 169 ++++++++ vendor/rack-test/lib/rack/test/methods.rb | 73 ++++ .../lib/rack/test/mock_digest_request.rb | 27 ++ .../rack-test/lib/rack/test/uploaded_file.rb | 36 ++ vendor/rack-test/lib/rack/test/utils.rb | 75 ++++ vendor/rack-test/spec/fixtures/config.ru | 3 + vendor/rack-test/spec/fixtures/fake_app.rb | 109 ++++++ vendor/rack-test/spec/fixtures/foo.txt | 1 + .../rack-test/spec/rack/test/cookie_spec.rb | 176 +++++++++ .../spec/rack/test/digest_auth_spec.rb | 48 +++ .../spec/rack/test/multipart_spec.rb | 85 ++++ vendor/rack-test/spec/rack/test/utils_spec.rb | 44 +++ vendor/rack-test/spec/rack/test_spec.rb | 363 ++++++++++++++++++ vendor/rack-test/spec/rcov.opts | 1 + vendor/rack-test/spec/spec.opts | 1 + vendor/rack-test/spec/spec_helper.rb | 48 +++ vendor/sinatra-content-for/LICENSE | 22 ++ vendor/sinatra-content-for/README.rdoc | 49 +++ vendor/sinatra-content-for/Rakefile | 33 ++ .../lib/sinatra/content_for.rb | 58 +++ .../sinatra-content-for.gemspec | 34 ++ .../test/content_for_test.rb | 156 ++++++++ vendor/sinatra-markaby/CHANGES | 7 + vendor/sinatra-markaby/LICENSE | 20 + vendor/sinatra-markaby/README.rdoc | 33 ++ vendor/sinatra-markaby/Rakefile | 45 +++ vendor/sinatra-markaby/TODO | 3 + vendor/sinatra-markaby/VERSION.yml | 4 + vendor/sinatra-markaby/lib/sinatra/markaby.rb | 31 ++ .../sinatra-markaby/sinatra-markaby.gemspec | 49 +++ .../test/sinatra_markaby_test.rb | 72 ++++ vendor/sinatra-markaby/test/test_helper.rb | 19 + vendor/sinatra-markaby/test/views/hello.mab | 1 + vendor/sinatra-markaby/test/views/html.mab | 4 + vendor/sinatra-maruku/LICENSE | 22 ++ vendor/sinatra-maruku/README.markdown | 85 ++++ vendor/sinatra-maruku/Rakefile | 34 ++ vendor/sinatra-maruku/VERSION.yml | 4 + vendor/sinatra-maruku/examples/app.rb | 8 + vendor/sinatra-maruku/examples/config.ru | 4 + vendor/sinatra-maruku/examples/mapp.rb | 15 + .../public/javascripts/application.js | 0 .../public/stylesheets/application.css | 23 ++ .../examples/public/stylesheets/print.css | 0 .../examples/views/index.maruku | 32 ++ .../examples/views/layout.maruku | 9 + vendor/sinatra-maruku/lib/sinatra/maruku.rb | 25 ++ vendor/sinatra-maruku/sinatra-maruku.gemspec | 70 ++++ .../test/sinatra_maruku_test.rb | 91 +++++ vendor/sinatra-maruku/test/test_helper.rb | 21 + vendor/sinatra-maruku/test/views/hello.maruku | 1 + .../sinatra-maruku/test/views/layout2.maruku | 2 + 58 files changed, 2850 insertions(+) create mode 100644 vendor/rack-test/History.txt create mode 100644 vendor/rack-test/MIT-LICENSE.txt create mode 100644 vendor/rack-test/README.rdoc create mode 100644 vendor/rack-test/Rakefile create mode 100644 vendor/rack-test/lib/rack/mock_session.rb create mode 100644 vendor/rack-test/lib/rack/test.rb create mode 100644 vendor/rack-test/lib/rack/test/cookie_jar.rb create mode 100644 vendor/rack-test/lib/rack/test/methods.rb create mode 100644 vendor/rack-test/lib/rack/test/mock_digest_request.rb create mode 100644 vendor/rack-test/lib/rack/test/uploaded_file.rb create mode 100644 vendor/rack-test/lib/rack/test/utils.rb create mode 100644 vendor/rack-test/spec/fixtures/config.ru create mode 100644 vendor/rack-test/spec/fixtures/fake_app.rb create mode 100644 vendor/rack-test/spec/fixtures/foo.txt create mode 100644 vendor/rack-test/spec/rack/test/cookie_spec.rb create mode 100644 vendor/rack-test/spec/rack/test/digest_auth_spec.rb create mode 100644 vendor/rack-test/spec/rack/test/multipart_spec.rb create mode 100644 vendor/rack-test/spec/rack/test/utils_spec.rb create mode 100644 vendor/rack-test/spec/rack/test_spec.rb create mode 100644 vendor/rack-test/spec/rcov.opts create mode 100644 vendor/rack-test/spec/spec.opts create mode 100644 vendor/rack-test/spec/spec_helper.rb create mode 100644 vendor/sinatra-content-for/LICENSE create mode 100644 vendor/sinatra-content-for/README.rdoc create mode 100644 vendor/sinatra-content-for/Rakefile create mode 100644 vendor/sinatra-content-for/lib/sinatra/content_for.rb create mode 100644 vendor/sinatra-content-for/sinatra-content-for.gemspec create mode 100644 vendor/sinatra-content-for/test/content_for_test.rb create mode 100644 vendor/sinatra-markaby/CHANGES create mode 100644 vendor/sinatra-markaby/LICENSE create mode 100644 vendor/sinatra-markaby/README.rdoc create mode 100644 vendor/sinatra-markaby/Rakefile create mode 100644 vendor/sinatra-markaby/TODO create mode 100644 vendor/sinatra-markaby/VERSION.yml create mode 100644 vendor/sinatra-markaby/lib/sinatra/markaby.rb create mode 100644 vendor/sinatra-markaby/sinatra-markaby.gemspec create mode 100644 vendor/sinatra-markaby/test/sinatra_markaby_test.rb create mode 100644 vendor/sinatra-markaby/test/test_helper.rb create mode 100644 vendor/sinatra-markaby/test/views/hello.mab create mode 100644 vendor/sinatra-markaby/test/views/html.mab create mode 100644 vendor/sinatra-maruku/LICENSE create mode 100644 vendor/sinatra-maruku/README.markdown create mode 100644 vendor/sinatra-maruku/Rakefile create mode 100644 vendor/sinatra-maruku/VERSION.yml create mode 100644 vendor/sinatra-maruku/examples/app.rb create mode 100644 vendor/sinatra-maruku/examples/config.ru create mode 100644 vendor/sinatra-maruku/examples/mapp.rb rename .gitmodules => vendor/sinatra-maruku/examples/public/javascripts/application.js (100%) create mode 100644 vendor/sinatra-maruku/examples/public/stylesheets/application.css create mode 100644 vendor/sinatra-maruku/examples/public/stylesheets/print.css create mode 100644 vendor/sinatra-maruku/examples/views/index.maruku create mode 100644 vendor/sinatra-maruku/examples/views/layout.maruku create mode 100644 vendor/sinatra-maruku/lib/sinatra/maruku.rb create mode 100644 vendor/sinatra-maruku/sinatra-maruku.gemspec create mode 100644 vendor/sinatra-maruku/test/sinatra_maruku_test.rb create mode 100644 vendor/sinatra-maruku/test/test_helper.rb create mode 100644 vendor/sinatra-maruku/test/views/hello.maruku create mode 100644 vendor/sinatra-maruku/test/views/layout2.maruku diff --git a/vendor/rack-test/History.txt b/vendor/rack-test/History.txt new file mode 100644 index 00000000..61705a4f --- /dev/null +++ b/vendor/rack-test/History.txt @@ -0,0 +1,64 @@ +== Git + +* Minor enhancements + + * Support initializing a Rack::Test::Session with an app in addition to + a Rack::MockSession + * Allow CONTENT_TYPE to be specified in the env and not overwritten when + sending a POST or PUT + +== 0.4.0 / 2009-06-25 + +* Minor enhancements + + * Expose hook for building Rack::MockSessions for frameworks that need + to configure them before use + * Support passing in arrays of raw cookies in addition to a newline + separated string + * Support after_request callbacks in MockSession for things like running + background jobs + * Allow multiple named sessions using with_session + * Initialize Rack::Test::Sessions with Rack::MockSessions instead of apps. + This change should help integration with other Ruby web frameworks + (like Merb). + * Support sending bodies for PUT requests (Larry Diehl) + +== 0.3.0 / 2009-05-17 + +* Major enhancements + + * Ruby 1.9 compatible (Simon Rozet, Michael Fellinger) + +* Minor enhancements + + * Add CookieJar#[] and CookieJar#[]= methods + * Make the default host configurable + * Use Rack::Lint and fix errors (Simon Rozet) + * Extract Rack::MockSession from Rack::Test::Session to handle tracking + the last request and response and the cookie jar + * Add #set_cookie and #clear_cookies methods + * Rename #authorize to #basic_authorize (#authorize remains as an alias) + (Simon Rozet) + +== 0.2.0 / 2009-04-26 + +Because #last_response is now a MockResponse instead of a Rack::Response, +#last_response.body now returns a string instead of an array. + +* Major enhancements + + * Support multipart requests via the UploadedFile class (thanks, Rails) + +* Minor enhancements + + * Updated for Rack 1.0 + * Don't require rubygems (See http://gist.github.com/54177) + * Support HTTP Digest authentication with the #digest_authorize method + * #last_response returns a MockResponse instead of a Response + (Michael Fellinger) + +== 0.1.0 / 2009-03-02 + +* 1 major enhancement + + * Birthday! diff --git a/vendor/rack-test/MIT-LICENSE.txt b/vendor/rack-test/MIT-LICENSE.txt new file mode 100644 index 00000000..f387441c --- /dev/null +++ b/vendor/rack-test/MIT-LICENSE.txt @@ -0,0 +1,19 @@ +Copyright (c) 2008-2009 Bryan Helmkamp, Engine Yard Inc. + +Permission is hereby granted, free of charge, to any person obtaining a copy +of this software and associated documentation files (the "Software"), to deal +in the Software without restriction, including without limitation the rights +to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +copies of the Software, and to permit persons to whom the Software is +furnished to do so, subject to the following conditions: + +The above copyright notice and this permission notice shall be included in +all copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN +THE SOFTWARE. diff --git a/vendor/rack-test/README.rdoc b/vendor/rack-test/README.rdoc new file mode 100644 index 00000000..c9f96b60 --- /dev/null +++ b/vendor/rack-test/README.rdoc @@ -0,0 +1,57 @@ += Rack::Test + +- http://gitrdoc.com/brynary/rack-test +- http://github.com/brynary/rack-test + +== Description + +Rack::Test is a small, simple testing API for Rack apps. It can be used on its +own or as a reusable starting point for Web frameworks and testing libraries +to build on. Most of its initial functionality is an extraction of Merb 1.0's +request helpers feature. + +== Features + +* Maintains a cookie jar across requests +* Easily follow redirects when desired +* Set request headers to be used by all subsequent requests +* Small footprint. Approximately 200 LOC + +== Example + + require "rack/test" + + class HomepageTest < Test::Unit::TestCase + include Rack::Test::Methods + + def app + MyApp.new + end + + def test_redirect_logged_in_users_to_dashboard + authorize "bryan", "secret" + get "/" + follow_redirect! + + assert_equal "http://example.org/redirected", last_request.url + assert last_response.ok? + end + + end + +== Install + +To install the latest release as a gem: + + sudo gem install rack-test + +== Authors + +- Maintained by {Bryan Helmkamp}[mailto:bryan@brynary.com] +- Contributions from Simon Rozet and Pat Nakajima +- Much of the original code was extracted from Merb 1.0's request helper + +== License + +Copyright (c) 2008-2009 Bryan Helmkamp, Engine Yard Inc. +See MIT-LICENSE.txt in this directory. diff --git a/vendor/rack-test/Rakefile b/vendor/rack-test/Rakefile new file mode 100644 index 00000000..87fb4c29 --- /dev/null +++ b/vendor/rack-test/Rakefile @@ -0,0 +1,62 @@ +require "rubygems" +require "rake/rdoctask" +require "rake/gempackagetask" +require "rake/clean" +require "spec/rake/spectask" +require File.expand_path("./lib/rack/test") + +Spec::Rake::SpecTask.new do |t| + t.spec_opts = ['--options', "\"#{File.dirname(__FILE__)}/spec/spec.opts\""] +end + +desc "Run all specs in spec directory with RCov" +Spec::Rake::SpecTask.new(:rcov) do |t| + t.spec_opts = ['--options', "\"#{File.dirname(__FILE__)}/spec/spec.opts\""] + t.rcov = true + t.rcov_opts = lambda do + IO.readlines(File.dirname(__FILE__) + "/spec/rcov.opts").map {|l| l.chomp.split " "}.flatten + end +end + +desc "Run the specs" +task :default => :spec + +spec = Gem::Specification.new do |s| + s.name = "rack-test" + s.version = Rack::Test::VERSION + s.author = "Bryan Helmkamp" + s.email = "bryan" + "@" + "brynary.com" + s.homepage = "http://github.com/brynary/rack-test" + s.summary = "Simple testing API built on Rack" + s.description = s.summary + s.files = %w[History.txt Rakefile README.rdoc] + Dir["lib/**/*"] + + # rdoc + s.has_rdoc = true + s.extra_rdoc_files = %w(README.rdoc MIT-LICENSE.txt) +end + +Rake::GemPackageTask.new(spec) do |package| + package.gem_spec = spec +end + +desc "Delete generated RDoc" +task :clobber_docs do + FileUtils.rm_rf("doc") +end + +desc "Generate RDoc" +task :docs => :clobber_docs do + system "hanna --title 'Rack::Test #{Rack::Test::VERSION} API Documentation'" +end + +desc 'Install the package as a gem.' +task :install => [:clean, :package] do + gem = Dir['pkg/*.gem'].first + sh "sudo gem install --no-rdoc --no-ri --local #{gem}" +end + +desc 'Removes trailing whitespace' +task :whitespace do + sh %{find . -name '*.rb' -exec sed -i '' 's/ *$//g' {} \\;} +end diff --git a/vendor/rack-test/lib/rack/mock_session.rb b/vendor/rack-test/lib/rack/mock_session.rb new file mode 100644 index 00000000..b5ba12a9 --- /dev/null +++ b/vendor/rack-test/lib/rack/mock_session.rb @@ -0,0 +1,57 @@ +module Rack + + class MockSession + attr_writer :cookie_jar + attr_reader :last_response + attr_reader :default_host + + def initialize(app, default_host = Rack::Test::DEFAULT_HOST) + @app = app + @after_request = [] + @default_host = default_host + end + + def after_request(&block) + @after_request << block + end + + def clear_cookies + @cookie_jar = Rack::Test::CookieJar.new([], @default_host) + end + + def set_cookie(cookie, uri = nil) + cookie_jar.merge(cookie, uri) + end + + def request(uri, env) + env["HTTP_COOKIE"] ||= cookie_jar.for(uri) + @last_request = Rack::Request.new(env) + status, headers, body = @app.call(@last_request.env) + @last_response = MockResponse.new(status, headers, body, env["rack.errors"].flush) + cookie_jar.merge(last_response.headers["Set-Cookie"], uri) + + @after_request.each { |hook| hook.call } + @last_response + end + + # Return the last request issued in the session. Raises an error if no + # requests have been sent yet. + def last_request + raise Rack::Test::Error.new("No request yet. Request a page first.") unless @last_request + @last_request + end + + # Return the last response received in the session. Raises an error if + # no requests have been sent yet. + def last_response + raise Rack::Test::Error.new("No response yet. Request a page first.") unless @last_response + @last_response + end + + def cookie_jar + @cookie_jar ||= Rack::Test::CookieJar.new([], @default_host) + end + + end + +end diff --git a/vendor/rack-test/lib/rack/test.rb b/vendor/rack-test/lib/rack/test.rb new file mode 100644 index 00000000..34532e36 --- /dev/null +++ b/vendor/rack-test/lib/rack/test.rb @@ -0,0 +1,246 @@ +unless $LOAD_PATH.include?(File.expand_path(File.dirname(__FILE__) + "/..")) + $LOAD_PATH.unshift(File.expand_path(File.dirname(__FILE__) + "/..")) +end + +require "uri" +require "rack" +require "rack/mock_session" +require "rack/test/cookie_jar" +require "rack/test/mock_digest_request" +require "rack/test/utils" +require "rack/test/methods" +require "rack/test/uploaded_file" + +module Rack + module Test + + VERSION = "0.4.0" + + DEFAULT_HOST = "example.org" + MULTIPART_BOUNDARY = "----------XnJLe9ZIbbGUYtzPQJ16u1" + + # The common base class for exceptions raised by Rack::Test + class Error < StandardError; end + + class Session + extend Forwardable + include Rack::Test::Utils + + def_delegators :@rack_mock_session, :clear_cookies, :set_cookie, :last_response, :last_request + + # Initialize a new session for the given Rack app + def initialize(mock_session) + @headers = {} + + if mock_session.is_a?(MockSession) + @rack_mock_session = mock_session + else + @rack_mock_session = MockSession.new(mock_session) + end + + @default_host = @rack_mock_session.default_host + end + + # Issue a GET request for the given URI with the given params and Rack + # environment. Stores the issues request object in #last_request and + # the app's response in #last_response. Yield #last_response to a block + # if given. + # + # Example: + # get "/" + def get(uri, params = {}, env = {}, &block) + env = env_for(uri, env.merge(:method => "GET", :params => params)) + process_request(uri, env, &block) + end + + # Issue a POST request for the given URI. See #get + # + # Example: + # post "/signup", "name" => "Bryan" + def post(uri, params = {}, env = {}, &block) + env = env_for(uri, env.merge(:method => "POST", :params => params)) + process_request(uri, env, &block) + end + + # Issue a PUT request for the given URI. See #get + # + # Example: + # put "/" + def put(uri, params = {}, env = {}, &block) + env = env_for(uri, env.merge(:method => "PUT", :params => params)) + process_request(uri, env, &block) + end + + # Issue a DELETE request for the given URI. See #get + # + # Example: + # delete "/" + def delete(uri, params = {}, env = {}, &block) + env = env_for(uri, env.merge(:method => "DELETE", :params => params)) + process_request(uri, env, &block) + end + + # Issue a HEAD request for the given URI. See #get + # + # Example: + # head "/" + def head(uri, params = {}, env = {}, &block) + env = env_for(uri, env.merge(:method => "HEAD", :params => params)) + process_request(uri, env, &block) + end + + # Issue a request to the Rack app for the given URI and optional Rack + # environment. Stores the issues request object in #last_request and + # the app's response in #last_response. Yield #last_response to a block + # if given. + # + # Example: + # request "/" + def request(uri, env = {}, &block) + env = env_for(uri, env) + process_request(uri, env, &block) + end + + # Set a header to be included on all subsequent requests through the + # session. Use a value of nil to remove a previously configured header. + # + # Example: + # header "User-Agent", "Firefox" + def header(name, value) + if value.nil? + @headers.delete(name) + else + @headers[name] = value + end + end + + # Set the username and password for HTTP Basic authorization, to be + # included in subsequent requests in the HTTP_AUTHORIZATION header. + # + # Example: + # basic_authorize "bryan", "secret" + def basic_authorize(username, password) + encoded_login = ["#{username}:#{password}"].pack("m*") + header('HTTP_AUTHORIZATION', "Basic #{encoded_login}") + end + + alias_method :authorize, :basic_authorize + + def digest_authorize(username, password) + @digest_username = username + @digest_password = password + end + + # Rack::Test will not follow any redirects automatically. This method + # will follow the redirect returned in the last response. If the last + # response was not a redirect, an error will be raised. + def follow_redirect! + unless last_response.redirect? + raise Error.new("Last response was not a redirect. Cannot follow_redirect!") + end + + get(last_response["Location"]) + end + + private + + def env_for(path, env) + uri = URI.parse(path) + uri.host ||= @default_host + + env = default_env.merge(env) + + env.update("HTTPS" => "on") if URI::HTTPS === uri + env["X-Requested-With"] = "XMLHttpRequest" if env[:xhr] + + if (env[:method] == "POST" || env["REQUEST_METHOD"] == "POST" || + env[:method] == "PUT" || env["REQUEST_METHOD"] == "PUT") && !env.has_key?(:input) + env["CONTENT_TYPE"] ||= "application/x-www-form-urlencoded" + + multipart = (Hash === env[:params]) && + env[:params].any? { |_, v| UploadedFile === v } + + if multipart + env[:input] = multipart_body(env.delete(:params)) + env["CONTENT_LENGTH"] ||= env[:input].length.to_s + env["CONTENT_TYPE"] = "multipart/form-data; boundary=#{MULTIPART_BOUNDARY}" + else + env[:input] = params_to_string(env.delete(:params)) + end + end + + params = env[:params] || {} + params.update(parse_query(uri.query)) + + uri.query = requestify(params) + + if env.has_key?(:cookie) + set_cookie(env.delete(:cookie), uri) + end + + Rack::MockRequest.env_for(uri.to_s, env) + end + + def process_request(uri, env) + uri = URI.parse(uri) + uri.host ||= @default_host + + @rack_mock_session.request(uri, env) + + if retry_with_digest_auth?(env) + auth_env = env.merge({ + "HTTP_AUTHORIZATION" => digest_auth_header, + "rack-test.digest_auth_retry" => true + }) + auth_env.delete('rack.request') + process_request(uri.path, auth_env) + else + yield last_response if block_given? + + last_response + end + end + + def digest_auth_header + challenge = last_response["WWW-Authenticate"].split(" ", 2).last + params = Rack::Auth::Digest::Params.parse(challenge) + + params.merge!({ + "username" => @digest_username, + "nc" => "00000001", + "cnonce" => "nonsensenonce", + "uri" => last_request.path_info, + "method" => last_request.env["REQUEST_METHOD"], + }) + + params["response"] = MockDigestRequest.new(params).response(@digest_password) + + "Digest #{params}" + end + + def retry_with_digest_auth?(env) + last_response.status == 401 && + digest_auth_configured? && + !env["rack-test.digest_auth_retry"] + end + + def digest_auth_configured? + @digest_username + end + + def default_env + { "rack.test" => true, "REMOTE_ADDR" => "127.0.0.1" }.merge(@headers) + end + + def params_to_string(params) + case params + when Hash then requestify(params) + when nil then "" + else params + end + end + + end + + end +end diff --git a/vendor/rack-test/lib/rack/test/cookie_jar.rb b/vendor/rack-test/lib/rack/test/cookie_jar.rb new file mode 100644 index 00000000..d2f3d2b9 --- /dev/null +++ b/vendor/rack-test/lib/rack/test/cookie_jar.rb @@ -0,0 +1,169 @@ +require "uri" +module Rack + module Test + + class Cookie + include Rack::Utils + + # :api: private + attr_reader :name, :value + + # :api: private + def initialize(raw, uri = nil, default_host = DEFAULT_HOST) + @default_host = default_host + uri ||= default_uri + + # separate the name / value pair from the cookie options + @name_value_raw, options = raw.split(/[;,] */n, 2) + + @name, @value = parse_query(@name_value_raw, ';').to_a.first + @options = parse_query(options, ';') + + @options["domain"] ||= (uri.host || default_host) + @options["path"] ||= uri.path.sub(/\/[^\/]*\Z/, "") + end + + def replaces?(other) + [name.downcase, domain, path] == [other.name.downcase, other.domain, other.path] + end + + # :api: private + def raw + @name_value_raw + end + + # :api: private + def empty? + @value.nil? || @value.empty? + end + + # :api: private + def domain + @options["domain"] + end + + def secure? + @options.has_key?("secure") + end + + # :api: private + def path + @options["path"].strip || "/" + end + + # :api: private + def expires + Time.parse(@options["expires"]) if @options["expires"] + end + + # :api: private + def expired? + expires && expires < Time.now + end + + # :api: private + def valid?(uri) + uri ||= default_uri + + if uri.host.nil? + uri.host = @default_host + end + + (!secure? || (secure? && uri.scheme == "https")) && + uri.host =~ Regexp.new("#{Regexp.escape(domain)}$", Regexp::IGNORECASE) && + uri.path =~ Regexp.new("^#{Regexp.escape(path)}") + end + + # :api: private + def matches?(uri) + ! expired? && valid?(uri) + end + + # :api: private + def <=>(other) + # Orders the cookies from least specific to most + [name, path, domain.reverse] <=> [other.name, other.path, other.domain.reverse] + end + + protected + + def default_uri + URI.parse("//" + @default_host + "/") + end + + end + + class CookieJar + + # :api: private + def initialize(cookies = [], default_host = DEFAULT_HOST) + @default_host = default_host + @cookies = cookies + @cookies.sort! + end + + def [](name) + cookies = hash_for(nil) + # TODO: Should be case insensitive + cookies[name] && cookies[name].value + end + + def []=(name, value) + # TODO: needs proper escaping + merge("#{name}=#{value}") + end + + def merge(raw_cookies, uri = nil) + return unless raw_cookies + + Array(raw_cookies).join("\n").split("\n").each do |raw_cookie| + cookie = Cookie.new(raw_cookie, uri, @default_host) + self << cookie if cookie.valid?(uri) + end + end + + def <<(new_cookie) + @cookies.reject! do |existing_cookie| + new_cookie.replaces?(existing_cookie) + end + + @cookies << new_cookie + @cookies.sort! + end + + # :api: private + def for(uri) + hash_for(uri).values.map { |c| c.raw }.join(';') + end + + def to_hash + cookies = {} + + hash_for(nil).each do |name, cookie| + cookies[name] = cookie.value + end + + return cookies + end + + protected + + def hash_for(uri = nil) + cookies = {} + + # The cookies are sorted by most specific first. So, we loop through + # all the cookies in order and add it to a hash by cookie name if + # the cookie can be sent to the current URI. It's added to the hash + # so that when we are done, the cookies will be unique by name and + # we'll have grabbed the most specific to the URI. + @cookies.each do |cookie| + cookies[cookie.name] = cookie if cookie.matches?(uri) + end + + return cookies + end + + end + + end +end diff --git a/vendor/rack-test/lib/rack/test/methods.rb b/vendor/rack-test/lib/rack/test/methods.rb new file mode 100644 index 00000000..1678fe56 --- /dev/null +++ b/vendor/rack-test/lib/rack/test/methods.rb @@ -0,0 +1,73 @@ +require "forwardable" + +module Rack + module Test + module Methods + extend Forwardable + + def rack_mock_session(name = :default) + return build_rack_mock_session unless name + + @_rack_mock_sessions ||= {} + @_rack_mock_sessions[name] ||= build_rack_mock_session + end + + def build_rack_mock_session + Rack::MockSession.new(app) + end + + def rack_test_session(name = :default) + return build_rack_test_session(name) unless name + + @_rack_test_sessions ||= {} + @_rack_test_sessions[name] ||= build_rack_test_session(name) + end + + def build_rack_test_session(name) + Rack::Test::Session.new(rack_mock_session(name)) + end + + def current_session + rack_test_session(_current_session_names.last) + end + + def with_session(name) + _current_session_names.push(name) + yield rack_test_session(name) + _current_session_names.pop + end + + def _current_session_names + @_current_session_names ||= [:default] + end + + METHODS = [ + :request, + + # HTTP verbs + :get, + :post, + :put, + :delete, + :head, + + # Redirects + :follow_redirect!, + + # Header-related features + :header, + :set_cookie, + :clear_cookies, + :authorize, + :basic_authorize, + :digest_authorize, + + # Expose the last request and response + :last_response, + :last_request + ] + + def_delegators :current_session, *METHODS + end + end +end diff --git a/vendor/rack-test/lib/rack/test/mock_digest_request.rb b/vendor/rack-test/lib/rack/test/mock_digest_request.rb new file mode 100644 index 00000000..81c398ba --- /dev/null +++ b/vendor/rack-test/lib/rack/test/mock_digest_request.rb @@ -0,0 +1,27 @@ +module Rack + module Test + + class MockDigestRequest + def initialize(params) + @params = params + end + + def method_missing(sym) + if @params.has_key? k = sym.to_s + return @params[k] + end + + super + end + + def method + @params['method'] + end + + def response(password) + Rack::Auth::Digest::MD5.new(nil).send :digest, self, password + end + end + + end +end diff --git a/vendor/rack-test/lib/rack/test/uploaded_file.rb b/vendor/rack-test/lib/rack/test/uploaded_file.rb new file mode 100644 index 00000000..239302fb --- /dev/null +++ b/vendor/rack-test/lib/rack/test/uploaded_file.rb @@ -0,0 +1,36 @@ +require "tempfile" + +module Rack + module Test + + class UploadedFile + # The filename, *not* including the path, of the "uploaded" file + attr_reader :original_filename + + # The content type of the "uploaded" file + attr_accessor :content_type + + def initialize(path, content_type = "text/plain", binary = false) + raise "#{path} file does not exist" unless ::File.exist?(path) + @content_type = content_type + @original_filename = ::File.basename(path) + @tempfile = Tempfile.new(@original_filename) + @tempfile.set_encoding(Encoding::BINARY) if @tempfile.respond_to?(:set_encoding) + @tempfile.binmode if binary + FileUtils.copy_file(path, @tempfile.path) + end + + def path + @tempfile.path + end + + alias_method :local_path, :path + + def method_missing(method_name, *args, &block) #:nodoc: + @tempfile.__send__(method_name, *args, &block) + end + + end + + end +end diff --git a/vendor/rack-test/lib/rack/test/utils.rb b/vendor/rack-test/lib/rack/test/utils.rb new file mode 100644 index 00000000..d25b8497 --- /dev/null +++ b/vendor/rack-test/lib/rack/test/utils.rb @@ -0,0 +1,75 @@ +module Rack + module Test + + module Utils + include Rack::Utils + + def requestify(value, prefix = nil) + case value + when Array + value.map do |v| + requestify(v, "#{prefix}[]") + end.join("&") + when Hash + value.map do |k, v| + requestify(v, prefix ? "#{prefix}[#{escape(k)}]" : escape(k)) + end.join("&") + else + "#{prefix}=#{escape(value)}" + end + end + + module_function :requestify + + def multipart_requestify(params, first=true) + p = Hash.new + + params.each do |key, value| + k = first ? key.to_s : "[#{key}]" + + if Hash === value + multipart_requestify(value, false).each do |subkey, subvalue| + p[k + subkey] = subvalue + end + else + p[k] = value + end + end + + return p + end + + module_function :multipart_requestify + + def multipart_body(params) + multipart_requestify(params).map do |key, value| + if value.respond_to?(:original_filename) + ::File.open(value.path, "rb") do |f| + f.set_encoding(Encoding::BINARY) if f.respond_to?(:set_encoding) + + <<-EOF +--#{MULTIPART_BOUNDARY}\r +Content-Disposition: form-data; name="#{key}"; filename="#{escape(value.original_filename)}"\r +Content-Type: #{value.content_type}\r +Content-Length: #{::File.stat(value.path).size}\r +\r +#{f.read}\r +EOF + end + else +<<-EOF +--#{MULTIPART_BOUNDARY}\r +Content-Disposition: form-data; name="#{key}"\r +\r +#{value}\r +EOF + end + end.join("")+"--#{MULTIPART_BOUNDARY}--\r" + end + + module_function :multipart_body + + end + + end +end diff --git a/vendor/rack-test/spec/fixtures/config.ru b/vendor/rack-test/spec/fixtures/config.ru new file mode 100644 index 00000000..407c9b94 --- /dev/null +++ b/vendor/rack-test/spec/fixtures/config.ru @@ -0,0 +1,3 @@ +require "fake_app" + +run Rack::Test::FakeApp diff --git a/vendor/rack-test/spec/fixtures/fake_app.rb b/vendor/rack-test/spec/fixtures/fake_app.rb new file mode 100644 index 00000000..3b2a7541 --- /dev/null +++ b/vendor/rack-test/spec/fixtures/fake_app.rb @@ -0,0 +1,109 @@ +require "sinatra/base" + +module Rack + module Test + + class FakeApp < Sinatra::Default + head "/" do + "meh" + end + + get "/" do + "Hello, GET: #{params.inspect}" + end + + get "/redirect" do + redirect "/redirected" + end + + get "/redirected" do + "You've been redirected" + end + + get "/void" do + [200, {}, ""] + end + + get "/cookies/show" do + request.cookies.inspect + end + + get "/COOKIES/show" do + request.cookies.inspect + end + + get "/not-cookies/show" do + request.cookies.inspect + end + + get "/cookies/set-secure" do + raise if params["value"].nil? + + response.set_cookie("secure-cookie", :value => params["value"], :secure => true) + "Set" + end + + get "/cookies/set-simple" do + raise if params["value"].nil? + + response.set_cookie "simple", params["value"] + "Set" + end + + get "/cookies/delete" do + response.delete_cookie "value" + end + + get "/cookies/count" do + old_value = request.cookies["count"].to_i || 0 + new_value = (old_value + 1).to_s + + response.set_cookie("count", :value => new_value) + new_value + end + + get "/cookies/set" do + raise if params["value"].nil? + + response.set_cookie("value", { + :value => params["value"], + :path => "/cookies", + :expires => Time.now + 10 + }) + "Set" + end + + get "/cookies/domain" do + old_value = request.cookies["count"].to_i || 0 + new_value = (old_value + 1).to_s + + response.set_cookie("count", :value => new_value, :domain => "localhost.com") + new_value + end + + get "/cookies/set-uppercase" do + raise if params["value"].nil? + + response.set_cookie("VALUE", { + :value => params["value"], + :path => "/cookies", + :expires => Time.now + 10 + }) + "Set" + end + + post "/" do + "Hello, POST: #{params.inspect}" + end + + put "/" do + "Hello, PUT: #{params.inspect}" + end + + delete "/" do + "Hello, DELETE: #{params.inspect}" + end + end + + end +end diff --git a/vendor/rack-test/spec/fixtures/foo.txt b/vendor/rack-test/spec/fixtures/foo.txt new file mode 100644 index 00000000..5716ca59 --- /dev/null +++ b/vendor/rack-test/spec/fixtures/foo.txt @@ -0,0 +1 @@ +bar diff --git a/vendor/rack-test/spec/rack/test/cookie_spec.rb b/vendor/rack-test/spec/rack/test/cookie_spec.rb new file mode 100644 index 00000000..a008d9c6 --- /dev/null +++ b/vendor/rack-test/spec/rack/test/cookie_spec.rb @@ -0,0 +1,176 @@ +require File.dirname(__FILE__) + "/../../spec_helper" + +describe Rack::Test::Session do + def have_body(string) + simple_matcher "have body #{string.inspect}" do |response| + response.body.should == string + end + end + + context "cookies" do + it "keeps a cookie jar" do + get "/cookies/show" + last_request.cookies.should == {} + + get "/cookies/set", "value" => "1" + get "/cookies/show" + last_request.cookies.should == { "value" => "1" } + end + + it "doesn't send expired cookies" do + get "/cookies/set", "value" => "1" + now = Time.now + Time.stub!(:now => now + 60) + get "/cookies/show" + last_request.cookies.should == {} + end + + it "doesn't send cookies with the wrong domain" do + get "http://www.example.com/cookies/set", "value" => "1" + get "http://www.other.example/cookies/show" + last_request.cookies.should == {} + end + + it "doesn't send cookies with the wrong path" do + get "/cookies/set", "value" => "1" + get "/not-cookies/show" + last_request.cookies.should == {} + end + + it "persists cookies across requests that don't return any cookie headers" do + get "/cookies/set", "value" => "1" + get "/void" + get "/cookies/show" + last_request.cookies.should == { "value" => "1" } + end + + it "deletes cookies" do + get "/cookies/set", "value" => "1" + get "/cookies/delete" + get "/cookies/show" + last_request.cookies.should == { } + end + + xit "respects cookie domains when no domain is explicitly set" do + request("http://example.org/cookies/count").should have_body("1") + request("http://www.example.org/cookies/count").should have_body("1") + request("http://example.org/cookies/count").should have_body("2") + request("http://www.example.org/cookies/count").should have_body("2") + end + + it "treats domains case insensitively" do + get "http://example.com/cookies/set", "value" => "1" + get "http://EXAMPLE.COM/cookies/show" + last_request.cookies.should == { "value" => "1" } + end + + it "treats paths case sensitively" do + get "/cookies/set", "value" => "1" + get "/COOKIES/show" + last_request.cookies.should == {} + end + + it "prefers more specific cookies" do + get "http://example.com/cookies/set", "value" => "domain" + get "http://sub.example.com/cookies/set", "value" => "sub" + + get "http://sub.example.com/cookies/show" + last_request.cookies.should == { "value" => "sub" } + + get "http://example.com/cookies/show" + last_request.cookies.should == { "value" => "domain" } + end + + it "treats cookie names case insensitively" do + get "/cookies/set", "value" => "lowercase" + get "/cookies/set-uppercase", "value" => "UPPERCASE" + get "/cookies/show" + last_request.cookies.should == { "VALUE" => "UPPERCASE" } + end + + it "defaults the domain to the request domain" do + get "http://example.com/cookies/set-simple", "value" => "cookie" + get "http://example.com/cookies/show" + last_request.cookies.should == { "simple" => "cookie" } + + get "http://other.example/cookies/show" + last_request.cookies.should == {} + end + + it "defaults the domain to the request path up to the last slash" do + get "/cookies/set-simple", "value" => "1" + get "/not-cookies/show" + last_request.cookies.should == {} + end + + it "supports secure cookies" do + get "https://example.com/cookies/set-secure", "value" => "set" + get "http://example.com/cookies/show" + last_request.cookies.should == {} + + get "https://example.com/cookies/show" + last_request.cookies.should == { "secure-cookie" => "set" } + end + + it "keeps separate cookie jars for different domains" do + get "http://example.com/cookies/set", "value" => "example" + get "http://example.com/cookies/show" + last_request.cookies.should == { "value" => "example" } + + get "http://other.example/cookies/set", "value" => "other" + get "http://other.example/cookies/show" + last_request.cookies.should == { "value" => "other" } + + get "http://example.com/cookies/show" + last_request.cookies.should == { "value" => "example" } + end + + it "allows cookies to be cleared" do + get "/cookies/set", "value" => "1" + clear_cookies + get "/cookies/show" + last_request.cookies.should == {} + end + + it "allow cookies to be set" do + set_cookie "value=10" + get "/cookies/show" + last_request.cookies.should == { "value" => "10" } + end + + it "allows an array of cookies to be set" do + set_cookie ["value=10", "foo=bar"] + get "/cookies/show" + last_request.cookies.should == { "value" => "10", "foo" => "bar" } + end + + it "supports multiple sessions" do + with_session(:first) do + get "/cookies/set", "value" => "1" + get "/cookies/show" + last_request.cookies.should == { "value" => "1" } + end + + with_session(:second) do + get "/cookies/show" + last_request.cookies.should == { } + end + end + + it "uses :default as the default session name" do + get "/cookies/set", "value" => "1" + get "/cookies/show" + last_request.cookies.should == { "value" => "1" } + + with_session(:default) do + get "/cookies/show" + last_request.cookies.should == { "value" => "1" } + end + end + + it "accepts explicitly provided cookies" do + request "/cookies/show", :cookie => "value=1" + last_request.cookies.should == { "value" => "1" } + end + end +end diff --git a/vendor/rack-test/spec/rack/test/digest_auth_spec.rb b/vendor/rack-test/spec/rack/test/digest_auth_spec.rb new file mode 100644 index 00000000..9e7de744 --- /dev/null +++ b/vendor/rack-test/spec/rack/test/digest_auth_spec.rb @@ -0,0 +1,48 @@ +require File.dirname(__FILE__) + "/../../spec_helper" + +describe Rack::Test::Session do + context "HTTP Digest authentication" do + + def app + app = Rack::Auth::Digest::MD5.new(Rack::Test::FakeApp.new) do |username| + { 'alice' => 'correct-password' }[username] + end + app.realm = 'WallysWorld' + app.opaque = 'this-should-be-secret' + app + end + + def be_challenge + simple_matcher "a HTTP Digest challenge response" do |response| + response.status == 401 && + response['WWW-Authenticate'] =~ /^Digest / && + response.body.empty? + end + end + + it 'incorrectly authenticates GETs' do + digest_authorize 'foo', 'bar' + get '/' + last_response.should be_challenge + end + + it "correctly authenticates GETs" do + digest_authorize "alice", "correct-password" + response = get "/" + response.should be_ok + end + + it "correctly authenticates POSTs" do + digest_authorize "alice", "correct-password" + response = post "/" + response.should be_ok + end + + it "returns a re-challenge if authenticating incorrectly" do + digest_authorize "alice", "incorrect-password" + response = get "/" + response.should be_challenge + end + + end +end diff --git a/vendor/rack-test/spec/rack/test/multipart_spec.rb b/vendor/rack-test/spec/rack/test/multipart_spec.rb new file mode 100644 index 00000000..12351847 --- /dev/null +++ b/vendor/rack-test/spec/rack/test/multipart_spec.rb @@ -0,0 +1,85 @@ +require File.dirname(__FILE__) + "/../../spec_helper" + +describe Rack::Test::Session do + + def test_file_path + File.dirname(__FILE__) + "/../../fixtures/foo.txt" + end + + def uploaded_file + Rack::Test::UploadedFile.new(test_file_path) + end + + context "uploading a file" do + it "sends the multipart/form-data content type" do + post "/", "photo" => uploaded_file + last_request.env["CONTENT_TYPE"].should include("multipart/form-data;") + end + + it "sends regular params" do + post "/", "photo" => uploaded_file, "foo" => "bar" + last_request.POST["foo"].should == "bar" + end + + it "sends nested params" do + post "/", "photo" => uploaded_file, "foo" => {"bar" => "baz"} + last_request.POST["foo"]["bar"].should == "baz" + end + + it "sends multiple nested params" do + post "/", "photo" => uploaded_file, "foo" => {"bar" => {"baz" => "bop"}} + last_request.POST["foo"]["bar"]["baz"].should == "bop" + end + + xit "sends params with arrays" do + post "/", "photo" => uploaded_file, "foo" => ["1", "2"] + last_request.POST["foo[]"].should == ["1", "2"] + end + + it "sends params with encoding sensitive values" do + post "/", "photo" => uploaded_file, "foo" => "bar? baz" + last_request.POST["foo"].should == "bar? baz" + end + + it "sends params with parens in names" do + post "/", "photo" => uploaded_file, "foo(1i)" => "bar" + last_request.POST["foo(1i)"].should == "bar" + end + + it "sends params with encoding sensitive names" do + post "/", "photo" => uploaded_file, "foo bar" => "baz" + last_request.POST["foo bar"].should == "baz" + end + + it "sends files with the filename" do + post "/", "photo" => uploaded_file + last_request.POST["photo"][:filename].should == "foo.txt" + end + + it "sends files with the text/plain MIME type by default" do + post "/", "photo" => uploaded_file + last_request.POST["photo"][:type].should == "text/plain" + end + + it "sends files with the right name" do + post "/", "photo" => uploaded_file + last_request.POST["photo"][:name].should == "photo" + end + + it "allows overriding the content type" do + post "/", "photo" => Rack::Test::UploadedFile.new(test_file_path, "image/jpeg") + last_request.POST["photo"][:type].should == "image/jpeg" + end + + it "sends files with a Content-Length in the header" do + post "/", "photo" => uploaded_file + last_request.POST["photo"][:head].should include("Content-Length: 4") + end + + it "sends files as Tempfiles" do + post "/", "photo" => uploaded_file + last_request.POST["photo"][:tempfile].should be_a(::Tempfile) + end + end + +end diff --git a/vendor/rack-test/spec/rack/test/utils_spec.rb b/vendor/rack-test/spec/rack/test/utils_spec.rb new file mode 100644 index 00000000..0a38811d --- /dev/null +++ b/vendor/rack-test/spec/rack/test/utils_spec.rb @@ -0,0 +1,44 @@ +require File.dirname(__FILE__) + "/../../spec_helper" + +describe Rack::Test::Utils do + include Rack::Test::Utils + + describe "requestify" do + it "converts empty strings to =" do + requestify("").should == "=" + end + + it "converts nil to =" do + requestify(nil).should == "=" + end + + it "converts hashes" do + requestify(:a => 1).should == "a=1" + end + + it "converts hashes with multiple keys" do + hash = { :a => 1, :b => 2 } + ["a=1&b=2", "b=2&a=1"].should include(requestify(hash)) + end + + it "converts arrays with one element" do + requestify(:a => [1]).should == "a[]=1" + end + + it "converts arrays with multiple elements" do + requestify(:a => [1, 2]).should == "a[]=1&a[]=2" + end + + it "converts nested hashes" do + requestify(:a => { :b => 1 }).should == "a[b]=1" + end + + it "converts arrays nested in a hash" do + requestify(:a => { :b => [1, 2] }).should == "a[b][]=1&a[b][]=2" + end + + it "converts arrays of hashes" do + requestify(:a => [{ :b => 2}, { :c => 3}]).should == "a[][b]=2&a[][c]=3" + end + end +end diff --git a/vendor/rack-test/spec/rack/test_spec.rb b/vendor/rack-test/spec/rack/test_spec.rb new file mode 100644 index 00000000..332fbc61 --- /dev/null +++ b/vendor/rack-test/spec/rack/test_spec.rb @@ -0,0 +1,363 @@ +require File.dirname(__FILE__) + "/../spec_helper" + +describe Rack::Test::Session do + describe "initialization" do + it "supports being initialized with a Rack::MockSession app" do + session = Rack::Test::Session.new(Rack::MockSession.new(app)) + session.request("/").should be_ok + end + + it "supports being initialized with an app" do + session = Rack::Test::Session.new(app) + session.request("/").should be_ok + end + end + + describe "#request" do + it "requests the URI using GET by default" do + request "/" + last_request.should be_get + last_response.should be_ok + end + + it "returns a response" do + request("/").should be_ok + end + + it "uses the provided env" do + request "/", "X-Foo" => "bar" + last_request.env["X-Foo"].should == "bar" + end + + it "defaults to GET" do + request "/" + last_request.env["REQUEST_METHOD"].should == "GET" + end + + it "defaults the REMOTE_ADDR to 127.0.0.1" do + request "/" + last_request.env["REMOTE_ADDR"].should == "127.0.0.1" + end + + it "sets rack.test to true in the env" do + request "/" + last_request.env["rack.test"].should == true + end + + it "defaults to port 80" do + request "/" + last_request.env["SERVER_PORT"].should == "80" + end + + it "defaults to example.org" do + request "/" + last_request.env["SERVER_NAME"].should == "example.org" + end + + it "yields the response to a given block" do + request "/" do |response| + response.should be_ok + end + end + + it "supports sending :params" do + request "/", :params => { "foo" => "bar" } + last_request.GET["foo"].should == "bar" + end + + it "doesn't follow redirects by default" do + request "/redirect" + last_response.should be_redirect + last_response.body.should be_empty + end + + context "when input is given" do + it "should send the input" do + request "/", :method => "POST", :input => "foo" + last_request.env["rack.input"].read.should == "foo" + end + + it "should not send a multipart request" do + request "/", :method => "POST", :input => "foo" + last_request.env["CONTENT_TYPE"].should_not == "application/x-www-form-urlencoded" + end + end + + context "for a POST specified with :method" do + it "uses application/x-www-form-urlencoded as the CONTENT_TYPE" do + request "/", :method => "POST" + last_request.env["CONTENT_TYPE"].should == "application/x-www-form-urlencoded" + end + end + + context "for a POST specified with REQUEST_METHOD" do + it "uses application/x-www-form-urlencoded as the CONTENT_TYPE" do + request "/", "REQUEST_METHOD" => "POST" + last_request.env["CONTENT_TYPE"].should == "application/x-www-form-urlencoded" + end + end + + context "when CONTENT_TYPE is specified in the env" do + it "does not overwrite the CONTENT_TYPE" do + request "/", "CONTENT_TYPE" => "application/xml" + last_request.env["CONTENT_TYPE"].should == "application/xml" + end + end + + context "when the URL is https://" do + it "sets SERVER_PORT to 443" do + get "https://example.org/" + last_request.env["SERVER_PORT"].should == "443" + end + + it "sets HTTPS to on" do + get "https://example.org/" + last_request.env["HTTPS"].should == "on" + end + end + + context "for a XHR" do + it "sends XMLHttpRequest for the X-Requested-With header" do + request "/", :xhr => true + last_request.env["X-Requested-With"].should == "XMLHttpRequest" + end + end + end + + describe "#header" do + it "sets a header to be sent with requests" do + header "User-Agent", "Firefox" + request "/" + + last_request.env["User-Agent"].should == "Firefox" + end + + it "persists across multiple requests" do + header "User-Agent", "Firefox" + request "/" + request "/" + + last_request.env["User-Agent"].should == "Firefox" + end + + it "overwrites previously set headers" do + header "User-Agent", "Firefox" + header "User-Agent", "Safari" + request "/" + + last_request.env["User-Agent"].should == "Safari" + end + + it "can be used to clear a header" do + header "User-Agent", "Firefox" + header "User-Agent", nil + request "/" + + last_request.env.should_not have_key("User-Agent") + end + + it "is overridden by headers sent during the request" do + header "User-Agent", "Firefox" + request "/", "User-Agent" => "Safari" + + last_request.env["User-Agent"].should == "Safari" + end + end + + describe "#authorize" do + it "sets the HTTP_AUTHORIZATION header" do + authorize "bryan", "secret" + request "/" + + last_request.env["HTTP_AUTHORIZATION"].should == "Basic YnJ5YW46c2VjcmV0\n" + end + + it "includes the header for subsequent requests" do + basic_authorize "bryan", "secret" + request "/" + request "/" + + last_request.env["HTTP_AUTHORIZATION"].should == "Basic YnJ5YW46c2VjcmV0\n" + end + end + + describe "follow_redirect!" do + it "follows redirects" do + get "/redirect" + follow_redirect! + + last_response.should_not be_redirect + last_response.body.should == "You've been redirected" + end + + it "does not include params when following the redirect" do + get "/redirect", { "foo" => "bar" } + follow_redirect! + + last_request.GET.should == {} + end + + it "raises an error if the last_response is not set" do + lambda { + follow_redirect! + }.should raise_error(Rack::Test::Error) + end + + it "raises an error if the last_response is not a redirect" do + get "/" + + lambda { + follow_redirect! + }.should raise_error(Rack::Test::Error) + end + end + + describe "#last_request" do + it "returns the most recent request" do + request "/" + last_request.env["PATH_INFO"].should == "/" + end + + it "raises an error if no requests have been issued" do + lambda { + last_request + }.should raise_error(Rack::Test::Error) + end + end + + describe "#last_response" do + it "returns the most recent response" do + request "/" + last_response["Content-Type"].should == "text/html" + end + + it "raises an error if no requests have been issued" do + lambda { + last_response + }.should raise_error + end + end + + describe "after_request" do + it "runs callbacks after each request" do + ran = false + + rack_mock_session.after_request do + ran = true + end + + get "/" + ran.should == true + end + + it "runs multiple callbacks" do + count = 0 + + 2.times do + rack_mock_session.after_request do + count += 1 + end + end + + get "/" + count.should == 2 + end + end + + describe "#get" do + it_should_behave_like "any #verb methods" + + def verb + "get" + end + + it "uses the provided params hash" do + get "/", :foo => "bar" + last_request.GET.should == { "foo" => "bar" } + end + + it "sends params with parens in names" do + get "/", "foo(1i)" => "bar" + last_request.GET["foo(1i)"].should == "bar" + end + + it "supports params with encoding sensitive names" do + get "/", "foo bar" => "baz" + last_request.GET["foo bar"].should == "baz" + end + + it "supports params with nested encoding sensitive names" do + get "/", "boo" => {"foo bar" => "baz"} + last_request.GET.should == {"boo" => {"foo bar" => "baz"}} + end + + it "accepts params in the path" do + get "/?foo=bar" + last_request.GET.should == { "foo" => "bar" } + end + end + + describe "#head" do + it_should_behave_like "any #verb methods" + + def verb + "head" + end + end + + describe "#post" do + it_should_behave_like "any #verb methods" + + def verb + "post" + end + + it "uses the provided params hash" do + post "/", :foo => "bar" + last_request.POST.should == { "foo" => "bar" } + end + + it "supports params with encoding sensitive names" do + post "/", "foo bar" => "baz" + last_request.POST["foo bar"].should == "baz" + end + + it "uses application/x-www-form-urlencoded as the CONTENT_TYPE" do + post "/" + last_request.env["CONTENT_TYPE"].should == "application/x-www-form-urlencoded" + end + + it "accepts a body" do + post "/", "Lobsterlicious!" + last_request.body.read.should == "Lobsterlicious!" + end + + context "when CONTENT_TYPE is specified in the env" do + it "does not overwrite the CONTENT_TYPE" do + post "/", {}, { "CONTENT_TYPE" => "application/xml" } + last_request.env["CONTENT_TYPE"].should == "application/xml" + end + end + end + + describe "#put" do + it_should_behave_like "any #verb methods" + + def verb + "put" + end + + it "accepts a body" do + put "/", "Lobsterlicious!" + last_request.body.read.should == "Lobsterlicious!" + end + end + + describe "#delete" do + it_should_behave_like "any #verb methods" + + def verb + "delete" + end + end +end diff --git a/vendor/rack-test/spec/rcov.opts b/vendor/rack-test/spec/rcov.opts new file mode 100644 index 00000000..9ed978e1 --- /dev/null +++ b/vendor/rack-test/spec/rcov.opts @@ -0,0 +1 @@ +-x gems,spec diff --git a/vendor/rack-test/spec/spec.opts b/vendor/rack-test/spec/spec.opts new file mode 100644 index 00000000..4e1e0d2f --- /dev/null +++ b/vendor/rack-test/spec/spec.opts @@ -0,0 +1 @@ +--color diff --git a/vendor/rack-test/spec/spec_helper.rb b/vendor/rack-test/spec/spec_helper.rb new file mode 100644 index 00000000..c18479ef --- /dev/null +++ b/vendor/rack-test/spec/spec_helper.rb @@ -0,0 +1,48 @@ +require "rubygems" +require "spec" + +gem "rack", "~> 1.0.0" + +require File.expand_path(File.dirname(__FILE__) + "/../lib/rack/test") +require File.dirname(__FILE__) + "/fixtures/fake_app" + +Spec::Runner.configure do |config| + config.include Rack::Test::Methods + + def app + Rack::Lint.new(Rack::Test::FakeApp.new) + end + +end + +describe "any #verb methods", :shared => true do + it "requests the URL using VERB" do + send(verb, "/") + + last_request.env["REQUEST_METHOD"].should == verb.upcase + last_response.should be_ok + end + + it "uses the provided env" do + send(verb, "/", {}, { "User-Agent" => "Rack::Test" }) + last_request.env["User-Agent"].should == "Rack::Test" + end + + it "yields the response to a given block" do + yielded = false + + send(verb, "/") do |response| + response.should be_ok + yielded = true + end + + yielded.should be_true + end + + context "for a XHR" do + it "sends XMLHttpRequest for the X-Requested-With header" do + send(verb, "/", {}, { :xhr => true }) + last_request.env["X-Requested-With"].should == "XMLHttpRequest" + end + end +end diff --git a/vendor/sinatra-content-for/LICENSE b/vendor/sinatra-content-for/LICENSE new file mode 100644 index 00000000..3eb6c2f4 --- /dev/null +++ b/vendor/sinatra-content-for/LICENSE @@ -0,0 +1,22 @@ +(The MIT License) + +Copyright (c) 2008-2009 Nicolas Sanguinetti, entp.com + +Permission is hereby granted, free of charge, to any person obtaining +a copy of this software and associated documentation files (the +'Software'), to deal in the Software without restriction, including +without limitation the rights to use, copy, modify, merge, publish, +distribute, sublicense, and/or sell copies of the Software, and to +permit persons to whom the Software is furnished to do so, subject to +the following conditions: + +The above copyright notice and this permission notice shall be +included in all copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED 'AS IS', WITHOUT WARRANTY OF ANY KIND, +EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF +MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. +IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY +CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, +TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE +SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. diff --git a/vendor/sinatra-content-for/README.rdoc b/vendor/sinatra-content-for/README.rdoc new file mode 100644 index 00000000..cf7c2abb --- /dev/null +++ b/vendor/sinatra-content-for/README.rdoc @@ -0,0 +1,49 @@ += ContentFor + +Small extension for the Sinatra[http://sinatrarb.com] web framework +that allows you to use the following helpers in your views: + + <% content_for :some_key do %> + ... + <% end %> + + <% yield_content :some_key %> + +This allows you to capture blocks inside views to be rendered later +in this request. For example, to populate different parts of your +layout from your view. + +When using this with the Haml rendering engine, you should do the +following: + + - content_for :some_key do + %chunk{ :of => "html" } ... + + = yield_content :some_key + +Note that with ERB yield_content is called without +an '=' block (<%= %>), but with Haml it uses = yield_content. + +Using an '=' block in ERB will output the content twice for each block, +so if you have problems with that, make sure to check for this. + +== Usage + +If you're writing "classic" style apps, then requring +sinatra/content_for should be enough. If you're writing +"classy" apps, then you also need to call +helpers Sinatra::ContentFor in your app definition. + +== And how is this useful? + +For example, some of your views might need a few javascript tags and +stylesheets, but you don't want to force this files in all your pages. +Then you can put <% yield_content :scripts_and_styles %> on +your layout, inside the tag, and each view can call +content_for setting the appropriate set of tags that should +be added to the layout. + +== Credits + +Code by foca[http://github.com/foca], inspired on the Ruby on Rails +helpers with the same name. Haml support by mattly[http://github.com/mattly]. diff --git a/vendor/sinatra-content-for/Rakefile b/vendor/sinatra-content-for/Rakefile new file mode 100644 index 00000000..37989821 --- /dev/null +++ b/vendor/sinatra-content-for/Rakefile @@ -0,0 +1,33 @@ +require "rake/testtask" + +begin + require "hanna/rdoctask" +rescue LoadError + require "rake/rdoctask" +end + +begin + require "metric_fu" +rescue LoadError +end + +begin + require "mg" + MG.new("sinatra-content-for.gemspec") +rescue LoadError +end + +desc "Default: run all tests" +task :default => :test + +desc "Run library tests" +Rake::TestTask.new do |t| + t.test_files = FileList['test/**/*_test.rb'] +end + +Rake::RDocTask.new do |rd| + rd.main = "README" + rd.title = "Documentation for ContentFor" + rd.rdoc_files.include("README.rdoc", "LICENSE", "lib/**/*.rb") + rd.rdoc_dir = "doc" +end diff --git a/vendor/sinatra-content-for/lib/sinatra/content_for.rb b/vendor/sinatra-content-for/lib/sinatra/content_for.rb new file mode 100644 index 00000000..31848c63 --- /dev/null +++ b/vendor/sinatra-content-for/lib/sinatra/content_for.rb @@ -0,0 +1,58 @@ +module Sinatra + module ContentFor + # Capture a block of content to be rendered later. For example: + # + # <% content_for :head do %> + # + # <% end %> + # + # You can call +content_for+ multiple times with the same key + # (in the example +:head+), and when you render the blocks for + # that key all of them will be rendered, in the same order you + # captured them. + # + # Your blocks can also receive values, which are passed to them + # by yield_content + def content_for(key, &block) + content_blocks[key.to_sym] << block + end + + # Render the captured blocks for a given key. For example: + # + # + # Example + # <% yield_content :head %> + # + # + # Would render everything you declared with content_for + # :head before closing the tag. + # + # You can also pass values to the content blocks by passing them + # as arguments after the key: + # + # <% yield_content :head, 1, 2 %> + # + # Would pass 1 and 2 to all the blocks registered + # for :head. + # + # *NOTICE* that you call this without an = sign. IE, + # in a <% %> block, and not in a <%= %> block. + def yield_content(key, *args) + content_blocks[key.to_sym].map do |content| + if respond_to?(:block_is_haml?) && block_is_haml?(content) + capture_haml(*args, &content) + else + content.call(*args) + end + end.join + end + + private + + def content_blocks + @content_blocks ||= Hash.new {|h,k| h[k] = [] } + end + end + + helpers ContentFor +end diff --git a/vendor/sinatra-content-for/sinatra-content-for.gemspec b/vendor/sinatra-content-for/sinatra-content-for.gemspec new file mode 100644 index 00000000..63242e6b --- /dev/null +++ b/vendor/sinatra-content-for/sinatra-content-for.gemspec @@ -0,0 +1,34 @@ +Gem::Specification.new do |s| + s.name = "sinatra-content-for" + s.version = "0.2" + s.date = "2009-05-09" + + s.description = "Small Sinatra extension to add a content_for helper similar to Rails'" + s.summary = "Small Sinatra extension to add a content_for helper similar to Rails'" + s.homepage = "http://sinatrarb.com" + + s.authors = ["Nicolás Sanguinetti"] + s.email = "contacto@nicolassanguinetti.info" + + s.require_paths = ["lib"] + s.rubyforge_project = "sinatra-ditties" + s.has_rdoc = true + s.rubygems_version = "1.3.1" + + s.add_dependency "sinatra" + + if s.respond_to?(:add_development_dependency) + s.add_development_dependency "contest" + s.add_development_dependency "sr-mg" + s.add_development_dependency "redgreen" + end + + s.files = %w[ +.gitignore +LICENSE +README.rdoc +sinatra-content-for.gemspec +lib/sinatra/content_for.rb +test/content_for_test.rb +] +end diff --git a/vendor/sinatra-content-for/test/content_for_test.rb b/vendor/sinatra-content-for/test/content_for_test.rb new file mode 100644 index 00000000..c9560f22 --- /dev/null +++ b/vendor/sinatra-content-for/test/content_for_test.rb @@ -0,0 +1,156 @@ +ENV['RACK_ENV'] = 'test' + +begin + require 'rack' +rescue LoadError + require 'rubygems' + require 'rack' +end + +require 'contest' +require 'sinatra/test' +require 'haml' + +begin + require 'redgreen' +rescue LoadError +end + +require File.dirname(__FILE__) + '/../lib/sinatra/content_for' + +Sinatra::Base.set :environment, :test + +module Sinatra + class Base + set :environment, :test + helpers ContentFor + end +end + +class Test::Unit::TestCase + include Sinatra::Test + + class << self + alias_method :it, :test + end + + def mock_app(base=Sinatra::Base, &block) + @app = Sinatra.new(base, &block) + end +end + +class ContentForTest < Test::Unit::TestCase + context 'using erb' do + def erb_app(view) + mock_app { + layout { '<% yield_content :foo %>' } + get('/') { erb view } + } + end + + it 'renders blocks declared with the same key you use when rendering' do + erb_app '<% content_for :foo do %>foo<% end %>' + + get '/' + assert ok? + assert_equal 'foo', body + end + + it 'does not render a block with a different key' do + erb_app '<% content_for :bar do %>bar<% end %>' + + get '/' + assert ok? + assert_equal '', body + end + + it 'renders multiple blocks with the same key' do + erb_app <<-erb_snippet + <% content_for :foo do %>foo<% end %> + <% content_for :foo do %>bar<% end %> + <% content_for :baz do %>WON'T RENDER ME<% end %> + <% content_for :foo do %>baz<% end %> + erb_snippet + + get '/' + assert ok? + assert_equal 'foobarbaz', body + end + + it 'passes values to the blocks' do + mock_app { + layout { '<% yield_content :foo, 1, 2 %>' } + get('/') { erb '<% content_for :foo do |a, b| %><%= a %> <%= b %><% end %>' } + } + + get '/' + assert ok? + assert_equal '1 2', body + end + end + + context 'with haml' do + def haml_app(view) + mock_app { + layout { '= yield_content :foo' } + get('/') { haml view } + } + end + + it 'renders blocks declared with the same key you use when rendering' do + haml_app <<-haml_end +- content_for :foo do + foo +haml_end + + get '/' + assert ok? + assert_equal "foo\n", body + end + + it 'does not render a block with a different key' do + haml_app <<-haml_end +- content_for :bar do + bar +haml_end + + get '/' + assert ok? + assert_equal "\n", body + end + + it 'renders multiple blocks with the same key' do + haml_app <<-haml_end +- content_for :foo do + foo +- content_for :foo do + bar +- content_for :baz do + WON'T RENDER ME +- content_for :foo do + baz +haml_end + + get '/' + assert ok? + assert_equal "foo\nbar\nbaz\n", body + end + + it 'passes values to the blocks' do + mock_app { + layout { '= yield_content :foo, 1, 2' } + get('/') { + haml <<-haml_end +- content_for :foo do |a, b| + %i= a + =b +haml_end + } + } + + get '/' + assert ok? + assert_equal "1\n2\n", body + end + end +end diff --git a/vendor/sinatra-markaby/CHANGES b/vendor/sinatra-markaby/CHANGES new file mode 100644 index 00000000..802e5133 --- /dev/null +++ b/vendor/sinatra-markaby/CHANGES @@ -0,0 +1,7 @@ += 0.9.2.2 + +* layout support is tested + += 0.9.2.1 + +* use Rack::Test instead of Sinatra::Test diff --git a/vendor/sinatra-markaby/LICENSE b/vendor/sinatra-markaby/LICENSE new file mode 100644 index 00000000..333cf6f2 --- /dev/null +++ b/vendor/sinatra-markaby/LICENSE @@ -0,0 +1,20 @@ +Copyright (c) 2009 unwwwired.net + +Permission is hereby granted, free of charge, to any person obtaining +a copy of this software and associated documentation files (the +"Software"), to deal in the Software without restriction, including +without limitation the rights to use, copy, modify, merge, publish, +distribute, sublicense, and/or sell copies of the Software, and to +permit persons to whom the Software is furnished to do so, subject to +the following conditions: + +The above copyright notice and this permission notice shall be +included in all copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, +EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF +MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND +NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE +LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION +OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION +WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. diff --git a/vendor/sinatra-markaby/README.rdoc b/vendor/sinatra-markaby/README.rdoc new file mode 100644 index 00000000..0815c81d --- /dev/null +++ b/vendor/sinatra-markaby/README.rdoc @@ -0,0 +1,33 @@ += sinatra-markaby + +sinatra-markaby is an extension for sinatra to enable rendering of html files +using markaby templates. + +== Installation + + sudo gem install sbfaulkner-sinatra-markaby -s http://gems.github.com + +== Example + + require 'rubygems' + require 'sinatra' + require 'sinatra/markaby' + + get '/' do + markaby :template + end + + __END__ + + @@ template + mab.html do + head { title "Hello world" } + body do + p "Hello world!!!!!" + end + end + +== Legal + +Author:: S. Brent Faulkner +License:: Copyright (c) 2009 unwwwired.net, released under the MIT license diff --git a/vendor/sinatra-markaby/Rakefile b/vendor/sinatra-markaby/Rakefile new file mode 100644 index 00000000..bad3f2ee --- /dev/null +++ b/vendor/sinatra-markaby/Rakefile @@ -0,0 +1,45 @@ +require 'rake' + +begin + require 'jeweler' + Jeweler::Tasks.new do |s| + s.name = "sinatra-markaby" + s.summary = %Q{Sinatra plugin to enable markaby (.mab) template rendering.} + s.email = "brentf@unwwwired.net" + s.homepage = "http://github.com/sbfaulkner/sinatra-markaby" + s.description = "Sinatra plugin to enable markaby (.mab) template rendering." + s.authors = ["S. Brent Faulkner"] + s.add_dependency "markaby" + end +rescue LoadError + puts "Jeweler not available. Install it with: sudo gem install technicalpickles-jeweler -s http://gems.github.com" +end + +require 'rake/rdoctask' +Rake::RDocTask.new do |rdoc| + rdoc.rdoc_dir = 'rdoc' + rdoc.title = 'sinatra-markaby' + rdoc.options << '--line-numbers' << '--inline-source' + rdoc.rdoc_files.include('README*') + rdoc.rdoc_files.include('lib/**/*.rb') +end + +require 'rake/testtask' +Rake::TestTask.new(:test) do |t| + t.libs << 'lib' << 'test' + t.pattern = 'test/**/*_test.rb' + t.verbose = false +end + +begin + require 'rcov/rcovtask' + Rcov::RcovTask.new do |t| + t.libs << 'test' + t.test_files = FileList['test/**/*_test.rb'] + t.verbose = true + end +rescue LoadError + puts "RCov is not available. In order to run rcov, you must: sudo gem install spicycode-rcov" +end + +task :default => :test diff --git a/vendor/sinatra-markaby/TODO b/vendor/sinatra-markaby/TODO new file mode 100644 index 00000000..39a2947d --- /dev/null +++ b/vendor/sinatra-markaby/TODO @@ -0,0 +1,3 @@ += TODO + +* refactor render/views in sinatra \ No newline at end of file diff --git a/vendor/sinatra-markaby/VERSION.yml b/vendor/sinatra-markaby/VERSION.yml new file mode 100644 index 00000000..8ee2d0c5 --- /dev/null +++ b/vendor/sinatra-markaby/VERSION.yml @@ -0,0 +1,4 @@ +--- +:major: 0 +:minor: 9 +:patch: 2.2 diff --git a/vendor/sinatra-markaby/lib/sinatra/markaby.rb b/vendor/sinatra-markaby/lib/sinatra/markaby.rb new file mode 100644 index 00000000..611eee04 --- /dev/null +++ b/vendor/sinatra-markaby/lib/sinatra/markaby.rb @@ -0,0 +1,31 @@ +require 'sinatra/base' +require 'markaby' + +module Sinatra + module Markaby + # Generate html file using Markaby. + # Takes the name of a template to render as a Symbol and returns a String with the rendered output. + # + # Options for markaby may be specified in Sinatra using set :markaby, { ... } + # TODO: the options aren't actually used yet + def mab(template=nil, options={}, locals = {}, &block) + options, template = template, nil if template.is_a?(Hash) + template = lambda { block } if template.nil? + render :mab, template, options, locals + end + + protected + def render_mab(template, data, options, locals, &block) + filename = options.delete(:filename) || '' + line = options.delete(:line) || 1 + mab = ::Markaby::Builder.new(locals) + if data.respond_to?(:to_str) + eval(data.to_str, binding, filename, line) + elsif data.kind_of?(Proc) + data.call(mab) + end + end + end + + helpers Markaby +end diff --git a/vendor/sinatra-markaby/sinatra-markaby.gemspec b/vendor/sinatra-markaby/sinatra-markaby.gemspec new file mode 100644 index 00000000..648a4b39 --- /dev/null +++ b/vendor/sinatra-markaby/sinatra-markaby.gemspec @@ -0,0 +1,49 @@ +# -*- encoding: utf-8 -*- + +Gem::Specification.new do |s| + s.name = %q{sinatra-markaby} + s.version = "0.9.2.2" + + s.required_rubygems_version = Gem::Requirement.new(">= 0") if s.respond_to? :required_rubygems_version= + s.authors = ["S. Brent Faulkner"] + s.date = %q{2009-04-29} + s.description = %q{Sinatra plugin to enable markaby (.mab) template rendering.} + s.email = %q{brentf@unwwwired.net} + s.extra_rdoc_files = [ + "LICENSE", + "README.rdoc" + ] + s.files = [ + "LICENSE", + "README.rdoc", + "Rakefile", + "VERSION.yml", + "lib/sinatra/markaby.rb", + "test/sinatra_markaby_test.rb", + "test/test_helper.rb", + "test/views/hello.mab" + ] + s.has_rdoc = true + s.homepage = %q{http://github.com/sbfaulkner/sinatra-markaby} + s.rdoc_options = ["--charset=UTF-8"] + s.require_paths = ["lib"] + s.rubygems_version = %q{1.3.1} + s.summary = %q{Sinatra plugin to enable markaby (.mab) template rendering.} + s.test_files = [ + "test/sinatra_markaby_test.rb", + "test/test_helper.rb" + ] + + if s.respond_to? :specification_version then + current_version = Gem::Specification::CURRENT_SPECIFICATION_VERSION + s.specification_version = 2 + + if Gem::Version.new(Gem::RubyGemsVersion) >= Gem::Version.new('1.2.0') then + s.add_runtime_dependency(%q, [">= 0"]) + else + s.add_dependency(%q, [">= 0"]) + end + else + s.add_dependency(%q, [">= 0"]) + end +end diff --git a/vendor/sinatra-markaby/test/sinatra_markaby_test.rb b/vendor/sinatra-markaby/test/sinatra_markaby_test.rb new file mode 100644 index 00000000..edee03ff --- /dev/null +++ b/vendor/sinatra-markaby/test/sinatra_markaby_test.rb @@ -0,0 +1,72 @@ +require File.dirname(__FILE__) + '/test_helper' + +class SinatraMarkabyTest < Test::Unit::TestCase + def markaby_app(&block) + mock_app { + use_in_file_templates! + helpers Sinatra::Markaby + set :views, File.dirname(__FILE__) + '/views' + get '/', &block + } + get '/' + end + + def test_renders_inline_strings + markaby_app { markaby 'mab.p "Hello shrimp!"' } + assert last_response.ok? + assert_equal '

Hello shrimp!

', last_response.body + end + + def test_renders_inline_blocks + markaby_app { + @name = 'Frank & Mary' + markaby do |mab| + mab.p "Hello #{@name}!" + end + } + assert last_response.ok? + assert_equal '

Hello Frank & Mary!

', last_response.body + end + + def test_renders_markaby_files_in_views_path + markaby_app { + @name = 'World' + markaby :hello + } + assert last_response.ok? + assert_equal '

Hello, World!

', last_response.body + end + + def test_renders_in_file_template + markaby_app { + @name = 'Joe' + markaby :in_file + } + assert last_response.ok? + assert_equal '

Hey Joe

', last_response.body + end + + def test_renders_with_layout + markaby_app { + @name = 'with Layout' + markaby :hello, :layout => :html + } + assert last_response.ok? + assert_equal 'Hello

Hello, with Layout!

', last_response.body + end + + def test_raises_error_if_template_not_found + mock_app { + helpers Sinatra::Markaby + set :environment, :test + set :raise_errors, true + get('/') { markaby :no_such_template } + } + assert_raises(Errno::ENOENT) { get('/') } + end +end + +__END__ + +@@ in_file +mab.p "Hey #{@name}" diff --git a/vendor/sinatra-markaby/test/test_helper.rb b/vendor/sinatra-markaby/test/test_helper.rb new file mode 100644 index 00000000..60fd6bfe --- /dev/null +++ b/vendor/sinatra-markaby/test/test_helper.rb @@ -0,0 +1,19 @@ +require 'rubygems' +require 'test/unit' +require 'rack/test' + +$LOAD_PATH.unshift(File.dirname(__FILE__)) +require 'sinatra/markaby' + +class Test::Unit::TestCase + include Rack::Test::Methods + + attr_reader :app + + # Sets up a Sinatra::Base subclass defined with the block + # given. Used in setup or individual spec methods to establish + # the application. + def mock_app(base=Sinatra::Base, &block) + @app = Sinatra.new(base, &block) + end +end diff --git a/vendor/sinatra-markaby/test/views/hello.mab b/vendor/sinatra-markaby/test/views/hello.mab new file mode 100644 index 00000000..afd9080a --- /dev/null +++ b/vendor/sinatra-markaby/test/views/hello.mab @@ -0,0 +1 @@ +mab.p "Hello, #{@name}!" diff --git a/vendor/sinatra-markaby/test/views/html.mab b/vendor/sinatra-markaby/test/views/html.mab new file mode 100644 index 00000000..a49025b7 --- /dev/null +++ b/vendor/sinatra-markaby/test/views/html.mab @@ -0,0 +1,4 @@ +mab.html do + head { title "Hello" } + body { yield } +end \ No newline at end of file diff --git a/vendor/sinatra-maruku/LICENSE b/vendor/sinatra-maruku/LICENSE new file mode 100644 index 00000000..222dc0bc --- /dev/null +++ b/vendor/sinatra-maruku/LICENSE @@ -0,0 +1,22 @@ +(The MIT License) + +Copyright (c) 2008 Wlodek Bzyl + +Permission is hereby granted, free of charge, to any person obtaining +a copy of this software and associated documentation files (the +'Software'), to deal in the Software without restriction, including +without limitation the rights to use, copy, modify, merge, publish, +distribute, sublicense, and/or sell copies of the Software, and to +permit persons to whom the Software is furnished to do so, subject to +the following conditions: + +The above copyright notice and this permission notice shall be +included in all copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED 'AS IS', WITHOUT WARRANTY OF ANY KIND, +EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF +MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. +IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY +CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, +TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE +SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. diff --git a/vendor/sinatra-maruku/README.markdown b/vendor/sinatra-maruku/README.markdown new file mode 100644 index 00000000..bb2bad9f --- /dev/null +++ b/vendor/sinatra-maruku/README.markdown @@ -0,0 +1,85 @@ +# Sinatra Maruku Extension + +The *sinatra-maruku* extension provides `maruku` helper method +for rendering Maruku templates. + +To install it, run: + + sudo gem install wbzyl-sinatra-maruku -s http://gems.github.com + +To test it, create a simple Sinatra application: + + # app.rb + require 'rubygems' + require 'sinatra' + + gem 'wbzyl-sinatra-maruku' + require 'sinatra/maruku' + + get "/" do + maruku "# Hello Maruku" + end + +and run it with: + + ruby app.rb + +The result could be seen at *http://localhost:4567*. + +Another example could be find in the *examples* directory. +Run it with: + + rackup -p 4567 config.ru + +and visit *http://localhost:4567* to contemplate the sheer +beauty of rendered text written in Maruku notation. + + +## Two links to Maruku related material + +* [Maruku features](http://maruku.rubyforge.org/maruku.html) +* [Literate Maruku](http://www.slideshare.net/schmidt/literate-maruku) + + +## Template Languages (*update to The Sinatra Book*) + +### Maruku Templates + +This helper method: + + get '/' do + maruku :index + end + +renders template *./views/index.maruku*. + +If a layout named *layout.maruku* exists, it will be used each time +a template is rendered. + +You can disable layouts by passing `:layout => false` +to *maruku* helper. For example + + get '/' do + maruku :index, :layout => false + end + +You can set a different layout from the default one with: + + get '/' do + maruku :index, :layout => :application + end + +This renders *./views/index.maruku* template +within *./views/application.maruku* layout. + + +## Sample layout for Maruku templates + + CSS: /stylesheets/application.css /stylesheets/print.css + Lang: pl + Title: Hello Maruku + LaTeX preamble: preamble.tex + + # Hello Maruku {.header} + + <%= yield %> diff --git a/vendor/sinatra-maruku/Rakefile b/vendor/sinatra-maruku/Rakefile new file mode 100644 index 00000000..eb96caef --- /dev/null +++ b/vendor/sinatra-maruku/Rakefile @@ -0,0 +1,34 @@ +require 'rake' +require 'rake/testtask' +require "rake/clean" + +begin + require 'jeweler' + Jeweler::Tasks.new do |gem| + gem.name = "sinatra-maruku" + gem.summary = "An extension providing Maruku templates for Sinatra applications." + gem.email = "matwb@univ.gda.pl" + gem.homepage = "http://github.com/wbzyl/sinatra-maruku" + gem.description = gem.description + gem.authors = ["Wlodek Bzyl"] + + gem.add_runtime_dependency 'sinatra', '>=0.10.1' + gem.add_runtime_dependency 'maruku', '>=0.6.0' + + gem.add_development_dependency 'rack', '>=1.0.0' + gem.add_development_dependency 'rack-test', '>=0.3.0' + + # gem is a Gem::Specification + # refer to http://www.rubygems.org/read/chapter/20 for additional settings + end +rescue LoadError + puts "Jeweler not available." + puts "Install it with:" + puts " sudo gem install technicalpickles-jeweler -s http://gems.github.com" +end + +Rake::TestTask.new(:test) do |t| + t.libs << 'lib' << 'test' + t.pattern = 'test/**/*_test.rb' + t.verbose = false +end diff --git a/vendor/sinatra-maruku/VERSION.yml b/vendor/sinatra-maruku/VERSION.yml new file mode 100644 index 00000000..eface56c --- /dev/null +++ b/vendor/sinatra-maruku/VERSION.yml @@ -0,0 +1,4 @@ +--- +:major: 0 +:minor: 10 +:patch: 1 diff --git a/vendor/sinatra-maruku/examples/app.rb b/vendor/sinatra-maruku/examples/app.rb new file mode 100644 index 00000000..f760b06f --- /dev/null +++ b/vendor/sinatra-maruku/examples/app.rb @@ -0,0 +1,8 @@ +require 'rubygems' +require 'sinatra' +require 'sinatra/maruku' + +get "/" do + #maruku :hello, :layout => false + maruku :index +end diff --git a/vendor/sinatra-maruku/examples/config.ru b/vendor/sinatra-maruku/examples/config.ru new file mode 100644 index 00000000..75999267 --- /dev/null +++ b/vendor/sinatra-maruku/examples/config.ru @@ -0,0 +1,4 @@ +# run it: rackup config.ru -p 4567 + +require 'app' +run Sinatra::Application diff --git a/vendor/sinatra-maruku/examples/mapp.rb b/vendor/sinatra-maruku/examples/mapp.rb new file mode 100644 index 00000000..76b9ccaa --- /dev/null +++ b/vendor/sinatra-maruku/examples/mapp.rb @@ -0,0 +1,15 @@ +require 'rubygems' +require 'sinatra/base' +require 'sinatra/maruku' + +require 'rack' + +class MApp < Sinatra::Base + helpers Sinatra::Maruku + + get '/' do + maruku "## hello form modular app" + end +end + +Rack::Handler::Thin.run MApp.new, :Port => 4567 diff --git a/.gitmodules b/vendor/sinatra-maruku/examples/public/javascripts/application.js similarity index 100% rename from .gitmodules rename to vendor/sinatra-maruku/examples/public/javascripts/application.js diff --git a/vendor/sinatra-maruku/examples/public/stylesheets/application.css b/vendor/sinatra-maruku/examples/public/stylesheets/application.css new file mode 100644 index 00000000..702b3926 --- /dev/null +++ b/vendor/sinatra-maruku/examples/public/stylesheets/application.css @@ -0,0 +1,23 @@ +html { + margin: 0; + padding: 0; + background-color: #B5052E; + line-height: 1.6; +} + +body { + margin: 1em auto 1em auto; + padding: 1em 2em 2em 1em; + width: 760px; + border: 1px solid black; + background-color: #E8DDCB; +} + +pre { + padding: 0.5em 0 0.5em 2em; + background-color: #D7D3C1; +} + +h1, h2, h3 { + color: #B5052E; +} diff --git a/vendor/sinatra-maruku/examples/public/stylesheets/print.css b/vendor/sinatra-maruku/examples/public/stylesheets/print.css new file mode 100644 index 00000000..e69de29b diff --git a/vendor/sinatra-maruku/examples/views/index.maruku b/vendor/sinatra-maruku/examples/views/index.maruku new file mode 100644 index 00000000..788a1119 --- /dev/null +++ b/vendor/sinatra-maruku/examples/views/index.maruku @@ -0,0 +1,32 @@ +Maruku features +=============== + +Maruku allows you to write in an easy-to-read-and-write syntax, like this: + +> [This document in Markdown][this_md] + +Then it can be translated to HTML: + +> [This document in HTML][this_html] + +or LaTeX, which is then converted to PDF: + +> [This document in PDF][this_pdf] + +Maruku implements: + +* the original [Markdown syntax][markdown_html] + ([HTML][markdown_html] or [PDF][markdown_pdf]), translated by Maruku). + +* all the improvements in PHP Markdown Extra. + +* a new [meta-data syntax][meta_data_proposal] + +[markdown_html]: http://maruku.rubyforge.org/markdown_syntax.html +[markdown_pdf]: http://maruku.rubyforge.org/markdown_syntax.pdf +[this_md]: http://maruku.rubyforge.org/maruku.md +[this_html]: http://maruku.rubyforge.org/maruku.html +[this_pdf]: http://maruku.rubyforge.org/maruku.pdf +[Andrea Censi]: http://www.dis.uniroma1.it/~acensi/ + +[meta_data_proposal]: http://maruku.rubyforge.org/proposal.html diff --git a/vendor/sinatra-maruku/examples/views/layout.maruku b/vendor/sinatra-maruku/examples/views/layout.maruku new file mode 100644 index 00000000..3207ebfd --- /dev/null +++ b/vendor/sinatra-maruku/examples/views/layout.maruku @@ -0,0 +1,9 @@ +CSS: /stylesheets/application.css /stylesheets/print.css +Javascript: /javascriprs/application.js +Lang: pl +Title: Hello Maruku +LaTeX preamble: preamble.tex + +# Hello Maruku {.header} + +<%= yield %> diff --git a/vendor/sinatra-maruku/lib/sinatra/maruku.rb b/vendor/sinatra-maruku/lib/sinatra/maruku.rb new file mode 100644 index 00000000..c798b2f4 --- /dev/null +++ b/vendor/sinatra-maruku/lib/sinatra/maruku.rb @@ -0,0 +1,25 @@ +require 'maruku' +require 'sinatra/base' + +module Sinatra + module Maruku + def maruku(template, options={}, locals={}) + render :maruku, template, options, locals + end + + private + def render_maruku(template, data, options, locals, &block) + maruku_src = render_erb(template, data, options, locals, &block) + instance = ::Maruku.new(maruku_src, options) + if block_given? + # render layout + instance.to_html_document + else + # render template + instance.to_html + end + end + end + + helpers Maruku +end diff --git a/vendor/sinatra-maruku/sinatra-maruku.gemspec b/vendor/sinatra-maruku/sinatra-maruku.gemspec new file mode 100644 index 00000000..b8bd41e7 --- /dev/null +++ b/vendor/sinatra-maruku/sinatra-maruku.gemspec @@ -0,0 +1,70 @@ +# -*- encoding: utf-8 -*- + +Gem::Specification.new do |s| + s.name = %q{sinatra-maruku} + s.version = "0.10.1" + + s.required_rubygems_version = Gem::Requirement.new(">= 0") if s.respond_to? :required_rubygems_version= + s.authors = ["Wlodek Bzyl"] + s.date = %q{2009-07-26} + s.description = %q{} + s.email = %q{matwb@univ.gda.pl} + s.extra_rdoc_files = [ + "LICENSE", + "README.markdown" + ] + s.files = [ + ".gitignore", + "LICENSE", + "README.markdown", + "Rakefile", + "VERSION.yml", + "examples/app.rb", + "examples/config.ru", + "examples/mapp.rb", + "examples/public/javascripts/application.js", + "examples/public/stylesheets/application.css", + "examples/public/stylesheets/print.css", + "examples/views/index.maruku", + "examples/views/layout.maruku", + "lib/sinatra/maruku.rb", + "sinatra-maruku.gemspec", + "test/sinatra_maruku_test.rb", + "test/test_helper.rb", + "test/views/hello.maruku", + "test/views/layout2.maruku" + ] + s.homepage = %q{http://github.com/wbzyl/sinatra-maruku} + s.rdoc_options = ["--charset=UTF-8"] + s.require_paths = ["lib"] + s.rubygems_version = %q{1.3.5} + s.summary = %q{An extension providing Maruku templates for Sinatra applications.} + s.test_files = [ + "test/test_helper.rb", + "test/sinatra_maruku_test.rb", + "examples/mapp.rb", + "examples/app.rb" + ] + + if s.respond_to? :specification_version then + current_version = Gem::Specification::CURRENT_SPECIFICATION_VERSION + s.specification_version = 3 + + if Gem::Version.new(Gem::RubyGemsVersion) >= Gem::Version.new('1.2.0') then + s.add_runtime_dependency(%q, [">= 0.10.1"]) + s.add_runtime_dependency(%q, [">= 0.6.0"]) + s.add_development_dependency(%q, [">= 1.0.0"]) + s.add_development_dependency(%q, [">= 0.3.0"]) + else + s.add_dependency(%q, [">= 0.10.1"]) + s.add_dependency(%q, [">= 0.6.0"]) + s.add_dependency(%q, [">= 1.0.0"]) + s.add_dependency(%q, [">= 0.3.0"]) + end + else + s.add_dependency(%q, [">= 0.10.1"]) + s.add_dependency(%q, [">= 0.6.0"]) + s.add_dependency(%q, [">= 1.0.0"]) + s.add_dependency(%q, [">= 0.3.0"]) + end +end diff --git a/vendor/sinatra-maruku/test/sinatra_maruku_test.rb b/vendor/sinatra-maruku/test/sinatra_maruku_test.rb new file mode 100644 index 00000000..8d99824e --- /dev/null +++ b/vendor/sinatra-maruku/test/sinatra_maruku_test.rb @@ -0,0 +1,91 @@ +require File.dirname(__FILE__) + '/test_helper' + +class SinatraMarukuTest < Test::Unit::TestCase + include Rack::Test::Methods + + def maruku_app(&block) + mock_app { + set :views, File.dirname(__FILE__) + '/views' + helpers Sinatra::Maruku + set :show_exceptions, false + get '/', &block + } + get '/' + end + + def test_renders_inline_strings + maruku_app { maruku 'hello world' } + assert last_response.ok? + assert_equal "

hello world

", last_response.body + end + + def test_renders_inline_erb_string + maruku_app { maruku '<%= 1 + 1 %>' } + assert last_response.ok? + assert_equal "

2

", last_response.body + end + + def test_renders_files_in_views_path + maruku_app { maruku :hello } + assert last_response.ok? + assert_equal "

hello world

", last_response.body + end + + def test_takes_locals_option + maruku_app { + locals = {:foo => 'Bar'} + maruku "<%= foo %>", :locals => locals + } + assert last_response.ok? + assert_equal "

Bar

", last_response.body + end + + def test_renders_with_inline_layouts + maruku_app { + maruku 'Sparta', :layout => 'THIS. IS. <%= yield.upcase %>' + } + assert last_response.ok? + assert_equal "\n\n\n\n\n

THIS. IS.

SPARTA

\n", last_response.body + end + + def test_renders_with_file_layouts + maruku_app { + maruku 'hello world', :layout => :layout2 + } + assert last_response.ok? + assert_equal "\n\n\n\n\n

erb layout

hello world

\n", last_response.body + end + + def test_renders_erb_with_blocks + mock_app { + set :views, File.dirname(__FILE__) + '/views' + helpers Sinatra::Maruku + + def container + yield + end + def is + "THIS. IS. SPARTA!" + end + + get '/' do + maruku '<% container do %> <%= is %> <% end %>' + end + } + + get '/' + assert last_response.ok? + assert_equal "

THIS. IS. SPARTA!

", last_response.body + end + + def test_raises_error_if_template_not_found + mock_app { + set :views, File.dirname(__FILE__) + '/views' + helpers Sinatra::Maruku + set :show_exceptions, false + + get('/') { maruku :no_such_template } + } + assert_raise(Errno::ENOENT) { get('/') } + end +end diff --git a/vendor/sinatra-maruku/test/test_helper.rb b/vendor/sinatra-maruku/test/test_helper.rb new file mode 100644 index 00000000..99dd126f --- /dev/null +++ b/vendor/sinatra-maruku/test/test_helper.rb @@ -0,0 +1,21 @@ +require 'rubygems' +require 'test/unit' +require 'rack/test' + +path = File.expand_path("../lib" + File.dirname(__FILE__)) +$:.unshift(path) unless $:.include?(path) + +require 'sinatra/maruku' + +class Test::Unit::TestCase + include Rack::Test::Methods + + attr_reader :app + + # Sets up a Sinatra::Base subclass defined with the block + # given. Used in setup or individual spec methods to establish + # the application. + def mock_app(base=Sinatra::Base, &block) + @app = Sinatra.new(base, &block) + end +end diff --git a/vendor/sinatra-maruku/test/views/hello.maruku b/vendor/sinatra-maruku/test/views/hello.maruku new file mode 100644 index 00000000..2be7c65a --- /dev/null +++ b/vendor/sinatra-maruku/test/views/hello.maruku @@ -0,0 +1 @@ +# hello world diff --git a/vendor/sinatra-maruku/test/views/layout2.maruku b/vendor/sinatra-maruku/test/views/layout2.maruku new file mode 100644 index 00000000..8f33055d --- /dev/null +++ b/vendor/sinatra-maruku/test/views/layout2.maruku @@ -0,0 +1,2 @@ +erb layout +<%= yield %>