dry_crud 1.6.0 → 1.7.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.
Files changed (49) hide show
  1. data/README.rdoc +25 -10
  2. data/Rakefile +30 -8
  3. data/VERSION +1 -1
  4. data/lib/generators/dry_crud/dry_crud_generator.rb +15 -2
  5. data/lib/generators/dry_crud/templates/app/controllers/crud_controller.rb +18 -10
  6. data/lib/generators/dry_crud/templates/app/controllers/list_controller.rb +14 -11
  7. data/lib/generators/dry_crud/templates/app/helpers/crud_helper.rb +71 -29
  8. data/lib/generators/dry_crud/templates/app/helpers/standard_form_builder.rb +40 -3
  9. data/lib/generators/dry_crud/templates/app/helpers/standard_helper.rb +8 -27
  10. data/lib/generators/dry_crud/templates/app/helpers/standard_table_builder.rb +13 -6
  11. data/lib/generators/dry_crud/templates/app/views/crud/_form.html.erb +1 -1
  12. data/lib/generators/dry_crud/templates/app/views/crud/_form.html.haml +1 -1
  13. data/lib/generators/dry_crud/templates/app/views/layouts/crud.html.erb +4 -4
  14. data/lib/generators/dry_crud/templates/app/views/layouts/crud.html.haml +5 -5
  15. data/lib/generators/dry_crud/templates/spec/controllers/crud_test_models_controller_spec.rb +433 -0
  16. data/lib/generators/dry_crud/templates/spec/helpers/crud_helper_spec.rb +146 -0
  17. data/lib/generators/dry_crud/templates/spec/helpers/list_helper_spec.rb +154 -0
  18. data/lib/generators/dry_crud/templates/spec/helpers/standard_form_builder_spec.rb +215 -0
  19. data/lib/generators/dry_crud/templates/spec/helpers/standard_helper_spec.rb +387 -0
  20. data/lib/generators/dry_crud/templates/spec/helpers/standard_table_builder_spec.rb +120 -0
  21. data/lib/generators/dry_crud/templates/spec/support/crud_controller_examples.rb +244 -0
  22. data/lib/generators/dry_crud/templates/spec/support/crud_controller_test_helper.rb +160 -0
  23. data/lib/generators/dry_crud/templates/test/crud_test_model.rb +45 -18
  24. data/lib/generators/dry_crud/templates/test/functional/crud_controller_test_helper.rb +19 -9
  25. data/lib/generators/dry_crud/templates/test/functional/crud_test_models_controller_test.rb +11 -14
  26. data/lib/generators/dry_crud/templates/test/unit/helpers/crud_helper_test.rb +26 -13
  27. data/lib/generators/dry_crud/templates/test/unit/helpers/list_helper_test.rb +0 -4
  28. data/lib/generators/dry_crud/templates/test/unit/helpers/standard_form_builder_test.rb +6 -0
  29. data/lib/generators/dry_crud/templates/test/unit/helpers/standard_helper_test.rb +9 -35
  30. data/lib/generators/dry_crud/templates/test/unit/helpers/standard_table_builder_test.rb +5 -4
  31. data/test/templates/Gemfile +3 -1
  32. data/test/templates/app/controllers/people_controller.rb +1 -1
  33. data/test/templates/app/controllers/vips_controller.rb +1 -1
  34. data/test/templates/app/models/city.rb +1 -1
  35. data/test/templates/app/views/admin/cities/_form.html.erb +1 -1
  36. data/test/templates/app/views/admin/cities/_form.html.haml +1 -1
  37. data/test/templates/app/views/admin/countries/_list.html.erb +3 -4
  38. data/test/templates/app/views/admin/countries/_list.html.haml +3 -4
  39. data/test/templates/app/views/ajax/_form.html.erb +1 -1
  40. data/test/templates/app/views/ajax/_form.html.haml +1 -1
  41. data/test/templates/spec/controllers/admin/cities_controller_spec.rb +74 -0
  42. data/test/templates/spec/controllers/admin/countries_controller_spec.rb +56 -0
  43. data/test/templates/spec/controllers/people_controller_spec.rb +80 -0
  44. data/test/templates/spec/routing/cities_routing_spec.rb +11 -0
  45. data/test/templates/spec/routing/countries_routing_spec.rb +11 -0
  46. data/test/templates/test/functional/admin/cities_controller_test.rb +1 -1
  47. data/test/templates/test/functional/admin/countries_controller_test.rb +1 -1
  48. data/test/templates/test/functional/people_controller_test.rb +3 -3
  49. metadata +18 -7
@@ -0,0 +1,387 @@
1
+ require 'spec_helper'
2
+
3
+ describe StandardHelper do
4
+
5
+ include CrudTestHelper
6
+
7
+ before(:all) do
8
+ reset_db
9
+ setup_db
10
+ create_test_data
11
+ end
12
+
13
+ after(:all) { reset_db }
14
+
15
+ # define some test format_ methods
16
+ def format_size(obj) #:nodoc:
17
+ "#{f(obj.size)} items"
18
+ end
19
+
20
+ def format_string_size(obj) #:nodoc:
21
+ "#{f(obj.size)} chars"
22
+ end
23
+
24
+ describe "#labeled" do
25
+ context "regular" do
26
+ subject { labeled('label') { 'value' } }
27
+
28
+ it { should be_html_safe }
29
+ it { assert_dom_equal '<div class="labeled"> <label>label</label> <div class="value">value</div> </div>', subject.squish }
30
+ end
31
+
32
+ context "with empty value" do
33
+ subject { labeled('label') { '' } }
34
+
35
+ it { should be_html_safe }
36
+ it { assert_dom_equal '<div class="labeled"> <label>label</label> <div class="value">'+StandardHelper::EMPTY_STRING+'</div> </div>', subject.squish }
37
+ end
38
+
39
+ context "with unsafe value" do
40
+ subject { labeled('label') { 'value <unsafe>' } }
41
+
42
+ it { should be_html_safe }
43
+ it { assert_dom_equal '<div class="labeled"> <label>label</label> <div class="value">value &lt;unsafe&gt;</div> </div>', subject.squish }
44
+ end
45
+ end
46
+
47
+ describe "#labeled_attr" do
48
+ subject { labeled_attr('foo', :size) }
49
+
50
+ it { should be_html_safe }
51
+ it { assert_dom_equal '<div class="labeled"> <label>Size</label> <div class="value">3 chars</div> </div>', subject.squish }
52
+ end
53
+
54
+ describe "#f" do
55
+
56
+ context "Fixnums" do
57
+ it "should print small values unchanged" do
58
+ f(10).should == '10'
59
+ end
60
+
61
+ it "should print large values with delimiters" do
62
+ f(10000000).should == '10,000,000'
63
+ end
64
+ end
65
+
66
+ context "Floats" do
67
+ it "should add two digits" do
68
+ f(1.0).should == '1.000'
69
+ end
70
+
71
+ it "should truncate to two digits" do
72
+ f(3.14159).should == '3.142'
73
+ end
74
+
75
+ it "should add delimiters" do
76
+ f(12345.6789).should == '12,345.679'
77
+ end
78
+ end
79
+
80
+ context "Booleans" do
81
+ it "true should print yes" do
82
+ f(true).should == 'yes'
83
+ end
84
+
85
+ it "false should print no" do
86
+ f(false).should == 'no'
87
+ end
88
+ end
89
+
90
+ context "nil" do
91
+ it "should print an empty string" do
92
+ f(nil).should == StandardHelper::EMPTY_STRING
93
+ end
94
+ end
95
+
96
+ context "Strings" do
97
+ it "should print regular strings unchanged" do
98
+ f('blah blah').should == 'blah blah'
99
+ end
100
+
101
+ it "should not be html safe" do
102
+ f('<injection>').should_not be_html_safe
103
+ end
104
+ end
105
+
106
+ end
107
+
108
+ describe "#format_attr" do
109
+ it "should use #f" do
110
+ format_attr("12.342", :to_f).should == f(12.342)
111
+ end
112
+
113
+ it "should use object attr format method if it exists" do
114
+ format_attr("abcd", :size).should == '4 chars'
115
+ end
116
+
117
+ it "should use general attr format method if it exists" do
118
+ format_attr([1,2], :size).should == '2 items'
119
+ end
120
+
121
+ it "should format empty belongs_to" do
122
+ format_attr(crud_test_models(:AAAAA), :companion).should == t(:'global.associations.no_entry')
123
+ end
124
+
125
+ it "should format existing belongs_to" do
126
+ string = format_attr(crud_test_models(:BBBBB), :companion)
127
+ string.should == "AAAAA"
128
+ end
129
+
130
+ it "should format existing has_many" do
131
+ string = format_attr(crud_test_models(:CCCCC), :others)
132
+ string.should be_html_safe
133
+ string.should == "<ul><li>AAAAA</li><li>BBBBB</li></ul>"
134
+ end
135
+ end
136
+
137
+ describe "#column_type" do
138
+ let(:model) { crud_test_models(:AAAAA) }
139
+
140
+ it "should recognize types" do
141
+ column_type(model, :name).should == :string
142
+ column_type(model, :children).should == :integer
143
+ column_type(model, :companion_id).should == :integer
144
+ column_type(model, :rating).should == :float
145
+ column_type(model, :income).should == :decimal
146
+ column_type(model, :birthdate).should == :date
147
+ column_type(model, :gets_up_at).should == :time
148
+ column_type(model, :last_seen).should == :datetime
149
+ column_type(model, :human).should == :boolean
150
+ column_type(model, :remarks).should == :text
151
+ column_type(model, :companion).should be_nil
152
+ end
153
+ end
154
+
155
+ describe "#format_type" do
156
+ let(:model) { crud_test_models(:AAAAA) }
157
+
158
+ it "should format integers" do
159
+ model.children = 10000
160
+ format_type(model, :children).should == '10,000'
161
+ end
162
+
163
+ it "should format floats" do
164
+ format_type(model, :rating).should == '1.100'
165
+ end
166
+
167
+ it "should format decimals" do
168
+ format_type(model, :income).should == '10,000,000.100'
169
+ end
170
+
171
+ it "should format dates" do
172
+ format_type(model, :birthdate).should == '1910-01-01'
173
+ end
174
+
175
+ it "should format times" do
176
+ format_type(model, :gets_up_at).should == '01:01'
177
+ end
178
+
179
+ it "should format datetimes" do
180
+ format_type(model, :last_seen).should == '2010-01-01 11:21'
181
+ end
182
+
183
+ it "should format texts" do
184
+ string = format_type(model, :remarks)
185
+ string.should be_html_safe
186
+ string.should == "<p>AAAAA BBBBB CCCCC\n<br />AAAAA BBBBB CCCCC\n</p>"
187
+ end
188
+
189
+ it "should escape texts" do
190
+ model.remarks = "<unsecure>bla"
191
+ string = format_type(model, :remarks)
192
+ string.should be_html_safe
193
+ string.should == "<p>&lt;unsecure&gt;bla</p>"
194
+ end
195
+
196
+ it "should format empty texts" do
197
+ model.remarks = " "
198
+ string = format_type(model, :remarks)
199
+ string.should be_html_safe
200
+ string.should == StandardHelper::EMPTY_STRING
201
+ end
202
+ end
203
+
204
+ describe "#content_tag_nested" do
205
+
206
+ it "should escape safe content" do
207
+ html = content_tag_nested(:div, ['a', 'b']) { |e| content_tag(:span, e) }
208
+ html.should be_html_safe
209
+ html.should == "<div><span>a</span><span>b</span></div>"
210
+ end
211
+
212
+ it "should escape unsafe content" do
213
+ html = content_tag_nested(:div, ['a', 'b']) { |e| "<#{e}>" }
214
+ html.should == "<div>&lt;a&gt;&lt;b&gt;</div>"
215
+ end
216
+
217
+ it "should simply join without block" do
218
+ html = content_tag_nested(:div, ['a', 'b'])
219
+ html.should == "<div>ab</div>"
220
+ end
221
+ end
222
+
223
+ describe "#safe_join" do
224
+ it "should works as super without block" do
225
+ html = safe_join(['<a>', '<b>'.html_safe])
226
+ html.should == "&lt;a&gt;<b>"
227
+ end
228
+
229
+ it "should collect contents for array" do
230
+ html = safe_join(['a', 'b']) { |e| content_tag(:span, e) }
231
+ html.should == "<span>a</span><span>b</span>"
232
+ end
233
+ end
234
+
235
+ describe "#captionize" do
236
+ it "should handle symbols" do
237
+ captionize(:camel_case).should == 'Camel Case'
238
+ end
239
+
240
+ it "should render all upper case" do
241
+ captionize('all upper case').should == 'All Upper Case'
242
+ end
243
+
244
+ it "should render human attribute name" do
245
+ captionize(:gets_up_at, CrudTestModel).should == 'Gets up at'
246
+ end
247
+ end
248
+
249
+ describe "#table" do
250
+ context "with empty data" do
251
+ subject { table([]) }
252
+
253
+ it { should be_html_safe }
254
+
255
+ it "should handle empty data" do
256
+ should match(/No entries/)
257
+ end
258
+ end
259
+
260
+ context "with data" do
261
+ subject { table(['foo', 'bar'], :size) {|t| t.attrs :upcase } }
262
+
263
+ it { should be_html_safe }
264
+
265
+ it "should render table" do
266
+ should match(/^\<table.*\<\/table\>$/)
267
+ end
268
+
269
+ it "should contain attrs" do
270
+ should match(/<th>Size<\/th>/)
271
+ end
272
+
273
+ it "should contain block" do
274
+ should match(/<th>Upcase<\/th>/)
275
+ end
276
+ end
277
+ end
278
+
279
+ describe "#standard_form" do
280
+ subject do
281
+ with_test_routing do
282
+ capture { standard_form(entry, :html => {:class => 'special'}) {|f| f.labeled_input_fields :name, :birthdate } }
283
+ end
284
+ end
285
+
286
+ context "for existing entry" do
287
+ let(:entry) { crud_test_models(:AAAAA) }
288
+
289
+ it { should match(/form .*?action="\/crud_test_models\/#{entry.id}" .?class="special form-horizontal" .*?method="post"/) }
290
+ it { should match(/input .*?name="_method" .*?type="hidden" .*?value="put"/) }
291
+ it { should match(/input .*?name="crud_test_model\[name\]" .*?type="text" .*?value="AAAAA"/) }
292
+ it { should match(/select .*?name="crud_test_model\[birthdate\(1i\)\]"/) }
293
+ it { should match(/option selected="selected" value="1910">1910<\/option>/) }
294
+ it { should match(/option selected="selected" value="1">January<\/option>/) }
295
+ it { should match(/option selected="selected" value="1">1<\/option>/) }
296
+ end
297
+
298
+ context "for invalid entry" do
299
+ let(:entry) do
300
+ e = crud_test_models(:AAAAA)
301
+ e.name = nil
302
+ e.valid?
303
+ e
304
+ end
305
+
306
+ it { should match(/div[^>]* id='error_explanation'/) }
307
+ it { should match(/div class="control-group error"\>.*?\<input .*?name="crud_test_model\[name\]" .*?type="text"/) }
308
+ it { should match(/input .*?name="_method" .*?type="hidden" .*?value="put"/) }
309
+ end
310
+ end
311
+
312
+ describe "#translate_inheritable" do
313
+ before { @controller = CrudTestModelsController.new }
314
+
315
+ before { I18n.backend.store_translations :en, :global => { :test_key => 'global' } }
316
+ subject { ti(:test_key) }
317
+
318
+ it { should == 'global' }
319
+
320
+ context "with list key" do
321
+ before { I18n.backend.store_translations :en, :list => { :global => {:test_key => 'list global'} } }
322
+ it { should == 'list global' }
323
+
324
+ context "and list action key" do
325
+ before { I18n.backend.store_translations :en, :list => { :index => {:test_key => 'list index'} } }
326
+ it { should == 'list index' }
327
+
328
+ context "and crud global key" do
329
+ before { I18n.backend.store_translations :en, :crud => { :global => {:test_key => 'crud global'} } }
330
+ it { should == 'crud global' }
331
+
332
+ context "and crud action key" do
333
+ before { I18n.backend.store_translations :en, :crud => { :index => {:test_key => 'crud index'} } }
334
+ it { should == 'crud index' }
335
+
336
+ context "and controller global key" do
337
+ before { I18n.backend.store_translations :en, :crud_test_models => { :global => {:test_key => 'test global'} } }
338
+ it { should == 'test global' }
339
+
340
+ context "and controller action key" do
341
+ before { I18n.backend.store_translations :en, :crud_test_models => { :index => {:test_key => 'test index'} } }
342
+ it { should == 'test index' }
343
+ end
344
+ end
345
+ end
346
+ end
347
+ end
348
+ end
349
+ end
350
+
351
+ describe "#translate_association" do
352
+ let(:assoc) { CrudTestModel.reflect_on_association(:companion) }
353
+ subject { ta(:test_key, assoc)}
354
+
355
+ before { I18n.backend.store_translations :en, :global => { :associations => {:test_key => 'global'} } }
356
+ it { should == 'global' }
357
+
358
+ context "with model key" do
359
+ before do
360
+ I18n.backend.store_translations :en,
361
+ :activerecord => {
362
+ :associations => {
363
+ :crud_test_model => {
364
+ :test_key => 'model'} } }
365
+ end
366
+
367
+ it { should == 'model' }
368
+
369
+ context "and assoc key" do
370
+ before do
371
+ I18n.backend.store_translations :en,
372
+ :activerecord => {
373
+ :associations => {
374
+ :models => {
375
+ :crud_test_model => {
376
+ :companion => {
377
+ :test_key => 'companion'} } } } }
378
+ end
379
+
380
+ it { should == 'companion' }
381
+ it "should use global without assoc" do
382
+ ta(:test_key).should == 'global'
383
+ end
384
+ end
385
+ end
386
+ end
387
+ end
@@ -0,0 +1,120 @@
1
+ require 'spec_helper'
2
+
3
+ describe 'StandardTableBuilder' do
4
+
5
+ include StandardHelper
6
+
7
+ let(:entries) { %w(foo bahr) }
8
+ let(:table) { StandardTableBuilder.new(entries, self) }
9
+
10
+ def format_size(obj) #:nodoc:
11
+ "#{obj.size} chars"
12
+ end
13
+
14
+ specify "#html_header" do
15
+ table.attrs :upcase, :size
16
+ dom = '<tr><th>Upcase</th><th>Size</th></tr>'
17
+ assert_dom_equal dom, table.send(:html_header)
18
+ end
19
+
20
+ specify "single attr row" do
21
+ table.attrs :upcase, :size
22
+ dom = '<tr><td>FOO</td><td>3 chars</td></tr>'
23
+ assert_dom_equal dom, table.send(:html_row, entries.first)
24
+ end
25
+
26
+ specify "custom row" do
27
+ table.col("Header", :class => 'hula') {|e| "Weights #{e.size} kg" }
28
+ dom = '<tr><td class="hula">Weights 3 kg</td></tr>'
29
+ assert_dom_equal dom, table.send(:html_row, entries.first)
30
+ end
31
+
32
+ context "attr col" do
33
+ let(:col) { table.cols.first }
34
+
35
+ context "output" do
36
+ before { table.attrs :upcase }
37
+
38
+ it { col.html_header.should == "<th>Upcase</th>" }
39
+ it { col.content('foo').should == "FOO" }
40
+ it { col.html_cell('foo').should == "<td>FOO</td>" }
41
+ end
42
+
43
+ context "content with custom format_size method" do
44
+ before { table.attrs :size }
45
+
46
+ it { col.content("abcd").should == "4 chars" }
47
+ end
48
+ end
49
+
50
+ specify "two x two table" do
51
+ dom = <<-FIN
52
+ <table class="table">
53
+ <thead>
54
+ <tr><th>Upcase</th><th>Size</th></tr>
55
+ </thead>
56
+ <tbody>
57
+ <tr><td>FOO</td><td>3 chars</td></tr>
58
+ <tr><td>BAHR</td><td>4 chars</td></tr>
59
+ </tbody>
60
+ </table>
61
+ FIN
62
+ dom.gsub!(/[\n\t]/, "").gsub!(/\s{2,}/, "")
63
+
64
+ table.attrs :upcase, :size
65
+
66
+ assert_dom_equal dom, table.to_html
67
+ end
68
+
69
+ specify "table with before and after cells" do
70
+ dom = <<-FIN
71
+ <table class="table">
72
+ <thead>
73
+ <tr><th>head</th><th>Upcase</th><th>Size</th><th></th></tr>
74
+ </thead>
75
+ <tbody>
76
+ <tr>
77
+ <td class='left'><a href='/'>foo</a></td>
78
+ <td>FOO</td>
79
+ <td>3 chars</td>
80
+ <td>Never foo</td>
81
+ </tr>
82
+ <tr>
83
+ <td class='left'><a href='/'>bahr</a></td>
84
+ <td>BAHR</td>
85
+ <td>4 chars</td>
86
+ <td>Never bahr</td>
87
+ </tr>
88
+ </tbody>
89
+ </table>
90
+ FIN
91
+ dom.gsub!(/[\n\t]/, "").gsub!(/\s{2,}/, "")
92
+
93
+ table.col('head', :class => 'left') { |e| link_to e, "/" }
94
+ table.attrs :upcase, :size
95
+ table.col { |e| "Never #{e}" }
96
+
97
+ assert_dom_equal dom, table.to_html
98
+ end
99
+
100
+ specify "empty entries collection renders empty table" do
101
+ dom = <<-FIN
102
+ <table class="table">
103
+ <thead>
104
+ <tr><th>head</th><th>Upcase</th><th>Size</th><th></th></tr>
105
+ </thead>
106
+ <tbody>
107
+ </tbody>
108
+ </table>
109
+ FIN
110
+ dom.gsub!(/[\n\t]/, "").gsub!(/\s{2,}/, "")
111
+
112
+ table = StandardTableBuilder.new([], self)
113
+ table.col('head', :class => 'left') { |e| link_to e, "/" }
114
+ table.attrs :upcase, :size
115
+ table.col { |e| "Never #{e}" }
116
+
117
+ assert_dom_equal dom, table.to_html
118
+ end
119
+
120
+ end