actionpack 1.8.1 → 1.9.0

Sign up to get free protection for your applications and to get access to all the features.

Potentially problematic release.


This version of actionpack might be problematic. Click here for more details.

Files changed (101) hide show
  1. data/CHANGELOG +309 -16
  2. data/README +1 -1
  3. data/lib/action_controller.rb +5 -0
  4. data/lib/action_controller/assertions.rb +57 -12
  5. data/lib/action_controller/auto_complete.rb +47 -0
  6. data/lib/action_controller/base.rb +288 -258
  7. data/lib/action_controller/benchmarking.rb +8 -3
  8. data/lib/action_controller/caching.rb +88 -42
  9. data/lib/action_controller/cgi_ext/cgi_ext.rb +1 -1
  10. data/lib/action_controller/cgi_ext/cgi_methods.rb +41 -11
  11. data/lib/action_controller/cgi_ext/multipart_progress.rb +169 -0
  12. data/lib/action_controller/cgi_ext/raw_post_data_fix.rb +30 -12
  13. data/lib/action_controller/cgi_process.rb +39 -11
  14. data/lib/action_controller/code_generation.rb +235 -0
  15. data/lib/action_controller/cookies.rb +14 -8
  16. data/lib/action_controller/deprecated_renders_and_redirects.rb +76 -0
  17. data/lib/action_controller/filters.rb +8 -7
  18. data/lib/action_controller/helpers.rb +41 -6
  19. data/lib/action_controller/layout.rb +45 -16
  20. data/lib/action_controller/request.rb +86 -23
  21. data/lib/action_controller/rescue.rb +1 -0
  22. data/lib/action_controller/response.rb +1 -1
  23. data/lib/action_controller/routing.rb +536 -272
  24. data/lib/action_controller/scaffolding.rb +30 -25
  25. data/lib/action_controller/session/active_record_store.rb +251 -50
  26. data/lib/action_controller/streaming.rb +133 -0
  27. data/lib/action_controller/templates/rescues/_request_and_response.rhtml +0 -7
  28. data/lib/action_controller/templates/scaffolds/edit.rhtml +2 -2
  29. data/lib/action_controller/templates/scaffolds/layout.rhtml +22 -18
  30. data/lib/action_controller/templates/scaffolds/list.rhtml +3 -3
  31. data/lib/action_controller/templates/scaffolds/new.rhtml +2 -2
  32. data/lib/action_controller/templates/scaffolds/show.rhtml +1 -1
  33. data/lib/action_controller/test_process.rb +68 -47
  34. data/lib/action_controller/upload_progress.rb +421 -0
  35. data/lib/action_controller/url_rewriter.rb +8 -11
  36. data/lib/action_controller/vendor/html-scanner/html/document.rb +6 -5
  37. data/lib/action_controller/vendor/html-scanner/html/node.rb +70 -14
  38. data/lib/action_controller/vendor/html-scanner/html/tokenizer.rb +17 -10
  39. data/lib/action_controller/vendor/html-scanner/html/version.rb +3 -3
  40. data/lib/action_controller/vendor/xml_simple.rb +1019 -0
  41. data/lib/action_controller/verification.rb +36 -30
  42. data/lib/action_view/base.rb +21 -14
  43. data/lib/action_view/helpers/active_record_helper.rb +15 -13
  44. data/lib/action_view/helpers/asset_tag_helper.rb +26 -9
  45. data/lib/action_view/helpers/benchmark_helper.rb +24 -0
  46. data/lib/action_view/helpers/capture_helper.rb +7 -5
  47. data/lib/action_view/helpers/date_helper.rb +63 -46
  48. data/lib/action_view/helpers/form_helper.rb +7 -1
  49. data/lib/action_view/helpers/form_options_helper.rb +19 -11
  50. data/lib/action_view/helpers/form_tag_helper.rb +5 -1
  51. data/lib/action_view/helpers/javascript_helper.rb +403 -35
  52. data/lib/action_view/helpers/javascripts/controls.js +261 -0
  53. data/lib/action_view/helpers/javascripts/dragdrop.js +476 -0
  54. data/lib/action_view/helpers/javascripts/effects.js +570 -0
  55. data/lib/action_view/helpers/javascripts/prototype.js +633 -371
  56. data/lib/action_view/helpers/number_helper.rb +11 -13
  57. data/lib/action_view/helpers/tag_helper.rb +1 -2
  58. data/lib/action_view/helpers/text_helper.rb +69 -6
  59. data/lib/action_view/helpers/upload_progress_helper.rb +433 -0
  60. data/lib/action_view/helpers/url_helper.rb +98 -3
  61. data/lib/action_view/partials.rb +14 -8
  62. data/lib/action_view/vendor/builder/xmlmarkup.rb +11 -0
  63. data/rakefile +13 -5
  64. data/test/abstract_unit.rb +1 -1
  65. data/test/controller/action_pack_assertions_test.rb +52 -9
  66. data/test/controller/active_record_assertions_test.rb +119 -120
  67. data/test/controller/active_record_store_test.rb +111 -0
  68. data/test/controller/addresses_render_test.rb +45 -0
  69. data/test/controller/caching_filestore.rb +92 -0
  70. data/test/controller/capture_test.rb +39 -0
  71. data/test/controller/cgi_test.rb +40 -3
  72. data/test/controller/helper_test.rb +65 -13
  73. data/test/controller/multipart_progress_testx.rb +365 -0
  74. data/test/controller/new_render_test.rb +263 -0
  75. data/test/controller/redirect_test.rb +64 -0
  76. data/test/controller/render_test.rb +20 -21
  77. data/test/controller/request_test.rb +83 -3
  78. data/test/controller/routing_test.rb +702 -0
  79. data/test/controller/send_file_test.rb +2 -0
  80. data/test/controller/test_test.rb +44 -8
  81. data/test/controller/upload_progress_testx.rb +89 -0
  82. data/test/controller/verification_test.rb +94 -29
  83. data/test/fixtures/addresses/list.rhtml +1 -0
  84. data/test/fixtures/test/capturing.rhtml +4 -0
  85. data/test/fixtures/test/list.rhtml +1 -1
  86. data/test/fixtures/test/update_element_with_capture.rhtml +9 -0
  87. data/test/template/active_record_helper_test.rb +30 -15
  88. data/test/template/asset_tag_helper_test.rb +12 -5
  89. data/test/template/benchmark_helper_test.rb +72 -0
  90. data/test/template/date_helper_test.rb +69 -0
  91. data/test/template/form_helper_test.rb +18 -10
  92. data/test/template/form_options_helper_test.rb +40 -5
  93. data/test/template/javascript_helper.rb +149 -2
  94. data/test/template/number_helper_test.rb +2 -0
  95. data/test/template/tag_helper_test.rb +4 -0
  96. data/test/template/text_helper_test.rb +36 -0
  97. data/test/template/upload_progress_helper_testx.rb +272 -0
  98. data/test/template/url_helper_test.rb +30 -0
  99. metadata +30 -6
  100. data/test/controller/layout_test.rb +0 -49
  101. data/test/controller/routing_tests.rb +0 -543
@@ -0,0 +1,111 @@
1
+ # Unfurl the safety net.
2
+ path_to_ar = File.dirname(__FILE__) + '/../../../activerecord'
3
+ if Object.const_defined?(:ActiveRecord) or File.exist?(path_to_ar)
4
+ begin
5
+
6
+ # These tests exercise CGI::Session::ActiveRecordStore, so you're going to
7
+ # need AR in a sibling directory to AP and have SQLite installed.
8
+
9
+ unless Object.const_defined?(:ActiveRecord)
10
+ require File.join(path_to_ar, 'lib', 'active_record')
11
+ end
12
+
13
+ require File.dirname(__FILE__) + '/../abstract_unit'
14
+ require 'action_controller/session/active_record_store'
15
+
16
+ #ActiveRecord::Base.logger = Logger.new($stdout)
17
+ begin
18
+ CGI::Session::ActiveRecordStore::Session.establish_connection(:adapter => 'sqlite3', :dbfile => ':memory:')
19
+ CGI::Session::ActiveRecordStore::Session.connection
20
+ rescue Object
21
+ $stderr.puts 'SQLite 3 unavailable; falling to SQLite 2.'
22
+ CGI::Session::ActiveRecordStore::Session.establish_connection(:adapter => 'sqlite', :dbfile => ':memory:')
23
+ end
24
+
25
+
26
+ module CommonActiveRecordStoreTests
27
+ def test_basics
28
+ s = session_class.new(:session_id => '1234', :data => { 'foo' => 'bar' })
29
+ assert_equal 'bar', s.data['foo']
30
+ assert s.save!
31
+ assert_equal 'bar', s.data['foo']
32
+
33
+ assert_not_nil t = session_class.find_by_session_id('1234')
34
+ assert_not_nil t.data
35
+ assert_equal 'bar', t.data['foo']
36
+ end
37
+
38
+ def test_reload_same_session
39
+ @new_session.update
40
+ reloaded = CGI::Session.new(CGI.new, 'session_id' => @new_session.session_id, 'database_manager' => CGI::Session::ActiveRecordStore)
41
+ assert_equal 'bar', reloaded['foo']
42
+ end
43
+
44
+ def test_tolerates_close_close
45
+ assert_nothing_raised do
46
+ @new_session.close
47
+ @new_session.close
48
+ end
49
+ end
50
+ end
51
+
52
+ class ActiveRecordStoreTest < Test::Unit::TestCase
53
+ include CommonActiveRecordStoreTests
54
+
55
+ def session_class
56
+ CGI::Session::ActiveRecordStore::Session
57
+ end
58
+
59
+ def setup
60
+ session_class.create_table!
61
+
62
+ ENV['REQUEST_METHOD'] = 'GET'
63
+ CGI::Session::ActiveRecordStore.session_class = session_class
64
+
65
+ @new_session = CGI::Session.new(CGI.new, 'database_manager' => CGI::Session::ActiveRecordStore, 'new_session' => true)
66
+ @new_session['foo'] = 'bar'
67
+ end
68
+
69
+ def teardown
70
+ session_class.drop_table!
71
+ end
72
+ end
73
+
74
+
75
+ class DeprecatedActiveRecordStoreTest < ActiveRecordStoreTest
76
+ def setup
77
+ session_class.connection.execute 'create table old_sessions (id integer primary key, sessid text unique, data text)'
78
+ session_class.table_name = 'old_sessions'
79
+ session_class.send :setup_sessid_compatibility!
80
+
81
+ ENV['REQUEST_METHOD'] = 'GET'
82
+ CGI::Session::ActiveRecordStore.session_class = session_class
83
+
84
+ @new_session = CGI::Session.new(CGI.new, 'database_manager' => CGI::Session::ActiveRecordStore, 'new_session' => true)
85
+ @new_session['foo'] = 'bar'
86
+ end
87
+
88
+ def teardown
89
+ session_class.connection.execute 'drop table old_sessions'
90
+ session_class.table_name = 'sessions'
91
+ session_class.send :setup_sessid_compatibility!
92
+ end
93
+ end
94
+
95
+ class SqlBypassActiveRecordStoreTest < ActiveRecordStoreTest
96
+ def session_class
97
+ unless @session_class
98
+ @session_class = CGI::Session::ActiveRecordStore::SqlBypass
99
+ @session_class.connection = CGI::Session::ActiveRecordStore::Session.connection
100
+ end
101
+ @session_class
102
+ end
103
+ end
104
+
105
+
106
+ # End of safety net.
107
+ rescue Object => e
108
+ $stderr.puts "Skipping CGI::Session::ActiveRecordStore tests: #{e}"
109
+ #$stderr.puts " #{e.backtrace.join("\n ")}"
110
+ end
111
+ end
@@ -0,0 +1,45 @@
1
+ require File.dirname(__FILE__) + '/../abstract_unit'
2
+
3
+ class Address
4
+
5
+ def Address.count(conditions = nil, join = nil)
6
+ nil
7
+ end
8
+
9
+ def Address.find_all(arg1, arg2, arg3, arg4)
10
+ []
11
+ end
12
+ end
13
+
14
+ class AddressesTestController < ActionController::Base
15
+
16
+ scaffold :address
17
+
18
+ def self.controller_name; "addresses"; end
19
+ def self.controller_path; "addresses"; end
20
+
21
+ end
22
+
23
+ AddressesTestController.template_root = File.dirname(__FILE__) + "/../fixtures/"
24
+
25
+ class AddressesTest < Test::Unit::TestCase
26
+ def setup
27
+ @controller = AddressesTestController.new
28
+
29
+ # enable a logger so that (e.g.) the benchmarking stuff runs, so we can get
30
+ # a more accurate simulation of what happens in "real life".
31
+ @controller.logger = Logger.new(nil)
32
+
33
+ @request = ActionController::TestRequest.new
34
+ @response = ActionController::TestResponse.new
35
+
36
+ @request.host = "www.nextangle.com"
37
+ end
38
+
39
+ def test_list
40
+ get :list
41
+ assert_equal "We only need to get this far!", @response.body.chomp
42
+ end
43
+
44
+
45
+ end
@@ -0,0 +1,92 @@
1
+ require 'fileutils'
2
+ require File.dirname(__FILE__) + '/../abstract_unit'
3
+
4
+ #generate the greatest logging class that ever lived
5
+ class TestLogDevice < Logger::LogDevice
6
+ attr :last_message, true
7
+
8
+ def initialize
9
+ @last_message=String.new
10
+ end
11
+
12
+ def write(message)
13
+ @last_message << message
14
+ end
15
+
16
+ def clear
17
+ @last_message = String.new
18
+ end
19
+ end
20
+
21
+ #setup our really sophisticated logger
22
+ TestLog = TestLogDevice.new
23
+ RAILS_DEFAULT_LOGGER = Logger.new(TestLog)
24
+ ActionController::Base.logger = RAILS_DEFAULT_LOGGER
25
+
26
+ #generate a random key to ensure the cache is always in a different location
27
+ RANDOM_KEY = rand(99999999).to_s
28
+ FILE_STORE_PATH = File.dirname(__FILE__) + '/../temp/' + RANDOM_KEY
29
+ ActionController::Base.perform_caching = true
30
+ ActionController::Base.fragment_cache_store = ActionController::Caching::Fragments::FileStore.new(FILE_STORE_PATH)
31
+
32
+ #setup the routing information...not sure if this does anything
33
+ ActionController::Routing::Routes.connect "test", :controller => 'test', :action => 'render_to_cache'
34
+
35
+ class TestController < ActionController::Base
36
+ caches_action :render_to_cache, :index
37
+
38
+ def render_to_cache
39
+ render_text "Render Cached"
40
+ end
41
+ alias :index :render_to_cache
42
+ end
43
+
44
+ class FileStoreTest < Test::Unit::TestCase
45
+ def setup
46
+ @request = ActionController::TestRequest.new
47
+ @response = ActionController::TestResponse.new
48
+ @request.host = "hostname.com"
49
+ end
50
+
51
+ #To prime the cache with hostname.com/test
52
+ def test_render_to_cache_prime_a
53
+ @request.path_parameters = {:controller => "test"}
54
+ assert_fragment_cached do process_request end
55
+ end
56
+
57
+ #To prime the cache with hostname.com/test/render_to_cache
58
+ def test_render_to_cache_prime_b
59
+ @request.path_parameters = {:action => "render_to_cache", :controller => "test"}
60
+ assert_fragment_cached do process_request end
61
+ end
62
+
63
+ #To hit the cache with hostname.com/test
64
+ def test_render_to_cache_zhit_a
65
+ @request.path_parameters = {:controller => "test"}
66
+ assert_fragment_hit do process_request end
67
+ end
68
+
69
+ #To hit the cache with hostname.com/test/render_to_cache
70
+ def test_render_to_cache_zhit_b
71
+ @request.path_parameters = {:action => "render_to_cache", :controller => "test"}
72
+ assert_fragment_hit do process_request end
73
+ end
74
+
75
+ private
76
+ def process_request
77
+ TestController.process(@request, @response)
78
+ end
79
+
80
+ def assert_fragment_cached(&proc)
81
+ proc.call
82
+ assert(TestLog.last_message.include?("Cached fragment:"), "--ERROR-- FileStore write failed ----")
83
+ assert(!TestLog.last_message.include?("Couldn't create cache directory:"), "--ERROR-- FileStore create directory failed ----")
84
+ TestLog.clear
85
+ end
86
+
87
+ def assert_fragment_hit(&proc)
88
+ proc.call
89
+ assert(TestLog.last_message.include?( "Fragment hit:"), "--ERROR-- Fragment not found in FileStore ----")
90
+ TestLog.clear
91
+ end
92
+ end
@@ -0,0 +1,39 @@
1
+ require File.dirname(__FILE__) + '/../abstract_unit'
2
+
3
+ class CaptureController < ActionController::Base
4
+ def self.controller_name; "test"; end
5
+ def self.controller_path; "test"; end
6
+
7
+ def rescue_action(e) raise end
8
+ end
9
+
10
+ CaptureController.template_root = File.dirname(__FILE__) + "/../fixtures/"
11
+
12
+ class CaptureTest < Test::Unit::TestCase
13
+ def setup
14
+ @controller = CaptureController.new
15
+
16
+ # enable a logger so that (e.g.) the benchmarking stuff runs, so we can get
17
+ # a more accurate simulation of what happens in "real life".
18
+ @controller.logger = Logger.new(nil)
19
+
20
+ @request = ActionController::TestRequest.new
21
+ @response = ActionController::TestResponse.new
22
+
23
+ @request.host = "www.nextangle.com"
24
+ end
25
+
26
+ def test_simple_capture
27
+ get :capturing
28
+ assert_equal "Dreamy days", @response.body.strip
29
+ end
30
+
31
+ def test_update_element_with_capture
32
+ get :update_element_with_capture
33
+ assert_equal(
34
+ "<script type=\"text/javascript\">$('products').innerHTML = '\\n <p>Product 1</p>\\n <p>Product 2</p>\\n';\n</script>" +
35
+ "\n\n$('status').innerHTML = '\\n <b>You bought something!</b>\\n';",
36
+ @response.body.strip
37
+ )
38
+ end
39
+ end
@@ -1,3 +1,4 @@
1
+ $:.unshift File.dirname(__FILE__) + "/../../lib"
1
2
 
2
3
  require 'test/unit'
3
4
  require 'action_controller/cgi_ext/cgi_methods'
@@ -21,6 +22,8 @@ class CGITest < Test::Unit::TestCase
21
22
  @query_string_with_amps = "action=create_customer&name=Don%27t+%26+Does"
22
23
  @query_string_with_multiple_of_same_name =
23
24
  "action=update_order&full_name=Lau%20Taarnskov&products=4&products=2&products=3"
25
+ @query_string_with_many_equal = "action=create_customer&full_name=abc=def=ghi"
26
+ @query_string_without_equal = "action"
24
27
  end
25
28
 
26
29
  def test_query_string
@@ -29,7 +32,16 @@ class CGITest < Test::Unit::TestCase
29
32
  CGIMethods.parse_query_parameters(@query_string)
30
33
  )
31
34
  end
32
-
35
+
36
+ def test_deep_query_string
37
+ assert_equal({'x' => {'y' => {'z' => '10'}}}, CGIMethods.parse_query_parameters('x[y][z]=10'))
38
+ end
39
+
40
+ def test_deep_query_string_with_array
41
+ assert_equal({'x' => {'y' => {'z' => ['10']}}}, CGIMethods.parse_query_parameters('x[y][z][]=10'))
42
+ assert_equal({'x' => {'y' => {'z' => ['10', '5']}}}, CGIMethods.parse_query_parameters('x[y][z][]=10&x[y][z][]=5'))
43
+ end
44
+
33
45
  def test_query_string_with_nil
34
46
  assert_equal(
35
47
  { "action" => "create_customer", "full_name" => nil},
@@ -38,10 +50,10 @@ class CGITest < Test::Unit::TestCase
38
50
  end
39
51
 
40
52
  def test_query_string_with_array
41
- assert_equal(
53
+ assert_equal(
42
54
  { "action" => "create_customer", "selected" => ["1", "2", "3"]},
43
55
  CGIMethods.parse_query_parameters(@query_string_with_array)
44
- )
56
+ )
45
57
  end
46
58
 
47
59
  def test_query_string_with_amps
@@ -51,6 +63,20 @@ class CGITest < Test::Unit::TestCase
51
63
  )
52
64
  end
53
65
 
66
+ def test_query_string_with_many_equal
67
+ assert_equal(
68
+ { "action" => "create_customer", "full_name" => "abc=def=ghi"},
69
+ CGIMethods.parse_query_parameters(@query_string_with_many_equal)
70
+ )
71
+ end
72
+
73
+ def test_query_string_without_equal
74
+ assert_equal(
75
+ { "action" => nil },
76
+ CGIMethods.parse_query_parameters(@query_string_without_equal)
77
+ )
78
+ end
79
+
54
80
  def test_parse_params
55
81
  input = {
56
82
  "customers[boston][first][name]" => [ "David" ],
@@ -94,12 +120,22 @@ class CGITest < Test::Unit::TestCase
94
120
 
95
121
  input = {
96
122
  "something" => [ StringIO.new("") ],
123
+ "array_of_stringios" => [[ StringIO.new("One"), StringIO.new("Two") ]],
124
+ "mixed_types_array" => [[ StringIO.new("Three"), "NotStringIO" ]],
125
+ "mixed_types_as_checkboxes[strings][nested]" => [[ mock_file, "String", StringIO.new("StringIO")]],
97
126
  "products[string]" => [ StringIO.new("Apple Computer") ],
98
127
  "products[file]" => [ mock_file ]
99
128
  }
100
129
 
101
130
  expected_output = {
102
131
  "something" => "",
132
+ "array_of_stringios" => ["One", "Two"],
133
+ "mixed_types_array" => [ "Three", "NotStringIO" ],
134
+ "mixed_types_as_checkboxes" => {
135
+ "strings"=> {
136
+ "nested"=>[ mock_file, "String", "StringIO" ]
137
+ },
138
+ },
103
139
  "products" => {
104
140
  "string" => "Apple Computer",
105
141
  "file" => mock_file
@@ -169,3 +205,4 @@ class CGITest < Test::Unit::TestCase
169
205
  assert_equal expected, CGIMethods.parse_request_parameters(input)
170
206
  end
171
207
  end
208
+
@@ -9,7 +9,7 @@ end
9
9
  module Fun
10
10
  class GamesController < ActionController::Base
11
11
  def render_hello_world
12
- render_template "hello: <%= stratego %>"
12
+ render :inline => "hello: <%= stratego %>"
13
13
  end
14
14
 
15
15
  def rescue_action(e) raise end
@@ -23,7 +23,6 @@ module LocalAbcHelper
23
23
  end
24
24
 
25
25
  class HelperTest < Test::Unit::TestCase
26
-
27
26
  def setup
28
27
  # Increment symbol counter.
29
28
  @symbol = (@@counter ||= 'A0').succ!.dup
@@ -50,7 +49,7 @@ class HelperTest < Test::Unit::TestCase
50
49
 
51
50
 
52
51
  def test_deprecated_helper
53
- assert_equal helper_methods, missing_methods
52
+ assert_equal expected_helper_methods, missing_methods
54
53
  assert_nothing_raised { @controller_class.helper TestHelper }
55
54
  assert_equal [], missing_methods
56
55
  end
@@ -58,13 +57,13 @@ class HelperTest < Test::Unit::TestCase
58
57
  def test_declare_helper
59
58
  require 'abc_helper'
60
59
  self.test_helper = AbcHelper
61
- assert_equal helper_methods, missing_methods
60
+ assert_equal expected_helper_methods, missing_methods
62
61
  assert_nothing_raised { @controller_class.helper :abc }
63
62
  assert_equal [], missing_methods
64
63
  end
65
64
 
66
65
  def test_declare_missing_helper
67
- assert_equal helper_methods, missing_methods
66
+ assert_equal expected_helper_methods, missing_methods
68
67
  assert_raise(MissingSourceFile) { @controller_class.helper :missing }
69
68
  end
70
69
 
@@ -78,11 +77,11 @@ class HelperTest < Test::Unit::TestCase
78
77
  assert_nothing_raised {
79
78
  @controller_class.helper { def block_helper_method; end }
80
79
  }
81
- assert template_methods.include?('block_helper_method')
80
+ assert master_helper_methods.include?('block_helper_method')
82
81
  end
83
82
 
84
83
  def test_helper_block_include
85
- assert_equal helper_methods, missing_methods
84
+ assert_equal expected_helper_methods, missing_methods
86
85
  assert_nothing_raised {
87
86
  @controller_class.helper { include TestHelper }
88
87
  }
@@ -91,13 +90,13 @@ class HelperTest < Test::Unit::TestCase
91
90
 
92
91
  def test_helper_method
93
92
  assert_nothing_raised { @controller_class.helper_method :delegate_method }
94
- assert template_methods.include?('delegate_method')
93
+ assert master_helper_methods.include?('delegate_method')
95
94
  end
96
95
 
97
96
  def test_helper_attr
98
97
  assert_nothing_raised { @controller_class.helper_attr :delegate_attr }
99
- assert template_methods.include?('delegate_attr')
100
- assert template_methods.include?('delegate_attr=')
98
+ assert master_helper_methods.include?('delegate_attr')
99
+ assert master_helper_methods.include?('delegate_attr=')
101
100
  end
102
101
 
103
102
  def test_helper_for_nested_controller
@@ -109,9 +108,17 @@ class HelperTest < Test::Unit::TestCase
109
108
  end
110
109
 
111
110
  private
112
- def helper_methods; TestHelper.instance_methods end
113
- def template_methods; @template_class.instance_methods end
114
- def missing_methods; helper_methods - template_methods end
111
+ def expected_helper_methods
112
+ TestHelper.instance_methods
113
+ end
114
+
115
+ def master_helper_methods
116
+ @controller_class.master_helper_module.instance_methods
117
+ end
118
+
119
+ def missing_methods
120
+ expected_helper_methods - master_helper_methods
121
+ end
115
122
 
116
123
  def test_helper=(helper_module)
117
124
  old_verbose, $VERBOSE = $VERBOSE, nil
@@ -119,3 +126,48 @@ class HelperTest < Test::Unit::TestCase
119
126
  $VERBOSE = old_verbose
120
127
  end
121
128
  end
129
+
130
+
131
+ class IsolatedHelpersTest < Test::Unit::TestCase
132
+ class A < ActionController::Base
133
+ def index
134
+ render :inline => '<%= shout %>'
135
+ end
136
+
137
+ def rescue_action(e) raise end
138
+ end
139
+
140
+ class B < A
141
+ helper { def shout; 'B' end }
142
+
143
+ def index
144
+ render :inline => '<%= shout %>'
145
+ end
146
+ end
147
+
148
+ class C < A
149
+ helper { def shout; 'C' end }
150
+
151
+ def index
152
+ render :inline => '<%= shout %>'
153
+ end
154
+ end
155
+
156
+ def setup
157
+ @request = ActionController::TestRequest.new
158
+ @response = ActionController::TestResponse.new
159
+ @request.action = 'index'
160
+ end
161
+
162
+ def test_helper_in_a
163
+ assert_raise(NameError) { A.process(@request, @response) }
164
+ end
165
+
166
+ def test_helper_in_b
167
+ assert_equal 'B', B.process(@request, @response).body
168
+ end
169
+
170
+ def test_helper_in_c
171
+ assert_equal 'C', C.process(@request, @response).body
172
+ end
173
+ end