ZenTest 3.1.0 → 3.2.0
Sign up to get free protection for your applications and to get access to all the features.
- 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
|
+
|