forme 1.9.0 → 1.10.0
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +4 -4
- data/CHANGELOG +22 -0
- data/README.rdoc +9 -1
- data/lib/forme/bs3.rb +1 -1
- data/lib/forme/form.rb +1 -1
- data/lib/forme/transformers/error_handler.rb +46 -1
- data/lib/forme/transformers/formatter.rb +33 -35
- data/lib/forme/transformers/inputs_wrapper.rb +2 -2
- data/lib/forme/transformers/labeler.rb +19 -0
- data/lib/forme/transformers/wrapper.rb +1 -1
- data/lib/forme/version.rb +1 -1
- data/spec/forme_spec.rb +46 -14
- data/spec/roda_integration_spec.rb +9 -1
- data/spec/sequel_plugin_spec.rb +6 -6
- metadata +3 -4
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA256:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: 581902a62cc974ce05fecf52a4b7debd41b5d89f5ba151c1c03a2f0589f15e7e
|
4
|
+
data.tar.gz: 5252e5dca95690ddf46341e443954058644f41c67e2109d7692a6dfb8c3b3ee8
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: 39c198d2db64a06eacf30e1ed2e5af10bce818fe45f81c17ab8fcd4db7b1693afb3c2e82d013615105dd71907e96eead22104340068b04361492b853fe03da65
|
7
|
+
data.tar.gz: 33bfcf058c9ffc34f9581f3aa78e924b6764b034c56495ebaebd241eb07f5984e4330ddbab3f3a934cc77e66412e01c07decbf81bee07bb10c5d829eb00dff6f
|
data/CHANGELOG
CHANGED
@@ -1,3 +1,25 @@
|
|
1
|
+
=== 1.10.0 (2019-05-13)
|
2
|
+
|
3
|
+
* Make readonly formatter ignore hidden inputs (jeremyevans)
|
4
|
+
|
5
|
+
* Add :select_labels for date inputs using :as=>:select to use labels for the inputs for better accessibility (jeremyevans)
|
6
|
+
|
7
|
+
* Add :after_legend error_handler for adding error message after legend when using :legend labeler (jeremyevans)
|
8
|
+
|
9
|
+
* Add aria-describedby to all inputs with errors where possible for better accessibility (jeremyevans)
|
10
|
+
|
11
|
+
* Add aria-invalid to all inputs with errors for better accessibility (jeremyevans)
|
12
|
+
|
13
|
+
* Support :fieldset wrapper and :legend labeler, can be used for accessible radioset/checkboxset (jeremyevans)
|
14
|
+
|
15
|
+
* Support :tag_label_attr option for radioset and checkbox set for label attributes for each radio/checkbox label (jeremyevans)
|
16
|
+
|
17
|
+
* Support custom :error_handler in radioset and checkboxset inputs (jeremyevans)
|
18
|
+
|
19
|
+
* Support custom :labeler in radioset and checkboxset inputs (jeremyevans)
|
20
|
+
|
21
|
+
* Avoid calling Proc.new with an implicit block, which is deprecated starting in ruby 2.7 (jeremyevans)
|
22
|
+
|
1
23
|
=== 1.9.0 (2018-11-16)
|
2
24
|
|
3
25
|
* Automatically add maxlength attributes to text and textarea inputs in the Sequel plugin based on maximum database column length (jeremyevans)
|
data/README.rdoc
CHANGED
@@ -822,6 +822,8 @@ creates multiple select options. Options:
|
|
822
822
|
for the select field and string to use a string
|
823
823
|
(:date default: <tt>[:year, '-', :month, '-', :day]</tt>)
|
824
824
|
(:datetime default: <tt>[:year, '-', :month, '-', :day, ' ', :hour, ':', :minute, ':', :second]</tt>)
|
825
|
+
:select_labels :: The labels to use for the select boxes. Should be a hash keyed by the
|
826
|
+
symbol used in order. By default, no labels are used.
|
825
827
|
:select_options :: The options to use for the select boxes. Should be a hash keyed by the
|
826
828
|
symbol used in order (e.g. <tt>{:year=>1970..2020}</tt>)
|
827
829
|
|
@@ -862,6 +864,7 @@ the following options:
|
|
862
864
|
|
863
865
|
:tag_wrapper :: The wrapper transformer for individual tags in the set
|
864
866
|
:tag_labeler :: The labeler transformer for individual tags in the set
|
867
|
+
:tag_label_attr :: The attributes to use for labels for individual tags in the set
|
865
868
|
|
866
869
|
=== :radioset
|
867
870
|
|
@@ -980,7 +983,9 @@ Forme ships with a bunch of built-in transformers that you can use:
|
|
980
983
|
|
981
984
|
=== +error_handler+
|
982
985
|
|
986
|
+
:after_legend :: designed for usage with :legend labeler, putting error message after legend, adding error for first input in the set
|
983
987
|
:default :: modifies tag to add an error class and adds a span with the error message
|
988
|
+
:set :: default error_handler for checkboxset and radioset inputs, that adds an error to the last input in the set
|
984
989
|
|
985
990
|
This supports the following options:
|
986
991
|
|
@@ -998,8 +1003,10 @@ This supports the following options:
|
|
998
1003
|
|
999
1004
|
:default :: uses implicit labels, where the tag is a child of the label tag
|
1000
1005
|
:explicit :: uses explicit labels with the for attribute, where tag is a sibling of the label tag
|
1006
|
+
:legend :: adds a legend before the tags, mostly useful for accessible checkboxset and radioset inputs
|
1007
|
+
:span :: default labeler for checkboxset and radioset inputs that adds a span before the tags
|
1001
1008
|
|
1002
|
-
|
1009
|
+
The :default and :explicit labelers respect the following options:
|
1003
1010
|
|
1004
1011
|
:label_position :: Can be set to :before or :after to place the label before or after the the input.
|
1005
1012
|
:label_attr :: A hash of attributes to use for the label tag
|
@@ -1008,6 +1015,7 @@ Both of these respect the following options:
|
|
1008
1015
|
|
1009
1016
|
:default :: returns tag without wrapping
|
1010
1017
|
:div :: wraps tag in div tag
|
1018
|
+
:fieldset :: wraps tags in a fieldset, mostly useful for accessible checkboxset and radioset inputs
|
1011
1019
|
:fieldset_ol :: same as :li, but also sets +inputs_wrapper+ to :fieldset_ol
|
1012
1020
|
:li :: wraps tag in li tag
|
1013
1021
|
:ol :: same as :li, but also sets +inputs_wrapper+ to :ol
|
data/lib/forme/bs3.rb
CHANGED
data/lib/forme/form.rb
CHANGED
@@ -11,10 +11,55 @@ module Forme
|
|
11
11
|
|
12
12
|
# Return tag with error message span tag after it.
|
13
13
|
def call(tag, input)
|
14
|
+
[tag, error_tag(input)]
|
15
|
+
end
|
16
|
+
|
17
|
+
private
|
18
|
+
|
19
|
+
def error_tag(input)
|
14
20
|
attr = input.opts[:error_attr]
|
15
21
|
attr = attr ? attr.dup : {}
|
16
22
|
Forme.attr_classes(attr, 'error_message')
|
17
|
-
|
23
|
+
|
24
|
+
if id = input.opts[:error_id]
|
25
|
+
unless attr['id'] || attr[:id]
|
26
|
+
attr['id'] = id
|
27
|
+
end
|
28
|
+
end
|
29
|
+
|
30
|
+
input.tag(:span, attr, input.opts[:error])
|
31
|
+
end
|
32
|
+
end
|
33
|
+
|
34
|
+
class ErrorHandler::Set < ErrorHandler
|
35
|
+
Forme.register_transformer(:error_handler, :set, new)
|
36
|
+
|
37
|
+
def call(tag, input)
|
38
|
+
return super unless last_input = input.opts[:last_input]
|
39
|
+
|
40
|
+
last_input.opts[:error] = input.opts[:error]
|
41
|
+
last_input.opts[:error_attr] = input.opts[:error_attr] if input.opts[:error_attr]
|
42
|
+
last_input.opts[:error_handler] = :default
|
43
|
+
|
44
|
+
tag
|
45
|
+
end
|
46
|
+
end
|
47
|
+
|
48
|
+
class ErrorHandler::AfterLegend < ErrorHandler
|
49
|
+
Forme.register_transformer(:error_handler, :after_legend, new)
|
50
|
+
|
51
|
+
def call(tag, input)
|
52
|
+
return super unless tag.is_a?(Array)
|
53
|
+
return super unless tag.first.is_a?(Tag)
|
54
|
+
return super unless tag.first.type == :legend
|
55
|
+
|
56
|
+
first_input = input.opts[:first_input]
|
57
|
+
attr = first_input.opts[:attr] ||= {}
|
58
|
+
Forme.attr_classes(attr, 'error')
|
59
|
+
attr['aria-invalid'] = 'true'
|
60
|
+
attr['aria-describedby'] = input.opts[:error_id] = "#{first_input.opts[:id]}_error_message"
|
61
|
+
|
62
|
+
tag.insert(1, error_tag(input))
|
18
63
|
end
|
19
64
|
end
|
20
65
|
end
|
@@ -61,7 +61,6 @@ module Forme
|
|
61
61
|
@attr = attr ? attr.dup : {}
|
62
62
|
@opts = input.opts
|
63
63
|
normalize_options
|
64
|
-
|
65
64
|
tag = if html = input.opts[:html]
|
66
65
|
html = html.call(input) if html.respond_to?(:call)
|
67
66
|
form.raw(html)
|
@@ -158,9 +157,10 @@ module Forme
|
|
158
157
|
ops = ops.merge(@opts[:select_options]) if @opts[:select_options]
|
159
158
|
first_input = true
|
160
159
|
format = DATE_SELECT_FORMAT
|
160
|
+
@opts[:select_labels] ||= {}
|
161
161
|
order.map do |x|
|
162
162
|
next x if x.is_a?(String)
|
163
|
-
opts = @opts.merge(:label
|
163
|
+
opts = @opts.merge(:label=>@opts[:select_labels][x], :wrapper=>nil, :error=>nil, :name=>"#{name}[#{x}]", :value=>values[x], :options=>ops[x].map{|y| [sprintf(format, y), y]})
|
164
164
|
opts[:id] = if first_input
|
165
165
|
first_input = false
|
166
166
|
id
|
@@ -221,23 +221,22 @@ module Forme
|
|
221
221
|
key = @opts[:key]
|
222
222
|
name = @opts[:name]
|
223
223
|
id = @opts[:id]
|
224
|
-
|
225
|
-
|
226
|
-
end
|
227
|
-
if @opts[:label]
|
228
|
-
@opts[:set_label] = @opts.delete(:label)
|
229
|
-
end
|
224
|
+
@opts[:labeler] ||= :span
|
225
|
+
@opts[:error_handler] ||= :set
|
230
226
|
|
231
227
|
tag_wrapper = Forme.transformer(:tag_wrapper, @opts.delete(:tag_wrapper), @input.form_opts) || :default
|
232
228
|
tag_labeler = Forme.transformer(:labeler, @opts.delete(:tag_labeler), @input.form_opts) || :default
|
233
229
|
wrapper = @opts.fetch(:wrapper){@opts[:wrapper] = @input.form_opts[:set_wrapper] || @input.form_opts[:wrapper]}
|
234
230
|
wrapper = Forme.transformer(:wrapper, wrapper)
|
231
|
+
tag_label_attr = @opts[:tag_label_attr] || @opts[:label_attr]
|
235
232
|
|
236
|
-
|
233
|
+
first_input = nil
|
234
|
+
last_input = nil
|
235
|
+
ret = process_select_optgroups(:_format_set_optgroup) do |label, value, sel, attrs|
|
237
236
|
value = label if value.nil?
|
238
237
|
label_attr = {:class=>:option}
|
239
|
-
label_attr.merge!(
|
240
|
-
r_opts = attrs.merge(tag_attrs).merge(:label=>label||value, :label_attr=>label_attr, :wrapper=>tag_wrapper, :labeler=>tag_labeler)
|
238
|
+
label_attr.merge!(tag_label_attr) if tag_label_attr
|
239
|
+
r_opts = attrs.merge(tag_attrs).merge(:label=>label||value, :label_attr=>label_attr, :wrapper=>tag_wrapper, :labeler=>tag_labeler, :error=>nil, :error_attr=>nil)
|
241
240
|
if r_opts[:value].nil?
|
242
241
|
r_opts[:value] = value unless value.nil?
|
243
242
|
end
|
@@ -255,31 +254,15 @@ module Forme
|
|
255
254
|
r_opts[:key_id] ||= value
|
256
255
|
end
|
257
256
|
|
258
|
-
form._input(type, r_opts)
|
259
|
-
|
260
|
-
|
261
|
-
if @opts[:set_error]
|
262
|
-
_add_set_error(tags)
|
257
|
+
input = form._input(type, r_opts)
|
258
|
+
first_input ||= input
|
259
|
+
last_input = input
|
263
260
|
end
|
264
261
|
|
265
|
-
|
266
|
-
|
267
|
-
tags
|
268
|
-
end
|
262
|
+
@opts[:first_input] = first_input
|
263
|
+
@opts[:last_input] = last_input
|
269
264
|
|
270
|
-
|
271
|
-
form._tag(:span, {:class=>:label}, @opts[:set_label])
|
272
|
-
end
|
273
|
-
|
274
|
-
def _add_set_error(tags)
|
275
|
-
if (last_input = tags.last) && last_input.is_a?(Input)
|
276
|
-
last_input.opts[:error] = @opts[:set_error]
|
277
|
-
last_input.opts[:error_attr] = @opts[:error_attr] if @opts[:error_attr]
|
278
|
-
else
|
279
|
-
attr = @opts[:error_attr] || {}
|
280
|
-
Forme.attr_classes(attr, 'error_message')
|
281
|
-
tags << form._tag(:span, attr, [@opts[:set_error]])
|
282
|
-
end
|
265
|
+
ret
|
283
266
|
end
|
284
267
|
|
285
268
|
# Formats a textarea. Respects the following options:
|
@@ -321,7 +304,19 @@ module Forme
|
|
321
304
|
handle_errors_option
|
322
305
|
|
323
306
|
Forme.attr_classes(@attr, @opts[:class]) if @opts.has_key?(:class)
|
324
|
-
|
307
|
+
|
308
|
+
if @opts[:error]
|
309
|
+
Forme.attr_classes(@attr, 'error')
|
310
|
+
@attr["aria-invalid"] = "true"
|
311
|
+
if @opts.fetch(:error_handler, true)
|
312
|
+
unless @opts[:error_id]
|
313
|
+
if id = @attr[:id] || @attr['id']
|
314
|
+
error_id = @attr['aria-describedby'] ||= "#{id}_error_message"
|
315
|
+
@opts[:error_id] = error_id
|
316
|
+
end
|
317
|
+
end
|
318
|
+
end
|
319
|
+
end
|
325
320
|
|
326
321
|
if data = opts[:data]
|
327
322
|
data.each do |k, v|
|
@@ -540,8 +535,11 @@ module Forme
|
|
540
535
|
end
|
541
536
|
|
542
537
|
# Use a span with text instead of an input field.
|
538
|
+
# For hidden inputs, do not show anything
|
543
539
|
def _format_input(type)
|
544
|
-
|
540
|
+
unless type.to_s == 'hidden'
|
541
|
+
tag(:span, {'class'=>'readonly-text'}, @attr[:value])
|
542
|
+
end
|
545
543
|
end
|
546
544
|
|
547
545
|
# Disabled radio button inputs.
|
@@ -10,7 +10,7 @@ module Forme
|
|
10
10
|
# Wrap the inputs in a <fieldset>. If the :legend
|
11
11
|
# option is given, add a <legend> tag as the first
|
12
12
|
# child of the fieldset.
|
13
|
-
def call(form, opts)
|
13
|
+
def call(form, opts, &block)
|
14
14
|
attr = opts[:attr] ? opts[:attr].dup : {}
|
15
15
|
Forme.attr_classes(attr, 'inputs')
|
16
16
|
if legend = opts[:legend]
|
@@ -19,7 +19,7 @@ module Forme
|
|
19
19
|
yield
|
20
20
|
end
|
21
21
|
else
|
22
|
-
form.tag(:fieldset, attr, &
|
22
|
+
form.tag(:fieldset, attr, &block)
|
23
23
|
end
|
24
24
|
end
|
25
25
|
end
|
@@ -77,4 +77,23 @@ module Forme
|
|
77
77
|
t
|
78
78
|
end
|
79
79
|
end
|
80
|
+
|
81
|
+
class Labeler::Span
|
82
|
+
Forme.register_transformer(:labeler, :span, new)
|
83
|
+
|
84
|
+
def call(tag, input)
|
85
|
+
label_attr = input.opts[:label_attr]
|
86
|
+
label_attr = label_attr ? label_attr.dup : {}
|
87
|
+
Forme.attr_classes(label_attr, "label")
|
88
|
+
[input.tag(:span, label_attr, input.opts[:label]), tag]
|
89
|
+
end
|
90
|
+
end
|
91
|
+
|
92
|
+
class Labeler::Legend
|
93
|
+
Forme.register_transformer(:labeler, :legend, new)
|
94
|
+
|
95
|
+
def call(tag, input)
|
96
|
+
[input.tag(:legend, input.opts[:label_attr], input.opts[:label]), tag]
|
97
|
+
end
|
98
|
+
end
|
80
99
|
end
|
data/lib/forme/version.rb
CHANGED
data/spec/forme_spec.rb
CHANGED
@@ -116,13 +116,13 @@ describe "Forme plain forms" do
|
|
116
116
|
|
117
117
|
it "should consider form's :errors hash based on the :key option" do
|
118
118
|
@f.opts[:errors] = { 'foo' => 'must be present' }
|
119
|
-
@f.input(:text, :key=>"foo").to_s.must_equal "<input class=\"error\" id=\"foo\" name=\"foo\" type=\"text\"/><span class=\"error_message\">must be present</span>"
|
119
|
+
@f.input(:text, :key=>"foo").to_s.must_equal "<input aria-describedby=\"foo_error_message\" aria-invalid=\"true\" class=\"error\" id=\"foo\" name=\"foo\" type=\"text\"/><span class=\"error_message\" id=\"foo_error_message\">must be present</span>"
|
120
120
|
end
|
121
121
|
|
122
122
|
it "should consider form's :errors hash based on the :key option when using namespaces" do
|
123
123
|
@f.opts[:errors] = { 'bar' => { 'foo' => 'must be present' } }
|
124
124
|
@f.with_opts(:namespace=>['bar']) do
|
125
|
-
@f.input(:text, :key=>"foo").to_s.must_equal "<input class=\"error\" id=\"bar_foo\" name=\"bar[foo]\" type=\"text\"/><span class=\"error_message\">must be present</span>"
|
125
|
+
@f.input(:text, :key=>"foo").to_s.must_equal "<input aria-describedby=\"bar_foo_error_message\" aria-invalid=\"true\" class=\"error\" id=\"bar_foo\" name=\"bar[foo]\" type=\"text\"/><span class=\"error_message\" id=\"bar_foo_error_message\">must be present</span>"
|
126
126
|
end
|
127
127
|
end
|
128
128
|
|
@@ -301,6 +301,10 @@ describe "Forme plain forms" do
|
|
301
301
|
@f.input(:date, :name=>"foo", :id=>"bar", :as=>:select, :value=>Date.new(2011, 6, 5)).to_s.must_equal %{<select id="bar" name="foo[year]">#{sel(1900..2050, 2011)}</select>-<select id="bar_month" name="foo[month]">#{sel(1..12, 6)}</select>-<select id="bar_day" name="foo[day]">#{sel(1..31, 5)}</select>}
|
302
302
|
end
|
303
303
|
|
304
|
+
it "should use labels for select boxes for dates if the :as=>:select and :select_labels options are given" do
|
305
|
+
@f.input(:date, :name=>"foo", :id=>"bar", :as=>:select, :value=>Date.new(2011, 6, 5), :select_labels=>{:year=>'Y', :month=>'M', :day=>'D'}, :labeler=>:explicit).to_s.must_equal %{<label class="label-before" for="bar">Y</label><select id="bar" name="foo[year]">#{sel(1900..2050, 2011)}</select>-<label class="label-before" for="bar_month">M</label><select id="bar_month" name="foo[month]">#{sel(1..12, 6)}</select>-<label class="label-before" for="bar_day">D</label><select id="bar_day" name="foo[day]">#{sel(1..31, 5)}</select>}
|
306
|
+
end
|
307
|
+
|
304
308
|
it "should allow ordering date select boxes via :order" do
|
305
309
|
@f.input(:date, :name=>"foo", :id=>"bar", :as=>:select, :value=>Date.new(2011, 6, 5), :order=>[:month, '/', :day, '/', :year]).to_s.must_equal %{<select id="bar" name="foo[month]">#{sel(1..12, 6)}</select>/<select id="bar_day" name="foo[day]">#{sel(1..31, 5)}</select>/<select id="bar_year" name="foo[year]">#{sel(1900..2050, 2011)}</select>}
|
306
310
|
end
|
@@ -433,7 +437,11 @@ describe "Forme plain forms" do
|
|
433
437
|
end
|
434
438
|
|
435
439
|
it "should create set of radio buttons with :error and :error_attr options" do
|
436
|
-
@f.input(:radioset, :options=>[1, 2, 3], :selected=>2, :error=>'foo', :error_attr=>{'bar'=>'baz'}).to_s.must_equal '<label class="option"><input type="radio" value="1"/> 1</label><label class="option"><input checked="checked" type="radio" value="2"/> 2</label><label class="option"><input class="error" type="radio" value="3"/> 3</label><span bar="baz" class="error_message">foo</span>'
|
440
|
+
@f.input(:radioset, :options=>[1, 2, 3], :selected=>2, :error=>'foo', :error_attr=>{'bar'=>'baz'}).to_s.must_equal '<label class="option"><input type="radio" value="1"/> 1</label><label class="option"><input checked="checked" type="radio" value="2"/> 2</label><label class="option"><input aria-invalid="true" class="error" type="radio" value="3"/> 3</label><span bar="baz" class="error_message">foo</span>'
|
441
|
+
end
|
442
|
+
|
443
|
+
it "should support custom error_handler for set of radio buttons" do
|
444
|
+
@f.input(:radioset, :options=>[1, 2, 3], :selected=>2, :error=>'foo', :error_attr=>{'bar'=>'baz'}, :error_handler=>lambda{|tag, input| input.tag(:div, {}, tag)}).to_s.must_equal '<div><label class="option"><input type="radio" value="1"/> 1</label><label class="option"><input checked="checked" type="radio" value="2"/> 2</label><label class="option"><input type="radio" value="3"/> 3</label></div>'
|
437
445
|
end
|
438
446
|
|
439
447
|
it "should create set of checkbox buttons" do
|
@@ -457,10 +465,26 @@ describe "Forme plain forms" do
|
|
457
465
|
@f.input(:checkboxset, :options=>[[:a, 1], [:b, 2], [:c, 3]], :label=>'foo').to_s.must_equal '<span class="label">foo</span><label class="option"><input type="checkbox" value="1"/> a</label><label class="option"><input type="checkbox" value="2"/> b</label><label class="option"><input type="checkbox" value="3"/> c</label>'
|
458
466
|
end
|
459
467
|
|
468
|
+
it "should support fieldset/legend for checkboxsets" do
|
469
|
+
@f.input(:checkboxset, :options=>[[:a, 1], [:b, 2], [:c, 3]], :label=>'foo', :labeler=>:legend, :wrapper=>:fieldset).to_s.must_equal '<fieldset><legend>foo</legend><label class="option"><input type="checkbox" value="1"/> a</label><label class="option"><input type="checkbox" value="2"/> b</label><label class="option"><input type="checkbox" value="3"/> c</label></fieldset>'
|
470
|
+
end
|
471
|
+
|
472
|
+
it "should support legend with attributes for checkboxsets" do
|
473
|
+
@f.input(:checkboxset, :options=>[[:a, 1], [:b, 2], [:c, 3]], :label=>'foo', :label_attr=>{:class=>"baz"}, :tag_label_attr=>{:class=>"bar"}, :labeler=>:legend, :wrapper=>:fieldset).to_s.must_equal '<fieldset><legend class="baz">foo</legend><label class="bar"><input type="checkbox" value="1"/> a</label><label class="bar"><input type="checkbox" value="2"/> b</label><label class="bar"><input type="checkbox" value="3"/> c</label></fieldset>'
|
474
|
+
end
|
475
|
+
|
476
|
+
it "should support legend with attributes for checkboxsets, handling errors with :error_handler=>:after_legend" do
|
477
|
+
@f.input(:checkboxset, :options=>[[:a, 1], [:b, 2], [:c, 3]], :id=>:quux, :label=>'foo', :label_attr=>{:class=>"baz"}, :tag_label_attr=>{:class=>"bar"}, :labeler=>:legend, :wrapper=>:fieldset, :error=>'bar2', :error_handler=>:after_legend).to_s.must_equal '<fieldset><legend class="baz">foo</legend><span class="error_message" id="quux_1_error_message">bar2</span><label class="bar"><input aria-describedby="quux_1_error_message" aria-invalid="true" class="error" id="quux_1" type="checkbox" value="1"/> a</label><label class="bar"><input id="quux_2" type="checkbox" value="2"/> b</label><label class="bar"><input id="quux_3" type="checkbox" value="3"/> c</label></fieldset>'
|
478
|
+
end
|
479
|
+
|
460
480
|
it "should support :tag_labeler for checkboxsets" do
|
461
481
|
@f.input(:checkboxset, :options=>[[:a, 1], [:b, 2], [:c, 3]], :tag_labeler=>:explicit).to_s.must_equal '<input type="checkbox" value="1"/><label class="option label-after">a</label><input type="checkbox" value="2"/><label class="option label-after">b</label><input type="checkbox" value="3"/><label class="option label-after">c</label>'
|
462
482
|
end
|
463
483
|
|
484
|
+
it "should support custom :labeler for checkboxsets" do
|
485
|
+
@f.input(:checkboxset, :options=>[[:a, 1], [:b, 2], [:c, 3]], :label=>'foo', :labeler=>lambda{|tag, input| input.tag(:div, {}, tag)}).to_s.must_equal '<div><label class="option"><input type="checkbox" value="1"/> a</label><label class="option"><input type="checkbox" value="2"/> b</label><label class="option"><input type="checkbox" value="3"/> c</label></div>'
|
486
|
+
end
|
487
|
+
|
464
488
|
it "should create set of checkbox buttons with options and values with hashes" do
|
465
489
|
@f.input(:checkboxset, :options=>[[:a, {:attr=>{:foo=>1}}], [:b, {:class=>'foo', :value=>2}], [:c, {:id=>:baz}]], :selected=>2).to_s.must_equal '<label class="option"><input foo="1" type="checkbox" value="a"/> a</label><label class="option"><input checked="checked" class="foo" type="checkbox" value="2"/> b</label><label class="option"><input id="baz" type="checkbox" value="c"/> c</label>'
|
466
490
|
end
|
@@ -491,7 +515,7 @@ describe "Forme plain forms" do
|
|
491
515
|
end
|
492
516
|
|
493
517
|
it "should respect the :error option for checkbox sets" do
|
494
|
-
@f.input(:checkboxset, :options=>[1, 2, 3], :error=>'foo', :value=>2).to_s.must_equal '<label class="option"><input type="checkbox" value="1"/> 1</label><label class="option"><input checked="checked" type="checkbox" value="2"/> 2</label><label class="option"><input class="error" type="checkbox" value="3"/> 3</label><span class="error_message">foo</span>'
|
518
|
+
@f.input(:checkboxset, :options=>[1, 2, 3], :error=>'foo', :value=>2).to_s.must_equal '<label class="option"><input type="checkbox" value="1"/> 1</label><label class="option"><input checked="checked" type="checkbox" value="2"/> 2</label><label class="option"><input aria-invalid="true" class="error" type="checkbox" value="3"/> 3</label><span class="error_message">foo</span>'
|
495
519
|
end
|
496
520
|
|
497
521
|
it "should create set of checkbox buttons with fieldsets and legends for optgroups" do
|
@@ -558,19 +582,23 @@ describe "Forme plain forms" do
|
|
558
582
|
end
|
559
583
|
|
560
584
|
it "should automatically note the input has errors if :error option is used" do
|
561
|
-
@f.input(:text, :error=>'Bad Stuff!', :value=>'foo').to_s.must_equal '<input class="error" type="text" value="foo"/><span class="error_message">Bad Stuff!</span>'
|
585
|
+
@f.input(:text, :error=>'Bad Stuff!', :value=>'foo').to_s.must_equal '<input aria-invalid="true" class="error" type="text" value="foo"/><span class="error_message">Bad Stuff!</span>'
|
562
586
|
end
|
563
587
|
|
564
588
|
it "should add an error message after the label" do
|
565
|
-
@f.input(:text, :error=>'Bad Stuff!', :value=>'foo', :label=>"Foo").to_s.must_equal '<label>Foo: <input class="error" type="text" value="foo"/></label><span class="error_message">Bad Stuff!</span>'
|
589
|
+
@f.input(:text, :error=>'Bad Stuff!', :value=>'foo', :label=>"Foo").to_s.must_equal '<label>Foo: <input aria-invalid="true" class="error" type="text" value="foo"/></label><span class="error_message">Bad Stuff!</span>'
|
566
590
|
end
|
567
591
|
|
568
592
|
it "should add to existing :class option if :error option is used" do
|
569
|
-
@f.input(:text, :error=>'Bad Stuff!', :class=>'bar', :value=>'foo').to_s.must_equal '<input class="bar error" type="text" value="foo"/><span class="error_message">Bad Stuff!</span>'
|
593
|
+
@f.input(:text, :error=>'Bad Stuff!', :class=>'bar', :value=>'foo').to_s.must_equal '<input aria-invalid="true" class="bar error" type="text" value="foo"/><span class="error_message">Bad Stuff!</span>'
|
570
594
|
end
|
571
595
|
|
572
596
|
it "should respect :error_attr option for setting the attributes for the error message span" do
|
573
|
-
@f.input(:text, :error=>'Bad Stuff!', :value=>'foo', :error_attr=>{:class=>'foo'}).to_s.must_equal '<input class="error" type="text" value="foo"/><span class="foo error_message">Bad Stuff!</span>'
|
597
|
+
@f.input(:text, :error=>'Bad Stuff!', :value=>'foo', :error_attr=>{:class=>'foo'}).to_s.must_equal '<input aria-invalid="true" class="error" type="text" value="foo"/><span class="foo error_message">Bad Stuff!</span>'
|
598
|
+
end
|
599
|
+
|
600
|
+
it "should use aria-describedby and aria-invalid tags for errors with where the id attribute can be determined" do
|
601
|
+
@f.input(:text, :error=>'Bad Stuff!', :id=>:bar, :value=>'foo', :error_attr=>{:class=>'foo'}).to_s.must_equal '<input aria-describedby="bar_error_message" aria-invalid="true" class="error" id="bar" type="text" value="foo"/><span class="foo error_message" id="bar_error_message">Bad Stuff!</span>'
|
574
602
|
end
|
575
603
|
|
576
604
|
it "#open should return an opening tag" do
|
@@ -696,7 +724,7 @@ describe "Forme plain forms" do
|
|
696
724
|
end
|
697
725
|
|
698
726
|
it "inputs should have helper displayed inside wrapper, after error" do
|
699
|
-
@f.input(:text, :help=>"List type of foo", :error=>'bad', :wrapper=>:li).to_s.must_equal '<li><input class="error" type="text"/><span class="error_message">bad</span><span class="helper">List type of foo</span></li>'
|
727
|
+
@f.input(:text, :help=>"List type of foo", :error=>'bad', :wrapper=>:li).to_s.must_equal '<li><input aria-invalid="true" class="error" type="text"/><span class="error_message">bad</span><span class="helper">List type of foo</span></li>'
|
700
728
|
end
|
701
729
|
|
702
730
|
it "inputs should accept a :formatter option to use a custom formatter" do
|
@@ -729,7 +757,7 @@ describe "Forme plain forms" do
|
|
729
757
|
end
|
730
758
|
|
731
759
|
it "inputs should accept a :error_handler option to use a custom error_handler" do
|
732
|
-
@f.input(:textarea, :error_handler=>proc{|t, i| [t, "!!! #{i.opts[:error]}"]}, :error=>'bar', :id=>:foo).to_s.must_equal '<textarea class="error" id="foo"></textarea>!!! bar'
|
760
|
+
@f.input(:textarea, :error_handler=>proc{|t, i| [t, "!!! #{i.opts[:error]}"]}, :error=>'bar', :id=>:foo).to_s.must_equal '<textarea aria-describedby="foo_error_message" aria-invalid="true" class="error" id="foo"></textarea>!!! bar'
|
733
761
|
end
|
734
762
|
|
735
763
|
it "#inputs should accept a :inputs_wrapper option to use a custom inputs_wrapper" do
|
@@ -745,7 +773,7 @@ describe "Forme plain forms" do
|
|
745
773
|
end
|
746
774
|
|
747
775
|
it "inputs should accept a :error_handler=>nil option to not use an error_handler" do
|
748
|
-
@f.input(:textarea, :error_handler=>nil, :error=>'bar', :id=>:foo).to_s.must_equal '<textarea class="error" id="foo"></textarea>'
|
776
|
+
@f.input(:textarea, :error_handler=>nil, :error=>'bar', :id=>:foo).to_s.must_equal '<textarea aria-invalid="true" class="error" id="foo"></textarea>'
|
749
777
|
end
|
750
778
|
|
751
779
|
it "#inputs should accept a :inputs_wrapper=>nil option to not use an inputs_wrapper" do
|
@@ -819,7 +847,7 @@ describe "Forme custom" do
|
|
819
847
|
end
|
820
848
|
|
821
849
|
it "error_handlers can be specified as a proc" do
|
822
|
-
Forme::Form.new(:error_handler=>proc{|t, i| [t, "!!! #{i.opts[:error]}"]}).input(:textarea, :name=>'foo', :error=>'bar').to_s.must_equal '<textarea class="error" name="foo"></textarea>!!! bar'
|
850
|
+
Forme::Form.new(:error_handler=>proc{|t, i| [t, "!!! #{i.opts[:error]}"]}).input(:textarea, :name=>'foo', :error=>'bar').to_s.must_equal '<textarea aria-invalid="true" class="error" name="foo"></textarea>!!! bar'
|
823
851
|
end
|
824
852
|
|
825
853
|
it "wrappers can be specified as a proc" do
|
@@ -854,6 +882,10 @@ describe "Forme built-in custom" do
|
|
854
882
|
Forme::Form.new(:formatter=>:readonly).input(:select, :label=>"Foo", :options=>[1, 2, 3], :value=>2).to_s.must_equal "<label>Foo: <span>2</span></label>"
|
855
883
|
end
|
856
884
|
|
885
|
+
it "formatter: readonly removes hidden inputs" do
|
886
|
+
Forme::Form.new(:formatter=>:readonly).input(:hidden, :value=>"Bar").to_s.must_equal ""
|
887
|
+
end
|
888
|
+
|
857
889
|
it "formatter: readonly formats text into paragraphs for textarea inputs" do
|
858
890
|
Forme::Form.new(:formatter=>:readonly).input(:textarea, :label=>"Foo", :value=>"\n Bar\nBaz\n\nQuuz\n\n1\n2 \n").to_s.must_equal "<label>Foo: <div class=\"readonly-textarea\"><p> Bar<br />Baz</p><p>Quuz</p><p>1<br />2 </p></div></label>"
|
859
891
|
end
|
@@ -877,7 +909,7 @@ describe "Forme built-in custom" do
|
|
877
909
|
end
|
878
910
|
|
879
911
|
it "labeler: explicit should handle tags with errors" do
|
880
|
-
Forme::Form.new(:labeler=>:explicit).input(:text, :error=>'Bad Stuff!', :value=>'f', :id=>'foo', :label=>'bar').to_s.must_equal '<label class="label-before" for="foo">bar</label><input class="error" id="foo" type="text" value="f"/><span class="error_message">Bad Stuff!</span>'
|
912
|
+
Forme::Form.new(:labeler=>:explicit).input(:text, :error=>'Bad Stuff!', :value=>'f', :id=>'foo', :label=>'bar').to_s.must_equal '<label class="label-before" for="foo">bar</label><input aria-describedby="foo_error_message" aria-invalid="true" class="error" id="foo" type="text" value="f"/><span class="error_message" id="foo_error_message">Bad Stuff!</span>'
|
881
913
|
end
|
882
914
|
|
883
915
|
it "wrapper: li wraps tag in an li" do
|
@@ -915,7 +947,7 @@ describe "Forme built-in custom" do
|
|
915
947
|
end
|
916
948
|
|
917
949
|
it "wrapper: trtd should use at most 2 td tags" do
|
918
|
-
Forme::Form.new(:wrapper=>:trtd, :labeler=>:explicit).input(:textarea, :id=>'foo', :label=>'Foo', :error=>'Bar').to_s.must_equal '<tr><td><label class="label-before" for="foo">Foo</label></td><td><textarea class="error" id="foo"></textarea><span class="error_message">Bar</span></td></tr>'
|
950
|
+
Forme::Form.new(:wrapper=>:trtd, :labeler=>:explicit).input(:textarea, :id=>'foo', :label=>'Foo', :error=>'Bar').to_s.must_equal '<tr><td><label class="label-before" for="foo">Foo</label></td><td><textarea aria-describedby="foo_error_message" aria-invalid="true" class="error" id="foo"></textarea><span class="error_message" id="foo_error_message">Bar</span></td></tr>'
|
919
951
|
end
|
920
952
|
|
921
953
|
it "wrapper: trtd should handle inputs with label after" do
|
@@ -20,7 +20,15 @@ rescue LoadError
|
|
20
20
|
end
|
21
21
|
|
22
22
|
class FormeRodaTest < Roda
|
23
|
-
|
23
|
+
opts[:check_dynamic_arity] = opts[:check_arity] = :warn
|
24
|
+
|
25
|
+
if defined?(Roda::RodaVersionNumber) && Roda::RodaVersionNumber >= 30100
|
26
|
+
require 'roda/session_middleware'
|
27
|
+
opts[:sessions_convert_symbols] = true
|
28
|
+
use RodaSessionMiddleware, :secret=>SecureRandom.random_bytes(64), :key=>'rack.session'
|
29
|
+
else
|
30
|
+
use Rack::Session::Cookie, :secret => "__a_very_long_string__"
|
31
|
+
end
|
24
32
|
|
25
33
|
def erb(s, opts={})
|
26
34
|
render(opts.merge(:inline=>s))
|
data/spec/sequel_plugin_spec.rb
CHANGED
@@ -134,7 +134,7 @@ describe "Forme Sequel::Model forms" do
|
|
134
134
|
|
135
135
|
it "should handle errors on radio buttons for boolean fields if :as=>:radio is used" do
|
136
136
|
@ab.errors.add(:platinum, 'foo')
|
137
|
-
@b.input(:platinum, :as=>:radio).to_s.must_equal '<span class="label">Platinum</span><label class="option"><input id="album_platinum_yes" name="album[platinum]" type="radio" value="t"/> Yes</label><label class="option"><input checked="checked" class="error" id="album_platinum_no" name="album[platinum]" type="radio" value="f"/> No</label><span class="error_message">foo</span>'
|
137
|
+
@b.input(:platinum, :as=>:radio).to_s.must_equal '<span class="label">Platinum</span><label class="option"><input id="album_platinum_yes" name="album[platinum]" type="radio" value="t"/> Yes</label><label class="option"><input aria-describedby="album_platinum_no_error_message" aria-invalid="true" checked="checked" class="error" id="album_platinum_no" name="album[platinum]" type="radio" value="f"/> No</label><span class="error_message" id="album_platinum_no_error_message">foo</span>'
|
138
138
|
end
|
139
139
|
|
140
140
|
it "should handle Raw :label options if :as=>:radio is used" do
|
@@ -272,8 +272,8 @@ describe "Forme Sequel::Model forms" do
|
|
272
272
|
|
273
273
|
it "should handle an error message on the underlying column for pg_array_to_many associations" do
|
274
274
|
@ab.errors.add(:atag_ids, 'tis not valid')
|
275
|
-
@b.input(:atags).to_s.must_equal '<label>Atags: <select class="error" id="album_atag_ids" multiple="multiple" name="album[atag_ids][]"><option selected="selected" value="1">s</option><option selected="selected" value="2">t</option><option value="3">u</option></select></label><span class="error_message">tis not valid</span>'
|
276
|
-
@b.input(:atags, :as=>:checkbox).to_s.must_equal '<span class="label">Atags</span><label class="option"><input checked="checked" id="album_atag_ids_1" name="album[atag_ids][]" type="checkbox" value="1"/> s</label><label class="option"><input checked="checked" id="album_atag_ids_2" name="album[atag_ids][]" type="checkbox" value="2"/> t</label><label class="option"><input class="error" id="album_atag_ids_3" name="album[atag_ids][]" type="checkbox" value="3"/> u</label><span class="error_message">tis not valid</span>'
|
275
|
+
@b.input(:atags).to_s.must_equal '<label>Atags: <select aria-describedby="album_atag_ids_error_message" aria-invalid="true" class="error" id="album_atag_ids" multiple="multiple" name="album[atag_ids][]"><option selected="selected" value="1">s</option><option selected="selected" value="2">t</option><option value="3">u</option></select></label><span class="error_message" id="album_atag_ids_error_message">tis not valid</span>'
|
276
|
+
@b.input(:atags, :as=>:checkbox).to_s.must_equal '<span class="label">Atags</span><label class="option"><input checked="checked" id="album_atag_ids_1" name="album[atag_ids][]" type="checkbox" value="1"/> s</label><label class="option"><input checked="checked" id="album_atag_ids_2" name="album[atag_ids][]" type="checkbox" value="2"/> t</label><label class="option"><input aria-describedby="album_atag_ids_3_error_message" aria-invalid="true" class="error" id="album_atag_ids_3" name="album[atag_ids][]" type="checkbox" value="3"/> u</label><span class="error_message" id="album_atag_ids_3_error_message">tis not valid</span>'
|
277
277
|
end
|
278
278
|
|
279
279
|
it "should use a regular select box for *_to_many associations if multiple if false" do
|
@@ -318,7 +318,7 @@ describe "Forme Sequel::Model forms" do
|
|
318
318
|
|
319
319
|
it "should handle errors on methods not backed by columns" do
|
320
320
|
@ab.errors.add(:artist_name, 'foo')
|
321
|
-
@b.input(:artist_name).to_s.must_equal '<label>Artist name: <input class="error" id="album_artist_name" name="album[artist_name]" type="text" value="a"/></label><span class="error_message">foo</span>'
|
321
|
+
@b.input(:artist_name).to_s.must_equal '<label>Artist name: <input aria-describedby="album_artist_name_error_message" aria-invalid="true" class="error" id="album_artist_name" name="album[artist_name]" type="text" value="a"/></label><span class="error_message" id="album_artist_name_error_message">foo</span>'
|
322
322
|
end
|
323
323
|
|
324
324
|
it "should respect a :type option with a schema type as the input type for methods not backed by columns" do
|
@@ -333,12 +333,12 @@ describe "Forme Sequel::Model forms" do
|
|
333
333
|
|
334
334
|
it "should correctly show an error message if there is one" do
|
335
335
|
@ab.errors.add(:name, 'tis not valid')
|
336
|
-
@b.input(:name).to_s.must_equal '<label>Name: <input class="error" id="album_name" maxlength="255" name="album[name]" type="text" value="b"/></label><span class="error_message">tis not valid</span>'
|
336
|
+
@b.input(:name).to_s.must_equal '<label>Name: <input aria-describedby="album_name_error_message" aria-invalid="true" class="error" id="album_name" maxlength="255" name="album[name]" type="text" value="b"/></label><span class="error_message" id="album_name_error_message">tis not valid</span>'
|
337
337
|
end
|
338
338
|
|
339
339
|
it "should correctly show an error message for many_to_one associations if there is one" do
|
340
340
|
@ab.errors.add(:artist_id, 'tis not valid')
|
341
|
-
@b.input(:artist).to_s.must_equal '<label>Artist: <select class="error" id="album_artist_id" name="album[artist_id]"><option value=""></option><option selected="selected" value="1">a</option><option value="2">d</option></select></label><span class="error_message">tis not valid</span>'
|
341
|
+
@b.input(:artist).to_s.must_equal '<label>Artist: <select aria-describedby="album_artist_id_error_message" aria-invalid="true" class="error" id="album_artist_id" name="album[artist_id]"><option value=""></option><option selected="selected" value="1">a</option><option value="2">d</option></select></label><span class="error_message" id="album_artist_id_error_message">tis not valid</span>'
|
342
342
|
end
|
343
343
|
|
344
344
|
it "should raise an error for unhandled associations" do
|
metadata
CHANGED
@@ -1,14 +1,14 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: forme
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 1.
|
4
|
+
version: 1.10.0
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- Jeremy Evans
|
8
8
|
autorequire:
|
9
9
|
bindir: bin
|
10
10
|
cert_chain: []
|
11
|
-
date:
|
11
|
+
date: 2019-05-13 00:00:00.000000000 Z
|
12
12
|
dependencies:
|
13
13
|
- !ruby/object:Gem::Dependency
|
14
14
|
name: minitest
|
@@ -220,8 +220,7 @@ required_rubygems_version: !ruby/object:Gem::Requirement
|
|
220
220
|
- !ruby/object:Gem::Version
|
221
221
|
version: '0'
|
222
222
|
requirements: []
|
223
|
-
|
224
|
-
rubygems_version: 2.7.6
|
223
|
+
rubygems_version: 3.0.3
|
225
224
|
signing_key:
|
226
225
|
specification_version: 4
|
227
226
|
summary: HTML forms library
|