template_streaming 0.0.11 → 0.1.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- data/CHANGELOG +9 -0
- data/README.markdown +177 -88
- data/Rakefile +0 -21
- data/lib/template_streaming.rb +184 -99
- data/lib/template_streaming/autoflushing.rb +88 -0
- data/lib/template_streaming/caching.rb +68 -0
- data/lib/template_streaming/error_recovery.rb +199 -85
- data/lib/template_streaming/new_relic.rb +555 -0
- data/lib/template_streaming/templates/errors.erb +37 -0
- data/lib/template_streaming/version.rb +1 -1
- data/rails/init.rb +3 -0
- data/spec/autoflushing_spec.rb +75 -0
- data/spec/caching_spec.rb +126 -0
- data/spec/error_recovery_spec.rb +261 -0
- data/spec/spec_helper.rb +13 -0
- data/spec/support/streaming_app.rb +135 -0
- data/spec/template_streaming_spec.rb +926 -0
- metadata +55 -27
@@ -0,0 +1,37 @@
|
|
1
|
+
<style>
|
2
|
+
#uncaught_exceptions {
|
3
|
+
position: absolute;
|
4
|
+
top: 0px;
|
5
|
+
left: 0px;
|
6
|
+
margin: 8px;
|
7
|
+
background-color: #fff; color: #333;
|
8
|
+
}
|
9
|
+
|
10
|
+
#uncaught_exceptions,
|
11
|
+
#uncaught_exceptions p,
|
12
|
+
#uncaught_exceptions ol,
|
13
|
+
#uncaught_exceptions ul,
|
14
|
+
#uncaught_exceptions td {
|
15
|
+
font-family: verdana, arial, helvetica, sans-serif;
|
16
|
+
font-size: 13px;
|
17
|
+
line-height: 18px;
|
18
|
+
}
|
19
|
+
|
20
|
+
#uncaught_exceptions h1 {
|
21
|
+
margin-top: 0px;
|
22
|
+
}
|
23
|
+
|
24
|
+
#uncaught_exceptions pre {
|
25
|
+
background-color: #eee;
|
26
|
+
padding: 10px;
|
27
|
+
font-size: 11px;
|
28
|
+
}
|
29
|
+
|
30
|
+
#uncaught_exceptions a { color: #000; }
|
31
|
+
#uncaught_exceptions a:visited { color: #666; }
|
32
|
+
#uncaught_exceptions a:hover { color: #fff; background-color:#000; }
|
33
|
+
</style>
|
34
|
+
|
35
|
+
<div id="uncaught_exceptions">
|
36
|
+
<%= @content %>
|
37
|
+
</div>
|
data/rails/init.rb
ADDED
@@ -0,0 +1,75 @@
|
|
1
|
+
require 'spec/spec_helper'
|
2
|
+
|
3
|
+
describe TemplateStreaming::Autoflushing do
|
4
|
+
include StreamingApp
|
5
|
+
|
6
|
+
describe "when streaming" do
|
7
|
+
describe "when autoflushing is on" do
|
8
|
+
use_attribute_value TemplateStreaming, :autoflush, 0
|
9
|
+
|
10
|
+
it "should automatically flush" do
|
11
|
+
layout "[<%= yield %>]"
|
12
|
+
view "(<%= render :partial => 'partial' %>)"
|
13
|
+
partial 'partial'
|
14
|
+
action { render :stream => true, :layout => 'layout' }
|
15
|
+
run
|
16
|
+
received.should == chunks('[', '(', 'partial', ')', ']', :end => true)
|
17
|
+
end
|
18
|
+
|
19
|
+
it "should autoflush correctly for partials with layouts where the partial is given as an option" do
|
20
|
+
layout "[<%= yield %>]"
|
21
|
+
view "(<%= render :partial => 'partial' %>)"
|
22
|
+
partial "{<%= render :layout => 'subpartial_layout', :partial => 'subpartial' %>}"
|
23
|
+
template 'test/_subpartial_layout', '<<%= yield %>>'
|
24
|
+
template 'test/_subpartial', 'subpartial'
|
25
|
+
action { render :stream => true, :layout => 'layout' }
|
26
|
+
run
|
27
|
+
received.should == chunks('[', '(', '{', '<', 'subpartial', '>', '}', ')', ']', :end => true)
|
28
|
+
end
|
29
|
+
|
30
|
+
it "should autoflush correctly for partials with layouts where the partial is given as a block" do
|
31
|
+
layout "[<%= yield %>]"
|
32
|
+
view "(<%= render :partial => 'partial' %>)"
|
33
|
+
partial "{<% render :layout => 'subpartial_layout' do %>`<%= render :partial => 'subpartial' %>'<% end %>}"
|
34
|
+
template 'test/_subpartial_layout', '<<%= yield %>>'
|
35
|
+
template 'test/_subpartial', 'subpartial'
|
36
|
+
action { render :stream => true, :layout => 'layout' }
|
37
|
+
run
|
38
|
+
received.should == chunks('[', '(', '{', '<', '`', 'subpartial', '\'', '>', '}', ')', ']', :end => true)
|
39
|
+
end
|
40
|
+
|
41
|
+
it "should autoflush correctly for views with multiple partials" do
|
42
|
+
layout "[<%= yield %>][<%= yield %>]"
|
43
|
+
view "(<%= render :partial => 'partial' %>)(<%= render :partial => 'partial' %>)"
|
44
|
+
partial 'partial'
|
45
|
+
action { render :stream => true, :layout => 'layout' }
|
46
|
+
run
|
47
|
+
received.should == chunks('[', '(', 'partial', ')(', 'partial', ')', '][', '(', 'partial', ')(', 'partial', ')', ']', :end => true)
|
48
|
+
end
|
49
|
+
|
50
|
+
it "should flush correctly when some of the automatic flushes are throttled" do
|
51
|
+
with_attribute_value TemplateStreaming, :autoflush, 0.2 do
|
52
|
+
data.t = Time.now
|
53
|
+
Time.stub(:now).and_return(data.t)
|
54
|
+
view <<-EOS.gsub(/^ *\|/, '')
|
55
|
+
|<%= 1 -%>
|
56
|
+
|<%= Time.stub(:now).and_return(data.t + 0.1); render :partial => 'a' -%>
|
57
|
+
|<%= 2 -%>
|
58
|
+
|<%= Time.stub(:now).and_return(data.t + 0.2); render :partial => 'b' -%>
|
59
|
+
|<%= 3 -%>
|
60
|
+
|<%= Time.stub(:now).and_return(data.t + 0.3); render :partial => 'c' -%>
|
61
|
+
|<%= 4 -%>
|
62
|
+
EOS
|
63
|
+
action { render :stream => true, :layout => nil }
|
64
|
+
template 'test/_a', 'a'
|
65
|
+
template 'test/_b', 'b'
|
66
|
+
template 'test/_c', 'c'
|
67
|
+
template 'test/_d', 'd'
|
68
|
+
action { render :stream => true, :layout => nil }
|
69
|
+
run
|
70
|
+
received.should == chunks('1', 'a2b3', 'c4', :end => true)
|
71
|
+
end
|
72
|
+
end
|
73
|
+
end
|
74
|
+
end
|
75
|
+
end
|
@@ -0,0 +1,126 @@
|
|
1
|
+
require 'spec/spec_helper'
|
2
|
+
|
3
|
+
describe TemplateStreaming::Caching do
|
4
|
+
include StreamingApp
|
5
|
+
|
6
|
+
describe "page caching" do
|
7
|
+
use_attribute_value ActionController::Base, :page_cache_directory, "#{TMP}/page_cache"
|
8
|
+
use_attribute_value ActionController::Base, :perform_caching, true
|
9
|
+
|
10
|
+
before do
|
11
|
+
controller.caches_page :action
|
12
|
+
action { render :stream => true }
|
13
|
+
view "a<% flush %>b"
|
14
|
+
end
|
15
|
+
|
16
|
+
it "should render and cache the page correctly" do
|
17
|
+
run
|
18
|
+
received.should == chunks('a', 'b', :end => true)
|
19
|
+
File.read("#{controller.page_cache_directory}/index.html").should == 'ab'
|
20
|
+
end
|
21
|
+
end
|
22
|
+
|
23
|
+
describe "action caching" do
|
24
|
+
before do
|
25
|
+
push_attribute_value ActionController::Base, :cache_store, ActiveSupport::Cache::MemoryStore.new
|
26
|
+
end
|
27
|
+
|
28
|
+
after do
|
29
|
+
pop_attribute_value ActionController::Base, :cache_store
|
30
|
+
end
|
31
|
+
|
32
|
+
describe "when streaming" do
|
33
|
+
describe "when no layout is used" do
|
34
|
+
before do
|
35
|
+
controller.caches_action :action
|
36
|
+
end
|
37
|
+
|
38
|
+
it "should render the page correctly" do
|
39
|
+
view "a<% flush %>b"
|
40
|
+
action { render :stream => true, :layout => nil }
|
41
|
+
run
|
42
|
+
received.should == chunks('a', 'b', :end => true)
|
43
|
+
end
|
44
|
+
|
45
|
+
it "should use the cached copy if it exists" do
|
46
|
+
view "<% data.render_count += 1 %>a<% flush %>b"
|
47
|
+
action { render :stream => true, :layout => nil }
|
48
|
+
data.render_count = 0
|
49
|
+
run
|
50
|
+
run
|
51
|
+
received.should == 'ab'
|
52
|
+
data.render_count.should == 1
|
53
|
+
end
|
54
|
+
end
|
55
|
+
end
|
56
|
+
|
57
|
+
describe "when not streaming" do
|
58
|
+
describe "when no layout is used" do
|
59
|
+
before do
|
60
|
+
controller.caches_action :action
|
61
|
+
action { render :stream => false, :layout => nil }
|
62
|
+
end
|
63
|
+
|
64
|
+
it "should render the page correctly" do
|
65
|
+
view "a<% flush %>b"
|
66
|
+
run
|
67
|
+
received.should == 'ab'
|
68
|
+
end
|
69
|
+
|
70
|
+
it "should use the cached copy if it exists" do
|
71
|
+
view "<% data.render_count += 1 %>a<% flush %>b"
|
72
|
+
data.render_count = 0
|
73
|
+
run
|
74
|
+
run
|
75
|
+
received.should == 'ab'
|
76
|
+
data.render_count.should == 1
|
77
|
+
end
|
78
|
+
end
|
79
|
+
|
80
|
+
describe "when the layout is cached" do
|
81
|
+
before do
|
82
|
+
controller.caches_action :action, :layout => true
|
83
|
+
action { render :stream => false, :layout => 'layout' }
|
84
|
+
end
|
85
|
+
|
86
|
+
it "should cache the layout" do
|
87
|
+
layout "<% data.render_count += 1 %>[<%= yield %>]"
|
88
|
+
view "view"
|
89
|
+
data.render_count = 0
|
90
|
+
|
91
|
+
run
|
92
|
+
received.should == '[view]'
|
93
|
+
data.render_count.should == 1
|
94
|
+
|
95
|
+
run
|
96
|
+
received.should == '[view]'
|
97
|
+
data.render_count.should == 1
|
98
|
+
end
|
99
|
+
end
|
100
|
+
|
101
|
+
describe "when the layout is not cached" do
|
102
|
+
before do
|
103
|
+
controller.caches_action :action, :layout => false
|
104
|
+
# AC always does render(:layout => true) to render the layout when the
|
105
|
+
# body is cached, even if an explicit layout name is given. Hence, our
|
106
|
+
# layout name must match the controller name.
|
107
|
+
action { render :stream => false, :layout => 'test' }
|
108
|
+
end
|
109
|
+
|
110
|
+
it "should not cache the layout" do
|
111
|
+
template 'layouts/test', "<% data.render_count += 1 %>[<%= yield %>]"
|
112
|
+
view "view"
|
113
|
+
data.render_count = 0
|
114
|
+
|
115
|
+
run
|
116
|
+
received.should == '[view]'
|
117
|
+
data.render_count.should == 1
|
118
|
+
|
119
|
+
run
|
120
|
+
received.should == '[view]'
|
121
|
+
data.render_count.should == 2
|
122
|
+
end
|
123
|
+
end
|
124
|
+
end
|
125
|
+
end
|
126
|
+
end
|
@@ -0,0 +1,261 @@
|
|
1
|
+
require 'spec/spec_helper'
|
2
|
+
|
3
|
+
describe TemplateStreaming::ErrorRecovery do
|
4
|
+
include StreamingApp
|
5
|
+
|
6
|
+
describe "when there is an error during rendering" do
|
7
|
+
before do
|
8
|
+
class TestController
|
9
|
+
def rescue_action(exception)
|
10
|
+
# Run the default handler.
|
11
|
+
ActionController::Base.instance_method(:rescue_action).bind(self).call(exception)
|
12
|
+
end
|
13
|
+
end
|
14
|
+
end
|
15
|
+
|
16
|
+
describe "when not streaming" do
|
17
|
+
it "should show the standard error page" do
|
18
|
+
view "<% raise 'test exception' %>"
|
19
|
+
run
|
20
|
+
received.should include("Action Controller: Exception caught")
|
21
|
+
received.should include('test exception')
|
22
|
+
end
|
23
|
+
end
|
24
|
+
|
25
|
+
describe "when streaming" do
|
26
|
+
before do
|
27
|
+
controller.render_streaming_errors_with do |view, exceptions|
|
28
|
+
messages = exceptions.map { |e| e.original_exception.message }
|
29
|
+
"(#{messages.join(',')})"
|
30
|
+
end
|
31
|
+
end
|
32
|
+
|
33
|
+
describe "for local requests" do
|
34
|
+
before do
|
35
|
+
controller.class_eval do
|
36
|
+
def local_request?
|
37
|
+
true
|
38
|
+
end
|
39
|
+
end
|
40
|
+
end
|
41
|
+
|
42
|
+
it "should run the error callback for each error raised" do
|
43
|
+
messages = []
|
44
|
+
controller.on_streaming_error do |error|
|
45
|
+
messages << error.original_exception.message
|
46
|
+
end
|
47
|
+
view "<% render :partial => 'a' %><% render :partial => 'b' %>"
|
48
|
+
template 'test/_a', "<% raise 'a' %>"
|
49
|
+
template 'test/_b', "<% raise 'b' %>"
|
50
|
+
action { render :stream => true, :layout => nil }
|
51
|
+
run
|
52
|
+
messages.should == ['a', 'b']
|
53
|
+
end
|
54
|
+
|
55
|
+
describe "when a structurally-complete response is rendered" do
|
56
|
+
before do
|
57
|
+
view "<% raise 'x' %>"
|
58
|
+
action { render :stream => true, :layout => 'layout' }
|
59
|
+
end
|
60
|
+
|
61
|
+
it "should inject errors correctly when the error occurs before the doctype" do
|
62
|
+
layout "<%= yield %><!DOCTYPE html><html><head></head><body></body></html>"
|
63
|
+
run
|
64
|
+
received.should == chunks("<!DOCTYPE html><html><head></head><body>(x)</body></html>", :end => true)
|
65
|
+
end
|
66
|
+
|
67
|
+
it "should inject errors correctly when the error occurs before the opening html tag" do
|
68
|
+
layout "<!DOCTYPE html><% flush %><% yield %><html><head></head><body></body></html>"
|
69
|
+
run
|
70
|
+
received.should == chunks("<!DOCTYPE html>", "<html><head></head><body>(x)</body></html>", :end => true)
|
71
|
+
end
|
72
|
+
|
73
|
+
it "should inject errors correctly when the error occurs before the beginning of the head" do
|
74
|
+
layout "<!DOCTYPE html><html><% flush %><% yield %><head></head><body></body></html>"
|
75
|
+
run
|
76
|
+
received.should == chunks("<!DOCTYPE html><html>", "<head></head><body>(x)</body></html>", :end => true)
|
77
|
+
end
|
78
|
+
|
79
|
+
it "should inject errors correctly when the error occurs during the head" do
|
80
|
+
layout "<!DOCTYPE html><html><head><% flush %><% yield %></head><body></body></html>"
|
81
|
+
run
|
82
|
+
received.should == chunks("<!DOCTYPE html><html><head>", "</head><body>(x)</body></html>", :end => true)
|
83
|
+
end
|
84
|
+
|
85
|
+
it "should inject errors correctly when the error occurs between the head and body" do
|
86
|
+
layout "<!DOCTYPE html><html><head></head><% flush %><% yield %><body></body></html>"
|
87
|
+
run
|
88
|
+
received.should == chunks("<!DOCTYPE html><html><head></head>", "<body>(x)</body></html>", :end => true)
|
89
|
+
end
|
90
|
+
|
91
|
+
it "should inject errors correctly when the error occurs during the body" do
|
92
|
+
layout "<!DOCTYPE html><html><head></head><body><% flush %><% yield %></body></html>"
|
93
|
+
run
|
94
|
+
received.should == chunks("<!DOCTYPE html><html><head></head><body>", "(x)</body></html>", :end => true)
|
95
|
+
end
|
96
|
+
|
97
|
+
it "should inject errors correctly when the error occurs after the body" do
|
98
|
+
layout "<!DOCTYPE html><html><head></head><body></body><% flush %><% yield %></html>"
|
99
|
+
run
|
100
|
+
received.should == chunks("<!DOCTYPE html><html><head></head><body></body>", "</html>", "(x)", :end => true)
|
101
|
+
end
|
102
|
+
|
103
|
+
it "should inject errors correctly when the error occurs after the closing html tag" do
|
104
|
+
layout "<!DOCTYPE html><html><head></head><body></body></html><% flush %><% yield %>"
|
105
|
+
run
|
106
|
+
received.should == chunks("<!DOCTYPE html><html><head></head><body></body></html>", "(x)", :end => true)
|
107
|
+
end
|
108
|
+
end
|
109
|
+
|
110
|
+
describe "when an structurally-incomplete response is rendered" do
|
111
|
+
before do
|
112
|
+
action { render :stream => true, :layout => nil }
|
113
|
+
end
|
114
|
+
|
115
|
+
it "should inject errors correctly when nothing is rendered" do
|
116
|
+
view "<% flush %><% raise 'x' %>"
|
117
|
+
run
|
118
|
+
received.should == chunks("<!DOCTYPE html><html><head><title>Unhandled Exception</title></head><body>(x)</body></html>", :end => true)
|
119
|
+
end
|
120
|
+
|
121
|
+
it "should inject errors correctly when just the doctype is rendered" do
|
122
|
+
view "<!DOCTYPE html><% flush %><% raise 'x' %>"
|
123
|
+
run
|
124
|
+
received.should == chunks("<!DOCTYPE html>", "<html><head><title>Unhandled Exception</title></head><body>(x)</body></html>", :end => true)
|
125
|
+
end
|
126
|
+
|
127
|
+
it "should inject errors correctly when just the doctype and opening html tag are rendered" do
|
128
|
+
view "<!DOCTYPE html><html><% flush %><% raise 'x' %>"
|
129
|
+
run
|
130
|
+
received.should == chunks("<!DOCTYPE html><html>", "<head><title>Unhandled Exception</title></head><body>(x)</body></html>", :end => true)
|
131
|
+
end
|
132
|
+
|
133
|
+
it "should inject errors correctly when only half the head is rendered" do
|
134
|
+
view "<!DOCTYPE html><html><head><% flush %><% raise 'x' %>"
|
135
|
+
run
|
136
|
+
received.should == chunks("<!DOCTYPE html><html><head>", "</head><body>(x)</body></html>", :end => true)
|
137
|
+
end
|
138
|
+
|
139
|
+
it "should inject errors correctly when only a head is rendered" do
|
140
|
+
view "<!DOCTYPE html><html><head></head><% flush %><% raise 'x' %>"
|
141
|
+
run
|
142
|
+
received.should == chunks("<!DOCTYPE html><html><head></head>", "<body>(x)</body></html>", :end => true)
|
143
|
+
end
|
144
|
+
|
145
|
+
it "should inject errors correctly when the closing body tag is missing" do
|
146
|
+
view "<!DOCTYPE html><html><head></head><body><% flush %><% raise 'x' %>"
|
147
|
+
run
|
148
|
+
received.should == chunks("<!DOCTYPE html><html><head></head><body>", "(x)</body></html>", :end => true)
|
149
|
+
end
|
150
|
+
|
151
|
+
it "should inject errors correctly when the closing html tag is missing" do
|
152
|
+
view "<!DOCTYPE html><html><head></head><body></body><% flush %><% raise 'x' %>"
|
153
|
+
run
|
154
|
+
received.should == chunks("<!DOCTYPE html><html><head></head><body></body>", "(x)</html>", :end => true)
|
155
|
+
end
|
156
|
+
end
|
157
|
+
|
158
|
+
describe "when the response consists of multiple templates" do
|
159
|
+
before do
|
160
|
+
action { render :stream => true, :layout => 'layout' }
|
161
|
+
end
|
162
|
+
|
163
|
+
it "should inject errors when there is an error in the toplevel layout" do
|
164
|
+
layout "<!DOCTYPE html><html><head></head><body><% flush %><%= raise 'x' %></body></html>"
|
165
|
+
view ''
|
166
|
+
run
|
167
|
+
received.should == chunks("<!DOCTYPE html><html><head></head><body>", "(x)</body></html>", :end => true)
|
168
|
+
end
|
169
|
+
|
170
|
+
it "should inject errors when there is an error in the toplevel view" do
|
171
|
+
layout "<!DOCTYPE html><html><head></head><body><% flush %>[<%= yield %>]</body></html>"
|
172
|
+
view "<% raise 'x' %>"
|
173
|
+
run
|
174
|
+
received.should == chunks("<!DOCTYPE html><html><head></head><body>", "[](x)</body></html>", :end => true)
|
175
|
+
end
|
176
|
+
|
177
|
+
it "should inject errors when there is an error in a partial" do
|
178
|
+
layout "<!DOCTYPE html><html><head></head><body><% flush %>[<%= yield %>]</body></html>"
|
179
|
+
view "view{<%= render :partial => 'partial' %>}"
|
180
|
+
partial "<% raise 'x' %>"
|
181
|
+
run
|
182
|
+
received.should == chunks("<!DOCTYPE html><html><head></head><body>", "[view{}](x)</body></html>", :end => true)
|
183
|
+
end
|
184
|
+
|
185
|
+
it "should inject errors when there is an error in a subpartial" do
|
186
|
+
layout "<!DOCTYPE html><html><head></head><body><% flush %><%= yield %></body></html>"
|
187
|
+
view "view{<%= render :partial => 'partial' %>}"
|
188
|
+
partial "partial`<%= render :partial => 'subpartial' %>'"
|
189
|
+
template 'test/_subpartial', "<% raise 'x' %>"
|
190
|
+
run
|
191
|
+
received.should == chunks("<!DOCTYPE html><html><head></head><body>", "view{partial`'}(x)</body></html>", :end => true)
|
192
|
+
end
|
193
|
+
|
194
|
+
it "should inject errors from all partials which raised an unhandled exception" do
|
195
|
+
layout "<!DOCTYPE html><html><head></head><body><% flush %><%= yield %></body></html>"
|
196
|
+
view "view[<%= render :partial => 'x' %><%= render :partial => 'ok' %><%= render :partial => 'y' %>]"
|
197
|
+
template 'test/_x', "<% raise 'x' %>"
|
198
|
+
template 'test/_y', "<% raise 'y' %>"
|
199
|
+
template 'test/_ok', "ok"
|
200
|
+
run
|
201
|
+
received.should == chunks("<!DOCTYPE html><html><head></head><body>", "view[ok](x,y)</body></html>", :end => true)
|
202
|
+
end
|
203
|
+
end
|
204
|
+
end
|
205
|
+
|
206
|
+
describe "for nonlocal requests" do
|
207
|
+
before do
|
208
|
+
controller.class_eval do
|
209
|
+
def local_request?
|
210
|
+
false
|
211
|
+
end
|
212
|
+
end
|
213
|
+
end
|
214
|
+
|
215
|
+
it "should run the error callback for each error raised" do
|
216
|
+
messages = []
|
217
|
+
controller.on_streaming_error do |error|
|
218
|
+
messages << error.original_exception.message
|
219
|
+
end
|
220
|
+
view "<% render :partial => 'a' %><% render :partial => 'b' %>"
|
221
|
+
template 'test/_a', "<% raise 'a' %>"
|
222
|
+
template 'test/_b', "<% raise 'b' %>"
|
223
|
+
action { render :stream => true, :layout => nil }
|
224
|
+
run
|
225
|
+
messages.should == ['a', 'b']
|
226
|
+
end
|
227
|
+
|
228
|
+
it "should not inject any error information" do
|
229
|
+
layout "<!DOCTYPE html><html><head></head><body><% flush %><%= yield %></body></html>"
|
230
|
+
view "...<% raise 'x' %>..."
|
231
|
+
action { render :stream => true, :layout => 'layout' }
|
232
|
+
run
|
233
|
+
received.should == chunks("<!DOCTYPE html><html><head></head><body>", "</body></html>", :end => true)
|
234
|
+
end
|
235
|
+
end
|
236
|
+
end
|
237
|
+
end
|
238
|
+
|
239
|
+
describe "the default error rendering callback" do
|
240
|
+
before do
|
241
|
+
TestController.class_eval do
|
242
|
+
def rescue_action(exception)
|
243
|
+
# Run the default handler.
|
244
|
+
ActionController::Base.instance_method(:rescue_action).bind(self).call(exception)
|
245
|
+
end
|
246
|
+
|
247
|
+
def local_request?
|
248
|
+
true
|
249
|
+
end
|
250
|
+
end
|
251
|
+
end
|
252
|
+
|
253
|
+
it "should render the standard error information" do
|
254
|
+
view "<% raise 'test exception' %>"
|
255
|
+
action { render :stream => true }
|
256
|
+
run
|
257
|
+
received.should include('test exception')
|
258
|
+
received.should include('#uncaught_exceptions')
|
259
|
+
end
|
260
|
+
end
|
261
|
+
end
|