diff --git a/.travis.yml b/.travis.yml
index 331435e7..1cdf0965 100644
--- a/.travis.yml
+++ b/.travis.yml
@@ -2,6 +2,12 @@ language: ruby
rvm:
- 1.9.3
- 2.0.0
+gemfile:
+ - gemfiles/Gemfile.rails-head
+ - Gemfile
+matrix:
+ allow_failures:
+ - gemfile: gemfiles/Gemfile.rails-head
notifications:
email: false
campfire:
diff --git a/CHANGELOG.md b/CHANGELOG.md
index 67a7fa10..083329ca 100644
--- a/CHANGELOG.md
+++ b/CHANGELOG.md
@@ -2,12 +2,21 @@
### enhancements
* For radio or checkbox collection always use `:item_wrapper_tag` to wrap the content and add `label` when using `boolean_style` with `:nested` [@kassio](https://github.com/kassio) and [@bernardoamc](https://github.com/bernardoamc)
+ * `input_field` uses the same wrapper as input but only with attribute components. [@nashby](https://github.com/nashby)
* Add wrapper mapping per form basis [@rcillo](https://github.com/rcillo) and [@bernardoamc](https://github.com/bernardoamc)
* Add `for` attribute to `label` when collections are rendered as radio or checkbox [@erichkist](https://github.com/erichkist), [@ulissesalmeida](https://github.com/ulissesalmeida) and [@fabioyamate](https://github.com/fabioyamate)
+ * Add `include_default_input_wrapper_class` config [@luizcosta](https://github.com/luizcosta)
+ * Map `datetime`, `date` and `time` input types to their respective HTML5 input tags
+ when the `:html5` is set to `true` [@volmer](https://github.com/volmer)
### bug fix
* Collection input generates `required` attribute if it has `prompt` option. [@nashby](https://github.com/nashby)
+## 3.0.1
+
+### bug fix
+ * Fix XSS vulnerability on label, hint and error components.
+
## 3.0.0
### enhancements
diff --git a/Gemfile b/Gemfile
index eb04fccf..d2d6ea04 100644
--- a/Gemfile
+++ b/Gemfile
@@ -3,9 +3,9 @@ source 'https://rubygems.org'
gemspec
gem 'country_select', '~> 1.1.1'
-gem 'railties', '>= 4.0.0', '< 4.1'
-gem 'activemodel', '>= 4.0.0', '< 4.1'
-gem 'actionpack', '>= 4.0.0', '< 4.1'
+gem 'railties', github: 'rails/rails', branch: '4-0-stable'
+gem 'activemodel', github: 'rails/rails', branch: '4-0-stable'
+gem 'actionpack', github: 'rails/rails', branch: '4-0-stable'
gem 'rake'
gem 'rdoc'
gem 'tzinfo'
diff --git a/Gemfile.lock b/Gemfile.lock
index 46d7040a..8cfe7adc 100644
--- a/Gemfile.lock
+++ b/Gemfile.lock
@@ -1,60 +1,66 @@
+GIT
+ remote: git://github.com/rails/rails.git
+ revision: b632a8237745c62747558551c74e32a3bb056e09
+ branch: 4-0-stable
+ specs:
+ actionpack (4.0.2)
+ activesupport (= 4.0.2)
+ builder (~> 3.1.0)
+ erubis (~> 2.7.0)
+ rack (~> 1.5.2)
+ rack-test (~> 0.6.2)
+ activemodel (4.0.2)
+ activesupport (= 4.0.2)
+ builder (~> 3.1.0)
+ activesupport (4.0.2)
+ i18n (~> 0.6, >= 0.6.4)
+ minitest (~> 4.2)
+ multi_json (~> 1.3)
+ thread_safe (~> 0.1)
+ tzinfo (~> 0.3.37)
+ railties (4.0.2)
+ actionpack (= 4.0.2)
+ activesupport (= 4.0.2)
+ rake (>= 0.8.7)
+ thor (>= 0.18.1, < 2.0)
+
PATH
remote: .
specs:
- simple_form (3.0.0)
+ simple_form (3.0.1)
actionpack (>= 4.0.0, < 4.1)
activemodel (>= 4.0.0, < 4.1)
GEM
remote: https://rubygems.org/
specs:
- actionpack (4.0.0)
- activesupport (= 4.0.0)
- builder (~> 3.1.0)
- erubis (~> 2.7.0)
- rack (~> 1.5.2)
- rack-test (~> 0.6.2)
- activemodel (4.0.0)
- activesupport (= 4.0.0)
- builder (~> 3.1.0)
- activesupport (4.0.0)
- i18n (~> 0.6, >= 0.6.4)
- minitest (~> 4.2)
- multi_json (~> 1.3)
- thread_safe (~> 0.1)
- tzinfo (~> 0.3.37)
- atomic (1.1.9)
+ atomic (1.1.14)
builder (3.1.4)
country_select (1.1.3)
erubis (2.7.0)
- i18n (0.6.4)
- json (1.7.7)
+ i18n (0.6.9)
+ json (1.8.1)
minitest (4.7.5)
- multi_json (1.7.7)
+ multi_json (1.8.2)
rack (1.5.2)
rack-test (0.6.2)
rack (>= 1.0)
- railties (4.0.0)
- actionpack (= 4.0.0)
- activesupport (= 4.0.0)
- rake (>= 0.8.7)
- thor (>= 0.18.1, < 2.0)
- rake (10.0.4)
+ rake (10.1.0)
rdoc (4.0.1)
json (~> 1.4)
thor (0.18.1)
- thread_safe (0.1.0)
+ thread_safe (0.1.3)
atomic
- tzinfo (0.3.37)
+ tzinfo (0.3.38)
PLATFORMS
ruby
DEPENDENCIES
- actionpack (>= 4.0.0, < 4.1)
- activemodel (>= 4.0.0, < 4.1)
+ actionpack!
+ activemodel!
country_select (~> 1.1.1)
- railties (>= 4.0.0, < 4.1)
+ railties!
rake
rdoc
simple_form!
diff --git a/README.md b/README.md
index 7b3dbcab..ad62cb4a 100644
--- a/README.md
+++ b/README.md
@@ -500,9 +500,9 @@ specifying the helper method in the column `Mapping` as the `as:` option.
`float` | `input[type=number]` | `float`
`decimal` | `input[type=number]` | `decimal`
`range` | `input[type=range]` | -
- `datetime` | `input[type=datetime]` | `datetime/timestamp`
- `date` | `input[type=date]` | `date`
- `time` | `input[type=time]` | `time`
+ `datetime` | `datetime select` | `datetime/timestamp`
+ `date` | `date select` | `date`
+ `time` | `time select` | `time`
`select` | `select` | `belongs_to`/`has_many`/`has_and_belongs_to_many` associations
`radio_buttons` | collection of `input[type=radio]` | `belongs_to` associations
`check_boxes` | collection of `input[type=checkbox]` | `has_many`/`has_and_belongs_to_many` associations
diff --git a/gemfiles/Gemfile.rails-head b/gemfiles/Gemfile.rails-head
new file mode 100644
index 00000000..968c0042
--- /dev/null
+++ b/gemfiles/Gemfile.rails-head
@@ -0,0 +1,11 @@
+source 'https://rubygems.org'
+
+gemspec :path => '..'
+
+gem 'country_select', '~> 1.1.1'
+gem 'railties', github: 'rails/rails'
+gem 'activemodel', github: 'rails/rails'
+gem 'actionpack', github: 'rails/rails'
+gem 'rake'
+gem 'rdoc'
+gem 'tzinfo'
diff --git a/lib/generators/simple_form/templates/config/initializers/simple_form.rb b/lib/generators/simple_form/templates/config/initializers/simple_form.rb
index ecd67dc2..328bea0c 100644
--- a/lib/generators/simple_form/templates/config/initializers/simple_form.rb
+++ b/lib/generators/simple_form/templates/config/initializers/simple_form.rb
@@ -142,4 +142,8 @@ SimpleForm.setup do |config|
# Default class for inputs
# config.input_class = nil
+
+ # Defines if the default input wrapper class should be included in radio
+ # collection wrappers.
+ # config.include_default_input_wrapper_class = true
end
diff --git a/lib/simple_form.rb b/lib/simple_form.rb
index 89ca9d67..4f977dea 100644
--- a/lib/simple_form.rb
+++ b/lib/simple_form.rb
@@ -153,6 +153,10 @@ module SimpleForm
mattr_accessor :input_class
@@input_class = nil
+ # Defines if an input wrapper class should be included or not
+ mattr_accessor :include_default_input_wrapper_class
+ @@include_default_input_wrapper_class = true
+
## WRAPPER CONFIGURATION
# The default wrapper to be used by the FormBuilder.
mattr_accessor :default_wrapper
diff --git a/lib/simple_form/components/errors.rb b/lib/simple_form/components/errors.rb
index 74d6f5ee..aad48335 100644
--- a/lib/simple_form/components/errors.rb
+++ b/lib/simple_form/components/errors.rb
@@ -12,7 +12,7 @@ module SimpleForm
protected
def error_text
- "#{options[:error_prefix]} #{errors.send(error_method)}".lstrip.html_safe
+ "#{html_escape(options[:error_prefix])} #{errors.send(error_method)}".lstrip.html_safe
end
def error_method
diff --git a/lib/simple_form/components/hints.rb b/lib/simple_form/components/hints.rb
index a95f9c5e..f9890d5b 100644
--- a/lib/simple_form/components/hints.rb
+++ b/lib/simple_form/components/hints.rb
@@ -5,8 +5,13 @@ module SimpleForm
def hint
@hint ||= begin
hint = options[:hint]
- hint_content = hint.is_a?(String) ? hint : translate(:hints)
- hint_content.html_safe if hint_content
+
+ if hint.is_a?(String)
+ html_escape(hint)
+ else
+ content = translate(:hints)
+ content.html_safe if content
+ end
end
end
diff --git a/lib/simple_form/components/labels.rb b/lib/simple_form/components/labels.rb
index 2e78a3f4..ae33f5d2 100644
--- a/lib/simple_form/components/labels.rb
+++ b/lib/simple_form/components/labels.rb
@@ -30,7 +30,7 @@ module SimpleForm
end
def label_text
- SimpleForm.label_text.call(raw_label_text, required_label_text).strip.html_safe
+ SimpleForm.label_text.call(html_escape(raw_label_text), required_label_text).strip.html_safe
end
def label_target
diff --git a/lib/simple_form/form_builder.rb b/lib/simple_form/form_builder.rb
index 44ae509e..94a0f5d5 100644
--- a/lib/simple_form/form_builder.rb
+++ b/lib/simple_form/form_builder.rb
@@ -108,16 +108,11 @@ module SimpleForm
#
def input(attribute_name, options={}, &block)
options = @defaults.deep_dup.deep_merge(options) if @defaults
- input = find_input(attribute_name, options, &block)
- chosen =
- if name = options[:wrapper] || find_wrapper_mapping(input.input_type)
- name.respond_to?(:render) ? name : SimpleForm.wrapper(name)
- else
- wrapper
- end
+ input = find_input(attribute_name, options, &block)
+ wrapper = find_wrapper(input.input_type, options)
- chosen.render input
+ wrapper.render input
end
alias :attribute :input
@@ -140,7 +135,11 @@ module SimpleForm
options[:input_html] = options.except(:as, :collection, :label_method, :value_method, *ATTRIBUTE_COMPONENTS)
options = @defaults.deep_dup.deep_merge(options) if @defaults
- SimpleForm::Wrappers::Root.new(ATTRIBUTE_COMPONENTS + [:input], wrapper: false).render find_input(attribute_name, options)
+ input = find_input(attribute_name, options)
+ wrapper = find_wrapper(input.input_type, options)
+ components = (wrapper.components & ATTRIBUTE_COMPONENTS) + [:input]
+
+ SimpleForm::Wrappers::Root.new(components, wrapper.options.merge(wrapper: false)).render input
end
# Helper for dealing with association selects/radios, generating the
@@ -564,6 +563,14 @@ module SimpleForm
end
end
+ def find_wrapper(input_type, options)
+ if name = options[:wrapper] || find_wrapper_mapping(input_type)
+ name.respond_to?(:render) ? name : SimpleForm.wrapper(name)
+ else
+ wrapper
+ end
+ end
+
# If cache_discovery is enabled, use the class level cache that persists
# between requests, otherwise use the instance one.
def discovery_cache #:nodoc:
diff --git a/lib/simple_form/inputs/base.rb b/lib/simple_form/inputs/base.rb
index a98d4e6e..e9eb3def 100644
--- a/lib/simple_form/inputs/base.rb
+++ b/lib/simple_form/inputs/base.rb
@@ -1,8 +1,11 @@
require 'simple_form/i18n_cache'
+require 'active_support/core_ext/string/output_safety'
module SimpleForm
module Inputs
class Base
+ include ERB::Util
+
extend I18nCache
include SimpleForm::Helpers::Autofocus
diff --git a/lib/simple_form/inputs/collection_radio_buttons_input.rb b/lib/simple_form/inputs/collection_radio_buttons_input.rb
index 0be885dc..52d47785 100644
--- a/lib/simple_form/inputs/collection_radio_buttons_input.rb
+++ b/lib/simple_form/inputs/collection_radio_buttons_input.rb
@@ -22,7 +22,7 @@ module SimpleForm
options[:item_wrapper_tag] ||= options.fetch(:item_wrapper_tag, SimpleForm.item_wrapper_tag)
options[:item_wrapper_class] = [
item_wrapper_class, options[:item_wrapper_class], SimpleForm.item_wrapper_class
- ].compact.presence
+ ].compact.presence if SimpleForm.include_default_input_wrapper_class
options[:collection_wrapper_tag] ||= options.fetch(:collection_wrapper_tag, SimpleForm.collection_wrapper_tag)
options[:collection_wrapper_class] = [
diff --git a/lib/simple_form/inputs/date_time_input.rb b/lib/simple_form/inputs/date_time_input.rb
index 64fd326f..0414ad2f 100644
--- a/lib/simple_form/inputs/date_time_input.rb
+++ b/lib/simple_form/inputs/date_time_input.rb
@@ -2,7 +2,11 @@ module SimpleForm
module Inputs
class DateTimeInput < Base
def input
- @builder.send(:"#{input_type}_select", attribute_name, input_options, input_html_options)
+ if use_html5_inputs?
+ @builder.send(:"#{input_type}_field", attribute_name, input_html_options)
+ else
+ @builder.send(:"#{input_type}_select", attribute_name, input_options, input_html_options)
+ end
end
private
@@ -19,6 +23,10 @@ module SimpleForm
position = ActionView::Helpers::DateTimeSelector::POSITION[position]
"#{attribute_name}_#{position}i"
end
+
+ def use_html5_inputs?
+ input_options[:html5]
+ end
end
end
end
diff --git a/lib/simple_form/tags.rb b/lib/simple_form/tags.rb
index 33a7db3b..aef3f995 100644
--- a/lib/simple_form/tags.rb
+++ b/lib/simple_form/tags.rb
@@ -17,7 +17,7 @@ module SimpleForm
if @options.fetch(:boolean_style, SimpleForm.boolean_style) == :nested
label_options = {}
- add_default_name_and_id_for_value(text, label_options)
+ add_default_name_and_id_for_value(value, label_options)
label_options['for'] = label_options['id']
rendered_item = content_tag(:label, rendered_item, label_options)
end
diff --git a/lib/simple_form/version.rb b/lib/simple_form/version.rb
index 7b9bda35..d1115316 100644
--- a/lib/simple_form/version.rb
+++ b/lib/simple_form/version.rb
@@ -1,3 +1,3 @@
module SimpleForm
- VERSION = "3.0.0".freeze
+ VERSION = "3.0.1".freeze
end
diff --git a/test/form_builder/error_test.rb b/test/form_builder/error_test.rb
index ce42ccb4..06a024a7 100644
--- a/test/form_builder/error_test.rb
+++ b/test/form_builder/error_test.rb
@@ -80,8 +80,13 @@ class ErrorTest < ActionView::TestCase
assert_no_select 'p.error[error_method]'
end
- test 'error should generate an error message with raw HTML tags' do
+ test 'error should escape error prefix text' do
with_error_for @user, :name, error_prefix: 'Name'
+ assert_select 'span.error', "<b>Name</b> can't be blank"
+ end
+
+ test 'error should generate an error message with raw HTML tags' do
+ with_error_for @user, :name, error_prefix: 'Name'.html_safe
assert_select 'span.error', "Name can't be blank"
assert_select 'span.error b', "Name"
end
diff --git a/test/form_builder/hint_test.rb b/test/form_builder/hint_test.rb
index f8fd2cbe..38252720 100644
--- a/test/form_builder/hint_test.rb
+++ b/test/form_builder/hint_test.rb
@@ -43,8 +43,14 @@ class HintTest < ActionView::TestCase
end
test 'hint should be output as html_safe' do
- with_hint_for @user, :name, hint: 'Bold and not...'
+ with_hint_for @user, :name, hint: 'Bold and not...'.html_safe
assert_select 'span.hint', 'Bold and not...'
+ assert_select 'span.hint b', 'Bold'
+ end
+
+ test 'builder should escape hint text' do
+ with_hint_for @user, :name, hint: ''
+ assert_select 'span.hint', "<script>alert(1337)</script>"
end
# Without attribute name
@@ -132,7 +138,7 @@ class HintTest < ActionView::TestCase
test 'hint with custom wrappers works' do
swap_wrapper do
with_hint_for @user, :name, hint: "can't be blank"
- assert_select 'div.omg_hint', "can't be blank"
+ assert_select 'div.omg_hint', "can't be blank"
end
end
end
diff --git a/test/form_builder/input_field_test.rb b/test/form_builder/input_field_test.rb
index 755ad85b..1f399c1e 100644
--- a/test/form_builder/input_field_test.rb
+++ b/test/form_builder/input_field_test.rb
@@ -88,14 +88,30 @@ class InputFieldTest < ActionView::TestCase
assert_select 'input[min=18]'
end
- test 'builder input_field should use pattern component' do
+ test 'builder input_field should not use pattern component by default' do
with_concat_form_for(@other_validating_user) do |f|
f.input_field :country, as: :string
end
+ assert_no_select 'input[pattern="\w+"]'
+ end
+
+ test 'builder input_field should infer pattern from attributes' do
+ with_concat_form_for(@other_validating_user) do |f|
+ f.input_field :country, as: :string, pattern: true
+ end
+
assert_select 'input[pattern="\w+"]'
end
+ test 'builder input_field should accept custom patter' do
+ with_concat_form_for(@other_validating_user) do |f|
+ f.input_field :country, as: :string, pattern: '\d+'
+ end
+
+ assert_select 'input[pattern="\d+"]'
+ end
+
test 'builder input_field should use readonly component' do
with_concat_form_for(@other_validating_user) do |f|
f.input_field :age, as: :integer, readonly: true
diff --git a/test/form_builder/label_test.rb b/test/form_builder/label_test.rb
index 4d4155c6..4b7e0a78 100644
--- a/test/form_builder/label_test.rb
+++ b/test/form_builder/label_test.rb
@@ -29,6 +29,16 @@ class LabelTest < ActionView::TestCase
assert_select 'label.string.required[for=validating_user_name]', /Name/
end
+ test 'builder should escape label text' do
+ with_label_for @user, :name, label: '', required: false
+ assert_select 'label.string', "<script>alert(1337)</script>"
+ end
+
+ test 'builder should not escape label text if it is safe' do
+ with_label_for @user, :name, label: ''.html_safe, required: false
+ assert_select 'label.string script', "alert(1337)"
+ end
+
test 'builder should allow passing options to label tag' do
with_label_for @user, :name, label: 'My label', id: 'name_label'
assert_select 'label.string#name_label', /My label/
diff --git a/test/inputs/collection_check_boxes_input_test.rb b/test/inputs/collection_check_boxes_input_test.rb
index 429ce680..5207b72f 100644
--- a/test/inputs/collection_check_boxes_input_test.rb
+++ b/test/inputs/collection_check_boxes_input_test.rb
@@ -230,4 +230,21 @@ class CollectionCheckBoxesInputTest < ActionView::TestCase
assert_select 'span.checkbox.inline > label > input'
end
end
+
+ test 'input check boxes wrapper class are not included when set to falsey' do
+ swap SimpleForm, include_default_input_wrapper_class: false, boolean_style: :nested do
+ with_input_for @user, :gender, :check_boxes, collection: [:male, :female]
+
+ assert_no_select 'label.checkbox'
+ end
+ end
+
+ test 'input check boxes custom wrapper class is included when include input wrapper class is falsey' do
+ swap SimpleForm, include_default_input_wrapper_class: false, boolean_style: :nested do
+ with_input_for @user, :gender, :check_boxes, collection: [:male, :female], item_wrapper_class: 'custom'
+
+ assert_no_select 'label.checkbox'
+ assert_select 'label.custom'
+ end
+ end
end
diff --git a/test/inputs/collection_radio_buttons_input_test.rb b/test/inputs/collection_radio_buttons_input_test.rb
index ff4b0e6e..3c78f56e 100644
--- a/test/inputs/collection_radio_buttons_input_test.rb
+++ b/test/inputs/collection_radio_buttons_input_test.rb
@@ -18,6 +18,14 @@ class CollectionRadioButtonsInputTest < ActionView::TestCase
assert_select 'label[for=user_active_false]', 'No'
end
+ test 'input as radio should generate internal labels with accurate `for` values with nested boolean style' do
+ swap SimpleForm, boolean_style: :nested do
+ with_input_for @user, :active, :radio_buttons
+ assert_select 'label[for=user_active_true]', 'Yes'
+ assert_select 'label[for=user_active_false]', 'No'
+ end
+ end
+
test 'input as radio should use i18n to translate internal labels' do
store_translations(:en, simple_form: { yes: 'Sim', no: 'Não' }) do
with_input_for @user, :active, :radio_buttons
@@ -323,4 +331,21 @@ class CollectionRadioButtonsInputTest < ActionView::TestCase
assert_select 'span.radio.inline > label > input'
end
end
+
+ test 'input radio wrapper class are not included when set to falsey' do
+ swap SimpleForm, include_default_input_wrapper_class: false, boolean_style: :nested do
+ with_input_for @user, :gender, :radio_buttons, collection: [:male, :female]
+
+ assert_no_select 'label.radio'
+ end
+ end
+
+ test 'input check boxes custom wrapper class is included when include input wrapper class is falsey' do
+ swap SimpleForm, include_default_input_wrapper_class: false, boolean_style: :nested do
+ with_input_for @user, :gender, :radio_buttons, collection: [:male, :female], item_wrapper_class: 'custom'
+
+ assert_no_select 'label.radio'
+ assert_select 'label.custom'
+ end
+ end
end
diff --git a/test/inputs/datetime_input_test.rb b/test/inputs/datetime_input_test.rb
index b1a77354..d0528b1b 100644
--- a/test/inputs/datetime_input_test.rb
+++ b/test/inputs/datetime_input_test.rb
@@ -1,18 +1,69 @@
# encoding: UTF-8
require 'test_helper'
-# Tests for all different kinds of inputs.
-class DateTimeInputTest < ActionView::TestCase
- # DateTime input
- test 'input should generate a datetime select by default for datetime attributes' do
+# Tests for datetime, date and time inputs when HTML5 compatibility is enabled in the wrapper.
+class DateTimeInputWithHtml5Test < ActionView::TestCase
+ test 'input should generate a datetime input for datetime attributes if HTML5 compatibility is explicitly enbled' do
+ with_input_for @user, :created_at, :datetime, html5: true
+
+ assert_select 'input[type="datetime"]'
+ end
+
+ test 'input should generate a datetime select for datetime attributes' do
with_input_for @user, :created_at, :datetime
- 1.upto(5) do |i|
- assert_select "form select.datetime#user_created_at_#{i}i"
+
+ assert_select 'select.datetime'
+ end
+
+ test 'input should generate a date input for date attributes if HTML5 compatibility is explicitly enbled' do
+ with_input_for @user, :born_at, :date, html5: true
+
+ assert_select 'input[type="date"]'
+ end
+
+ test 'input should generate a date select for date attributes' do
+ with_input_for @user, :born_at, :date
+
+ assert_select 'select.date'
+ end
+
+ test 'input should generate a time input for time attributes if HTML5 compatibility is explicitly enbled' do
+ with_input_for @user, :delivery_time, :time, html5: true
+
+ assert_select 'input[type="time"]'
+ end
+
+ test 'input should generate a time select for time attributes' do
+ with_input_for @user, :delivery_time, :time
+
+ assert_select 'select.time'
+ end
+
+ test 'input should generate required html attribute' do
+ with_input_for @user, :delivery_time, :time, required: true, html5: true
+ assert_select 'input.required'
+ assert_select 'input[required]'
+ end
+
+ test 'input should have an aria-required html attribute' do
+ with_input_for @user, :delivery_time, :time, required: true, html5: true
+ assert_select 'input[aria-required=true]'
+ end
+end
+
+# Tests for datetime, date and time inputs when HTML5 compatibility is enabled in the wrapper.
+class DateTimeInputWithoutHtml5Test < ActionView::TestCase
+ test 'input should generate a datetime select by default for datetime attributes' do
+ swap_wrapper do
+ with_input_for @user, :created_at, :datetime
+ 1.upto(5) do |i|
+ assert_select "form select.datetime#user_created_at_#{i}i"
+ end
end
end
test 'input should be able to pass options to datetime select' do
- with_input_for @user, :created_at, :datetime,
+ with_input_for @user, :created_at, :datetime, html5: false,
disabled: true, prompt: { year: 'ano', month: 'mês', day: 'dia' }
assert_select 'select.datetime[disabled=disabled]'
@@ -21,16 +72,26 @@ class DateTimeInputTest < ActionView::TestCase
assert_select 'select.datetime option', 'dia'
end
+ test 'input should generate a datetime input for datetime attributes if HTML5 compatibility is explicitly enabled' do
+ swap_wrapper do
+ with_input_for @user, :created_at, :datetime, html5: true
+
+ assert_select 'input[type="datetime"]'
+ end
+ end
+
test 'input should generate a date select for date attributes' do
- with_input_for @user, :born_at, :date
- assert_select 'select.date#user_born_at_1i'
- assert_select 'select.date#user_born_at_2i'
- assert_select 'select.date#user_born_at_3i'
- assert_no_select 'select.date#user_born_at_4i'
+ swap_wrapper do
+ with_input_for @user, :born_at, :date
+ assert_select 'select.date#user_born_at_1i'
+ assert_select 'select.date#user_born_at_2i'
+ assert_select 'select.date#user_born_at_3i'
+ assert_no_select 'select.date#user_born_at_4i'
+ end
end
test 'input should be able to pass options to date select' do
- with_input_for @user, :born_at, :date, as: :date,
+ with_input_for @user, :born_at, :date, as: :date, html5: false,
disabled: true, prompt: { year: 'ano', month: 'mês', day: 'dia' }
assert_select 'select.date[disabled=disabled]'
@@ -40,21 +101,31 @@ class DateTimeInputTest < ActionView::TestCase
end
test 'input should be able to pass :default to date select' do
- with_input_for @user, :born_at, :date, default: Date.today
+ with_input_for @user, :born_at, :date, default: Date.today, html5: false
assert_select "select.date option[value=#{Date.today.year}][selected=selected]"
end
+ test 'input should generate a date input for date attributes if HTML5 compatibility is explicitly enabled' do
+ swap_wrapper do
+ with_input_for @user, :born_at, :date, html5: true
+
+ assert_select 'input[type="date"]'
+ end
+ end
+
test 'input should generate a time select for time attributes' do
- with_input_for @user, :delivery_time, :time
- assert_select 'input[type=hidden]#user_delivery_time_1i'
- assert_select 'input[type=hidden]#user_delivery_time_2i'
- assert_select 'input[type=hidden]#user_delivery_time_3i'
- assert_select 'select.time#user_delivery_time_4i'
- assert_select 'select.time#user_delivery_time_5i'
+ swap_wrapper do
+ with_input_for @user, :delivery_time, :time
+ assert_select 'input[type=hidden]#user_delivery_time_1i'
+ assert_select 'input[type=hidden]#user_delivery_time_2i'
+ assert_select 'input[type=hidden]#user_delivery_time_3i'
+ assert_select 'select.time#user_delivery_time_4i'
+ assert_select 'select.time#user_delivery_time_5i'
+ end
end
test 'input should be able to pass options to time select' do
- with_input_for @user, :delivery_time, :time, required: true,
+ with_input_for @user, :delivery_time, :time, required: true, html5: false,
disabled: true, prompt: { hour: 'hora', minute: 'minuto' }
assert_select 'select.time[disabled=disabled]'
@@ -62,44 +133,40 @@ class DateTimeInputTest < ActionView::TestCase
assert_select 'select.time option', 'minuto'
end
+ test 'input should generate a time input for time attributes if HTML5 compatibility is explicitly enabled' do
+ swap_wrapper do
+ with_input_for @user, :delivery_time, :time, html5: true
+
+ assert_select 'input[type="time"]'
+ end
+ end
+
test 'label should use i18n to get target for date input type' do
store_translations(:en, date: { order: ['month', 'day', 'year'] }) do
- with_input_for :project, :created_at, :date
+ with_input_for :project, :created_at, :date, html5: false
assert_select 'label[for=project_created_at_2i]'
end
end
test 'label should use i18n to get target for datetime input type' do
store_translations(:en, date: { order: ['month', 'day', 'year'] }) do
- with_input_for :project, :created_at, :datetime
+ with_input_for :project, :created_at, :datetime, html5: false
assert_select 'label[for=project_created_at_2i]'
end
end
test 'label should use order to get target when date input type' do
- with_input_for :project, :created_at, :date, order: ['month', 'year', 'day']
+ with_input_for :project, :created_at, :date, order: ['month', 'year', 'day'], html5: false
assert_select 'label[for=project_created_at_2i]'
end
test 'label should use order to get target when datetime input type' do
- with_input_for :project, :created_at, :datetime, order: ['month', 'year', 'day']
+ with_input_for :project, :created_at, :datetime, order: ['month', 'year', 'day'], html5: false
assert_select 'label[for=project_created_at_2i]'
end
test 'label should point to first option when time input type' do
- with_input_for :project, :created_at, :time
+ with_input_for :project, :created_at, :time, html5: false
assert_select 'label[for=project_created_at_4i]'
end
-
- test 'date time input should generate required html attribute' do
- with_input_for @user, :delivery_time, :time, required: true
- assert_select 'select.required'
- assert_select 'select[required]'
- end
-
- test 'date time input has an aria-required html attribute' do
- with_input_for @user, :delivery_time, :time, required: true
- assert_select 'select.required'
- assert_select 'select[aria-required=true]'
- end
end