sinatra-contrib-1.4.1/ 0000755 0000041 0000041 00000000000 12207620341 014641 5 ustar www-data www-data sinatra-contrib-1.4.1/LICENSE 0000644 0000041 0000041 00000002110 12207620341 015640 0 ustar www-data www-data Copyright (c) 2008-2011 Nicolas Sanguinetti, entp.com, Konstantin Haase
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.
sinatra-contrib-1.4.1/README.md 0000644 0000041 0000041 00000006726 12207620341 016133 0 ustar www-data www-data [](http://travis-ci.org/sinatra/sinatra-contrib)
Collection of common Sinatra extensions, semi-officially supported.
# Goals
* For every future Sinatra release, have at least one fully compatible release
* High code quality, high test coverage
* Include plugins people usually ask for a lot
# Included extensions
## Common Extensions
These are common extension which will not add significant overhead or change any
behavior of already existing APIs. They do not add any dependencies not already
installed with this gem.
Currently included:
* `sinatra/capture`: Let's you capture the content of blocks in templates.
* `sinatra/config_file`: Allows loading configuration from yaml files.
* `sinatra/content_for`: Adds Rails-style `content_for` helpers to Haml, Erb,
Erubis and Slim.
* `sinatra/cookies`: A `cookies` helper for reading and writing cookies.
* `sinatra/engine_tracking`: Adds methods like `haml?` that allow helper
methods to check whether they are called from within a template.
* `sinatra/json`: Adds a `#json` helper method to return JSON documents.
* `sinatra/link_header`: Helpers for generating `link` HTML tags and
corresponding `Link` HTTP headers. Adds `link`, `stylesheet` and `prefetch`
helper methods.
* `sinatra/multi_route`: Adds ability to define one route block for multiple
routes and multiple or custom HTTP verbs.
* `sinatra/namespace`: Adds namespace support to Sinatra.
* `sinatra/respond_with`: Choose action and/or template automatically
depending on the incoming request. Adds helpers `respond_to` and
`respond_with`.
## Custom Extensions
These extensions may add additional dependencies and enhance the behavior of the
existing APIs.
Currently included:
* `sinatra/decompile`: Recreates path patterns from Sinatra's internal data
structures (used by other extensions).
* `sinatra/reloader`: Automatically reloads Ruby files on code changes.
## Other Tools
* `sinatra/extension`: Mixin for writing your own Sinatra extensions.
* `sinatra/test_helpers`: Helper methods to ease testing your Sinatra
application. Partly extracted from Sinatra. Testing framework agnostic
# Installation
Add `gem 'sinatra-contrib'` to *Gemfile*, then execute `bundle install`.
If you don't use Bundler, install the gem manually by executing `gem install sinatra-contrib` in your command line.
# Usage
## Classic Style
A single extension (example: sinatra-content-for):
``` ruby
require 'sinatra'
require 'sinatra/content_for'
```
Common extensions:
``` ruby
require 'sinatra'
require 'sinatra/contrib'
```
All extensions:
``` ruby
require 'sinatra'
require 'sinatra/contrib/all'
```
## Modular Style
A single extension (example: sinatra-content-for):
``` ruby
require 'sinatra/base'
require 'sinatra/content_for'
require 'sinatra/namespace'
class MyApp < Sinatra::Base
# Note: Some modules are extensions, some helpers, see the specific
# documentation or the source
helpers Sinatra::ContentFor
register Sinatra::Namespace
end
```
Common extensions:
``` ruby
require 'sinatra/base'
require 'sinatra/contrib'
class MyApp < Sinatra::Base
register Sinatra::Contrib
end
```
All extensions:
``` ruby
require 'sinatra/base'
require 'sinatra/contrib/all'
class MyApp < Sinatra::Base
register Sinatra::Contrib
end
```
## Documentation
For more info check the [official docs](http://www.sinatrarb.com/contrib/) and
[api docs](http://rubydoc.info/gems/sinatra-contrib/1.4.0/frames).
sinatra-contrib-1.4.1/Rakefile 0000644 0000041 0000041 00000004641 12207620341 016313 0 ustar www-data www-data $LOAD_PATH.unshift File.expand_path('../lib', __FILE__)
require 'open-uri'
require 'yaml'
require 'sinatra/contrib/version'
desc "run specs"
task(:spec) { ruby '-S rspec spec -c' }
task(:test => :spec)
task(:default => :spec)
namespace :doc do
task :readmes do
Dir.glob 'lib/sinatra/*.rb' do |file|
excluded_files = %w[lib/sinatra/contrib.rb lib/sinatra/capture.rb lib/sinatra/engine_tracking.rb]
next if excluded_files.include?(file)
doc = File.read(file)[/^module Sinatra(\n)+( #[^\n]*\n)*/m].scan(/^ *#(?!#) ?(.*)\n/).join("\n")
file = "doc/#{file[4..-4].tr("/_", "-")}.rdoc"
Dir.mkdir "doc" unless File.directory? "doc"
puts "writing #{file}"
File.open(file, "w") { |f| f << doc }
end
end
task :all => [:readmes]
end
desc "generate documentation"
task :doc => 'doc:all'
desc "generate gemspec"
task 'sinatra-contrib.gemspec' do
content = File.read 'sinatra-contrib.gemspec'
fields = {
:authors => `git shortlog -sn`.scan(/[^\d\s].*/),
:email => `git shortlog -sne`.scan(/[^<]+@[^>]+/),
:files => `git ls-files`.split("\n").reject { |f| f =~ /^(\.|Gemfile)/ }
}
fields.each do |field, values|
updated = " s.#{field} = ["
updated << values.map { |v| "\n %p" % v }.join(',')
updated << "\n ]"
content.sub!(/ s\.#{field} = \[\n( .*\n)* \]/, updated)
end
File.open('sinatra-contrib.gemspec', 'w') { |f| f << content }
end
task :gemspec => 'sinatra-contrib.gemspec'
desc 'update travis config to correspond to sinatra'
task :travis, [:branch] do |t, a|
a.with_defaults :branch => :master
data = YAML.load open("https://raw.github.com/sinatra/sinatra/#{a.branch}/.travis.yml")
data["notifications"]["recipients"] << "ohhgabriel@gmail.com"
File.open('.travis.yml', 'w') { |f| f << data.to_yaml }
system 'git add .travis.yml && git diff --cached .travis.yml'
end
task :release => :gemspec do
sh <<-SH
rm -Rf sinatra-contrib*.gem &&
gem build sinatra-contrib.gemspec &&
gem install sinatra-contrib*.gem --local &&
gem push sinatra-contrib*.gem &&
git commit --allow-empty -a -m '#{Sinatra::Contrib::VERSION} release' &&
git tag -s v#{Sinatra::Contrib::VERSION} -m '#{Sinatra::Contrib::VERSION} release' &&
git tag -s #{Sinatra::Contrib::VERSION} -m '#{Sinatra::Contrib::VERSION} release' &&
git push && (git push sinatra || true) &&
git push --tags && (git push sinatra --tags || true)
SH
end
sinatra-contrib-1.4.1/spec/ 0000755 0000041 0000041 00000000000 12207620341 015573 5 ustar www-data www-data sinatra-contrib-1.4.1/spec/okjson.rb 0000644 0000041 0000041 00000032634 12207620341 017433 0 ustar www-data www-data # Copyright 2011 Keith Rarick
#
# 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.
# See https://github.com/kr/okjson for updates.
require 'stringio'
# Some parts adapted from
# http://golang.org/src/pkg/json/decode.go and
# http://golang.org/src/pkg/utf8/utf8.go
module OkJson
extend self
# Decodes a json document in string s and
# returns the corresponding ruby value.
# String s must be valid UTF-8. If you have
# a string in some other encoding, convert
# it first.
#
# String values in the resulting structure
# will be UTF-8.
def decode(s)
ts = lex(s)
v, ts = textparse(ts)
if ts.length > 0
raise Error, 'trailing garbage'
end
v
end
# Parses a "json text" in the sense of RFC 4627.
# Returns the parsed value and any trailing tokens.
# Note: this is almost the same as valparse,
# except that it does not accept atomic values.
def textparse(ts)
if ts.length < 0
raise Error, 'empty'
end
typ, _, val = ts[0]
case typ
when '{' then objparse(ts)
when '[' then arrparse(ts)
else
raise Error, "unexpected #{val.inspect}"
end
end
# Parses a "value" in the sense of RFC 4627.
# Returns the parsed value and any trailing tokens.
def valparse(ts)
if ts.length < 0
raise Error, 'empty'
end
typ, _, val = ts[0]
case typ
when '{' then objparse(ts)
when '[' then arrparse(ts)
when :val,:str then [val, ts[1..-1]]
else
raise Error, "unexpected #{val.inspect}"
end
end
# Parses an "object" in the sense of RFC 4627.
# Returns the parsed value and any trailing tokens.
def objparse(ts)
ts = eat('{', ts)
obj = {}
if ts[0][0] == '}'
return obj, ts[1..-1]
end
k, v, ts = pairparse(ts)
obj[k] = v
if ts[0][0] == '}'
return obj, ts[1..-1]
end
loop do
ts = eat(',', ts)
k, v, ts = pairparse(ts)
obj[k] = v
if ts[0][0] == '}'
return obj, ts[1..-1]
end
end
end
# Parses a "member" in the sense of RFC 4627.
# Returns the parsed values and any trailing tokens.
def pairparse(ts)
(typ, _, k), ts = ts[0], ts[1..-1]
if typ != :str
raise Error, "unexpected #{k.inspect}"
end
ts = eat(':', ts)
v, ts = valparse(ts)
[k, v, ts]
end
# Parses an "array" in the sense of RFC 4627.
# Returns the parsed value and any trailing tokens.
def arrparse(ts)
ts = eat('[', ts)
arr = []
if ts[0][0] == ']'
return arr, ts[1..-1]
end
v, ts = valparse(ts)
arr << v
if ts[0][0] == ']'
return arr, ts[1..-1]
end
loop do
ts = eat(',', ts)
v, ts = valparse(ts)
arr << v
if ts[0][0] == ']'
return arr, ts[1..-1]
end
end
end
def eat(typ, ts)
if ts[0][0] != typ
raise Error, "expected #{typ} (got #{ts[0].inspect})"
end
ts[1..-1]
end
# Sans s and returns a list of json tokens,
# excluding white space (as defined in RFC 4627).
def lex(s)
ts = []
while s.length > 0
typ, lexeme, val = tok(s)
if typ == nil
raise Error, "invalid character at #{s[0,10].inspect}"
end
if typ != :space
ts << [typ, lexeme, val]
end
s = s[lexeme.length..-1]
end
ts
end
# Scans the first token in s and
# returns a 3-element list, or nil
# if no such token exists.
#
# The first list element is one of
# '{', '}', ':', ',', '[', ']',
# :val, :str, and :space.
#
# The second element is the lexeme.
#
# The third element is the value of the
# token for :val and :str, otherwise
# it is the lexeme.
def tok(s)
case s[0]
when ?{ then ['{', s[0,1], s[0,1]]
when ?} then ['}', s[0,1], s[0,1]]
when ?: then [':', s[0,1], s[0,1]]
when ?, then [',', s[0,1], s[0,1]]
when ?[ then ['[', s[0,1], s[0,1]]
when ?] then [']', s[0,1], s[0,1]]
when ?n then nulltok(s)
when ?t then truetok(s)
when ?f then falsetok(s)
when ?" then strtok(s)
when Spc then [:space, s[0,1], s[0,1]]
when ?\t then [:space, s[0,1], s[0,1]]
when ?\n then [:space, s[0,1], s[0,1]]
when ?\r then [:space, s[0,1], s[0,1]]
else numtok(s)
end
end
def nulltok(s); s[0,4] == 'null' && [:val, 'null', nil] end
def truetok(s); s[0,4] == 'true' && [:val, 'true', true] end
def falsetok(s); s[0,5] == 'false' && [:val, 'false', false] end
def numtok(s)
m = /-?([1-9][0-9]+|[0-9])([.][0-9]+)?([eE][+-]?[0-9]+)?/.match(s)
if m && m.begin(0) == 0
if m[3] && !m[2]
[:val, m[0], Integer(m[1])*(10**Integer(m[3][1..-1]))]
elsif m[2]
[:val, m[0], Float(m[0])]
else
[:val, m[0], Integer(m[0])]
end
end
end
def strtok(s)
m = /"([^"\\]|\\["\/\\bfnrt]|\\u[0-9a-fA-F]{4})*"/.match(s)
if ! m
raise Error, "invalid string literal at #{abbrev(s)}"
end
[:str, m[0], unquote(m[0])]
end
def abbrev(s)
t = s[0,10]
p = t['`']
t = t[0,p] if p
t = t + '...' if t.length < s.length
'`' + t + '`'
end
# Converts a quoted json string literal q into a UTF-8-encoded string.
# The rules are different than for Ruby, so we cannot use eval.
# Unquote will raise an error if q contains control characters.
def unquote(q)
q = q[1...-1]
a = q.dup # allocate a big enough string
r, w = 0, 0
while r < q.length
c = q[r]
case true
when c == ?\\
r += 1
if r >= q.length
raise Error, "string literal ends with a \"\\\": \"#{q}\""
end
case q[r]
when ?",?\\,?/,?'
a[w] = q[r]
r += 1
w += 1
when ?b,?f,?n,?r,?t
a[w] = Unesc[q[r]]
r += 1
w += 1
when ?u
r += 1
uchar = begin
hexdec4(q[r,4])
rescue RuntimeError => e
raise Error, "invalid escape sequence \\u#{q[r,4]}: #{e}"
end
r += 4
if surrogate? uchar
if q.length >= r+6
uchar1 = hexdec4(q[r+2,4])
uchar = subst(uchar, uchar1)
if uchar != Ucharerr
# A valid pair; consume.
r += 6
end
end
end
w += ucharenc(a, w, uchar)
else
raise Error, "invalid escape char #{q[r]} in \"#{q}\""
end
when c == ?", c < Spc
raise Error, "invalid character in string literal \"#{q}\""
else
# Copy anything else byte-for-byte.
# Valid UTF-8 will remain valid UTF-8.
# Invalid UTF-8 will remain invalid UTF-8.
a[w] = c
r += 1
w += 1
end
end
a[0,w]
end
# Encodes unicode character u as UTF-8
# bytes in string a at position i.
# Returns the number of bytes written.
def ucharenc(a, i, u)
case true
when u <= Uchar1max
a[i] = (u & 0xff).chr
1
when u <= Uchar2max
a[i+0] = (Utag2 | ((u>>6)&0xff)).chr
a[i+1] = (Utagx | (u&Umaskx)).chr
2
when u <= Uchar3max
a[i+0] = (Utag3 | ((u>>12)&0xff)).chr
a[i+1] = (Utagx | ((u>>6)&Umaskx)).chr
a[i+2] = (Utagx | (u&Umaskx)).chr
3
else
a[i+0] = (Utag4 | ((u>>18)&0xff)).chr
a[i+1] = (Utagx | ((u>>12)&Umaskx)).chr
a[i+2] = (Utagx | ((u>>6)&Umaskx)).chr
a[i+3] = (Utagx | (u&Umaskx)).chr
4
end
end
def hexdec4(s)
if s.length != 4
raise Error, 'short'
end
(nibble(s[0])<<12) | (nibble(s[1])<<8) | (nibble(s[2])<<4) | nibble(s[3])
end
def subst(u1, u2)
if Usurr1 <= u1 && u1 < Usurr2 && Usurr2 <= u2 && u2 < Usurr3
return ((u1-Usurr1)<<10) | (u2-Usurr2) + Usurrself
end
return Ucharerr
end
def unsubst(u)
if u < Usurrself || u > Umax || surrogate?(u)
return Ucharerr, Ucharerr
end
u -= Usurrself
[Usurr1 + ((u>>10)&0x3ff), Usurr2 + (u&0x3ff)]
end
def surrogate?(u)
Usurr1 <= u && u < Usurr3
end
def nibble(c)
case true
when ?0 <= c && c <= ?9 then c.ord - ?0.ord
when ?a <= c && c <= ?z then c.ord - ?a.ord + 10
when ?A <= c && c <= ?Z then c.ord - ?A.ord + 10
else
raise Error, "invalid hex code #{c}"
end
end
# Encodes x into a json text. It may contain only
# Array, Hash, String, Numeric, true, false, nil.
# (Note, this list excludes Symbol.)
# X itself must be an Array or a Hash.
# No other value can be encoded, and an error will
# be raised if x contains any other value, such as
# Nan, Infinity, Symbol, and Proc, or if a Hash key
# is not a String.
# Strings contained in x must be valid UTF-8.
def encode(x)
case x
when Hash then objenc(x)
when Array then arrenc(x)
else
raise Error, 'root value must be an Array or a Hash'
end
end
def valenc(x)
case x
when Hash then objenc(x)
when Array then arrenc(x)
when String then strenc(x)
when Numeric then numenc(x)
when true then "true"
when false then "false"
when nil then "null"
else
raise Error, "cannot encode #{x.class}: #{x.inspect}"
end
end
def objenc(x)
'{' + x.map{|k,v| keyenc(k) + ':' + valenc(v)}.join(',') + '}'
end
def arrenc(a)
'[' + a.map{|x| valenc(x)}.join(',') + ']'
end
def keyenc(k)
case k
when String then strenc(k)
else
raise Error, "Hash key is not a string: #{k.inspect}"
end
end
def strenc(s)
t = StringIO.new
t.putc(?")
r = 0
while r < s.length
case s[r]
when ?" then t.print('\\"')
when ?\\ then t.print('\\\\')
when ?\b then t.print('\\b')
when ?\f then t.print('\\f')
when ?\n then t.print('\\n')
when ?\r then t.print('\\r')
when ?\t then t.print('\\t')
else
c = s[r]
case true
when Spc <= c && c <= ?~
t.putc(c)
when true
u, size = uchardec(s, r)
r += size - 1 # we add one more at the bottom of the loop
if u < 0x10000
t.print('\\u')
hexenc4(t, u)
else
u1, u2 = unsubst(u)
t.print('\\u')
hexenc4(t, u1)
t.print('\\u')
hexenc4(t, u2)
end
else
# invalid byte; skip it
end
end
r += 1
end
t.putc(?")
t.string
end
def hexenc4(t, u)
t.putc(Hex[(u>>12)&0xf])
t.putc(Hex[(u>>8)&0xf])
t.putc(Hex[(u>>4)&0xf])
t.putc(Hex[u&0xf])
end
def numenc(x)
if x.nan? || x.infinite?
return 'null'
end rescue nil
"#{x}"
end
# Decodes unicode character u from UTF-8
# bytes in string s at position i.
# Returns u and the number of bytes read.
def uchardec(s, i)
n = s.length - i
return [Ucharerr, 1] if n < 1
c0 = s[i].ord
# 1-byte, 7-bit sequence?
if c0 < Utagx
return [c0, 1]
end
# unexpected continuation byte?
return [Ucharerr, 1] if c0 < Utag2
# need continuation byte
return [Ucharerr, 1] if n < 2
c1 = s[i+1].ord
return [Ucharerr, 1] if c1 < Utagx || Utag2 <= c1
# 2-byte, 11-bit sequence?
if c0 < Utag3
u = (c0&Umask2)<<6 | (c1&Umaskx)
return [Ucharerr, 1] if u <= Uchar1max
return [u, 2]
end
# need second continuation byte
return [Ucharerr, 1] if n < 3
c2 = s[i+2].ord
return [Ucharerr, 1] if c2 < Utagx || Utag2 <= c2
# 3-byte, 16-bit sequence?
if c0 < Utag4
u = (c0&Umask3)<<12 | (c1&Umaskx)<<6 | (c2&Umaskx)
return [Ucharerr, 1] if u <= Uchar2max
return [u, 3]
end
# need third continuation byte
return [Ucharerr, 1] if n < 4
c3 = s[i+3].ord
return [Ucharerr, 1] if c3 < Utagx || Utag2 <= c3
# 4-byte, 21-bit sequence?
if c0 < Utag5
u = (c0&Umask4)<<18 | (c1&Umaskx)<<12 | (c2&Umaskx)<<6 | (c3&Umaskx)
return [Ucharerr, 1] if u <= Uchar3max
return [u, 4]
end
return [Ucharerr, 1]
end
class Error < ::StandardError
end
Utagx = 0x80 # 1000 0000
Utag2 = 0xc0 # 1100 0000
Utag3 = 0xe0 # 1110 0000
Utag4 = 0xf0 # 1111 0000
Utag5 = 0xF8 # 1111 1000
Umaskx = 0x3f # 0011 1111
Umask2 = 0x1f # 0001 1111
Umask3 = 0x0f # 0000 1111
Umask4 = 0x07 # 0000 0111
Uchar1max = (1<<7) - 1
Uchar2max = (1<<11) - 1
Uchar3max = (1<<16) - 1
Ucharerr = 0xFFFD # unicode "replacement char"
Usurrself = 0x10000
Usurr1 = 0xd800
Usurr2 = 0xdc00
Usurr3 = 0xe000
Umax = 0x10ffff
Spc = ' '[0]
Unesc = {?b=>?\b, ?f=>?\f, ?n=>?\n, ?r=>?\r, ?t=>?\t}
Hex = '0123456789abcdef'
end
sinatra-contrib-1.4.1/spec/reloader_spec.rb 0000644 0000041 0000041 00000032236 12207620341 020735 0 ustar www-data www-data require 'backports'
require_relative 'spec_helper'
require 'fileutils'
describe Sinatra::Reloader do
# Returns the temporary directory.
def tmp_dir
File.expand_path('../../tmp', __FILE__)
end
# Returns the path of the Sinatra application file created by
# +setup_example_app+.
def app_file_path
File.join(tmp_dir, "example_app_#{$example_app_counter}.rb")
end
# Returns the name of the Sinatra application created by
# +setup_example_app+: 'ExampleApp1' for the first application,
# 'ExampleApp2' fo the second one, and so on...
def app_name
"ExampleApp#{$example_app_counter}"
end
# Returns the (constant of the) Sinatra application created by
# +setup_example_app+.
def app_const
Module.const_get(app_name)
end
# Writes a file with a Sinatra application using the template
# located at specs/reloader/app.rb.erb. It expects an
# +options+ hash, with an array of strings containing the
# application's routes (+:routes+ key), a hash with the inline
# template's names as keys and the bodys as values
# (+:inline_templates+ key) and an optional application name
# (+:name+) otherwise +app_name+ is used.
#
# It ensures to change the written file's mtime when it already
# exists.
def write_app_file(options={})
options[:routes] ||= ['get("/foo") { erb :foo }']
options[:inline_templates] ||= nil
options[:extensions] ||= []
options[:middlewares] ||= []
options[:filters] ||= []
options[:errors] ||= {}
options[:name] ||= app_name
options[:enable_reloader] = true unless options[:enable_reloader] === false
options[:parent] ||= 'Sinatra::Base'
update_file(app_file_path) do |f|
template_path = File.expand_path('../reloader/app.rb.erb', __FILE__)
template = Tilt.new(template_path, nil, :trim => '<>')
f.write template.render(Object.new, options)
end
end
alias update_app_file write_app_file
# It calls File.open(path, 'w', &block) all the times
# needed to change the file's mtime.
def update_file(path, &block)
original_mtime = File.exist?(path) ? File.mtime(path) : Time.at(0)
new_time = original_mtime + 1
File.open(path, 'w', &block)
File.utime(new_time, new_time, path)
end
# Writes a Sinatra application to a file, requires the file, sets
# the new application as the one being tested and enables the
# reloader.
def setup_example_app(options={})
$example_app_counter ||= 0
$example_app_counter += 1
FileUtils.mkdir_p(tmp_dir)
write_app_file(options)
$LOADED_FEATURES.delete app_file_path
require app_file_path
self.app = app_const
app_const.enable :reloader
end
after(:all) { FileUtils.rm_rf(tmp_dir) }
describe "default route reloading mechanism" do
before(:each) do
setup_example_app(:routes => ['get("/foo") { "foo" }'])
end
it "doesn't mess up the application" do
get('/foo').body.should == 'foo'
end
it "knows when a route has been modified" do
update_app_file(:routes => ['get("/foo") { "bar" }'])
get('/foo').body.should == 'bar'
end
it "knows when a route has been added" do
update_app_file(
:routes => ['get("/foo") { "foo" }', 'get("/bar") { "bar" }']
)
get('/foo').body.should == 'foo'
get('/bar').body.should == 'bar'
end
it "knows when a route has been removed" do
update_app_file(:routes => ['get("/bar") { "bar" }'])
get('/foo').status.should == 404
end
it "doesn't try to reload a removed file" do
update_app_file(:routes => ['get("/foo") { "i shall not be reloaded" }'])
FileUtils.rm app_file_path
get('/foo').body.strip.should == 'foo'
end
end
describe "default inline templates reloading mechanism" do
before(:each) do
setup_example_app(
:routes => ['get("/foo") { erb :foo }'],
:inline_templates => { :foo => 'foo' }
)
end
it "doesn't mess up the application" do
get('/foo').body.strip.should == 'foo'
end
it "reloads inline templates in the app file" do
update_app_file(
:routes => ['get("/foo") { erb :foo }'],
:inline_templates => { :foo => 'bar' }
)
get('/foo').body.strip.should == 'bar'
end
it "reloads inline templates in other file" do
setup_example_app(:routes => ['get("/foo") { erb :foo }'])
template_file_path = File.join(tmp_dir, 'templates.rb')
File.open(template_file_path, 'w') do |f|
f.write "__END__\n\n@@foo\nfoo"
end
require template_file_path
app_const.inline_templates= template_file_path
get('/foo').body.strip.should == 'foo'
update_file(template_file_path) do |f|
f.write "__END__\n\n@@foo\nbar"
end
get('/foo').body.strip.should == 'bar'
end
end
describe "default middleware reloading mechanism" do
it "knows when a middleware has been added" do
setup_example_app(:routes => ['get("/foo") { "foo" }'])
update_app_file(
:routes => ['get("/foo") { "foo" }'],
:middlewares => [Rack::Head]
)
get('/foo') # ...to perform the reload
app_const.middleware.should_not be_empty
end
it "knows when a middleware has been removed" do
setup_example_app(
:routes => ['get("/foo") { "foo" }'],
:middlewares => [Rack::Head]
)
update_app_file(:routes => ['get("/foo") { "foo" }'])
get('/foo') # ...to perform the reload
app_const.middleware.should be_empty
end
end
describe "default filter reloading mechanism" do
it "knows when a before filter has been added" do
setup_example_app(:routes => ['get("/foo") { "foo" }'])
expect {
update_app_file(
:routes => ['get("/foo") { "foo" }'],
:filters => ['before { @hi = "hi" }']
)
get('/foo') # ...to perform the reload
}.to change { app_const.filters[:before].size }.by(1)
end
it "knows when an after filter has been added" do
setup_example_app(:routes => ['get("/foo") { "foo" }'])
expect {
update_app_file(
:routes => ['get("/foo") { "foo" }'],
:filters => ['after { @bye = "bye" }']
)
get('/foo') # ...to perform the reload
}.to change { app_const.filters[:after].size }.by(1)
end
it "knows when a before filter has been removed" do
setup_example_app(
:routes => ['get("/foo") { "foo" }'],
:filters => ['before { @hi = "hi" }']
)
expect {
update_app_file(:routes => ['get("/foo") { "foo" }'])
get('/foo') # ...to perform the reload
}.to change { app_const.filters[:before].size }.by(-1)
end
it "knows when an after filter has been removed" do
setup_example_app(
:routes => ['get("/foo") { "foo" }'],
:filters => ['after { @bye = "bye" }']
)
expect {
update_app_file(:routes => ['get("/foo") { "foo" }'])
get('/foo') # ...to perform the reload
}.to change { app_const.filters[:after].size }.by(-1)
end
end
describe "error reloading" do
before do
setup_example_app(
:routes => ['get("/secret") { 403 }'],
:errors => { 403 => "'Access forbiden'" }
)
end
it "doesn't mess up the application" do
get('/secret').should be_client_error
get('/secret').body.strip.should == 'Access forbiden'
end
it "knows when a error has been added" do
update_app_file(:errors => { 404 => "'Nowhere'" })
get('/nowhere').should be_not_found
get('/nowhere').body.should == 'Nowhere'
end
it "knows when a error has been removed" do
update_app_file(:routes => ['get("/secret") { 403 }'])
get('/secret').should be_client_error
get('/secret').body.should_not == 'Access forbiden'
end
it "knows when a error has been modified" do
update_app_file(
:routes => ['get("/secret") { 403 }'],
:errors => { 403 => "'What are you doing here?'" }
)
get('/secret').should be_client_error
get('/secret').body.should == 'What are you doing here?'
end
end
describe "extension reloading" do
it "doesn't duplicate routes with every reload" do
module ::RouteExtension
def self.registered(klass)
klass.get('/bar') { 'bar' }
end
end
setup_example_app(
:routes => ['get("/foo") { "foo" }'],
:extensions => ['RouteExtension']
)
expect {
update_app_file(
:routes => ['get("/foo") { "foo" }'],
:extensions => ['RouteExtension']
)
get('/foo') # ...to perform the reload
}.to_not change { app_const.routes['GET'].size }
end
it "doesn't duplicate middleware with every reload" do
module ::MiddlewareExtension
def self.registered(klass)
klass.use Rack::Head
end
end
setup_example_app(
:routes => ['get("/foo") { "foo" }'],
:extensions => ['MiddlewareExtension']
)
expect {
update_app_file(
:routes => ['get("/foo") { "foo" }'],
:extensions => ['MiddlewareExtension']
)
get('/foo') # ...to perform the reload
}.to_not change { app_const.middleware.size }
end
it "doesn't duplicate before filters with every reload" do
module ::BeforeFilterExtension
def self.registered(klass)
klass.before { @hi = 'hi' }
end
end
setup_example_app(
:routes => ['get("/foo") { "foo" }'],
:extensions => ['BeforeFilterExtension']
)
expect {
update_app_file(
:routes => ['get("/foo") { "foo" }'],
:extensions => ['BeforeFilterExtension']
)
get('/foo') # ...to perform the reload
}.to_not change { app_const.filters[:before].size }
end
it "doesn't duplicate after filters with every reload" do
module ::AfterFilterExtension
def self.registered(klass)
klass.after { @bye = 'bye' }
end
end
setup_example_app(
:routes => ['get("/foo") { "foo" }'],
:extensions => ['AfterFilterExtension']
)
expect {
update_app_file(
:routes => ['get("/foo") { "foo" }'],
:extensions => ['AfterFilterExtension']
)
get('/foo') # ...to perform the reload
}.to_not change { app_const.filters[:after].size }
end
end
describe ".dont_reload" do
before(:each) do
setup_example_app(
:routes => ['get("/foo") { erb :foo }'],
:inline_templates => { :foo => 'foo' }
)
end
it "allows to specify a file to stop from being reloaded" do
app_const.dont_reload app_file_path
update_app_file(:routes => ['get("/foo") { "bar" }'])
get('/foo').body.strip.should == 'foo'
end
it "allows to specify a glob to stop matching files from being reloaded" do
app_const.dont_reload '**/*.rb'
update_app_file(:routes => ['get("/foo") { "bar" }'])
get('/foo').body.strip.should == 'foo'
end
it "doesn't interfere with other application's reloading policy" do
app_const.dont_reload '**/*.rb'
setup_example_app(:routes => ['get("/foo") { "foo" }'])
update_app_file(:routes => ['get("/foo") { "bar" }'])
get('/foo').body.strip.should == 'bar'
end
end
describe ".also_reload" do
before(:each) do
setup_example_app(:routes => ['get("/foo") { Foo.foo }'])
@foo_path = File.join(tmp_dir, 'foo.rb')
update_file(@foo_path) do |f|
f.write 'class Foo; def self.foo() "foo" end end'
end
$LOADED_FEATURES.delete @foo_path
require @foo_path
app_const.also_reload @foo_path
end
it "allows to specify a file to be reloaded" do
get('/foo').body.strip.should == 'foo'
update_file(@foo_path) do |f|
f.write 'class Foo; def self.foo() "bar" end end'
end
get('/foo').body.strip.should == 'bar'
end
it "allows to specify glob to reaload matching files" do
get('/foo').body.strip.should == 'foo'
update_file(@foo_path) do |f|
f.write 'class Foo; def self.foo() "bar" end end'
end
get('/foo').body.strip.should == 'bar'
end
it "doesn't try to reload a removed file" do
update_file(@foo_path) do |f|
f.write 'class Foo; def self.foo() "bar" end end'
end
FileUtils.rm @foo_path
get('/foo').body.strip.should == 'foo'
end
it "doesn't interfere with other application's reloading policy" do
app_const.also_reload '**/*.rb'
setup_example_app(:routes => ['get("/foo") { Foo.foo }'])
get('/foo').body.strip.should == 'foo'
update_file(@foo_path) do |f|
f.write 'class Foo; def self.foo() "bar" end end'
end
get('/foo').body.strip.should == 'foo'
end
end
it "automatically registers the reloader in the subclasses" do
class ::Parent < Sinatra::Base
register Sinatra::Reloader
enable :reloader
end
setup_example_app(
:routes => ['get("/foo") { "foo" }'],
:enable_reloader => false,
:parent => 'Parent'
)
update_app_file(
:routes => ['get("/foo") { "bar" }'],
:enable_reloader => false,
:parent => 'Parent'
)
get('/foo').body.should == 'bar'
end
end
sinatra-contrib-1.4.1/spec/namespace/ 0000755 0000041 0000041 00000000000 12207620341 017527 5 ustar www-data www-data sinatra-contrib-1.4.1/spec/namespace/nested/ 0000755 0000041 0000041 00000000000 12207620341 021011 5 ustar www-data www-data sinatra-contrib-1.4.1/spec/namespace/nested/foo.erb 0000644 0000041 0000041 00000000003 12207620341 022257 0 ustar www-data www-data ho
sinatra-contrib-1.4.1/spec/namespace/foo.erb 0000644 0000041 0000041 00000000003 12207620341 020775 0 ustar www-data www-data hi
sinatra-contrib-1.4.1/spec/extension_spec.rb 0000644 0000041 0000041 00000001251 12207620341 021145 0 ustar www-data www-data require 'backports'
require_relative 'spec_helper'
describe Sinatra::Extension do
module ExampleExtension
extend Sinatra::Extension
set :foo, :bar
settings.set :bar, :blah
configure :test, :production do
set :reload_stuff, false
end
configure :development do
set :reload_stuff, true
end
get '/' do
"from extension, yay"
end
end
before { mock_app { register ExampleExtension }}
it('allows using set') { settings.foo.should == :bar }
it('implements configure') { settings.reload_stuff.should be_false }
it 'allows defing routes' do
get('/').should be_ok
body.should == "from extension, yay"
end
end
sinatra-contrib-1.4.1/spec/content_for_spec.rb 0000644 0000041 0000041 00000014706 12207620341 021462 0 ustar www-data www-data require 'backports'
require_relative 'spec_helper'
describe Sinatra::ContentFor do
subject do
Sinatra.new do
helpers Sinatra::ContentFor
set :views, File.expand_path("../content_for", __FILE__)
end.new!
end
Tilt.prefer Tilt::ERBTemplate
extend Forwardable
def_delegators :subject, :content_for, :yield_content
def render(engine, template)
subject.send(:render, engine, template, :layout => false).gsub(/\s/, '')
end
describe "without templates" do
it 'renders blocks declared with the same key you use when rendering' do
content_for(:foo) { "foo" }
yield_content(:foo).should == "foo"
end
it 'renders blocks more than once' do
content_for(:foo) { "foo" }
3.times { yield_content(:foo).should == "foo" }
end
it 'does not render a block with a different key' do
content_for(:bar) { "bar" }
yield_content(:foo).should be_empty
end
it 'renders multiple blocks with the same key' do
content_for(:foo) { "foo" }
content_for(:foo) { "bar" }
content_for(:bar) { "WON'T RENDER ME" }
content_for(:foo) { "baz" }
yield_content(:foo).should == "foobarbaz"
end
it 'renders multiple blocks more than once' do
content_for(:foo) { "foo" }
content_for(:foo) { "bar" }
content_for(:bar) { "WON'T RENDER ME" }
content_for(:foo) { "baz" }
3.times { yield_content(:foo).should == "foobarbaz" }
end
it 'passes values to the blocks' do
content_for(:foo) { |a| a.upcase }
yield_content(:foo, 'a').should == "A"
yield_content(:foo, 'b').should == "B"
end
end
# TODO: liquid radius markaby builder nokogiri
engines = %w[erb erubis haml slim]
engines.each do |inner|
describe inner.capitalize do
before :all do
begin
require inner
rescue LoadError => e
pending "Skipping: " << e.message
end
end
describe "with yield_content in Ruby" do
it 'renders blocks declared with the same key you use when rendering' do
render inner, :same_key
yield_content(:foo).strip.should == "foo"
end
it 'renders blocks more than once' do
render inner, :same_key
3.times { yield_content(:foo).strip.should == "foo" }
end
it 'does not render a block with a different key' do
render inner, :different_key
yield_content(:foo).should be_empty
end
it 'renders multiple blocks with the same key' do
render inner, :multiple_blocks
yield_content(:foo).gsub(/\s/, '').should == "foobarbaz"
end
it 'renders multiple blocks more than once' do
render inner, :multiple_blocks
3.times { yield_content(:foo).gsub(/\s/, '').should == "foobarbaz" }
end
it 'passes values to the blocks' do
render inner, :takes_values
yield_content(:foo, 1, 2).gsub(/\s/, '').should == "12"
end
end
describe "with content_for in Ruby" do
it 'renders blocks declared with the same key you use when rendering' do
content_for(:foo) { "foo" }
render(inner, :layout).should == "foo"
end
it 'renders blocks more than once' do
content_for(:foo) { "foo" }
render(inner, :multiple_yields).should == "foofoofoo"
end
it 'does not render a block with a different key' do
content_for(:bar) { "foo" }
render(inner, :layout).should be_empty
end
it 'renders multiple blocks with the same key' do
content_for(:foo) { "foo" }
content_for(:foo) { "bar" }
content_for(:bar) { "WON'T RENDER ME" }
content_for(:foo) { "baz" }
render(inner, :layout).should == "foobarbaz"
end
it 'renders multiple blocks more than once' do
content_for(:foo) { "foo" }
content_for(:foo) { "bar" }
content_for(:bar) { "WON'T RENDER ME" }
content_for(:foo) { "baz" }
render(inner, :multiple_yields).should == "foobarbazfoobarbazfoobarbaz"
end
it 'passes values to the blocks' do
content_for(:foo) { |a,b| "#{a}#{b}" }
render(inner, :passes_values).should == "12"
end
end
describe "with content_for? in Ruby" do
it 'renders block if key is set' do
content_for(:foo) { "foot" }
render(inner, :footer).should == "foot"
end
it 'does not render a block if different key' do
content_for(:different_key) { "foot" }
render(inner, :footer).should be_empty
end
end
engines.each do |outer|
describe "with yield_content in #{outer.capitalize}" do
def body
last_response.body.gsub(/\s/, '')
end
before :all do
begin
require outer
rescue LoadError => e
pending "Skipping: " << e.message
end
end
before do
mock_app do
helpers Sinatra::ContentFor
set inner, :layout_engine => outer
set :views, File.expand_path("../content_for", __FILE__)
get('/:view') { render(inner, params[:view].to_sym) }
get('/:layout/:view') do
render inner, params[:view].to_sym, :layout => params[:layout].to_sym
end
end
end
it 'renders blocks declared with the same key you use when rendering' do
get('/same_key').should be_ok
body.should == "foo"
end
it 'renders blocks more than once' do
get('/multiple_yields/same_key').should be_ok
body.should == "foofoofoo"
end
it 'does not render a block with a different key' do
get('/different_key').should be_ok
body.should be_empty
end
it 'renders multiple blocks with the same key' do
get('/multiple_blocks').should be_ok
body.should == "foobarbaz"
end
it 'renders multiple blocks more than once' do
get('/multiple_yields/multiple_blocks').should be_ok
body.should == "foobarbazfoobarbazfoobarbaz"
end
it 'passes values to the blocks' do
get('/passes_values/takes_values').should be_ok
body.should == "12"
end
end
end
end
end
end
sinatra-contrib-1.4.1/spec/capture_spec.rb 0000644 0000041 0000041 00000003370 12207620341 020600 0 ustar www-data www-data # -*- coding: utf-8 -*-
require 'backports'
require 'slim'
require_relative 'spec_helper'
describe Sinatra::Capture do
subject do
Sinatra.new do
enable :inline_templates
helpers Sinatra::Capture
end.new!
end
Tilt.prefer Tilt::ERBTemplate
extend Forwardable
def_delegators :subject, :capture, :capture_later
def render(engine, template)
subject.send(:render, engine, template.to_sym).strip.gsub(/\s+/, ' ')
end
shared_examples_for "a template language" do |engine|
lang = engine == :erubis ? :erb : engine
require "#{engine}"
it "captures content" do
render(engine, "simple_#{lang}").should == "Say Hello World!"
end
it "allows nested captures" do
render(engine, "nested_#{lang}").should == "Say Hello World!"
end
end
describe('haml') { it_behaves_like "a template language", :haml }
describe('slim') { it_behaves_like "a template language", :slim }
describe('erubis') { it_behaves_like "a template language", :erubis }
describe 'erb' do
it_behaves_like "a template language", :erb
it "handles utf-8 encoding" do
render(:erb, "utf_8").should == "UTF-8 –"
end
end
end
__END__
@@ simple_erb
Say
<% a = capture do %>World<% end %>
Hello <%= a %>!
@@ nested_erb
Say
<% a = capture do %>
<% b = capture do %>World<% end %>
<%= b %>!
<% end %>
Hello <%= a.strip %>
@@ simple_slim
| Say
- a = capture do
| World
| Hello #{a.strip}!
@@ nested_slim
| Say
- a = capture do
- b = capture do
| World
| #{b.strip}!
| Hello #{a.strip}
@@ simple_haml
Say
- a = capture do
World
Hello #{a.strip}!
@@ nested_haml
Say
- a = capture do
- b = capture do
World
#{b.strip}!
Hello #{a.strip}
@@ utf_8
<% a = capture do %>–<% end %>
UTF-8 <%= a %>
sinatra-contrib-1.4.1/spec/multi_route_spec.rb 0000644 0000041 0000041 00000002345 12207620341 021506 0 ustar www-data www-data require 'backports'
require_relative 'spec_helper'
describe Sinatra::MultiRoute do
it 'does not break normal routing' do
mock_app do
register Sinatra::MultiRoute
get('/') { 'normal' }
end
get('/').should be_ok
body.should be == 'normal'
end
it 'supports multiple routes' do
mock_app do
register Sinatra::MultiRoute
get('/foo', '/bar') { 'paths' }
end
get('/foo').should be_ok
body.should be == 'paths'
get('/bar').should be_ok
body.should be == 'paths'
end
it 'triggers conditions' do
count = 0
mock_app do
register Sinatra::MultiRoute
set(:some_condition) { |_| count += 1 }
get('/foo', '/bar', :some_condition => true) { 'paths' }
end
count.should be == 4
end
it 'supports multiple verbs' do
mock_app do
register Sinatra::MultiRoute
route('PUT', 'POST', '/') { 'verb' }
end
post('/').should be_ok
body.should be == 'verb'
put('/').should be_ok
body.should be == 'verb'
end
it 'takes symbols as verbs' do
mock_app do
register Sinatra::MultiRoute
route(:get, '/baz') { 'symbol as verb' }
end
get('/baz').should be_ok
body.should be == 'symbol as verb'
end
end
sinatra-contrib-1.4.1/spec/reloader/ 0000755 0000041 0000041 00000000000 12207620341 017370 5 ustar www-data www-data sinatra-contrib-1.4.1/spec/reloader/app.rb.erb 0000644 0000041 0000041 00000001270 12207620341 021244 0 ustar www-data www-data class <%= name %> < <%= parent %>
<% if enable_reloader %>
register Sinatra::Reloader
enable :reloader
<% end %>
<% unless inline_templates.nil? %>
enable :inline_templates
<% end %>
<% extensions.each do |extension| %>
register <%= extension %>
<% end %>
<% middlewares.each do |middleware| %>
use <%= middleware %>
<% end %>
<% filters.each do |filter| %>
<%= filter %>
<% end %>
<% errors.each do |number, code| %>
error <%= number %> do
<%= code %>
end
<% end %>
<% routes.each do |route| %>
<%= route %>
<% end %>
end
<% unless inline_templates.nil? %>
__END__
<% inline_templates.each_pair do |name, content| %>
@@<%= name %>
<%= content %>
<% end %>
<% end %>
sinatra-contrib-1.4.1/spec/streaming_spec.rb 0000644 0000041 0000041 00000022132 12207620341 021123 0 ustar www-data www-data require 'backports'
require_relative 'spec_helper'
describe Sinatra::Streaming do
def stream(&block)
rack_middleware = @use
out = nil
mock_app do
rack_middleware.each { |args| use(*args) }
helpers Sinatra::Streaming
get('/') { out = stream(&block) }
end
get('/')
out
end
def use(*args)
@use << args
end
before do
@use = []
end
context 'stream test helper' do
it 'runs the given block' do
ran = false
stream { ran = true }
ran.should be_true
end
it 'returns the stream object' do
out = stream { }
out.should be_a(Sinatra::Helpers::Stream)
end
it 'fires a request against that stream' do
stream { |out| out << "Hello World!" }
last_response.should be_ok
body.should be == "Hello World!"
end
it 'passes the stream object to the block' do
passed = nil
returned = stream { |out| passed = out }
passed.should be == returned
end
end
context Sinatra::Streaming::Stream do
it 'should extend the stream object' do
out = stream { }
out.should be_a(Sinatra::Streaming::Stream)
end
it 'should not extend stream objects of other apps' do
out = nil
mock_app { get('/') { out = stream { }}}
get('/')
out.should be_a(Sinatra::Helpers::Stream)
out.should_not be_a(Sinatra::Streaming::Stream)
end
end
context 'app' do
it 'is the app instance the stream was created from' do
out = stream { }
out.app.should be_a(Sinatra::Base)
end
end
context 'lineno' do
it 'defaults to 0' do
stream { }.lineno.should be == 0
end
it 'does not increase on write' do
stream do |out|
out << "many\nlines\n"
out.lineno.should be == 0
end
end
it 'is writable' do
out = stream { }
out.lineno = 10
out.lineno.should be == 10
end
end
context 'pos' do
it 'defaults to 0' do
stream { }.pos.should be == 0
end
it 'increases when writing data' do
stream do |out|
out.pos.should be == 0
out << 'hi'
out.pos.should be == 2
end
end
it 'is writable' do
out = stream { }
out.pos = 10
out.pos.should be == 10
end
it 'aliased to #tell' do
out = stream { }
out.tell.should be == 0
out.pos = 10
out.tell.should be == 10
end
end
context 'closed' do
it 'returns false while streaming' do
stream { |out| out.should_not be_closed }
end
it 'returns true after streaming' do
stream {}.should be_closed
end
end
context 'map!' do
it 'applies transformations later' do
stream do |out|
out.map! { |s| s.upcase }
out << 'ok'
end
body.should be == "OK"
end
it 'is chainable' do
stream do |out|
out.map! { |s| s.upcase }
out.map! { |s| s.reverse }
out << 'ok'
end
body.should be == "KO"
end
it 'works with middleware' do
middleware = Class.new do
def initialize(app) @app = app end
def call(env)
status, headers, body = @app.call(env)
body.map! { |s| s.upcase }
[status, headers, body]
end
end
use middleware
stream { |out| out << "ok" }
body.should be == "OK"
end
it 'modifies each value separately' do
stream do |out|
out.map! { |s| s.reverse }
out << "ab" << "cd"
end
body.should be == "badc"
end
end
context 'map' do
it 'works with middleware' do
middleware = Class.new do
def initialize(app) @app = app end
def call(env)
status, headers, body = @app.call(env)
[status, headers, body.map(&:upcase)]
end
end
use middleware
stream { |out| out << "ok" }
body.should be == "OK"
end
it 'is chainable' do
middleware = Class.new do
def initialize(app) @app = app end
def call(env)
status, headers, body = @app.call(env)
[status, headers, body.map(&:upcase).map(&:reverse)]
end
end
use middleware
stream { |out| out << "ok" }
body.should be == "KO"
end
it 'can be written as each.map' do
middleware = Class.new do
def initialize(app) @app = app end
def call(env)
status, headers, body = @app.call(env)
[status, headers, body.each.map(&:upcase)]
end
end
use middleware
stream { |out| out << "ok" }
body.should be == "OK"
end
it 'does not modify the original body' do
stream do |out|
out.map { |s| s.reverse }
out << 'ok'
end
body.should be == 'ok'
end
end
context 'write' do
it 'writes to the stream' do
stream { |out| out.write 'hi' }
body.should be == 'hi'
end
it 'returns the number of bytes' do
stream do |out|
out.write('hi').should be == 2
out.write('hello').should be == 5
end
end
it 'accepts non-string objects' do
stream do |out|
out.write(12).should be == 2
end
end
it 'should be aliased to syswrite' do
stream { |out| out.syswrite('hi').should be == 2 }
body.should be == 'hi'
end
it 'should be aliased to write_nonblock' do
stream { |out| out.write_nonblock('hi').should be == 2 }
body.should be == 'hi'
end
end
context 'print' do
it 'writes to the stream' do
stream { |out| out.print('hi') }
body.should be == 'hi'
end
it 'accepts multiple arguments' do
stream { |out| out.print(1, 2, 3, 4) }
body.should be == '1234'
end
it 'returns nil' do
stream { |out| out.print('hi').should be_nil }
end
end
context 'printf' do
it 'writes to the stream' do
stream { |out| out.printf('hi') }
body.should be == 'hi'
end
it 'interpolates the format string' do
stream { |out| out.printf("%s: %d", "answer", 42) }
body.should be == 'answer: 42'
end
it 'returns nil' do
stream { |out| out.printf('hi').should be_nil }
end
end
context 'putc' do
it 'writes the first character of a string' do
stream { |out| out.putc('hi') }
body.should be == 'h'
end
it 'writes the character corresponding to an integer' do
stream { |out| out.putc(42) }
body.should be == '*'
end
it 'returns nil' do
stream { |out| out.putc('hi').should be_nil }
end
end
context 'puts' do
it 'writes to the stream' do
stream { |out| out.puts('hi') }
body.should be == "hi\n"
end
it 'accepts multiple arguments' do
stream { |out| out.puts(1, 2, 3, 4) }
body.should be == "1\n2\n3\n4\n"
end
it 'returns nil' do
stream { |out| out.puts('hi').should be_nil }
end
end
context 'close' do
it 'sets #closed? to true' do
stream do |out|
out.close
out.should be_closed
end
end
it 'sets #closed_write? to true' do
stream do |out|
out.should_not be_closed_write
out.close
out.should be_closed_write
end
end
it 'fires callbacks' do
stream do |out|
fired = false
out.callback { fired = true }
out.close
fired.should be_true
end
end
it 'prevents from further writing' do
stream do |out|
out.close
expect { out << 'hi' }.to raise_error(IOError, 'not opened for writing')
end
end
end
context 'close_read' do
it 'raises the appropriate exception' do
expect { stream { |out| out.close_read }}.
to raise_error(IOError, "closing non-duplex IO for reading")
end
end
context 'closed_read?' do
it('returns true') { stream { |out| out.should be_closed_read }}
end
context 'rewind' do
it 'resets pos' do
stream do |out|
out << 'hi'
out.rewind
out.pos.should be == 0
end
end
it 'resets lineno' do
stream do |out|
out.lineno = 10
out.rewind
out.lineno.should be == 0
end
end
end
raises = %w[
bytes eof? eof getbyte getc gets read read_nonblock readbyte readchar
readline readlines readpartial sysread ungetbyte ungetc
]
enum = %w[chars each_line each_byte each_char lines]
dummies = %w[flush fsync internal_encoding pid]
raises.each do |method|
context method do
it 'raises the appropriate exception' do
expect { stream { |out| out.public_send(method) }}.
to raise_error(IOError, "not opened for reading")
end
end
end
enum.each do |method|
context method do
it 'creates an Enumerator' do
stream { |out| out.public_send(method).should be_a(Enumerator) }
end
it 'calling each raises the appropriate exception' do
expect { stream { |out| out.public_send(method).each { }}}.
to raise_error(IOError, "not opened for reading")
end
end
end
dummies.each do |method|
context method do
it 'returns nil' do
stream { |out| out.public_send(method).should be_nil }
end
end
end
end
sinatra-contrib-1.4.1/spec/content_for/ 0000755 0000041 0000041 00000000000 12207620341 020113 5 ustar www-data www-data sinatra-contrib-1.4.1/spec/content_for/passes_values.haml 0000644 0000041 0000041 00000000033 12207620341 023627 0 ustar www-data www-data = yield_content :foo, 1, 2
sinatra-contrib-1.4.1/spec/content_for/passes_values.erb 0000644 0000041 0000041 00000000037 12207620341 023462 0 ustar www-data www-data <%= yield_content :foo, 1, 2 %> sinatra-contrib-1.4.1/spec/content_for/different_key.erubis 0000644 0000041 0000041 00000000046 12207620341 024144 0 ustar www-data www-data <% content_for :bar do %>bar<% end %>
sinatra-contrib-1.4.1/spec/content_for/different_key.erb 0000644 0000041 0000041 00000000046 12207620341 023423 0 ustar www-data www-data <% content_for :bar do %>bar<% end %>
sinatra-contrib-1.4.1/spec/content_for/takes_values.erb 0000644 0000041 0000041 00000000101 12207620341 023263 0 ustar www-data www-data <% content_for :foo do |a, b| %><%= a %> <%= b %><% end %> sinatra-contrib-1.4.1/spec/content_for/layout.slim 0000644 0000041 0000041 00000000025 12207620341 022313 0 ustar www-data www-data = yield_content :foo
sinatra-contrib-1.4.1/spec/content_for/multiple_blocks.slim 0000644 0000041 0000041 00000000204 12207620341 024165 0 ustar www-data www-data - content_for :foo do
| foo
- content_for :foo do
| bar
- content_for :baz do
| WON'T RENDER ME
- content_for :foo do
| baz
sinatra-contrib-1.4.1/spec/content_for/multiple_yields.erubis 0000644 0000041 0000041 00000000116 12207620341 024530 0 ustar www-data www-data <%= yield_content :foo %>
<%= yield_content :foo %>
<%= yield_content :foo %>
sinatra-contrib-1.4.1/spec/content_for/takes_values.slim 0000644 0000041 0000041 00000000052 12207620341 023464 0 ustar www-data www-data - content_for :foo do |a, b|
i= a
= b
sinatra-contrib-1.4.1/spec/content_for/footer.erb 0000644 0000041 0000041 00000000100 12207620341 022072 0 ustar www-data www-data <% if content_for? :foo %>
<%= yield_content :foo %>
<% end %> sinatra-contrib-1.4.1/spec/content_for/different_key.slim 0000644 0000041 0000041 00000000036 12207620341 023616 0 ustar www-data www-data - content_for :bar do
| bar
sinatra-contrib-1.4.1/spec/content_for/same_key.erb 0000644 0000041 0000041 00000000046 12207620341 022402 0 ustar www-data www-data <% content_for :foo do %>foo<% end %>
sinatra-contrib-1.4.1/spec/content_for/footer.slim 0000644 0000041 0000041 00000000054 12207620341 022276 0 ustar www-data www-data - if content_for? :foo
= yield_content :foo sinatra-contrib-1.4.1/spec/content_for/passes_values.erubis 0000644 0000041 0000041 00000000037 12207620341 024203 0 ustar www-data www-data <%= yield_content :foo, 1, 2 %> sinatra-contrib-1.4.1/spec/content_for/passes_values.slim 0000644 0000041 0000041 00000000034 12207620341 023653 0 ustar www-data www-data == yield_content :foo, 1, 2
sinatra-contrib-1.4.1/spec/content_for/multiple_yields.slim 0000644 0000041 0000041 00000000077 12207620341 024211 0 ustar www-data www-data = yield_content :foo
= yield_content :foo
= yield_content :foo
sinatra-contrib-1.4.1/spec/content_for/multiple_yields.erb 0000644 0000041 0000041 00000000116 12207620341 024007 0 ustar www-data www-data <%= yield_content :foo %>
<%= yield_content :foo %>
<%= yield_content :foo %>
sinatra-contrib-1.4.1/spec/content_for/multiple_blocks.erubis 0000644 0000041 0000041 00000000244 12207620341 024516 0 ustar www-data www-data <% 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 %>
sinatra-contrib-1.4.1/spec/content_for/takes_values.haml 0000644 0000041 0000041 00000000052 12207620341 023441 0 ustar www-data www-data - content_for :foo do |a, b|
%i= a
=b
sinatra-contrib-1.4.1/spec/content_for/footer.erubis 0000644 0000041 0000041 00000000100 12207620341 022613 0 ustar www-data www-data <% if content_for? :foo %>
<%= yield_content :foo %>
<% end %> sinatra-contrib-1.4.1/spec/content_for/layout.haml 0000644 0000041 0000041 00000000025 12207620341 022270 0 ustar www-data www-data = yield_content :foo
sinatra-contrib-1.4.1/spec/content_for/layout.erb 0000644 0000041 0000041 00000000031 12207620341 022114 0 ustar www-data www-data <%= yield_content :foo %> sinatra-contrib-1.4.1/spec/content_for/multiple_blocks.haml 0000644 0000041 0000041 00000000174 12207620341 024150 0 ustar www-data www-data - content_for :foo do
foo
- content_for :foo do
bar
- content_for :baz do
WON'T RENDER ME
- content_for :foo do
baz
sinatra-contrib-1.4.1/spec/content_for/different_key.haml 0000644 0000041 0000041 00000000034 12207620341 023571 0 ustar www-data www-data - content_for :bar do
bar
sinatra-contrib-1.4.1/spec/content_for/same_key.erubis 0000644 0000041 0000041 00000000046 12207620341 023123 0 ustar www-data www-data <% content_for :foo do %>foo<% end %>
sinatra-contrib-1.4.1/spec/content_for/layout.erubis 0000644 0000041 0000041 00000000031 12207620341 022635 0 ustar www-data www-data <%= yield_content :foo %> sinatra-contrib-1.4.1/spec/content_for/multiple_blocks.erb 0000644 0000041 0000041 00000000244 12207620341 023775 0 ustar www-data www-data <% 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 %>
sinatra-contrib-1.4.1/spec/content_for/multiple_yields.haml 0000644 0000041 0000041 00000000077 12207620341 024166 0 ustar www-data www-data = yield_content :foo
= yield_content :foo
= yield_content :foo
sinatra-contrib-1.4.1/spec/content_for/takes_values.erubis 0000644 0000041 0000041 00000000101 12207620341 024004 0 ustar www-data www-data <% content_for :foo do |a, b| %><%= a %> <%= b %><% end %> sinatra-contrib-1.4.1/spec/content_for/same_key.slim 0000644 0000041 0000041 00000000036 12207620341 022575 0 ustar www-data www-data - content_for :foo do
| foo
sinatra-contrib-1.4.1/spec/content_for/footer.haml 0000644 0000041 0000041 00000000054 12207620341 022253 0 ustar www-data www-data - if content_for? :foo
= yield_content :foo sinatra-contrib-1.4.1/spec/content_for/same_key.haml 0000644 0000041 0000041 00000000034 12207620341 022550 0 ustar www-data www-data - content_for :foo do
foo
sinatra-contrib-1.4.1/spec/config_file/ 0000755 0000041 0000041 00000000000 12207620341 020037 5 ustar www-data www-data sinatra-contrib-1.4.1/spec/config_file/with_nested_envs.yml 0000644 0000041 0000041 00000000310 12207620341 024124 0 ustar www-data www-data ---
database:
production:
adapter: postgresql
database: foo_production
development:
adapter: sqlite
database: db/development.db
test:
adapter: sqlite
database: db/test.db sinatra-contrib-1.4.1/spec/config_file/key_value_override.yml 0000644 0000041 0000041 00000000015 12207620341 024441 0 ustar www-data www-data ---
foo: foo
sinatra-contrib-1.4.1/spec/config_file/key_value.yml 0000644 0000041 0000041 00000000061 12207620341 022543 0 ustar www-data www-data ---
foo: bar
something: 42
nested:
a: 1
b: 2
sinatra-contrib-1.4.1/spec/config_file/key_value.yml.erb 0000644 0000041 0000041 00000000117 12207620341 023314 0 ustar www-data www-data ---
foo: <%= "bar" %>
something: <%= 42 %>
nested:
a: <%= 1 %>
b: <%= 2 %>
sinatra-contrib-1.4.1/spec/config_file/missing_env.yml 0000644 0000041 0000041 00000000053 12207620341 023101 0 ustar www-data www-data ---
foo:
production: 10
development: 20 sinatra-contrib-1.4.1/spec/config_file/with_envs.yml 0000644 0000041 0000041 00000000124 12207620341 022565 0 ustar www-data www-data ---
development:
foo: development
production:
foo: production
test:
foo: test
sinatra-contrib-1.4.1/spec/json_spec.rb 0000644 0000041 0000041 00000006337 12207620341 020114 0 ustar www-data www-data require 'backports'
require 'multi_json'
require_relative 'spec_helper'
require_relative 'okjson'
shared_examples_for "a json encoder" do |lib, const|
before do
begin
require lib if lib
@encoder = eval(const)
rescue LoadError
pending "unable to load #{lib}"
end
end
it "allows setting :encoder to #{const}" do
enc = @encoder
mock_app { get('/') { json({'foo' => 'bar'}, :encoder => enc) }}
results_in 'foo' => 'bar'
end
it "allows setting settings.json_encoder to #{const}" do
enc = @encoder
mock_app do
set :json_encoder, enc
get('/') { json 'foo' => 'bar' }
end
results_in 'foo' => 'bar'
end
end
describe Sinatra::JSON do
def mock_app(&block)
super do
class_eval(&block)
end
end
def results_in(obj)
OkJson.decode(get('/').body).should == obj
end
it "encodes objects to json out of the box" do
mock_app { get('/') { json :foo => [1, 'bar', nil] } }
results_in 'foo' => [1, 'bar', nil]
end
it "sets the content type to 'application/json'" do
mock_app { get('/') { json({}) } }
get('/')["Content-Type"].should include("application/json")
end
it "allows overriding content type with :content_type" do
mock_app { get('/') { json({}, :content_type => "foo/bar") } }
get('/')["Content-Type"].should == "foo/bar"
end
it "accepts shorthands for :content_type" do
mock_app { get('/') { json({}, :content_type => :js) } }
get('/')["Content-Type"].should == "application/javascript;charset=utf-8"
end
it 'calls generate on :encoder if available' do
enc = Object.new
def enc.generate(obj) obj.inspect end
mock_app { get('/') { json(42, :encoder => enc) }}
get('/').body.should == '42'
end
it 'calls encode on :encoder if available' do
enc = Object.new
def enc.encode(obj) obj.inspect end
mock_app { get('/') { json(42, :encoder => enc) }}
get('/').body.should == '42'
end
it 'sends :encoder as method call if it is a Symbol' do
mock_app { get('/') { json(42, :encoder => :inspect) }}
get('/').body.should == '42'
end
it 'calls generate on settings.json_encoder if available' do
enc = Object.new
def enc.generate(obj) obj.inspect end
mock_app do
set :json_encoder, enc
get('/') { json 42 }
end
get('/').body.should == '42'
end
it 'calls encode on settings.json_encode if available' do
enc = Object.new
def enc.encode(obj) obj.inspect end
mock_app do
set :json_encoder, enc
get('/') { json 42 }
end
get('/').body.should == '42'
end
it 'sends settings.json_encode as method call if it is a Symbol' do
mock_app do
set :json_encoder, :inspect
get('/') { json 42 }
end
get('/').body.should == '42'
end
describe('Yajl') { it_should_behave_like "a json encoder", "yajl", "Yajl::Encoder" } unless defined? JRUBY_VERSION
describe('JSON') { it_should_behave_like "a json encoder", "json", "::JSON" }
describe('OkJson') { it_should_behave_like "a json encoder", nil, "OkJson" }
describe('to_json') { it_should_behave_like "a json encoder", "json", ":to_json" }
describe('without') { it_should_behave_like "a json encoder", nil, "Sinatra::JSON" }
end
sinatra-contrib-1.4.1/spec/namespace_spec.rb 0000644 0000041 0000041 00000053004 12207620341 021070 0 ustar www-data www-data require 'backports'
require_relative 'spec_helper'
describe Sinatra::Namespace do
verbs = [:get, :head, :post, :put, :delete, :options]
verbs << :patch if Sinatra::VERSION >= '1.3'
def mock_app(&block)
super do
register Sinatra::Namespace
class_eval(&block)
end
end
def namespace(*args, &block)
mock_app { namespace(*args, &block) }
end
verbs.each do |verb|
describe "HTTP #{verb.to_s.upcase}" do
it 'prefixes the path with the namespace' do
namespace('/foo') { send(verb, '/bar') { 'baz' }}
send(verb, '/foo/bar').should be_ok
body.should == 'baz' unless verb == :head
send(verb, '/foo/baz').should_not be_ok
end
context 'when namespace is a string' do
it 'accepts routes with no path' do
namespace('/foo') { send(verb) { 'bar' } }
send(verb, '/foo').should be_ok
body.should == 'bar' unless verb == :head
end
it 'accepts the path as a named parameter' do
namespace('/foo') { send(verb, '/:bar') { params[:bar] }}
send(verb, '/foo/bar').should be_ok
body.should == 'bar' unless verb == :head
send(verb, '/foo/baz').should be_ok
body.should == 'baz' unless verb == :head
end
it 'accepts the path as a regular expression' do
namespace('/foo') { send(verb, /\/\d\d/) { 'bar' }}
send(verb, '/foo/12').should be_ok
body.should == 'bar' unless verb == :head
send(verb, '/foo/123').should_not be_ok
end
end
context 'when namespace is a named parameter' do
it 'accepts routes with no path' do
namespace('/:foo') { send(verb) { 'bar' } }
send(verb, '/foo').should be_ok
body.should == 'bar' unless verb == :head
end
it 'sets the parameter correctly' do
namespace('/:foo') { send(verb, '/bar') { params[:foo] }}
send(verb, '/foo/bar').should be_ok
body.should == 'foo' unless verb == :head
send(verb, '/fox/bar').should be_ok
body.should == 'fox' unless verb == :head
send(verb, '/foo/baz').should_not be_ok
end
it 'accepts the path as a named parameter' do
namespace('/:foo') { send(verb, '/:bar') { params[:bar] }}
send(verb, '/foo/bar').should be_ok
body.should == 'bar' unless verb == :head
send(verb, '/foo/baz').should be_ok
body.should == 'baz' unless verb == :head
end
it 'accepts the path as regular expression' do
namespace('/:foo') { send(verb, %r{/bar}) { params[:foo] }}
send(verb, '/foo/bar').should be_ok
body.should == 'foo' unless verb == :head
send(verb, '/fox/bar').should be_ok
body.should == 'fox' unless verb == :head
send(verb, '/foo/baz').should_not be_ok
end
end
context 'when namespace is a regular expression' do
it 'accepts routes with no path' do
namespace(%r{/foo}) { send(verb) { 'bar' } }
send(verb, '/foo').should be_ok
body.should == 'bar' unless verb == :head
end
it 'accepts the path as a named parameter' do
namespace(%r{/foo}) { send(verb, '/:bar') { params[:bar] }}
send(verb, '/foo/bar').should be_ok
body.should == 'bar' unless verb == :head
send(verb, '/foo/baz').should be_ok
body.should == 'baz' unless verb == :head
end
it 'accepts the path as a regular expression' do
namespace(/\/\d\d/) { send(verb, /\/\d\d/) { 'foo' }}
send(verb, '/23/12').should be_ok
body.should == 'foo' unless verb == :head
send(verb, '/123/12').should_not be_ok
end
end
context 'when namespace is a splat' do
it 'accepts the path as a splat' do
namespace('/*') { send(verb, '/*') { params[:splat].join ' - ' }}
send(verb, '/foo/bar').should be_ok
body.should == 'foo - bar' unless verb == :head
end
end
describe 'before-filters' do
specify 'are triggered' do
ran = false
namespace('/foo') { before { ran = true }}
send(verb, '/foo')
ran.should be_true
end
specify 'are not triggered for a different namespace' do
ran = false
namespace('/foo') { before { ran = true }}
send(verb, '/fox')
ran.should be_false
end
end
describe 'after-filters' do
specify 'are triggered' do
ran = false
namespace('/foo') { after { ran = true }}
send(verb, '/foo')
ran.should be_true
end
specify 'are not triggered for a different namespace' do
ran = false
namespace('/foo') { after { ran = true }}
send(verb, '/fox')
ran.should be_false
end
end
describe 'conditions' do
context 'when the namespace has no prefix' do
specify 'are accepted in the namespace' do
mock_app do
namespace(:host_name => 'example.com') { send(verb) { 'yes' }}
send(verb, '/') { 'no' }
end
send(verb, '/', {}, 'HTTP_HOST' => 'example.com')
last_response.should be_ok
body.should == 'yes' unless verb == :head
send(verb, '/', {}, 'HTTP_HOST' => 'example.org')
last_response.should be_ok
body.should == 'no' unless verb == :head
end
specify 'are accepted in the route definition' do
namespace :host_name => 'example.com' do
send(verb, '/foo', :provides => :txt) { 'ok' }
end
send(verb, '/foo', {}, 'HTTP_HOST' => 'example.com', 'HTTP_ACCEPT' => 'text/plain').should be_ok
send(verb, '/foo', {}, 'HTTP_HOST' => 'example.com', 'HTTP_ACCEPT' => 'text/html').should_not be_ok
send(verb, '/foo', {}, 'HTTP_HOST' => 'example.org', 'HTTP_ACCEPT' => 'text/plain').should_not be_ok
end
specify 'are accepted in the before-filter' do
ran = false
namespace :provides => :txt do
before('/foo', :host_name => 'example.com') { ran = true }
send(verb, '/*') { 'ok' }
end
send(verb, '/foo', {}, 'HTTP_HOST' => 'example.org', 'HTTP_ACCEPT' => 'text/plain')
ran.should be_false
send(verb, '/foo', {}, 'HTTP_HOST' => 'example.com', 'HTTP_ACCEPT' => 'text/html')
ran.should be_false
send(verb, '/bar', {}, 'HTTP_HOST' => 'example.com', 'HTTP_ACCEPT' => 'text/plain')
ran.should be_false
send(verb, '/foo', {}, 'HTTP_HOST' => 'example.com', 'HTTP_ACCEPT' => 'text/plain')
ran.should be_true
end
specify 'are accepted in the after-filter' do
ran = false
namespace :provides => :txt do
after('/foo', :host_name => 'example.com') { ran = true }
send(verb, '/*') { 'ok' }
end
send(verb, '/foo', {}, 'HTTP_HOST' => 'example.org', 'HTTP_ACCEPT' => 'text/plain')
ran.should be_false
send(verb, '/foo', {}, 'HTTP_HOST' => 'example.com', 'HTTP_ACCEPT' => 'text/html')
ran.should be_false
send(verb, '/bar', {}, 'HTTP_HOST' => 'example.com', 'HTTP_ACCEPT' => 'text/plain')
ran.should be_false
send(verb, '/foo', {}, 'HTTP_HOST' => 'example.com', 'HTTP_ACCEPT' => 'text/plain')
ran.should be_true
end
end
context 'when the namespace is a string' do
specify 'are accepted in the namespace' do
namespace '/foo', :host_name => 'example.com' do
send(verb) { 'ok' }
end
send(verb, '/foo', {}, 'HTTP_HOST' => 'example.com').should be_ok
send(verb, '/foo', {}, 'HTTP_HOST' => 'example.org').should_not be_ok
end
specify 'are accepted in the before-filter' do
namespace '/foo' do
before(:host_name => 'example.com') { @yes = 'yes' }
send(verb) { @yes || 'no' }
end
send(verb, '/foo', {}, 'HTTP_HOST' => 'example.com')
last_response.should be_ok
body.should == 'yes' unless verb == :head
send(verb, '/foo', {}, 'HTTP_HOST' => 'example.org')
last_response.should be_ok
body.should == 'no' unless verb == :head
end
specify 'are accepted in the after-filter' do
ran = false
namespace '/foo' do
before(:host_name => 'example.com') { ran = true }
send(verb) { 'ok' }
end
send(verb, '/foo', {}, 'HTTP_HOST' => 'example.org')
ran.should be_false
send(verb, '/foo', {}, 'HTTP_HOST' => 'example.com')
ran.should be_true
end
specify 'are accepted in the route definition' do
namespace '/foo' do
send(verb, :host_name => 'example.com') { 'ok' }
end
send(verb, '/foo', {}, 'HTTP_HOST' => 'example.com').should be_ok
send(verb, '/foo', {}, 'HTTP_HOST' => 'example.org').should_not be_ok
end
context 'when the namespace has a condition' do
specify 'are accepted in the before-filter' do
ran = false
namespace '/', :provides => :txt do
before(:host_name => 'example.com') { ran = true }
send(verb) { 'ok' }
end
send(verb, '/', {}, 'HTTP_HOST' => 'example.org', 'HTTP_ACCEPT' => 'text/plain')
ran.should be_false
send(verb, '/', {}, 'HTTP_HOST' => 'example.com', 'HTTP_ACCEPT' => 'text/html')
ran.should be_false
send(verb, '/', {}, 'HTTP_HOST' => 'example.com', 'HTTP_ACCEPT' => 'text/plain')
ran.should be_true
end
specify 'are accepted in the filters' do
ran = false
namespace '/f', :provides => :txt do
before('oo', :host_name => 'example.com') { ran = true }
send(verb, '/*') { 'ok' }
end
send(verb, '/foo', {}, 'HTTP_HOST' => 'example.org', 'HTTP_ACCEPT' => 'text/plain')
ran.should be_false
send(verb, '/foo', {}, 'HTTP_HOST' => 'example.com', 'HTTP_ACCEPT' => 'text/html')
ran.should be_false
send(verb, '/far', {}, 'HTTP_HOST' => 'example.com', 'HTTP_ACCEPT' => 'text/plain')
ran.should be_false
send(verb, '/foo', {}, 'HTTP_HOST' => 'example.com', 'HTTP_ACCEPT' => 'text/plain')
ran.should be_true
end
end
end
end
describe 'helpers' do
it 'are defined using the helpers method' do
namespace '/foo' do
helpers do
def magic
42
end
end
send verb, '/bar' do
magic.to_s
end
end
send(verb, '/foo/bar').should be_ok
body.should == '42' unless verb == :head
end
it 'can be defined as normal methods' do
namespace '/foo' do
def magic
42
end
send verb, '/bar' do
magic.to_s
end
end
send(verb, '/foo/bar').should be_ok
body.should == '42' unless verb == :head
end
it 'can be defined using module mixins' do
mixin = Module.new do
def magic
42
end
end
namespace '/foo' do
helpers mixin
send verb, '/bar' do
magic.to_s
end
end
send(verb, '/foo/bar').should be_ok
body.should == '42' unless verb == :head
end
specify 'are unavailable outside the namespace where they are defined' do
mock_app do
namespace '/foo' do
def magic
42
end
send verb, '/bar' do
magic.to_s
end
end
send verb, '/' do
magic.to_s
end
end
proc { send verb, '/' }.should raise_error(NameError)
end
specify 'are unavailable outside the namespace that they are mixed into' do
mixin = Module.new do
def magic
42
end
end
mock_app do
namespace '/foo' do
helpers mixin
send verb, '/bar' do
magic.to_s
end
end
send verb, '/' do
magic.to_s
end
end
proc { send verb, '/' }.should raise_error(NameError)
end
specify 'are available to nested namespaces' do
mock_app do
helpers do
def magic
42
end
end
namespace '/foo' do
send verb, '/bar' do
magic.to_s
end
end
end
send(verb, '/foo/bar').should be_ok
body.should == '42' unless verb == :head
end
specify 'can call super from nested definitions' do
mock_app do
helpers do
def magic
42
end
end
namespace '/foo' do
def magic
super - 19
end
send verb, '/bar' do
magic.to_s
end
end
end
send(verb, '/foo/bar').should be_ok
body.should == '23' unless verb == :head
end
end
describe 'nesting' do
it 'routes to nested namespaces' do
namespace '/foo' do
namespace '/bar' do
send(verb, '/baz') { 'OKAY!!11!'}
end
end
send(verb, '/foo/bar/baz').should be_ok
body.should == 'OKAY!!11!' unless verb == :head
end
it 'exposes helpers to nested namespaces' do
namespace '/foo' do
helpers do
def magic
42
end
end
namespace '/bar' do
send verb, '/baz' do
magic.to_s
end
end
end
send(verb, '/foo/bar/baz').should be_ok
body.should == '42' unless verb == :head
end
specify 'does not provide access to nested helper methods' do
namespace '/foo' do
namespace '/bar' do
def magic
42
end
send verb, '/baz' do
magic.to_s
end
end
send verb do
magic.to_s
end
end
proc { send verb, '/foo' }.should raise_error(NameError)
end
it 'accepts a nested namespace as a named parameter' do
namespace('/:a') { namespace('/:b') { send(verb) { params[:a] }}}
send(verb, '/foo/bar').should be_ok
body.should == 'foo' unless verb == :head
end
end
describe 'error handling' do
it 'can be customized using the not_found block' do
namespace('/de') do
not_found { 'nicht gefunden' }
end
send(verb, '/foo').status.should == 404
last_response.body.should_not == 'nicht gefunden' unless verb == :head
get('/en/foo').status.should == 404
last_response.body.should_not == 'nicht gefunden' unless verb == :head
get('/de/foo').status.should == 404
last_response.body.should == 'nicht gefunden' unless verb == :head
end
it 'can be customized for specific error codes' do
namespace('/de') do
error(404) { 'nicht gefunden' }
end
send(verb, '/foo').status.should == 404
last_response.body.should_not == 'nicht gefunden' unless verb == :head
get('/en/foo').status.should == 404
last_response.body.should_not == 'nicht gefunden' unless verb == :head
get('/de/foo').status.should == 404
last_response.body.should == 'nicht gefunden' unless verb == :head
end
it 'falls back to the handler defined in the base app' do
mock_app do
error(404) { 'not found...' }
namespace('/en') do
end
namespace('/de') do
error(404) { 'nicht gefunden' }
end
end
send(verb, '/foo').status.should == 404
last_response.body.should == 'not found...' unless verb == :head
get('/en/foo').status.should == 404
last_response.body.should == 'not found...' unless verb == :head
get('/de/foo').status.should == 404
last_response.body.should == 'nicht gefunden' unless verb == :head
end
it 'can be customized for specific Exception classes' do
mock_app do
class AError < StandardError; end
class BError < AError; end
error(AError) do
body('auth failed')
401
end
namespace('/en') do
get '/foo' do
raise BError
end
end
namespace('/de') do
error(AError) do
body('methode nicht erlaubt')
406
end
get '/foo' do
raise BError
end
end
end
get('/en/foo').status.should == 401
last_response.body.should == 'auth failed' unless verb == :head
get('/de/foo').status.should == 406
last_response.body.should == 'methode nicht erlaubt' unless verb == :head
end
end
unless verb == :head
describe 'templates' do
specify 'default to the base app\'s template' do
mock_app do
template(:foo) { 'hi' }
send(verb, '/') { erb :foo }
namespace '/foo' do
send(verb) { erb :foo }
end
end
send(verb, '/').body.should == 'hi'
send(verb, '/foo').body.should == 'hi'
end
specify 'can be nested' do
mock_app do
template(:foo) { 'hi' }
send(verb, '/') { erb :foo }
namespace '/foo' do
template(:foo) { 'ho' }
send(verb) { erb :foo }
end
end
send(verb, '/').body.should == 'hi'
send(verb, '/foo').body.should == 'ho'
end
specify 'can use a custom views directory' do
mock_app do
set :views, File.expand_path('../namespace', __FILE__)
send(verb, '/') { erb :foo }
namespace('/foo') do
set :views, File.expand_path('../namespace/nested', __FILE__)
send(verb) { erb :foo }
end
end
send(verb, '/').body.should == "hi\n"
send(verb, '/foo').body.should == "ho\n"
end
specify 'default to the base app\'s layout' do
mock_app do
layout { 'he said: <%= yield %>' }
template(:foo) { 'hi' }
send(verb, '/') { erb :foo }
namespace '/foo' do
template(:foo) { 'ho' }
send(verb) { erb :foo }
end
end
send(verb, '/').body.should == 'he said: hi'
send(verb, '/foo').body.should == 'he said: ho'
end
specify 'can define nested layouts' do
mock_app do
layout { 'Hello <%= yield %>!' }
template(:foo) { 'World' }
send(verb, '/') { erb :foo }
namespace '/foo' do
layout { 'Hi <%= yield %>!' }
send(verb) { erb :foo }
end
end
send(verb, '/').body.should == 'Hello World!'
send(verb, '/foo').body.should == 'Hi World!'
end
end
end
describe 'extensions' do
specify 'provide read access to settings' do
value = nil
mock_app do
set :foo, 42
namespace '/foo' do
value = foo
end
end
value.should == 42
end
specify 'can be registered within a namespace' do
a = b = nil
extension = Module.new { define_method(:views) { 'CUSTOM!!!' } }
mock_app do
namespace '/' do
register extension
a = views
end
b = views
end
a.should == 'CUSTOM!!!'
b.should_not == 'CUSTOM!!!'
end
specify 'trigger the route_added hook' do
route = nil
extension = Module.new
extension.singleton_class.class_eval do
define_method(:route_added) { |*r| route = r }
end
mock_app do
namespace '/f' do
register extension
get('oo') { }
end
get('/bar') { }
end
route[1].should == '/foo'
end
specify 'prevent app-global settings from being changed' do
proc { namespace('/') { set :foo, :bar }}.should raise_error
end
end
end
end
end
sinatra-contrib-1.4.1/spec/spec_helper.rb 0000644 0000041 0000041 00000000240 12207620341 020405 0 ustar www-data www-data ENV['RACK_ENV'] = 'test'
require 'sinatra/contrib'
RSpec.configure do |config|
config.expect_with :rspec#, :stdlib
config.include Sinatra::TestHelpers
end
sinatra-contrib-1.4.1/spec/respond_with/ 0000755 0000041 0000041 00000000000 12207620341 020300 5 ustar www-data www-data sinatra-contrib-1.4.1/spec/respond_with/not_html.sass 0000644 0000041 0000041 00000000022 12207620341 023011 0 ustar www-data www-data body
color: red
sinatra-contrib-1.4.1/spec/respond_with/foo.html.erb 0000644 0000041 0000041 00000000022 12207620341 022512 0 ustar www-data www-data Hello <%= name %>! sinatra-contrib-1.4.1/spec/respond_with/bar.erb 0000644 0000041 0000041 00000000044 12207620341 021534 0 ustar www-data www-data Girl! I wanna take you to a ... bar! sinatra-contrib-1.4.1/spec/respond_with/baz.yajl 0000644 0000041 0000041 00000000017 12207620341 021733 0 ustar www-data www-data json = "yajl!"
sinatra-contrib-1.4.1/spec/respond_with/bar.json.erb 0000644 0000041 0000041 00000000005 12207620341 022501 0 ustar www-data www-data json! sinatra-contrib-1.4.1/spec/respond_with_spec.rb 0000644 0000041 0000041 00000020373 12207620341 021644 0 ustar www-data www-data require 'backports'
require 'multi_json'
require_relative 'spec_helper'
require_relative 'okjson'
describe Sinatra::RespondWith do
def provides(*args)
@provides = args
end
def respond_app(&block)
types = @provides
mock_app do
set :app_file, __FILE__
set :views, root + '/respond_with'
register Sinatra::RespondWith
respond_to(*types) if types
class_eval(&block)
end
end
def respond_to(*args, &block)
respond_app { get('/') { respond_to(*args, &block) } }
end
def respond_with(*args, &block)
respond_app { get('/') { respond_with(*args, &block) } }
end
def req(*types)
p = types.shift if types.first.is_a? String and types.first.start_with? '/'
accept = types.map { |t| Sinatra::Base.mime_type(t).to_s }.join ','
get (p || '/'), {}, 'HTTP_ACCEPT' => accept
end
describe "Helpers#respond_to" do
it 'allows defining handlers by file extensions' do
respond_to do |format|
format.html { "html!" }
format.json { "json!" }
end
req(:html).body.should == "html!"
req(:json).body.should == "json!"
end
it 'respects quality' do
respond_to do |format|
format.html { "html!" }
format.json { "json!" }
end
req("text/html;q=0.7, application/json;q=0.3").body.should == "html!"
req("text/html;q=0.3, application/json;q=0.7").body.should == "json!"
end
it 'allows using mime types' do
respond_to do |format|
format.on('text/html') { "html!" }
format.json { "json!" }
end
req(:html).body.should == "html!"
end
it 'allows using wildcards in format matchers' do
respond_to do |format|
format.on('text/*') { "text!" }
format.json { "json!" }
end
req(:html).body.should == "text!"
end
it 'allows using catch all wildcards in format matchers' do
respond_to do |format|
format.on('*/*') { "anything!" }
format.json { "json!" }
end
req(:html).body.should == "anything!"
end
it 'prefers concret over generic' do
respond_to do |format|
format.on('text/*') { "text!" }
format.on('*/*') { "anything!" }
format.json { "json!" }
end
req(:json).body.should == "json!"
req(:html).body.should == "text!"
end
it 'does not set up default handlers' do
respond_to
req.should_not be_ok
status.should == 406
end
end
describe "Helpers#respond_with" do
describe "matching" do
it 'allows defining handlers by file extensions' do
respond_with(:ignore) do |format|
format.html { "html!" }
format.json { "json!" }
end
req(:html).body.should == "html!"
req(:json).body.should == "json!"
end
it 'respects quality' do
respond_with(:ignore) do |format|
format.html { "html!" }
format.json { "json!" }
end
req("text/html;q=0.7, application/json;q=0.3").body.should == "html!"
req("text/html;q=0.3, application/json;q=0.7").body.should == "json!"
end
it 'allows using mime types' do
respond_with(:ignore) do |format|
format.on('text/html') { "html!" }
format.json { "json!" }
end
req(:html).body.should == "html!"
end
it 'allows using wildcards in format matchers' do
respond_with(:ignore) do |format|
format.on('text/*') { "text!" }
format.json { "json!" }
end
req(:html).body.should == "text!"
end
it 'allows using catch all wildcards in format matchers' do
respond_with(:ignore) do |format|
format.on('*/*') { "anything!" }
format.json { "json!" }
end
req(:html).body.should == "anything!"
end
it 'prefers concret over generic' do
respond_with(:ignore) do |format|
format.on('text/*') { "text!" }
format.on('*/*') { "anything!" }
format.json { "json!" }
end
req(:json).body.should == "json!"
req(:html).body.should == "text!"
end
end
describe "default behavior" do
it 'converts objects to json out of the box' do
respond_with 'a' => 'b'
OkJson.decode(req(:json).body).should == {'a' => 'b'}
end
it 'handles multiple routes correctly' do
respond_app do
get('/') { respond_with 'a' => 'b' }
get('/:name') { respond_with 'a' => params[:name] }
end
OkJson.decode(req('/', :json).body).should == {'a' => 'b'}
OkJson.decode(req('/b', :json).body).should == {'a' => 'b'}
OkJson.decode(req('/c', :json).body).should == {'a' => 'c'}
end
it "calls to_EXT if available" do
respond_with Struct.new(:to_pdf).new("hello")
req(:pdf).body.should == "hello"
end
it 'results in a 406 if format cannot be produced' do
respond_with({})
req(:html).should_not be_ok
status.should == 406
end
end
describe 'templates' do
it 'looks for templates with name.target.engine' do
respond_with :foo, :name => 'World'
req(:html).should be_ok
body.should == "Hello World!"
end
it 'looks for templates with name.engine for specific engines' do
respond_with :bar
req(:html).should be_ok
body.should == "Girl! I wanna take you to a ... bar!"
end
it 'does not use name.engine for engines producing other formats' do
respond_with :not_html
req(:html).should_not be_ok
status.should == 406
body.should be_empty
end
it 'falls back to #json if no template is found' do
respond_with :foo, :name => 'World'
req(:json).should be_ok
OkJson.decode(body).should == {'name' => 'World'}
end
it 'favors templates over #json' do
respond_with :bar, :name => 'World'
req(:json).should be_ok
body.should == 'json!'
end
it 'falls back to to_EXT if no template is found' do
object = {:name => 'World'}
def object.to_pdf; "hi" end
respond_with :foo, object
req(:pdf).should be_ok
body.should == "hi"
end
unless defined? JRUBY_VERSION
it 'uses yajl for json' do
respond_with :baz
req(:json).should be_ok
body.should == "\"yajl!\""
end
end
end
describe 'customizing' do
it 'allows customizing' do
respond_with(:foo, :name => 'World') { |f| f.html { 'html!' }}
req(:html).should be_ok
body.should == "html!"
end
it 'falls back to default behavior if none matches' do
respond_with(:foo, :name => 'World') { |f| f.json { 'json!' }}
req(:html).should be_ok
body.should == "Hello World!"
end
it 'favors generic rule over default behavior' do
respond_with(:foo, :name => 'World') { |f| f.on('*/*') { 'generic!' }}
req(:html).should be_ok
body.should == "generic!"
end
end
describe "inherited" do
it "registers RespondWith in an inherited app" do
app = Sinatra.new do
set :app_file, __FILE__
set :views, root + '/respond_with'
register Sinatra::RespondWith
get '/a' do
respond_with :json
end
end
self.app = Sinatra.new(app)
req('/a', :json).should_not be_ok
end
end
end
describe :respond_to do
it 'acts as global provides condition' do
respond_app do
respond_to :json, :html
get('/a') { 'ok' }
get('/b') { 'ok' }
end
req('/b', :xml).should_not be_ok
req('/b', :html).should be_ok
end
it 'still allows provides' do
respond_app do
respond_to :json, :html
get('/a') { 'ok' }
get('/b', :provides => :json) { 'ok' }
end
req('/b', :html).should_not be_ok
req('/b', :json).should be_ok
end
it 'plays well with namespaces' do
respond_app do
register Sinatra::Namespace
namespace '/a' do
respond_to :json
get { 'json' }
end
get('/b') { 'anything' }
end
req('/a', :html).should_not be_ok
req('/b', :html).should be_ok
end
end
end
sinatra-contrib-1.4.1/spec/config_file_spec.rb 0000644 0000041 0000041 00000003532 12207620341 021401 0 ustar www-data www-data require 'backports'
require_relative 'spec_helper'
describe Sinatra::ConfigFile do
def config_file(*args, &block)
mock_app do
register Sinatra::ConfigFile
set :root, File.expand_path('../config_file', __FILE__)
instance_eval(&block) if block
config_file(*args)
end
end
it 'should set options from a simple config_file' do
config_file 'key_value.yml'
settings.foo.should == 'bar'
settings.something.should == 42
end
it 'should create indifferent hashes' do
config_file 'key_value.yml'
settings.nested['a'].should == 1
settings.nested[:a].should == 1
end
it 'should render options in ERB tags' do
config_file 'key_value.yml.erb'
settings.foo.should == "bar"
settings.something.should == 42
settings.nested['a'].should == 1
settings.nested[:a].should == 1
settings.nested['b'].should == 2
settings.nested[:b].should == 2
end
it 'should recognize env specific settings per file' do
config_file 'with_envs.yml'
settings.foo.should == 'test'
end
it 'should recognize env specific settings per setting' do
config_file 'with_nested_envs.yml'
settings.database[:adapter].should == 'sqlite'
end
it 'should not set present values to nil if the current env is missing' do
# first let's check the test is actually working properly
config_file('missing_env.yml') { set :foo => 42, :environment => :production }
settings.foo.should == 10
# now test it
config_file('missing_env.yml') { set :foo => 42, :environment => :test }
settings.foo.should == 42
end
it 'should prioritize settings in latter files' do
# first let's check the test is actually working properly
config_file 'key_value.yml'
settings.foo.should == 'bar'
# now test it
config_file 'key_value_override.yml'
settings.foo.should == 'foo'
end
end
sinatra-contrib-1.4.1/spec/decompile_spec.rb 0000644 0000041 0000041 00000002440 12207620341 021073 0 ustar www-data www-data require 'backports'
require_relative 'spec_helper'
RSpec::Matchers.define :decompile do |path|
match do |app|
@compiled, @keys = app.send :compile, path
@decompiled = app.decompile(@compiled, @keys)
@decompiled.should == path
end
failure_message_for_should do |app|
values = [app, @compiled, @keys, path, @decompiled].map(&:inspect)
"expected %s to decompile %s with %s to %s, but was %s" % values
end
end
describe Sinatra::Decompile do
subject { Sinatra::Application }
it { should decompile("") }
it { should decompile("/") }
it { should decompile("/?") }
it { should decompile("/foo") }
it { should decompile("/:name") }
it { should decompile("/:name?") }
it { should decompile("/:foo/:bar") }
it { should decompile("/page/:id/edit") }
it { should decompile("/hello/*") }
it { should decompile("/*/foo/*") }
it { should decompile("*") }
it { should decompile(":name.:format") }
it { should decompile("a b") }
it { should decompile("a+b") }
it { should decompile(/./) }
it { should decompile(/f(oo)/) }
it { should decompile(/ba+r/) }
it 'just returns strings' do
subject.decompile('/foo').should == '/foo'
end
it 'just decompile simple regexps without keys' do
subject.decompile(%r{/foo}).should == '/foo'
end
end
sinatra-contrib-1.4.1/spec/link_header_spec.rb 0000644 0000041 0000041 00000004436 12207620341 021406 0 ustar www-data www-data require 'backports'
require_relative 'spec_helper'
describe Sinatra::LinkHeader do
before do
mock_app do
helpers Sinatra::LinkHeader
before('/') { link 'something', :rel => 'from-filter', :foo => :bar }
get '/' do
link :something, 'booyah'
end
get '/style' do
stylesheet '/style.css'
end
get '/prefetch' do
prefetch '/foo'
end
get '/link_headers' do
response['Link'] = "