ZenTest 3.1.0 → 3.2.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/History.txt +16 -4
- data/Manifest.txt +13 -0
- data/README.txt +19 -46
- data/Rakefile +31 -14
- data/bin/rails_test_audit +80 -0
- data/bin/unit_diff +4 -6
- data/lib/autotest.rb +22 -10
- data/lib/rails_autotest.rb +67 -15
- data/lib/test/rails.rb +267 -0
- data/lib/test/rails/controller_test_case.rb +357 -0
- data/lib/test/rails/functional_test_case.rb +64 -0
- data/lib/test/rails/ivar_proxy.rb +31 -0
- data/lib/test/rails/rake_tasks.rb +49 -0
- data/lib/test/rails/test_case.rb +12 -0
- data/lib/test/rails/view_test_case.rb +431 -0
- data/lib/test/zentest_assertions.rb +46 -0
- data/lib/zentest.rb +48 -2
- data/test/data/normal/test/#test_photo.rb# +0 -0
- data/test/data/rails/app/views/route/index.rhtml +0 -0
- data/test/data/rails/test/controllers/route_controller_test.rb +0 -0
- data/test/data/rails/test/views/route_view_test.rb +0 -0
- data/test/test_autotest.rb +9 -5
- data/test/test_rails_autotest.rb +142 -49
- metadata +30 -13
- data/bin/ZenTest +0 -28
@@ -0,0 +1,64 @@
|
|
1
|
+
##
|
2
|
+
# FunctionalTestCase is an abstract class that sets up a controller instance
|
3
|
+
# for its subclasses.
|
4
|
+
|
5
|
+
class Test::Rails::FunctionalTestCase < Test::Rails::TestCase
|
6
|
+
|
7
|
+
##
|
8
|
+
# Sets up instance variables to allow tests depending on a controller work.
|
9
|
+
#
|
10
|
+
# setup uses the instance variable @controller_class_name to determine which
|
11
|
+
# controller class to instantiate.
|
12
|
+
#
|
13
|
+
# setup also instantiates a new @request and @response object.
|
14
|
+
|
15
|
+
def setup
|
16
|
+
return if self.class.name =~ /TestCase$/
|
17
|
+
|
18
|
+
@controller_class = Object.path2class @controller_class_name
|
19
|
+
raise "Can't determine controller class for #{self.class}" if @controller_class.nil?
|
20
|
+
|
21
|
+
@controller = @controller_class.new
|
22
|
+
|
23
|
+
@session = ActionController::TestSession.new
|
24
|
+
|
25
|
+
@flash = ActionController::Flash::FlashHash.new
|
26
|
+
@session['flash'] = @flash
|
27
|
+
|
28
|
+
@request = ActionController::TestRequest.new
|
29
|
+
@request.session = @session
|
30
|
+
|
31
|
+
@response = ActionController::TestResponse.new
|
32
|
+
end
|
33
|
+
|
34
|
+
##
|
35
|
+
# Flash accessor. The flash can be assigned to before calling process or
|
36
|
+
# render and it will Just Work (yay!)
|
37
|
+
#
|
38
|
+
# view:
|
39
|
+
# <div class="error"><%= flash[:error] %></div>
|
40
|
+
#
|
41
|
+
# test:
|
42
|
+
# flash[:error] = 'You did a bad thing.'
|
43
|
+
# render
|
44
|
+
# assert_tag :tag => 'div', :attributes => { :class => 'error' },
|
45
|
+
# :content => 'You did a bad thing.'
|
46
|
+
|
47
|
+
attr_reader :flash
|
48
|
+
|
49
|
+
##
|
50
|
+
# Session accessor. The session can be assigned to before calling process
|
51
|
+
# or render and it will Just Work (yay!)
|
52
|
+
#
|
53
|
+
# test:
|
54
|
+
#
|
55
|
+
# def test_logout
|
56
|
+
# session[:user] = users(:herbert)
|
57
|
+
# post :logout
|
58
|
+
# assert_equal nil, session[:user]
|
59
|
+
# end
|
60
|
+
|
61
|
+
attr_reader :session
|
62
|
+
|
63
|
+
end
|
64
|
+
|
@@ -0,0 +1,31 @@
|
|
1
|
+
require 'test/rails'
|
2
|
+
|
3
|
+
##
|
4
|
+
# A wrapper that allows instance variables to be manipulated using +[]+ and
|
5
|
+
# +[]=+
|
6
|
+
|
7
|
+
class Test::Rails::IvarProxy
|
8
|
+
|
9
|
+
##
|
10
|
+
# Wraps +object+ allowing its instance variables to be manipulated.
|
11
|
+
|
12
|
+
def initialize(object)
|
13
|
+
@object = object
|
14
|
+
end
|
15
|
+
|
16
|
+
##
|
17
|
+
# Retrieves +ivar+ from the wrapped object.
|
18
|
+
|
19
|
+
def [](ivar)
|
20
|
+
@object.instance_variable_get "@#{ivar}"
|
21
|
+
end
|
22
|
+
|
23
|
+
##
|
24
|
+
# Sets +ivar+ to +val+ on the wrapped object.
|
25
|
+
|
26
|
+
def []=(ivar, val)
|
27
|
+
@object.instance_variable_set "@#{ivar}", val
|
28
|
+
end
|
29
|
+
|
30
|
+
end
|
31
|
+
|
@@ -0,0 +1,49 @@
|
|
1
|
+
require 'code_statistics'
|
2
|
+
|
3
|
+
namespace :test do
|
4
|
+
desc 'Run the view tests in test/views'
|
5
|
+
Rake::TestTask.new :views => [ 'db:test:prepare' ] do |t|
|
6
|
+
t.libs << 'test'
|
7
|
+
t.pattern = 'test/views/**/*_test.rb'
|
8
|
+
t.verbose = true
|
9
|
+
end
|
10
|
+
|
11
|
+
desc 'Run the controller tests in test/controllers'
|
12
|
+
Rake::TestTask.new :controllers => [ 'db:test:prepare' ] do |t|
|
13
|
+
t.libs << 'test'
|
14
|
+
t.pattern = 'test/controllers/**/*_test.rb'
|
15
|
+
t.verbose = true
|
16
|
+
end
|
17
|
+
end
|
18
|
+
|
19
|
+
desc 'Run all tests'
|
20
|
+
task :test => %w[
|
21
|
+
test:units
|
22
|
+
test:controllers
|
23
|
+
test:views
|
24
|
+
test:functionals
|
25
|
+
test:integration
|
26
|
+
]
|
27
|
+
|
28
|
+
dirs = [
|
29
|
+
%w[Libraries lib/],
|
30
|
+
%w[Models app/models],
|
31
|
+
%w[Unit\ tests test/unit],
|
32
|
+
%w[Components components],
|
33
|
+
%w[Controllers app/controllers],
|
34
|
+
%w[Controller\ tests test/controllers],
|
35
|
+
%w[View\ tests test/views],
|
36
|
+
%w[Functional\ tests test/functional],
|
37
|
+
%w[Integration\ tests test/integration],
|
38
|
+
%w[APIs app/apis],
|
39
|
+
%w[Helpers app/helpers],
|
40
|
+
]
|
41
|
+
|
42
|
+
dirs = dirs.map { |name, dir| [name, File.join(RAILS_ROOT, dir)] }
|
43
|
+
dirs = dirs.select { |name, dir| File.directory? dir }
|
44
|
+
|
45
|
+
STATS_DIRECTORIES.replace dirs
|
46
|
+
|
47
|
+
CodeStatistics::TEST_TYPES << 'View tests'
|
48
|
+
CodeStatistics::TEST_TYPES << 'Controller tests'
|
49
|
+
|
@@ -0,0 +1,431 @@
|
|
1
|
+
##
|
2
|
+
# ViewTestCase allows views to be tested independent of their controllers.
|
3
|
+
# Testcase implementors must set up the instance variables the view needs to
|
4
|
+
# render itself.
|
5
|
+
#
|
6
|
+
# = Features
|
7
|
+
#
|
8
|
+
# * Allows testing of individual AJAX templates.
|
9
|
+
# * Allows testing of individual partials.
|
10
|
+
# * Large library of helful assertions.
|
11
|
+
#
|
12
|
+
# = Naming
|
13
|
+
#
|
14
|
+
# The test class must be named after your controller class name, so if
|
15
|
+
# you're testing views for the +RouteController+ you would name your
|
16
|
+
# test case +RouteViewTest+. The test case will expect to find your
|
17
|
+
# view files in <tt>app/views/route</tt>.
|
18
|
+
#
|
19
|
+
# The test names should be in the form of +test_view_edgecase+ where
|
20
|
+
# 'view' corresponds to the name of the view file, and 'edgecase'
|
21
|
+
# describes the scenario you are testing.
|
22
|
+
#
|
23
|
+
# If you are testing a view file named 'show.rhtml' your test should
|
24
|
+
# be named +test_show+. If your view is behaves differently depending
|
25
|
+
# upon its parameters then you can make the test name descriptive like
|
26
|
+
# +test_show_photos+ and +test_show_no_photos+.
|
27
|
+
#
|
28
|
+
# = Examples
|
29
|
+
#
|
30
|
+
# == Typical View Test
|
31
|
+
#
|
32
|
+
# class RouteViewTest < Test::Rails::ViewTestCase
|
33
|
+
#
|
34
|
+
# fixtures :users, :routes, :points, :photos
|
35
|
+
#
|
36
|
+
# def test_delete
|
37
|
+
# # Set up instance variables for template
|
38
|
+
# assigns[:loggedin_user] = users(:herbert)
|
39
|
+
# assigns[:route] = routes(:work)
|
40
|
+
#
|
41
|
+
# # render template for the delete action in RouteController
|
42
|
+
# render
|
43
|
+
#
|
44
|
+
# # assert that there's a form with an action of "/route/destroy"
|
45
|
+
# form_url = '/route/destroy'
|
46
|
+
# assert_post_form form_url
|
47
|
+
# # with a hidden id field
|
48
|
+
# assert_input form_url, :hidden, :id
|
49
|
+
# # And a submit button that says 'Delete!'
|
50
|
+
# assert_submit form_url, 'Delete!'
|
51
|
+
# # And a link back to the route so you don't delete it
|
52
|
+
# assert_links_to "/route/show/#{routes(:work).id}", 'No, I do not!'
|
53
|
+
# end
|
54
|
+
#
|
55
|
+
# end
|
56
|
+
#
|
57
|
+
# == Typical Layout Test
|
58
|
+
#
|
59
|
+
# require 'test/test_helper'
|
60
|
+
#
|
61
|
+
# # Create a dummy controller for layout views. This lets the setup use the
|
62
|
+
# # right path with minimum fuss.
|
63
|
+
# class LayoutsController < ApplicationController; end
|
64
|
+
#
|
65
|
+
# class LayoutsViewTest < Test::Rails::ViewTestCase
|
66
|
+
#
|
67
|
+
# fixtures :users, :routes, :points, :photos
|
68
|
+
#
|
69
|
+
# def test_default
|
70
|
+
# # Template set-up
|
71
|
+
# @request.request_uri = '/foo'
|
72
|
+
# assigns[:action_title] = 'Hello & Goodbye'
|
73
|
+
#
|
74
|
+
# # Render an empty string with the 'default' layout.
|
75
|
+
# render :text => '', :layout => 'default'
|
76
|
+
#
|
77
|
+
# # Assert content just like a regular view test.
|
78
|
+
# assert_links_to '/', 'Home'
|
79
|
+
# assert_links_to '/user', 'Login'
|
80
|
+
# deny_links_to '/user/logout', 'Logout'
|
81
|
+
# assert_tag :tag => 'title', :content => 'Hello & Goodbye'
|
82
|
+
# assert_tag :tag => 'h1', :content => 'Hello & Goodbye'
|
83
|
+
# end
|
84
|
+
#
|
85
|
+
# end
|
86
|
+
|
87
|
+
class Test::Rails::ViewTestCase < Test::Rails::FunctionalTestCase
|
88
|
+
|
89
|
+
##
|
90
|
+
# Sets up the test case.
|
91
|
+
|
92
|
+
def setup
|
93
|
+
return if self.class == Test::Rails::ViewTestCase
|
94
|
+
|
95
|
+
klass_name = self.class.name.sub(/View/, 'Controller')
|
96
|
+
@controller_class_name ||= klass_name.sub 'Test', ''
|
97
|
+
|
98
|
+
super
|
99
|
+
|
100
|
+
@ivar_proxy = Test::Rails::IvarProxy.new @controller
|
101
|
+
|
102
|
+
# these go here so that flash and session work as they should.
|
103
|
+
@controller.send :initialize_template_class, @response
|
104
|
+
@controller.send :assign_shortcuts, @request, @response
|
105
|
+
@controller.send :reset_session
|
106
|
+
|
107
|
+
assigns[:session] = @controller.session
|
108
|
+
@controller.class.send :public, :flash # make flash accessible to the test
|
109
|
+
end
|
110
|
+
|
111
|
+
##
|
112
|
+
# Allows the view instance variables to be set like flash:
|
113
|
+
#
|
114
|
+
# test:
|
115
|
+
# def test_show
|
116
|
+
# assigns[:route] = routes(:work)
|
117
|
+
|
118
|
+
def assigns
|
119
|
+
@ivar_proxy
|
120
|
+
end
|
121
|
+
|
122
|
+
##
|
123
|
+
# Renders the template. The template is determined from the test name. If
|
124
|
+
# you have multiple tests for the same view render will try to Do The Right
|
125
|
+
# Thing and remove parts of the name looking for the template file.
|
126
|
+
#
|
127
|
+
# By default, render has the added option <tt>:layout => false</tt>,
|
128
|
+
# so if want to test behavior in your layout add <tt>:layout => true</tt>.
|
129
|
+
#
|
130
|
+
# The action can be forced by using the options:
|
131
|
+
#
|
132
|
+
# render :action => 'new'
|
133
|
+
#
|
134
|
+
# render :template => 'profile/index'
|
135
|
+
#
|
136
|
+
# For this test:
|
137
|
+
#
|
138
|
+
# class RouteViewTest < Test::Rails::ViewTestCase
|
139
|
+
# def test_show_photos
|
140
|
+
# render
|
141
|
+
# end
|
142
|
+
# def test_show_no_photos
|
143
|
+
# render
|
144
|
+
# end
|
145
|
+
# end
|
146
|
+
#
|
147
|
+
# For test_show_photos will look for:
|
148
|
+
# * app/views/route/show_photos.rhtml
|
149
|
+
# * app/views/route/show_photos.rxml
|
150
|
+
# * app/views/route/show.rhtml
|
151
|
+
# * app/views/route/show.rxml
|
152
|
+
#
|
153
|
+
# And test_show_no_photos will look for:
|
154
|
+
# * app/views/route/show_no_photos.rhtml
|
155
|
+
# * app/views/route/show_no_photos.rxml
|
156
|
+
# * app/views/route/show_no.rhtml
|
157
|
+
# * app/views/route/show_no.rxml
|
158
|
+
# * app/views/route/show.rhtml
|
159
|
+
# * app/views/route/show.rxml
|
160
|
+
#
|
161
|
+
# If a view cannot be found the test will flunk.
|
162
|
+
|
163
|
+
def render(options = {}, deprecated_status = nil)
|
164
|
+
@action_name = action_name caller[0] if options.empty?
|
165
|
+
assigns[:action_name] = @action_name
|
166
|
+
|
167
|
+
@request.path_parameters = {
|
168
|
+
:controller => @controller.controller_name,
|
169
|
+
:action => @action_name,
|
170
|
+
}
|
171
|
+
|
172
|
+
defaults = { :layout => false }
|
173
|
+
options = defaults.merge options
|
174
|
+
|
175
|
+
@controller.instance_variable_set :@params, @request.parameters
|
176
|
+
@controller.send :initialize_current_url
|
177
|
+
|
178
|
+
# Rails 1.0
|
179
|
+
@controller.send :assign_names rescue nil
|
180
|
+
@controller.send :fire_flash rescue nil
|
181
|
+
|
182
|
+
# Rails 1.1
|
183
|
+
@controller.send :forget_variables_added_to_assigns rescue nil
|
184
|
+
|
185
|
+
# Do the render
|
186
|
+
@controller.render options, deprecated_status
|
187
|
+
|
188
|
+
# Rails 1.1
|
189
|
+
@controller.send :process_cleanup rescue nil
|
190
|
+
end
|
191
|
+
|
192
|
+
##
|
193
|
+
# Asserts that there is an error on +field+ of type +type+.
|
194
|
+
|
195
|
+
def assert_error_on(field, type)
|
196
|
+
error_message = ActiveRecord::Errors.default_error_messages[type]
|
197
|
+
assert_tag :tag => 'div', :attributes => { :class => 'errorExplanation' },
|
198
|
+
:descendant => {
|
199
|
+
:tag => 'li',
|
200
|
+
:content => /^#{field} #{error_message}/i }
|
201
|
+
end
|
202
|
+
|
203
|
+
##
|
204
|
+
# Asserts that a form with +form_action+ has an input element of +type+ with
|
205
|
+
# a name of "+model+[+column+]" and has a label with a for attribute of
|
206
|
+
# "+model+_+column+".
|
207
|
+
#
|
208
|
+
# view:
|
209
|
+
# <%= start_form_tag :controller => 'game', :action => 'save' %>
|
210
|
+
# <label for="game_amount">Amount:</label>
|
211
|
+
# <% text_field 'game', 'amount' %>
|
212
|
+
#
|
213
|
+
# test:
|
214
|
+
# assert_field '/game/save', :text, :game, :amount
|
215
|
+
|
216
|
+
def assert_field(form_action, type, model, column, value = nil)
|
217
|
+
assert_input form_action, type, "#{model}[#{column}]", value
|
218
|
+
assert_label form_action, "#{model}_#{column}", false
|
219
|
+
end
|
220
|
+
|
221
|
+
##
|
222
|
+
# Asserts that an image exists with a src of +src+.
|
223
|
+
#
|
224
|
+
# view:
|
225
|
+
# <img src="/images/bucket.jpg" alt="Bucket">
|
226
|
+
#
|
227
|
+
# test:
|
228
|
+
# assert_image '/images/bucket.jpg'
|
229
|
+
|
230
|
+
def assert_image(src)
|
231
|
+
assert_tag :tag => 'img', :attributes => { :src => src }
|
232
|
+
end
|
233
|
+
|
234
|
+
##
|
235
|
+
# Asserts that a form with +form_action+ has an input element of +type+ with
|
236
|
+
# a name of +name+.
|
237
|
+
#
|
238
|
+
# view:
|
239
|
+
# <%= start_form_tag :controller => 'game', :action => 'save' %>
|
240
|
+
# <%= text_field 'game', 'amount' %>
|
241
|
+
#
|
242
|
+
# test:
|
243
|
+
# assert_input '/game/save', :text, "game[amount]"
|
244
|
+
|
245
|
+
def assert_input(form_action, type, name, value = nil)
|
246
|
+
attrs = { :type => type.to_s, :name => name.to_s }
|
247
|
+
attrs[:value] = value unless value.nil?
|
248
|
+
assert_tag_in_form form_action, :tag => 'input', :attributes => attrs
|
249
|
+
end
|
250
|
+
|
251
|
+
##
|
252
|
+
# Asserts that a form with +form_action+ has a label with a for attribute of
|
253
|
+
# "+model+_+column+".
|
254
|
+
#
|
255
|
+
# view:
|
256
|
+
# <%= start_form_tag :controller => 'game', :action => 'save' %>
|
257
|
+
# <label for="game_amount">Amount:</label>
|
258
|
+
#
|
259
|
+
# test:
|
260
|
+
# assert_label '/game/save', :game, :amount
|
261
|
+
|
262
|
+
def assert_label(form_action, name, include_f = true)
|
263
|
+
for_attribute = (include_f ? 'f_' : '') << name
|
264
|
+
assert_tag_in_form form_action, :tag => 'label', :attributes => {
|
265
|
+
:for => for_attribute }
|
266
|
+
end
|
267
|
+
|
268
|
+
##
|
269
|
+
# Asserts that there is an anchor tag with an href of +href+ and optionally
|
270
|
+
# has +content+.
|
271
|
+
#
|
272
|
+
# view:
|
273
|
+
# <%= link_to 'drbrain', :model => user %>
|
274
|
+
#
|
275
|
+
# test:
|
276
|
+
# assert_links_to '/players/show/1', 'drbrain'
|
277
|
+
|
278
|
+
def assert_links_to(href, content = nil)
|
279
|
+
assert_tag links_to_options_for(href, content)
|
280
|
+
end
|
281
|
+
|
282
|
+
##
|
283
|
+
# Denies the existence of an anchor tag with an href of +href+ and
|
284
|
+
# optionally +content+.
|
285
|
+
#
|
286
|
+
# view (for /players/show/1):
|
287
|
+
# <%= link_to_unless_current 'drbrain', :model => user %>
|
288
|
+
#
|
289
|
+
# test:
|
290
|
+
# deny_links_to '/players/show/1'
|
291
|
+
|
292
|
+
def deny_links_to(href, content = nil)
|
293
|
+
assert_no_tag links_to_options_for(href, content)
|
294
|
+
end
|
295
|
+
|
296
|
+
##
|
297
|
+
# Asserts that there is a form using the 'POST' method whose action is
|
298
|
+
# +form_action+ and uses the multipart content type.
|
299
|
+
#
|
300
|
+
# view:
|
301
|
+
# <%= start_form_tag({ :action => 'create_file' }, :multipart => true) %>
|
302
|
+
#
|
303
|
+
# test:
|
304
|
+
# assert_multipart_form '/game/save'
|
305
|
+
|
306
|
+
def assert_multipart_form(form_action)
|
307
|
+
assert_tag :tag => 'form', :attributes => { :action => form_action,
|
308
|
+
:method => 'post', :enctype => 'multipart/form-data' }
|
309
|
+
end
|
310
|
+
|
311
|
+
##
|
312
|
+
# Asserts that there is a form using the 'POST' method whose action is
|
313
|
+
# +form_action+.
|
314
|
+
#
|
315
|
+
# view:
|
316
|
+
# <%= start_form_tag :action => 'create_file' %>
|
317
|
+
#
|
318
|
+
# test:
|
319
|
+
# assert_post_form '/game/save'
|
320
|
+
|
321
|
+
def assert_post_form(form_action)
|
322
|
+
assert_tag :tag => 'form', :attributes => { :action => form_action,
|
323
|
+
:method => 'post' }
|
324
|
+
end
|
325
|
+
|
326
|
+
##
|
327
|
+
# Asserts that a form with +form_action+ has a select element with a name of
|
328
|
+
# "+model+[+column+]" and options with specified names and values.
|
329
|
+
#
|
330
|
+
# view:
|
331
|
+
# <%= start_form_tag :action => 'save' %>
|
332
|
+
# <%= collection_select :game, :location_id, @locations, :id, :name %>
|
333
|
+
#
|
334
|
+
# test:
|
335
|
+
# assert_select '/games/save', :game, :location_id,
|
336
|
+
# 'Ballet' => 1, 'Guaymas' => 2
|
337
|
+
|
338
|
+
def assert_select(form_action, model, column, options)
|
339
|
+
assert_kind_of Hash, options, "options needs to be a Hash"
|
340
|
+
deny options.empty?, "options must not be empty"
|
341
|
+
options.each do |option_name, option_id|
|
342
|
+
assert_tag_in_form(form_action,
|
343
|
+
:tag => 'select',
|
344
|
+
:attributes => { :name => "#{model}[#{column}]" },
|
345
|
+
:child => {
|
346
|
+
:tag => 'option',
|
347
|
+
:attributes => { :value => option_id },
|
348
|
+
:content => option_name
|
349
|
+
})
|
350
|
+
end
|
351
|
+
end
|
352
|
+
|
353
|
+
##
|
354
|
+
# Asserts that a form with +form_action+ has a submit element with a value
|
355
|
+
# of +value+.
|
356
|
+
#
|
357
|
+
# view:
|
358
|
+
# <%= start_form_tag :action => 'save' %>
|
359
|
+
# <input type="submit" value="Create!" %>
|
360
|
+
#
|
361
|
+
# test:
|
362
|
+
# assert_submit '/route/save', 'Create!'
|
363
|
+
|
364
|
+
def assert_submit(form_action, value)
|
365
|
+
assert_tag_in_form form_action, :tag => 'input', :attributes => {
|
366
|
+
:type => "submit", :value => value }
|
367
|
+
end
|
368
|
+
|
369
|
+
##
|
370
|
+
# Asserts that a form with +form_action+ has a descendent that matches
|
371
|
+
# +options+.
|
372
|
+
#
|
373
|
+
# Typically this is not used directly in tests. Instead use it to build
|
374
|
+
# expressive tests that assert which fields are in what form.
|
375
|
+
#
|
376
|
+
# view:
|
377
|
+
# <%= start_form_tag :action => 'save' %>
|
378
|
+
# <table>
|
379
|
+
#
|
380
|
+
# test:
|
381
|
+
# assert_tag_in_form '/route/save', :tag => 'table'
|
382
|
+
|
383
|
+
def assert_tag_in_form(form_action, options)
|
384
|
+
assert_tag :tag => 'form', :attributes => { :action => form_action },
|
385
|
+
:descendant => options
|
386
|
+
end
|
387
|
+
|
388
|
+
##
|
389
|
+
# Creates a new Paginator that uses the current controller. +item_count+,
|
390
|
+
# +items_per_page+ and +page_number+ are passed straight through.
|
391
|
+
|
392
|
+
def util_make_paginator(item_count, items_per_page, page_number)
|
393
|
+
ActionController::Pagination::Paginator.new(@controller, item_count,
|
394
|
+
items_per_page, page_number)
|
395
|
+
end
|
396
|
+
|
397
|
+
protected
|
398
|
+
|
399
|
+
##
|
400
|
+
# Creates an assertion options hash for +href+ and +content+.
|
401
|
+
|
402
|
+
def links_to_options_for(href, content = nil)
|
403
|
+
options = { :tag => 'a', :attributes => { :href => href } }
|
404
|
+
options[:content] = content unless content.nil?
|
405
|
+
return options
|
406
|
+
end
|
407
|
+
|
408
|
+
private
|
409
|
+
|
410
|
+
##
|
411
|
+
# Returns the action_name based on a backtrace line passed in as +test+.
|
412
|
+
|
413
|
+
def action_name(test)
|
414
|
+
orig_name = test = test.sub(/.*in `test_(.*)'/, '\1')
|
415
|
+
controller = @controller.class.name.sub('Controller', '')
|
416
|
+
controller = controller.gsub(/([A-Z])/, '_\1'.downcase).sub('_', '')
|
417
|
+
|
418
|
+
while test =~ /_/ do
|
419
|
+
return test if File.file? "app/views/#{controller}/#{test}.rhtml"
|
420
|
+
return test if File.file? "app/views/#{controller}/#{test}.rxml"
|
421
|
+
test = test.sub(/_[^_]+$/, '')
|
422
|
+
end
|
423
|
+
|
424
|
+
return test if File.file? "app/views/#{controller}/#{test}.rhtml"
|
425
|
+
return test if File.file? "app/views/#{controller}/#{test}.rxml"
|
426
|
+
|
427
|
+
flunk "Couldn't find view for test_#{orig_name}"
|
428
|
+
end
|
429
|
+
|
430
|
+
end
|
431
|
+
|