Merge branch 'master' into kb-ek-change-wraper-collection

Conflicts:
	CHANGELOG.md
	lib/simple_form/tags.rb
This commit is contained in:
Erich Kist 2013-12-09 11:11:42 -02:00
commit e8e1973d17
24 changed files with 305 additions and 96 deletions

View File

@ -2,6 +2,12 @@ language: ruby
rvm: rvm:
- 1.9.3 - 1.9.3
- 2.0.0 - 2.0.0
gemfile:
- gemfiles/Gemfile.rails-head
- Gemfile
matrix:
allow_failures:
- gemfile: gemfiles/Gemfile.rails-head
notifications: notifications:
email: false email: false
campfire: campfire:

View File

@ -2,12 +2,21 @@
### enhancements ### 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) * 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 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 `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 ### bug fix
* Collection input generates `required` attribute if it has `prompt` option. [@nashby](https://github.com/nashby) * 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 ## 3.0.0
### enhancements ### enhancements

View File

@ -3,9 +3,9 @@ source 'https://rubygems.org'
gemspec gemspec
gem 'country_select', '~> 1.1.1' gem 'country_select', '~> 1.1.1'
gem 'railties', '>= 4.0.0', '< 4.1' gem 'railties', github: 'rails/rails', branch: '4-0-stable'
gem 'activemodel', '>= 4.0.0', '< 4.1' gem 'activemodel', github: 'rails/rails', branch: '4-0-stable'
gem 'actionpack', '>= 4.0.0', '< 4.1' gem 'actionpack', github: 'rails/rails', branch: '4-0-stable'
gem 'rake' gem 'rake'
gem 'rdoc' gem 'rdoc'
gem 'tzinfo' gem 'tzinfo'

View File

@ -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 PATH
remote: . remote: .
specs: specs:
simple_form (3.0.0) simple_form (3.0.1)
actionpack (>= 4.0.0, < 4.1) actionpack (>= 4.0.0, < 4.1)
activemodel (>= 4.0.0, < 4.1) activemodel (>= 4.0.0, < 4.1)
GEM GEM
remote: https://rubygems.org/ remote: https://rubygems.org/
specs: specs:
actionpack (4.0.0) atomic (1.1.14)
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)
builder (3.1.4) builder (3.1.4)
country_select (1.1.3) country_select (1.1.3)
erubis (2.7.0) erubis (2.7.0)
i18n (0.6.4) i18n (0.6.9)
json (1.7.7) json (1.8.1)
minitest (4.7.5) minitest (4.7.5)
multi_json (1.7.7) multi_json (1.8.2)
rack (1.5.2) rack (1.5.2)
rack-test (0.6.2) rack-test (0.6.2)
rack (>= 1.0) rack (>= 1.0)
railties (4.0.0) rake (10.1.0)
actionpack (= 4.0.0)
activesupport (= 4.0.0)
rake (>= 0.8.7)
thor (>= 0.18.1, < 2.0)
rake (10.0.4)
rdoc (4.0.1) rdoc (4.0.1)
json (~> 1.4) json (~> 1.4)
thor (0.18.1) thor (0.18.1)
thread_safe (0.1.0) thread_safe (0.1.3)
atomic atomic
tzinfo (0.3.37) tzinfo (0.3.38)
PLATFORMS PLATFORMS
ruby ruby
DEPENDENCIES DEPENDENCIES
actionpack (>= 4.0.0, < 4.1) actionpack!
activemodel (>= 4.0.0, < 4.1) activemodel!
country_select (~> 1.1.1) country_select (~> 1.1.1)
railties (>= 4.0.0, < 4.1) railties!
rake rake
rdoc rdoc
simple_form! simple_form!

View File

@ -500,9 +500,9 @@ specifying the helper method in the column `Mapping` as the `as:` option.
`float` | `input[type=number]` | `float` `float` | `input[type=number]` | `float`
`decimal` | `input[type=number]` | `decimal` `decimal` | `input[type=number]` | `decimal`
`range` | `input[type=range]` | - `range` | `input[type=range]` | -
`datetime` | `input[type=datetime]` | `datetime/timestamp` `datetime` | `datetime select` | `datetime/timestamp`
`date` | `input[type=date]` | `date` `date` | `date select` | `date`
`time` | `input[type=time]` | `time` `time` | `time select` | `time`
`select` | `select` | `belongs_to`/`has_many`/`has_and_belongs_to_many` associations `select` | `select` | `belongs_to`/`has_many`/`has_and_belongs_to_many` associations
`radio_buttons` | collection of `input[type=radio]` | `belongs_to` 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 `check_boxes` | collection of `input[type=checkbox]` | `has_many`/`has_and_belongs_to_many` associations

View File

@ -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'

View File

@ -142,4 +142,8 @@ SimpleForm.setup do |config|
# Default class for inputs # Default class for inputs
# config.input_class = nil # 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 end

View File

@ -153,6 +153,10 @@ module SimpleForm
mattr_accessor :input_class mattr_accessor :input_class
@@input_class = nil @@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 ## WRAPPER CONFIGURATION
# The default wrapper to be used by the FormBuilder. # The default wrapper to be used by the FormBuilder.
mattr_accessor :default_wrapper mattr_accessor :default_wrapper

View File

@ -12,7 +12,7 @@ module SimpleForm
protected protected
def error_text 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 end
def error_method def error_method

View File

@ -5,8 +5,13 @@ module SimpleForm
def hint def hint
@hint ||= begin @hint ||= begin
hint = options[:hint] 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
end end

View File

@ -30,7 +30,7 @@ module SimpleForm
end end
def label_text 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 end
def label_target def label_target

View File

@ -108,16 +108,11 @@ module SimpleForm
# #
def input(attribute_name, options={}, &block) def input(attribute_name, options={}, &block)
options = @defaults.deep_dup.deep_merge(options) if @defaults options = @defaults.deep_dup.deep_merge(options) if @defaults
input = find_input(attribute_name, options, &block)
chosen = input = find_input(attribute_name, options, &block)
if name = options[:wrapper] || find_wrapper_mapping(input.input_type) wrapper = find_wrapper(input.input_type, options)
name.respond_to?(:render) ? name : SimpleForm.wrapper(name)
else
wrapper
end
chosen.render input wrapper.render input
end end
alias :attribute :input alias :attribute :input
@ -140,7 +135,11 @@ module SimpleForm
options[:input_html] = options.except(:as, :collection, :label_method, :value_method, *ATTRIBUTE_COMPONENTS) options[:input_html] = options.except(:as, :collection, :label_method, :value_method, *ATTRIBUTE_COMPONENTS)
options = @defaults.deep_dup.deep_merge(options) if @defaults 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 end
# Helper for dealing with association selects/radios, generating the # Helper for dealing with association selects/radios, generating the
@ -564,6 +563,14 @@ module SimpleForm
end end
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 # If cache_discovery is enabled, use the class level cache that persists
# between requests, otherwise use the instance one. # between requests, otherwise use the instance one.
def discovery_cache #:nodoc: def discovery_cache #:nodoc:

View File

@ -1,8 +1,11 @@
require 'simple_form/i18n_cache' require 'simple_form/i18n_cache'
require 'active_support/core_ext/string/output_safety'
module SimpleForm module SimpleForm
module Inputs module Inputs
class Base class Base
include ERB::Util
extend I18nCache extend I18nCache
include SimpleForm::Helpers::Autofocus include SimpleForm::Helpers::Autofocus

View File

@ -22,7 +22,7 @@ module SimpleForm
options[:item_wrapper_tag] ||= options.fetch(:item_wrapper_tag, SimpleForm.item_wrapper_tag) options[:item_wrapper_tag] ||= options.fetch(:item_wrapper_tag, SimpleForm.item_wrapper_tag)
options[:item_wrapper_class] = [ options[:item_wrapper_class] = [
item_wrapper_class, options[:item_wrapper_class], SimpleForm.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_tag] ||= options.fetch(:collection_wrapper_tag, SimpleForm.collection_wrapper_tag)
options[:collection_wrapper_class] = [ options[:collection_wrapper_class] = [

View File

@ -2,7 +2,11 @@ module SimpleForm
module Inputs module Inputs
class DateTimeInput < Base class DateTimeInput < Base
def input 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 end
private private
@ -19,6 +23,10 @@ module SimpleForm
position = ActionView::Helpers::DateTimeSelector::POSITION[position] position = ActionView::Helpers::DateTimeSelector::POSITION[position]
"#{attribute_name}_#{position}i" "#{attribute_name}_#{position}i"
end end
def use_html5_inputs?
input_options[:html5]
end
end end
end end
end end

View File

@ -17,7 +17,7 @@ module SimpleForm
if @options.fetch(:boolean_style, SimpleForm.boolean_style) == :nested if @options.fetch(:boolean_style, SimpleForm.boolean_style) == :nested
label_options = {} 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'] label_options['for'] = label_options['id']
rendered_item = content_tag(:label, rendered_item, label_options) rendered_item = content_tag(:label, rendered_item, label_options)
end end

View File

@ -1,3 +1,3 @@
module SimpleForm module SimpleForm
VERSION = "3.0.0".freeze VERSION = "3.0.1".freeze
end end

View File

@ -80,8 +80,13 @@ class ErrorTest < ActionView::TestCase
assert_no_select 'p.error[error_method]' assert_no_select 'p.error[error_method]'
end 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: '<b>Name</b>' with_error_for @user, :name, error_prefix: '<b>Name</b>'
assert_select 'span.error', "&lt;b&gt;Name&lt;/b&gt; can't be blank"
end
test 'error should generate an error message with raw HTML tags' do
with_error_for @user, :name, error_prefix: '<b>Name</b>'.html_safe
assert_select 'span.error', "Name can't be blank" assert_select 'span.error', "Name can't be blank"
assert_select 'span.error b', "Name" assert_select 'span.error b', "Name"
end end

View File

@ -43,8 +43,14 @@ class HintTest < ActionView::TestCase
end end
test 'hint should be output as html_safe' do test 'hint should be output as html_safe' do
with_hint_for @user, :name, hint: '<b>Bold</b> and not...' with_hint_for @user, :name, hint: '<b>Bold</b> and not...'.html_safe
assert_select 'span.hint', 'Bold and not...' 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: '<script>alert(1337)</script>'
assert_select 'span.hint', "&lt;script&gt;alert(1337)&lt;/script&gt;"
end end
# Without attribute name # Without attribute name
@ -132,7 +138,7 @@ class HintTest < ActionView::TestCase
test 'hint with custom wrappers works' do test 'hint with custom wrappers works' do
swap_wrapper do swap_wrapper do
with_hint_for @user, :name, hint: "can't be blank" 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&#39;t be blank"
end end
end end
end end

View File

@ -88,14 +88,30 @@ class InputFieldTest < ActionView::TestCase
assert_select 'input[min=18]' assert_select 'input[min=18]'
end 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| with_concat_form_for(@other_validating_user) do |f|
f.input_field :country, as: :string f.input_field :country, as: :string
end 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+"]' assert_select 'input[pattern="\w+"]'
end 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 test 'builder input_field should use readonly component' do
with_concat_form_for(@other_validating_user) do |f| with_concat_form_for(@other_validating_user) do |f|
f.input_field :age, as: :integer, readonly: true f.input_field :age, as: :integer, readonly: true

View File

@ -29,6 +29,16 @@ class LabelTest < ActionView::TestCase
assert_select 'label.string.required[for=validating_user_name]', /Name/ assert_select 'label.string.required[for=validating_user_name]', /Name/
end end
test 'builder should escape label text' do
with_label_for @user, :name, label: '<script>alert(1337)</script>', required: false
assert_select 'label.string', "&lt;script&gt;alert(1337)&lt;/script&gt;"
end
test 'builder should not escape label text if it is safe' do
with_label_for @user, :name, label: '<script>alert(1337)</script>'.html_safe, required: false
assert_select 'label.string script', "alert(1337)"
end
test 'builder should allow passing options to label tag' do test 'builder should allow passing options to label tag' do
with_label_for @user, :name, label: 'My label', id: 'name_label' with_label_for @user, :name, label: 'My label', id: 'name_label'
assert_select 'label.string#name_label', /My label/ assert_select 'label.string#name_label', /My label/

View File

@ -230,4 +230,21 @@ class CollectionCheckBoxesInputTest < ActionView::TestCase
assert_select 'span.checkbox.inline > label > input' assert_select 'span.checkbox.inline > label > input'
end end
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 end

View File

@ -18,6 +18,14 @@ class CollectionRadioButtonsInputTest < ActionView::TestCase
assert_select 'label[for=user_active_false]', 'No' assert_select 'label[for=user_active_false]', 'No'
end 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 test 'input as radio should use i18n to translate internal labels' do
store_translations(:en, simple_form: { yes: 'Sim', no: 'Não' }) do store_translations(:en, simple_form: { yes: 'Sim', no: 'Não' }) do
with_input_for @user, :active, :radio_buttons with_input_for @user, :active, :radio_buttons
@ -323,4 +331,21 @@ class CollectionRadioButtonsInputTest < ActionView::TestCase
assert_select 'span.radio.inline > label > input' assert_select 'span.radio.inline > label > input'
end end
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 end

View File

@ -1,18 +1,69 @@
# encoding: UTF-8 # encoding: UTF-8
require 'test_helper' require 'test_helper'
# Tests for all different kinds of inputs. # Tests for datetime, date and time inputs when HTML5 compatibility is enabled in the wrapper.
class DateTimeInputTest < ActionView::TestCase class DateTimeInputWithHtml5Test < ActionView::TestCase
# DateTime input test 'input should generate a datetime input for datetime attributes if HTML5 compatibility is explicitly enbled' do
test 'input should generate a datetime select by default for datetime attributes' 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 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
end end
test 'input should be able to pass options to datetime select' do 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' } disabled: true, prompt: { year: 'ano', month: 'mês', day: 'dia' }
assert_select 'select.datetime[disabled=disabled]' assert_select 'select.datetime[disabled=disabled]'
@ -21,16 +72,26 @@ class DateTimeInputTest < ActionView::TestCase
assert_select 'select.datetime option', 'dia' assert_select 'select.datetime option', 'dia'
end 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 test 'input should generate a date select for date attributes' do
with_input_for @user, :born_at, :date swap_wrapper do
assert_select 'select.date#user_born_at_1i' with_input_for @user, :born_at, :date
assert_select 'select.date#user_born_at_2i' assert_select 'select.date#user_born_at_1i'
assert_select 'select.date#user_born_at_3i' assert_select 'select.date#user_born_at_2i'
assert_no_select 'select.date#user_born_at_4i' assert_select 'select.date#user_born_at_3i'
assert_no_select 'select.date#user_born_at_4i'
end
end end
test 'input should be able to pass options to date select' do 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' } disabled: true, prompt: { year: 'ano', month: 'mês', day: 'dia' }
assert_select 'select.date[disabled=disabled]' assert_select 'select.date[disabled=disabled]'
@ -40,21 +101,31 @@ class DateTimeInputTest < ActionView::TestCase
end end
test 'input should be able to pass :default to date select' do 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]" assert_select "select.date option[value=#{Date.today.year}][selected=selected]"
end 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 test 'input should generate a time select for time attributes' do
with_input_for @user, :delivery_time, :time swap_wrapper do
assert_select 'input[type=hidden]#user_delivery_time_1i' with_input_for @user, :delivery_time, :time
assert_select 'input[type=hidden]#user_delivery_time_2i' assert_select 'input[type=hidden]#user_delivery_time_1i'
assert_select 'input[type=hidden]#user_delivery_time_3i' assert_select 'input[type=hidden]#user_delivery_time_2i'
assert_select 'select.time#user_delivery_time_4i' assert_select 'input[type=hidden]#user_delivery_time_3i'
assert_select 'select.time#user_delivery_time_5i' assert_select 'select.time#user_delivery_time_4i'
assert_select 'select.time#user_delivery_time_5i'
end
end end
test 'input should be able to pass options to time select' do 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' } disabled: true, prompt: { hour: 'hora', minute: 'minuto' }
assert_select 'select.time[disabled=disabled]' assert_select 'select.time[disabled=disabled]'
@ -62,44 +133,40 @@ class DateTimeInputTest < ActionView::TestCase
assert_select 'select.time option', 'minuto' assert_select 'select.time option', 'minuto'
end 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 test 'label should use i18n to get target for date input type' do
store_translations(:en, date: { order: ['month', 'day', 'year'] }) 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]' assert_select 'label[for=project_created_at_2i]'
end end
end end
test 'label should use i18n to get target for datetime input type' do test 'label should use i18n to get target for datetime input type' do
store_translations(:en, date: { order: ['month', 'day', 'year'] }) 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]' assert_select 'label[for=project_created_at_2i]'
end end
end end
test 'label should use order to get target when date input type' do 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]' assert_select 'label[for=project_created_at_2i]'
end end
test 'label should use order to get target when datetime input type' do 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]' assert_select 'label[for=project_created_at_2i]'
end end
test 'label should point to first option when time input type' do 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]' assert_select 'label[for=project_created_at_4i]'
end 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 end