diff --git a/.rspec b/.rspec
new file mode 100644
index 0000000..83e16f8
--- /dev/null
+++ b/.rspec
@@ -0,0 +1,2 @@
+--color
+--require spec_helper
diff --git a/.rubocop.yml b/.rubocop.yml
index 4e4c583..a76f493 100644
--- a/.rubocop.yml
+++ b/.rubocop.yml
@@ -5,5 +5,10 @@ inherit_from:
Metrics/BlockLength:
Exclude:
- "test/**/*_test.rb" # Minitest syntax generates this false positive
+ - 'spec/**/*'
Style/MethodMissing:
Enabled: false
+Style/IndentHeredoc:
+ Enabled: false
+Style/SymbolArray:
+ Enabled: false
diff --git a/.travis.yml b/.travis.yml
index b72bae5..9b09564 100644
--- a/.travis.yml
+++ b/.travis.yml
@@ -5,7 +5,7 @@ before_install:
- gem update --system
- rvm @global do gem uninstall bundler -a -x
- rvm @global do gem install bundler -v 1.13.7
-script: 'bundle exec rake test:coverage --trace && bundle exec rubocop'
+script: 'bundle exec rake spec:coverage --trace && bundle exec rubocop'
rvm:
- 2.3.3
- 2.4.0
diff --git a/Rakefile b/Rakefile
index 9e6597c..91788cf 100644
--- a/Rakefile
+++ b/Rakefile
@@ -1,17 +1,25 @@
require 'rake'
-require 'rake/testtask'
require 'bundler/gem_tasks'
+require 'rspec/core/rake_task'
+require 'rake/testtask'
Rake::TestTask.new do |t|
t.pattern = 'test/**/*_test.rb'
t.libs.push 'test'
end
-namespace :test do
+namespace :spec do
+ RSpec::Core::RakeTask.new(:unit) do |task|
+ file_list = FileList['spec/**/*_spec.rb']
+ file_list = file_list.exclude("spec/{integration,isolation}/**/*_spec.rb")
+
+ task.pattern = file_list
+ end
+
task :coverage do
- ENV['COVERALL'] = 'true'
- Rake::Task['test'].invoke
+ ENV['COVERAGE'] = 'true'
+ Rake::Task['spec:unit'].invoke
end
end
-task default: :test
+task default: 'spec:unit'
diff --git a/hanami-helpers.gemspec b/hanami-helpers.gemspec
index 83513cd..0b6b181 100644
--- a/hanami-helpers.gemspec
+++ b/hanami-helpers.gemspec
@@ -1,5 +1,7 @@
# coding: utf-8
+
lib = File.expand_path('../lib', __FILE__)
+
$LOAD_PATH.unshift(lib) unless $LOAD_PATH.include?(lib)
require 'hanami/helpers/version'
@@ -25,6 +27,6 @@ Gem::Specification.new do |spec|
spec.add_development_dependency 'bundler', '~> 1.6'
spec.add_development_dependency 'rake', '~> 11'
spec.add_development_dependency 'minitest', '~> 5.5'
-
+ spec.add_development_dependency 'rspec', '~> 3.5'
spec.add_development_dependency 'dry-struct', '~> 0.1'
end
diff --git a/spec/hanami/helpers/escape_helper_spec.rb b/spec/hanami/helpers/escape_helper_spec.rb
new file mode 100644
index 0000000..c0ead3d
--- /dev/null
+++ b/spec/hanami/helpers/escape_helper_spec.rb
@@ -0,0 +1,64 @@
+RSpec.describe Hanami::Helpers::EscapeHelper do
+ before do
+ @view = EscapeView.new
+ end
+
+ it 'has a private escape html method' do
+ expect { @view.escape_html }.to raise_error(NoMethodError)
+ end
+
+ it 'has a private escape html attribute method' do
+ expect { @view.escape_html_attribute }.to raise_error(NoMethodError)
+ end
+
+ it 'has a private escape url method' do
+ expect { @view.escape_url }.to raise_error(NoMethodError)
+ end
+
+ it 'has a private raw method' do
+ expect { @view.raw }.to raise_error(NoMethodError)
+ end
+ it 'autoscape evil string' do
+ expect(@view.evil_string).to eq(%(<script>alert('xss')</script>))
+ end
+
+ it "don't autoscape safe string" do
+ expect(@view.good_string).to eq(%(this is a good string))
+ end
+
+ it 'autoscape attributes evil string' do
+ expect(@view.good_attributes_string).to eq(%(link))
+ end
+
+ it "don't autoscape attributes safe string" do
+ expect(@view.evil_attributes_string).to eq(%(link))
+ end
+
+ it 'autoscape url evil string' do
+ expect(@view.good_url_string).to eq(%(http://hanamirb.org))
+ end
+
+ it "don't autoscape url evil string" do
+ expect(@view.evil_url_string).to be_empty
+ end
+
+ it 'raw string is returned' do
+ expect(@view.raw_string).to eq(%(
I'm a raw string
))
+ end
+
+ it 'raw string is a Hanami::Helpers::Escape::SafeString class' do
+ expect(@view.raw_string.class).to eq(Hanami::Utils::Escape::SafeString)
+ end
+
+ it 'html helper alias' do
+ expect(@view.html_string_alias).to eq(%(this is a good string))
+ end
+
+ it 'html attribute helper alias' do
+ expect(@view.html_attribute_string_alias).to eq(%(link))
+ end
+
+ it 'url helper alias' do
+ expect(@view.url_string_alias).to eq(%(http://hanamirb.org))
+ end
+end
diff --git a/spec/hanami/helpers/form_helper_spec.rb b/spec/hanami/helpers/form_helper_spec.rb
new file mode 100644
index 0000000..fb4477f
--- /dev/null
+++ b/spec/hanami/helpers/form_helper_spec.rb
@@ -0,0 +1,2495 @@
+require 'ostruct'
+
+RSpec.describe Hanami::Helpers::FormHelper do
+ let(:view) { FormHelperView.new(params) }
+ let(:params) { Hash[] }
+ let(:action) { '/books' }
+
+ #
+ # FORM
+ #
+
+ describe '#form_for' do
+ it 'renders' do
+ actual = view.form_for(:book, action).to_s
+ expect(actual).to eq(%())
+ end
+
+ it "allows to override 'id' attribute" do
+ actual = view.form_for(:book, action, id: 'books').to_s
+ expect(actual).to eq(%())
+ end
+
+ it "allows to override 'method' attribute (get)" do
+ actual = view.form_for(:book, action, method: 'get').to_s
+ expect(actual).to eq(%())
+ end
+
+ it "allows to override 'method' attribute (:get)" do
+ actual = view.form_for(:book, action, method: :get).to_s
+ expect(actual).to eq(%())
+ end
+
+ it "allows to override 'method' attribute (GET)" do
+ actual = view.form_for(:book, action, method: 'GET').to_s
+ expect(actual).to eq(%())
+ end
+
+ [:patch, :put, :delete].each do |verb|
+ it "allows to override 'method' attribute (#{verb})" do
+ actual = view.form_for(:book, action, method: verb) do
+ text_field :title
+ end.to_s
+
+ expect(actual).to eq(%())
+ end
+ end
+
+ it "allows to override 'action' attribute" do
+ actual = view.form_for(:book, action, action: '/b').to_s
+ expect(actual).to eq(%())
+ end
+
+ it 'allows to specify HTML attributes' do
+ actual = view.form_for(:book, action, class: 'form-horizonal').to_s
+ expect(actual).to eq(%())
+ end
+
+ describe 'CSRF protection' do
+ let(:view) { SessionFormHelperView.new(params, csrf_token) }
+ let(:csrf_token) { 'abc123' }
+
+ it 'injects hidden field session is enabled' do
+ actual = view.form_for(:book, action, class: 'form-horizonal') {}
+ expect(actual.to_s).to eq(%())
+ end
+
+ describe 'with missing token' do
+ let(:csrf_token) { nil }
+
+ it "doesn't inject hidden field" do
+ actual = view.form_for(:book, action, class: 'form-horizonal') {}
+ expect(actual.to_s).to eq(%())
+ end
+ end
+
+ describe 'with csrf_token on get verb' do
+ let(:csrf_token) { 'abcd-1234-xyz' }
+
+ it "doesn't inject hidden field" do
+ actual = view.form_for(:book, action, method: 'GET', class: 'form-horizonal') {}
+ expect(actual.to_s).to eq(%())
+ end
+ end
+
+ [:patch, :put, :delete].each do |verb|
+ it "it injects hidden field when Method Override (#{verb}) is active" do
+ actual = view.form_for(:book, action, method: verb) do
+ text_field :title
+ end.to_s
+
+ expect(actual).to eq(%())
+ end
+ end
+ end
+ end
+
+ #
+ # NESTED FIELDS
+ #
+
+ describe '#fields_for' do
+ it 'renders' do
+ actual = view.form_for(:book, action) do
+ fields_for :categories do
+ text_field :name
+
+ fields_for :subcategories do
+ text_field :name
+ end
+
+ text_field :name2
+ end
+
+ text_field :title
+ end.to_s
+
+ expect(actual).to eq(%())
+ end
+
+ describe 'with filled params' do
+ let(:params) { Hash[book: { title: 'TDD', categories: { name: 'foo', name2: 'bar', subcategories: { name: 'sub' } } }] }
+
+ it 'renders' do
+ actual = view.form_for(:book, action) do
+ fields_for :categories do
+ text_field :name
+
+ fields_for :subcategories do
+ text_field :name
+ end
+
+ text_field :name2
+ end
+
+ text_field :title
+ end.to_s
+
+ expect(actual).to eq(%())
+ end
+ end
+ end
+
+ #
+ # LABEL
+ #
+
+ describe '#label' do
+ it 'renders capitalized string' do
+ actual = view.form_for(:book, action) do
+ label :free_shipping
+ end.to_s
+
+ expect(actual).to include(%())
+ end
+
+ it 'accepts a string as custom content' do
+ actual = view.form_for(:book, action) do
+ label 'Free Shipping', for: :free_shipping
+ end.to_s
+
+ expect(actual).to include(%())
+ end
+
+ it 'accepts a string as explicit "for" attribute' do
+ actual = view.form_for(:book, action) do
+ label :free_shipping, for: 'free-shipping'
+ end.to_s
+
+ expect(actual).to include(%())
+ end
+ end
+
+ #
+ # BUTTONS
+ #
+
+ describe '#button' do
+ it 'renders a button' do
+ actual = view.form_for(:book, action) do
+ button "Click me"
+ end.to_s
+
+ expect(actual).to include(%())
+ end
+
+ it 'renders a button with HTML attributes' do
+ actual = view.form_for(:book, action) do
+ button "Click me", class: "btn btn-secondary"
+ end.to_s
+
+ expect(actual).to include(%())
+ end
+ end
+
+ describe '#submit' do
+ it 'renders a submit button' do
+ actual = view.form_for(:book, action) do
+ submit "Create"
+ end.to_s
+
+ expect(actual).to include(%())
+ end
+
+ it 'renders a submit button with HTML attributes' do
+ actual = view.form_for(:book, action) do
+ submit "Create", class: "btn btn-primary"
+ end.to_s
+
+ expect(actual).to include(%())
+ end
+ end
+
+ describe '#image_button' do
+ it 'renders an image button' do
+ actual = view.form_for(:book, action) do
+ image_button "https://hanamirb.org/assets/image_button.png"
+ end.to_s
+
+ expect(actual).to include(%())
+ end
+
+ it 'renders an image button with HTML attributes' do
+ actual = view.form_for(:book, action) do
+ image_button "https://hanamirb.org/assets/image_button.png", name: "image", width: "50"
+ end.to_s
+
+ expect(actual).to include(%())
+ end
+
+ it 'prevents XSS attacks' do
+ actual = view.form_for(:book, action) do
+ image_button ""
+ end.to_s
+
+ expect(actual).to include(%())
+ end
+ end
+
+ #
+ # FIELDSET
+ #
+ describe '#fieldset' do
+ it 'renders a fieldset' do
+ actual = view.form_for(:book, action) do
+ fieldset do
+ legend "Author"
+
+ fields_for :author do
+ label :name
+ text_field :name
+ end
+ end
+ end.to_s
+
+ expect(actual).to include(%())
+ end
+ end
+
+ #
+ # INPUT FIELDS
+ #
+
+ describe '#check_box' do
+ it 'renders' do
+ actual = view.form_for(:book, action) do
+ check_box :free_shipping
+ end.to_s
+
+ expect(actual).to include(%(\n))
+ end
+
+ it 'allows to pass checked and unchecked value' do
+ actual = view.form_for(:book, action) do
+ check_box :free_shipping, checked_value: 'true', unchecked_value: 'false'
+ end.to_s
+
+ expect(actual).to include(%(\n))
+ end
+
+ it "allows to override 'id' attribute" do
+ actual = view.form_for(:book, action) do
+ check_box :free_shipping, id: 'shipping'
+ end.to_s
+
+ expect(actual).to include(%(\n))
+ end
+
+ it "allows to override 'name' attribute" do
+ actual = view.form_for(:book, action) do
+ check_box :free_shipping, name: 'book[free]'
+ end.to_s
+
+ expect(actual).to include(%(\n))
+ end
+
+ it 'allows to specify HTML attributes' do
+ actual = view.form_for(:book, action) do
+ check_box :free_shipping, class: 'form-control'
+ end.to_s
+
+ expect(actual).to include(%(\n))
+ end
+
+ it "doesn't render hidden field if 'value' attribute is specified" do
+ actual = view.form_for(:book, action) do
+ check_box :free_shipping, value: 'ok'
+ end.to_s
+
+ expect(actual).not_to include(%())
+ expect(actual).to include(%())
+ end
+
+ it "renders hidden field if 'value' attribute and 'unchecked_value' option are both specified" do
+ actual = view.form_for(:book, action) do
+ check_box :free_shipping, value: 'yes', unchecked_value: 'no'
+ end.to_s
+
+ expect(actual).to include(%(\n))
+ end
+
+ it 'handles multiple checkboxes' do
+ actual = view.form_for(:book, action) do
+ check_box :languages, name: 'book[languages][]', value: 'italian' # , id: nil FIXME
+ check_box :languages, name: 'book[languages][]', value: 'english' # , id: nil FIXME
+ end.to_s
+
+ expect(actual).to include(%(\n))
+ end
+
+ describe 'with filled params' do
+ let(:params) { Hash[book: { free_shipping: val }] }
+
+ describe 'when the params value equals to check box value' do
+ let(:val) { '1' }
+
+ it "renders with 'checked' attribute" do
+ actual = view.form_for(:book, action) do
+ check_box :free_shipping
+ end.to_s
+
+ expect(actual).to include(%(\n))
+ end
+ end
+
+ describe 'when the params value equals to the hidden field value' do
+ let(:val) { '0' }
+
+ it "renders without 'checked' attribute" do
+ actual = view.form_for(:book, action) do
+ check_box :free_shipping
+ end.to_s
+
+ expect(actual).to include(%(\n))
+ end
+
+ it "allows to override 'checked' attribute" do
+ actual = view.form_for(:book, action) do
+ check_box :free_shipping, checked: 'checked'
+ end.to_s
+
+ expect(actual).to include(%(\n))
+ end
+ end
+
+ describe 'with a boolean argument' do
+ let(:val) { true }
+
+ it "renders with 'checked' attribute" do
+ actual = view.form_for(:book, action) do
+ check_box :free_shipping
+ end.to_s
+
+ expect(actual).to include(%(\n))
+ end
+ end
+
+ describe 'when multiple params are present' do
+ let(:params) { Hash[book: { languages: ['italian'] }] }
+
+ it 'handles multiple checkboxes' do
+ actual = view.form_for(:book, action) do
+ check_box :languages, name: 'book[languages][]', value: 'italian' # , id: nil FIXME
+ check_box :languages, name: 'book[languages][]', value: 'english' # , id: nil FIXME
+ end.to_s
+
+ expect(actual).to include(%(\n))
+ end
+ end
+
+ describe 'checked_value is boolean' do
+ let(:params) { Hash[book: { free_shipping: 'true' }] }
+
+ it "renders with 'checked' attribute" do
+ actual = view.form_for(:book, action) do
+ check_box :free_shipping, checked_value: true
+ end.to_s
+
+ expect(actual).to include(%())
+ end
+ end
+
+ describe 'checked_value is boolean' do
+ let(:params) { Hash[book: { free_shipping: 'true' }] }
+
+ it "renders with 'checked' attribute" do
+ actual = view.form_for(:book, action) do
+ check_box :free_shipping, checked_value: true
+ end.to_s
+
+ expect(actual).to include(%())
+ end
+ end
+ end
+
+ describe 'automatic values' do
+ describe 'checkbox' do
+ describe 'value boolean, helper boolean, values differ' do
+ let(:values) { Hash[book: OpenStruct.new(free_shipping: false)] }
+
+ it 'renders' do
+ actual = view.form_for(:book, action, values: values) do
+ check_box :free_shipping, checked_value: true
+ end.to_s
+
+ expect(actual).to include(%())
+ end
+ end
+ end
+ end
+ end
+
+ describe '#color_field' do
+ it 'renders' do
+ actual = view.form_for(:book, action) do
+ color_field :cover
+ end.to_s
+
+ expect(actual).to include(%())
+ end
+
+ it "allows to override 'id' attribute" do
+ actual = view.form_for(:book, action) do
+ color_field :cover, id: 'b-cover'
+ end.to_s
+
+ expect(actual).to include(%())
+ end
+
+ it "allows to override 'name' attribute" do
+ actual = view.form_for(:book, action) do
+ color_field :cover, name: 'cover'
+ end.to_s
+
+ expect(actual).to include(%())
+ end
+
+ it "allows to override 'value' attribute" do
+ actual = view.form_for(:book, action) do
+ color_field :cover, value: '#ffffff'
+ end.to_s
+
+ expect(actual).to include(%())
+ end
+
+ it 'allows to specify HTML attributes' do
+ actual = view.form_for(:book, action) do
+ color_field :cover, class: 'form-control'
+ end.to_s
+
+ expect(actual).to include(%())
+ end
+
+ describe 'with values' do
+ let(:values) { Hash[book: Book.new(cover: val)] }
+ let(:val) { '#d3397e' }
+
+ it 'renders with value' do
+ actual = view.form_for(:book, action, values: values) do
+ color_field :cover
+ end.to_s
+
+ expect(actual).to include(%())
+ end
+
+ it "allows to override 'value' attribute" do
+ actual = view.form_for(:book, action, values: values) do
+ color_field :cover, value: '#000000'
+ end.to_s
+
+ expect(actual).to include(%())
+ end
+ end
+
+ describe 'with filled params' do
+ let(:params) { Hash[book: { cover: val }] }
+ let(:val) { '#d3397e' }
+
+ it 'renders with value' do
+ actual = view.form_for(:book, action) do
+ color_field :cover
+ end.to_s
+
+ expect(actual).to include(%())
+ end
+
+ it "allows to override 'value' attribute" do
+ actual = view.form_for(:book, action) do
+ color_field :cover, value: '#000000'
+ end.to_s
+
+ expect(actual).to include(%())
+ end
+ end
+ end
+
+ describe '#date_field' do
+ it 'renders' do
+ actual = view.form_for(:book, action) do
+ date_field :release_date
+ end.to_s
+
+ expect(actual).to include(%())
+ end
+
+ it "allows to override 'id' attribute" do
+ actual = view.form_for(:book, action) do
+ date_field :release_date, id: 'release-date'
+ end.to_s
+
+ expect(actual).to include(%())
+ end
+
+ it "allows to override 'name' attribute" do
+ actual = view.form_for(:book, action) do
+ date_field :release_date, name: 'release_date'
+ end.to_s
+
+ expect(actual).to include(%())
+ end
+
+ it "allows to override 'value' attribute" do
+ actual = view.form_for(:book, action) do
+ date_field :release_date, value: '2015-02-19'
+ end.to_s
+
+ expect(actual).to include(%())
+ end
+
+ it 'allows to specify HTML attributes' do
+ actual = view.form_for(:book, action) do
+ date_field :release_date, class: 'form-control'
+ end.to_s
+
+ expect(actual).to include(%())
+ end
+
+ describe 'with values' do
+ let(:values) { Hash[book: Book.new(release_date: val)] }
+ let(:val) { '2014-06-23' }
+
+ it 'renders with value' do
+ actual = view.form_for(:book, action, values: values) do
+ date_field :release_date
+ end.to_s
+
+ expect(actual).to include(%())
+ end
+
+ it "allows to override 'value' attribute" do
+ actual = view.form_for(:book, action, values: values) do
+ date_field :release_date, value: '2015-03-23'
+ end.to_s
+
+ expect(actual).to include(%())
+ end
+ end
+
+ describe 'with filled params' do
+ let(:params) { Hash[book: { release_date: val }] }
+ let(:val) { '2014-06-23' }
+
+ it 'renders with value' do
+ actual = view.form_for(:book, action) do
+ date_field :release_date
+ end.to_s
+
+ expect(actual).to include(%())
+ end
+
+ it "allows to override 'value' attribute" do
+ actual = view.form_for(:book, action) do
+ date_field :release_date, value: '2015-03-23'
+ end.to_s
+
+ expect(actual).to include(%())
+ end
+ end
+ end
+
+ describe '#datetime_field' do
+ it 'renders' do
+ actual = view.form_for(:book, action) do
+ datetime_field :published_at
+ end.to_s
+
+ expect(actual).to include(%())
+ end
+
+ it "allows to override 'id' attribute" do
+ actual = view.form_for(:book, action) do
+ datetime_field :published_at, id: 'published-timestamp'
+ end.to_s
+
+ expect(actual).to include(%())
+ end
+
+ it "allows to override 'name' attribute" do
+ actual = view.form_for(:book, action) do
+ datetime_field :published_at, name: 'book[published][timestamp]'
+ end.to_s
+
+ expect(actual).to include(%())
+ end
+
+ it "allows to override 'value' attribute" do
+ actual = view.form_for(:book, action) do
+ datetime_field :published_at, value: '2015-02-19T12:50:36Z'
+ end.to_s
+
+ expect(actual).to include(%())
+ end
+
+ it 'allows to specify HTML attributes' do
+ actual = view.form_for(:book, action) do
+ datetime_field :published_at, class: 'form-control'
+ end.to_s
+
+ expect(actual).to include(%())
+ end
+
+ describe 'with values' do
+ let(:values) { Hash[book: Book.new(published_at: val)] }
+ let(:val) { '2015-02-19T12:56:31Z' }
+
+ it 'renders with value' do
+ actual = view.form_for(:book, action, values: values) do
+ datetime_field :published_at
+ end.to_s
+
+ expect(actual).to include(%())
+ end
+
+ it "allows to override 'value' attribute" do
+ actual = view.form_for(:book, action, values: values) do
+ datetime_field :published_at, value: '2015-02-19T12:50:36Z'
+ end.to_s
+
+ expect(actual).to include(%())
+ end
+ end
+
+ describe 'with filled params' do
+ let(:params) { Hash[book: { published_at: val }] }
+ let(:val) { '2015-02-19T12:56:31Z' }
+
+ it 'renders with value' do
+ actual = view.form_for(:book, action) do
+ datetime_field :published_at
+ end.to_s
+
+ expect(actual).to include(%())
+ end
+
+ it "allows to override 'value' attribute" do
+ actual = view.form_for(:book, action) do
+ datetime_field :published_at, value: '2015-02-19T12:50:36Z'
+ end.to_s
+
+ expect(actual).to include(%())
+ end
+ end
+ end
+
+ describe '#datetime_local_field' do
+ it 'renders' do
+ actual = view.form_for(:book, action) do
+ datetime_local_field :released_at
+ end.to_s
+
+ expect(actual).to include(%())
+ end
+
+ it "allows to override 'id' attribute" do
+ actual = view.form_for(:book, action) do
+ datetime_local_field :released_at, id: 'local-release-timestamp'
+ end.to_s
+
+ expect(actual).to include(%())
+ end
+
+ it "allows to override 'name' attribute" do
+ actual = view.form_for(:book, action) do
+ datetime_local_field :released_at, name: 'book[release-timestamp]'
+ end.to_s
+
+ expect(actual).to include(%())
+ end
+
+ it "allows to override 'value' attribute" do
+ actual = view.form_for(:book, action) do
+ datetime_local_field :released_at, value: '2015-02-19T14:01:28+01:00'
+ end.to_s
+
+ expect(actual).to include(%())
+ end
+
+ it 'allows to specify HTML attributes' do
+ actual = view.form_for(:book, action) do
+ datetime_local_field :released_at, class: 'form-control'
+ end.to_s
+
+ expect(actual).to include(%())
+ end
+
+ describe 'with filled params' do
+ let(:params) { Hash[book: { released_at: val }] }
+ let(:val) { '2015-02-19T14:11:19+01:00' }
+
+ it 'renders with value' do
+ actual = view.form_for(:book, action) do
+ datetime_local_field :released_at
+ end.to_s
+
+ expect(actual).to include(%())
+ end
+
+ it "allows to override 'value' attribute" do
+ actual = view.form_for(:book, action) do
+ datetime_local_field :released_at, value: '2015-02-19T14:01:28+01:00'
+ end.to_s
+
+ expect(actual).to include(%())
+ end
+ end
+ end
+
+ describe '#time_field' do
+ it 'renders' do
+ actual = view.form_for(:book, action) do
+ time_field :release_hour
+ end.to_s
+
+ expect(actual).to include(%())
+ end
+
+ it "allows to override 'id' attribute" do
+ actual = view.form_for(:book, action) do
+ time_field :release_hour, id: 'release-hour'
+ end.to_s
+
+ expect(actual).to include(%())
+ end
+
+ it "allows to override 'name' attribute" do
+ actual = view.form_for(:book, action) do
+ time_field :release_hour, name: 'release_hour'
+ end.to_s
+
+ expect(actual).to include(%())
+ end
+
+ it "allows to override 'value' attribute" do
+ actual = view.form_for(:book, action) do
+ time_field :release_hour, value: '00:00'
+ end.to_s
+
+ expect(actual).to include(%())
+ end
+
+ it 'allows to specify HTML attributes' do
+ actual = view.form_for(:book, action) do
+ time_field :release_hour, class: 'form-control'
+ end.to_s
+
+ expect(actual).to include(%())
+ end
+
+ describe 'with values' do
+ let(:values) { Hash[book: Book.new(release_hour: val)] }
+ let(:val) { '18:30' }
+
+ it 'renders with value' do
+ actual = view.form_for(:book, action, values: values) do
+ time_field :release_hour
+ end.to_s
+
+ expect(actual).to include(%())
+ end
+
+ it "allows to override 'value' attribute" do
+ actual = view.form_for(:book, action, values: values) do
+ time_field :release_hour, value: '17:00'
+ end.to_s
+
+ expect(actual).to include(%())
+ end
+ end
+
+ describe 'with filled params' do
+ let(:params) { Hash[book: { release_hour: val }] }
+ let(:val) { '11:30' }
+
+ it 'renders with value' do
+ actual = view.form_for(:book, action) do
+ time_field :release_hour
+ end.to_s
+
+ expect(actual).to include(%())
+ end
+
+ it "allows to override 'value' attribute" do
+ actual = view.form_for(:book, action) do
+ time_field :release_hour, value: '8:15'
+ end.to_s
+
+ expect(actual).to include(%())
+ end
+ end
+ end
+
+ describe '#month_field' do
+ it 'renders' do
+ actual = view.form_for(:book, action) do
+ month_field :release_month
+ end.to_s
+
+ expect(actual).to include(%())
+ end
+
+ it "allows to override 'id' attribute" do
+ actual = view.form_for(:book, action) do
+ month_field :release_month, id: 'release-month'
+ end.to_s
+
+ expect(actual).to include(%())
+ end
+
+ it "allows to override 'name' attribute" do
+ actual = view.form_for(:book, action) do
+ month_field :release_month, name: 'release_month'
+ end.to_s
+
+ expect(actual).to include(%())
+ end
+
+ it "allows to override 'value' attribute" do
+ actual = view.form_for(:book, action) do
+ month_field :release_month, value: '2017-03'
+ end.to_s
+
+ expect(actual).to include(%())
+ end
+
+ it 'allows to specify HTML attributes' do
+ actual = view.form_for(:book, action) do
+ month_field :release_month, class: 'form-control'
+ end.to_s
+
+ expect(actual).to include(%())
+ end
+
+ describe 'with values' do
+ let(:values) { Hash[book: Book.new(release_month: val)] }
+ let(:val) { '2017-03' }
+
+ it 'renders with value' do
+ actual = view.form_for(:book, action, values: values) do
+ month_field :release_month
+ end.to_s
+
+ expect(actual).to include(%())
+ end
+
+ it "allows to override 'value' attribute" do
+ actual = view.form_for(:book, action, values: values) do
+ month_field :release_month, value: '2017-04'
+ end.to_s
+
+ expect(actual).to include(%())
+ end
+ end
+
+ describe 'with filled params' do
+ let(:params) { Hash[book: { release_month: val }] }
+ let(:val) { '2017-10' }
+
+ it 'renders with value' do
+ actual = view.form_for(:book, action) do
+ month_field :release_month
+ end.to_s
+
+ expect(actual).to include(%())
+ end
+
+ it "allows to override 'value' attribute" do
+ actual = view.form_for(:book, action) do
+ month_field :release_month, value: '2017-04'
+ end.to_s
+
+ expect(actual).to include(%())
+ end
+ end
+ end
+
+ describe '#week_field' do
+ it 'renders' do
+ actual = view.form_for(:book, action) do
+ week_field :release_week
+ end.to_s
+
+ expect(actual).to include(%())
+ end
+
+ it "allows to override 'id' attribute" do
+ actual = view.form_for(:book, action) do
+ week_field :release_week, id: 'release-week'
+ end.to_s
+
+ expect(actual).to include(%())
+ end
+
+ it "allows to override 'name' attribute" do
+ actual = view.form_for(:book, action) do
+ week_field :release_week, name: 'release_week'
+ end.to_s
+
+ expect(actual).to include(%())
+ end
+
+ it "allows to override 'value' attribute" do
+ actual = view.form_for(:book, action) do
+ week_field :release_week, value: '2017-W10'
+ end.to_s
+
+ expect(actual).to include(%())
+ end
+
+ it 'allows to specify HTML attributes' do
+ actual = view.form_for(:book, action) do
+ week_field :release_week, class: 'form-control'
+ end.to_s
+
+ expect(actual).to include(%())
+ end
+
+ describe 'with values' do
+ let(:values) { Hash[book: Book.new(release_week: val)] }
+ let(:val) { '2017-W10' }
+
+ it 'renders with value' do
+ actual = view.form_for(:book, action, values: values) do
+ week_field :release_week
+ end.to_s
+
+ expect(actual).to include(%())
+ end
+
+ it "allows to override 'value' attribute" do
+ actual = view.form_for(:book, action, values: values) do
+ week_field :release_week, value: '2017-W31'
+ end.to_s
+
+ expect(actual).to include(%())
+ end
+ end
+
+ describe 'with filled params' do
+ let(:params) { Hash[book: { release_week: val }] }
+ let(:val) { '2017-W44' }
+
+ it 'renders with value' do
+ actual = view.form_for(:book, action) do
+ week_field :release_week
+ end.to_s
+
+ expect(actual).to include(%())
+ end
+
+ it "allows to override 'value' attribute" do
+ actual = view.form_for(:book, action) do
+ week_field :release_week, value: '2017-W07'
+ end.to_s
+
+ expect(actual).to include(%())
+ end
+ end
+ end
+
+ describe '#email_field' do
+ it 'renders' do
+ actual = view.form_for(:book, action) do
+ email_field :publisher_email
+ end.to_s
+
+ expect(actual).to include(%())
+ end
+
+ it "allows to override 'id' attribute" do
+ actual = view.form_for(:book, action) do
+ email_field :publisher_email, id: 'publisher-email'
+ end.to_s
+
+ expect(actual).to include(%())
+ end
+
+ it "allows to override 'name' attribute" do
+ actual = view.form_for(:book, action) do
+ email_field :publisher_email, name: 'book[email]'
+ end.to_s
+
+ expect(actual).to include(%())
+ end
+
+ it "allows to override 'value' attribute" do
+ actual = view.form_for(:book, action) do
+ email_field :publisher_email, value: 'publisher@example.org'
+ end.to_s
+
+ expect(actual).to include(%())
+ end
+
+ it "allows to specify 'multiple' attribute" do
+ actual = view.form_for(:book, action) do
+ email_field :publisher_email, multiple: true
+ end.to_s
+
+ expect(actual).to include(%())
+ end
+
+ it 'allows to specify HTML attributes' do
+ actual = view.form_for(:book, action) do
+ email_field :publisher_email, class: 'form-control'
+ end.to_s
+
+ expect(actual).to include(%())
+ end
+
+ describe 'with values' do
+ let(:values) { Hash[book: Book.new(publisher_email: val)] }
+ let(:val) { 'maria@publisher.org' }
+
+ it 'renders with value' do
+ actual = view.form_for(:book, action, values: values) do
+ email_field :publisher_email
+ end.to_s
+
+ expect(actual).to include(%())
+ end
+
+ it "allows to override 'value' attribute" do
+ actual = view.form_for(:book, action, values: values) do
+ email_field :publisher_email, value: 'publisher@example.org'
+ end.to_s
+
+ expect(actual).to include(%())
+ end
+ end
+
+ describe 'with filled params' do
+ let(:params) { Hash[book: { publisher_email: val }] }
+ let(:val) { 'maria@publisher.org' }
+
+ it 'renders with value' do
+ actual = view.form_for(:book, action) do
+ email_field :publisher_email
+ end.to_s
+
+ expect(actual).to include(%())
+ end
+
+ it "allows to override 'value' attribute" do
+ actual = view.form_for(:book, action) do
+ email_field :publisher_email, value: 'publisher@example.org'
+ end.to_s
+
+ expect(actual).to include(%())
+ end
+ end
+ end
+
+ describe '#url_field' do
+ it 'renders' do
+ actual = view.form_for(:book, action) do
+ url_field :website
+ end.to_s
+
+ expect(actual).to include(%())
+ end
+
+ it "allows to override 'id' attribute" do
+ actual = view.form_for(:book, action) do
+ url_field :website, id: 'website'
+ end.to_s
+
+ expect(actual).to include(%())
+ end
+
+ it "allows to override 'name' attribute" do
+ actual = view.form_for(:book, action) do
+ url_field :website, name: 'book[url]'
+ end.to_s
+
+ expect(actual).to include(%())
+ end
+
+ it "allows to override 'value' attribute" do
+ actual = view.form_for(:book, action) do
+ url_field :website, value: 'http://example.org'
+ end.to_s
+
+ expect(actual).to include(%())
+ end
+
+ it "allows to specify 'multiple' attribute" do
+ actual = view.form_for(:book, action) do
+ url_field :website, multiple: true
+ end.to_s
+
+ expect(actual).to include(%())
+ end
+
+ it 'allows to specify HTML attributes' do
+ actual = view.form_for(:book, action) do
+ url_field :website, class: 'form-control'
+ end.to_s
+
+ expect(actual).to include(%())
+ end
+
+ describe 'with values' do
+ let(:values) { Hash[book: Book.new(website: val)] }
+ let(:val) { 'http://publisher.org' }
+
+ it 'renders with value' do
+ actual = view.form_for(:book, action, values: values) do
+ url_field :website
+ end.to_s
+
+ expect(actual).to include(%())
+ end
+
+ it "allows to override 'value' attribute" do
+ actual = view.form_for(:book, action, values: values) do
+ url_field :website, value: 'https://www.example.org'
+ end.to_s
+
+ expect(actual).to include(%())
+ end
+ end
+
+ describe 'with filled params' do
+ let(:params) { Hash[book: { website: val }] }
+ let(:val) { 'http://publisher.org' }
+
+ it 'renders with value' do
+ actual = view.form_for(:book, action) do
+ url_field :website
+ end.to_s
+
+ expect(actual).to include(%())
+ end
+
+ it "allows to override 'value' attribute" do
+ actual = view.form_for(:book, action) do
+ url_field :website, value: 'http://example.org'
+ end.to_s
+
+ expect(actual).to include(%())
+ end
+ end
+
+ describe 'with escape url' do
+ let(:values) { Hash[book: Book.new(website: val)] }
+ let(:val) { %("onclick=javascript:alert('xss')) }
+
+ it 'renders with automatic value' do
+ actual = view.form_for(:book, action, values: values) do
+ url_field :website
+ end.to_s
+
+ expect(actual).to include(%())
+ end
+
+ it 'renders with explicit value' do
+ actual = view.form_for(:book, action, values: values) do
+ url_field :website, value: val
+ end.to_s
+
+ expect(actual).to include(%())
+ end
+ end
+ end
+
+ describe '#tel_field' do
+ it 'renders' do
+ actual = view.form_for(:book, action) do
+ tel_field :publisher_telephone
+ end.to_s
+
+ expect(actual).to include(%())
+ end
+
+ it "allows to override 'id' attribute" do
+ actual = view.form_for(:book, action) do
+ tel_field :publisher_telephone, id: 'publisher-telephone'
+ end.to_s
+
+ expect(actual).to include(%())
+ end
+
+ it "allows to override 'name' attribute" do
+ actual = view.form_for(:book, action) do
+ tel_field :publisher_telephone, name: 'book[telephone]'
+ end.to_s
+
+ expect(actual).to include(%())
+ end
+
+ it "allows to override 'value' attribute" do
+ actual = view.form_for(:book, action) do
+ tel_field :publisher_telephone, value: 'publisher@example.org'
+ end.to_s
+
+ expect(actual).to include(%())
+ end
+
+ it "allows to specify 'multiple' attribute" do
+ actual = view.form_for(:book, action) do
+ tel_field :publisher_telephone, multiple: true
+ end.to_s
+
+ expect(actual).to include(%())
+ end
+
+ it 'allows to specify HTML attributes' do
+ actual = view.form_for(:book, action) do
+ tel_field :publisher_telephone, class: 'form-control'
+ end.to_s
+
+ expect(actual).to include(%())
+ end
+
+ describe 'with values' do
+ let(:values) { Hash[book: Book.new(publisher_telephone: val)] }
+ let(:val) { 'maria@publisher.org' }
+
+ it 'renders with value' do
+ actual = view.form_for(:book, action, values: values) do
+ tel_field :publisher_telephone
+ end.to_s
+
+ expect(actual).to include(%())
+ end
+
+ it "allows to override 'value' attribute" do
+ actual = view.form_for(:book, action, values: values) do
+ tel_field :publisher_telephone, value: 'publisher@example.org'
+ end.to_s
+
+ expect(actual).to include(%())
+ end
+ end
+
+ describe 'with filled params' do
+ let(:params) { Hash[book: { publisher_telephone: val }] }
+ let(:val) { 'maria@publisher.org' }
+
+ it 'renders with value' do
+ actual = view.form_for(:book, action) do
+ tel_field :publisher_telephone
+ end.to_s
+
+ expect(actual).to include(%())
+ end
+
+ it "allows to override 'value' attribute" do
+ actual = view.form_for(:book, action) do
+ tel_field :publisher_telephone, value: 'publisher@example.org'
+ end.to_s
+
+ expect(actual).to include(%())
+ end
+ end
+ end
+
+ describe '#file_field' do
+ it 'renders' do
+ actual = view.form_for(:book, action) do
+ file_field :image_cover
+ end.to_s
+
+ expect(actual).to include(%())
+ end
+
+ it "sets 'enctype' attribute to the form"
+ # it "sets 'enctype' attribute to the form" do
+ # actual = view.form_for(:book, action) do
+ # file_field :image_cover
+ # end.to_s
+
+ # expect(actual).to include(%(