dry_crud 1.6.0 → 1.7.0
Sign up to get free protection for your applications and to get access to all the features.
- data/README.rdoc +25 -10
- data/Rakefile +30 -8
- data/VERSION +1 -1
- data/lib/generators/dry_crud/dry_crud_generator.rb +15 -2
- data/lib/generators/dry_crud/templates/app/controllers/crud_controller.rb +18 -10
- data/lib/generators/dry_crud/templates/app/controllers/list_controller.rb +14 -11
- data/lib/generators/dry_crud/templates/app/helpers/crud_helper.rb +71 -29
- data/lib/generators/dry_crud/templates/app/helpers/standard_form_builder.rb +40 -3
- data/lib/generators/dry_crud/templates/app/helpers/standard_helper.rb +8 -27
- data/lib/generators/dry_crud/templates/app/helpers/standard_table_builder.rb +13 -6
- data/lib/generators/dry_crud/templates/app/views/crud/_form.html.erb +1 -1
- data/lib/generators/dry_crud/templates/app/views/crud/_form.html.haml +1 -1
- data/lib/generators/dry_crud/templates/app/views/layouts/crud.html.erb +4 -4
- data/lib/generators/dry_crud/templates/app/views/layouts/crud.html.haml +5 -5
- data/lib/generators/dry_crud/templates/spec/controllers/crud_test_models_controller_spec.rb +433 -0
- data/lib/generators/dry_crud/templates/spec/helpers/crud_helper_spec.rb +146 -0
- data/lib/generators/dry_crud/templates/spec/helpers/list_helper_spec.rb +154 -0
- data/lib/generators/dry_crud/templates/spec/helpers/standard_form_builder_spec.rb +215 -0
- data/lib/generators/dry_crud/templates/spec/helpers/standard_helper_spec.rb +387 -0
- data/lib/generators/dry_crud/templates/spec/helpers/standard_table_builder_spec.rb +120 -0
- data/lib/generators/dry_crud/templates/spec/support/crud_controller_examples.rb +244 -0
- data/lib/generators/dry_crud/templates/spec/support/crud_controller_test_helper.rb +160 -0
- data/lib/generators/dry_crud/templates/test/crud_test_model.rb +45 -18
- data/lib/generators/dry_crud/templates/test/functional/crud_controller_test_helper.rb +19 -9
- data/lib/generators/dry_crud/templates/test/functional/crud_test_models_controller_test.rb +11 -14
- data/lib/generators/dry_crud/templates/test/unit/helpers/crud_helper_test.rb +26 -13
- data/lib/generators/dry_crud/templates/test/unit/helpers/list_helper_test.rb +0 -4
- data/lib/generators/dry_crud/templates/test/unit/helpers/standard_form_builder_test.rb +6 -0
- data/lib/generators/dry_crud/templates/test/unit/helpers/standard_helper_test.rb +9 -35
- data/lib/generators/dry_crud/templates/test/unit/helpers/standard_table_builder_test.rb +5 -4
- data/test/templates/Gemfile +3 -1
- data/test/templates/app/controllers/people_controller.rb +1 -1
- data/test/templates/app/controllers/vips_controller.rb +1 -1
- data/test/templates/app/models/city.rb +1 -1
- data/test/templates/app/views/admin/cities/_form.html.erb +1 -1
- data/test/templates/app/views/admin/cities/_form.html.haml +1 -1
- data/test/templates/app/views/admin/countries/_list.html.erb +3 -4
- data/test/templates/app/views/admin/countries/_list.html.haml +3 -4
- data/test/templates/app/views/ajax/_form.html.erb +1 -1
- data/test/templates/app/views/ajax/_form.html.haml +1 -1
- data/test/templates/spec/controllers/admin/cities_controller_spec.rb +74 -0
- data/test/templates/spec/controllers/admin/countries_controller_spec.rb +56 -0
- data/test/templates/spec/controllers/people_controller_spec.rb +80 -0
- data/test/templates/spec/routing/cities_routing_spec.rb +11 -0
- data/test/templates/spec/routing/countries_routing_spec.rb +11 -0
- data/test/templates/test/functional/admin/cities_controller_test.rb +1 -1
- data/test/templates/test/functional/admin/countries_controller_test.rb +1 -1
- data/test/templates/test/functional/people_controller_test.rb +3 -3
- metadata +18 -7
@@ -0,0 +1,244 @@
|
|
1
|
+
require 'support/crud_controller_test_helper'
|
2
|
+
|
3
|
+
RSpec.configure do |c|
|
4
|
+
c.before :failing => true do
|
5
|
+
model_class.any_instance.stub(:save).and_return(false)
|
6
|
+
model_class.any_instance.stub(:destroy).and_return(false)
|
7
|
+
end
|
8
|
+
end
|
9
|
+
|
10
|
+
# A set of examples to include into the tests for your crud controller subclasses.
|
11
|
+
# Simply #let :test_entry, :new_entry_attrs and :edit_entry_attrs to test the basic
|
12
|
+
# crud functionality.
|
13
|
+
# If single examples do not match with you implementation, you may skip
|
14
|
+
# them by passing a skip parameter with context arrays:
|
15
|
+
# include_examples 'crud controller', :skip => [%w(index html sort) %w(destroy json)]
|
16
|
+
shared_examples "crud controller" do |options|
|
17
|
+
|
18
|
+
include CrudControllerTestHelper
|
19
|
+
|
20
|
+
render_views
|
21
|
+
|
22
|
+
subject { response }
|
23
|
+
|
24
|
+
let(:model_class) { controller.send(:model_class) }
|
25
|
+
let(:model_identifier) { controller.model_identifier }
|
26
|
+
let(:test_params) { scope_params }
|
27
|
+
let(:entry) { assigns(controller.send(:ivar_name, model_class)) }
|
28
|
+
let(:entries) { assigns(controller.send(:ivar_name, model_class).pluralize) }
|
29
|
+
let(:sort_column) { model_class.column_names.first }
|
30
|
+
let(:search_value) do
|
31
|
+
field = controller.search_columns.first
|
32
|
+
val = test_entry[field].to_s
|
33
|
+
val[0..((val.size + 1)/ 2)]
|
34
|
+
end
|
35
|
+
|
36
|
+
before do
|
37
|
+
m = example.metadata
|
38
|
+
perform_combined_request if m[:perform_request] != false && m[:action] && m[:method]
|
39
|
+
end
|
40
|
+
|
41
|
+
|
42
|
+
describe_action :get, :index, :unless => skip?(options, 'index') do
|
43
|
+
context ".html", :format => :html, :unless => skip?(options, %w(index html)) do
|
44
|
+
|
45
|
+
context 'plain', :unless => skip?(options, %w(index html plain)), :combine => 'ihp' do
|
46
|
+
it_should_respond
|
47
|
+
it_should_assign_entries
|
48
|
+
it_should_render
|
49
|
+
end
|
50
|
+
|
51
|
+
context "search", :if => described_class.search_columns.present?, :unless => skip?(options, %w(index html search)), :combine => 'ihse' do
|
52
|
+
let(:params) { {:q => search_value} }
|
53
|
+
|
54
|
+
it_should_respond
|
55
|
+
context "entries" do
|
56
|
+
subject { entries }
|
57
|
+
it { should include(test_entry) }
|
58
|
+
end
|
59
|
+
end
|
60
|
+
|
61
|
+
context "sort", :unless => skip?(options, %w(index html sort)) do
|
62
|
+
context "ascending", :unless => skip?(options, %w(index html sort ascending)), :combine => 'ihso' do
|
63
|
+
let(:params) { {:sort => sort_column, :sort_dir => 'asc'} }
|
64
|
+
|
65
|
+
it_should_respond
|
66
|
+
it "should have sorted entries" do
|
67
|
+
sorted = entries.sort_by(&(sort_column.to_sym))
|
68
|
+
entries.should == sorted
|
69
|
+
end
|
70
|
+
end
|
71
|
+
|
72
|
+
context "descending", :unless => skip?(options, %w(index html sort descending)), :combine => 'ihsd' do
|
73
|
+
let(:params) { {:sort => sort_column, :sort_dir => 'desc'} }
|
74
|
+
|
75
|
+
it_should_respond
|
76
|
+
it "should have sorted entries" do
|
77
|
+
sorted = entries.sort_by(&(sort_column.to_sym))
|
78
|
+
entries.should == sorted.reverse
|
79
|
+
end
|
80
|
+
end
|
81
|
+
end
|
82
|
+
end
|
83
|
+
|
84
|
+
context ".json", :format => :json, :unless => skip?(options, %w(index json)), :combine => 'ij' do
|
85
|
+
it_should_respond
|
86
|
+
it_should_assign_entries
|
87
|
+
its(:body) { should start_with('[{') }
|
88
|
+
end
|
89
|
+
end
|
90
|
+
|
91
|
+
describe_action :get, :show, :id => true, :unless => skip?(options, 'show') do
|
92
|
+
|
93
|
+
context ".html", :format => :html, :unless => skip?(options, %w(show html)) do
|
94
|
+
context "plain", :unless => skip?(options, %w(show html plain)), :combine => 'sh' do
|
95
|
+
it_should_respond
|
96
|
+
it_should_assign_entry
|
97
|
+
it_should_render
|
98
|
+
end
|
99
|
+
|
100
|
+
context "with non-existing id", :unless => skip?(options, 'show', 'html', 'with non-existing id') do
|
101
|
+
let(:params) { {:id => 9999 } }
|
102
|
+
|
103
|
+
it "should raise RecordNotFound", :perform_request => false do
|
104
|
+
expect { perform_request }.to raise_error(ActiveRecord::RecordNotFound)
|
105
|
+
end
|
106
|
+
end
|
107
|
+
end
|
108
|
+
|
109
|
+
context ".json", :format => :json, :unless => skip?(options, %w(show json)), :combine => 'sj' do
|
110
|
+
it_should_respond
|
111
|
+
it_should_assign_entry
|
112
|
+
its(:body) { should start_with('{') }
|
113
|
+
end
|
114
|
+
end
|
115
|
+
|
116
|
+
describe_action :get, :new, :unless => skip?(options, %w(new)) do
|
117
|
+
context "plain", :unless => skip?(options, %w(new plain)), :combine => 'new' do
|
118
|
+
it_should_respond
|
119
|
+
it_should_render
|
120
|
+
it_should_persist_entry(false)
|
121
|
+
end
|
122
|
+
|
123
|
+
context "with params", :unless => skip?(options, 'new', 'with params') do
|
124
|
+
let(:params) { { model_identifier => new_entry_attrs } }
|
125
|
+
it_should_set_attrs(:new)
|
126
|
+
end
|
127
|
+
end
|
128
|
+
|
129
|
+
describe_action :post, :create, :unless => skip?(options, %w(create)) do
|
130
|
+
let(:params) { { model_identifier => new_entry_attrs } }
|
131
|
+
|
132
|
+
it "should add entry to database", :perform_request => false do
|
133
|
+
expect { perform_request }.to change { model_class.count }.by(1)
|
134
|
+
end
|
135
|
+
|
136
|
+
context "html", :format => :html, :unless => skip?(options, %w(create html)) do
|
137
|
+
context "with valid params", :unless => skip?(options, %w(create html valid)), :combine => 'ch' do
|
138
|
+
it_should_redirect_to_show
|
139
|
+
it_should_set_attrs(:new)
|
140
|
+
it_should_persist_entry
|
141
|
+
it_should_have_flash(:notice)
|
142
|
+
end
|
143
|
+
|
144
|
+
context "with invalid params", :failing => true, :unless => skip?(options, %w(create html invalid)), :combine => 'chi' do
|
145
|
+
it_should_render('new')
|
146
|
+
it_should_persist_entry(false)
|
147
|
+
it_should_set_attrs(:new)
|
148
|
+
it_should_not_have_flash(:notice)
|
149
|
+
end
|
150
|
+
end
|
151
|
+
|
152
|
+
context "json", :format => :json, :unless => skip?(options, %w(create json)) do
|
153
|
+
context "with valid params", :unless => skip?(options, %w(create json valid)), :combine => 'cjv' do
|
154
|
+
it_should_respond(201)
|
155
|
+
it_should_set_attrs(:new)
|
156
|
+
its(:body) { should start_with('{') }
|
157
|
+
it_should_persist_entry
|
158
|
+
end
|
159
|
+
|
160
|
+
context "with invalid params", :failing => true, :unless => skip?(options, %w(create json invalid)), :combine => 'cji' do
|
161
|
+
it_should_respond(422)
|
162
|
+
it_should_set_attrs(:new)
|
163
|
+
its(:body) { should match(/"errors":\{/) }
|
164
|
+
it_should_persist_entry(false)
|
165
|
+
end
|
166
|
+
end
|
167
|
+
end
|
168
|
+
|
169
|
+
describe_action :get, :edit, :id => true, :unless => skip?(options, %w(edit)), :combine => 'edit' do
|
170
|
+
it_should_respond
|
171
|
+
it_should_render
|
172
|
+
it_should_assign_entry
|
173
|
+
end
|
174
|
+
|
175
|
+
describe_action :put, :update, :id => true, :unless => skip?(options, %w(update)) do
|
176
|
+
let(:params) { {model_identifier => edit_entry_attrs} }
|
177
|
+
|
178
|
+
it "should update entry in database", :perform_request => false do
|
179
|
+
expect { perform_request }.to change { model_class.count }.by(0)
|
180
|
+
end
|
181
|
+
|
182
|
+
context ".html", :format => :html, :unless => skip?(options, %w(update html)) do
|
183
|
+
context "with valid params", :unless => skip?(options, %w(update html valid)), :combine => 'uhv' do
|
184
|
+
it_should_set_attrs(:edit)
|
185
|
+
it_should_redirect_to_show
|
186
|
+
it_should_persist_entry
|
187
|
+
it_should_have_flash(:notice)
|
188
|
+
end
|
189
|
+
|
190
|
+
context "with invalid params", :failing => true, :unless => skip?(options, %w(update html invalid)), :combine => 'uhi' do
|
191
|
+
it_should_render('edit')
|
192
|
+
it_should_set_attrs(:edit)
|
193
|
+
it_should_not_have_flash(:notice)
|
194
|
+
end
|
195
|
+
end
|
196
|
+
|
197
|
+
context ".json", :format => :json, :unless => skip?(options, %w(udpate json)) do
|
198
|
+
context "with valid params", :unless => skip?(options, %w(udpate json valid)), :combine => 'ujv' do
|
199
|
+
it_should_respond(204)
|
200
|
+
it_should_set_attrs(:edit)
|
201
|
+
its(:body) { should match(/s*/) }
|
202
|
+
it_should_persist_entry
|
203
|
+
end
|
204
|
+
|
205
|
+
context "with invalid params", :failing => true, :unless => skip?(options, %w(update json invalid)), :combine => 'uji' do
|
206
|
+
it_should_respond(422)
|
207
|
+
it_should_set_attrs(:edit)
|
208
|
+
its(:body) { should match(/"errors":\{/) }
|
209
|
+
end
|
210
|
+
end
|
211
|
+
end
|
212
|
+
|
213
|
+
describe_action :delete, :destroy, :id => true, :unless => skip?(options, %w(destroy)) do
|
214
|
+
|
215
|
+
it "should remove entry from database", :perform_request => false do
|
216
|
+
expect { perform_request }.to change { model_class.count }.by(-1)
|
217
|
+
end
|
218
|
+
|
219
|
+
context ".html", :format => :html, :unless => skip?(options, %w(destroy html)) do
|
220
|
+
context "successfull", :combine => 'dhs' do
|
221
|
+
it_should_redirect_to_index
|
222
|
+
it_should_have_flash(:notice)
|
223
|
+
end
|
224
|
+
|
225
|
+
context "with failure", :failing => true, :combine => 'dhf' do
|
226
|
+
it_should_redirect_to_index
|
227
|
+
it_should_have_flash(:alert)
|
228
|
+
end
|
229
|
+
end
|
230
|
+
|
231
|
+
context ".json", :format => :json, :unless => skip?(options, %w(destroy json)) do
|
232
|
+
context "successfull", :combine => 'djs' do
|
233
|
+
it_should_respond(204)
|
234
|
+
its(:body) { should match(/s*/) }
|
235
|
+
end
|
236
|
+
|
237
|
+
context "with failure", :failing => true, :combine => 'djf' do
|
238
|
+
it_should_respond(422)
|
239
|
+
its(:body) { should match(/"errors":\{/) }
|
240
|
+
end
|
241
|
+
end
|
242
|
+
end
|
243
|
+
|
244
|
+
end
|
@@ -0,0 +1,160 @@
|
|
1
|
+
# Contains assertions for testing common crud controller use cases.
|
2
|
+
# See crud_controller_examples for use cases.
|
3
|
+
module CrudControllerTestHelper
|
4
|
+
extend ActiveSupport::Concern
|
5
|
+
|
6
|
+
# Performs a request based on the metadata of the action example under test.
|
7
|
+
def perform_request
|
8
|
+
m = example.metadata
|
9
|
+
example_params = respond_to?(:params) ? send(:params) : {}
|
10
|
+
params = scope_params.merge(:format => m[:format])
|
11
|
+
params.merge!(:id => test_entry.id) if m[:id]
|
12
|
+
params.merge!(example_params)
|
13
|
+
send(m[:method], m[:action], params)
|
14
|
+
end
|
15
|
+
|
16
|
+
# If a combine key is given in metadata, only the first request for all examples
|
17
|
+
# with the same key will be performed.
|
18
|
+
def perform_combined_request
|
19
|
+
if stack = example.metadata[:combine]
|
20
|
+
@@current_stack ||= nil
|
21
|
+
if stack == @@current_stack && described_class == @@current_controller.class
|
22
|
+
@response = @@current_response
|
23
|
+
@templates = @@current_templates
|
24
|
+
@controller = @@current_controller
|
25
|
+
@request = @@current_request
|
26
|
+
else
|
27
|
+
perform_request
|
28
|
+
|
29
|
+
@@current_stack = stack
|
30
|
+
@@current_response = @response
|
31
|
+
@@current_request = @request
|
32
|
+
@@current_controller = @controller
|
33
|
+
@@current_templates = @templates
|
34
|
+
end
|
35
|
+
else
|
36
|
+
perform_request
|
37
|
+
end
|
38
|
+
end
|
39
|
+
|
40
|
+
# The params defining the nesting of the test entry.
|
41
|
+
def scope_params
|
42
|
+
params = {}
|
43
|
+
# for nested controllers, add parent ids to each request
|
44
|
+
Array(controller.nesting).reverse.inject(test_entry) do |parent, p|
|
45
|
+
if p.is_a?(Class) && p < ActiveRecord::Base
|
46
|
+
assoc = p.name.underscore
|
47
|
+
params["#{assoc}_id"] = parent.send(:"#{assoc}_id")
|
48
|
+
parent.send(assoc)
|
49
|
+
else
|
50
|
+
parent
|
51
|
+
end
|
52
|
+
end
|
53
|
+
params
|
54
|
+
end
|
55
|
+
|
56
|
+
module ClassMethods
|
57
|
+
|
58
|
+
# Describe a certain action and provide some usefull metadata.
|
59
|
+
# Tests whether this action is configured to be skipped.
|
60
|
+
def describe_action(method, action, metadata = {}, &block)
|
61
|
+
describe("#{method.to_s.upcase} #{action}",
|
62
|
+
{:if => described_class.instance_methods.collect(&:to_s).include?(action.to_s),
|
63
|
+
:method => method,
|
64
|
+
:action => action}.
|
65
|
+
merge(metadata),
|
66
|
+
&block)
|
67
|
+
end
|
68
|
+
|
69
|
+
def skip?(options, *contexts)
|
70
|
+
options ||= {}
|
71
|
+
contexts = Array(contexts).flatten
|
72
|
+
skips = Array(options[:skip])
|
73
|
+
skips = [skips] if skips.blank? || !skips.first.is_a?(Array)
|
74
|
+
|
75
|
+
skips.flatten.present? &&
|
76
|
+
skips.any? { |skip| skip == contexts.take(skip.size) }
|
77
|
+
end
|
78
|
+
|
79
|
+
# Test the response status, default 200.
|
80
|
+
def it_should_respond(status = 200)
|
81
|
+
its(:status) { should == status }
|
82
|
+
end
|
83
|
+
|
84
|
+
# Test that entries are assigned.
|
85
|
+
def it_should_assign_entries
|
86
|
+
it "should assign entries" do
|
87
|
+
entries.should be_present
|
88
|
+
end
|
89
|
+
end
|
90
|
+
|
91
|
+
# Test that entry is assigned.
|
92
|
+
def it_should_assign_entry
|
93
|
+
it "should assign entry" do
|
94
|
+
entry.should == test_entry
|
95
|
+
end
|
96
|
+
end
|
97
|
+
|
98
|
+
# Test that the given template or the main template of the action under test is rendered.
|
99
|
+
def it_should_render(template = nil)
|
100
|
+
it { should render_template(template || example.metadata[:action]) }
|
101
|
+
end
|
102
|
+
|
103
|
+
# Test that test_entry_attrs are set on entry.
|
104
|
+
def it_should_set_attrs(action = nil)
|
105
|
+
it "should set params as entry attributes" do
|
106
|
+
attrs = send("#{action}_entry_attrs")
|
107
|
+
actual = {}
|
108
|
+
attrs.keys.each do |key|
|
109
|
+
actual[key] = entry.attributes[key.to_s]
|
110
|
+
end
|
111
|
+
actual.should == attrs
|
112
|
+
end
|
113
|
+
end
|
114
|
+
|
115
|
+
# Test that the response redirects to the index action.
|
116
|
+
def it_should_redirect_to_index
|
117
|
+
it { should redirect_to scope_params.merge(:action => 'index', :returning => true) }
|
118
|
+
end
|
119
|
+
|
120
|
+
# Test that the response redirects to the show action of the current entry.
|
121
|
+
def it_should_redirect_to_show
|
122
|
+
it { should redirect_to scope_params.merge(:action => 'show', :id => entry.id) }
|
123
|
+
end
|
124
|
+
|
125
|
+
# Test that the given flash type is present.
|
126
|
+
def it_should_have_flash(type, message = nil)
|
127
|
+
context "flash" do
|
128
|
+
subject { flash }
|
129
|
+
|
130
|
+
its([type]) do
|
131
|
+
should(message ? match(message) : be_present)
|
132
|
+
end
|
133
|
+
end
|
134
|
+
end
|
135
|
+
|
136
|
+
# Test that not flash of the given type is present.
|
137
|
+
def it_should_not_have_flash(type)
|
138
|
+
context "flash" do
|
139
|
+
subject { flash }
|
140
|
+
its([type]) { should be_blank }
|
141
|
+
end
|
142
|
+
end
|
143
|
+
|
144
|
+
# Test that the current entry is persistend and valid, or not.
|
145
|
+
def it_should_persist_entry(bool = true)
|
146
|
+
context "entry" do
|
147
|
+
subject { entry }
|
148
|
+
|
149
|
+
if bool
|
150
|
+
it { should be_persisted }
|
151
|
+
it { should be_valid }
|
152
|
+
else
|
153
|
+
it { should_not be_persisted }
|
154
|
+
end
|
155
|
+
end
|
156
|
+
end
|
157
|
+
end
|
158
|
+
|
159
|
+
end
|
160
|
+
|
@@ -1,8 +1,8 @@
|
|
1
1
|
# A dummy model used for general testing.
|
2
2
|
class CrudTestModel < ActiveRecord::Base #:nodoc:
|
3
3
|
|
4
|
-
|
5
|
-
|
4
|
+
attr_accessible :name, :whatever, :children, :rating, :income, :birthdate, :gets_up_at, :last_seen, :human, :remarks
|
5
|
+
|
6
6
|
belongs_to :companion, :class_name => 'CrudTestModel'
|
7
7
|
has_and_belongs_to_many :others, :class_name => 'OtherCrudTestModel'
|
8
8
|
has_many :mores, :class_name => 'OtherCrudTestModel', :foreign_key => :more_id
|
@@ -86,7 +86,7 @@ class CrudTestModelsController < CrudController #:nodoc:
|
|
86
86
|
end
|
87
87
|
end
|
88
88
|
|
89
|
-
|
89
|
+
private
|
90
90
|
|
91
91
|
def list_entries
|
92
92
|
entries = super
|
@@ -98,6 +98,12 @@ class CrudTestModelsController < CrudController #:nodoc:
|
|
98
98
|
|
99
99
|
private
|
100
100
|
|
101
|
+
def build_entry
|
102
|
+
entry = super
|
103
|
+
entry.companion_id = model_params.delete(:companion_id) if model_params
|
104
|
+
entry
|
105
|
+
end
|
106
|
+
|
101
107
|
# custom callback
|
102
108
|
def handle_name
|
103
109
|
if entry.name == 'illegal'
|
@@ -106,6 +112,17 @@ class CrudTestModelsController < CrudController #:nodoc:
|
|
106
112
|
end
|
107
113
|
end
|
108
114
|
|
115
|
+
# callback to redirect if @should_redirect is set
|
116
|
+
def possibly_redirect
|
117
|
+
redirect_to :action => 'index' if should_redirect && !performed?
|
118
|
+
!should_redirect
|
119
|
+
end
|
120
|
+
|
121
|
+
def set_companions
|
122
|
+
@companions = CrudTestModel.all :conditions => {:human => true}
|
123
|
+
end
|
124
|
+
|
125
|
+
|
109
126
|
# create callback methods that record the before/after callbacks
|
110
127
|
[:create, :update, :save, :destroy].each do |a|
|
111
128
|
callback = "before_#{a.to_s}"
|
@@ -125,16 +142,6 @@ class CrudTestModelsController < CrudController #:nodoc:
|
|
125
142
|
called_callback(sym.to_s[HANDLE_PREFIX.size..-1].to_sym) if sym.to_s.starts_with?(HANDLE_PREFIX)
|
126
143
|
end
|
127
144
|
|
128
|
-
# callback to redirect if @should_redirect is set
|
129
|
-
def possibly_redirect
|
130
|
-
redirect_to :action => 'index' if should_redirect && !performed?
|
131
|
-
!should_redirect
|
132
|
-
end
|
133
|
-
|
134
|
-
def set_companions
|
135
|
-
@companions = CrudTestModel.all :conditions => {:human => true}
|
136
|
-
end
|
137
|
-
|
138
145
|
# records a callback
|
139
146
|
def called_callback(callback)
|
140
147
|
@called_callbacks ||= []
|
@@ -142,7 +149,14 @@ class CrudTestModelsController < CrudController #:nodoc:
|
|
142
149
|
end
|
143
150
|
|
144
151
|
end
|
145
|
-
|
152
|
+
|
153
|
+
#:nodoc:
|
154
|
+
REGEXP_ROWS = /<tr.+?<\/tr>/m #:nodoc:
|
155
|
+
REGEXP_HEADERS = /<th.+?<\/th>/m #:nodoc:
|
156
|
+
REGEXP_SORT_HEADERS = /<th><a .*?sort_dir=asc.*?>.*?<\/a><\/th>/m #:nodoc:
|
157
|
+
REGEXP_ACTION_CELL = /<td class=\"action\"><a href.+?<\/a><\/td>/m #:nodoc:
|
158
|
+
|
159
|
+
|
146
160
|
# A simple test helper to prepare the test database with a CrudTestModel model.
|
147
161
|
# This helper is used to test the CrudController and various helpers
|
148
162
|
# without the need for an application based model.
|
@@ -178,7 +192,7 @@ module CrudTestHelper
|
|
178
192
|
ERB::Util.h(text)
|
179
193
|
end
|
180
194
|
|
181
|
-
|
195
|
+
private
|
182
196
|
|
183
197
|
# Sets up the test database with a crud_test_models table.
|
184
198
|
# Look at the source to view the column definition.
|
@@ -245,13 +259,23 @@ module CrudTestHelper
|
|
245
259
|
end
|
246
260
|
end
|
247
261
|
|
248
|
-
|
262
|
+
def special_routing
|
263
|
+
controller = @controller || controller # test:unit uses instance variable, rspec the method
|
264
|
+
@routes = ActionDispatch::Routing::RouteSet.new
|
265
|
+
_routes = @routes
|
266
|
+
|
267
|
+
controller.singleton_class.send(:include, _routes.url_helpers)
|
268
|
+
controller.view_context_class = Class.new(controller.view_context_class) do
|
269
|
+
include _routes.url_helpers
|
270
|
+
end
|
271
|
+
|
272
|
+
@routes.draw { resources :crud_test_models }
|
273
|
+
end
|
249
274
|
|
250
275
|
def create(index, companion)
|
251
276
|
c = str(index)
|
252
|
-
CrudTestModel.
|
277
|
+
m = CrudTestModel.new(:name => c,
|
253
278
|
:children => 10 - index,
|
254
|
-
:companion => companion,
|
255
279
|
:rating => "#{index}.#{index}".to_f,
|
256
280
|
:income => 10000000 * index + 0.1 * index,
|
257
281
|
:birthdate => "#{1900 + 10 * index}-#{index}-#{index}",
|
@@ -262,6 +286,9 @@ module CrudTestHelper
|
|
262
286
|
:last_seen => "#{2000 + 10 * index}-#{index}-#{index} 1#{index}:2#{index}",
|
263
287
|
:human => index % 2 == 0,
|
264
288
|
:remarks => "#{c} #{str(index + 1)} #{str(index + 2)}\n" * (index % 3 + 1))
|
289
|
+
m.companion = companion
|
290
|
+
m.save!
|
291
|
+
m
|
265
292
|
end
|
266
293
|
|
267
294
|
def create_other(index)
|
@@ -76,16 +76,16 @@ module CrudControllerTestHelper
|
|
76
76
|
|
77
77
|
def test_create
|
78
78
|
assert_difference("#{model_class.name}.count") do
|
79
|
-
post :create, test_params(model_identifier =>
|
79
|
+
post :create, test_params(model_identifier => new_entry_attrs)
|
80
80
|
end
|
81
81
|
assert_redirected_to_show entry
|
82
82
|
assert ! entry.new_record?
|
83
|
-
|
83
|
+
assert_attrs_equal(new_entry_attrs)
|
84
84
|
end
|
85
85
|
|
86
86
|
def test_create_json
|
87
87
|
assert_difference("#{model_class.name}.count") do
|
88
|
-
post :create, test_params(model_identifier =>
|
88
|
+
post :create, test_params(model_identifier => new_entry_attrs, :format => 'json')
|
89
89
|
end
|
90
90
|
assert_response :success
|
91
91
|
assert @response.body.starts_with?("{")
|
@@ -100,15 +100,15 @@ module CrudControllerTestHelper
|
|
100
100
|
|
101
101
|
def test_update
|
102
102
|
assert_no_difference("#{model_class.name}.count") do
|
103
|
-
put :update, test_params(:id => test_entry.id, model_identifier =>
|
103
|
+
put :update, test_params(:id => test_entry.id, model_identifier => edit_entry_attrs)
|
104
104
|
end
|
105
|
-
|
105
|
+
assert_attrs_equal(edit_entry_attrs)
|
106
106
|
assert_redirected_to_show entry
|
107
107
|
end
|
108
108
|
|
109
109
|
def test_update_json
|
110
110
|
assert_no_difference("#{model_class.name}.count") do
|
111
|
-
put :update, test_params(:id => test_entry.id, model_identifier =>
|
111
|
+
put :update, test_params(:id => test_entry.id, model_identifier => edit_entry_attrs, :format => 'json')
|
112
112
|
end
|
113
113
|
assert_response :success
|
114
114
|
assert_equal "", @response.body.strip
|
@@ -129,7 +129,7 @@ module CrudControllerTestHelper
|
|
129
129
|
assert_equal "", @response.body.strip
|
130
130
|
end
|
131
131
|
|
132
|
-
|
132
|
+
private
|
133
133
|
|
134
134
|
def assert_redirected_to_index
|
135
135
|
assert_redirected_to test_params(:action => 'index', :returning => true)
|
@@ -139,8 +139,8 @@ module CrudControllerTestHelper
|
|
139
139
|
assert_redirected_to test_params(:action => 'show', :id => entry.id)
|
140
140
|
end
|
141
141
|
|
142
|
-
def
|
143
|
-
|
142
|
+
def assert_attrs_equal(attrs)
|
143
|
+
attrs.each do |key, value|
|
144
144
|
actual = entry.send(key)
|
145
145
|
assert_equal value, actual, "#{key} is expected to be <#{value.inspect}>, got <#{actual.inspect}>"
|
146
146
|
end
|
@@ -175,6 +175,16 @@ module CrudControllerTestHelper
|
|
175
175
|
def test_entry_attrs
|
176
176
|
raise "Implement this method in your test class"
|
177
177
|
end
|
178
|
+
|
179
|
+
# Attribute hash used in edit/update tests.
|
180
|
+
def edit_entry_attrs
|
181
|
+
test_entry_attrs
|
182
|
+
end
|
183
|
+
|
184
|
+
# Attribute hash used in new/create tests.
|
185
|
+
def new_entry_attrs
|
186
|
+
test_entry_attrs
|
187
|
+
end
|
178
188
|
|
179
189
|
# The params to pass to an action, including required nesting params.
|
180
190
|
def test_params(params = {})
|
@@ -278,25 +278,13 @@ class CrudTestModelsControllerTest < ActionController::TestCase
|
|
278
278
|
assert_equal 'Crud Test Model', @controller.models_label(false)
|
279
279
|
end
|
280
280
|
|
281
|
-
|
282
|
-
|
283
|
-
def special_routing
|
284
|
-
@routes = ActionDispatch::Routing::RouteSet.new
|
285
|
-
_routes = @routes
|
286
|
-
|
287
|
-
@controller.singleton_class.send(:include, _routes.url_helpers)
|
288
|
-
@controller.view_context_class = Class.new(@controller.view_context_class) do
|
289
|
-
include _routes.url_helpers
|
290
|
-
end
|
291
|
-
|
292
|
-
@routes.draw { resources :crud_test_models }
|
293
|
-
end
|
281
|
+
private
|
294
282
|
|
295
283
|
def test_entry
|
296
284
|
crud_test_models(:AAAAA)
|
297
285
|
end
|
298
286
|
|
299
|
-
def
|
287
|
+
def new_entry_attrs
|
300
288
|
{:name => 'foo',
|
301
289
|
:children => 42,
|
302
290
|
:companion_id => 3,
|
@@ -307,4 +295,13 @@ class CrudTestModelsControllerTest < ActionController::TestCase
|
|
307
295
|
:remarks => "some custom\n\tremarks"}
|
308
296
|
end
|
309
297
|
|
298
|
+
def edit_entry_attrs
|
299
|
+
{:name => 'foo',
|
300
|
+
:children => 42,
|
301
|
+
:rating => 8.5,
|
302
|
+
:income => 2.42,
|
303
|
+
:birthdate => '31-12-1999'.to_date,
|
304
|
+
:human => true,
|
305
|
+
:remarks => "some custom\n\tremarks"}
|
306
|
+
end
|
310
307
|
end
|