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.
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