sinatra-base 1.0 → 1.4.0

Sign up to get free protection for your applications and to get access to all the features.
Files changed (101) hide show
  1. data/.yardopts +4 -0
  2. data/AUTHORS +15 -0
  3. data/CHANGES +524 -1
  4. data/Gemfile +82 -0
  5. data/LICENSE +1 -1
  6. data/README.de.rdoc +2093 -0
  7. data/README.es.rdoc +2091 -0
  8. data/README.fr.rdoc +2116 -0
  9. data/README.hu.rdoc +607 -0
  10. data/README.jp.rdoc +514 -23
  11. data/README.pt-br.rdoc +647 -0
  12. data/README.pt-pt.rdoc +646 -0
  13. data/README.rdoc +1580 -205
  14. data/README.ru.rdoc +2015 -0
  15. data/README.zh.rdoc +1816 -0
  16. data/Rakefile +110 -44
  17. data/examples/chat.rb +61 -0
  18. data/examples/simple.rb +3 -0
  19. data/examples/stream.ru +26 -0
  20. data/lib/sinatra.rb +0 -3
  21. data/lib/sinatra/base.rb +923 -393
  22. data/lib/sinatra/main.rb +9 -7
  23. data/lib/sinatra/showexceptions.rb +37 -4
  24. data/lib/sinatra/version.rb +3 -0
  25. data/sinatra-base.gemspec +15 -91
  26. data/test/base_test.rb +2 -2
  27. data/test/builder_test.rb +32 -2
  28. data/test/coffee_test.rb +92 -0
  29. data/test/contest.rb +62 -28
  30. data/test/creole_test.rb +65 -0
  31. data/test/delegator_test.rb +162 -0
  32. data/test/encoding_test.rb +20 -0
  33. data/test/erb_test.rb +25 -2
  34. data/test/extensions_test.rb +1 -1
  35. data/test/filter_test.rb +226 -8
  36. data/test/haml_test.rb +8 -2
  37. data/test/helper.rb +47 -0
  38. data/test/helpers_test.rb +1287 -80
  39. data/test/integration/app.rb +62 -0
  40. data/test/integration_helper.rb +208 -0
  41. data/test/integration_test.rb +82 -0
  42. data/test/less_test.rb +36 -6
  43. data/test/liquid_test.rb +59 -0
  44. data/test/mapped_error_test.rb +84 -7
  45. data/test/markaby_test.rb +80 -0
  46. data/test/markdown_test.rb +81 -0
  47. data/test/middleware_test.rb +1 -1
  48. data/test/nokogiri_test.rb +69 -0
  49. data/test/rack_test.rb +45 -0
  50. data/test/radius_test.rb +59 -0
  51. data/test/rdoc_test.rb +66 -0
  52. data/test/readme_test.rb +136 -0
  53. data/test/request_test.rb +13 -1
  54. data/test/response_test.rb +21 -2
  55. data/test/result_test.rb +5 -5
  56. data/test/route_added_hook_test.rb +1 -1
  57. data/test/routing_test.rb +328 -13
  58. data/test/sass_test.rb +48 -18
  59. data/test/scss_test.rb +88 -0
  60. data/test/server_test.rb +4 -3
  61. data/test/settings_test.rb +191 -21
  62. data/test/sinatra_test.rb +5 -1
  63. data/test/slim_test.rb +88 -0
  64. data/test/static_test.rb +89 -5
  65. data/test/streaming_test.rb +140 -0
  66. data/test/templates_test.rb +143 -4
  67. data/test/textile_test.rb +65 -0
  68. data/test/views/a/in_a.str +1 -0
  69. data/test/views/ascii.erb +2 -0
  70. data/test/views/b/in_b.str +1 -0
  71. data/test/views/calc.html.erb +1 -0
  72. data/test/views/explicitly_nested.str +1 -0
  73. data/test/views/hello.coffee +1 -0
  74. data/test/views/hello.creole +1 -0
  75. data/test/views/hello.liquid +1 -0
  76. data/test/views/hello.mab +1 -0
  77. data/test/views/hello.md +1 -0
  78. data/test/views/hello.nokogiri +1 -0
  79. data/test/views/hello.radius +1 -0
  80. data/test/views/hello.rdoc +1 -0
  81. data/test/views/hello.sass +1 -1
  82. data/test/views/hello.scss +3 -0
  83. data/test/views/hello.slim +1 -0
  84. data/test/views/hello.str +1 -0
  85. data/test/views/hello.textile +1 -0
  86. data/test/views/hello.yajl +1 -0
  87. data/test/views/layout2.liquid +2 -0
  88. data/test/views/layout2.mab +2 -0
  89. data/test/views/layout2.nokogiri +3 -0
  90. data/test/views/layout2.radius +2 -0
  91. data/test/views/layout2.slim +3 -0
  92. data/test/views/layout2.str +2 -0
  93. data/test/views/nested.str +1 -0
  94. data/test/views/utf8.erb +2 -0
  95. data/test/yajl_test.rb +80 -0
  96. metadata +126 -91
  97. data/lib/sinatra/tilt.rb +0 -746
  98. data/test/erubis_test.rb +0 -82
  99. data/test/views/error.erubis +0 -3
  100. data/test/views/hello.erubis +0 -1
  101. data/test/views/layout2.erubis +0 -2
@@ -8,16 +8,16 @@ module Sinatra
8
8
  # on this path by default.
9
9
  set :app_file, caller_files.first || $0
10
10
 
11
- set :run, Proc.new { $0 == app_file }
11
+ set :run, Proc.new { File.expand_path($0) == File.expand_path(app_file) }
12
12
 
13
13
  if run? && ARGV.any?
14
14
  require 'optparse'
15
15
  OptionParser.new { |op|
16
- op.on('-x') { set :lock, true }
17
- op.on('-e env') { |val| set :environment, val.to_sym }
18
- op.on('-s server') { |val| set :server, val }
19
- op.on('-p port') { |val| set :port, val.to_i }
20
- op.on('-o addr') { |val| set :bind, val }
16
+ op.on('-p port', 'set the port (default is 4567)') { |val| set :port, Integer(val) }
17
+ op.on('-o addr', 'set the host (default is 0.0.0.0)') { |val| set :bind, val }
18
+ op.on('-e env', 'set the environment (default is development)') { |val| set :environment, val.to_sym }
19
+ op.on('-s server', 'specify rack server/handler (default is thin)') { |val| set :server, val }
20
+ op.on('-x', 'turn on the mutex lock (default is off)') { set :lock, true }
21
21
  }.parse!(ARGV.dup)
22
22
  end
23
23
  end
@@ -25,4 +25,6 @@ module Sinatra
25
25
  at_exit { Application.run! if $!.nil? && Application.run? }
26
26
  end
27
27
 
28
- include Sinatra::Delegator
28
+ # include would include the module in Object
29
+ # extend only extends the `main` object
30
+ extend Sinatra::Delegator
@@ -1,12 +1,45 @@
1
1
  require 'rack/showexceptions'
2
2
 
3
3
  module Sinatra
4
+ # Sinatra::ShowExceptions catches all exceptions raised from the app it
5
+ # wraps. It shows a useful backtrace with the sourcefile and clickable
6
+ # context, the whole Rack environment and the request data.
7
+ #
8
+ # Be careful when you use this on public-facing sites as it could reveal
9
+ # information helpful to attackers.
4
10
  class ShowExceptions < Rack::ShowExceptions
11
+ @@eats_errors = Object.new
12
+ def @@eats_errors.flush(*) end
13
+ def @@eats_errors.puts(*) end
14
+
5
15
  def initialize(app)
6
16
  @app = app
7
17
  @template = ERB.new(TEMPLATE)
8
18
  end
9
19
 
20
+ def call(env)
21
+ @app.call(env)
22
+ rescue Exception => e
23
+ errors, env["rack.errors"] = env["rack.errors"], @@eats_errors
24
+
25
+ if respond_to?(:prefers_plain_text?) and prefers_plain_text?(env)
26
+ content_type = "text/plain"
27
+ body = [dump_exception(e)]
28
+ else
29
+ content_type = "text/html"
30
+ body = pretty(env, e)
31
+ end
32
+
33
+ env["rack.errors"] = errors
34
+
35
+ [500,
36
+ {"Content-Type" => content_type,
37
+ "Content-Length" => Rack::Utils.bytesize(body.join).to_s},
38
+ body]
39
+ end
40
+
41
+ private
42
+
10
43
  def frame_class(frame)
11
44
  if frame.filename =~ /lib\/sinatra.*\.rb/
12
45
  "framework"
@@ -18,7 +51,7 @@ module Sinatra
18
51
  end
19
52
  end
20
53
 
21
- TEMPLATE = <<HTML
54
+ TEMPLATE = <<-HTML # :nodoc:
22
55
  <!DOCTYPE html>
23
56
  <html>
24
57
  <head>
@@ -141,7 +174,7 @@ TEMPLATE = <<HTML
141
174
  <body>
142
175
  <div id="wrap">
143
176
  <div id="header">
144
- <img src="/__sinatra__/500.png" alt="application error" height="161" width="313" />
177
+ <img src="<%= env['SCRIPT_NAME'] %>/__sinatra__/500.png" alt="application error" height="161" width="313" />
145
178
  <div id="summary">
146
179
  <h1><strong><%=h exception.class %></strong> at <strong><%=h path %>
147
180
  </strong></h1>
@@ -219,7 +252,7 @@ TEMPLATE = <<HTML
219
252
 
220
253
  <div id="get">
221
254
  <h3 id="get-info">GET</h3>
222
- <% unless req.GET.empty? %>
255
+ <% if req.GET and not req.GET.empty? %>
223
256
  <table class="req">
224
257
  <tr>
225
258
  <th>Variable</th>
@@ -240,7 +273,7 @@ TEMPLATE = <<HTML
240
273
 
241
274
  <div id="post">
242
275
  <h3 id="post-info">POST</h3>
243
- <% unless req.POST.empty? %>
276
+ <% if req.POST and not req.POST.empty? %>
244
277
  <table class="req">
245
278
  <tr>
246
279
  <th>Variable</th>
@@ -0,0 +1,3 @@
1
+ module Sinatra
2
+ VERSION = '1.4.0'
3
+ end
@@ -1,94 +1,18 @@
1
- Gem::Specification.new do |s|
2
- s.specification_version = 2 if s.respond_to? :specification_version=
3
- s.required_rubygems_version = Gem::Requirement.new(">= 0") if s.respond_to? :required_rubygems_version=
1
+ $LOAD_PATH.unshift File.expand_path('../lib', __FILE__)
2
+ require 'sinatra/version'
4
3
 
5
- s.name = 'sinatra-base'
6
- s.version = '1.0'
7
- s.date = '2010-03-23'
4
+ Gem::Specification.new 'sinatra-base', Sinatra::VERSION do |s|
5
+ s.description = "Sinatra is a DSL for quickly creating web applications in Ruby with minimal effort."
6
+ s.summary = "Classy web-development dressed in a DSL"
7
+ s.authors = ["Blake Mizerany", "Ryan Tomayko", "Simon Rozet", "Konstantin Haase"]
8
+ s.email = "sinatrarb@googlegroups.com"
9
+ s.homepage = "http://www.sinatrarb.com/"
10
+ s.files = `git ls-files`.split("\n") - %w[.gitignore .travis.yml]
11
+ s.test_files = s.files.select { |p| p =~ /^test\/.*_test.rb/ }
12
+ s.extra_rdoc_files = s.files.select { |p| p =~ /^README/ } << 'LICENSE'
13
+ s.rdoc_options = %w[--line-numbers --inline-source --title Sinatra --main README.rdoc]
8
14
 
9
- s.description = "Classy web-development dressed in a DSL"
10
- s.summary = "Classy web-development dressed in a DSL"
11
-
12
- s.authors = ["Blake Mizerany", "Ryan Tomayko", "Simon Rozet"]
13
- s.email = "sinatrarb@googlegroups.com"
14
-
15
- # = MANIFEST =
16
- s.files = %w[
17
- AUTHORS
18
- CHANGES
19
- LICENSE
20
- README.jp.rdoc
21
- README.rdoc
22
- Rakefile
23
- lib/sinatra.rb
24
- lib/sinatra/base.rb
25
- lib/sinatra/images/404.png
26
- lib/sinatra/images/500.png
27
- lib/sinatra/main.rb
28
- lib/sinatra/showexceptions.rb
29
- lib/sinatra/tilt.rb
30
- sinatra-base.gemspec
31
- test/base_test.rb
32
- test/builder_test.rb
33
- test/contest.rb
34
- test/erb_test.rb
35
- test/erubis_test.rb
36
- test/extensions_test.rb
37
- test/filter_test.rb
38
- test/haml_test.rb
39
- test/helper.rb
40
- test/helpers_test.rb
41
- test/less_test.rb
42
- test/mapped_error_test.rb
43
- test/middleware_test.rb
44
- test/public/favicon.ico
45
- test/request_test.rb
46
- test/response_test.rb
47
- test/result_test.rb
48
- test/route_added_hook_test.rb
49
- test/routing_test.rb
50
- test/sass_test.rb
51
- test/server_test.rb
52
- test/settings_test.rb
53
- test/sinatra_test.rb
54
- test/static_test.rb
55
- test/templates_test.rb
56
- test/views/error.builder
57
- test/views/error.erb
58
- test/views/error.erubis
59
- test/views/error.haml
60
- test/views/error.sass
61
- test/views/foo/hello.test
62
- test/views/hello.builder
63
- test/views/hello.erb
64
- test/views/hello.erubis
65
- test/views/hello.haml
66
- test/views/hello.less
67
- test/views/hello.sass
68
- test/views/hello.test
69
- test/views/layout2.builder
70
- test/views/layout2.erb
71
- test/views/layout2.erubis
72
- test/views/layout2.haml
73
- test/views/layout2.test
74
- ]
75
- # = MANIFEST =
76
-
77
- s.test_files = s.files.select {|path| path =~ /^test\/.*_test.rb/}
78
-
79
- s.extra_rdoc_files = %w[README.rdoc LICENSE]
80
- s.add_dependency 'rack', '>= 1.0'
81
- s.add_development_dependency 'shotgun', '>= 0.6', '< 1.0'
82
- s.add_development_dependency 'rack-test', '>= 0.3.0'
83
- s.add_development_dependency 'haml'
84
- s.add_development_dependency 'builder'
85
- s.add_development_dependency 'erubis'
86
- s.add_development_dependency 'less'
87
-
88
- s.has_rdoc = true
89
- s.homepage = "http://sinatra.rubyforge.org"
90
- s.rdoc_options = ["--line-numbers", "--inline-source", "--title", "Sinatra", "--main", "README.rdoc"]
91
- s.require_paths = %w[lib]
92
- s.rubyforge_project = 'sinatra'
93
- s.rubygems_version = '1.1.1'
15
+ s.add_dependency 'rack', '~> 1.3', '>= 1.3.6'
16
+ s.add_dependency 'rack-protection', '~> 1.2'
17
+ s.add_dependency 'tilt', '~> 1.3', '>= 1.3.3'
94
18
  end
@@ -1,4 +1,4 @@
1
- require File.dirname(__FILE__) + '/helper'
1
+ require File.expand_path('../helper', __FILE__)
2
2
 
3
3
  class BaseTest < Test::Unit::TestCase
4
4
  def test_default
@@ -71,7 +71,7 @@ class BaseTest < Test::Unit::TestCase
71
71
  end
72
72
 
73
73
  it 'exposes the downstream app' do
74
- middleware = TestMiddleware.new(app)
74
+ middleware = TestMiddleware.new!(app)
75
75
  assert_same app, middleware.app
76
76
  end
77
77
 
@@ -1,10 +1,13 @@
1
- require File.dirname(__FILE__) + '/helper'
1
+ require File.expand_path('../helper', __FILE__)
2
+
3
+ begin
2
4
  require 'builder'
3
5
 
4
6
  class BuilderTest < Test::Unit::TestCase
5
- def builder_app(&block)
7
+ def builder_app(options = {}, &block)
6
8
  mock_app {
7
9
  set :views, File.dirname(__FILE__) + '/views'
10
+ set options
8
11
  get '/', &block
9
12
  }
10
13
  get '/'
@@ -16,6 +19,29 @@ class BuilderTest < Test::Unit::TestCase
16
19
  assert_equal %{<?xml version="1.0" encoding="UTF-8"?>\n}, body
17
20
  end
18
21
 
22
+ it 'defaults content type to xml' do
23
+ builder_app { builder 'xml.instruct!' }
24
+ assert ok?
25
+ assert_equal "application/xml;charset=utf-8", response['Content-Type']
26
+ end
27
+
28
+ it 'defaults allows setting content type per route' do
29
+ builder_app do
30
+ content_type :html
31
+ builder 'xml.instruct!'
32
+ end
33
+ assert ok?
34
+ assert_equal "text/html;charset=utf-8", response['Content-Type']
35
+ end
36
+
37
+ it 'defaults allows setting content type globally' do
38
+ builder_app(:builder => { :content_type => 'html' }) do
39
+ builder 'xml.instruct!'
40
+ end
41
+ assert ok?
42
+ assert_equal "text/html;charset=utf-8", response['Content-Type']
43
+ end
44
+
19
45
  it 'renders inline blocks' do
20
46
  builder_app {
21
47
  @name = "Frank & Mary"
@@ -63,3 +89,7 @@ class BuilderTest < Test::Unit::TestCase
63
89
  assert_raise(Errno::ENOENT) { get('/') }
64
90
  end
65
91
  end
92
+
93
+ rescue LoadError
94
+ warn "#{$!.to_s}: skipping builder tests"
95
+ end
@@ -0,0 +1,92 @@
1
+ require File.expand_path('../helper', __FILE__)
2
+
3
+ begin
4
+ require 'coffee-script'
5
+ require 'execjs'
6
+
7
+ begin
8
+ ExecJS.compile '1'
9
+ rescue Exception
10
+ raise LoadError, 'unable to execute JavaScript'
11
+ end
12
+
13
+ class CoffeeTest < Test::Unit::TestCase
14
+ def coffee_app(options = {}, &block)
15
+ mock_app {
16
+ set :views, File.dirname(__FILE__) + '/views'
17
+ set(options)
18
+ get '/', &block
19
+ }
20
+ get '/'
21
+ end
22
+
23
+ it 'renders inline Coffee strings' do
24
+ coffee_app { coffee "alert 'Aye!'\n" }
25
+ assert ok?
26
+ assert body.include?("alert('Aye!');")
27
+ end
28
+
29
+ it 'defaults content type to javascript' do
30
+ coffee_app { coffee "alert 'Aye!'\n" }
31
+ assert ok?
32
+ assert_equal "application/javascript;charset=utf-8", response['Content-Type']
33
+ end
34
+
35
+ it 'defaults allows setting content type per route' do
36
+ coffee_app do
37
+ content_type :html
38
+ coffee "alert 'Aye!'\n"
39
+ end
40
+ assert ok?
41
+ assert_equal "text/html;charset=utf-8", response['Content-Type']
42
+ end
43
+
44
+ it 'defaults allows setting content type globally' do
45
+ coffee_app(:coffee => { :content_type => 'html' }) do
46
+ coffee "alert 'Aye!'\n"
47
+ end
48
+ assert ok?
49
+ assert_equal "text/html;charset=utf-8", response['Content-Type']
50
+ end
51
+
52
+ it 'renders .coffee files in views path' do
53
+ coffee_app { coffee :hello }
54
+ assert ok?
55
+ assert_include body, "alert(\"Aye!\");"
56
+ end
57
+
58
+ it 'ignores the layout option' do
59
+ coffee_app { coffee :hello, :layout => :layout2 }
60
+ assert ok?
61
+ assert_include body, "alert(\"Aye!\");"
62
+ end
63
+
64
+ it "raises error if template not found" do
65
+ mock_app {
66
+ get('/') { coffee :no_such_template }
67
+ }
68
+ assert_raise(Errno::ENOENT) { get('/') }
69
+ end
70
+
71
+ it "passes coffee options to the coffee engine" do
72
+ coffee_app { coffee "alert 'Aye!'\n", :no_wrap => true }
73
+ assert ok?
74
+ assert_body "alert('Aye!');"
75
+ end
76
+
77
+ it "passes default coffee options to the coffee engine" do
78
+ mock_app do
79
+ set :coffee, :no_wrap => true # default coffee style is :nested
80
+ get '/' do
81
+ coffee "alert 'Aye!'\n"
82
+ end
83
+ end
84
+ get '/'
85
+ assert ok?
86
+ assert_body "alert('Aye!');"
87
+ end
88
+ end
89
+
90
+ rescue LoadError
91
+ warn "#{$!.to_s}: skipping coffee tests"
92
+ end
@@ -1,38 +1,67 @@
1
+ # Copyright (c) 2009 Damian Janowski and Michel Martens for Citrusbyte
2
+ #
3
+ # Permission is hereby granted, free of charge, to any person obtaining a copy
4
+ # of this software and associated documentation files (the "Software"), to deal
5
+ # in the Software without restriction, including without limitation the rights
6
+ # to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
7
+ # copies of the Software, and to permit persons to whom the Software is
8
+ # furnished to do so, subject to the following conditions:
9
+ #
10
+ # The above copyright notice and this permission notice shall be included in
11
+ # all copies or substantial portions of the Software.
12
+ #
13
+ # THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
14
+ # IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
15
+ # FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
16
+ # AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
17
+ # LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
18
+ # OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
19
+ # THE SOFTWARE.
1
20
  require "test/unit"
2
21
 
3
- # Test::Unit loads a default test if the suite is empty, and the only
4
- # purpose of that test is to fail. As having empty contexts is a common
5
- # practice, we decided to overwrite TestSuite#empty? in order to
6
- # allow them. Having a failure when no tests have been defined seems
7
- # counter-intuitive.
22
+ # Test::Unit loads a default test if the suite is empty, whose purpose is to
23
+ # fail. Since having empty contexts is a common practice, we decided to
24
+ # overwrite TestSuite#empty? in order to allow them. Having a failure when no
25
+ # tests have been defined seems counter-intuitive.
8
26
  class Test::Unit::TestSuite
9
- unless method_defined?(:empty?)
10
- def empty?
11
- false
12
- end
27
+ def empty?
28
+ false
13
29
  end
14
30
  end
15
31
 
16
- # We added setup, test and context as class methods, and the instance
17
- # method setup now iterates on the setup blocks. Note that all setup
18
- # blocks must be defined with the block syntax. Adding a setup instance
19
- # method defeats the purpose of this library.
32
+ # Contest adds +teardown+, +test+ and +context+ as class methods, and the
33
+ # instance methods +setup+ and +teardown+ now iterate on the corresponding
34
+ # blocks. Note that all setup and teardown blocks must be defined with the
35
+ # block syntax. Adding setup or teardown instance methods defeats the purpose
36
+ # of this library.
20
37
  class Test::Unit::TestCase
21
- def self.setup(&block)
22
- setup_blocks << block
38
+ def self.setup(&block) setup_blocks << block end
39
+ def self.teardown(&block) teardown_blocks << block end
40
+ def self.setup_blocks() @setup_blocks ||= [] end
41
+ def self.teardown_blocks() @teardown_blocks ||= [] end
42
+
43
+ def setup_blocks(base = self.class)
44
+ setup_blocks base.superclass if base.superclass.respond_to? :setup_blocks
45
+ base.setup_blocks.each do |block|
46
+ instance_eval(&block)
47
+ end
23
48
  end
24
49
 
25
- def setup
26
- self.class.setup_blocks.each do |block|
50
+ def teardown_blocks(base = self.class)
51
+ teardown_blocks base.superclass if base.superclass.respond_to? :teardown_blocks
52
+ base.teardown_blocks.each do |block|
27
53
  instance_eval(&block)
28
54
  end
29
55
  end
30
56
 
31
- def self.context(name, &block)
32
- subclass = Class.new(self.superclass)
33
- subclass.setup_blocks.unshift(*setup_blocks)
34
- subclass.class_eval(&block)
35
- const_set(context_name(name), subclass)
57
+ alias setup setup_blocks
58
+ alias teardown teardown_blocks
59
+
60
+ def self.context(*name, &block)
61
+ subclass = Class.new(self)
62
+ remove_tests(subclass)
63
+ subclass.class_eval(&block) if block_given?
64
+ const_set(context_name(name.join(" ")), subclass)
36
65
  end
37
66
 
38
67
  def self.test(name, &block)
@@ -46,12 +75,10 @@ class Test::Unit::TestCase
46
75
 
47
76
  private
48
77
 
49
- def self.setup_blocks
50
- @setup_blocks ||= []
51
- end
52
-
53
78
  def self.context_name(name)
54
- "Test#{sanitize_name(name).gsub(/(^| )(\w)/) { $2.upcase }}".to_sym
79
+ # "Test#{sanitize_name(name).gsub(/(^| )(\w)/) { $2.upcase }}".to_sym
80
+ name = "Test#{sanitize_name(name).gsub(/(^| )(\w)/) { $2.upcase }}"
81
+ name.tr(" ", "_").to_sym
55
82
  end
56
83
 
57
84
  def self.test_name(name)
@@ -59,6 +86,13 @@ private
59
86
  end
60
87
 
61
88
  def self.sanitize_name(name)
62
- name.gsub(/\W+/, ' ').strip
89
+ # name.gsub(/\W+/, ' ').strip
90
+ name.gsub(/\W+/, ' ')
91
+ end
92
+
93
+ def self.remove_tests(subclass)
94
+ subclass.public_instance_methods.grep(/^test_/).each do |meth|
95
+ subclass.send(:undef_method, meth.to_sym)
96
+ end
63
97
  end
64
98
  end