hanami 2.0.3 → 2.1.0.beta1
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- checksums.yaml +4 -4
- data/CHANGELOG.md +19 -0
- data/LICENSE.md +1 -1
- data/README.md +25 -9
- data/hanami.gemspec +2 -2
- data/lib/hanami/config/actions.rb +0 -4
- data/lib/hanami/config/views.rb +0 -4
- data/lib/hanami/config.rb +54 -0
- data/lib/hanami/extensions/action/slice_configured_action.rb +15 -7
- data/lib/hanami/extensions/action.rb +4 -4
- data/lib/hanami/extensions/router/errors.rb +58 -0
- data/lib/hanami/extensions/view/context.rb +129 -60
- data/lib/hanami/extensions/view/part.rb +26 -0
- data/lib/hanami/extensions/view/scope.rb +26 -0
- data/lib/hanami/extensions/view/slice_configured_context.rb +0 -2
- data/lib/hanami/extensions/view/slice_configured_helpers.rb +44 -0
- data/lib/hanami/extensions/view/slice_configured_view.rb +106 -21
- data/lib/hanami/extensions/view/standard_helpers.rb +14 -0
- data/lib/hanami/extensions.rb +10 -3
- data/lib/hanami/helpers/form_helper/form_builder.rb +1391 -0
- data/lib/hanami/helpers/form_helper/values.rb +75 -0
- data/lib/hanami/helpers/form_helper.rb +213 -0
- data/lib/hanami/middleware/public_errors_app.rb +75 -0
- data/lib/hanami/middleware/render_errors.rb +93 -0
- data/lib/hanami/slice.rb +27 -2
- data/lib/hanami/slice_configurable.rb +3 -2
- data/lib/hanami/version.rb +1 -1
- data/lib/hanami/web/rack_logger.rb +1 -1
- data/lib/hanami.rb +1 -1
- data/spec/integration/action/view_rendering/view_context_spec.rb +221 -0
- data/spec/integration/action/view_rendering_spec.rb +0 -18
- data/spec/integration/rack_app/middleware_spec.rb +23 -23
- data/spec/integration/rack_app/rack_app_spec.rb +5 -1
- data/spec/integration/view/config/default_context_spec.rb +149 -0
- data/spec/integration/view/{inflector_spec.rb → config/inflector_spec.rb} +1 -1
- data/spec/integration/view/config/part_class_spec.rb +147 -0
- data/spec/integration/view/config/part_namespace_spec.rb +103 -0
- data/spec/integration/view/config/paths_spec.rb +119 -0
- data/spec/integration/view/config/scope_class_spec.rb +147 -0
- data/spec/integration/view/config/scope_namespace_spec.rb +103 -0
- data/spec/integration/view/config/template_spec.rb +38 -0
- data/spec/integration/view/context/request_spec.rb +3 -7
- data/spec/integration/view/helpers/form_helper_spec.rb +174 -0
- data/spec/integration/view/helpers/part_helpers_spec.rb +124 -0
- data/spec/integration/view/helpers/scope_helpers_spec.rb +84 -0
- data/spec/integration/view/helpers/user_defined_helpers/part_helpers_spec.rb +162 -0
- data/spec/integration/view/helpers/user_defined_helpers/scope_helpers_spec.rb +119 -0
- data/spec/integration/view/slice_configuration_spec.rb +9 -9
- data/spec/integration/web/render_detailed_errors_spec.rb +90 -0
- data/spec/integration/web/render_errors_spec.rb +240 -0
- data/spec/spec_helper.rb +1 -1
- data/spec/support/matchers.rb +32 -0
- data/spec/unit/hanami/config/actions/default_values_spec.rb +0 -4
- data/spec/unit/hanami/config/render_detailed_errors_spec.rb +25 -0
- data/spec/unit/hanami/config/render_errors_spec.rb +25 -0
- data/spec/unit/hanami/config/views_spec.rb +0 -18
- data/spec/unit/hanami/extensions/view/context_spec.rb +59 -0
- data/spec/unit/hanami/helpers/form_helper_spec.rb +2826 -0
- data/spec/unit/hanami/router/errors/not_allowed_error_spec.rb +27 -0
- data/spec/unit/hanami/router/errors/not_found_error_spec.rb +22 -0
- data/spec/unit/hanami/slice_configurable_spec.rb +18 -0
- data/spec/unit/hanami/version_spec.rb +1 -1
- data/spec/unit/hanami/web/rack_logger_spec.rb +1 -1
- metadata +65 -33
- data/spec/integration/action/view_integration_spec.rb +0 -165
- data/spec/integration/view/part_namespace_spec.rb +0 -96
- data/spec/integration/view/path_spec.rb +0 -56
- data/spec/integration/view/template_spec.rb +0 -68
- data/spec/isolation/hanami/application/already_configured_spec.rb +0 -19
- data/spec/isolation/hanami/application/inherit_anonymous_class_spec.rb +0 -10
- data/spec/isolation/hanami/application/inherit_concrete_class_spec.rb +0 -14
- data/spec/isolation/hanami/application/not_configured_spec.rb +0 -9
- data/spec/isolation/hanami/application/routes/configured_spec.rb +0 -44
- data/spec/isolation/hanami/application/routes/not_configured_spec.rb +0 -16
- data/spec/isolation/hanami/boot/success_spec.rb +0 -50
@@ -0,0 +1,2826 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
require "hanami/helpers/form_helper"
|
4
|
+
require "hanami/view/erb/template"
|
5
|
+
|
6
|
+
RSpec.describe Hanami::Helpers::FormHelper do
|
7
|
+
subject(:obj) {
|
8
|
+
Class.new {
|
9
|
+
include Hanami::Helpers::FormHelper
|
10
|
+
|
11
|
+
attr_reader :_context
|
12
|
+
|
13
|
+
def initialize(context)
|
14
|
+
@_context = context
|
15
|
+
end
|
16
|
+
}.new(context)
|
17
|
+
}
|
18
|
+
|
19
|
+
let(:context) {
|
20
|
+
Hanami::View::Context.new(request: request, inflector: Dry::Inflector.new)
|
21
|
+
}
|
22
|
+
|
23
|
+
let(:request) {
|
24
|
+
Hanami::Action::Request.new(env: rack_request, params: params, session_enabled: true)
|
25
|
+
}
|
26
|
+
|
27
|
+
let(:rack_request) {
|
28
|
+
Rack::MockRequest.env_for("http://example.com/")
|
29
|
+
}
|
30
|
+
|
31
|
+
let(:params) { {} }
|
32
|
+
|
33
|
+
def form_for(...)
|
34
|
+
obj.instance_eval { form_for(...) }
|
35
|
+
end
|
36
|
+
|
37
|
+
def h(&block)
|
38
|
+
obj.instance_eval(&block)
|
39
|
+
end
|
40
|
+
|
41
|
+
def render(erb)
|
42
|
+
Hanami::View::ERB::Template.new { erb }.render(obj)
|
43
|
+
end
|
44
|
+
|
45
|
+
describe "#form_for" do
|
46
|
+
it "renders" do
|
47
|
+
html = form_for("/books")
|
48
|
+
expect(html).to eq %(<form action="/books" accept-charset="utf-8" method="POST"></form>)
|
49
|
+
end
|
50
|
+
|
51
|
+
it "allows to assign 'id' attribute" do
|
52
|
+
html = form_for("/books", id: "book-form")
|
53
|
+
|
54
|
+
expect(html).to eq %(<form action="/books" id="book-form" accept-charset="utf-8" method="POST"></form>)
|
55
|
+
end
|
56
|
+
|
57
|
+
it "allows to override 'method' attribute ('get')" do
|
58
|
+
html = form_for("/books", method: "get")
|
59
|
+
expect(html).to eq %(<form action="/books" method="GET" accept-charset="utf-8"></form>)
|
60
|
+
end
|
61
|
+
|
62
|
+
it "allows to override 'method' attribute (:get)" do
|
63
|
+
html = form_for("/books", method: :get)
|
64
|
+
expect(html).to eq %(<form action="/books" method="GET" accept-charset="utf-8"></form>)
|
65
|
+
end
|
66
|
+
|
67
|
+
it "allows to override 'method' attribute ('GET')" do
|
68
|
+
html = form_for("/books", method: "GET")
|
69
|
+
expect(html).to eq %(<form action="/books" method="GET" accept-charset="utf-8"></form>)
|
70
|
+
end
|
71
|
+
|
72
|
+
%i[patch put delete].each do |verb|
|
73
|
+
it "allows to override 'method' attribute (#{verb})" do
|
74
|
+
html = form_for("/books", method: verb) do |f|
|
75
|
+
f.text_field "book.title"
|
76
|
+
end
|
77
|
+
|
78
|
+
expect(html).to eq %(<form action="/books" method="POST" accept-charset="utf-8"><input type="hidden" name="_method" value="#{verb.to_s.upcase}"><input type="text" name="book[title]" id="book-title" value=""></form>)
|
79
|
+
end
|
80
|
+
end
|
81
|
+
|
82
|
+
it "allows to specify HTML attributes" do
|
83
|
+
html = form_for("/books", class: "form-horizonal")
|
84
|
+
expect(html).to eq %(<form action="/books" class="form-horizonal" accept-charset="utf-8" method="POST"></form>)
|
85
|
+
end
|
86
|
+
|
87
|
+
context "input name" do
|
88
|
+
it "sets a base name" do
|
89
|
+
expected_html = <<~HTML
|
90
|
+
<form action="/books" accept-charset="utf-8" method="POST">
|
91
|
+
<input type="text" name="book[author][avatar][url]" id="book-author-avatar-url" value="">
|
92
|
+
</form>
|
93
|
+
HTML
|
94
|
+
|
95
|
+
html = form_for("book", "/books") do |f|
|
96
|
+
f.text_field("author.avatar.url")
|
97
|
+
end
|
98
|
+
|
99
|
+
expect(html).to eq_html expected_html
|
100
|
+
|
101
|
+
html = form_for("book", "/books") do |f|
|
102
|
+
f.fields_for("author.avatar") do |fa|
|
103
|
+
fa.text_field("url")
|
104
|
+
end
|
105
|
+
end
|
106
|
+
|
107
|
+
expect(html).to eq_html expected_html
|
108
|
+
end
|
109
|
+
|
110
|
+
it "renders nested field names" do
|
111
|
+
html = form_for("/books") do |f|
|
112
|
+
f.text_field "book.author.avatar.url"
|
113
|
+
end
|
114
|
+
|
115
|
+
expect(html).to include %(<input type="text" name="book[author][avatar][url]" id="book-author-avatar-url" value="">)
|
116
|
+
end
|
117
|
+
|
118
|
+
context "using values from scope locals" do
|
119
|
+
let(:values) { {book: double("book", author: double("author", avatar: double("avatar", url: val)))} }
|
120
|
+
let(:val) { "https://hanami.test/avatar.png" }
|
121
|
+
|
122
|
+
before do
|
123
|
+
# TODO: Maybe our `obj` should actually be a real Scope subclass
|
124
|
+
values = self.values
|
125
|
+
obj.define_singleton_method(:_locals) { values }
|
126
|
+
end
|
127
|
+
|
128
|
+
it "renders with value" do
|
129
|
+
html = form_for("/books") do |f|
|
130
|
+
f.text_field "book.author.avatar.url"
|
131
|
+
end
|
132
|
+
|
133
|
+
expect(html).to include %(<input type="text" name="book[author][avatar][url]" id="book-author-avatar-url" value="#{val}">)
|
134
|
+
end
|
135
|
+
end
|
136
|
+
|
137
|
+
context "with explicit values given" do
|
138
|
+
let(:values) { {book: double("book", author: double("author", avatar: double("avatar", url: val)))} }
|
139
|
+
let(:val) { "https://hanami.test/avatar.png" }
|
140
|
+
|
141
|
+
it "renders with value" do
|
142
|
+
html = form_for("/books", values: values) do |f|
|
143
|
+
f.text_field "book.author.avatar.url"
|
144
|
+
end
|
145
|
+
|
146
|
+
expect(html).to include %(<input type="text" name="book[author][avatar][url]" id="book-author-avatar-url" value="#{val}">)
|
147
|
+
end
|
148
|
+
|
149
|
+
it "allows to override 'value' attribute" do
|
150
|
+
html = form_for("/books", values: values) do |f|
|
151
|
+
f.text_field "book.author.avatar.url", value: "https://hanami.test/another-avatar.jpg"
|
152
|
+
end
|
153
|
+
|
154
|
+
expect(html).to include %(<input type="text" name="book[author][avatar][url]" id="book-author-avatar-url" value="https://hanami.test/another-avatar.jpg">)
|
155
|
+
end
|
156
|
+
end
|
157
|
+
|
158
|
+
context "with filled params" do
|
159
|
+
let(:params) { {book: {author: {avatar: {url: val}}}} }
|
160
|
+
let(:val) { "https://hanami.test/avatar.png" }
|
161
|
+
|
162
|
+
it "renders with value" do
|
163
|
+
html = form_for("/books") do |f|
|
164
|
+
f.text_field "book.author.avatar.url"
|
165
|
+
end
|
166
|
+
|
167
|
+
expect(html).to include %(<input type="text" name="book[author][avatar][url]" id="book-author-avatar-url" value="#{val}">)
|
168
|
+
end
|
169
|
+
|
170
|
+
it "allows to override 'value' attribute" do
|
171
|
+
html = form_for("/books") do |f|
|
172
|
+
f.text_field "book.author.avatar.url", value: "https://hanami.test/another-avatar.jpg"
|
173
|
+
end
|
174
|
+
|
175
|
+
expect(html).to include %(<input type="text" name="book[author][avatar][url]" id="book-author-avatar-url" value="https://hanami.test/another-avatar.jpg">)
|
176
|
+
end
|
177
|
+
end
|
178
|
+
end
|
179
|
+
|
180
|
+
context "CSRF protection" do
|
181
|
+
let(:csrf_token) { "abc123" }
|
182
|
+
|
183
|
+
before do
|
184
|
+
allow(request).to receive(:session) { {_csrf_token: csrf_token} }
|
185
|
+
end
|
186
|
+
|
187
|
+
it "injects hidden field session is enabled" do
|
188
|
+
html = form_for("/books")
|
189
|
+
expect(html).to eq %(<form action="/books" accept-charset="utf-8" method="POST"><input type="hidden" name="_csrf_token" value="#{csrf_token}"></form>)
|
190
|
+
end
|
191
|
+
|
192
|
+
context "with missing token" do
|
193
|
+
let(:csrf_token) { nil }
|
194
|
+
|
195
|
+
it "doesn't inject hidden field" do
|
196
|
+
html = form_for("/books")
|
197
|
+
expect(html).to eq %(<form action="/books" accept-charset="utf-8" method="POST"></form>)
|
198
|
+
end
|
199
|
+
end
|
200
|
+
|
201
|
+
context "with csrf_token on get verb" do
|
202
|
+
it "doesn't inject hidden field" do
|
203
|
+
html = form_for("/books", method: "GET")
|
204
|
+
expect(html).to eq %(<form action="/books" method="GET" accept-charset="utf-8"></form>)
|
205
|
+
end
|
206
|
+
end
|
207
|
+
|
208
|
+
%i[patch put delete].each do |verb|
|
209
|
+
it "it injects hidden field when method override (#{verb}) is active" do
|
210
|
+
html = form_for("/books", method: verb)
|
211
|
+
expect(html).to eq %(<form action="/books" method="POST" accept-charset="utf-8"><input type="hidden" name="_method" value="#{verb.to_s.upcase}"><input type="hidden" name="_csrf_token" value="#{csrf_token}"></form>)
|
212
|
+
end
|
213
|
+
end
|
214
|
+
end
|
215
|
+
|
216
|
+
context "CSRF meta tags" do
|
217
|
+
let(:csrf_token) { "abc123" }
|
218
|
+
|
219
|
+
before do
|
220
|
+
allow(request).to receive(:session) { {_csrf_token: csrf_token} }
|
221
|
+
end
|
222
|
+
|
223
|
+
def csrf_meta_tags(...)
|
224
|
+
h { csrf_meta_tags(...) }
|
225
|
+
end
|
226
|
+
|
227
|
+
it "prints meta tags" do
|
228
|
+
html = csrf_meta_tags
|
229
|
+
expect(html).to eq %(<meta name="csrf-param" content="_csrf_token"><meta name="csrf-token" content="#{csrf_token}">)
|
230
|
+
end
|
231
|
+
|
232
|
+
context "when CSRF token is nil" do
|
233
|
+
let(:csrf_token) { nil }
|
234
|
+
|
235
|
+
it "returns nil" do
|
236
|
+
expect(csrf_meta_tags).to be(nil)
|
237
|
+
end
|
238
|
+
end
|
239
|
+
end
|
240
|
+
|
241
|
+
context "remote: true" do
|
242
|
+
it "adds data-remote=true to form attributes" do
|
243
|
+
html = form_for("/books", "data-remote": true)
|
244
|
+
expect(html).to eq %(<form action="/books" data-remote="true" accept-charset="utf-8" method="POST"></form>)
|
245
|
+
end
|
246
|
+
|
247
|
+
it "adds data-remote=false to form attributes" do
|
248
|
+
html = form_for("/books", "data-remote": false)
|
249
|
+
expect(html).to eq %(<form action="/books" data-remote="false" accept-charset="utf-8" method="POST"></form>)
|
250
|
+
end
|
251
|
+
|
252
|
+
it "adds data-remote= to form attributes" do
|
253
|
+
html = form_for("/books", "data-remote": nil)
|
254
|
+
expect(html).to eq %(<form action="/books" accept-charset="utf-8" method="POST"></form>)
|
255
|
+
end
|
256
|
+
end
|
257
|
+
|
258
|
+
context "explicitly given params" do
|
259
|
+
let(:params) { {song: {title: "Orphans"}} }
|
260
|
+
let(:given_params) { {song: {title: "Arabesque"}} }
|
261
|
+
let(:action) { "/songs" }
|
262
|
+
|
263
|
+
it "renders" do
|
264
|
+
html = form_for("/songs", params: given_params) do |f|
|
265
|
+
f.text_field "song.title"
|
266
|
+
end
|
267
|
+
|
268
|
+
expect(html).to eq(%(<form action="/songs" accept-charset="utf-8" method="POST"><input type="text" name="song[title]" id="song-title" value="Arabesque"></form>))
|
269
|
+
end
|
270
|
+
end
|
271
|
+
end
|
272
|
+
|
273
|
+
describe "#fields_for" do
|
274
|
+
it "renders" do
|
275
|
+
html = render(<<~ERB)
|
276
|
+
<%= form_for("/books") do |f| %>
|
277
|
+
<% f.fields_for "book.categories" do |fa| %>
|
278
|
+
<%= fa.text_field :name %>
|
279
|
+
|
280
|
+
<% fa.fields_for :subcategories do |fb| %>
|
281
|
+
<%= fb.text_field :name %>
|
282
|
+
<% end %>
|
283
|
+
|
284
|
+
<%= fa.text_field :name2 %>
|
285
|
+
<% end %>
|
286
|
+
|
287
|
+
<%= f.text_field "book.title" %>
|
288
|
+
<% end %>
|
289
|
+
ERB
|
290
|
+
|
291
|
+
expect(html).to eq_html <<~HTML
|
292
|
+
<form action="/books" accept-charset="utf-8" method="POST">
|
293
|
+
<input type="text" name="book[categories][name]" id="book-categories-name" value="">
|
294
|
+
<input type="text" name="book[categories][subcategories][name]" id="book-categories-subcategories-name" value="">
|
295
|
+
<input type="text" name="book[categories][name2]" id="book-categories-name2" value="">
|
296
|
+
<input type="text" name="book[title]" id="book-title" value="">
|
297
|
+
</form>
|
298
|
+
HTML
|
299
|
+
end
|
300
|
+
|
301
|
+
describe "with filled params" do
|
302
|
+
let(:params) { {book: {title: "TDD", categories: {name: "foo", name2: "bar", subcategories: {name: "sub"}}}} }
|
303
|
+
|
304
|
+
it "renders" do
|
305
|
+
html = render(<<~ERB)
|
306
|
+
<%= form_for("/books") do |f| %>
|
307
|
+
<% f.fields_for "book.categories" do |fa| %>
|
308
|
+
<%= fa.text_field :name %>
|
309
|
+
|
310
|
+
<% fa.fields_for :subcategories do |fb| %>
|
311
|
+
<%= fb.text_field :name %>
|
312
|
+
<% end %>
|
313
|
+
|
314
|
+
<%= fa.text_field :name2 %>
|
315
|
+
<% end %>
|
316
|
+
|
317
|
+
<%= f.text_field "book.title" %>
|
318
|
+
<% end %>
|
319
|
+
ERB
|
320
|
+
|
321
|
+
expect(html).to eq_html <<~HTML
|
322
|
+
<form action="/books" accept-charset="utf-8" method="POST">
|
323
|
+
<input type="text" name="book[categories][name]" id="book-categories-name" value="foo">
|
324
|
+
<input type="text" name="book[categories][subcategories][name]" id="book-categories-subcategories-name" value="sub">
|
325
|
+
<input type="text" name="book[categories][name2]" id="book-categories-name2" value="bar">
|
326
|
+
<input type="text" name="book[title]" id="book-title" value="TDD">
|
327
|
+
</form>
|
328
|
+
HTML
|
329
|
+
end
|
330
|
+
end
|
331
|
+
end
|
332
|
+
|
333
|
+
describe "#fields_for_collection" do
|
334
|
+
let(:params) { {book: {categories: [{name: "foo", new: true, genre: nil}]}} }
|
335
|
+
|
336
|
+
it "renders" do
|
337
|
+
html = render(<<~ERB)
|
338
|
+
<%= form_for("/books") do |f| %>
|
339
|
+
<% f.fields_for_collection "book.categories" do |fa| %>
|
340
|
+
<%= fa.text_field :name %>
|
341
|
+
<%= fa.hidden_field :name %>
|
342
|
+
<%= fa.text_area :name %>
|
343
|
+
<%= fa.check_box :new %>
|
344
|
+
<%= fa.select :genre, [%w[Terror terror], %w[Comedy comedy]] %>
|
345
|
+
<%= fa.color_field :name %>
|
346
|
+
<%= fa.date_field :name %>
|
347
|
+
<%= fa.datetime_field :name %>
|
348
|
+
<%= fa.datetime_local_field :name %>
|
349
|
+
<%= fa.time_field :name %>
|
350
|
+
<%= fa.month_field :name %>
|
351
|
+
<%= fa.week_field :name %>
|
352
|
+
<%= fa.email_field :name %>
|
353
|
+
<%= fa.url_field :name %>
|
354
|
+
<%= fa.tel_field :name %>
|
355
|
+
<%= fa.file_field :name %>
|
356
|
+
<%= fa.number_field :name %>
|
357
|
+
<%= fa.range_field :name %>
|
358
|
+
<%= fa.search_field :name %>
|
359
|
+
<%= fa.radio_button :name, "Fiction" %>
|
360
|
+
<%= fa.password_field :name %>
|
361
|
+
<%= fa.datalist :name, ["Italy", "United States"], "books" %>
|
362
|
+
<% end %>
|
363
|
+
<% end %>
|
364
|
+
ERB
|
365
|
+
|
366
|
+
expected = <<~HTML
|
367
|
+
<form action="/books" enctype="multipart/form-data" accept-charset="utf-8" method="POST">
|
368
|
+
<input type="text" name="book[categories][][name]" id="book-categories-0-name" value="foo">
|
369
|
+
<input type="hidden" name="book[categories][][name]" id="book-categories-0-name" value="foo">
|
370
|
+
<textarea name="book[categories][][name]" id="book-categories-0-name">
|
371
|
+
foo</textarea>
|
372
|
+
<input type="hidden" name="book[categories][][new]" value="0"><input type="checkbox" name="book[categories][][new]" id="book-categories-0-new" value="1" checked="checked">
|
373
|
+
<select name="book[categories][][genre]" id="book-categories-0-genre"><option value="terror">Terror</option><option value="comedy">Comedy</option></select>
|
374
|
+
<input type="color" name="book[categories][][name]" id="book-categories-0-name" value="foo">
|
375
|
+
<input type="date" name="book[categories][][name]" id="book-categories-0-name" value="foo">
|
376
|
+
<input type="datetime" name="book[categories][][name]" id="book-categories-0-name" value="foo">
|
377
|
+
<input type="datetime-local" name="book[categories][][name]" id="book-categories-0-name" value="foo">
|
378
|
+
<input type="time" name="book[categories][][name]" id="book-categories-0-name" value="foo">
|
379
|
+
<input type="month" name="book[categories][][name]" id="book-categories-0-name" value="foo">
|
380
|
+
<input type="week" name="book[categories][][name]" id="book-categories-0-name" value="foo">
|
381
|
+
<input type="email" name="book[categories][][name]" id="book-categories-0-name" value="foo">
|
382
|
+
<input type="url" name="book[categories][][name]" id="book-categories-0-name" value="">
|
383
|
+
<input type="tel" name="book[categories][][name]" id="book-categories-0-name" value="foo">
|
384
|
+
<input type="file" name="book[categories][][name]" id="book-categories-0-name">
|
385
|
+
<input type="number" name="book[categories][][name]" id="book-categories-0-name" value="foo">
|
386
|
+
<input type="range" name="book[categories][][name]" id="book-categories-0-name" value="foo">
|
387
|
+
<input type="search" name="book[categories][][name]" id="book-categories-0-name" value="foo">
|
388
|
+
<input type="radio" name="book[categories][][name]" value="Fiction">
|
389
|
+
<input type="password" name="book[categories][][name]" id="book-categories-0-name" value="">
|
390
|
+
<input type="text" name="book[categories][][name]" id="book-categories-0-name" value="foo" list="books"><datalist id="books"><option value="Italy"></option><option value="United States"></option></datalist>
|
391
|
+
</form>
|
392
|
+
HTML
|
393
|
+
|
394
|
+
expect(html).to eq_html(expected)
|
395
|
+
end
|
396
|
+
end
|
397
|
+
|
398
|
+
describe "#label" do
|
399
|
+
it "renders capitalized string" do
|
400
|
+
html = form_for("/books") do |f|
|
401
|
+
f.label "book.free_shipping"
|
402
|
+
end
|
403
|
+
|
404
|
+
expect(html).to include %(<label for="book-free-shipping">Free shipping</label>)
|
405
|
+
end
|
406
|
+
|
407
|
+
it "accepts a string as custom content" do
|
408
|
+
html = form_for("/books") do |f|
|
409
|
+
f.label "Free Shipping!", for: "book.free_shipping"
|
410
|
+
end
|
411
|
+
|
412
|
+
expect(html).to include %(<label for="book-free-shipping">Free Shipping!</label>)
|
413
|
+
end
|
414
|
+
|
415
|
+
it "renders a label with block" do
|
416
|
+
html = render(<<~ERB)
|
417
|
+
<%= form_for "/books" do |f| %>
|
418
|
+
<%= f.label for: "book.free_shipping" do %>
|
419
|
+
Free Shipping
|
420
|
+
<%= tag.abbr "*", title: "optional", aria: {label: "optional"} %>
|
421
|
+
<% end %>
|
422
|
+
<% end %>
|
423
|
+
ERB
|
424
|
+
|
425
|
+
expect(html).to eq <<~HTML
|
426
|
+
<form action="/books" accept-charset="utf-8" method="POST">
|
427
|
+
<label for="book-free-shipping">
|
428
|
+
Free Shipping
|
429
|
+
<abbr title="optional" aria-label="optional">*</abbr>
|
430
|
+
</label>
|
431
|
+
</form>
|
432
|
+
HTML
|
433
|
+
end
|
434
|
+
end
|
435
|
+
|
436
|
+
describe "#button" do
|
437
|
+
it "renders a button" do
|
438
|
+
html = form_for("/books") do |f|
|
439
|
+
f.button "Click me"
|
440
|
+
end
|
441
|
+
|
442
|
+
expect(html).to include %(<button>Click me</button>)
|
443
|
+
end
|
444
|
+
|
445
|
+
it "renders a button with HTML attributes" do
|
446
|
+
html = form_for("/books") do |f|
|
447
|
+
f.button "Click me", class: "btn btn-secondary"
|
448
|
+
end
|
449
|
+
|
450
|
+
expect(html).to include(%(<button class="btn btn-secondary">Click me</button>))
|
451
|
+
end
|
452
|
+
|
453
|
+
it "renders a button with block" do
|
454
|
+
html = render(<<~ERB)
|
455
|
+
<%= form_for("/books") do |f| %>
|
456
|
+
<%= f.button class: "btn btn-secondary" do %>
|
457
|
+
<%= tag.span class: "oi oi-check" %>
|
458
|
+
<% end %>
|
459
|
+
<% end %>
|
460
|
+
ERB
|
461
|
+
|
462
|
+
expect(html).to eq <<~HTML
|
463
|
+
<form action="/books" accept-charset="utf-8" method="POST">
|
464
|
+
<button class="btn btn-secondary">
|
465
|
+
<span class="oi oi-check"></span>
|
466
|
+
</button>
|
467
|
+
</form>
|
468
|
+
HTML
|
469
|
+
end
|
470
|
+
end
|
471
|
+
|
472
|
+
describe "#submit" do
|
473
|
+
it "renders a submit button" do
|
474
|
+
html = form_for("/books") do |f|
|
475
|
+
f.submit "Create"
|
476
|
+
end
|
477
|
+
|
478
|
+
expect(html).to include %(<button type="submit">Create</button>)
|
479
|
+
end
|
480
|
+
|
481
|
+
it "renders a submit button with HTML attributes" do
|
482
|
+
html = form_for("/books") do |f|
|
483
|
+
f.submit "Create", class: "btn btn-primary"
|
484
|
+
end
|
485
|
+
|
486
|
+
expect(html).to include %(<button type="submit" class="btn btn-primary">Create</button>)
|
487
|
+
end
|
488
|
+
|
489
|
+
it "renders a submit button with block" do
|
490
|
+
html = render(<<~ERB)
|
491
|
+
<%= form_for "/books" do |f| %>
|
492
|
+
<%= f.submit class: "btn btn-primary" do %>
|
493
|
+
<%= tag.span class: "oi oi-check" %>
|
494
|
+
<% end %>
|
495
|
+
<% end %>
|
496
|
+
ERB
|
497
|
+
|
498
|
+
expect(html).to eq <<~HTML
|
499
|
+
<form action="/books" accept-charset="utf-8" method="POST">
|
500
|
+
<button type="submit" class="btn btn-primary">
|
501
|
+
<span class="oi oi-check"></span>
|
502
|
+
</button>
|
503
|
+
</form>
|
504
|
+
HTML
|
505
|
+
end
|
506
|
+
end
|
507
|
+
|
508
|
+
describe "#image_button" do
|
509
|
+
it "renders an image button" do
|
510
|
+
html = form_for("/books") do |f|
|
511
|
+
f.image_button "https://hanamirb.org/assets/image_button.png"
|
512
|
+
end
|
513
|
+
|
514
|
+
expect(html).to include %(<input type="image" src="https://hanamirb.org/assets/image_button.png">)
|
515
|
+
end
|
516
|
+
|
517
|
+
it "renders an image button with HTML attributes" do
|
518
|
+
html = form_for("/books") do |f|
|
519
|
+
f.image_button "https://hanamirb.org/assets/image_button.png", name: "image", width: "50"
|
520
|
+
end
|
521
|
+
|
522
|
+
expect(html).to include %(<input name="image" width="50" type="image" src="https://hanamirb.org/assets/image_button.png">)
|
523
|
+
end
|
524
|
+
|
525
|
+
it "prevents XSS attacks" do
|
526
|
+
html = form_for("/books") do |f|
|
527
|
+
f.image_button "<script>alert('xss');</script>"
|
528
|
+
end
|
529
|
+
|
530
|
+
expect(html).to include %(<input type="image" src="">)
|
531
|
+
end
|
532
|
+
end
|
533
|
+
|
534
|
+
#
|
535
|
+
# FIELDSET
|
536
|
+
#
|
537
|
+
|
538
|
+
describe "#fieldset" do
|
539
|
+
it "renders a fieldset" do
|
540
|
+
html = render(<<~ERB)
|
541
|
+
<%= form_for "/books" do |f| %>
|
542
|
+
<%= f.fieldset do %>
|
543
|
+
<%= tag.legend "Author" %>
|
544
|
+
<%= f.label "author.name" %>
|
545
|
+
<%= f.text_field "author.name" %>
|
546
|
+
<% end %>
|
547
|
+
<% end %>
|
548
|
+
ERB
|
549
|
+
|
550
|
+
expect(html).to include_html <<~HTML
|
551
|
+
<fieldset>
|
552
|
+
<legend>Author</legend>
|
553
|
+
<label for="author-name">Name</label>
|
554
|
+
<input type="text" name="author[name]" id="author-name" value="">
|
555
|
+
</fieldset>
|
556
|
+
HTML
|
557
|
+
end
|
558
|
+
end
|
559
|
+
|
560
|
+
#
|
561
|
+
# INPUT FIELDS
|
562
|
+
#
|
563
|
+
|
564
|
+
describe "#check_box" do
|
565
|
+
it "renders" do
|
566
|
+
html = form_for("/books") do |f|
|
567
|
+
f.check_box "book.free_shipping"
|
568
|
+
end
|
569
|
+
|
570
|
+
expect(html).to include %(<input type="hidden" name="book[free_shipping]" value="0"><input type="checkbox" name="book[free_shipping]" id="book-free-shipping" value="1">)
|
571
|
+
end
|
572
|
+
|
573
|
+
it "allows to pass checked and unchecked value" do
|
574
|
+
html = form_for("/books") do |f|
|
575
|
+
f.check_box "book.free_shipping", checked_value: "true", unchecked_value: "false"
|
576
|
+
end
|
577
|
+
|
578
|
+
expect(html).to include %(<input type="hidden" name="book[free_shipping]" value="false"><input type="checkbox" name="book[free_shipping]" id="book-free-shipping" value="true">)
|
579
|
+
end
|
580
|
+
|
581
|
+
it "allows to override 'id' attribute" do
|
582
|
+
html = form_for("/books") do |f|
|
583
|
+
f.check_box "book.free_shipping", id: "shipping"
|
584
|
+
end
|
585
|
+
|
586
|
+
expect(html).to include %(<input type="hidden" name="book[free_shipping]" value="0"><input type="checkbox" name="book[free_shipping]" id="shipping" value="1">)
|
587
|
+
end
|
588
|
+
|
589
|
+
it "allows to override 'name' attribute" do
|
590
|
+
html = form_for("/books") do |f|
|
591
|
+
f.check_box "book.free_shipping", name: "book[free]"
|
592
|
+
end
|
593
|
+
|
594
|
+
expect(html).to include %(<input type="hidden" name="book[free]" value="0"><input type="checkbox" name="book[free]" id="book-free-shipping" value="1">)
|
595
|
+
end
|
596
|
+
|
597
|
+
it "allows to specify HTML attributes" do
|
598
|
+
html = form_for("/books") do |f|
|
599
|
+
f.check_box "book.free_shipping", class: "form-control"
|
600
|
+
end
|
601
|
+
|
602
|
+
expect(html).to include %(<input type="hidden" name="book[free_shipping]" value="0"><input type="checkbox" name="book[free_shipping]" id="book-free-shipping" value="1" class="form-control">)
|
603
|
+
end
|
604
|
+
|
605
|
+
it "doesn't render hidden field if 'value' attribute is specified" do
|
606
|
+
html = form_for("/books") do |f|
|
607
|
+
f.check_box "book.free_shipping", value: "ok"
|
608
|
+
end
|
609
|
+
|
610
|
+
expect(html).not_to include %(<input type="hidden" name="book[free_shipping]" value="0">)
|
611
|
+
expect(html).to include %(<input type="checkbox" name="book[free_shipping]" id="book-free-shipping" value="ok">)
|
612
|
+
end
|
613
|
+
|
614
|
+
it "renders hidden field if 'value' attribute and 'unchecked_value' option are both specified" do
|
615
|
+
html = form_for("/books") do |f|
|
616
|
+
f.check_box "book.free_shipping", value: "yes", unchecked_value: "no"
|
617
|
+
end
|
618
|
+
|
619
|
+
expect(html).to include %(<input type="hidden" name="book[free_shipping]" value="no"><input type="checkbox" name="book[free_shipping]" id="book-free-shipping" value="yes">)
|
620
|
+
end
|
621
|
+
|
622
|
+
it "handles multiple checkboxes" do
|
623
|
+
html = render(<<~ERB)
|
624
|
+
<%= form_for("/books") do |f| %>
|
625
|
+
<%= f.check_box "book.languages", name: "book[languages][]", value: "italian", id: nil %>
|
626
|
+
<%= f.check_box "book.languages", name: "book[languages][]", value: "english", id: nil %>
|
627
|
+
<% end %>
|
628
|
+
ERB
|
629
|
+
|
630
|
+
expect(html).to include_html <<~HTML
|
631
|
+
<input type="checkbox" name="book[languages][]" value="italian">
|
632
|
+
<input type="checkbox" name="book[languages][]" value="english">
|
633
|
+
HTML
|
634
|
+
end
|
635
|
+
|
636
|
+
context "with filled params" do
|
637
|
+
let(:params) { {book: {free_shipping: val}} }
|
638
|
+
|
639
|
+
context "when the params value equals to check box value" do
|
640
|
+
let(:val) { "1" }
|
641
|
+
|
642
|
+
it "renders with 'checked' attribute" do
|
643
|
+
html = form_for("/books") do |f|
|
644
|
+
f.check_box "book.free_shipping"
|
645
|
+
end
|
646
|
+
|
647
|
+
expect(html).to include %(<input type="hidden" name="book[free_shipping]" value="0"><input type="checkbox" name="book[free_shipping]" id="book-free-shipping" value="1" checked="checked">)
|
648
|
+
end
|
649
|
+
end
|
650
|
+
|
651
|
+
context "when the params value equals to the hidden field value" do
|
652
|
+
let(:val) { "0" }
|
653
|
+
|
654
|
+
it "renders without 'checked' attribute" do
|
655
|
+
html = form_for("/books") do |f|
|
656
|
+
f.check_box "book.free_shipping"
|
657
|
+
end
|
658
|
+
|
659
|
+
expect(html).to include %(<input type="hidden" name="book[free_shipping]" value="0"><input type="checkbox" name="book[free_shipping]" id="book-free-shipping" value="1">)
|
660
|
+
end
|
661
|
+
|
662
|
+
it "allows to override 'checked' attribute" do
|
663
|
+
html = form_for("/books") do |f|
|
664
|
+
f.check_box "book.free_shipping", checked: "checked"
|
665
|
+
end
|
666
|
+
|
667
|
+
expect(html).to include %(<input type="hidden" name="book[free_shipping]" value="0"><input type="checkbox" name="book[free_shipping]" id="book-free-shipping" value="1" checked="checked">)
|
668
|
+
end
|
669
|
+
end
|
670
|
+
|
671
|
+
context "with a boolean argument" do
|
672
|
+
let(:val) { true }
|
673
|
+
|
674
|
+
it "renders with 'checked' attribute" do
|
675
|
+
html = form_for("/books") do |f|
|
676
|
+
f.check_box "book.free_shipping"
|
677
|
+
end
|
678
|
+
|
679
|
+
expect(html).to include %(<input type="hidden" name="book[free_shipping]" value="0"><input type="checkbox" name="book[free_shipping]" id="book-free-shipping" value="1" checked="checked">)
|
680
|
+
end
|
681
|
+
end
|
682
|
+
|
683
|
+
context "when multiple params are present" do
|
684
|
+
let(:params) { {book: {languages: ["italian"]}} }
|
685
|
+
|
686
|
+
it "handles multiple checkboxes" do
|
687
|
+
html = render(<<~ERB)
|
688
|
+
<%= form_for("/books") do |f| %>
|
689
|
+
<%= f.check_box "book.languages", name: "book[languages][]", value: "italian", id: nil %>
|
690
|
+
<%= f.check_box "book.languages", name: "book[languages][]", value: "english", id: nil %>
|
691
|
+
<% end %>
|
692
|
+
ERB
|
693
|
+
|
694
|
+
expect(html).to include_html <<~HTML
|
695
|
+
<input type="checkbox" name="book[languages][]" value="italian" checked="checked">
|
696
|
+
<input type="checkbox" name="book[languages][]" value="english">
|
697
|
+
HTML
|
698
|
+
end
|
699
|
+
end
|
700
|
+
|
701
|
+
context "checked_value is boolean" do
|
702
|
+
let(:params) { {book: {free_shipping: "true"}} }
|
703
|
+
|
704
|
+
it "renders with 'checked' attribute" do
|
705
|
+
html = form_for("/books") do |f|
|
706
|
+
f.check_box "book.free_shipping", checked_value: true
|
707
|
+
end
|
708
|
+
|
709
|
+
expect(html).to include %(<input type="checkbox" name="book[free_shipping]" id="book-free-shipping" value="true" checked="checked">)
|
710
|
+
end
|
711
|
+
end
|
712
|
+
end
|
713
|
+
|
714
|
+
context "automatic values" do
|
715
|
+
context "checkbox" do
|
716
|
+
context "value boolean, helper boolean, values differ" do
|
717
|
+
let(:values) { {book: Struct.new(:free_shipping).new(false)} }
|
718
|
+
|
719
|
+
it "renders" do
|
720
|
+
html = form_for("/books", values: values) do |f|
|
721
|
+
f.check_box "book.free_shipping", checked_value: true
|
722
|
+
end
|
723
|
+
|
724
|
+
expect(html).to include %(<input type="checkbox" name="book[free_shipping]" id="book-free-shipping" value="true">)
|
725
|
+
end
|
726
|
+
end
|
727
|
+
end
|
728
|
+
end
|
729
|
+
end
|
730
|
+
|
731
|
+
describe "#color_field" do
|
732
|
+
it "renders" do
|
733
|
+
html = form_for("/books") do |f|
|
734
|
+
f.color_field "book.cover"
|
735
|
+
end
|
736
|
+
|
737
|
+
expect(html).to include %(<input type="color" name="book[cover]" id="book-cover" value="">)
|
738
|
+
end
|
739
|
+
|
740
|
+
it "allows to override 'id' attribute" do
|
741
|
+
html = form_for("/books") do |f|
|
742
|
+
f.color_field "book.cover", id: "b-cover"
|
743
|
+
end
|
744
|
+
|
745
|
+
expect(html).to include %(<input type="color" name="book[cover]" id="b-cover" value="">)
|
746
|
+
end
|
747
|
+
|
748
|
+
it "allows to override 'name' attribute" do
|
749
|
+
html = form_for("/books") do |f|
|
750
|
+
f.color_field "book.cover", name: "cover"
|
751
|
+
end
|
752
|
+
|
753
|
+
expect(html).to include %(<input type="color" name="cover" id="book-cover" value="">)
|
754
|
+
end
|
755
|
+
|
756
|
+
it "allows to override 'value' attribute" do
|
757
|
+
html = form_for("/books") do |f|
|
758
|
+
f.color_field "book.cover", value: "#ffffff"
|
759
|
+
end
|
760
|
+
|
761
|
+
expect(html).to include %(<input type="color" name="book[cover]" id="book-cover" value="#ffffff">)
|
762
|
+
end
|
763
|
+
|
764
|
+
it "allows to specify HTML attributes" do
|
765
|
+
html = form_for("/books") do |f|
|
766
|
+
f.color_field "book.cover", class: "form-control"
|
767
|
+
end
|
768
|
+
|
769
|
+
expect(html).to include %(<input type="color" name="book[cover]" id="book-cover" value="" class="form-control">)
|
770
|
+
end
|
771
|
+
|
772
|
+
context "with values" do
|
773
|
+
let(:values) { {book: Struct.new(:cover).new(val)} }
|
774
|
+
let(:val) { "#d3397e" }
|
775
|
+
|
776
|
+
it "renders with value" do
|
777
|
+
html = form_for("/books", values: values) do |f|
|
778
|
+
f.color_field "book.cover"
|
779
|
+
end
|
780
|
+
|
781
|
+
expect(html).to include %(<input type="color" name="book[cover]" id="book-cover" value="#{val}">)
|
782
|
+
end
|
783
|
+
|
784
|
+
it "allows to override 'value' attribute" do
|
785
|
+
html = form_for("/books", values: values) do |f|
|
786
|
+
f.color_field "book.cover", value: "#000000"
|
787
|
+
end
|
788
|
+
|
789
|
+
expect(html).to include %(<input type="color" name="book[cover]" id="book-cover" value="#000000">)
|
790
|
+
end
|
791
|
+
end
|
792
|
+
|
793
|
+
context "with filled params" do
|
794
|
+
let(:params) { {book: {cover: val}} }
|
795
|
+
let(:val) { "#d3397e" }
|
796
|
+
|
797
|
+
it "renders with value" do
|
798
|
+
html = form_for("/books") do |f|
|
799
|
+
f.color_field "book.cover"
|
800
|
+
end
|
801
|
+
|
802
|
+
expect(html).to include %(<input type="color" name="book[cover]" id="book-cover" value="#{val}">)
|
803
|
+
end
|
804
|
+
|
805
|
+
it "allows to override 'value' attribute" do
|
806
|
+
html = form_for("/books") do |f|
|
807
|
+
f.color_field "book.cover", value: "#000000"
|
808
|
+
end
|
809
|
+
|
810
|
+
expect(html).to include %(<input type="color" name="book[cover]" id="book-cover" value="#000000">)
|
811
|
+
end
|
812
|
+
end
|
813
|
+
end
|
814
|
+
|
815
|
+
describe "#date_field" do
|
816
|
+
it "renders" do
|
817
|
+
html = form_for("/books") do |f|
|
818
|
+
f.date_field "book.release_date"
|
819
|
+
end
|
820
|
+
|
821
|
+
expect(html).to include %(<input type="date" name="book[release_date]" id="book-release-date" value="">)
|
822
|
+
end
|
823
|
+
|
824
|
+
it "allows to override 'id' attribute" do
|
825
|
+
html = form_for("/books") do |f|
|
826
|
+
f.date_field "book.release_date", id: "release-date"
|
827
|
+
end
|
828
|
+
|
829
|
+
expect(html).to include %(<input type="date" name="book[release_date]" id="release-date" value="">)
|
830
|
+
end
|
831
|
+
|
832
|
+
it "allows to override 'name' attribute" do
|
833
|
+
html = form_for("/books") do |f|
|
834
|
+
f.date_field "book.release_date", name: "release_date"
|
835
|
+
end
|
836
|
+
|
837
|
+
expect(html).to include %(<input type="date" name="release_date" id="book-release-date" value="">)
|
838
|
+
end
|
839
|
+
|
840
|
+
it "allows to override 'value' attribute" do
|
841
|
+
html = form_for("/books") do |f|
|
842
|
+
f.date_field "book.release_date", value: "2015-02-19"
|
843
|
+
end
|
844
|
+
|
845
|
+
expect(html).to include %(<input type="date" name="book[release_date]" id="book-release-date" value="2015-02-19">)
|
846
|
+
end
|
847
|
+
|
848
|
+
it "allows to specify HTML attributes" do
|
849
|
+
html = form_for("/books") do |f|
|
850
|
+
f.date_field "book.release_date", class: "form-control"
|
851
|
+
end
|
852
|
+
|
853
|
+
expect(html).to include %(<input type="date" name="book[release_date]" id="book-release-date" value="" class="form-control">)
|
854
|
+
end
|
855
|
+
|
856
|
+
context "with values" do
|
857
|
+
let(:values) { {book: Struct.new(:release_date).new(val)} }
|
858
|
+
let(:val) { "2014-06-23" }
|
859
|
+
|
860
|
+
it "renders with value" do
|
861
|
+
html = form_for("/books", values: values) do |f|
|
862
|
+
f.date_field "book.release_date"
|
863
|
+
end
|
864
|
+
|
865
|
+
expect(html).to include %(<input type="date" name="book[release_date]" id="book-release-date" value="#{val}">)
|
866
|
+
end
|
867
|
+
|
868
|
+
it "allows to override 'value' attribute" do
|
869
|
+
html = form_for("/books", values: values) do |f|
|
870
|
+
f.date_field "book.release_date", value: "2015-03-23"
|
871
|
+
end
|
872
|
+
|
873
|
+
expect(html).to include %(<input type="date" name="book[release_date]" id="book-release-date" value="2015-03-23">)
|
874
|
+
end
|
875
|
+
end
|
876
|
+
|
877
|
+
context "with filled params" do
|
878
|
+
let(:params) { {book: {release_date: val}} }
|
879
|
+
let(:val) { "2014-06-23" }
|
880
|
+
|
881
|
+
it "renders with value" do
|
882
|
+
html = form_for("/books") do |f|
|
883
|
+
f.date_field "book.release_date"
|
884
|
+
end
|
885
|
+
|
886
|
+
expect(html).to include %(<input type="date" name="book[release_date]" id="book-release-date" value="#{val}">)
|
887
|
+
end
|
888
|
+
|
889
|
+
it "allows to override 'value' attribute" do
|
890
|
+
html = form_for("/books") do |f|
|
891
|
+
f.date_field "book.release_date", value: "2015-03-23"
|
892
|
+
end
|
893
|
+
|
894
|
+
expect(html).to include %(<input type="date" name="book[release_date]" id="book-release-date" value="2015-03-23">)
|
895
|
+
end
|
896
|
+
end
|
897
|
+
end
|
898
|
+
|
899
|
+
describe "#datetime_field" do
|
900
|
+
it "renders" do
|
901
|
+
html = form_for("/books") do |f|
|
902
|
+
f.datetime_field "book.published_at"
|
903
|
+
end
|
904
|
+
|
905
|
+
expect(html).to include %(<input type="datetime" name="book[published_at]" id="book-published-at" value="">)
|
906
|
+
end
|
907
|
+
|
908
|
+
it "allows to override 'id' attribute" do
|
909
|
+
html = form_for("/books") do |f|
|
910
|
+
f.datetime_field "book.published_at", id: "published-timestamp"
|
911
|
+
end
|
912
|
+
|
913
|
+
expect(html).to include %(<input type="datetime" name="book[published_at]" id="published-timestamp" value="">)
|
914
|
+
end
|
915
|
+
|
916
|
+
it "allows to override 'name' attribute" do
|
917
|
+
html = form_for("/books") do |f|
|
918
|
+
f.datetime_field "book.published_at", name: "book[published][timestamp]"
|
919
|
+
end
|
920
|
+
|
921
|
+
expect(html).to include %(<input type="datetime" name="book[published][timestamp]" id="book-published-at" value="">)
|
922
|
+
end
|
923
|
+
|
924
|
+
it "allows to override 'value' attribute" do
|
925
|
+
html = form_for("/books") do |f|
|
926
|
+
f.datetime_field "book.published_at", value: "2015-02-19T12:50:36Z"
|
927
|
+
end
|
928
|
+
|
929
|
+
expect(html).to include %(<input type="datetime" name="book[published_at]" id="book-published-at" value="2015-02-19T12:50:36Z">)
|
930
|
+
end
|
931
|
+
|
932
|
+
it "allows to specify HTML attributes" do
|
933
|
+
html = form_for("/books") do |f|
|
934
|
+
f.datetime_field "book.published_at", class: "form-control"
|
935
|
+
end
|
936
|
+
|
937
|
+
expect(html).to include %(<input type="datetime" name="book[published_at]" id="book-published-at" value="" class="form-control">)
|
938
|
+
end
|
939
|
+
|
940
|
+
context "with values" do
|
941
|
+
let(:values) { {book: Struct.new(:published_at).new(val)} }
|
942
|
+
let(:val) { "2015-02-19T12:56:31Z" }
|
943
|
+
|
944
|
+
it "renders with value" do
|
945
|
+
html = form_for("/books", values: values) do |f|
|
946
|
+
f.datetime_field "book.published_at"
|
947
|
+
end
|
948
|
+
|
949
|
+
expect(html).to include %(<input type="datetime" name="book[published_at]" id="book-published-at" value="#{val}">)
|
950
|
+
end
|
951
|
+
|
952
|
+
it "allows to override 'value' attribute" do
|
953
|
+
html = form_for("/books", values: values) do |f|
|
954
|
+
f.datetime_field "book.published_at", value: "2015-02-19T12:50:36Z"
|
955
|
+
end
|
956
|
+
|
957
|
+
expect(html).to include %(<input type="datetime" name="book[published_at]" id="book-published-at" value="2015-02-19T12:50:36Z">)
|
958
|
+
end
|
959
|
+
end
|
960
|
+
|
961
|
+
context "with filled params" do
|
962
|
+
let(:params) { {book: {published_at: val}} }
|
963
|
+
let(:val) { "2015-02-19T12:56:31Z" }
|
964
|
+
|
965
|
+
it "renders with value" do
|
966
|
+
html = form_for("/books") do |f|
|
967
|
+
f.datetime_field "book.published_at"
|
968
|
+
end
|
969
|
+
|
970
|
+
expect(html).to include %(<input type="datetime" name="book[published_at]" id="book-published-at" value="#{val}">)
|
971
|
+
end
|
972
|
+
|
973
|
+
it "allows to override 'value' attribute" do
|
974
|
+
html = form_for("/books") do |f|
|
975
|
+
f.datetime_field "book.published_at", value: "2015-02-19T12:50:36Z"
|
976
|
+
end
|
977
|
+
|
978
|
+
expect(html).to include %(<input type="datetime" name="book[published_at]" id="book-published-at" value="2015-02-19T12:50:36Z">)
|
979
|
+
end
|
980
|
+
end
|
981
|
+
end
|
982
|
+
|
983
|
+
describe "#datetime_local_field" do
|
984
|
+
it "renders" do
|
985
|
+
html = form_for("/books") do |f|
|
986
|
+
f.datetime_local_field "book.released_at"
|
987
|
+
end
|
988
|
+
|
989
|
+
expect(html).to include %(<input type="datetime-local" name="book[released_at]" id="book-released-at" value="">)
|
990
|
+
end
|
991
|
+
|
992
|
+
it "allows to override 'id' attribute" do
|
993
|
+
html = form_for("/books") do |f|
|
994
|
+
f.datetime_local_field "book.released_at", id: "local-release-timestamp"
|
995
|
+
end
|
996
|
+
|
997
|
+
expect(html).to include %(<input type="datetime-local" name="book[released_at]" id="local-release-timestamp" value="">)
|
998
|
+
end
|
999
|
+
|
1000
|
+
it "allows to override 'name' attribute" do
|
1001
|
+
html = form_for("/books") do |f|
|
1002
|
+
f.datetime_local_field "book.released_at", name: "book[release-timestamp]"
|
1003
|
+
end
|
1004
|
+
|
1005
|
+
expect(html).to include %(<input type="datetime-local" name="book[release-timestamp]" id="book-released-at" value="">)
|
1006
|
+
end
|
1007
|
+
|
1008
|
+
it "allows to override 'value' attribute" do
|
1009
|
+
html = form_for("/books") do |f|
|
1010
|
+
f.datetime_local_field "book.released_at", value: "2015-02-19T14:01:28+01:00"
|
1011
|
+
end
|
1012
|
+
|
1013
|
+
expect(html).to include %(<input type="datetime-local" name="book[released_at]" id="book-released-at" value="2015-02-19T14:01:28+01:00">)
|
1014
|
+
end
|
1015
|
+
|
1016
|
+
it "allows to specify HTML attributes" do
|
1017
|
+
html = form_for("/books") do |f|
|
1018
|
+
f.datetime_local_field "book.released_at", class: "form-control"
|
1019
|
+
end
|
1020
|
+
|
1021
|
+
expect(html).to include %(<input type="datetime-local" name="book[released_at]" id="book-released-at" value="" class="form-control">)
|
1022
|
+
end
|
1023
|
+
|
1024
|
+
context "with filled params" do
|
1025
|
+
let(:params) { {book: {released_at: val}} }
|
1026
|
+
let(:val) { "2015-02-19T14:11:19+01:00" }
|
1027
|
+
|
1028
|
+
it "renders with value" do
|
1029
|
+
html = form_for("/books") do |f|
|
1030
|
+
f.datetime_local_field "book.released_at"
|
1031
|
+
end
|
1032
|
+
|
1033
|
+
expect(html).to include %(<input type="datetime-local" name="book[released_at]" id="book-released-at" value="#{val}">)
|
1034
|
+
end
|
1035
|
+
|
1036
|
+
it "allows to override 'value' attribute" do
|
1037
|
+
html = form_for("/books") do |f|
|
1038
|
+
f.datetime_local_field "book.released_at", value: "2015-02-19T14:01:28+01:00"
|
1039
|
+
end
|
1040
|
+
|
1041
|
+
expect(html).to include %(<input type="datetime-local" name="book[released_at]" id="book-released-at" value="2015-02-19T14:01:28+01:00">)
|
1042
|
+
end
|
1043
|
+
end
|
1044
|
+
end
|
1045
|
+
|
1046
|
+
describe "#time_field" do
|
1047
|
+
it "renders" do
|
1048
|
+
html = form_for("/books") do |f|
|
1049
|
+
f.time_field "book.release_hour"
|
1050
|
+
end
|
1051
|
+
|
1052
|
+
expect(html).to include %(<input type="time" name="book[release_hour]" id="book-release-hour" value="">)
|
1053
|
+
end
|
1054
|
+
|
1055
|
+
it "allows to override 'id' attribute" do
|
1056
|
+
html = form_for("/books") do |f|
|
1057
|
+
f.time_field "book.release_hour", id: "release-hour"
|
1058
|
+
end
|
1059
|
+
|
1060
|
+
expect(html).to include %(<input type="time" name="book[release_hour]" id="release-hour" value="">)
|
1061
|
+
end
|
1062
|
+
|
1063
|
+
it "allows to override 'name' attribute" do
|
1064
|
+
html = form_for("/books") do |f|
|
1065
|
+
f.time_field "book.release_hour", name: "release_hour"
|
1066
|
+
end
|
1067
|
+
|
1068
|
+
expect(html).to include %(<input type="time" name="release_hour" id="book-release-hour" value="">)
|
1069
|
+
end
|
1070
|
+
|
1071
|
+
it "allows to override 'value' attribute" do
|
1072
|
+
html = form_for("/books") do |f|
|
1073
|
+
f.time_field "book.release_hour", value: "00:00"
|
1074
|
+
end
|
1075
|
+
|
1076
|
+
expect(html).to include %(<input type="time" name="book[release_hour]" id="book-release-hour" value="00:00">)
|
1077
|
+
end
|
1078
|
+
|
1079
|
+
it "allows to specify HTML attributes" do
|
1080
|
+
html = form_for("/books") do |f|
|
1081
|
+
f.time_field "book.release_hour", class: "form-control"
|
1082
|
+
end
|
1083
|
+
|
1084
|
+
expect(html).to include %(<input type="time" name="book[release_hour]" id="book-release-hour" value="" class="form-control">)
|
1085
|
+
end
|
1086
|
+
|
1087
|
+
context "with values" do
|
1088
|
+
let(:values) { {book: Struct.new(:release_hour).new(val)} }
|
1089
|
+
let(:val) { "18:30" }
|
1090
|
+
|
1091
|
+
it "renders with value" do
|
1092
|
+
html = form_for("/books", values: values) do |f|
|
1093
|
+
f.time_field "book.release_hour"
|
1094
|
+
end
|
1095
|
+
|
1096
|
+
expect(html).to include %(<input type="time" name="book[release_hour]" id="book-release-hour" value="#{val}">)
|
1097
|
+
end
|
1098
|
+
|
1099
|
+
it "allows to override 'value' attribute" do
|
1100
|
+
html = form_for("/books", values: values) do |f|
|
1101
|
+
f.time_field "book.release_hour", value: "17:00"
|
1102
|
+
end
|
1103
|
+
|
1104
|
+
expect(html).to include %(<input type="time" name="book[release_hour]" id="book-release-hour" value="17:00">)
|
1105
|
+
end
|
1106
|
+
end
|
1107
|
+
|
1108
|
+
context "with filled params" do
|
1109
|
+
let(:params) { {book: {release_hour: val}} }
|
1110
|
+
let(:val) { "11:30" }
|
1111
|
+
|
1112
|
+
it "renders with value" do
|
1113
|
+
html = form_for("/books") do |f|
|
1114
|
+
f.time_field "book.release_hour"
|
1115
|
+
end
|
1116
|
+
|
1117
|
+
expect(html).to include %(<input type="time" name="book[release_hour]" id="book-release-hour" value="#{val}">)
|
1118
|
+
end
|
1119
|
+
|
1120
|
+
it "allows to override 'value' attribute" do
|
1121
|
+
html = form_for("/books") do |f|
|
1122
|
+
f.time_field "book.release_hour", value: "8:15"
|
1123
|
+
end
|
1124
|
+
|
1125
|
+
expect(html).to include %(<input type="time" name="book[release_hour]" id="book-release-hour" value="8:15">)
|
1126
|
+
end
|
1127
|
+
end
|
1128
|
+
end
|
1129
|
+
|
1130
|
+
describe "#month_field" do
|
1131
|
+
it "renders" do
|
1132
|
+
html = form_for("/books") do |f|
|
1133
|
+
f.month_field "book.release_month"
|
1134
|
+
end
|
1135
|
+
|
1136
|
+
expect(html).to include %(<input type="month" name="book[release_month]" id="book-release-month" value="">)
|
1137
|
+
end
|
1138
|
+
|
1139
|
+
it "allows to override 'id' attribute" do
|
1140
|
+
html = form_for("/books") do |f|
|
1141
|
+
f.month_field "book.release_month", id: "release-month"
|
1142
|
+
end
|
1143
|
+
|
1144
|
+
expect(html).to include %(<input type="month" name="book[release_month]" id="release-month" value="">)
|
1145
|
+
end
|
1146
|
+
|
1147
|
+
it "allows to override 'name' attribute" do
|
1148
|
+
html = form_for("/books") do |f|
|
1149
|
+
f.month_field "book.release_month", name: "release_month"
|
1150
|
+
end
|
1151
|
+
|
1152
|
+
expect(html).to include %(<input type="month" name="release_month" id="book-release-month" value="">)
|
1153
|
+
end
|
1154
|
+
|
1155
|
+
it "allows to override 'value' attribute" do
|
1156
|
+
html = form_for("/books") do |f|
|
1157
|
+
f.month_field "book.release_month", value: "2017-03"
|
1158
|
+
end
|
1159
|
+
|
1160
|
+
expect(html).to include %(<input type="month" name="book[release_month]" id="book-release-month" value="2017-03">)
|
1161
|
+
end
|
1162
|
+
|
1163
|
+
it "allows to specify HTML attributes" do
|
1164
|
+
html = form_for("/books") do |f|
|
1165
|
+
f.month_field "book.release_month", class: "form-control"
|
1166
|
+
end
|
1167
|
+
|
1168
|
+
expect(html).to include %(<input type="month" name="book[release_month]" id="book-release-month" value="" class="form-control">)
|
1169
|
+
end
|
1170
|
+
|
1171
|
+
context "with values" do
|
1172
|
+
let(:values) { {book: Struct.new(:release_month).new(val)} }
|
1173
|
+
let(:val) { "2017-03" }
|
1174
|
+
|
1175
|
+
it "renders with value" do
|
1176
|
+
html = form_for("/books", values: values) do |f|
|
1177
|
+
f.month_field "book.release_month"
|
1178
|
+
end
|
1179
|
+
|
1180
|
+
expect(html).to include %(<input type="month" name="book[release_month]" id="book-release-month" value="#{val}">)
|
1181
|
+
end
|
1182
|
+
|
1183
|
+
it "allows to override 'value' attribute" do
|
1184
|
+
html = form_for("/books", values: values) do |f|
|
1185
|
+
f.month_field "book.release_month", value: "2017-04"
|
1186
|
+
end
|
1187
|
+
|
1188
|
+
expect(html).to include %(<input type="month" name="book[release_month]" id="book-release-month" value="2017-04">)
|
1189
|
+
end
|
1190
|
+
end
|
1191
|
+
|
1192
|
+
context "with filled params" do
|
1193
|
+
let(:params) { {book: {release_month: val}} }
|
1194
|
+
let(:val) { "2017-10" }
|
1195
|
+
|
1196
|
+
it "renders with value" do
|
1197
|
+
html = form_for("/books") do |f|
|
1198
|
+
f.month_field "book.release_month"
|
1199
|
+
end
|
1200
|
+
|
1201
|
+
expect(html).to include %(<input type="month" name="book[release_month]" id="book-release-month" value="#{val}">)
|
1202
|
+
end
|
1203
|
+
|
1204
|
+
it "allows to override 'value' attribute" do
|
1205
|
+
html = form_for("/books") do |f|
|
1206
|
+
f.month_field "book.release_month", value: "2017-04"
|
1207
|
+
end
|
1208
|
+
|
1209
|
+
expect(html).to include %(<input type="month" name="book[release_month]" id="book-release-month" value="2017-04">)
|
1210
|
+
end
|
1211
|
+
end
|
1212
|
+
end
|
1213
|
+
|
1214
|
+
describe "#week_field" do
|
1215
|
+
it "renders" do
|
1216
|
+
html = form_for("/books") do |f|
|
1217
|
+
f.week_field "book.release_week"
|
1218
|
+
end
|
1219
|
+
|
1220
|
+
expect(html).to include %(<input type="week" name="book[release_week]" id="book-release-week" value="">)
|
1221
|
+
end
|
1222
|
+
|
1223
|
+
it "allows to override 'id' attribute" do
|
1224
|
+
html = form_for("/books") do |f|
|
1225
|
+
f.week_field "book.release_week", id: "release-week"
|
1226
|
+
end
|
1227
|
+
|
1228
|
+
expect(html).to include %(<input type="week" name="book[release_week]" id="release-week" value="">)
|
1229
|
+
end
|
1230
|
+
|
1231
|
+
it "allows to override 'name' attribute" do
|
1232
|
+
html = form_for("/books") do |f|
|
1233
|
+
f.week_field "book.release_week", name: "release_week"
|
1234
|
+
end
|
1235
|
+
|
1236
|
+
expect(html).to include %(<input type="week" name="release_week" id="book-release-week" value="">)
|
1237
|
+
end
|
1238
|
+
|
1239
|
+
it "allows to override 'value' attribute" do
|
1240
|
+
html = form_for("/books") do |f|
|
1241
|
+
f.week_field "book.release_week", value: "2017-W10"
|
1242
|
+
end
|
1243
|
+
|
1244
|
+
expect(html).to include %(<input type="week" name="book[release_week]" id="book-release-week" value="2017-W10">)
|
1245
|
+
end
|
1246
|
+
|
1247
|
+
it "allows to specify HTML attributes" do
|
1248
|
+
html = form_for("/books") do |f|
|
1249
|
+
f.week_field "book.release_week", class: "form-control"
|
1250
|
+
end
|
1251
|
+
|
1252
|
+
expect(html).to include %(<input type="week" name="book[release_week]" id="book-release-week" value="" class="form-control">)
|
1253
|
+
end
|
1254
|
+
|
1255
|
+
context "with values" do
|
1256
|
+
let(:values) { {book: Struct.new(:release_week).new(val)} }
|
1257
|
+
let(:val) { "2017-W10" }
|
1258
|
+
|
1259
|
+
it "renders with value" do
|
1260
|
+
html = form_for("/books", values: values) do |f|
|
1261
|
+
f.week_field "book.release_week"
|
1262
|
+
end
|
1263
|
+
|
1264
|
+
expect(html).to include %(<input type="week" name="book[release_week]" id="book-release-week" value="#{val}">)
|
1265
|
+
end
|
1266
|
+
|
1267
|
+
it "allows to override 'value' attribute" do
|
1268
|
+
html = form_for("/books", values: values) do |f|
|
1269
|
+
f.week_field "book.release_week", value: "2017-W31"
|
1270
|
+
end
|
1271
|
+
|
1272
|
+
expect(html).to include %(<input type="week" name="book[release_week]" id="book-release-week" value="2017-W31">)
|
1273
|
+
end
|
1274
|
+
end
|
1275
|
+
|
1276
|
+
context "with filled params" do
|
1277
|
+
let(:params) { {book: {release_week: val}} }
|
1278
|
+
let(:val) { "2017-W44" }
|
1279
|
+
|
1280
|
+
it "renders with value" do
|
1281
|
+
html = form_for("/books") do |f|
|
1282
|
+
f.week_field "book.release_week"
|
1283
|
+
end
|
1284
|
+
|
1285
|
+
expect(html).to include %(<input type="week" name="book[release_week]" id="book-release-week" value="#{val}">)
|
1286
|
+
end
|
1287
|
+
|
1288
|
+
it "allows to override 'value' attribute" do
|
1289
|
+
html = form_for("/books") do |f|
|
1290
|
+
f.week_field "book.release_week", value: "2017-W07"
|
1291
|
+
end
|
1292
|
+
|
1293
|
+
expect(html).to include %(<input type="week" name="book[release_week]" id="book-release-week" value="2017-W07">)
|
1294
|
+
end
|
1295
|
+
end
|
1296
|
+
end
|
1297
|
+
|
1298
|
+
describe "#email_field" do
|
1299
|
+
it "renders" do
|
1300
|
+
html = form_for("/books") do |f|
|
1301
|
+
f.email_field "book.publisher_email"
|
1302
|
+
end
|
1303
|
+
|
1304
|
+
expect(html).to include %(<input type="email" name="book[publisher_email]" id="book-publisher-email" value="">)
|
1305
|
+
end
|
1306
|
+
|
1307
|
+
it "allows to override 'id' attribute" do
|
1308
|
+
html = form_for("/books") do |f|
|
1309
|
+
f.email_field "book.publisher_email", id: "publisher-email"
|
1310
|
+
end
|
1311
|
+
|
1312
|
+
expect(html).to include %(<input type="email" name="book[publisher_email]" id="publisher-email" value="">)
|
1313
|
+
end
|
1314
|
+
|
1315
|
+
it "allows to override 'name' attribute" do
|
1316
|
+
html = form_for("/books") do |f|
|
1317
|
+
f.email_field "book.publisher_email", name: "book[email]"
|
1318
|
+
end
|
1319
|
+
|
1320
|
+
expect(html).to include %(<input type="email" name="book[email]" id="book-publisher-email" value="">)
|
1321
|
+
end
|
1322
|
+
|
1323
|
+
it "allows to override 'value' attribute" do
|
1324
|
+
html = form_for("/books") do |f|
|
1325
|
+
f.email_field "book.publisher_email", value: "publisher@example.org"
|
1326
|
+
end
|
1327
|
+
|
1328
|
+
expect(html).to include %(<input type="email" name="book[publisher_email]" id="book-publisher-email" value="publisher@example.org">)
|
1329
|
+
end
|
1330
|
+
|
1331
|
+
it "allows to specify 'multiple' attribute" do
|
1332
|
+
html = form_for("/books") do |f|
|
1333
|
+
f.email_field "book.publisher_email", multiple: true
|
1334
|
+
end
|
1335
|
+
|
1336
|
+
expect(html).to include %(<input type="email" name="book[publisher_email]" id="book-publisher-email" value="" multiple="multiple">)
|
1337
|
+
end
|
1338
|
+
|
1339
|
+
it "allows to specify HTML attributes" do
|
1340
|
+
html = form_for("/books") do |f|
|
1341
|
+
f.email_field "book.publisher_email", class: "form-control"
|
1342
|
+
end
|
1343
|
+
|
1344
|
+
expect(html).to include %(<input type="email" name="book[publisher_email]" id="book-publisher-email" value="" class="form-control">)
|
1345
|
+
end
|
1346
|
+
|
1347
|
+
context "with values" do
|
1348
|
+
let(:values) { {book: Struct.new(:publisher_email).new(val)} }
|
1349
|
+
let(:val) { "maria@publisher.org" }
|
1350
|
+
|
1351
|
+
it "renders with value" do
|
1352
|
+
html = form_for("/books", values: values) do |f|
|
1353
|
+
f.email_field "book.publisher_email"
|
1354
|
+
end
|
1355
|
+
|
1356
|
+
expect(html).to include %(<input type="email" name="book[publisher_email]" id="book-publisher-email" value="maria@publisher.org">)
|
1357
|
+
end
|
1358
|
+
|
1359
|
+
it "allows to override 'value' attribute" do
|
1360
|
+
html = form_for("/books", values: values) do |f|
|
1361
|
+
f.email_field "book.publisher_email", value: "publisher@example.org"
|
1362
|
+
end
|
1363
|
+
|
1364
|
+
expect(html).to include %(<input type="email" name="book[publisher_email]" id="book-publisher-email" value="publisher@example.org">)
|
1365
|
+
end
|
1366
|
+
end
|
1367
|
+
|
1368
|
+
context "with filled params" do
|
1369
|
+
let(:params) { {book: {publisher_email: val}} }
|
1370
|
+
let(:val) { "maria@publisher.org" }
|
1371
|
+
|
1372
|
+
it "renders with value" do
|
1373
|
+
html = form_for("/books") do |f|
|
1374
|
+
f.email_field "book.publisher_email"
|
1375
|
+
end
|
1376
|
+
|
1377
|
+
expect(html).to include %(<input type="email" name="book[publisher_email]" id="book-publisher-email" value="maria@publisher.org">)
|
1378
|
+
end
|
1379
|
+
|
1380
|
+
it "allows to override 'value' attribute" do
|
1381
|
+
html = form_for("/books") do |f|
|
1382
|
+
f.email_field "book.publisher_email", value: "publisher@example.org"
|
1383
|
+
end
|
1384
|
+
|
1385
|
+
expect(html).to include %(<input type="email" name="book[publisher_email]" id="book-publisher-email" value="publisher@example.org">)
|
1386
|
+
end
|
1387
|
+
end
|
1388
|
+
end
|
1389
|
+
|
1390
|
+
describe "#url_field" do
|
1391
|
+
it "renders" do
|
1392
|
+
html = form_for("/books") do |f|
|
1393
|
+
f.url_field "book.website"
|
1394
|
+
end
|
1395
|
+
|
1396
|
+
expect(html).to include %(<input type="url" name="book[website]" id="book-website" value="">)
|
1397
|
+
end
|
1398
|
+
|
1399
|
+
it "allows to override 'id' attribute" do
|
1400
|
+
html = form_for("/books") do |f|
|
1401
|
+
f.url_field "book.website", id: "website"
|
1402
|
+
end
|
1403
|
+
|
1404
|
+
expect(html).to include %(<input type="url" name="book[website]" id="website" value="">)
|
1405
|
+
end
|
1406
|
+
|
1407
|
+
it "allows to override 'name' attribute" do
|
1408
|
+
html = form_for("/books") do |f|
|
1409
|
+
f.url_field "book.website", name: "book[url]"
|
1410
|
+
end
|
1411
|
+
|
1412
|
+
expect(html).to include %(<input type="url" name="book[url]" id="book-website" value="">)
|
1413
|
+
end
|
1414
|
+
|
1415
|
+
it "allows to override 'value' attribute" do
|
1416
|
+
html = form_for("/books") do |f|
|
1417
|
+
f.url_field "book.website", value: "http://example.org"
|
1418
|
+
end
|
1419
|
+
|
1420
|
+
expect(html).to include %(<input type="url" name="book[website]" id="book-website" value="http://example.org">)
|
1421
|
+
end
|
1422
|
+
|
1423
|
+
it "allows to specify 'multiple' attribute" do
|
1424
|
+
html = form_for("/books") do |f|
|
1425
|
+
f.url_field "book.website", multiple: true
|
1426
|
+
end
|
1427
|
+
|
1428
|
+
expect(html).to include %(<input type="url" name="book[website]" id="book-website" value="" multiple="multiple">)
|
1429
|
+
end
|
1430
|
+
|
1431
|
+
it "allows to specify HTML attributes" do
|
1432
|
+
html = form_for("/books") do |f|
|
1433
|
+
f.url_field "book.website", class: "form-control"
|
1434
|
+
end
|
1435
|
+
|
1436
|
+
expect(html).to include %(<input type="url" name="book[website]" id="book-website" value="" class="form-control">)
|
1437
|
+
end
|
1438
|
+
|
1439
|
+
context "with values" do
|
1440
|
+
let(:values) { {book: Struct.new(:website).new(val)} }
|
1441
|
+
let(:val) { "http://publisher.org" }
|
1442
|
+
|
1443
|
+
it "renders with value" do
|
1444
|
+
html = form_for("/books", values: values) do |f|
|
1445
|
+
f.url_field "book.website"
|
1446
|
+
end
|
1447
|
+
|
1448
|
+
expect(html).to include %(<input type="url" name="book[website]" id="book-website" value="http://publisher.org">)
|
1449
|
+
end
|
1450
|
+
|
1451
|
+
it "allows to override 'value' attribute" do
|
1452
|
+
html = form_for("/books", values: values) do |f|
|
1453
|
+
f.url_field "book.website", value: "https://www.example.org"
|
1454
|
+
end
|
1455
|
+
|
1456
|
+
expect(html).to include %(<input type="url" name="book[website]" id="book-website" value="https://www.example.org">)
|
1457
|
+
end
|
1458
|
+
end
|
1459
|
+
|
1460
|
+
context "with filled params" do
|
1461
|
+
let(:params) { {book: {website: val}} }
|
1462
|
+
let(:val) { "http://publisher.org" }
|
1463
|
+
|
1464
|
+
it "renders with value" do
|
1465
|
+
html = form_for("/books") do |f|
|
1466
|
+
f.url_field "book.website"
|
1467
|
+
end
|
1468
|
+
|
1469
|
+
expect(html).to include %(<input type="url" name="book[website]" id="book-website" value="http://publisher.org">)
|
1470
|
+
end
|
1471
|
+
|
1472
|
+
it "allows to override 'value' attribute" do
|
1473
|
+
html = form_for("/books") do |f|
|
1474
|
+
f.url_field "book.website", value: "http://example.org"
|
1475
|
+
end
|
1476
|
+
|
1477
|
+
expect(html).to include %(<input type="url" name="book[website]" id="book-website" value="http://example.org">)
|
1478
|
+
end
|
1479
|
+
end
|
1480
|
+
|
1481
|
+
context "with escape url" do
|
1482
|
+
let(:values) { {book: Struct.new(:website).new(val)} }
|
1483
|
+
let(:val) { %("onclick=javascript:alert('xss')) }
|
1484
|
+
|
1485
|
+
it "renders with automatic value" do
|
1486
|
+
html = form_for("/books", values: values) do |f|
|
1487
|
+
f.url_field "book.website"
|
1488
|
+
end
|
1489
|
+
|
1490
|
+
expect(html).to include %(<input type="url" name="book[website]" id="book-website" value="">)
|
1491
|
+
end
|
1492
|
+
|
1493
|
+
it "renders with explicit value" do
|
1494
|
+
html = form_for("/books", values: values) do |f|
|
1495
|
+
f.url_field "book.website", value: val
|
1496
|
+
end
|
1497
|
+
|
1498
|
+
expect(html).to include %(<input type="url" name="book[website]" id="book-website" value="">)
|
1499
|
+
end
|
1500
|
+
end
|
1501
|
+
end
|
1502
|
+
|
1503
|
+
describe "#tel_field" do
|
1504
|
+
it "renders" do
|
1505
|
+
html = form_for("/books") do |f|
|
1506
|
+
f.tel_field "book.publisher_telephone"
|
1507
|
+
end
|
1508
|
+
|
1509
|
+
expect(html).to include %(<input type="tel" name="book[publisher_telephone]" id="book-publisher-telephone" value="">)
|
1510
|
+
end
|
1511
|
+
|
1512
|
+
it "allows to override 'id' attribute" do
|
1513
|
+
html = form_for("/books") do |f|
|
1514
|
+
f.tel_field "book.publisher_telephone", id: "publisher-telephone"
|
1515
|
+
end
|
1516
|
+
|
1517
|
+
expect(html).to include %(<input type="tel" name="book[publisher_telephone]" id="publisher-telephone" value="">)
|
1518
|
+
end
|
1519
|
+
|
1520
|
+
it "allows to override 'name' attribute" do
|
1521
|
+
html = form_for("/books") do |f|
|
1522
|
+
f.tel_field "book.publisher_telephone", name: "book[telephone]"
|
1523
|
+
end
|
1524
|
+
|
1525
|
+
expect(html).to include %(<input type="tel" name="book[telephone]" id="book-publisher-telephone" value="">)
|
1526
|
+
end
|
1527
|
+
|
1528
|
+
it "allows to override 'value' attribute" do
|
1529
|
+
html = form_for("/books") do |f|
|
1530
|
+
f.tel_field "book.publisher_telephone", value: "publisher@example.org"
|
1531
|
+
end
|
1532
|
+
|
1533
|
+
expect(html).to include %(<input type="tel" name="book[publisher_telephone]" id="book-publisher-telephone" value="publisher@example.org">)
|
1534
|
+
end
|
1535
|
+
|
1536
|
+
it "allows to specify 'multiple' attribute" do
|
1537
|
+
html = form_for("/books") do |f|
|
1538
|
+
f.tel_field "book.publisher_telephone", multiple: true
|
1539
|
+
end
|
1540
|
+
|
1541
|
+
expect(html).to include %(<input type="tel" name="book[publisher_telephone]" id="book-publisher-telephone" value="" multiple="multiple">)
|
1542
|
+
end
|
1543
|
+
|
1544
|
+
it "allows to specify HTML attributes" do
|
1545
|
+
html = form_for("/books") do |f|
|
1546
|
+
f.tel_field "book.publisher_telephone", class: "form-control"
|
1547
|
+
end
|
1548
|
+
|
1549
|
+
expect(html).to include %(<input type="tel" name="book[publisher_telephone]" id="book-publisher-telephone" value="" class="form-control">)
|
1550
|
+
end
|
1551
|
+
|
1552
|
+
context "with values" do
|
1553
|
+
let(:values) { {book: Struct.new(:publisher_telephone).new(val)} }
|
1554
|
+
let(:val) { "maria@publisher.org" }
|
1555
|
+
|
1556
|
+
it "renders with value" do
|
1557
|
+
html = form_for("/books", values: values) do |f|
|
1558
|
+
f.tel_field "book.publisher_telephone"
|
1559
|
+
end
|
1560
|
+
|
1561
|
+
expect(html).to include %(<input type="tel" name="book[publisher_telephone]" id="book-publisher-telephone" value="maria@publisher.org">)
|
1562
|
+
end
|
1563
|
+
|
1564
|
+
it "allows to override 'value' attribute" do
|
1565
|
+
html = form_for("/books", values: values) do |f|
|
1566
|
+
f.tel_field "book.publisher_telephone", value: "publisher@example.org"
|
1567
|
+
end
|
1568
|
+
|
1569
|
+
expect(html).to include %(<input type="tel" name="book[publisher_telephone]" id="book-publisher-telephone" value="publisher@example.org">)
|
1570
|
+
end
|
1571
|
+
end
|
1572
|
+
|
1573
|
+
context "with filled params" do
|
1574
|
+
let(:params) { {book: {publisher_telephone: val}} }
|
1575
|
+
let(:val) { "maria@publisher.org" }
|
1576
|
+
|
1577
|
+
it "renders with value" do
|
1578
|
+
html = form_for("/books") do |f|
|
1579
|
+
f.tel_field "book.publisher_telephone"
|
1580
|
+
end
|
1581
|
+
|
1582
|
+
expect(html).to include %(<input type="tel" name="book[publisher_telephone]" id="book-publisher-telephone" value="maria@publisher.org">)
|
1583
|
+
end
|
1584
|
+
|
1585
|
+
it "allows to override 'value' attribute" do
|
1586
|
+
html = form_for("/books") do |f|
|
1587
|
+
f.tel_field "book.publisher_telephone", value: "publisher@example.org"
|
1588
|
+
end
|
1589
|
+
|
1590
|
+
expect(html).to include %(<input type="tel" name="book[publisher_telephone]" id="book-publisher-telephone" value="publisher@example.org">)
|
1591
|
+
end
|
1592
|
+
end
|
1593
|
+
end
|
1594
|
+
|
1595
|
+
describe "#file_field" do
|
1596
|
+
it "renders" do
|
1597
|
+
html = form_for("/books") do |f|
|
1598
|
+
f.file_field "book.image_cover"
|
1599
|
+
end
|
1600
|
+
|
1601
|
+
expect(html).to include %(<input type="file" name="book[image_cover]" id="book-image-cover">)
|
1602
|
+
end
|
1603
|
+
|
1604
|
+
it "sets 'enctype' attribute to the form" do
|
1605
|
+
html = form_for("/books") do |f|
|
1606
|
+
f.file_field "book.image_cover"
|
1607
|
+
end
|
1608
|
+
|
1609
|
+
expect(html).to include %(<form action="/books" enctype="multipart/form-data" accept-charset="utf-8" method="POST">)
|
1610
|
+
end
|
1611
|
+
|
1612
|
+
it "sets 'enctype' attribute to the form when there are nested fields" do
|
1613
|
+
html = form_for("/books") do |f|
|
1614
|
+
f.fields_for("images") do
|
1615
|
+
f.file_field("cover")
|
1616
|
+
end
|
1617
|
+
end
|
1618
|
+
|
1619
|
+
expect(html).to include %(<form action="/books" enctype="multipart/form-data" accept-charset="utf-8" method="POST">)
|
1620
|
+
end
|
1621
|
+
|
1622
|
+
it "allows to override 'id' attribute" do
|
1623
|
+
html = form_for("/books") do |f|
|
1624
|
+
f.file_field "book.image_cover", id: "book-cover"
|
1625
|
+
end
|
1626
|
+
|
1627
|
+
expect(html).to include %(<input type="file" name="book[image_cover]" id="book-cover">)
|
1628
|
+
end
|
1629
|
+
|
1630
|
+
it "allows to override 'name' attribute" do
|
1631
|
+
html = form_for("/books") do |f|
|
1632
|
+
f.file_field "book.image_cover", name: "book[cover]"
|
1633
|
+
end
|
1634
|
+
|
1635
|
+
expect(html).to include %(<input type="file" name="book[cover]" id="book-image-cover">)
|
1636
|
+
end
|
1637
|
+
|
1638
|
+
it "allows to specify 'multiple' attribute" do
|
1639
|
+
html = form_for("/books") do |f|
|
1640
|
+
f.file_field "book.image_cover", multiple: true
|
1641
|
+
end
|
1642
|
+
|
1643
|
+
expect(html).to include %(<input type="file" name="book[image_cover]" id="book-image-cover" multiple="multiple">)
|
1644
|
+
end
|
1645
|
+
|
1646
|
+
it "allows to specify single value for 'accept' attribute" do
|
1647
|
+
html = form_for("/books") do |f|
|
1648
|
+
f.file_field "book.image_cover", accept: "application/pdf"
|
1649
|
+
end
|
1650
|
+
|
1651
|
+
expect(html).to include %(<input type="file" name="book[image_cover]" id="book-image-cover" accept="application/pdf">)
|
1652
|
+
end
|
1653
|
+
|
1654
|
+
it "allows to specify multiple values for 'accept' attribute" do
|
1655
|
+
html = form_for("/books") do |f|
|
1656
|
+
f.file_field "book.image_cover", accept: "image/png,image/jpg"
|
1657
|
+
end
|
1658
|
+
|
1659
|
+
expect(html).to include %(<input type="file" name="book[image_cover]" id="book-image-cover" accept="image/png,image/jpg">)
|
1660
|
+
end
|
1661
|
+
|
1662
|
+
it "allows to specify multiple values (array) for 'accept' attribute" do
|
1663
|
+
html = form_for("/books") do |f|
|
1664
|
+
f.file_field "book.image_cover", accept: ["image/png", "image/jpg"]
|
1665
|
+
end
|
1666
|
+
|
1667
|
+
expect(html).to include %(<input type="file" name="book[image_cover]" id="book-image-cover" accept="image/png,image/jpg">)
|
1668
|
+
end
|
1669
|
+
|
1670
|
+
context "with values" do
|
1671
|
+
let(:values) { {book: Struct.new(:image_cover).new(val)} }
|
1672
|
+
let(:val) { "image" }
|
1673
|
+
|
1674
|
+
it "ignores value" do
|
1675
|
+
html = form_for("/books", values: values) do |f|
|
1676
|
+
f.file_field "book.image_cover"
|
1677
|
+
end
|
1678
|
+
|
1679
|
+
expect(html).to include %(<input type="file" name="book[image_cover]" id="book-image-cover">)
|
1680
|
+
end
|
1681
|
+
end
|
1682
|
+
|
1683
|
+
context "with filled params" do
|
1684
|
+
let(:params) { {book: {image_cover: val}} }
|
1685
|
+
let(:val) { "image" }
|
1686
|
+
|
1687
|
+
it "ignores value" do
|
1688
|
+
html = form_for("/books") do |f|
|
1689
|
+
f.file_field "book.image_cover"
|
1690
|
+
end
|
1691
|
+
|
1692
|
+
expect(html).to include %(<input type="file" name="book[image_cover]" id="book-image-cover">)
|
1693
|
+
end
|
1694
|
+
end
|
1695
|
+
end
|
1696
|
+
|
1697
|
+
describe "#hidden_field" do
|
1698
|
+
it "renders" do
|
1699
|
+
html = form_for("/books") do |f|
|
1700
|
+
f.hidden_field "book.author_id"
|
1701
|
+
end
|
1702
|
+
|
1703
|
+
expect(html).to include %(<input type="hidden" name="book[author_id]" id="book-author-id" value="">)
|
1704
|
+
end
|
1705
|
+
|
1706
|
+
it "allows to override 'id' attribute" do
|
1707
|
+
html = form_for("/books") do |f|
|
1708
|
+
f.hidden_field "book.author_id", id: "author-id"
|
1709
|
+
end
|
1710
|
+
|
1711
|
+
expect(html).to include %(<input type="hidden" name="book[author_id]" id="author-id" value="">)
|
1712
|
+
end
|
1713
|
+
|
1714
|
+
it "allows to override 'name' attribute" do
|
1715
|
+
html = form_for("/books") do |f|
|
1716
|
+
f.hidden_field "book.author_id", name: "book[author]"
|
1717
|
+
end
|
1718
|
+
|
1719
|
+
expect(html).to include %(<input type="hidden" name="book[author]" id="book-author-id" value="">)
|
1720
|
+
end
|
1721
|
+
|
1722
|
+
it "allows to override 'value' attribute" do
|
1723
|
+
html = form_for("/books") do |f|
|
1724
|
+
f.hidden_field "book.author_id", value: "23"
|
1725
|
+
end
|
1726
|
+
|
1727
|
+
expect(html).to include %(<input type="hidden" name="book[author_id]" id="book-author-id" value="23">)
|
1728
|
+
end
|
1729
|
+
|
1730
|
+
it "allows to specify HTML attributes" do
|
1731
|
+
html = form_for("/books") do |f|
|
1732
|
+
f.hidden_field "book.author_id", class: "form-details"
|
1733
|
+
end
|
1734
|
+
|
1735
|
+
expect(html).to include %(<input type="hidden" name="book[author_id]" id="book-author-id" value="" class="form-details">)
|
1736
|
+
end
|
1737
|
+
|
1738
|
+
context "with values" do
|
1739
|
+
let(:values) { {book: Struct.new(:author_id).new(val)} }
|
1740
|
+
let(:val) { "1" }
|
1741
|
+
|
1742
|
+
it "renders with value" do
|
1743
|
+
html = form_for("/books", values: values) do |f|
|
1744
|
+
f.hidden_field "book.author_id"
|
1745
|
+
end
|
1746
|
+
|
1747
|
+
expect(html).to include %(<input type="hidden" name="book[author_id]" id="book-author-id" value="1">)
|
1748
|
+
end
|
1749
|
+
|
1750
|
+
it "allows to override 'value' attribute" do
|
1751
|
+
html = form_for("/books", values: values) do |f|
|
1752
|
+
f.hidden_field "book.author_id", value: "23"
|
1753
|
+
end
|
1754
|
+
|
1755
|
+
expect(html).to include %(<input type="hidden" name="book[author_id]" id="book-author-id" value="23">)
|
1756
|
+
end
|
1757
|
+
end
|
1758
|
+
|
1759
|
+
context "with filled params" do
|
1760
|
+
let(:params) { {book: {author_id: val}} }
|
1761
|
+
let(:val) { "1" }
|
1762
|
+
|
1763
|
+
it "renders with value" do
|
1764
|
+
html = form_for("/books") do |f|
|
1765
|
+
f.hidden_field "book.author_id"
|
1766
|
+
end
|
1767
|
+
|
1768
|
+
expect(html).to include %(<input type="hidden" name="book[author_id]" id="book-author-id" value="1">)
|
1769
|
+
end
|
1770
|
+
|
1771
|
+
it "allows to override 'value' attribute" do
|
1772
|
+
html = form_for("/books") do |f|
|
1773
|
+
f.hidden_field "book.author_id", value: "23"
|
1774
|
+
end
|
1775
|
+
|
1776
|
+
expect(html).to include %(<input type="hidden" name="book[author_id]" id="book-author-id" value="23">)
|
1777
|
+
end
|
1778
|
+
end
|
1779
|
+
end
|
1780
|
+
|
1781
|
+
describe "#number_field" do
|
1782
|
+
it "renders the element" do
|
1783
|
+
html = form_for("/books") do |f|
|
1784
|
+
f.number_field "book.percent_read"
|
1785
|
+
end
|
1786
|
+
|
1787
|
+
expect(html).to include %(<input type="number" name="book[percent_read]" id="book-percent-read" value="">)
|
1788
|
+
end
|
1789
|
+
|
1790
|
+
it "allows to override 'id' attribute" do
|
1791
|
+
html = form_for("/books") do |f|
|
1792
|
+
f.number_field "book.percent_read", id: "percent-read"
|
1793
|
+
end
|
1794
|
+
|
1795
|
+
expect(html).to include %(<input type="number" name="book[percent_read]" id="percent-read" value="">)
|
1796
|
+
end
|
1797
|
+
|
1798
|
+
it "allows to override the 'name' attribute" do
|
1799
|
+
html = form_for("/books") do |f|
|
1800
|
+
f.number_field "book.percent_read", name: "book[read]"
|
1801
|
+
end
|
1802
|
+
|
1803
|
+
expect(html).to include %(<input type="number" name="book[read]" id="book-percent-read" value="">)
|
1804
|
+
end
|
1805
|
+
|
1806
|
+
it "allows to override the 'value' attribute" do
|
1807
|
+
html = form_for("/books") do |f|
|
1808
|
+
f.number_field "book.percent_read", value: "99"
|
1809
|
+
end
|
1810
|
+
|
1811
|
+
expect(html).to include %(<input type="number" name="book[percent_read]" id="book-percent-read" value="99">)
|
1812
|
+
end
|
1813
|
+
|
1814
|
+
it "allows to specify HTML attributes" do
|
1815
|
+
html = form_for("/books") do |f|
|
1816
|
+
f.number_field "book.percent_read", class: "form-control"
|
1817
|
+
end
|
1818
|
+
|
1819
|
+
expect(html).to include %(<input type="number" name="book[percent_read]" id="book-percent-read" value="" class="form-control">)
|
1820
|
+
end
|
1821
|
+
|
1822
|
+
it "allows to specify a 'min' attribute" do
|
1823
|
+
html = form_for("/books") do |f|
|
1824
|
+
f.number_field "book.percent_read", min: 0
|
1825
|
+
end
|
1826
|
+
|
1827
|
+
expect(html).to include %(<input type="number" name="book[percent_read]" id="book-percent-read" value="" min="0">)
|
1828
|
+
end
|
1829
|
+
|
1830
|
+
it "allows to specify a 'max' attribute" do
|
1831
|
+
html = form_for("/books") do |f|
|
1832
|
+
f.number_field "book.percent_read", max: 100
|
1833
|
+
end
|
1834
|
+
|
1835
|
+
expect(html).to include %(<input type="number" name="book[percent_read]" id="book-percent-read" value="" max="100">)
|
1836
|
+
end
|
1837
|
+
|
1838
|
+
it "allows to specify a 'step' attribute" do
|
1839
|
+
html = form_for("/books") do |f|
|
1840
|
+
f.number_field "book.percent_read", step: 5
|
1841
|
+
end
|
1842
|
+
|
1843
|
+
expect(html).to include %(<input type="number" name="book[percent_read]" id="book-percent-read" value="" step="5">)
|
1844
|
+
end
|
1845
|
+
|
1846
|
+
context "with values" do
|
1847
|
+
let(:values) { {book: Struct.new(:percent_read).new(val)} }
|
1848
|
+
let(:val) { 95 }
|
1849
|
+
|
1850
|
+
it "renders with value" do
|
1851
|
+
html = form_for("/books", values: values) do |f|
|
1852
|
+
f.number_field "book.percent_read"
|
1853
|
+
end
|
1854
|
+
|
1855
|
+
expect(html).to include %(<input type="number" name="book[percent_read]" id="book-percent-read" value="95">)
|
1856
|
+
end
|
1857
|
+
|
1858
|
+
it "allows to override 'value' attribute" do
|
1859
|
+
html = form_for("/books", values: values) do |f|
|
1860
|
+
f.number_field "book.percent_read", value: 50
|
1861
|
+
end
|
1862
|
+
|
1863
|
+
expect(html).to include %(<input type="number" name="book[percent_read]" id="book-percent-read" value="50">)
|
1864
|
+
end
|
1865
|
+
end
|
1866
|
+
|
1867
|
+
context "with filled params" do
|
1868
|
+
let(:params) { {book: {percent_read: val}} }
|
1869
|
+
let(:val) { 95 }
|
1870
|
+
|
1871
|
+
it "renders with value" do
|
1872
|
+
html = form_for("/books") do |f|
|
1873
|
+
f.number_field "book.percent_read"
|
1874
|
+
end
|
1875
|
+
|
1876
|
+
expect(html).to include %(<input type="number" name="book[percent_read]" id="book-percent-read" value="95">)
|
1877
|
+
end
|
1878
|
+
|
1879
|
+
it "allows to override 'value' attribute" do
|
1880
|
+
html = form_for("/books") do |f|
|
1881
|
+
f.number_field "book.percent_read", value: 50
|
1882
|
+
end
|
1883
|
+
|
1884
|
+
expect(html).to include %(<input type="number" name="book[percent_read]" id="book-percent-read" value="50">)
|
1885
|
+
end
|
1886
|
+
end
|
1887
|
+
end
|
1888
|
+
|
1889
|
+
describe "#range_field" do
|
1890
|
+
it "renders the element" do
|
1891
|
+
html = form_for("/books") do |f|
|
1892
|
+
f.range_field "book.discount_percentage"
|
1893
|
+
end
|
1894
|
+
|
1895
|
+
expect(html).to include %(<input type="range" name="book[discount_percentage]" id="book-discount-percentage" value="">)
|
1896
|
+
end
|
1897
|
+
|
1898
|
+
it "allows to override 'id' attribute" do
|
1899
|
+
html = form_for("/books") do |f|
|
1900
|
+
f.range_field "book.discount_percentage", id: "discount-percentage"
|
1901
|
+
end
|
1902
|
+
|
1903
|
+
expect(html).to include %(<input type="range" name="book[discount_percentage]" id="discount-percentage" value="">)
|
1904
|
+
end
|
1905
|
+
|
1906
|
+
it "allows to override the 'name' attribute" do
|
1907
|
+
html = form_for("/books") do |f|
|
1908
|
+
f.range_field "book.discount_percentage", name: "book[read]"
|
1909
|
+
end
|
1910
|
+
|
1911
|
+
expect(html).to include %(<input type="range" name="book[read]" id="book-discount-percentage" value="">)
|
1912
|
+
end
|
1913
|
+
|
1914
|
+
it "allows to override the 'value' attribute" do
|
1915
|
+
html = form_for("/books") do |f|
|
1916
|
+
f.range_field "book.discount_percentage", value: "99"
|
1917
|
+
end
|
1918
|
+
|
1919
|
+
expect(html).to include %(<input type="range" name="book[discount_percentage]" id="book-discount-percentage" value="99">)
|
1920
|
+
end
|
1921
|
+
|
1922
|
+
it "allows to specify HTML attributes" do
|
1923
|
+
html = form_for("/books") do |f|
|
1924
|
+
f.range_field "book.discount_percentage", class: "form-control"
|
1925
|
+
end
|
1926
|
+
|
1927
|
+
expect(html).to include %(<input type="range" name="book[discount_percentage]" id="book-discount-percentage" value="" class="form-control">)
|
1928
|
+
end
|
1929
|
+
|
1930
|
+
it "allows to specify a 'min' attribute" do
|
1931
|
+
html = form_for("/books") do |f|
|
1932
|
+
f.range_field "book.discount_percentage", min: 0
|
1933
|
+
end
|
1934
|
+
|
1935
|
+
expect(html).to include %(<input type="range" name="book[discount_percentage]" id="book-discount-percentage" value="" min="0">)
|
1936
|
+
end
|
1937
|
+
|
1938
|
+
it "allows to specify a 'max' attribute" do
|
1939
|
+
html = form_for("/books") do |f|
|
1940
|
+
f.range_field "book.discount_percentage", max: 100
|
1941
|
+
end
|
1942
|
+
|
1943
|
+
expect(html).to include %(<input type="range" name="book[discount_percentage]" id="book-discount-percentage" value="" max="100">)
|
1944
|
+
end
|
1945
|
+
|
1946
|
+
it "allows to specify a 'step' attribute" do
|
1947
|
+
html = form_for("/books") do |f|
|
1948
|
+
f.range_field "book.discount_percentage", step: 5
|
1949
|
+
end
|
1950
|
+
|
1951
|
+
expect(html).to include %(<input type="range" name="book[discount_percentage]" id="book-discount-percentage" value="" step="5">)
|
1952
|
+
end
|
1953
|
+
|
1954
|
+
context "with values" do
|
1955
|
+
let(:values) { {book: Struct.new(:discount_percentage).new(val)} }
|
1956
|
+
let(:val) { 95 }
|
1957
|
+
|
1958
|
+
it "renders with value" do
|
1959
|
+
html = form_for("/books", values: values) do |f|
|
1960
|
+
f.range_field "book.discount_percentage"
|
1961
|
+
end
|
1962
|
+
|
1963
|
+
expect(html).to include %(<input type="range" name="book[discount_percentage]" id="book-discount-percentage" value="95">)
|
1964
|
+
end
|
1965
|
+
|
1966
|
+
it "allows to override 'value' attribute" do
|
1967
|
+
html = form_for("/books", values: values) do |f|
|
1968
|
+
f.range_field "book.discount_percentage", value: 50
|
1969
|
+
end
|
1970
|
+
|
1971
|
+
expect(html).to include %(<input type="range" name="book[discount_percentage]" id="book-discount-percentage" value="50">)
|
1972
|
+
end
|
1973
|
+
end
|
1974
|
+
|
1975
|
+
context "with filled params" do
|
1976
|
+
let(:params) { {book: {discount_percentage: val}} }
|
1977
|
+
let(:val) { 95 }
|
1978
|
+
|
1979
|
+
it "renders with value" do
|
1980
|
+
html = form_for("/books") do |f|
|
1981
|
+
f.range_field "book.discount_percentage"
|
1982
|
+
end
|
1983
|
+
|
1984
|
+
expect(html).to include %(<input type="range" name="book[discount_percentage]" id="book-discount-percentage" value="95">)
|
1985
|
+
end
|
1986
|
+
|
1987
|
+
it "allows to override 'value' attribute" do
|
1988
|
+
html = form_for("/books") do |f|
|
1989
|
+
f.range_field "book.discount_percentage", value: 50
|
1990
|
+
end
|
1991
|
+
|
1992
|
+
expect(html).to include %(<input type="range" name="book[discount_percentage]" id="book-discount-percentage" value="50">)
|
1993
|
+
end
|
1994
|
+
end
|
1995
|
+
end
|
1996
|
+
|
1997
|
+
describe "#text_area" do
|
1998
|
+
it "renders the element" do
|
1999
|
+
html = form_for("/books") do |f|
|
2000
|
+
f.text_area "book.description"
|
2001
|
+
end
|
2002
|
+
|
2003
|
+
expect(html).to include %(<textarea name="book[description]" id="book-description">\n</textarea>)
|
2004
|
+
end
|
2005
|
+
|
2006
|
+
it "allows to override 'id' attribute" do
|
2007
|
+
html = form_for("/books") do |f|
|
2008
|
+
f.text_area "book.description", nil, id: "desc"
|
2009
|
+
end
|
2010
|
+
|
2011
|
+
expect(html).to include %(<textarea name="book[description]" id="desc">\n</textarea>)
|
2012
|
+
end
|
2013
|
+
|
2014
|
+
it "allows to override 'name' attribute" do
|
2015
|
+
html = form_for("/books") do |f|
|
2016
|
+
f.text_area "book.description", nil, name: "book[desc]"
|
2017
|
+
end
|
2018
|
+
|
2019
|
+
expect(html).to include %(<textarea name="book[desc]" id="book-description">\n</textarea>)
|
2020
|
+
end
|
2021
|
+
|
2022
|
+
it "allows to specify HTML attributes" do
|
2023
|
+
html = form_for("/books") do |f|
|
2024
|
+
f.text_area "book.description", nil, class: "form-control", cols: "5"
|
2025
|
+
end
|
2026
|
+
|
2027
|
+
expect(html).to include %(<textarea name="book[description]" id="book-description" class="form-control" cols="5">\n</textarea>)
|
2028
|
+
end
|
2029
|
+
|
2030
|
+
it "allows to omit content" do
|
2031
|
+
html = form_for("/books") do |f|
|
2032
|
+
f.text_area "book.description", class: "form-control", cols: "5"
|
2033
|
+
end
|
2034
|
+
|
2035
|
+
expect(html).to include %(<textarea name="book[description]" id="book-description" class="form-control" cols="5">\n</textarea>)
|
2036
|
+
end
|
2037
|
+
|
2038
|
+
it "allows to omit content, by accepting Hash serializable options" do
|
2039
|
+
options = {class: "form-control", cols: 5}
|
2040
|
+
|
2041
|
+
html = form_for("/books") do |f|
|
2042
|
+
f.text_area "book.description", options
|
2043
|
+
end
|
2044
|
+
|
2045
|
+
expect(html).to include %(<textarea name="book[description]" id="book-description" class="form-control" cols="5">\n</textarea>)
|
2046
|
+
end
|
2047
|
+
|
2048
|
+
context "set content explicitly" do
|
2049
|
+
let(:content) { "A short description of the book" }
|
2050
|
+
|
2051
|
+
it "allows to set content" do
|
2052
|
+
html = form_for("/books") do |f|
|
2053
|
+
f.text_area "book.description", content
|
2054
|
+
end
|
2055
|
+
|
2056
|
+
expect(html).to include %(<textarea name="book[description]" id="book-description">\n#{content}</textarea>)
|
2057
|
+
end
|
2058
|
+
end
|
2059
|
+
|
2060
|
+
context "with values" do
|
2061
|
+
let(:values) { {book: Struct.new(:description).new(val)} }
|
2062
|
+
let(:val) { "A short description of the book" }
|
2063
|
+
|
2064
|
+
it "renders with value" do
|
2065
|
+
html = form_for("/books", values: values) do |f|
|
2066
|
+
f.text_area "book.description"
|
2067
|
+
end
|
2068
|
+
|
2069
|
+
expect(html).to include %(<textarea name="book[description]" id="book-description">\n#{val}</textarea>)
|
2070
|
+
end
|
2071
|
+
|
2072
|
+
it "renders with value, when only attributes are specified" do
|
2073
|
+
html = form_for("/books", values: values) do |f|
|
2074
|
+
f.text_area "book.description", class: "form-control"
|
2075
|
+
end
|
2076
|
+
|
2077
|
+
expect(html).to include %(<textarea name="book[description]" id="book-description" class="form-control">\n#{val}</textarea>)
|
2078
|
+
end
|
2079
|
+
|
2080
|
+
it "allows to override value" do
|
2081
|
+
html = form_for("/books", values: values) do |f|
|
2082
|
+
f.text_area "book.description", "Just a simple description"
|
2083
|
+
end
|
2084
|
+
|
2085
|
+
expect(html).to include %(<textarea name="book[description]" id="book-description">\nJust a simple description</textarea>)
|
2086
|
+
end
|
2087
|
+
|
2088
|
+
it "forces blank value" do
|
2089
|
+
html = form_for("/books", values: values) do |f|
|
2090
|
+
f.text_area "book.description", ""
|
2091
|
+
end
|
2092
|
+
|
2093
|
+
expect(html).to include %(<textarea name="book[description]" id="book-description">\n</textarea>)
|
2094
|
+
end
|
2095
|
+
|
2096
|
+
it "forces blank value, when also attributes are specified" do
|
2097
|
+
html = form_for("/books", values: values) do |f|
|
2098
|
+
f.text_area "book.description", "", class: "form-control"
|
2099
|
+
end
|
2100
|
+
|
2101
|
+
expect(html).to include %(<textarea name="book[description]" id="book-description" class="form-control">\n</textarea>)
|
2102
|
+
end
|
2103
|
+
end
|
2104
|
+
|
2105
|
+
context "with filled params" do
|
2106
|
+
let(:params) { {book: {description: val}} }
|
2107
|
+
let(:val) { "A short description of the book" }
|
2108
|
+
|
2109
|
+
it "renders with value" do
|
2110
|
+
html = form_for("/books") do |f|
|
2111
|
+
f.text_area "book.description"
|
2112
|
+
end
|
2113
|
+
|
2114
|
+
expect(html).to include %(<textarea name="book[description]" id="book-description">\n#{val}</textarea>)
|
2115
|
+
end
|
2116
|
+
|
2117
|
+
it "renders with value, when only attributes are specified" do
|
2118
|
+
html = form_for("/books") do |f|
|
2119
|
+
f.text_area "book.description", class: "form-control"
|
2120
|
+
end
|
2121
|
+
|
2122
|
+
expect(html).to include %(<textarea name="book[description]" id="book-description" class="form-control">\n#{val}</textarea>)
|
2123
|
+
end
|
2124
|
+
|
2125
|
+
it "allows to override value" do
|
2126
|
+
html = form_for("/books") do |f|
|
2127
|
+
f.text_area "book.description", "Just a simple description"
|
2128
|
+
end
|
2129
|
+
|
2130
|
+
expect(html).to include %(<textarea name="book[description]" id="book-description">\nJust a simple description</textarea>)
|
2131
|
+
end
|
2132
|
+
|
2133
|
+
it "forces blank value" do
|
2134
|
+
html = form_for("/books") do |f|
|
2135
|
+
f.text_area "book.description", ""
|
2136
|
+
end
|
2137
|
+
|
2138
|
+
expect(html).to include %(<textarea name="book[description]" id="book-description">\n</textarea>)
|
2139
|
+
end
|
2140
|
+
|
2141
|
+
it "forces blank value, when also attributes are specified" do
|
2142
|
+
html = form_for("/books") do |f|
|
2143
|
+
f.text_area "book.description", "", class: "form-control"
|
2144
|
+
end
|
2145
|
+
|
2146
|
+
expect(html).to include %(<textarea name="book[description]" id="book-description" class="form-control">\n</textarea>)
|
2147
|
+
end
|
2148
|
+
end
|
2149
|
+
end
|
2150
|
+
|
2151
|
+
describe "#text_field" do
|
2152
|
+
it "renders" do
|
2153
|
+
html = form_for("/books") do |f|
|
2154
|
+
f.text_field "book.title"
|
2155
|
+
end
|
2156
|
+
|
2157
|
+
expect(html).to include %(<input type="text" name="book[title]" id="book-title" value="">)
|
2158
|
+
end
|
2159
|
+
|
2160
|
+
it "allows to override 'id' attribute" do
|
2161
|
+
html = form_for("/books") do |f|
|
2162
|
+
f.text_field "book.title", id: "book-short-title"
|
2163
|
+
end
|
2164
|
+
|
2165
|
+
expect(html).to include %(<input type="text" name="book[title]" id="book-short-title" value="">)
|
2166
|
+
end
|
2167
|
+
|
2168
|
+
it "allows to override 'name' attribute" do
|
2169
|
+
html = form_for("/books") do |f|
|
2170
|
+
f.text_field "book.title", name: "book[short_title]"
|
2171
|
+
end
|
2172
|
+
|
2173
|
+
expect(html).to include %(<input type="text" name="book[short_title]" id="book-title" value="">)
|
2174
|
+
end
|
2175
|
+
|
2176
|
+
it "allows to override 'value' attribute" do
|
2177
|
+
html = form_for("/books") do |f|
|
2178
|
+
f.text_field "book.title", value: "Refactoring"
|
2179
|
+
end
|
2180
|
+
|
2181
|
+
expect(html).to include %(<input type="text" name="book[title]" id="book-title" value="Refactoring">)
|
2182
|
+
end
|
2183
|
+
|
2184
|
+
it "allows to specify HTML attributes" do
|
2185
|
+
html = form_for("/books") do |f|
|
2186
|
+
f.text_field "book.title", class: "form-control"
|
2187
|
+
end
|
2188
|
+
|
2189
|
+
expect(html).to include %(<input type="text" name="book[title]" id="book-title" value="" class="form-control">)
|
2190
|
+
end
|
2191
|
+
|
2192
|
+
context "with values" do
|
2193
|
+
let(:values) { {book: Struct.new(:title).new(val)} }
|
2194
|
+
let(:val) { "Learn some <html>!" }
|
2195
|
+
|
2196
|
+
it "renders with value" do
|
2197
|
+
html = form_for("/books", values: values) do |f|
|
2198
|
+
f.text_field "book.title"
|
2199
|
+
end
|
2200
|
+
|
2201
|
+
expect(html).to include %(<input type="text" name="book[title]" id="book-title" value="Learn some <html>!">)
|
2202
|
+
end
|
2203
|
+
|
2204
|
+
it "allows to override 'value' attribute" do
|
2205
|
+
html = form_for("/books", values: values) do |f|
|
2206
|
+
f.text_field "book.title", value: "DDD"
|
2207
|
+
end
|
2208
|
+
|
2209
|
+
expect(html).to include %(<input type="text" name="book[title]" id="book-title" value="DDD">)
|
2210
|
+
end
|
2211
|
+
end
|
2212
|
+
|
2213
|
+
context "with filled params" do
|
2214
|
+
let(:params) { {book: {title: val}} }
|
2215
|
+
let(:val) { "Learn some <html>!" }
|
2216
|
+
|
2217
|
+
it "renders with value" do
|
2218
|
+
html = form_for("/books") do |f|
|
2219
|
+
f.text_field "book.title"
|
2220
|
+
end
|
2221
|
+
|
2222
|
+
expect(html).to include %(<input type="text" name="book[title]" id="book-title" value="Learn some <html>!">)
|
2223
|
+
end
|
2224
|
+
|
2225
|
+
it "allows to override 'value' attribute" do
|
2226
|
+
html = form_for("/books") do |f|
|
2227
|
+
f.text_field "book.title", value: "DDD"
|
2228
|
+
end
|
2229
|
+
|
2230
|
+
expect(html).to include %(<input type="text" name="book[title]" id="book-title" value="DDD">)
|
2231
|
+
end
|
2232
|
+
end
|
2233
|
+
end
|
2234
|
+
|
2235
|
+
describe "#search_field" do
|
2236
|
+
it "renders" do
|
2237
|
+
html = form_for("/books") do |f|
|
2238
|
+
f.search_field "book.search_title"
|
2239
|
+
end
|
2240
|
+
|
2241
|
+
expect(html).to include %(<input type="search" name="book[search_title]" id="book-search-title" value="">)
|
2242
|
+
end
|
2243
|
+
|
2244
|
+
it "allows to override 'id' attribute" do
|
2245
|
+
html = form_for("/books") do |f|
|
2246
|
+
f.search_field "book.search_title", id: "book-short-title"
|
2247
|
+
end
|
2248
|
+
|
2249
|
+
expect(html).to include %(<input type="search" name="book[search_title]" id="book-short-title" value="">)
|
2250
|
+
end
|
2251
|
+
|
2252
|
+
it "allows to override 'name' attribute" do
|
2253
|
+
html = form_for("/books") do |f|
|
2254
|
+
f.search_field "book.search_title", name: "book[short_title]"
|
2255
|
+
end
|
2256
|
+
|
2257
|
+
expect(html).to include %(<input type="search" name="book[short_title]" id="book-search-title" value="">)
|
2258
|
+
end
|
2259
|
+
|
2260
|
+
it "allows to override 'value' attribute" do
|
2261
|
+
html = form_for("/books") do |f|
|
2262
|
+
f.search_field "book.search_title", value: "Refactoring"
|
2263
|
+
end
|
2264
|
+
|
2265
|
+
expect(html).to include %(<input type="search" name="book[search_title]" id="book-search-title" value="Refactoring">)
|
2266
|
+
end
|
2267
|
+
|
2268
|
+
it "allows to specify HTML attributes" do
|
2269
|
+
html = form_for("/books") do |f|
|
2270
|
+
f.search_field "book.search_title", class: "form-control"
|
2271
|
+
end
|
2272
|
+
|
2273
|
+
expect(html).to include %(<input type="search" name="book[search_title]" id="book-search-title" value="" class="form-control">)
|
2274
|
+
end
|
2275
|
+
|
2276
|
+
context "with values" do
|
2277
|
+
let(:values) { {book: Struct.new(:search_title).new(val)} }
|
2278
|
+
let(:val) { "PPoEA" }
|
2279
|
+
|
2280
|
+
it "renders with value" do
|
2281
|
+
html = form_for("/books", values: values) do |f|
|
2282
|
+
f.search_field "book.search_title"
|
2283
|
+
end
|
2284
|
+
|
2285
|
+
expect(html).to include %(<input type="search" name="book[search_title]" id="book-search-title" value="PPoEA">)
|
2286
|
+
end
|
2287
|
+
|
2288
|
+
it "allows to override 'value' attribute" do
|
2289
|
+
html = form_for("/books", values: values) do |f|
|
2290
|
+
f.search_field "book.search_title", value: "DDD"
|
2291
|
+
end
|
2292
|
+
|
2293
|
+
expect(html).to include %(<input type="search" name="book[search_title]" id="book-search-title" value="DDD">)
|
2294
|
+
end
|
2295
|
+
end
|
2296
|
+
|
2297
|
+
context "with filled params" do
|
2298
|
+
let(:params) { {book: {search_title: val}} }
|
2299
|
+
let(:val) { "PPoEA" }
|
2300
|
+
|
2301
|
+
it "renders with value" do
|
2302
|
+
html = form_for("/books") do |f|
|
2303
|
+
f.search_field "book.search_title"
|
2304
|
+
end
|
2305
|
+
|
2306
|
+
expect(html).to include %(<input type="search" name="book[search_title]" id="book-search-title" value="PPoEA">)
|
2307
|
+
end
|
2308
|
+
|
2309
|
+
it "allows to override 'value' attribute" do
|
2310
|
+
html = form_for("/books") do |f|
|
2311
|
+
f.search_field "book.search_title", value: "DDD"
|
2312
|
+
end
|
2313
|
+
|
2314
|
+
expect(html).to include %(<input type="search" name="book[search_title]" id="book-search-title" value="DDD">)
|
2315
|
+
end
|
2316
|
+
end
|
2317
|
+
end
|
2318
|
+
|
2319
|
+
describe "#password_field" do
|
2320
|
+
it "renders" do
|
2321
|
+
html = form_for("/books") do |f|
|
2322
|
+
f.password_field "signup.password"
|
2323
|
+
end
|
2324
|
+
|
2325
|
+
expect(html).to include %(<input type="password" name="signup[password]" id="signup-password" value="">)
|
2326
|
+
end
|
2327
|
+
|
2328
|
+
it "allows to override 'id' attribute" do
|
2329
|
+
html = form_for("/books") do |f|
|
2330
|
+
f.password_field "signup.password", id: "signup-pass"
|
2331
|
+
end
|
2332
|
+
|
2333
|
+
expect(html).to include %(<input type="password" name="signup[password]" id="signup-pass" value="">)
|
2334
|
+
end
|
2335
|
+
|
2336
|
+
it "allows to override 'name' attribute" do
|
2337
|
+
html = form_for("/books") do |f|
|
2338
|
+
f.password_field "signup.password", name: "password"
|
2339
|
+
end
|
2340
|
+
|
2341
|
+
expect(html).to include %(<input type="password" name="password" id="signup-password" value="">)
|
2342
|
+
end
|
2343
|
+
|
2344
|
+
it "allows to override 'value' attribute" do
|
2345
|
+
html = form_for("/books") do |f|
|
2346
|
+
f.password_field "signup.password", value: "topsecret"
|
2347
|
+
end
|
2348
|
+
|
2349
|
+
expect(html).to include %(<input type="password" name="signup[password]" id="signup-password" value="topsecret">)
|
2350
|
+
end
|
2351
|
+
|
2352
|
+
it "allows to specify HTML attributes" do
|
2353
|
+
html = form_for("/books") do |f|
|
2354
|
+
f.password_field "signup.password", class: "form-control"
|
2355
|
+
end
|
2356
|
+
|
2357
|
+
expect(html).to include %(<input type="password" name="signup[password]" id="signup-password" value="" class="form-control">)
|
2358
|
+
end
|
2359
|
+
|
2360
|
+
context "with values" do
|
2361
|
+
let(:values) { {signup: Struct.new(:password).new(val)} }
|
2362
|
+
let(:val) { "secret" }
|
2363
|
+
|
2364
|
+
it "ignores value" do
|
2365
|
+
html = form_for("/books", values: values) do |f|
|
2366
|
+
f.password_field "signup.password"
|
2367
|
+
end
|
2368
|
+
|
2369
|
+
expect(html).to include %(<input type="password" name="signup[password]" id="signup-password" value="">)
|
2370
|
+
end
|
2371
|
+
|
2372
|
+
it "allows to override 'value' attribute" do
|
2373
|
+
html = form_for("/books", values: values) do |f|
|
2374
|
+
f.password_field "signup.password", value: "123"
|
2375
|
+
end
|
2376
|
+
|
2377
|
+
expect(html).to include %(<input type="password" name="signup[password]" id="signup-password" value="123">)
|
2378
|
+
end
|
2379
|
+
end
|
2380
|
+
|
2381
|
+
context "with filled params" do
|
2382
|
+
let(:params) { {signup: {password: val}} }
|
2383
|
+
let(:val) { "secret" }
|
2384
|
+
|
2385
|
+
it "ignores value" do
|
2386
|
+
html = form_for("/books") do |f|
|
2387
|
+
f.password_field "signup.password"
|
2388
|
+
end
|
2389
|
+
|
2390
|
+
expect(html).to include %(<input type="password" name="signup[password]" id="signup-password" value="">)
|
2391
|
+
end
|
2392
|
+
|
2393
|
+
it "allows to override 'value' attribute" do
|
2394
|
+
html = form_for("/books") do |f|
|
2395
|
+
f.password_field "signup.password", value: "123"
|
2396
|
+
end
|
2397
|
+
|
2398
|
+
expect(html).to include %(<input type="password" name="signup[password]" id="signup-password" value="123">)
|
2399
|
+
end
|
2400
|
+
end
|
2401
|
+
end
|
2402
|
+
|
2403
|
+
describe "#radio_button" do
|
2404
|
+
it "renders" do
|
2405
|
+
html = form_for("/books") do |f|
|
2406
|
+
f.radio_button("book.category", "Fiction") +
|
2407
|
+
f.radio_button("book.category", "Non-Fiction")
|
2408
|
+
end
|
2409
|
+
|
2410
|
+
expect(html).to include %(<input type="radio" name="book[category]" value="Fiction"><input type="radio" name="book[category]" value="Non-Fiction">)
|
2411
|
+
end
|
2412
|
+
|
2413
|
+
it "allows to override 'name' attribute" do
|
2414
|
+
html = form_for("/books") do |f|
|
2415
|
+
f.radio_button("book.category", "Fiction", name: "category_name") +
|
2416
|
+
f.radio_button("book.category", "Non-Fiction", name: "category_name")
|
2417
|
+
end
|
2418
|
+
|
2419
|
+
expect(html).to include %(<input type="radio" name="category_name" value="Fiction"><input type="radio" name="category_name" value="Non-Fiction">)
|
2420
|
+
end
|
2421
|
+
|
2422
|
+
it "allows to specify HTML attributes" do
|
2423
|
+
html = form_for("/books") do |f|
|
2424
|
+
f.radio_button("book.category", "Fiction", class: "form-control") +
|
2425
|
+
f.radio_button("book.category", "Non-Fiction", class: "radio-button")
|
2426
|
+
end
|
2427
|
+
|
2428
|
+
expect(html).to include %(<input type="radio" name="book[category]" value="Fiction" class="form-control"><input type="radio" name="book[category]" value="Non-Fiction" class="radio-button">)
|
2429
|
+
end
|
2430
|
+
|
2431
|
+
context "with values" do
|
2432
|
+
let(:values) { {book: Struct.new(:category).new(val)} }
|
2433
|
+
let(:val) { "Non-Fiction" }
|
2434
|
+
|
2435
|
+
it "renders with value" do
|
2436
|
+
html = form_for("/books", values: values) do |f|
|
2437
|
+
f.radio_button("book.category", "Fiction") +
|
2438
|
+
f.radio_button("book.category", "Non-Fiction")
|
2439
|
+
end
|
2440
|
+
|
2441
|
+
expect(html).to include %(<input type="radio" name="book[category]" value="Fiction"><input type="radio" name="book[category]" value="Non-Fiction" checked="checked">)
|
2442
|
+
end
|
2443
|
+
end
|
2444
|
+
|
2445
|
+
context "with filled params" do
|
2446
|
+
context "string value" do
|
2447
|
+
let(:params) { {book: {category: val}} }
|
2448
|
+
let(:val) { "Non-Fiction" }
|
2449
|
+
|
2450
|
+
it "renders with value" do
|
2451
|
+
html = form_for("/books") do |f|
|
2452
|
+
f.radio_button("book.category", "Fiction") +
|
2453
|
+
f.radio_button("book.category", "Non-Fiction")
|
2454
|
+
end
|
2455
|
+
|
2456
|
+
expect(html).to include %(<input type="radio" name="book[category]" value="Fiction"><input type="radio" name="book[category]" value="Non-Fiction" checked="checked">)
|
2457
|
+
end
|
2458
|
+
end
|
2459
|
+
|
2460
|
+
context "decimal value" do
|
2461
|
+
let(:params) { {book: {price: val}} }
|
2462
|
+
let(:val) { "20.0" }
|
2463
|
+
|
2464
|
+
it "renders with value" do
|
2465
|
+
html = form_for("/books") do |f|
|
2466
|
+
f.radio_button("book.price", 10.0) +
|
2467
|
+
f.radio_button("book.price", 20.0)
|
2468
|
+
end
|
2469
|
+
|
2470
|
+
expect(html).to include %(<input type="radio" name="book[price]" value="10.0"><input type="radio" name="book[price]" value="20.0" checked="checked">)
|
2471
|
+
end
|
2472
|
+
end
|
2473
|
+
end
|
2474
|
+
end
|
2475
|
+
|
2476
|
+
describe "#select" do
|
2477
|
+
let(:option_values) { {"Italy" => "it", "United States" => "us"} }
|
2478
|
+
|
2479
|
+
it "renders" do
|
2480
|
+
html = form_for("/books") do |f|
|
2481
|
+
f.select "book.store", option_values
|
2482
|
+
end
|
2483
|
+
|
2484
|
+
expect(html).to include %(<select name="book[store]" id="book-store"><option value="it">Italy</option><option value="us">United States</option></select>)
|
2485
|
+
end
|
2486
|
+
|
2487
|
+
it "allows to override 'id' attribute" do
|
2488
|
+
html = form_for("/books") do |f|
|
2489
|
+
f.select "book.store", option_values, id: "store"
|
2490
|
+
end
|
2491
|
+
|
2492
|
+
expect(html).to include %(<select name="book[store]" id="store"><option value="it">Italy</option><option value="us">United States</option></select>)
|
2493
|
+
end
|
2494
|
+
|
2495
|
+
it "allows to override 'name' attribute" do
|
2496
|
+
html = form_for("/books") do |f|
|
2497
|
+
f.select "book.store", option_values, name: "store"
|
2498
|
+
end
|
2499
|
+
|
2500
|
+
expect(html).to include %(<select name="store" id="book-store"><option value="it">Italy</option><option value="us">United States</option></select>)
|
2501
|
+
end
|
2502
|
+
|
2503
|
+
it "allows to specify HTML attributes" do
|
2504
|
+
html = form_for("/books") do |f|
|
2505
|
+
f.select "book.store", option_values, class: "form-control"
|
2506
|
+
end
|
2507
|
+
|
2508
|
+
expect(html).to include %(<select name="book[store]" id="book-store" class="form-control"><option value="it">Italy</option><option value="us">United States</option></select>)
|
2509
|
+
end
|
2510
|
+
|
2511
|
+
it "allows to specify HTML attributes for options" do
|
2512
|
+
html = form_for("/books") do |f|
|
2513
|
+
f.select "book.store", option_values, options: {class: "form-option"}
|
2514
|
+
end
|
2515
|
+
|
2516
|
+
expect(html).to include %(<select name="book[store]" id="book-store"><option value="it" class="form-option">Italy</option><option value="us" class="form-option">United States</option></select>)
|
2517
|
+
end
|
2518
|
+
|
2519
|
+
context "with option 'multiple'" do
|
2520
|
+
it "renders" do
|
2521
|
+
html = form_for("/books") do |f|
|
2522
|
+
f.select "book.store", option_values, multiple: true
|
2523
|
+
end
|
2524
|
+
|
2525
|
+
expect(html).to include %(<select name="book[store][]" id="book-store" multiple="multiple"><option value="it">Italy</option><option value="us">United States</option></select>)
|
2526
|
+
end
|
2527
|
+
|
2528
|
+
it "allows to select values" do
|
2529
|
+
html = form_for("/books") do |f|
|
2530
|
+
f.select "book.store", option_values, multiple: true, options: {selected: %w[it us]}
|
2531
|
+
end
|
2532
|
+
|
2533
|
+
expect(html).to include %(<select name="book[store][]" id="book-store" multiple="multiple"><option value="it" selected="selected">Italy</option><option value="us" selected="selected">United States</option></select>)
|
2534
|
+
end
|
2535
|
+
end
|
2536
|
+
|
2537
|
+
context "with values an structured Array of values" do
|
2538
|
+
let(:option_values) { [%w[Italy it], ["United States", "us"]] }
|
2539
|
+
|
2540
|
+
it "renders" do
|
2541
|
+
html = form_for("/books") do |f|
|
2542
|
+
f.select "book.store", option_values
|
2543
|
+
end
|
2544
|
+
|
2545
|
+
expect(html).to include %(<select name="book[store]" id="book-store"><option value="it">Italy</option><option value="us">United States</option></select>)
|
2546
|
+
end
|
2547
|
+
|
2548
|
+
context "and filled params" do
|
2549
|
+
let(:params) { {book: {store: val}} }
|
2550
|
+
let(:val) { "it" }
|
2551
|
+
|
2552
|
+
it "renders with value" do
|
2553
|
+
html = form_for("/books") do |f|
|
2554
|
+
f.select "book.store", option_values
|
2555
|
+
end
|
2556
|
+
|
2557
|
+
expect(html).to include %(<select name="book[store]" id="book-store"><option value="it" selected="selected">Italy</option><option value="us">United States</option></select>)
|
2558
|
+
end
|
2559
|
+
end
|
2560
|
+
|
2561
|
+
context "and repeated values" do
|
2562
|
+
let(:option_values) { [%w[Italy it], ["United States", "us"], %w[Italy it]] }
|
2563
|
+
|
2564
|
+
it "renders" do
|
2565
|
+
html = form_for("/books") do |f|
|
2566
|
+
f.select "book.store", option_values
|
2567
|
+
end
|
2568
|
+
|
2569
|
+
expect(html).to include %(<select name="book[store]" id="book-store"><option value="it">Italy</option><option value="us">United States</option><option value="it">Italy</option></select>)
|
2570
|
+
end
|
2571
|
+
end
|
2572
|
+
end
|
2573
|
+
|
2574
|
+
context "with values an Array of objects" do
|
2575
|
+
let(:values) { [Store.new("it", "Italy"), Store.new("us", "United States")] }
|
2576
|
+
|
2577
|
+
it "renders" do
|
2578
|
+
html = form_for("/books") do |f|
|
2579
|
+
f.select "book.store", option_values
|
2580
|
+
end
|
2581
|
+
|
2582
|
+
expect(html).to include %(<select name="book[store]" id="book-store"><option value="it">Italy</option><option value="us">United States</option></select>)
|
2583
|
+
end
|
2584
|
+
|
2585
|
+
context "and filled params" do
|
2586
|
+
let(:params) { {book: {store: val}} }
|
2587
|
+
let(:val) { "it" }
|
2588
|
+
|
2589
|
+
it "renders with value" do
|
2590
|
+
html = form_for("/books") do |f|
|
2591
|
+
f.select "book.store", option_values
|
2592
|
+
end
|
2593
|
+
|
2594
|
+
expect(html).to include %(<select name="book[store]" id="book-store"><option value="it" selected="selected">Italy</option><option value="us">United States</option></select>)
|
2595
|
+
end
|
2596
|
+
end
|
2597
|
+
end
|
2598
|
+
|
2599
|
+
context "with values" do
|
2600
|
+
let(:values) { {book: Struct.new(:store).new(val)} }
|
2601
|
+
let(:val) { "it" }
|
2602
|
+
|
2603
|
+
it "renders with value" do
|
2604
|
+
html = form_for("/books", values: values) do |f|
|
2605
|
+
f.select "book.store", option_values
|
2606
|
+
end
|
2607
|
+
|
2608
|
+
expect(html).to include %(<select name="book[store]" id="book-store"><option value="it" selected="selected">Italy</option><option value="us">United States</option></select>)
|
2609
|
+
end
|
2610
|
+
end
|
2611
|
+
|
2612
|
+
context "with filled params" do
|
2613
|
+
let(:params) { {book: {store: val}} }
|
2614
|
+
let(:val) { "it" }
|
2615
|
+
|
2616
|
+
it "renders with value" do
|
2617
|
+
html = form_for("/books") do |f|
|
2618
|
+
f.select "book.store", option_values
|
2619
|
+
end
|
2620
|
+
|
2621
|
+
expect(html).to include %(<select name="book[store]" id="book-store"><option value="it" selected="selected">Italy</option><option value="us">United States</option></select>)
|
2622
|
+
end
|
2623
|
+
end
|
2624
|
+
|
2625
|
+
context "with prompt option" do
|
2626
|
+
it "allows string" do
|
2627
|
+
html = form_for("/books") do |f|
|
2628
|
+
f.select "book.store", option_values, options: {prompt: "Select a store"}
|
2629
|
+
end
|
2630
|
+
|
2631
|
+
expect(html).to include %(<select name="book[store]" id="book-store"><option disabled="disabled">Select a store</option><option value="it">Italy</option><option value="us">United States</option></select>)
|
2632
|
+
end
|
2633
|
+
|
2634
|
+
it "allows blank string" do
|
2635
|
+
html = form_for("/books") do |f|
|
2636
|
+
f.select "book.store", option_values, options: {prompt: ""}
|
2637
|
+
end
|
2638
|
+
|
2639
|
+
expect(html).to include %(<select name="book[store]" id="book-store"><option disabled="disabled"></option><option value="it">Italy</option><option value="us">United States</option></select>)
|
2640
|
+
end
|
2641
|
+
|
2642
|
+
context "with values" do
|
2643
|
+
let(:values) { {book: Struct.new(:store).new(val)} }
|
2644
|
+
let(:val) { "it" }
|
2645
|
+
|
2646
|
+
it "renders with value" do
|
2647
|
+
html = form_for("/books", values: values) do |f|
|
2648
|
+
f.select "book.store", option_values, options: {prompt: "Select a store"}
|
2649
|
+
end
|
2650
|
+
|
2651
|
+
expect(html).to include %(<select name="book[store]" id="book-store"><option disabled="disabled">Select a store</option><option value="it" selected="selected">Italy</option><option value="us">United States</option></select>)
|
2652
|
+
end
|
2653
|
+
end
|
2654
|
+
|
2655
|
+
context "with filled params" do
|
2656
|
+
context "string values" do
|
2657
|
+
let(:params) { {book: {store: val}} }
|
2658
|
+
let(:val) { "it" }
|
2659
|
+
|
2660
|
+
it "renders with value" do
|
2661
|
+
html = form_for("/books") do |f|
|
2662
|
+
f.select "book.store", option_values, options: {prompt: "Select a store"}
|
2663
|
+
end
|
2664
|
+
|
2665
|
+
expect(html).to include %(<select name="book[store]" id="book-store"><option disabled="disabled">Select a store</option><option value="it" selected="selected">Italy</option><option value="us">United States</option></select>)
|
2666
|
+
end
|
2667
|
+
end
|
2668
|
+
|
2669
|
+
context "integer values" do
|
2670
|
+
let(:values) { {"Brave new world" => 1, "Solaris" => 2} }
|
2671
|
+
let(:params) { {bookshelf: {book: val}} }
|
2672
|
+
let(:val) { "1" }
|
2673
|
+
|
2674
|
+
it "renders" do
|
2675
|
+
html = form_for("/books") do |f|
|
2676
|
+
f.select "bookshelf.book", values
|
2677
|
+
end
|
2678
|
+
|
2679
|
+
expect(html).to include %(<select name="bookshelf[book]" id="bookshelf-book"><option value="1" selected="selected">Brave new world</option><option value="2">Solaris</option></select>)
|
2680
|
+
end
|
2681
|
+
end
|
2682
|
+
end
|
2683
|
+
end
|
2684
|
+
|
2685
|
+
context "with selected attribute" do
|
2686
|
+
let(:params) { {book: {store: val}} }
|
2687
|
+
let(:val) { "it" }
|
2688
|
+
|
2689
|
+
it "sets the selected attribute" do
|
2690
|
+
html = form_for("/books") do |f|
|
2691
|
+
f.select "book.store", option_values, options: {selected: val}
|
2692
|
+
end
|
2693
|
+
|
2694
|
+
expect(html).to include %(<select name="book[store]" id="book-store"><option value="it" selected="selected">Italy</option><option value="us">United States</option></select>)
|
2695
|
+
end
|
2696
|
+
end
|
2697
|
+
|
2698
|
+
context "with nil as a value" do
|
2699
|
+
let(:option_values) { {"Italy" => "it", "United States" => "us", "N/A" => nil} }
|
2700
|
+
|
2701
|
+
it "sets nil option as selected by default" do
|
2702
|
+
html = form_for("/books") do |f|
|
2703
|
+
f.select "book.store", option_values
|
2704
|
+
end
|
2705
|
+
|
2706
|
+
expect(html).to include %(<select name="book[store]" id="book-store"><option value="it">Italy</option><option value="us">United States</option><option selected="selected">N/A</option></select>)
|
2707
|
+
end
|
2708
|
+
|
2709
|
+
it "set as selected the option with nil value" do
|
2710
|
+
html = form_for("/books") do |f|
|
2711
|
+
f.select "book.store", option_values, options: {selected: nil}
|
2712
|
+
end
|
2713
|
+
|
2714
|
+
expect(html).to include %(<select name="book[store]" id="book-store"><option value="it">Italy</option><option value="us">United States</option><option selected="selected">N/A</option></select>)
|
2715
|
+
end
|
2716
|
+
|
2717
|
+
it "set as selected the option with a value" do
|
2718
|
+
html = form_for("/books") do |f|
|
2719
|
+
f.select "book.store", option_values, options: {selected: "it"}
|
2720
|
+
end
|
2721
|
+
|
2722
|
+
expect(html).to include %(<select name="book[store]" id="book-store"><option value="it" selected="selected">Italy</option><option value="us">United States</option><option>N/A</option></select>)
|
2723
|
+
end
|
2724
|
+
|
2725
|
+
it "allows to force the selection of none" do
|
2726
|
+
html = form_for("/books") do |f|
|
2727
|
+
f.select "book.store", option_values, options: {selected: "none"}
|
2728
|
+
end
|
2729
|
+
|
2730
|
+
expect(html).to include %(<select name="book[store]" id="book-store"><option value="it">Italy</option><option value="us">United States</option><option>N/A</option></select>)
|
2731
|
+
end
|
2732
|
+
|
2733
|
+
context "with values" do
|
2734
|
+
let(:values) { {book: Struct.new(:category).new(val)} }
|
2735
|
+
let(:option_values) { {"N/A" => nil, "Horror" => "horror", "SciFy" => "scify"} }
|
2736
|
+
let(:val) { "horror" }
|
2737
|
+
|
2738
|
+
it "sets correct value as selected" do
|
2739
|
+
html = form_for("/books", values: values) do |f|
|
2740
|
+
f.select "book.category", option_values
|
2741
|
+
end
|
2742
|
+
|
2743
|
+
expect(html).to include %(<form action="/books" accept-charset="utf-8" method="POST"><select name="book[category]" id="book-category"><option>N/A</option><option value="horror" selected="selected">Horror</option><option value="scify">SciFy</option></select></form>)
|
2744
|
+
end
|
2745
|
+
end
|
2746
|
+
|
2747
|
+
context "with non String values" do
|
2748
|
+
let(:values) { {book: Struct.new(:category).new(val)} }
|
2749
|
+
let(:option_values) { {"Horror" => "1", "SciFy" => "2"} }
|
2750
|
+
let(:val) { 1 }
|
2751
|
+
|
2752
|
+
it "sets correct value as selected" do
|
2753
|
+
html = form_for("/books", values: values) do |f|
|
2754
|
+
f.select "book.category", option_values
|
2755
|
+
end
|
2756
|
+
|
2757
|
+
expect(html).to include %(<form action="/books" accept-charset="utf-8" method="POST"><select name="book[category]" id="book-category"><option value="1" selected="selected">Horror</option><option value="2">SciFy</option></select></form>)
|
2758
|
+
end
|
2759
|
+
end
|
2760
|
+
end
|
2761
|
+
end
|
2762
|
+
|
2763
|
+
describe "#datalist" do
|
2764
|
+
let(:values) { ["Italy", "United States"] }
|
2765
|
+
|
2766
|
+
it "renders" do
|
2767
|
+
html = form_for("/books") do |f|
|
2768
|
+
f.datalist "book.store", values, "books"
|
2769
|
+
end
|
2770
|
+
|
2771
|
+
expect(html).to include %(<input type="text" name="book[store]" id="book-store" value="" list="books"><datalist id="books"><option value="Italy"></option><option value="United States"></option></datalist>)
|
2772
|
+
end
|
2773
|
+
|
2774
|
+
it "just allows to override 'id' attribute of the text input" do
|
2775
|
+
html = form_for("/books") do |f|
|
2776
|
+
f.datalist "book.store", values, "books", id: "store"
|
2777
|
+
end
|
2778
|
+
|
2779
|
+
expect(html).to include %(<input type="text" name="book[store]" id="store" value="" list="books"><datalist id="books"><option value="Italy"></option><option value="United States"></option></datalist>)
|
2780
|
+
end
|
2781
|
+
|
2782
|
+
it "allows to override 'name' attribute" do
|
2783
|
+
html = form_for("/books") do |f|
|
2784
|
+
f.datalist "book.store", values, "books", name: "store"
|
2785
|
+
end
|
2786
|
+
|
2787
|
+
expect(html).to include %(<input type="text" name="store" id="book-store" value="" list="books"><datalist id="books"><option value="Italy"></option><option value="United States"></option></datalist>)
|
2788
|
+
end
|
2789
|
+
|
2790
|
+
it "allows to specify HTML attributes" do
|
2791
|
+
html = form_for("/books") do |f|
|
2792
|
+
f.datalist "book.store", values, "books", class: "form-control"
|
2793
|
+
end
|
2794
|
+
|
2795
|
+
expect(html).to include %(<input type="text" name="book[store]" id="book-store" value="" class="form-control" list="books"><datalist id="books"><option value="Italy"></option><option value="United States"></option></datalist>)
|
2796
|
+
end
|
2797
|
+
|
2798
|
+
it "allows to specify HTML attributes for options" do
|
2799
|
+
html = form_for("/books") do |f|
|
2800
|
+
f.datalist "book.store", values, "books", options: {class: "form-option"}
|
2801
|
+
end
|
2802
|
+
|
2803
|
+
expect(html).to include %(<input type="text" name="book[store]" id="book-store" value="" list="books"><datalist id="books"><option value="Italy" class="form-option"></option><option value="United States" class="form-option"></option></datalist>)
|
2804
|
+
end
|
2805
|
+
|
2806
|
+
it "allows to specify HTML attributes for datalist" do
|
2807
|
+
html = form_for("/books") do |f|
|
2808
|
+
f.datalist "book.store", values, "books", datalist: {class: "form-option"}
|
2809
|
+
end
|
2810
|
+
|
2811
|
+
expect(html).to include %(<input type="text" name="book[store]" id="book-store" value="" list="books"><datalist class="form-option" id="books"><option value="Italy"></option><option value="United States"></option></datalist>)
|
2812
|
+
end
|
2813
|
+
|
2814
|
+
context "with a Hash of values" do
|
2815
|
+
let(:values) { {"Italy" => "it", "United States" => "us"} }
|
2816
|
+
|
2817
|
+
it "renders" do
|
2818
|
+
html = form_for("/books") do |f|
|
2819
|
+
f.datalist "book.store", values, "books"
|
2820
|
+
end
|
2821
|
+
|
2822
|
+
expect(html).to include %(<input type="text" name="book[store]" id="book-store" value="" list="books"><datalist id="books"><option value="Italy">it</option><option value="United States">us</option></datalist>)
|
2823
|
+
end
|
2824
|
+
end
|
2825
|
+
end
|
2826
|
+
end
|