# frozen_string_literal: true require "hanami/helpers/form_helper" require "hanami/view/erb/template" RSpec.describe Hanami::Helpers::FormHelper do subject(:obj) { Class.new { include Hanami::Helpers::FormHelper attr_reader :_context def initialize(context) @_context = context end }.new(context) } let(:context) { Hanami::View::Context.new(request: request, inflector: Dry::Inflector.new) } let(:request) { Hanami::Action::Request.new(env: rack_request, params: params, session_enabled: true) } let(:rack_request) { Rack::MockRequest.env_for("http://example.com/") } let(:params) { {} } def form_for(...) obj.instance_eval { form_for(...) } end def h(&block) obj.instance_eval(&block) end def render(erb) Hanami::View::ERB::Template.new { erb }.render(obj) end describe "#form_for" do it "renders" do html = form_for("/books") expect(html).to eq %(
) end it "allows to assign 'id' attribute" do html = form_for("/books", id: "book-form") expect(html).to eq %() end it "allows to override 'method' attribute ('get')" do html = form_for("/books", method: "get") expect(html).to eq %() end it "allows to override 'method' attribute (:get)" do html = form_for("/books", method: :get) expect(html).to eq %() end it "allows to override 'method' attribute ('GET')" do html = form_for("/books", method: "GET") expect(html).to eq %() end %i[patch put delete].each do |verb| it "allows to override 'method' attribute (#{verb})" do html = form_for("/books", method: verb) do |f| f.text_field "book.title" end expect(html).to eq %() end end it "allows to specify HTML attributes" do html = form_for("/books", class: "form-horizonal") expect(html).to eq %() end context "input name" do it "sets a base name" do expected_html = <<~HTML HTML html = form_for("book", "/books") do |f| f.text_field("author.avatar.url") end expect(html).to eq_html expected_html html = form_for("book", "/books") do |f| f.fields_for("author.avatar") do |fa| fa.text_field("url") end end expect(html).to eq_html expected_html end it "renders nested field names" do html = form_for("/books") do |f| f.text_field "book.author.avatar.url" end expect(html).to include %() end context "using values from scope locals" do let(:values) { {book: double("book", author: double("author", avatar: double("avatar", url: val)))} } let(:val) { "https://hanami.test/avatar.png" } before do # TODO: Maybe our `obj` should actually be a real Scope subclass values = self.values obj.define_singleton_method(:_locals) { values } end it "renders with value" do html = form_for("/books") do |f| f.text_field "book.author.avatar.url" end expect(html).to include %() end end context "with explicit values given" do let(:values) { {book: double("book", author: double("author", avatar: double("avatar", url: val)))} } let(:val) { "https://hanami.test/avatar.png" } it "renders with value" do html = form_for("/books", values: values) do |f| f.text_field "book.author.avatar.url" end expect(html).to include %() end it "allows to override 'value' attribute" do html = form_for("/books", values: values) do |f| f.text_field "book.author.avatar.url", value: "https://hanami.test/another-avatar.jpg" end expect(html).to include %() end end context "with filled params" do let(:params) { {book: {author: {avatar: {url: val}}}} } let(:val) { "https://hanami.test/avatar.png" } it "renders with value" do html = form_for("/books") do |f| f.text_field "book.author.avatar.url" end expect(html).to include %() end it "allows to override 'value' attribute" do html = form_for("/books") do |f| f.text_field "book.author.avatar.url", value: "https://hanami.test/another-avatar.jpg" end expect(html).to include %() end end end context "CSRF protection" do let(:csrf_token) { "abc123" } before do allow(request).to receive(:session) { {_csrf_token: csrf_token} } end it "injects hidden field session is enabled" do html = form_for("/books") expect(html).to eq %() end context "with missing token" do let(:csrf_token) { nil } it "doesn't inject hidden field" do html = form_for("/books") expect(html).to eq %() end end context "with csrf_token on get verb" do it "doesn't inject hidden field" do html = form_for("/books", method: "GET") expect(html).to eq %() end end %i[patch put delete].each do |verb| it "it injects hidden field when method override (#{verb}) is active" do html = form_for("/books", method: verb) expect(html).to eq %() end end end context "CSRF meta tags" do let(:csrf_token) { "abc123" } before do allow(request).to receive(:session) { {_csrf_token: csrf_token} } end def csrf_meta_tags(...) h { csrf_meta_tags(...) } end it "prints meta tags" do html = csrf_meta_tags expect(html).to eq %() end context "when CSRF token is nil" do let(:csrf_token) { nil } it "returns nil" do expect(csrf_meta_tags).to be(nil) end end end context "remote: true" do it "adds data-remote=true to form attributes" do html = form_for("/books", "data-remote": true) expect(html).to eq %() end it "adds data-remote=false to form attributes" do html = form_for("/books", "data-remote": false) expect(html).to eq %() end it "adds data-remote= to form attributes" do html = form_for("/books", "data-remote": nil) expect(html).to eq %() end end context "explicitly given params" do let(:params) { {song: {title: "Orphans"}} } let(:given_params) { {song: {title: "Arabesque"}} } let(:action) { "/songs" } it "renders" do html = form_for("/songs", params: given_params) do |f| f.text_field "song.title" end expect(html).to eq(%()) end end end describe "#fields_for" do it "renders" do html = render(<<~ERB) <%= form_for("/books") do |f| %> <% f.fields_for "book.categories" do |fa| %> <%= fa.text_field :name %> <% fa.fields_for :subcategories do |fb| %> <%= fb.text_field :name %> <% end %> <%= fa.text_field :name2 %> <% end %> <%= f.text_field "book.title" %> <% end %> ERB expect(html).to eq_html <<~HTML HTML end describe "with filled params" do let(:params) { {book: {title: "TDD", categories: {name: "foo", name2: "bar", subcategories: {name: "sub"}}}} } it "renders" do html = render(<<~ERB) <%= form_for("/books") do |f| %> <% f.fields_for "book.categories" do |fa| %> <%= fa.text_field :name %> <% fa.fields_for :subcategories do |fb| %> <%= fb.text_field :name %> <% end %> <%= fa.text_field :name2 %> <% end %> <%= f.text_field "book.title" %> <% end %> ERB expect(html).to eq_html <<~HTML HTML end end end describe "#fields_for_collection" do let(:params) { {book: {categories: [{name: "foo", new: true, genre: nil}]}} } it "renders" do html = render(<<~ERB) <%= form_for("/books") do |f| %> <% f.fields_for_collection "book.categories" do |fa| %> <%= fa.text_field :name %> <%= fa.hidden_field :name %> <%= fa.text_area :name %> <%= fa.check_box :new %> <%= fa.select :genre, [%w[Terror terror], %w[Comedy comedy]] %> <%= fa.color_field :name %> <%= fa.date_field :name %> <%= fa.datetime_field :name %> <%= fa.datetime_local_field :name %> <%= fa.time_field :name %> <%= fa.month_field :name %> <%= fa.week_field :name %> <%= fa.email_field :name %> <%= fa.url_field :name %> <%= fa.tel_field :name %> <%= fa.file_field :name %> <%= fa.number_field :name %> <%= fa.range_field :name %> <%= fa.search_field :name %> <%= fa.radio_button :name, "Fiction" %> <%= fa.password_field :name %> <%= fa.datalist :name, ["Italy", "United States"], "books" %> <% end %> <% end %> ERB expected = <<~HTML HTML expect(html).to eq_html(expected) end end describe "#label" do it "renders capitalized string" do html = form_for("/books") do |f| f.label "book.free_shipping" end expect(html).to include %() end it "accepts a string as custom content" do html = form_for("/books") do |f| f.label "Free Shipping!", for: "book.free_shipping" end expect(html).to include %() end it "renders a label with block" do html = render(<<~ERB) <%= form_for "/books" do |f| %> <%= f.label for: "book.free_shipping" do %> Free Shipping <%= tag.abbr "*", title: "optional", aria: {label: "optional"} %> <% end %> <% end %> ERB expect(html).to eq <<~HTML HTML end end describe "#button" do it "renders a button" do html = form_for("/books") do |f| f.button "Click me" end expect(html).to include %() end it "renders a button with HTML attributes" do html = form_for("/books") do |f| f.button "Click me", class: "btn btn-secondary" end expect(html).to include(%()) end it "renders a button with block" do html = render(<<~ERB) <%= form_for("/books") do |f| %> <%= f.button class: "btn btn-secondary" do %> <%= tag.span class: "oi oi-check" %> <% end %> <% end %> ERB expect(html).to eq <<~HTML HTML end end describe "#submit" do it "renders a submit button" do html = form_for("/books") do |f| f.submit "Create" end expect(html).to include %() end it "renders a submit button with HTML attributes" do html = form_for("/books") do |f| f.submit "Create", class: "btn btn-primary" end expect(html).to include %() end it "renders a submit button with block" do html = render(<<~ERB) <%= form_for "/books" do |f| %> <%= f.submit class: "btn btn-primary" do %> <%= tag.span class: "oi oi-check" %> <% end %> <% end %> ERB expect(html).to eq <<~HTML HTML end end describe "#image_button" do it "renders an image button" do html = form_for("/books") do |f| f.image_button "https://hanamirb.org/assets/image_button.png" end expect(html).to include %() end it "renders an image button with HTML attributes" do html = form_for("/books") do |f| f.image_button "https://hanamirb.org/assets/image_button.png", name: "image", width: "50" end expect(html).to include %() end it "prevents XSS attacks" do html = form_for("/books") do |f| f.image_button "" end expect(html).to include %() end end # # FIELDSET # describe "#fieldset" do it "renders a fieldset" do html = render(<<~ERB) <%= form_for "/books" do |f| %> <%= f.fieldset do %> <%= tag.legend "Author" %> <%= f.label "author.name" %> <%= f.text_field "author.name" %> <% end %> <% end %> ERB expect(html).to include_html <<~HTML HTML end end # # INPUT FIELDS # describe "#check_box" do it "renders" do html = form_for("/books") do |f| f.check_box "book.free_shipping" end expect(html).to include %() end it "allows to pass checked and unchecked value" do html = form_for("/books") do |f| f.check_box "book.free_shipping", checked_value: "true", unchecked_value: "false" end expect(html).to include %() end it "allows to override 'id' attribute" do html = form_for("/books") do |f| f.check_box "book.free_shipping", id: "shipping" end expect(html).to include %() end it "allows to override 'name' attribute" do html = form_for("/books") do |f| f.check_box "book.free_shipping", name: "book[free]" end expect(html).to include %() end it "allows to specify HTML attributes" do html = form_for("/books") do |f| f.check_box "book.free_shipping", class: "form-control" end expect(html).to include %() end it "doesn't render hidden field if 'value' attribute is specified" do html = form_for("/books") do |f| f.check_box "book.free_shipping", value: "ok" end expect(html).not_to include %() expect(html).to include %() end it "renders hidden field if 'value' attribute and 'unchecked_value' option are both specified" do html = form_for("/books") do |f| f.check_box "book.free_shipping", value: "yes", unchecked_value: "no" end expect(html).to include %() end it "handles multiple checkboxes" do html = render(<<~ERB) <%= form_for("/books") do |f| %> <%= f.check_box "book.languages", name: "book[languages][]", value: "italian", id: nil %> <%= f.check_box "book.languages", name: "book[languages][]", value: "english", id: nil %> <% end %> ERB expect(html).to include_html <<~HTML HTML end context "with filled params" do let(:params) { {book: {free_shipping: val}} } context "when the params value equals to check box value" do let(:val) { "1" } it "renders with 'checked' attribute" do html = form_for("/books") do |f| f.check_box "book.free_shipping" end expect(html).to include %() end end context "when the params value equals to the hidden field value" do let(:val) { "0" } it "renders without 'checked' attribute" do html = form_for("/books") do |f| f.check_box "book.free_shipping" end expect(html).to include %() end it "allows to override 'checked' attribute" do html = form_for("/books") do |f| f.check_box "book.free_shipping", checked: "checked" end expect(html).to include %() end end context "with a boolean argument" do let(:val) { true } it "renders with 'checked' attribute" do html = form_for("/books") do |f| f.check_box "book.free_shipping" end expect(html).to include %() end end context "when multiple params are present" do let(:params) { {book: {languages: ["italian"]}} } it "handles multiple checkboxes" do html = render(<<~ERB) <%= form_for("/books") do |f| %> <%= f.check_box "book.languages", name: "book[languages][]", value: "italian", id: nil %> <%= f.check_box "book.languages", name: "book[languages][]", value: "english", id: nil %> <% end %> ERB expect(html).to include_html <<~HTML HTML end end context "checked_value is boolean" do let(:params) { {book: {free_shipping: "true"}} } it "renders with 'checked' attribute" do html = form_for("/books") do |f| f.check_box "book.free_shipping", checked_value: true end expect(html).to include %() end end end context "automatic values" do context "checkbox" do context "value boolean, helper boolean, values differ" do let(:values) { {book: Struct.new(:free_shipping).new(false)} } it "renders" do html = form_for("/books", values: values) do |f| f.check_box "book.free_shipping", checked_value: true end expect(html).to include %() end end end end end describe "#color_field" do it "renders" do html = form_for("/books") do |f| f.color_field "book.cover" end expect(html).to include %() end it "allows to override 'id' attribute" do html = form_for("/books") do |f| f.color_field "book.cover", id: "b-cover" end expect(html).to include %() end it "allows to override 'name' attribute" do html = form_for("/books") do |f| f.color_field "book.cover", name: "cover" end expect(html).to include %() end it "allows to override 'value' attribute" do html = form_for("/books") do |f| f.color_field "book.cover", value: "#ffffff" end expect(html).to include %() end it "allows to specify HTML attributes" do html = form_for("/books") do |f| f.color_field "book.cover", class: "form-control" end expect(html).to include %() end context "with values" do let(:values) { {book: Struct.new(:cover).new(val)} } let(:val) { "#d3397e" } it "renders with value" do html = form_for("/books", values: values) do |f| f.color_field "book.cover" end expect(html).to include %() end it "allows to override 'value' attribute" do html = form_for("/books", values: values) do |f| f.color_field "book.cover", value: "#000000" end expect(html).to include %() end end context "with filled params" do let(:params) { {book: {cover: val}} } let(:val) { "#d3397e" } it "renders with value" do html = form_for("/books") do |f| f.color_field "book.cover" end expect(html).to include %() end it "allows to override 'value' attribute" do html = form_for("/books") do |f| f.color_field "book.cover", value: "#000000" end expect(html).to include %() end end end describe "#date_field" do it "renders" do html = form_for("/books") do |f| f.date_field "book.release_date" end expect(html).to include %() end it "allows to override 'id' attribute" do html = form_for("/books") do |f| f.date_field "book.release_date", id: "release-date" end expect(html).to include %() end it "allows to override 'name' attribute" do html = form_for("/books") do |f| f.date_field "book.release_date", name: "release_date" end expect(html).to include %() end it "allows to override 'value' attribute" do html = form_for("/books") do |f| f.date_field "book.release_date", value: "2015-02-19" end expect(html).to include %() end it "allows to specify HTML attributes" do html = form_for("/books") do |f| f.date_field "book.release_date", class: "form-control" end expect(html).to include %() end context "with values" do let(:values) { {book: Struct.new(:release_date).new(val)} } let(:val) { "2014-06-23" } it "renders with value" do html = form_for("/books", values: values) do |f| f.date_field "book.release_date" end expect(html).to include %() end it "allows to override 'value' attribute" do html = form_for("/books", values: values) do |f| f.date_field "book.release_date", value: "2015-03-23" end expect(html).to include %() end end context "with filled params" do let(:params) { {book: {release_date: val}} } let(:val) { "2014-06-23" } it "renders with value" do html = form_for("/books") do |f| f.date_field "book.release_date" end expect(html).to include %() end it "allows to override 'value' attribute" do html = form_for("/books") do |f| f.date_field "book.release_date", value: "2015-03-23" end expect(html).to include %() end end end describe "#datetime_field" do it "renders" do html = form_for("/books") do |f| f.datetime_field "book.published_at" end expect(html).to include %() end it "allows to override 'id' attribute" do html = form_for("/books") do |f| f.datetime_field "book.published_at", id: "published-timestamp" end expect(html).to include %() end it "allows to override 'name' attribute" do html = form_for("/books") do |f| f.datetime_field "book.published_at", name: "book[published][timestamp]" end expect(html).to include %() end it "allows to override 'value' attribute" do html = form_for("/books") do |f| f.datetime_field "book.published_at", value: "2015-02-19T12:50:36Z" end expect(html).to include %() end it "allows to specify HTML attributes" do html = form_for("/books") do |f| f.datetime_field "book.published_at", class: "form-control" end expect(html).to include %() end context "with values" do let(:values) { {book: Struct.new(:published_at).new(val)} } let(:val) { "2015-02-19T12:56:31Z" } it "renders with value" do html = form_for("/books", values: values) do |f| f.datetime_field "book.published_at" end expect(html).to include %() end it "allows to override 'value' attribute" do html = form_for("/books", values: values) do |f| f.datetime_field "book.published_at", value: "2015-02-19T12:50:36Z" end expect(html).to include %() end end context "with filled params" do let(:params) { {book: {published_at: val}} } let(:val) { "2015-02-19T12:56:31Z" } it "renders with value" do html = form_for("/books") do |f| f.datetime_field "book.published_at" end expect(html).to include %() end it "allows to override 'value' attribute" do html = form_for("/books") do |f| f.datetime_field "book.published_at", value: "2015-02-19T12:50:36Z" end expect(html).to include %() end end end describe "#datetime_local_field" do it "renders" do html = form_for("/books") do |f| f.datetime_local_field "book.released_at" end expect(html).to include %() end it "allows to override 'id' attribute" do html = form_for("/books") do |f| f.datetime_local_field "book.released_at", id: "local-release-timestamp" end expect(html).to include %() end it "allows to override 'name' attribute" do html = form_for("/books") do |f| f.datetime_local_field "book.released_at", name: "book[release-timestamp]" end expect(html).to include %() end it "allows to override 'value' attribute" do html = form_for("/books") do |f| f.datetime_local_field "book.released_at", value: "2015-02-19T14:01:28+01:00" end expect(html).to include %() end it "allows to specify HTML attributes" do html = form_for("/books") do |f| f.datetime_local_field "book.released_at", class: "form-control" end expect(html).to include %() end context "with filled params" do let(:params) { {book: {released_at: val}} } let(:val) { "2015-02-19T14:11:19+01:00" } it "renders with value" do html = form_for("/books") do |f| f.datetime_local_field "book.released_at" end expect(html).to include %() end it "allows to override 'value' attribute" do html = form_for("/books") do |f| f.datetime_local_field "book.released_at", value: "2015-02-19T14:01:28+01:00" end expect(html).to include %() end end end describe "#time_field" do it "renders" do html = form_for("/books") do |f| f.time_field "book.release_hour" end expect(html).to include %() end it "allows to override 'id' attribute" do html = form_for("/books") do |f| f.time_field "book.release_hour", id: "release-hour" end expect(html).to include %() end it "allows to override 'name' attribute" do html = form_for("/books") do |f| f.time_field "book.release_hour", name: "release_hour" end expect(html).to include %() end it "allows to override 'value' attribute" do html = form_for("/books") do |f| f.time_field "book.release_hour", value: "00:00" end expect(html).to include %() end it "allows to specify HTML attributes" do html = form_for("/books") do |f| f.time_field "book.release_hour", class: "form-control" end expect(html).to include %() end context "with values" do let(:values) { {book: Struct.new(:release_hour).new(val)} } let(:val) { "18:30" } it "renders with value" do html = form_for("/books", values: values) do |f| f.time_field "book.release_hour" end expect(html).to include %() end it "allows to override 'value' attribute" do html = form_for("/books", values: values) do |f| f.time_field "book.release_hour", value: "17:00" end expect(html).to include %() end end context "with filled params" do let(:params) { {book: {release_hour: val}} } let(:val) { "11:30" } it "renders with value" do html = form_for("/books") do |f| f.time_field "book.release_hour" end expect(html).to include %() end it "allows to override 'value' attribute" do html = form_for("/books") do |f| f.time_field "book.release_hour", value: "8:15" end expect(html).to include %() end end end describe "#month_field" do it "renders" do html = form_for("/books") do |f| f.month_field "book.release_month" end expect(html).to include %() end it "allows to override 'id' attribute" do html = form_for("/books") do |f| f.month_field "book.release_month", id: "release-month" end expect(html).to include %() end it "allows to override 'name' attribute" do html = form_for("/books") do |f| f.month_field "book.release_month", name: "release_month" end expect(html).to include %() end it "allows to override 'value' attribute" do html = form_for("/books") do |f| f.month_field "book.release_month", value: "2017-03" end expect(html).to include %() end it "allows to specify HTML attributes" do html = form_for("/books") do |f| f.month_field "book.release_month", class: "form-control" end expect(html).to include %() end context "with values" do let(:values) { {book: Struct.new(:release_month).new(val)} } let(:val) { "2017-03" } it "renders with value" do html = form_for("/books", values: values) do |f| f.month_field "book.release_month" end expect(html).to include %() end it "allows to override 'value' attribute" do html = form_for("/books", values: values) do |f| f.month_field "book.release_month", value: "2017-04" end expect(html).to include %() end end context "with filled params" do let(:params) { {book: {release_month: val}} } let(:val) { "2017-10" } it "renders with value" do html = form_for("/books") do |f| f.month_field "book.release_month" end expect(html).to include %() end it "allows to override 'value' attribute" do html = form_for("/books") do |f| f.month_field "book.release_month", value: "2017-04" end expect(html).to include %() end end end describe "#week_field" do it "renders" do html = form_for("/books") do |f| f.week_field "book.release_week" end expect(html).to include %() end it "allows to override 'id' attribute" do html = form_for("/books") do |f| f.week_field "book.release_week", id: "release-week" end expect(html).to include %() end it "allows to override 'name' attribute" do html = form_for("/books") do |f| f.week_field "book.release_week", name: "release_week" end expect(html).to include %() end it "allows to override 'value' attribute" do html = form_for("/books") do |f| f.week_field "book.release_week", value: "2017-W10" end expect(html).to include %() end it "allows to specify HTML attributes" do html = form_for("/books") do |f| f.week_field "book.release_week", class: "form-control" end expect(html).to include %() end context "with values" do let(:values) { {book: Struct.new(:release_week).new(val)} } let(:val) { "2017-W10" } it "renders with value" do html = form_for("/books", values: values) do |f| f.week_field "book.release_week" end expect(html).to include %() end it "allows to override 'value' attribute" do html = form_for("/books", values: values) do |f| f.week_field "book.release_week", value: "2017-W31" end expect(html).to include %() end end context "with filled params" do let(:params) { {book: {release_week: val}} } let(:val) { "2017-W44" } it "renders with value" do html = form_for("/books") do |f| f.week_field "book.release_week" end expect(html).to include %() end it "allows to override 'value' attribute" do html = form_for("/books") do |f| f.week_field "book.release_week", value: "2017-W07" end expect(html).to include %() end end end describe "#email_field" do it "renders" do html = form_for("/books") do |f| f.email_field "book.publisher_email" end expect(html).to include %() end it "allows to override 'id' attribute" do html = form_for("/books") do |f| f.email_field "book.publisher_email", id: "publisher-email" end expect(html).to include %() end it "allows to override 'name' attribute" do html = form_for("/books") do |f| f.email_field "book.publisher_email", name: "book[email]" end expect(html).to include %() end it "allows to override 'value' attribute" do html = form_for("/books") do |f| f.email_field "book.publisher_email", value: "publisher@example.org" end expect(html).to include %() end it "allows to specify 'multiple' attribute" do html = form_for("/books") do |f| f.email_field "book.publisher_email", multiple: true end expect(html).to include %() end it "allows to specify HTML attributes" do html = form_for("/books") do |f| f.email_field "book.publisher_email", class: "form-control" end expect(html).to include %() end context "with values" do let(:values) { {book: Struct.new(:publisher_email).new(val)} } let(:val) { "maria@publisher.org" } it "renders with value" do html = form_for("/books", values: values) do |f| f.email_field "book.publisher_email" end expect(html).to include %() end it "allows to override 'value' attribute" do html = form_for("/books", values: values) do |f| f.email_field "book.publisher_email", value: "publisher@example.org" end expect(html).to include %() end end context "with filled params" do let(:params) { {book: {publisher_email: val}} } let(:val) { "maria@publisher.org" } it "renders with value" do html = form_for("/books") do |f| f.email_field "book.publisher_email" end expect(html).to include %() end it "allows to override 'value' attribute" do html = form_for("/books") do |f| f.email_field "book.publisher_email", value: "publisher@example.org" end expect(html).to include %() end end end describe "#url_field" do it "renders" do html = form_for("/books") do |f| f.url_field "book.website" end expect(html).to include %() end it "allows to override 'id' attribute" do html = form_for("/books") do |f| f.url_field "book.website", id: "website" end expect(html).to include %() end it "allows to override 'name' attribute" do html = form_for("/books") do |f| f.url_field "book.website", name: "book[url]" end expect(html).to include %() end it "allows to override 'value' attribute" do html = form_for("/books") do |f| f.url_field "book.website", value: "http://example.org" end expect(html).to include %() end it "allows to specify 'multiple' attribute" do html = form_for("/books") do |f| f.url_field "book.website", multiple: true end expect(html).to include %() end it "allows to specify HTML attributes" do html = form_for("/books") do |f| f.url_field "book.website", class: "form-control" end expect(html).to include %() end context "with values" do let(:values) { {book: Struct.new(:website).new(val)} } let(:val) { "http://publisher.org" } it "renders with value" do html = form_for("/books", values: values) do |f| f.url_field "book.website" end expect(html).to include %() end it "allows to override 'value' attribute" do html = form_for("/books", values: values) do |f| f.url_field "book.website", value: "https://www.example.org" end expect(html).to include %() end end context "with filled params" do let(:params) { {book: {website: val}} } let(:val) { "http://publisher.org" } it "renders with value" do html = form_for("/books") do |f| f.url_field "book.website" end expect(html).to include %() end it "allows to override 'value' attribute" do html = form_for("/books") do |f| f.url_field "book.website", value: "http://example.org" end expect(html).to include %() end end context "with escape url" do let(:values) { {book: Struct.new(:website).new(val)} } let(:val) { %("onclick=javascript:alert('xss')) } it "renders with automatic value" do html = form_for("/books", values: values) do |f| f.url_field "book.website" end expect(html).to include %() end it "renders with explicit value" do html = form_for("/books", values: values) do |f| f.url_field "book.website", value: val end expect(html).to include %() end end end describe "#tel_field" do it "renders" do html = form_for("/books") do |f| f.tel_field "book.publisher_telephone" end expect(html).to include %() end it "allows to override 'id' attribute" do html = form_for("/books") do |f| f.tel_field "book.publisher_telephone", id: "publisher-telephone" end expect(html).to include %() end it "allows to override 'name' attribute" do html = form_for("/books") do |f| f.tel_field "book.publisher_telephone", name: "book[telephone]" end expect(html).to include %() end it "allows to override 'value' attribute" do html = form_for("/books") do |f| f.tel_field "book.publisher_telephone", value: "publisher@example.org" end expect(html).to include %() end it "allows to specify 'multiple' attribute" do html = form_for("/books") do |f| f.tel_field "book.publisher_telephone", multiple: true end expect(html).to include %() end it "allows to specify HTML attributes" do html = form_for("/books") do |f| f.tel_field "book.publisher_telephone", class: "form-control" end expect(html).to include %() end context "with values" do let(:values) { {book: Struct.new(:publisher_telephone).new(val)} } let(:val) { "maria@publisher.org" } it "renders with value" do html = form_for("/books", values: values) do |f| f.tel_field "book.publisher_telephone" end expect(html).to include %() end it "allows to override 'value' attribute" do html = form_for("/books", values: values) do |f| f.tel_field "book.publisher_telephone", value: "publisher@example.org" end expect(html).to include %() end end context "with filled params" do let(:params) { {book: {publisher_telephone: val}} } let(:val) { "maria@publisher.org" } it "renders with value" do html = form_for("/books") do |f| f.tel_field "book.publisher_telephone" end expect(html).to include %() end it "allows to override 'value' attribute" do html = form_for("/books") do |f| f.tel_field "book.publisher_telephone", value: "publisher@example.org" end expect(html).to include %() end end end describe "#file_field" do it "renders" do html = form_for("/books") do |f| f.file_field "book.image_cover" end expect(html).to include %() end it "sets 'enctype' attribute to the form" do html = form_for("/books") do |f| f.file_field "book.image_cover" end expect(html).to include %() end end context "with non String values" do let(:values) { {book: Struct.new(:category).new(val)} } let(:option_values) { {"Horror" => "1", "SciFy" => "2"} } let(:val) { 1 } it "sets correct value as selected" do html = form_for("/books", values: values) do |f| f.select "book.category", option_values end expect(html).to include %() end end end end describe "#datalist" do let(:values) { ["Italy", "United States"] } it "renders" do html = form_for("/books") do |f| f.datalist "book.store", values, "books" end expect(html).to include %() end it "just allows to override 'id' attribute of the text input" do html = form_for("/books") do |f| f.datalist "book.store", values, "books", id: "store" end expect(html).to include %() end it "allows to override 'name' attribute" do html = form_for("/books") do |f| f.datalist "book.store", values, "books", name: "store" end expect(html).to include %() end it "allows to specify HTML attributes" do html = form_for("/books") do |f| f.datalist "book.store", values, "books", class: "form-control" end expect(html).to include %() end it "allows to specify HTML attributes for options" do html = form_for("/books") do |f| f.datalist "book.store", values, "books", options: {class: "form-option"} end expect(html).to include %() end it "allows to specify HTML attributes for datalist" do html = form_for("/books") do |f| f.datalist "book.store", values, "books", datalist: {class: "form-option"} end expect(html).to include %() end context "with a Hash of values" do let(:values) { {"Italy" => "it", "United States" => "us"} } it "renders" do html = form_for("/books") do |f| f.datalist "book.store", values, "books" end expect(html).to include %() end end end end