simple_form_with_client_validation 0.0.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.
- data/CHANGELOG.md +6 -0
- data/MIT-LICENSE +20 -0
- data/README.md +783 -0
- data/lib/generators/simple_form_with_client_validation/USAGE +3 -0
- data/lib/generators/simple_form_with_client_validation/install_generator.rb +32 -0
- data/lib/generators/simple_form_with_client_validation/templates/README +12 -0
- data/lib/generators/simple_form_with_client_validation/templates/_form.html.erb +13 -0
- data/lib/generators/simple_form_with_client_validation/templates/_form.html.haml +10 -0
- data/lib/generators/simple_form_with_client_validation/templates/_form.html.slim +10 -0
- data/lib/generators/simple_form_with_client_validation/templates/config/initializers/simple_form.rb.tt +179 -0
- data/lib/generators/simple_form_with_client_validation/templates/config/locales/simple_form.en.yml +26 -0
- data/lib/simple_form_with_client_validation/action_view_extensions/builder.rb +331 -0
- data/lib/simple_form_with_client_validation/action_view_extensions/form_helper.rb +74 -0
- data/lib/simple_form_with_client_validation/components/errors.rb +35 -0
- data/lib/simple_form_with_client_validation/components/hints.rb +18 -0
- data/lib/simple_form_with_client_validation/components/html5.rb +26 -0
- data/lib/simple_form_with_client_validation/components/label_input.rb +15 -0
- data/lib/simple_form_with_client_validation/components/labels.rb +79 -0
- data/lib/simple_form_with_client_validation/components/maxlength.rb +41 -0
- data/lib/simple_form_with_client_validation/components/min_max.rb +50 -0
- data/lib/simple_form_with_client_validation/components/minlength.rb +41 -0
- data/lib/simple_form_with_client_validation/components/pattern.rb +34 -0
- data/lib/simple_form_with_client_validation/components/placeholders.rb +16 -0
- data/lib/simple_form_with_client_validation/components/readonly.rb +22 -0
- data/lib/simple_form_with_client_validation/components.rb +21 -0
- data/lib/simple_form_with_client_validation/core_ext/hash.rb +16 -0
- data/lib/simple_form_with_client_validation/error_notification.rb +48 -0
- data/lib/simple_form_with_client_validation/form_builder.rb +484 -0
- data/lib/simple_form_with_client_validation/helpers/autofocus.rb +11 -0
- data/lib/simple_form_with_client_validation/helpers/disabled.rb +15 -0
- data/lib/simple_form_with_client_validation/helpers/readonly.rb +15 -0
- data/lib/simple_form_with_client_validation/helpers/required.rb +35 -0
- data/lib/simple_form_with_client_validation/helpers/validators.rb +44 -0
- data/lib/simple_form_with_client_validation/helpers.rb +12 -0
- data/lib/simple_form_with_client_validation/i18n_cache.rb +22 -0
- data/lib/simple_form_with_client_validation/inputs/base.rb +162 -0
- data/lib/simple_form_with_client_validation/inputs/block_input.rb +14 -0
- data/lib/simple_form_with_client_validation/inputs/boolean_input.rb +64 -0
- data/lib/simple_form_with_client_validation/inputs/collection_check_boxes_input.rb +21 -0
- data/lib/simple_form_with_client_validation/inputs/collection_input.rb +101 -0
- data/lib/simple_form_with_client_validation/inputs/collection_radio_buttons_input.rb +63 -0
- data/lib/simple_form_with_client_validation/inputs/collection_select_input.rb +14 -0
- data/lib/simple_form_with_client_validation/inputs/date_time_input.rb +28 -0
- data/lib/simple_form_with_client_validation/inputs/file_input.rb +9 -0
- data/lib/simple_form_with_client_validation/inputs/grouped_collection_select_input.rb +41 -0
- data/lib/simple_form_with_client_validation/inputs/hidden_input.rb +17 -0
- data/lib/simple_form_with_client_validation/inputs/numeric_input.rb +24 -0
- data/lib/simple_form_with_client_validation/inputs/password_input.rb +12 -0
- data/lib/simple_form_with_client_validation/inputs/priority_input.rb +24 -0
- data/lib/simple_form_with_client_validation/inputs/range_input.rb +14 -0
- data/lib/simple_form_with_client_validation/inputs/string_input.rb +23 -0
- data/lib/simple_form_with_client_validation/inputs/text_input.rb +11 -0
- data/lib/simple_form_with_client_validation/inputs.rb +21 -0
- data/lib/simple_form_with_client_validation/map_type.rb +16 -0
- data/lib/simple_form_with_client_validation/version.rb +3 -0
- data/lib/simple_form_with_client_validation/wrappers/builder.rb +115 -0
- data/lib/simple_form_with_client_validation/wrappers/many.rb +78 -0
- data/lib/simple_form_with_client_validation/wrappers/root.rb +34 -0
- data/lib/simple_form_with_client_validation/wrappers/single.rb +18 -0
- data/lib/simple_form_with_client_validation/wrappers.rb +8 -0
- data/lib/simple_form_with_client_validation.rb +218 -0
- data/test/action_view_extensions/builder_test.rb +577 -0
- data/test/action_view_extensions/form_helper_test.rb +104 -0
- data/test/components/label_test.rb +310 -0
- data/test/form_builder/association_test.rb +177 -0
- data/test/form_builder/button_test.rb +47 -0
- data/test/form_builder/error_notification_test.rb +79 -0
- data/test/form_builder/error_test.rb +121 -0
- data/test/form_builder/general_test.rb +356 -0
- data/test/form_builder/hint_test.rb +139 -0
- data/test/form_builder/input_field_test.rb +63 -0
- data/test/form_builder/label_test.rb +71 -0
- data/test/form_builder/wrapper_test.rb +149 -0
- data/test/generators/simple_form_generator_test.rb +32 -0
- data/test/inputs/boolean_input_test.rb +108 -0
- data/test/inputs/collection_check_boxes_input_test.rb +224 -0
- data/test/inputs/collection_radio_buttons_input_test.rb +326 -0
- data/test/inputs/collection_select_input_test.rb +241 -0
- data/test/inputs/datetime_input_test.rb +99 -0
- data/test/inputs/disabled_test.rb +38 -0
- data/test/inputs/discovery_test.rb +61 -0
- data/test/inputs/file_input_test.rb +16 -0
- data/test/inputs/general_test.rb +69 -0
- data/test/inputs/grouped_collection_select_input_test.rb +118 -0
- data/test/inputs/hidden_input_test.rb +30 -0
- data/test/inputs/numeric_input_test.rb +173 -0
- data/test/inputs/priority_input_test.rb +43 -0
- data/test/inputs/readonly_test.rb +61 -0
- data/test/inputs/required_test.rb +113 -0
- data/test/inputs/string_input_test.rb +140 -0
- data/test/inputs/text_input_test.rb +29 -0
- data/test/simple_form_test.rb +9 -0
- data/test/support/discovery_inputs.rb +21 -0
- data/test/support/misc_helpers.rb +102 -0
- data/test/support/mock_controller.rb +24 -0
- data/test/support/mock_response.rb +14 -0
- data/test/support/models.rb +210 -0
- data/test/test_helper.rb +95 -0
- metadata +227 -0
@@ -0,0 +1,78 @@
|
|
1
|
+
module SimpleFormWithClientValidation
|
2
|
+
module Wrappers
|
3
|
+
# A wrapper is an object that holds several components and render them.
|
4
|
+
# A component may either be a symbol or any object that responds to `render`.
|
5
|
+
# This API allows inputs/components to be easily wrapped, removing the
|
6
|
+
# need to modify the code only to wrap input in an extra tag.
|
7
|
+
#
|
8
|
+
# `Many` represents a wrapper around several components at the same time.
|
9
|
+
# It may optionally receive a namespace, allowing it to be configured
|
10
|
+
# on demand on input generation. The find function returns if it
|
11
|
+
# matches namespace
|
12
|
+
class Many
|
13
|
+
attr_reader :namespace, :defaults, :components
|
14
|
+
alias :to_sym :namespace
|
15
|
+
|
16
|
+
def initialize(namespace, components, defaults={})
|
17
|
+
@namespace = namespace
|
18
|
+
@components = components
|
19
|
+
@defaults = defaults
|
20
|
+
@defaults[:tag] = :div unless @defaults.key?(:tag)
|
21
|
+
@defaults[:class] = Array.wrap(@defaults[:class])
|
22
|
+
end
|
23
|
+
|
24
|
+
def render(input)
|
25
|
+
content = "".html_safe
|
26
|
+
options = input.options
|
27
|
+
|
28
|
+
components.each do |component|
|
29
|
+
next if options[component] == false
|
30
|
+
rendered = component.respond_to?(:render) ? component.render(input) : input.send(component)
|
31
|
+
content.safe_concat rendered.to_s if rendered
|
32
|
+
end
|
33
|
+
|
34
|
+
wrap(input, options, content)
|
35
|
+
end
|
36
|
+
|
37
|
+
def find(name)
|
38
|
+
return self if namespace == name
|
39
|
+
|
40
|
+
@components.each do |c|
|
41
|
+
if c.is_a?(Symbol)
|
42
|
+
return nil if c == namespace
|
43
|
+
elsif value = c.find(name)
|
44
|
+
return value
|
45
|
+
end
|
46
|
+
end
|
47
|
+
|
48
|
+
nil
|
49
|
+
end
|
50
|
+
|
51
|
+
private
|
52
|
+
|
53
|
+
#this will wrap the content
|
54
|
+
#unless options for this namespace=false which is set by b.optional :namespace
|
55
|
+
#and user didn't explicitly set one
|
56
|
+
def wrap(input, options, content)
|
57
|
+
|
58
|
+
#this would be triggered if b.optional :namespace and user didn't supply :namespace explicitly
|
59
|
+
#in b.input :myfield, :namespace => "something"
|
60
|
+
return content if options[namespace] == false
|
61
|
+
|
62
|
+
tag = (namespace && options[:"#{namespace}_tag"]) || @defaults[:tag]
|
63
|
+
return content unless tag
|
64
|
+
|
65
|
+
klass = html_classes(input, options)
|
66
|
+
opts = options[:"#{namespace}_html"] || {}
|
67
|
+
opts[:class] = (klass << opts[:class]).join(' ').strip unless klass.empty?
|
68
|
+
|
69
|
+
#this outputs into @builder.template of input
|
70
|
+
input.template.content_tag(tag, content, opts)
|
71
|
+
end
|
72
|
+
|
73
|
+
def html_classes(input, options)
|
74
|
+
@defaults[:class].dup
|
75
|
+
end
|
76
|
+
end
|
77
|
+
end
|
78
|
+
end
|
@@ -0,0 +1,34 @@
|
|
1
|
+
module SimpleFormWithClientValidation
|
2
|
+
module Wrappers
|
3
|
+
# `Root` is the root wrapper for all components. It is special cased to
|
4
|
+
# always have a namespace and to add special html classes.
|
5
|
+
class Root < Many
|
6
|
+
attr_reader :options
|
7
|
+
|
8
|
+
def initialize(*args)
|
9
|
+
super(:wrapper, *args)
|
10
|
+
@options = @defaults.except(:tag, :class, :error_class, :hint_class)
|
11
|
+
end
|
12
|
+
|
13
|
+
def render(input)
|
14
|
+
input.options.reverse_merge!(@options)
|
15
|
+
super
|
16
|
+
end
|
17
|
+
|
18
|
+
# Provide a fallback if name cannot be found.
|
19
|
+
def find(name)
|
20
|
+
super || SimpleFormWithClientValidation::Wrappers::Many.new(name, [name])
|
21
|
+
end
|
22
|
+
|
23
|
+
private
|
24
|
+
|
25
|
+
def html_classes(input, options)
|
26
|
+
css = options[:wrapper_class] ? Array.wrap(options[:wrapper_class]) : @defaults[:class]
|
27
|
+
css += SimpleFormWithClientValidation.additional_classes_for(:wrapper) { input.html_classes }
|
28
|
+
css << (options[:wrapper_error_class] || @defaults[:error_class]) if input.has_errors?
|
29
|
+
css << (options[:wrapper_hint_class] || @defaults[:hint_class]) if input.has_hint?
|
30
|
+
css
|
31
|
+
end
|
32
|
+
end
|
33
|
+
end
|
34
|
+
end
|
@@ -0,0 +1,18 @@
|
|
1
|
+
module SimpleFormWithClientValidation
|
2
|
+
module Wrappers
|
3
|
+
# `Single` is an optimization for a wrapper that has only one component.
|
4
|
+
class Single < Many
|
5
|
+
def initialize(name, options={})
|
6
|
+
super(name, [name], options)
|
7
|
+
end
|
8
|
+
|
9
|
+
def render(input)
|
10
|
+
options = input.options
|
11
|
+
if options[namespace] != false
|
12
|
+
content = input.send(namespace)
|
13
|
+
wrap(input, options, content) if content
|
14
|
+
end
|
15
|
+
end
|
16
|
+
end
|
17
|
+
end
|
18
|
+
end
|
@@ -0,0 +1,8 @@
|
|
1
|
+
module SimpleFormWithClientValidation
|
2
|
+
module Wrappers
|
3
|
+
autoload :Builder, 'simple_form_with_client_validation/wrappers/builder'
|
4
|
+
autoload :Many, 'simple_form_with_client_validation/wrappers/many'
|
5
|
+
autoload :Root, 'simple_form_with_client_validation/wrappers/root'
|
6
|
+
autoload :Single, 'simple_form_with_client_validation/wrappers/single'
|
7
|
+
end
|
8
|
+
end
|
@@ -0,0 +1,218 @@
|
|
1
|
+
require 'action_view'
|
2
|
+
require 'simple_form_with_client_validation/action_view_extensions/form_helper'
|
3
|
+
require 'simple_form_with_client_validation/action_view_extensions/builder'
|
4
|
+
require 'active_support/core_ext/hash/slice'
|
5
|
+
require 'active_support/core_ext/hash/except'
|
6
|
+
require 'active_support/core_ext/hash/reverse_merge'
|
7
|
+
|
8
|
+
module SimpleFormWithClientValidation
|
9
|
+
autoload :Components, 'simple_form_with_client_validation/components'
|
10
|
+
autoload :ErrorNotification, 'simple_form_with_client_validation/error_notification'
|
11
|
+
autoload :FormBuilder, 'simple_form_with_client_validation/form_builder'
|
12
|
+
autoload :Helpers, 'simple_form_with_client_validation/helpers'
|
13
|
+
autoload :I18nCache, 'simple_form_with_client_validation/i18n_cache'
|
14
|
+
autoload :Inputs, 'simple_form_with_client_validation/inputs'
|
15
|
+
autoload :MapType, 'simple_form_with_client_validation/map_type'
|
16
|
+
autoload :Wrappers, 'simple_form_with_client_validation/wrappers'
|
17
|
+
|
18
|
+
## CONFIGURATION OPTIONS
|
19
|
+
|
20
|
+
# Method used to tidy up errors.
|
21
|
+
mattr_accessor :error_method
|
22
|
+
@@error_method = :first
|
23
|
+
|
24
|
+
# Default tag used for error notification helper.
|
25
|
+
mattr_accessor :error_notification_tag
|
26
|
+
@@error_notification_tag = :p
|
27
|
+
|
28
|
+
# CSS class to add for error notification helper.
|
29
|
+
mattr_accessor :error_notification_class
|
30
|
+
@@error_notification_class = :error_notification
|
31
|
+
|
32
|
+
# Series of attemps to detect a default label method for collection.
|
33
|
+
mattr_accessor :collection_label_methods
|
34
|
+
@@collection_label_methods = [ :to_label, :name, :title, :to_s ]
|
35
|
+
|
36
|
+
# Series of attemps to detect a default value method for collection.
|
37
|
+
mattr_accessor :collection_value_methods
|
38
|
+
@@collection_value_methods = [ :id, :to_s ]
|
39
|
+
|
40
|
+
# You can wrap a collection of radio/check boxes in a pre-defined tag, defaulting to none.
|
41
|
+
mattr_accessor :collection_wrapper_tag
|
42
|
+
@@collection_wrapper_tag = nil
|
43
|
+
|
44
|
+
# You can define the class to use on all collection wrappers, defaulting to none.
|
45
|
+
mattr_accessor :collection_wrapper_class
|
46
|
+
@@collection_wrapper_class = nil
|
47
|
+
|
48
|
+
# You can wrap each item in a collection of radio/check boxes with a tag,
|
49
|
+
# defaulting to none. Please note that when using :boolean_style = :nested,
|
50
|
+
# SimpleFormWithClientValidation will force this option to be a :label.
|
51
|
+
mattr_accessor :item_wrapper_tag
|
52
|
+
@@item_wrapper_tag = :span
|
53
|
+
|
54
|
+
# You can define the class to use on all item wrappers, defaulting to none.
|
55
|
+
mattr_accessor :item_wrapper_class
|
56
|
+
@@item_wrapper_class = nil
|
57
|
+
|
58
|
+
# How the label text should be generated altogether with the required text.
|
59
|
+
mattr_accessor :label_text
|
60
|
+
@@label_text = lambda { |label, required| "#{required} #{label}" }
|
61
|
+
|
62
|
+
# You can define the class to use on all labels. Default is nil.
|
63
|
+
mattr_accessor :label_class
|
64
|
+
@@label_class = nil
|
65
|
+
|
66
|
+
# Define the way to render check boxes / radio buttons with labels.
|
67
|
+
# :inline => input + label (default)
|
68
|
+
# :nested => label > input
|
69
|
+
mattr_accessor :boolean_style
|
70
|
+
@@boolean_style = :inline
|
71
|
+
|
72
|
+
# You can define the class to use on all forms. Default is simple_form.
|
73
|
+
mattr_accessor :form_class
|
74
|
+
@@form_class = :simple_form
|
75
|
+
|
76
|
+
# You can define which elements should obtain additional classes
|
77
|
+
mattr_accessor :generate_additional_classes_for
|
78
|
+
@@generate_additional_classes_for = [:wrapper, :label, :input]
|
79
|
+
|
80
|
+
# Whether attributes are required by default (or not).
|
81
|
+
mattr_accessor :required_by_default
|
82
|
+
@@required_by_default = true
|
83
|
+
|
84
|
+
# Tell browsers whether to use default HTML5 validations (novalidate option).
|
85
|
+
mattr_accessor :browser_validations
|
86
|
+
@@browser_validations = true
|
87
|
+
|
88
|
+
# Collection of methods to detect if a file type was given.
|
89
|
+
mattr_accessor :file_methods
|
90
|
+
@@file_methods = [ :mounted_as, :file?, :public_filename ]
|
91
|
+
|
92
|
+
# Custom mappings for input types. This should be a hash containing a regexp
|
93
|
+
# to match as key, and the input type that will be used when the field name
|
94
|
+
# matches the regexp as value, such as { /count/ => :integer }.
|
95
|
+
mattr_accessor :input_mappings
|
96
|
+
@@input_mappings = nil
|
97
|
+
|
98
|
+
# Default priority for time_zone inputs.
|
99
|
+
mattr_accessor :time_zone_priority
|
100
|
+
@@time_zone_priority = nil
|
101
|
+
|
102
|
+
# Default priority for country inputs.
|
103
|
+
mattr_accessor :country_priority
|
104
|
+
@@country_priority = nil
|
105
|
+
|
106
|
+
# Maximum size allowed for inputs.
|
107
|
+
mattr_accessor :default_input_size
|
108
|
+
@@default_input_size = 50
|
109
|
+
|
110
|
+
# When off, do not use translations in labels. Disabling translation in
|
111
|
+
# hints and placeholders can be done manually in the wrapper API.
|
112
|
+
mattr_accessor :translate_labels
|
113
|
+
@@translate_labels = true
|
114
|
+
|
115
|
+
# Automatically discover new inputs in Rails' autoload path.
|
116
|
+
mattr_accessor :inputs_discovery
|
117
|
+
@@inputs_discovery = true
|
118
|
+
|
119
|
+
# Cache SimpleFormWithClientValidation inputs discovery
|
120
|
+
mattr_accessor :cache_discovery
|
121
|
+
@@cache_discovery = defined?(Rails) && !Rails.env.development?
|
122
|
+
|
123
|
+
# Adds a class to each generated button, mostly for compatiblity
|
124
|
+
mattr_accessor :button_class
|
125
|
+
@@button_class = 'button'
|
126
|
+
|
127
|
+
## WRAPPER CONFIGURATION
|
128
|
+
# The default wrapper to be used by the FormBuilder.
|
129
|
+
mattr_accessor :default_wrapper
|
130
|
+
@@default_wrapper = :default
|
131
|
+
@@wrappers = {}
|
132
|
+
|
133
|
+
# Retrieves a given wrapper
|
134
|
+
def self.wrapper(name)
|
135
|
+
@@wrappers[name.to_sym] or raise WrapperNotFound, "Couldn't find wrapper with name #{name}"
|
136
|
+
end
|
137
|
+
|
138
|
+
# Raised when fails to find a given wrapper name
|
139
|
+
class WrapperNotFound < StandardError
|
140
|
+
end
|
141
|
+
|
142
|
+
# Define a new wrapper using SimpleFormWithClientValidation::Wrappers::Builder
|
143
|
+
# and store it in the given name.
|
144
|
+
def self.wrappers(*args, &block)
|
145
|
+
if block_given?
|
146
|
+
options = args.extract_options!
|
147
|
+
name = args.first || :default
|
148
|
+
@@wrappers[name.to_sym] = build(options, &block)
|
149
|
+
else
|
150
|
+
@@wrappers
|
151
|
+
end
|
152
|
+
end
|
153
|
+
|
154
|
+
# Builds a new wrapper using SimpleFormWithClientValidation::Wrappers::Builder.
|
155
|
+
def self.build(options={})
|
156
|
+
options[:tag] = :div if options[:tag].nil?
|
157
|
+
builder = SimpleFormWithClientValidation::Wrappers::Builder.new(options)
|
158
|
+
yield builder
|
159
|
+
SimpleFormWithClientValidation::Wrappers::Root.new(builder.to_a, options)
|
160
|
+
end
|
161
|
+
|
162
|
+
#this creates a :default wrapper that will be overridden if user configures
|
163
|
+
#one in config/initializers/simple_form_with_client_validation.rb
|
164
|
+
wrappers :class => :input, :hint_class => :field_with_hint, :error_class => :field_with_errors do |b|
|
165
|
+
b.use :html5
|
166
|
+
|
167
|
+
b.use :min_max
|
168
|
+
b.use :maxlength
|
169
|
+
b.use :minlength
|
170
|
+
b.use :placeholder
|
171
|
+
b.optional :pattern
|
172
|
+
b.optional :readonly
|
173
|
+
|
174
|
+
b.use :label_input
|
175
|
+
b.use :hint, :wrap_with => { :tag => :span, :class => :hint }
|
176
|
+
b.use :error, :wrap_with => { :tag => :span, :class => :error }
|
177
|
+
end
|
178
|
+
|
179
|
+
## SETUP
|
180
|
+
|
181
|
+
DEPRECATED = %w(hint_tag hint_class error_tag error_class error_notification_id wrapper_tag wrapper_class wrapper_error_class components html5)
|
182
|
+
@@deprecated = []
|
183
|
+
|
184
|
+
DEPRECATED.each do |method|
|
185
|
+
class_eval "def self.#{method}=(*); @@deprecated << :#{method}=; end"
|
186
|
+
class_eval "def self.#{method}; deprecation_warn 'SimpleFormWithClientValidation.#{method} is deprecated and has no effect'; end"
|
187
|
+
end
|
188
|
+
|
189
|
+
def self.translate=(value)
|
190
|
+
deprecation_warn "SimpleFormWithClientValidation.translate= is disabled in favor of translate_labels="
|
191
|
+
self.translate_labels = value
|
192
|
+
end
|
193
|
+
|
194
|
+
def self.translate
|
195
|
+
deprecation_warn "SimpleFormWithClientValidation.translate is disabled in favor of translate_labels"
|
196
|
+
self.translate_labels
|
197
|
+
end
|
198
|
+
|
199
|
+
def self.deprecation_warn(message)
|
200
|
+
ActiveSupport::Deprecation.warn "[SIMPLE_FORM] #{message}", caller
|
201
|
+
end
|
202
|
+
|
203
|
+
def self.additional_classes_for(component)
|
204
|
+
generate_additional_classes_for.include?(component) ? yield : []
|
205
|
+
end
|
206
|
+
|
207
|
+
# Default way to setup SimpleFormWithClientValidation. Run rails generate simple_form:install
|
208
|
+
# to create a fresh initializer with all configuration values.
|
209
|
+
def self.setup
|
210
|
+
yield self
|
211
|
+
|
212
|
+
unless @@deprecated.empty?
|
213
|
+
raise "[SIMPLE FORM] Your SimpleFormWithClientValidation initializer file is using the following methods: #{@@deprecated.to_sentence}. " <<
|
214
|
+
"Those methods are part of the outdated configuration API. Updating to the new API is easy and fast. " <<
|
215
|
+
"Check for more info here: https://github.com/plataformatec/simple_form/wiki/Upgrading-to-Simple-Form-2.0"
|
216
|
+
end
|
217
|
+
end
|
218
|
+
end
|
@@ -0,0 +1,577 @@
|
|
1
|
+
require 'test_helper'
|
2
|
+
|
3
|
+
class BuilderTest < ActionView::TestCase
|
4
|
+
def with_custom_form_for(object, *args, &block)
|
5
|
+
with_concat_custom_form_for(object) do |f|
|
6
|
+
assert f.instance_of?(CustomFormBuilder)
|
7
|
+
yield f
|
8
|
+
end
|
9
|
+
end
|
10
|
+
|
11
|
+
def with_collection_radio_buttons(object, attribute, collection, value_method, text_method, options={}, html_options={}, &block)
|
12
|
+
with_concat_form_for(object) do |f|
|
13
|
+
f.collection_radio_buttons attribute, collection, value_method, text_method, options, html_options, &block
|
14
|
+
end
|
15
|
+
end
|
16
|
+
|
17
|
+
def with_collection_check_boxes(object, attribute, collection, value_method, text_method, options={}, html_options={}, &block)
|
18
|
+
with_concat_form_for(object) do |f|
|
19
|
+
f.collection_check_boxes attribute, collection, value_method, text_method, options, html_options, &block
|
20
|
+
end
|
21
|
+
end
|
22
|
+
|
23
|
+
# COLLECTION RADIO
|
24
|
+
test 'collection radio accepts a collection and generate inputs from value method' do
|
25
|
+
with_collection_radio_buttons @user, :active, [true, false], :to_s, :to_s
|
26
|
+
|
27
|
+
assert_select 'form input[type=radio][value=true]#user_active_true'
|
28
|
+
assert_select 'form input[type=radio][value=false]#user_active_false'
|
29
|
+
end
|
30
|
+
|
31
|
+
test 'collection radio accepts a collection and generate inputs from label method' do
|
32
|
+
with_collection_radio_buttons @user, :active, [true, false], :to_s, :to_s
|
33
|
+
|
34
|
+
assert_select 'form label.collection_radio_buttons[for=user_active_true]', 'true'
|
35
|
+
assert_select 'form label.collection_radio_buttons[for=user_active_false]', 'false'
|
36
|
+
end
|
37
|
+
|
38
|
+
test 'collection radio handles camelized collection values for labels correctly' do
|
39
|
+
with_collection_radio_buttons @user, :active, ['Yes', 'No'], :to_s, :to_s
|
40
|
+
|
41
|
+
assert_select 'form label.collection_radio_buttons[for=user_active_yes]', 'Yes'
|
42
|
+
assert_select 'form label.collection_radio_buttons[for=user_active_no]', 'No'
|
43
|
+
end
|
44
|
+
|
45
|
+
test 'collection radio should sanitize collection values for labels correctly' do
|
46
|
+
with_collection_radio_buttons @user, :name, ['$0.99', '$1.99'], :to_s, :to_s
|
47
|
+
assert_select 'label.collection_radio_buttons[for=user_name_099]', '$0.99'
|
48
|
+
assert_select 'label.collection_radio_buttons[for=user_name_199]', '$1.99'
|
49
|
+
end
|
50
|
+
|
51
|
+
test 'collection radio checks the correct value to local variables' do
|
52
|
+
user = User.new
|
53
|
+
user.active = false
|
54
|
+
with_collection_radio_buttons user, :active, [true, false], :to_s, :to_s
|
55
|
+
|
56
|
+
assert_select 'form input[type=radio][value=true]'
|
57
|
+
assert_select 'form input[type=radio][value=false][checked=checked]'
|
58
|
+
end
|
59
|
+
|
60
|
+
test 'collection radio accepts checked item' do
|
61
|
+
with_collection_radio_buttons @user, :active, [[1, true], [0, false]], :last, :first, :checked => true
|
62
|
+
|
63
|
+
assert_select 'form input[type=radio][value=true][checked=checked]'
|
64
|
+
assert_no_select 'form input[type=radio][value=false][checked=checked]'
|
65
|
+
end
|
66
|
+
|
67
|
+
test 'collection radio accepts checked item which has a value of false' do
|
68
|
+
with_collection_radio_buttons @user, :active, [[1, true], [0, false]], :last, :first, :checked => false
|
69
|
+
assert_no_select 'form input[type=radio][value=true][checked=checked]'
|
70
|
+
assert_select 'form input[type=radio][value=false][checked=checked]'
|
71
|
+
end
|
72
|
+
|
73
|
+
test 'collection radio accepts multiple disabled items' do
|
74
|
+
collection = [[1, true], [0, false], [2, 'other']]
|
75
|
+
with_collection_radio_buttons @user, :active, collection, :last, :first, :disabled => [true, false]
|
76
|
+
|
77
|
+
assert_select 'form input[type=radio][value=true][disabled=disabled]'
|
78
|
+
assert_select 'form input[type=radio][value=false][disabled=disabled]'
|
79
|
+
assert_no_select 'form input[type=radio][value=other][disabled=disabled]'
|
80
|
+
end
|
81
|
+
|
82
|
+
test 'collection radio accepts single disable item' do
|
83
|
+
collection = [[1, true], [0, false]]
|
84
|
+
with_collection_radio_buttons @user, :active, collection, :last, :first, :disabled => true
|
85
|
+
|
86
|
+
assert_select 'form input[type=radio][value=true][disabled=disabled]'
|
87
|
+
assert_no_select 'form input[type=radio][value=false][disabled=disabled]'
|
88
|
+
end
|
89
|
+
|
90
|
+
test 'collection radio accepts html options as input' do
|
91
|
+
collection = [[1, true], [0, false]]
|
92
|
+
with_collection_radio_buttons @user, :active, collection, :last, :first, {}, :class => 'special-radio'
|
93
|
+
|
94
|
+
assert_select 'form input[type=radio][value=true].special-radio#user_active_true'
|
95
|
+
assert_select 'form input[type=radio][value=false].special-radio#user_active_false'
|
96
|
+
end
|
97
|
+
|
98
|
+
test 'collection radio wraps the collection in the given collection wrapper tag' do
|
99
|
+
with_collection_radio_buttons @user, :active, [true, false], :to_s, :to_s, :collection_wrapper_tag => :ul
|
100
|
+
|
101
|
+
assert_select 'form ul input[type=radio]', :count => 2
|
102
|
+
end
|
103
|
+
|
104
|
+
test 'collection radio does not render any wrapper tag by default' do
|
105
|
+
with_collection_radio_buttons @user, :active, [true, false], :to_s, :to_s
|
106
|
+
|
107
|
+
assert_select 'form input[type=radio]', :count => 2
|
108
|
+
assert_no_select 'form ul'
|
109
|
+
end
|
110
|
+
|
111
|
+
test 'collection radio does not wrap the collection when given falsy values' do
|
112
|
+
with_collection_radio_buttons @user, :active, [true, false], :to_s, :to_s, :collection_wrapper_tag => false
|
113
|
+
|
114
|
+
assert_select 'form input[type=radio]', :count => 2
|
115
|
+
assert_no_select 'form ul'
|
116
|
+
end
|
117
|
+
|
118
|
+
test 'collection radio uses the given class for collection wrapper tag' do
|
119
|
+
with_collection_radio_buttons @user, :active, [true, false], :to_s, :to_s,
|
120
|
+
:collection_wrapper_tag => :ul, :collection_wrapper_class => "items-list"
|
121
|
+
|
122
|
+
assert_select 'form ul.items-list input[type=radio]', :count => 2
|
123
|
+
end
|
124
|
+
|
125
|
+
test 'collection radio uses no class for collection wrapper tag when no wrapper tag is given' do
|
126
|
+
with_collection_radio_buttons @user, :active, [true, false], :to_s, :to_s,
|
127
|
+
:collection_wrapper_class => "items-list"
|
128
|
+
|
129
|
+
assert_select 'form input[type=radio]', :count => 2
|
130
|
+
assert_no_select 'form ul'
|
131
|
+
assert_no_select '.items-list'
|
132
|
+
end
|
133
|
+
|
134
|
+
test 'collection radio uses no class for collection wrapper tag by default' do
|
135
|
+
with_collection_radio_buttons @user, :active, [true, false], :to_s, :to_s, :collection_wrapper_tag => :ul
|
136
|
+
|
137
|
+
assert_select 'form ul'
|
138
|
+
assert_no_select 'form ul[class]'
|
139
|
+
end
|
140
|
+
|
141
|
+
test 'collection radio wrap items in a span tag by default' do
|
142
|
+
with_collection_radio_buttons @user, :active, [true, false], :to_s, :to_s
|
143
|
+
|
144
|
+
assert_select 'form span input[type=radio][value=true]#user_active_true + label'
|
145
|
+
assert_select 'form span input[type=radio][value=false]#user_active_false + label'
|
146
|
+
end
|
147
|
+
|
148
|
+
test 'collection radio wraps each item in the given item wrapper tag' do
|
149
|
+
with_collection_radio_buttons @user, :active, [true, false], :to_s, :to_s, :item_wrapper_tag => :li
|
150
|
+
|
151
|
+
assert_select 'form li input[type=radio]', :count => 2
|
152
|
+
end
|
153
|
+
|
154
|
+
test 'collection radio does not wrap each item when given explicitly falsy value' do
|
155
|
+
with_collection_radio_buttons @user, :active, [true, false], :to_s, :to_s, :item_wrapper_tag => false
|
156
|
+
|
157
|
+
assert_select 'form input[type=radio]'
|
158
|
+
assert_no_select 'form span input[type=radio]'
|
159
|
+
end
|
160
|
+
|
161
|
+
test 'collection radio uses the given class for item wrapper tag' do
|
162
|
+
with_collection_radio_buttons @user, :active, [true, false], :to_s, :to_s,
|
163
|
+
:item_wrapper_tag => :li, :item_wrapper_class => "inline"
|
164
|
+
|
165
|
+
assert_select "form li.inline input[type=radio]", :count => 2
|
166
|
+
end
|
167
|
+
|
168
|
+
test 'collection radio uses no class for item wrapper tag when no wrapper tag is given' do
|
169
|
+
with_collection_radio_buttons @user, :active, [true, false], :to_s, :to_s,
|
170
|
+
:item_wrapper_tag => nil, :item_wrapper_class => "inline"
|
171
|
+
|
172
|
+
assert_select 'form input[type=radio]', :count => 2
|
173
|
+
assert_no_select 'form li'
|
174
|
+
assert_no_select '.inline'
|
175
|
+
end
|
176
|
+
|
177
|
+
test 'collection radio uses no class for item wrapper tag by default' do
|
178
|
+
with_collection_radio_buttons @user, :active, [true, false], :to_s, :to_s,
|
179
|
+
:item_wrapper_tag => :li
|
180
|
+
|
181
|
+
assert_select "form li", :count => 2
|
182
|
+
assert_no_select "form li[class]"
|
183
|
+
end
|
184
|
+
|
185
|
+
test 'collection radio does not wrap input inside the label' do
|
186
|
+
with_collection_radio_buttons @user, :active, [true, false], :to_s, :to_s
|
187
|
+
|
188
|
+
assert_select 'form input[type=radio] + label'
|
189
|
+
assert_no_select 'form label input'
|
190
|
+
end
|
191
|
+
|
192
|
+
test 'collection radio accepts a block to render the label as radio button wrapper' do
|
193
|
+
with_collection_radio_buttons :user, :active, [true, false], :to_s, :to_s do |b|
|
194
|
+
b.label { b.radio_button }
|
195
|
+
end
|
196
|
+
|
197
|
+
assert_select 'label[for=user_active_true] > input#user_active_true[type=radio]'
|
198
|
+
assert_select 'label[for=user_active_false] > input#user_active_false[type=radio]'
|
199
|
+
end
|
200
|
+
|
201
|
+
test 'collection radio accepts a block to change the order of label and radio button' do
|
202
|
+
with_collection_radio_buttons :user, :active, [true, false], :to_s, :to_s do |b|
|
203
|
+
b.label + b.radio_button
|
204
|
+
end
|
205
|
+
|
206
|
+
assert_select 'label[for=user_active_true] + input#user_active_true[type=radio]'
|
207
|
+
assert_select 'label[for=user_active_false] + input#user_active_false[type=radio]'
|
208
|
+
end
|
209
|
+
|
210
|
+
test 'collection radio with block helpers accept extra html options' do
|
211
|
+
with_collection_radio_buttons :user, :active, [true, false], :to_s, :to_s do |b|
|
212
|
+
b.label(:class => "radio_button") + b.radio_button(:class => "radio_button")
|
213
|
+
end
|
214
|
+
|
215
|
+
assert_select 'label.radio_button[for=user_active_true] + input#user_active_true.radio_button[type=radio]'
|
216
|
+
assert_select 'label.radio_button[for=user_active_false] + input#user_active_false.radio_button[type=radio]'
|
217
|
+
end
|
218
|
+
|
219
|
+
test 'collection radio with block helpers allows access to current text and value' do
|
220
|
+
with_collection_radio_buttons :user, :active, [true, false], :to_s, :to_s do |b|
|
221
|
+
b.label(:"data-value" => b.value) { b.radio_button + b.text }
|
222
|
+
end
|
223
|
+
|
224
|
+
assert_select 'label[for=user_active_true][data-value=true]', 'true' do
|
225
|
+
assert_select 'input#user_active_true[type=radio]'
|
226
|
+
end
|
227
|
+
assert_select 'label[for=user_active_false][data-value=false]', 'false' do
|
228
|
+
assert_select 'input#user_active_false[type=radio]'
|
229
|
+
end
|
230
|
+
end
|
231
|
+
|
232
|
+
test 'collection radio with block helpers allows access to the current object item in the collection to access extra properties' do
|
233
|
+
with_collection_radio_buttons :user, :active, [true, false], :to_s, :to_s do |b|
|
234
|
+
b.label(:class => b.object) { b.radio_button + b.text }
|
235
|
+
end
|
236
|
+
|
237
|
+
assert_select 'label.true[for=user_active_true]', 'true' do
|
238
|
+
assert_select 'input#user_active_true[type=radio]'
|
239
|
+
end
|
240
|
+
assert_select 'label.false[for=user_active_false]', 'false' do
|
241
|
+
assert_select 'input#user_active_false[type=radio]'
|
242
|
+
end
|
243
|
+
end
|
244
|
+
|
245
|
+
test 'collection_radio helper is deprecated in favor of collection_radio_buttons' do
|
246
|
+
assert_deprecated "[SIMPLE_FORM] The `collection_radio` helper is deprecated, " \
|
247
|
+
"please use `collection_radio_buttons` instead" do
|
248
|
+
with_concat_form_for(@user) do |f|
|
249
|
+
f.collection_radio :active, [true, false], :to_s, :to_s
|
250
|
+
end
|
251
|
+
end
|
252
|
+
|
253
|
+
assert_select 'input[type=radio][value=true]'
|
254
|
+
assert_select 'input[type=radio][value=false]'
|
255
|
+
end
|
256
|
+
|
257
|
+
# COLLECTION CHECK BOX
|
258
|
+
test 'collection check box accepts a collection and generate a serie of checkboxes for value method' do
|
259
|
+
collection = [Tag.new(1, 'Tag 1'), Tag.new(2, 'Tag 2')]
|
260
|
+
with_collection_check_boxes @user, :tag_ids, collection, :id, :name
|
261
|
+
|
262
|
+
assert_select 'form input#user_tag_ids_1[type=checkbox][value=1]'
|
263
|
+
assert_select 'form input#user_tag_ids_2[type=checkbox][value=2]'
|
264
|
+
end
|
265
|
+
|
266
|
+
test 'collection check box generates only one hidden field for the entire collection, to ensure something will be sent back to the server when posting an empty collection' do
|
267
|
+
collection = [Tag.new(1, 'Tag 1'), Tag.new(2, 'Tag 2')]
|
268
|
+
with_collection_check_boxes @user, :tag_ids, collection, :id, :name
|
269
|
+
|
270
|
+
assert_select "form input[type=hidden][name='user[tag_ids][]'][value=]", :count => 1
|
271
|
+
end
|
272
|
+
|
273
|
+
test 'collection check box accepts a collection and generate a serie of checkboxes with labels for label method' do
|
274
|
+
collection = [Tag.new(1, 'Tag 1'), Tag.new(2, 'Tag 2')]
|
275
|
+
with_collection_check_boxes @user, :tag_ids, collection, :id, :name
|
276
|
+
|
277
|
+
assert_select 'form label.collection_check_boxes[for=user_tag_ids_1]', 'Tag 1'
|
278
|
+
assert_select 'form label.collection_check_boxes[for=user_tag_ids_2]', 'Tag 2'
|
279
|
+
end
|
280
|
+
|
281
|
+
test 'collection check box handles camelized collection values for labels correctly' do
|
282
|
+
with_collection_check_boxes @user, :active, ['Yes', 'No'], :to_s, :to_s
|
283
|
+
|
284
|
+
assert_select 'form label.collection_check_boxes[for=user_active_yes]', 'Yes'
|
285
|
+
assert_select 'form label.collection_check_boxes[for=user_active_no]', 'No'
|
286
|
+
end
|
287
|
+
|
288
|
+
test 'collection check box should sanitize collection values for labels correctly' do
|
289
|
+
with_collection_check_boxes @user, :name, ['$0.99', '$1.99'], :to_s, :to_s
|
290
|
+
assert_select 'label.collection_check_boxes[for=user_name_099]', '$0.99'
|
291
|
+
assert_select 'label.collection_check_boxes[for=user_name_199]', '$1.99'
|
292
|
+
end
|
293
|
+
|
294
|
+
test 'collection check box checks the correct value to local variables' do
|
295
|
+
user = User.new
|
296
|
+
user.tag_ids = [1, 3]
|
297
|
+
collection = (1..3).map{|i| [i, "Tag #{i}"] }
|
298
|
+
with_collection_check_boxes user, :tag_ids, collection, :first, :last
|
299
|
+
|
300
|
+
assert_select 'form input[type=checkbox][value=1][checked=checked]'
|
301
|
+
assert_select 'form input[type=checkbox][value=3][checked=checked]'
|
302
|
+
assert_no_select 'form input[type=checkbox][value=2][checked=checked]'
|
303
|
+
end
|
304
|
+
|
305
|
+
|
306
|
+
test 'collection check box accepts selected values as :checked option' do
|
307
|
+
collection = (1..3).map{|i| [i, "Tag #{i}"] }
|
308
|
+
with_collection_check_boxes @user, :tag_ids, collection, :first, :last, :checked => [1, 3]
|
309
|
+
|
310
|
+
assert_select 'form input[type=checkbox][value=1][checked=checked]'
|
311
|
+
assert_select 'form input[type=checkbox][value=3][checked=checked]'
|
312
|
+
assert_no_select 'form input[type=checkbox][value=2][checked=checked]'
|
313
|
+
end
|
314
|
+
|
315
|
+
test 'collection check box accepts a single checked value' do
|
316
|
+
collection = (1..3).map{|i| [i, "Tag #{i}"] }
|
317
|
+
with_collection_check_boxes @user, :tag_ids, collection, :first, :last, :checked => 3
|
318
|
+
|
319
|
+
assert_select 'form input[type=checkbox][value=3][checked=checked]'
|
320
|
+
assert_no_select 'form input[type=checkbox][value=1][checked=checked]'
|
321
|
+
assert_no_select 'form input[type=checkbox][value=2][checked=checked]'
|
322
|
+
end
|
323
|
+
|
324
|
+
test 'collection check box accepts selected values as :checked option and override the model values' do
|
325
|
+
collection = (1..3).map{|i| [i, "Tag #{i}"] }
|
326
|
+
@user.tag_ids = [2]
|
327
|
+
with_collection_check_boxes @user, :tag_ids, collection, :first, :last, :checked => [1, 3]
|
328
|
+
|
329
|
+
assert_select 'form input[type=checkbox][value=1][checked=checked]'
|
330
|
+
assert_select 'form input[type=checkbox][value=3][checked=checked]'
|
331
|
+
assert_no_select 'form input[type=checkbox][value=2][checked=checked]'
|
332
|
+
end
|
333
|
+
|
334
|
+
test 'collection check box accepts multiple disabled items' do
|
335
|
+
collection = (1..3).map{|i| [i, "Tag #{i}"] }
|
336
|
+
with_collection_check_boxes @user, :tag_ids, collection, :first, :last, :disabled => [1, 3]
|
337
|
+
|
338
|
+
assert_select 'form input[type=checkbox][value=1][disabled=disabled]'
|
339
|
+
assert_select 'form input[type=checkbox][value=3][disabled=disabled]'
|
340
|
+
assert_no_select 'form input[type=checkbox][value=2][disabled=disabled]'
|
341
|
+
end
|
342
|
+
|
343
|
+
test 'collection check box accepts single disable item' do
|
344
|
+
collection = (1..3).map{|i| [i, "Tag #{i}"] }
|
345
|
+
with_collection_check_boxes @user, :tag_ids, collection, :first, :last, :disabled => 1
|
346
|
+
|
347
|
+
assert_select 'form input[type=checkbox][value=1][disabled=disabled]'
|
348
|
+
assert_no_select 'form input[type=checkbox][value=3][disabled=disabled]'
|
349
|
+
assert_no_select 'form input[type=checkbox][value=2][disabled=disabled]'
|
350
|
+
end
|
351
|
+
|
352
|
+
test 'collection check box accepts a proc to disabled items' do
|
353
|
+
collection = (1..3).map{|i| [i, "Tag #{i}"] }
|
354
|
+
with_collection_check_boxes @user, :tag_ids, collection, :first, :last, :disabled => proc { |i| i.first == 1 }
|
355
|
+
|
356
|
+
assert_select 'form input[type=checkbox][value=1][disabled=disabled]'
|
357
|
+
assert_no_select 'form input[type=checkbox][value=3][disabled=disabled]'
|
358
|
+
assert_no_select 'form input[type=checkbox][value=2][disabled=disabled]'
|
359
|
+
end
|
360
|
+
|
361
|
+
test 'collection check box accepts html options' do
|
362
|
+
collection = [[1, 'Tag 1'], [2, 'Tag 2']]
|
363
|
+
with_collection_check_boxes @user, :tag_ids, collection, :first, :last, {}, :class => 'check'
|
364
|
+
|
365
|
+
assert_select 'form input.check[type=checkbox][value=1]'
|
366
|
+
assert_select 'form input.check[type=checkbox][value=2]'
|
367
|
+
end
|
368
|
+
|
369
|
+
test 'collection check box with fields for' do
|
370
|
+
collection = [Tag.new(1, 'Tag 1'), Tag.new(2, 'Tag 2')]
|
371
|
+
with_concat_form_for(@user) do |f|
|
372
|
+
f.fields_for(:post) do |p|
|
373
|
+
p.collection_check_boxes :tag_ids, collection, :id, :name
|
374
|
+
end
|
375
|
+
end
|
376
|
+
|
377
|
+
assert_select 'form input#user_post_tag_ids_1[type=checkbox][value=1]'
|
378
|
+
assert_select 'form input#user_post_tag_ids_2[type=checkbox][value=2]'
|
379
|
+
|
380
|
+
assert_select 'form label.collection_check_boxes[for=user_post_tag_ids_1]', 'Tag 1'
|
381
|
+
assert_select 'form label.collection_check_boxes[for=user_post_tag_ids_2]', 'Tag 2'
|
382
|
+
end
|
383
|
+
|
384
|
+
test 'collection check boxes wraps the collection in the given collection wrapper tag' do
|
385
|
+
with_collection_check_boxes @user, :active, [true, false], :to_s, :to_s, :collection_wrapper_tag => :ul
|
386
|
+
|
387
|
+
assert_select 'form ul input[type=checkbox]', :count => 2
|
388
|
+
end
|
389
|
+
|
390
|
+
test 'collection check boxes does not render any wrapper tag by default' do
|
391
|
+
with_collection_check_boxes @user, :active, [true, false], :to_s, :to_s
|
392
|
+
|
393
|
+
assert_select 'form input[type=checkbox]', :count => 2
|
394
|
+
assert_no_select 'form ul'
|
395
|
+
end
|
396
|
+
|
397
|
+
test 'collection check boxes does not wrap the collection when given falsy values' do
|
398
|
+
with_collection_check_boxes @user, :active, [true, false], :to_s, :to_s, :collection_wrapper_tag => false
|
399
|
+
|
400
|
+
assert_select 'form input[type=checkbox]', :count => 2
|
401
|
+
assert_no_select 'form ul'
|
402
|
+
end
|
403
|
+
|
404
|
+
test 'collection check boxes uses the given class for collection wrapper tag' do
|
405
|
+
with_collection_check_boxes @user, :active, [true, false], :to_s, :to_s,
|
406
|
+
:collection_wrapper_tag => :ul, :collection_wrapper_class => "items-list"
|
407
|
+
|
408
|
+
assert_select 'form ul.items-list input[type=checkbox]', :count => 2
|
409
|
+
end
|
410
|
+
|
411
|
+
test 'collection check boxes uses no class for collection wrapper tag when no wrapper tag is given' do
|
412
|
+
with_collection_check_boxes @user, :active, [true, false], :to_s, :to_s,
|
413
|
+
:collection_wrapper_class => "items-list"
|
414
|
+
|
415
|
+
assert_select 'form input[type=checkbox]', :count => 2
|
416
|
+
assert_no_select 'form ul'
|
417
|
+
assert_no_select '.items-list'
|
418
|
+
end
|
419
|
+
|
420
|
+
test 'collection check boxes uses no class for collection wrapper tag by default' do
|
421
|
+
with_collection_check_boxes @user, :active, [true, false], :to_s, :to_s, :collection_wrapper_tag => :ul
|
422
|
+
|
423
|
+
assert_select 'form ul'
|
424
|
+
assert_no_select 'form ul[class]'
|
425
|
+
end
|
426
|
+
|
427
|
+
test 'collection check boxes wrap items in a span tag by default' do
|
428
|
+
with_collection_check_boxes @user, :active, [true, false], :to_s, :to_s
|
429
|
+
|
430
|
+
assert_select 'form span input[type=checkbox]', :count => 2
|
431
|
+
end
|
432
|
+
|
433
|
+
test 'collection check boxes wraps each item in the given item wrapper tag' do
|
434
|
+
with_collection_check_boxes @user, :active, [true, false], :to_s, :to_s, :item_wrapper_tag => :li
|
435
|
+
|
436
|
+
assert_select 'form li input[type=checkbox]', :count => 2
|
437
|
+
end
|
438
|
+
|
439
|
+
test 'collection check boxes does not wrap each item when given explicitly falsy value' do
|
440
|
+
with_collection_check_boxes @user, :active, [true, false], :to_s, :to_s, :item_wrapper_tag => false
|
441
|
+
|
442
|
+
assert_select 'form input[type=checkbox]'
|
443
|
+
assert_no_select 'form span input[type=checkbox]'
|
444
|
+
end
|
445
|
+
|
446
|
+
test 'collection check boxes uses the given class for item wrapper tag' do
|
447
|
+
with_collection_check_boxes @user, :active, [true, false], :to_s, :to_s,
|
448
|
+
:item_wrapper_tag => :li, :item_wrapper_class => "inline"
|
449
|
+
|
450
|
+
assert_select "form li.inline input[type=checkbox]", :count => 2
|
451
|
+
end
|
452
|
+
|
453
|
+
test 'collection check boxes uses no class for item wrapper tag when no wrapper tag is given' do
|
454
|
+
with_collection_check_boxes @user, :active, [true, false], :to_s, :to_s,
|
455
|
+
:item_wrapper_tag => nil, :item_wrapper_class => "inline"
|
456
|
+
|
457
|
+
assert_select 'form input[type=checkbox]', :count => 2
|
458
|
+
assert_no_select 'form li'
|
459
|
+
assert_no_select '.inline'
|
460
|
+
end
|
461
|
+
|
462
|
+
test 'collection check boxes uses no class for item wrapper tag by default' do
|
463
|
+
with_collection_check_boxes @user, :active, [true, false], :to_s, :to_s,
|
464
|
+
:item_wrapper_tag => :li
|
465
|
+
|
466
|
+
assert_select "form li", :count => 2
|
467
|
+
assert_no_select "form li[class]"
|
468
|
+
end
|
469
|
+
|
470
|
+
test 'collection check box does not wrap input inside the label' do
|
471
|
+
with_collection_check_boxes @user, :active, [true, false], :to_s, :to_s
|
472
|
+
|
473
|
+
assert_select 'form input[type=checkbox] + label'
|
474
|
+
assert_no_select 'form label input'
|
475
|
+
end
|
476
|
+
|
477
|
+
test 'collection check boxes accepts a block to render the label as check box wrapper' do
|
478
|
+
with_collection_check_boxes :user, :active, [true, false], :to_s, :to_s do |b|
|
479
|
+
b.label { b.check_box }
|
480
|
+
end
|
481
|
+
|
482
|
+
assert_select 'label[for=user_active_true] > input#user_active_true[type=checkbox]'
|
483
|
+
assert_select 'label[for=user_active_false] > input#user_active_false[type=checkbox]'
|
484
|
+
end
|
485
|
+
|
486
|
+
test 'collection check boxes accepts a block to change the order of label and check box' do
|
487
|
+
with_collection_check_boxes :user, :active, [true, false], :to_s, :to_s do |b|
|
488
|
+
b.label + b.check_box
|
489
|
+
end
|
490
|
+
|
491
|
+
assert_select 'label[for=user_active_true] + input#user_active_true[type=checkbox]'
|
492
|
+
assert_select 'label[for=user_active_false] + input#user_active_false[type=checkbox]'
|
493
|
+
end
|
494
|
+
|
495
|
+
test 'collection check boxes with block helpers accept extra html options' do
|
496
|
+
with_collection_check_boxes :user, :active, [true, false], :to_s, :to_s do |b|
|
497
|
+
b.label(:class => "check_box") + b.check_box(:class => "check_box")
|
498
|
+
end
|
499
|
+
|
500
|
+
assert_select 'label.check_box[for=user_active_true] + input#user_active_true.check_box[type=checkbox]'
|
501
|
+
assert_select 'label.check_box[for=user_active_false] + input#user_active_false.check_box[type=checkbox]'
|
502
|
+
end
|
503
|
+
|
504
|
+
test 'collection check boxes with block helpers allows access to current text and value' do
|
505
|
+
with_collection_check_boxes :user, :active, [true, false], :to_s, :to_s do |b|
|
506
|
+
b.label(:"data-value" => b.value) { b.check_box + b.text }
|
507
|
+
end
|
508
|
+
|
509
|
+
assert_select 'label[for=user_active_true][data-value=true]', 'true' do
|
510
|
+
assert_select 'input#user_active_true[type=checkbox]'
|
511
|
+
end
|
512
|
+
assert_select 'label[for=user_active_false][data-value=false]', 'false' do
|
513
|
+
assert_select 'input#user_active_false[type=checkbox]'
|
514
|
+
end
|
515
|
+
end
|
516
|
+
|
517
|
+
test 'collection check boxes with block helpers allows access to the current object item in the collection to access extra properties' do
|
518
|
+
with_collection_check_boxes :user, :active, [true, false], :to_s, :to_s do |b|
|
519
|
+
b.label(:class => b.object) { b.check_box + b.text }
|
520
|
+
end
|
521
|
+
|
522
|
+
assert_select 'label.true[for=user_active_true]', 'true' do
|
523
|
+
assert_select 'input#user_active_true[type=checkbox]'
|
524
|
+
end
|
525
|
+
assert_select 'label.false[for=user_active_false]', 'false' do
|
526
|
+
assert_select 'input#user_active_false[type=checkbox]'
|
527
|
+
end
|
528
|
+
end
|
529
|
+
|
530
|
+
# SIMPLE FIELDS
|
531
|
+
test 'simple fields for is available and yields an instance of FormBuilder' do
|
532
|
+
with_concat_form_for(@user) do |f|
|
533
|
+
f.simple_fields_for(:posts) do |posts_form|
|
534
|
+
assert posts_form.instance_of?(SimpleFormWithClientValidation::FormBuilder)
|
535
|
+
end
|
536
|
+
end
|
537
|
+
end
|
538
|
+
|
539
|
+
test 'fields for with a hash like model yeilds an instance of FormBuilder' do
|
540
|
+
@hash_backed_author = HashBackedAuthor.new
|
541
|
+
|
542
|
+
with_concat_form_for(:user) do |f|
|
543
|
+
f.simple_fields_for(:author, @hash_backed_author) do |author|
|
544
|
+
assert author.instance_of?(SimpleFormWithClientValidation::FormBuilder)
|
545
|
+
author.input :name
|
546
|
+
end
|
547
|
+
end
|
548
|
+
|
549
|
+
assert_select "input[name='user[author][name]'][value='hash backed author']"
|
550
|
+
end
|
551
|
+
|
552
|
+
test 'fields for yields an instance of CustomBuilder if main builder is a CustomBuilder' do
|
553
|
+
with_custom_form_for(:user) do |f|
|
554
|
+
f.simple_fields_for(:company) do |company|
|
555
|
+
assert company.instance_of?(CustomFormBuilder)
|
556
|
+
end
|
557
|
+
end
|
558
|
+
end
|
559
|
+
|
560
|
+
test 'fields for yields an instance of FormBuilder if it was set in options' do
|
561
|
+
with_custom_form_for(:user) do |f|
|
562
|
+
f.simple_fields_for(:company, :builder => SimpleFormWithClientValidation::FormBuilder) do |company|
|
563
|
+
assert company.instance_of?(SimpleFormWithClientValidation::FormBuilder)
|
564
|
+
end
|
565
|
+
end
|
566
|
+
end
|
567
|
+
|
568
|
+
test 'fields inherites wrapper option from the parent form' do
|
569
|
+
swap_wrapper :another do
|
570
|
+
simple_form_for(:user, :wrapper => :another) do |f|
|
571
|
+
f.simple_fields_for(:company) do |company|
|
572
|
+
assert_equal :another, company.options[:wrapper]
|
573
|
+
end
|
574
|
+
end
|
575
|
+
end
|
576
|
+
end
|
577
|
+
end
|