design_system 0.7.0 → 0.8.0

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.
Files changed (33) hide show
  1. checksums.yaml +4 -4
  2. data/README.md +3 -1
  3. data/app/controllers/concerns/design_system/branded.rb +7 -0
  4. data/app/helpers/design_system_helper.rb +0 -2
  5. data/app/views/layouts/govuk/application.html.erb +14 -25
  6. data/app/views/layouts/nhsuk/application.html.erb +24 -37
  7. data/app/views/nhsuk/_navigation.html.erb +9 -12
  8. data/lib/design_system/engine.rb +0 -3
  9. data/lib/design_system/generic/builders/base.rb +2 -1
  10. data/lib/design_system/generic/builders/button.rb +0 -2
  11. data/lib/design_system/generic/builders/fixed_elements.rb +0 -5
  12. data/lib/design_system/generic/builders/link.rb +0 -2
  13. data/lib/design_system/generic/builders/summary_list.rb +0 -3
  14. data/lib/design_system/generic/builders/tab.rb +0 -3
  15. data/lib/design_system/generic/builders/table.rb +0 -3
  16. data/lib/design_system/generic/form_builder.rb +2 -12
  17. data/lib/design_system/govuk/builders/button.rb +0 -2
  18. data/lib/design_system/govuk/builders/fixed_elements.rb +0 -4
  19. data/lib/design_system/govuk/builders/link.rb +0 -2
  20. data/lib/design_system/govuk/builders/summary_list.rb +0 -2
  21. data/lib/design_system/govuk/builders/tab.rb +0 -2
  22. data/lib/design_system/govuk/builders/table.rb +0 -2
  23. data/lib/design_system/govuk/form_builder.rb +0 -1
  24. data/lib/design_system/govuk/test_helpers/form_builder_assertions_helper.rb +99 -0
  25. data/lib/design_system/govuk/test_helpers/form_builder_testable.rb +1300 -0
  26. data/lib/design_system/helpers/css_helper.rb +20 -0
  27. data/lib/design_system/nhsuk/builders/fixed_elements.rb +0 -3
  28. data/lib/design_system/nhsuk/builders/summary_list.rb +0 -2
  29. data/lib/design_system/nhsuk/form_builder.rb +0 -2
  30. data/lib/design_system/version.rb +1 -1
  31. data/lib/design_system.rb +9 -0
  32. metadata +21 -5
  33. data/app/helpers/css_helper.rb +0 -13
@@ -0,0 +1,1300 @@
1
+ require 'design_system/govuk/test_helpers/form_builder_assertions_helper'
2
+
3
+ module DesignSystem
4
+ module Govuk
5
+ class DummyModel
6
+ include ActiveModel::Model
7
+
8
+ attr_accessor :role
9
+ end
10
+
11
+ module DummyAdmin
12
+ class DummyUser
13
+ include ActiveModel::Model
14
+
15
+ attr_accessor :status
16
+ end
17
+ end
18
+
19
+ module TestHelpers
20
+ # This concern manages choosing the relevant layout for our given design system
21
+ module FormBuilderTestable
22
+ include DesignSystemHelper
23
+ include DesignSystem::Govuk::TestHelpers::FormBuilderAssertionsHelper
24
+ extend ActiveSupport::Concern
25
+
26
+ included do
27
+ setup do
28
+ I18n.backend.store_translations(:en, {
29
+ helpers: {
30
+ options: {
31
+ assistant: {
32
+ terms_agreed: {
33
+ true: 'Yes, I agree'
34
+ }
35
+ },
36
+ 'design_system/govuk/dummy_model': {
37
+ role: {
38
+ admin: 'Administrator'
39
+ }
40
+ },
41
+ 'design_system/govuk/dummy_admin/dummy_user': {
42
+ status: {
43
+ active: 'Still in the game'
44
+ }
45
+ }
46
+ }
47
+ }
48
+ })
49
+ end
50
+
51
+ test 'self.brand' do
52
+ assert_equal @brand, @builder.brand
53
+ end
54
+
55
+ test 'ds_check_box with single checkbox' do
56
+ @output_buffer = ds_form_with(model: assistants(:one), builder: @builder) do |f|
57
+ f.ds_check_boxes_fieldset(:desired_filling, { multiple: true, legend: { size: 'm' } }) do
58
+ f.ds_check_box(:desired_filling, { multiple: true }, :pastrami)
59
+ end
60
+ end
61
+
62
+ assert_form_group do
63
+ assert_select("fieldset.#{@brand}-fieldset") do
64
+ assert_select("legend.#{@brand}-fieldset__legend.#{@brand}-fieldset__legend--m", 'What do you want in your sandwich?')
65
+
66
+ input = assert_select('input').first
67
+ assert_equal 'assistant_desired_filling', input['id']
68
+ assert_equal 'assistant[desired_filling][]', input['name']
69
+ assert_equal '', input['value']
70
+ assert_equal 'hidden', input['type']
71
+ assert_equal 'off', input['autocomplete']
72
+
73
+ assert_select("div.#{@brand}-checkboxes[data-module='#{@brand}-checkboxes']") do
74
+ assert_select("div.#{@brand}-checkboxes__item") do
75
+ input = assert_select("input.#{@brand}-checkboxes__input").first
76
+ assert_equal 'assistant_desired_filling_pastrami', input['id']
77
+ assert_equal 'assistant[desired_filling][]', input['name']
78
+ assert_equal 'pastrami', input['value']
79
+ assert_equal 'checkbox', input['type']
80
+
81
+ label = assert_select("label.#{@brand}-label.#{@brand}-checkboxes__label[for='assistant_desired_filling_pastrami']").first
82
+ assert_equal 'pastrami', label.text.strip
83
+ end
84
+ end
85
+ end
86
+ end
87
+ end
88
+
89
+ test 'ds_check_box item translation for activerecord attributes' do
90
+ @output_buffer = ds_form_with(model: assistants(:one), builder: @builder) do |f|
91
+ f.ds_check_box(:terms_agreed, {}, :true)
92
+ end
93
+
94
+ assert_select('form') do
95
+ assert_select("div.#{@brand}-checkboxes__item") do
96
+ assert_select("label.#{@brand}-label.#{@brand}-checkboxes__label", 'Yes, I agree')
97
+ end
98
+ end
99
+ end
100
+
101
+ test 'ds_check_box item translation for activemodel attributes' do
102
+ @output_buffer = ds_form_with(model: DummyModel.new, builder: @builder, url: '/') do |f|
103
+ f.ds_check_box(:role, {}, :admin)
104
+ end
105
+
106
+ assert_select('form') do
107
+ assert_select("div.#{@brand}-checkboxes__item") do
108
+ assert_select("label.#{@brand}-label.#{@brand}-checkboxes__label", 'Administrator')
109
+ end
110
+ end
111
+ end
112
+
113
+ test 'ds_check_box item translation for activemodel attributes with nested attributes' do
114
+ @output_buffer = ds_form_with(model: DummyAdmin::DummyUser.new, builder: @builder, url: '/') do |f|
115
+ f.ds_check_box(:status, {}, :active)
116
+ end
117
+
118
+ assert_select('form') do
119
+ assert_select("div.#{@brand}-checkboxes__item") do
120
+ assert_select("label.#{@brand}-label.#{@brand}-checkboxes__label", 'Still in the game')
121
+ end
122
+ end
123
+ end
124
+
125
+ test 'ds_check_box item with dot in value is not incorrectly translated' do
126
+ value_with_dot = 'Made up dummy values (e.g. see with dot it works)'
127
+ @output_buffer = ds_form_with(model: DummyModel.new, builder: @builder, url: '/') do |f|
128
+ f.ds_check_box(:role, {}, value_with_dot)
129
+ end
130
+
131
+ assert_select('form') do
132
+ assert_select("div.#{@brand}-checkboxes__item") do
133
+ label = assert_select("label.#{@brand}-label.#{@brand}-checkboxes__label").first
134
+ assert_equal value_with_dot, label.text.strip
135
+ end
136
+ end
137
+ end
138
+
139
+ test 'ds_collection_select' do
140
+ @output_buffer = ds_form_with(model: assistants(:one), builder: @builder) do |f|
141
+ f.ds_collection_select(:department_id, Department.all, :id, :title)
142
+ end
143
+
144
+ assert_form_group do
145
+ assert_label :department_id, nil, 'What is your department?'
146
+
147
+ select = assert_select("select.#{@brand}-select").first
148
+ assert_equal 'assistant_department_id', select['id']
149
+ assert_equal 'assistant[department_id]', select['name']
150
+
151
+ options = assert_select('option')
152
+ assert_equal '1', options[0]['value']
153
+ assert_equal 'Sales', options[0].text.strip
154
+ assert_equal '2', options[1]['value']
155
+ assert_equal 'Marketing', options[1].text.strip
156
+ assert_equal '3', options[2]['value']
157
+ assert_equal 'Finance', options[2].text.strip
158
+ end
159
+ end
160
+
161
+ test 'ds_collection_select with hint' do
162
+ @output_buffer = ds_form_with(model: assistants(:one), builder: @builder) do |f|
163
+ f.ds_collection_select(:department_id, Department.all, :id, :title, hint: 'This is a hint')
164
+ end
165
+
166
+ assert_form_group do
167
+ assert_label :department_id, nil, 'What is your department?'
168
+ assert_hint :department_id, nil, 'This is a hint'
169
+
170
+ select = assert_select("select.#{@brand}-select").first
171
+ assert_equal 'assistant_department_id_hint', select['aria-describedby']
172
+ end
173
+ end
174
+
175
+ test 'ds_collection_select with html options' do
176
+ @output_buffer = ds_form_with(model: assistants(:one), builder: @builder) do |f|
177
+ f.ds_collection_select(:department_id, Department.all, :id, :title, {}, { class: 'geoff', placeholder: 'bar' })
178
+ end
179
+
180
+ assert_form_group do
181
+ assert_label :department_id, nil, 'What is your department?'
182
+
183
+ select = assert_select("select.#{@brand}-select.geoff[placeholder=bar]").first
184
+ assert_equal 'assistant_department_id', select['id']
185
+ assert_equal 'assistant[department_id]', select['name']
186
+
187
+ options = assert_select('option')
188
+ assert_equal '1', options[0]['value']
189
+ assert_equal 'Sales', options[0].text.strip
190
+ end
191
+ end
192
+
193
+ test 'ds_collection_select with custom label size' do
194
+ @output_buffer = ds_form_with(model: assistants(:one), builder: @builder) do |f|
195
+ f.ds_collection_select(:department_id, Department.all, :id, :title, label: { size: 'l' })
196
+ end
197
+
198
+ assert_form_group do
199
+ assert_select("label.#{@brand}-label.#{@brand}-label--l", text: 'What is your department?')
200
+ end
201
+ end
202
+
203
+ test 'ds_date_field' do
204
+ @output_buffer = ds_form_with(model: assistants(:one), builder: @builder) do |f|
205
+ f.ds_date_field(:date_of_birth, hint: 'This is a hint')
206
+ end
207
+
208
+ assert_form_group do
209
+ assert_select("fieldset.#{@brand}-fieldset[aria-describedby=assistant_date_of_birth_hint]") do
210
+ legend = assert_select("legend.#{@brand}-fieldset__legend").first
211
+ assert_equal 'What is your date of birth?', legend.text.strip
212
+
213
+ assert_hint :date_of_birth, nil, 'This is a hint'
214
+
215
+ date_input = assert_select("div.#{@brand}-date-input").first
216
+ assert date_input, 'Date input container not found'
217
+
218
+ # Test day input
219
+ assert_select("div.#{@brand}-date-input__item:nth-child(1)")
220
+ assert_select("div.#{@brand}-form-group") do
221
+ day_label = assert_select("label.#{@brand}-label[for='assistant_date_of_birth_3i']").first
222
+ assert_equal 'Day', day_label.text.strip
223
+
224
+ day_input = assert_select("input.#{@brand}-input.#{@brand}-date-input__input.#{@brand}-input--width-2").first
225
+ assert_equal 'assistant_date_of_birth_3i', day_input['id']
226
+ assert_equal 'assistant[date_of_birth(3i)]', day_input['name']
227
+ assert_equal 'text', day_input['type']
228
+ assert_equal 'numeric', day_input['inputmode']
229
+ end
230
+
231
+ # Test month input
232
+ assert_select("div.#{@brand}-date-input__item:nth-child(2)")
233
+ assert_select("div.#{@brand}-form-group") do
234
+ month_label = assert_select("label.#{@brand}-label[for='assistant_date_of_birth_2i']").first
235
+ assert_equal 'Month', month_label.text.strip
236
+
237
+ month_input = assert_select("input.#{@brand}-input.#{@brand}-date-input__input.#{@brand}-input--width-2").last
238
+ assert_equal 'assistant_date_of_birth_2i', month_input['id']
239
+ assert_equal 'assistant[date_of_birth(2i)]', month_input['name']
240
+ assert_equal 'text', month_input['type']
241
+ assert_equal 'numeric', month_input['inputmode']
242
+ end
243
+
244
+ # Test year input
245
+ assert_select("div.#{@brand}-date-input__item:nth-child(3)")
246
+ assert_select("div.#{@brand}-form-group") do
247
+ year_label = assert_select("label.#{@brand}-label[for='assistant_date_of_birth_1i']").first
248
+ assert_equal 'Year', year_label.text.strip
249
+
250
+ year_input = assert_select("input.#{@brand}-input.#{@brand}-date-input__input.#{@brand}-input--width-4").first
251
+ assert_equal 'assistant_date_of_birth_1i', year_input['id']
252
+ assert_equal 'assistant[date_of_birth(1i)]', year_input['name']
253
+ assert_equal 'text', year_input['type']
254
+ assert_equal 'numeric', year_input['inputmode']
255
+ end
256
+ end
257
+ end
258
+ end
259
+
260
+ test 'ds_date_field with custom legend size' do
261
+ @output_buffer = ds_form_with(model: assistants(:one), builder: @builder) do |f|
262
+ f.ds_date_field(:date_of_birth, legend: { size: nil })
263
+ end
264
+
265
+ assert_form_group do
266
+ assert_select("legend.#{@brand}-fieldset__legend", text: 'What is your date of birth?')
267
+ end
268
+ end
269
+
270
+ test 'ds_email_field' do
271
+ @output_buffer = ds_form_with(model: assistants(:one), builder: @builder) do |f|
272
+ f.ds_email_field(:email)
273
+ end
274
+
275
+ assert_form_group do
276
+ assert_label :email, nil, 'What is your email?'
277
+ assert_input :email, type: :email, value: 'one@ex.com'
278
+ end
279
+ end
280
+
281
+ test 'ds_email_field with hint' do
282
+ @output_buffer = ds_form_with(model: assistants(:one), builder: @builder) do |f|
283
+ f.ds_email_field(:email, hint: 'This is a hint')
284
+ end
285
+
286
+ assert_form_group do
287
+ assert_label :email, nil, 'What is your email?'
288
+ assert_hint :email, nil, 'This is a hint'
289
+ assert_input :email, type: :email, value: 'one@ex.com',
290
+ attributes: { 'aria-describedby' => 'assistant_email_hint' }
291
+ end
292
+ end
293
+
294
+ test 'ds_email_field with options' do
295
+ @output_buffer = ds_form_with(model: assistants(:one), builder: @builder) do |f|
296
+ f.ds_email_field(:email, class: 'geoff', placeholder: 'bar')
297
+ end
298
+
299
+ assert_form_group do
300
+ assert_label :email, nil, 'What is your email?'
301
+ assert_input :email, type: :email, value: 'one@ex.com',
302
+ classes: ['geoff'],
303
+ attributes: { placeholder: 'bar' }
304
+ end
305
+ end
306
+
307
+ test 'ds_email_field with pirate locale' do
308
+ I18n.with_locale :pirate do
309
+ @output_buffer = ds_form_with(model: assistants(:one), builder: @builder) do |f|
310
+ f.ds_email_field(:email)
311
+ end
312
+
313
+ assert_form_group do
314
+ assert_label :email, nil, 'Email, yarr'
315
+ end
316
+ end
317
+ end
318
+
319
+ test 'ds_error_summary' do
320
+ assistant = Assistant.new(
321
+ title: '',
322
+ department_id: nil,
323
+ password: assistants(:one).password,
324
+ date_of_birth: assistants(:one).date_of_birth,
325
+ phone: assistants(:one).phone
326
+ )
327
+ assistant.valid?
328
+
329
+ @output_buffer = ds_form_with(model: assistant, builder: @builder) do |f|
330
+ f.ds_error_summary
331
+ end
332
+
333
+ assert_select("div.#{@brand}-error-summary[data-module='#{@brand}-error-summary']") do
334
+ assert_select("div[role='alert']") do
335
+ assert_select("h2.#{@brand}-error-summary__title", 'There is a problem')
336
+ assert_select("div.#{@brand}-error-summary__body") do
337
+ assert_select("ul.#{@brand}-list.#{@brand}-error-summary__list") do
338
+ assert_select('li') do
339
+ assert_select("a[href='#assistant_title_error']", 'Enter a title')
340
+ end
341
+ assert_select('li') do
342
+ assert_select("a[href='#assistant_department_id_error']", 'Select a department')
343
+ end
344
+ end
345
+ end
346
+ end
347
+ end
348
+ end
349
+
350
+ test 'ds_error_summary with title' do
351
+ assistant = Assistant.new(
352
+ title: '',
353
+ department_id: nil,
354
+ password: assistants(:one).password,
355
+ date_of_birth: assistants(:one).date_of_birth,
356
+ phone: assistants(:one).phone
357
+ )
358
+ assistant.valid?
359
+
360
+ @output_buffer = ds_form_with(model: assistant, builder: @builder) do |f|
361
+ f.ds_error_summary('Oops')
362
+ end
363
+
364
+ assert_select("div.#{@brand}-error-summary") do
365
+ assert_select("h2.#{@brand}-error-summary__title", 'Oops')
366
+ assert_select("div.#{@brand}-error-summary__body") do
367
+ assert_select("ul.#{@brand}-list.#{@brand}-error-summary__list") do
368
+ assert_select('li') do
369
+ assert_select("a[href='#assistant_title_error']", 'Enter a title')
370
+ end
371
+ assert_select('li') do
372
+ assert_select("a[href='#assistant_department_id_error']", 'Select a department')
373
+ end
374
+ end
375
+ end
376
+ end
377
+ end
378
+
379
+ test 'ds_error_summary with options' do
380
+ assistant = Assistant.new(
381
+ title: assistants(:one).title,
382
+ department_id: assistants(:one).department_id,
383
+ password: assistants(:one).password,
384
+ date_of_birth: assistants(:one).date_of_birth,
385
+ phone: nil,
386
+ email: nil
387
+ )
388
+ assistant.valid?
389
+
390
+ @output_buffer = ds_form_with(model: assistant, builder: @builder) do |f|
391
+ f.ds_error_summary(link_base_errors_to: :email)
392
+ end
393
+
394
+ assert_select("div.#{@brand}-error-summary") do
395
+ assert_select("div[role='alert']") do
396
+ assert_select("h2.#{@brand}-error-summary__title", 'There is a problem')
397
+ assert_select("div.#{@brand}-error-summary__body") do
398
+ assert_select("ul.#{@brand}-list.#{@brand}-error-summary__list") do
399
+ assert_select('li') do
400
+ assert_select("a[href='#assistant_email']", 'Enter a telephone number or email address')
401
+ end
402
+ end
403
+ end
404
+ end
405
+ end
406
+ end
407
+
408
+ test 'ds_error_summary with html options' do
409
+ assistant = Assistant.new(
410
+ title: assistants(:one).title,
411
+ department_id: assistants(:one).department_id,
412
+ password: assistants(:one).password,
413
+ date_of_birth: assistants(:one).date_of_birth,
414
+ phone: nil,
415
+ email: nil
416
+ )
417
+ assistant.valid?
418
+
419
+ @output_buffer = ds_form_with(model: assistant, builder: @builder) do |f|
420
+ f.ds_error_summary(class: 'geoff', 'data-foo': 'bar')
421
+ end
422
+
423
+ assert_select("div.#{@brand}-error-summary.geoff[data-foo=bar]") do
424
+ assert_select("div[role='alert']") do
425
+ assert_select("h2.#{@brand}-error-summary__title", 'There is a problem')
426
+ end
427
+ end
428
+ end
429
+
430
+ test 'ds_error_summary with pirate locale' do
431
+ assistant = Assistant.new(
432
+ title: assistants(:one).title,
433
+ department_id: assistants(:one).department_id,
434
+ password: assistants(:one).password,
435
+ date_of_birth: assistants(:one).date_of_birth,
436
+ phone: nil,
437
+ email: nil
438
+ )
439
+ assistant.valid?
440
+
441
+ I18n.with_locale :pirate do
442
+ @output_buffer = ds_form_with(model: assistant, builder: @builder, &:ds_error_summary)
443
+
444
+ assert_select("div.#{@brand}-error-summary") do
445
+ assert_select("div[role='alert']") do
446
+ assert_select("h2.#{@brand}-error-summary__title", 'There is a problem, yarr')
447
+ end
448
+ end
449
+ end
450
+ end
451
+
452
+ # NOTE: We test the file field without ActiveStorage to keep the design system lightweight.
453
+ # We only test the HTML structure and attributes, not the actual file handling functionality.
454
+ test 'ds_file_field' do
455
+ @output_buffer = ds_form_with(model: assistants(:one), builder: @builder) do |f|
456
+ f.ds_file_field(:cv)
457
+ end
458
+
459
+ assert_form_group do
460
+ assert_label :cv, nil, 'Upload a file'
461
+ assert_file_upload :cv, type: :file
462
+ end
463
+ end
464
+
465
+ test 'ds_file_field with hint' do
466
+ @output_buffer = ds_form_with(model: assistants(:one), builder: @builder) do |f|
467
+ f.ds_file_field(:cv, hint: 'This is a hint')
468
+ end
469
+
470
+ assert_form_group do
471
+ assert_label :cv, nil, 'Upload a file'
472
+ assert_hint :cv, nil, 'This is a hint'
473
+ assert_file_upload :cv, type: :file, attributes: { 'aria-describedby' => 'assistant_cv_hint' }
474
+ end
475
+ end
476
+
477
+ test 'ds_label' do
478
+ @output_buffer = ds_form_with(model: assistants(:one), builder: @builder) do |f|
479
+ f.ds_label(:title)
480
+ end
481
+
482
+ assert_select('form') do
483
+ assert_label :title, nil, 'Title'
484
+ end
485
+ end
486
+
487
+ test 'ds_label with content and options' do
488
+ @output_buffer = ds_form_with(model: assistants(:one), builder: @builder) do |f|
489
+ f.ds_label(:title, 'Titlezzz', class: 'bob', 'data-foo': 'bar')
490
+ end
491
+
492
+ assert_select('form') do
493
+ assert_select("label.#{@brand}-label[data-foo=bar]", 'Titlezzz')
494
+ end
495
+ end
496
+
497
+ test 'ds_label with pirate locale' do
498
+ I18n.with_locale :pirate do
499
+ @output_buffer = ds_form_with(model: assistants(:one), builder: @builder) do |f|
500
+ f.ds_label(:title)
501
+ end
502
+
503
+ assert_select('form') do
504
+ assert_label :title, nil, 'Title, yarr'
505
+ end
506
+ end
507
+ end
508
+
509
+ test 'ds_number_field' do
510
+ @output_buffer = ds_form_with(model: assistants(:one), builder: @builder) do |f|
511
+ f.ds_number_field(:age)
512
+ end
513
+
514
+ assert_form_group do
515
+ assert_label :age, nil, 'What is your age?'
516
+ assert_input :age, type: :number, value: '30'
517
+ end
518
+ end
519
+
520
+ test 'ds_number_field with hint' do
521
+ @output_buffer = ds_form_with(model: assistants(:one), builder: @builder) do |f|
522
+ f.ds_number_field(:age, hint: 'This is a hint')
523
+ end
524
+
525
+ assert_form_group do
526
+ assert_label :age, nil, 'What is your age?'
527
+ assert_hint :age, nil, 'This is a hint'
528
+ assert_input :age, type: :number, value: '30',
529
+ attributes: { 'aria-describedby' => 'assistant_age_hint' }
530
+ end
531
+ end
532
+
533
+ test 'ds_number_field with options' do
534
+ @output_buffer = ds_form_with(model: assistants(:one), builder: @builder) do |f|
535
+ f.ds_number_field(:age, class: 'geoff', placeholder: 'bar')
536
+ end
537
+
538
+ assert_form_group do
539
+ assert_label :age, nil, 'What is your age?'
540
+ assert_input :age, type: :number, value: '30',
541
+ classes: ['geoff'],
542
+ attributes: { placeholder: 'bar' }
543
+ end
544
+ end
545
+
546
+ test 'ds_number_field with pirate locale' do
547
+ I18n.with_locale :pirate do
548
+ @output_buffer = ds_form_with(model: assistants(:one), builder: @builder) do |f|
549
+ f.ds_number_field(:age)
550
+ end
551
+
552
+ assert_form_group do
553
+ assert_label :age, nil, 'Age, yarr'
554
+ end
555
+ end
556
+ end
557
+
558
+ test 'ds_phone_field' do
559
+ @output_buffer = ds_form_with(model: assistants(:one), builder: @builder) do |f|
560
+ f.ds_phone_field(:phone)
561
+ end
562
+
563
+ assert_form_group do
564
+ assert_label :phone, nil, 'What is your phone number?'
565
+ assert_input :phone, type: :tel, value: '07700900001'
566
+ end
567
+ end
568
+
569
+ test 'ds_phone_field with hint' do
570
+ @output_buffer = ds_form_with(model: assistants(:one), builder: @builder) do |f|
571
+ f.ds_phone_field(:phone, hint: 'This is a hint')
572
+ end
573
+
574
+ assert_form_group do
575
+ assert_label :phone, nil, 'What is your phone number?'
576
+ assert_hint :phone, nil, 'This is a hint'
577
+ assert_input :phone, type: :tel, value: '07700900001', attributes: { 'aria-describedby' => 'assistant_phone_hint' }
578
+ end
579
+ end
580
+
581
+ test 'ds_phone_field with options' do
582
+ @output_buffer = ds_form_with(model: assistants(:one), builder: @builder) do |f|
583
+ f.ds_phone_field(:phone, class: 'geoff', placeholder: 'bar', width: 20)
584
+ end
585
+
586
+ assert_form_group do
587
+ assert_label :phone, nil, 'What is your phone number?'
588
+ assert_input :phone, type: :tel, value: '07700900001',
589
+ classes: ["#{@brand}-input--width-20", 'geoff'],
590
+ attributes: { placeholder: 'bar' }
591
+ end
592
+ end
593
+
594
+ test 'ds_phone_field with pirate locale' do
595
+ I18n.with_locale :pirate do
596
+ @output_buffer = ds_form_with(model: assistants(:one), builder: @builder) do |f|
597
+ f.ds_phone_field(:phone)
598
+ end
599
+
600
+ assert_form_group do
601
+ assert_label :phone, nil, 'Phone, yarr'
602
+ end
603
+ end
604
+ end
605
+
606
+ test 'ds_radio_button' do
607
+ @output_buffer = ds_form_with(model: assistants(:one), builder: @builder) do |f|
608
+ f.ds_radio_buttons_fieldset(:desired_filling) do
609
+ f.ds_radio_button(:desired_filling, :pastrami) +
610
+ f.ds_radio_button(:desired_filling, :cheddar)
611
+ end
612
+ end
613
+
614
+ assert_form_group do
615
+ assert_select("fieldset.#{@brand}-fieldset") do
616
+ legend = assert_select("legend.#{@brand}-fieldset__legend").first
617
+ assert_equal 'What do you want in your sandwich?', legend.text.strip
618
+
619
+ assert_select("div.#{@brand}-radios[data-module='#{@brand}-radios']") do
620
+ assert_select("div.#{@brand}-radios__item:nth-child(1)") do
621
+ input = assert_select("input.#{@brand}-radios__input").first
622
+ assert_equal 'assistant_desired_filling_pastrami', input['id']
623
+ assert_equal 'assistant[desired_filling]', input['name']
624
+ assert_equal 'pastrami', input['value']
625
+ assert_equal 'radio', input['type']
626
+
627
+ assert_label :desired_filling, 'pastrami', classes: ["#{@brand}-radios__label"]
628
+ end
629
+
630
+ assert_select("div.#{@brand}-radios__item:nth-child(2)") do
631
+ input = assert_select("input.#{@brand}-radios__input").first
632
+ assert_equal 'assistant_desired_filling_cheddar', input['id']
633
+ assert_equal 'assistant[desired_filling]', input['name']
634
+ assert_equal 'cheddar', input['value']
635
+ assert_equal 'radio', input['type']
636
+
637
+ assert_label :desired_filling, 'cheddar', classes: ["#{@brand}-radios__label"]
638
+ end
639
+ end
640
+ end
641
+ end
642
+ end
643
+
644
+ test 'ds_radio_button with hint' do
645
+ @output_buffer = ds_form_with(model: assistants(:one), builder: @builder) do |f|
646
+ f.ds_radio_buttons_fieldset(:desired_filling, hint: 'This is a hint') do
647
+ f.ds_radio_button(:desired_filling, :pastrami, hint: 'Brined, smoked, steamed and seasoned') +
648
+ f.ds_radio_button(:desired_filling, :cheddar, hint: 'A sharp, off-white natural cheese')
649
+ end
650
+ end
651
+
652
+ assert_form_group do
653
+ assert_select("fieldset.#{@brand}-fieldset") do
654
+ legend = assert_select("legend.#{@brand}-fieldset__legend").first
655
+ assert_equal 'What do you want in your sandwich?', legend.text.strip
656
+
657
+ assert_hint :desired_filling, nil, 'This is a hint'
658
+
659
+ assert_select("div.#{@brand}-radios[data-module='#{@brand}-radios']") do
660
+ assert_select("div.#{@brand}-radios__item:nth-child(1)") do
661
+ input = assert_select("input.#{@brand}-radios__input").first
662
+ assert_equal 'assistant_desired_filling_pastrami', input['id']
663
+ assert_equal 'assistant[desired_filling]', input['name']
664
+ assert_equal 'pastrami', input['value']
665
+ assert_equal 'radio', input['type']
666
+
667
+ assert_label :desired_filling, 'pastrami', classes: ["#{@brand}-radios__label"]
668
+
669
+ assert_hint :desired_filling, 'pastrami', 'Brined, smoked, steamed and seasoned', classes: ["#{@brand}-radios__hint"]
670
+ end
671
+
672
+ assert_select("div.#{@brand}-radios__item:nth-child(2)") do
673
+ input = assert_select("input.#{@brand}-radios__input").first
674
+ assert_equal 'assistant_desired_filling_cheddar', input['id']
675
+ assert_equal 'assistant[desired_filling]', input['name']
676
+ assert_equal 'cheddar', input['value']
677
+ assert_equal 'radio', input['type']
678
+
679
+ assert_label :desired_filling, 'cheddar', classes: ["#{@brand}-radios__label"]
680
+
681
+ assert_hint :desired_filling, 'cheddar', 'A sharp, off-white natural cheese', classes: ["#{@brand}-radios__hint"]
682
+ end
683
+ end
684
+ end
685
+ end
686
+ end
687
+
688
+ test 'ds_radio_buttons_fieldset with option inline' do
689
+ @output_buffer = ds_form_with(model: assistants(:one), builder: @builder) do |f|
690
+ f.ds_radio_buttons_fieldset(:desired_filling, inline: true) do
691
+ f.ds_radio_button(:desired_filling, :pastrami) +
692
+ f.ds_radio_button(:desired_filling, :cheddar)
693
+ end
694
+ end
695
+
696
+ assert_form_group do
697
+ assert_select("fieldset.#{@brand}-fieldset") do
698
+ legend = assert_select("legend.#{@brand}-fieldset__legend").first
699
+ assert_equal 'What do you want in your sandwich?', legend.text.strip
700
+
701
+ assert_select("div.#{@brand}-radios.#{@brand}-radios--inline[data-module='#{@brand}-radios']") do
702
+ assert_select("div.#{@brand}-radios__item:nth-child(1)") do
703
+ assert_select("input.#{@brand}-radios__input")
704
+ assert_select("label.#{@brand}-label.#{@brand}-radios__label", 'Pastrami')
705
+ end
706
+
707
+ assert_select("div.#{@brand}-radios__item:nth-child(2)") do
708
+ assert_select("input.#{@brand}-radios__input")
709
+ assert_select("label.#{@brand}-label.#{@brand}-radios__label", 'Cheddar')
710
+ end
711
+ end
712
+ end
713
+ end
714
+ end
715
+
716
+ test 'ds_radio_buttons_fieldset with html options' do
717
+ @output_buffer = ds_form_with(model: assistants(:one), builder: @builder) do |f|
718
+ f.ds_radio_buttons_fieldset(:desired_filling, class: 'geoff', 'data-foo': 'bar') do
719
+ f.ds_radio_button(:desired_filling, :pastrami) +
720
+ f.ds_radio_button(:desired_filling, :cheddar)
721
+ end
722
+ end
723
+
724
+ assert_form_group do
725
+ assert_select("fieldset.#{@brand}-fieldset") do
726
+ legend = assert_select("legend.#{@brand}-fieldset__legend").first
727
+ assert_equal 'What do you want in your sandwich?', legend.text.strip
728
+
729
+ assert_select("div.#{@brand}-radios.geoff[data-foo=bar][data-module='#{@brand}-radios']") do
730
+ assert_select("div.#{@brand}-radios__item:nth-child(1)") do
731
+ assert_select("input.#{@brand}-radios__input")
732
+ assert_select("label.#{@brand}-label.#{@brand}-radios__label", 'Pastrami')
733
+ end
734
+ end
735
+ end
736
+ end
737
+ end
738
+
739
+ test 'ds_collection_radio_buttons with hint' do
740
+ @output_buffer = ds_form_with(model: assistants(:one), builder: @builder) do |f|
741
+ f.ds_collection_radio_buttons(:department_id, Department.all, :id, :title, hint: 'This is a hint')
742
+ end
743
+
744
+ assert_form_group do
745
+ assert_select("fieldset.#{@brand}-fieldset") do
746
+ legend = assert_select("legend.#{@brand}-fieldset__legend").first
747
+ assert_equal 'What is your department?', legend.text.strip
748
+
749
+ assert_hint :department_id, nil, 'This is a hint'
750
+
751
+ assert_select("div.#{@brand}-radios") do
752
+ radio_items = assert_select("div.#{@brand}-radios__item")
753
+ assert_equal 5, radio_items.length, 'Expected 3 radio items'
754
+ end
755
+
756
+ assert_select("div.#{@brand}-radios__item:nth-child(1)") do
757
+ radio_1 = assert_select("input.#{@brand}-radios__input").first
758
+ assert_equal 'assistant_department_id_1', radio_1['id']
759
+ assert_equal 'assistant[department_id]', radio_1['name']
760
+ assert_equal 'radio', radio_1['type']
761
+ assert_equal '1', radio_1['value']
762
+
763
+ assert_label :department_id, '1', 'Sales', classes: ["#{@brand}-radios__label"]
764
+ end
765
+
766
+ assert_select("div.#{@brand}-radios__item:nth-child(2)") do
767
+ radio_2 = assert_select("input.#{@brand}-radios__input").first
768
+ assert_equal 'assistant_department_id_2', radio_2['id']
769
+ assert_equal 'assistant[department_id]', radio_2['name']
770
+ assert_equal 'radio', radio_2['type']
771
+ assert_equal '2', radio_2['value']
772
+
773
+ assert_label :department_id, '2', 'Marketing', classes: ["#{@brand}-radios__label"]
774
+ end
775
+
776
+ assert_select("div.#{@brand}-radios__item:nth-child(3)") do
777
+ radio_3 = assert_select("input.#{@brand}-radios__input").first
778
+ assert_equal 'assistant_department_id_3', radio_3['id']
779
+ assert_equal 'assistant[department_id]', radio_3['name']
780
+ assert_equal 'radio', radio_3['type']
781
+ assert_equal '3', radio_3['value']
782
+
783
+ assert_label :department_id, '3', 'Finance', classes: ["#{@brand}-radios__label"]
784
+ end
785
+
786
+ assert_select("div.#{@brand}-radios__item:nth-child(4)") do
787
+ radio_4 = assert_select("input.#{@brand}-radios__input").first
788
+ assert_equal 'assistant_department_id_4', radio_4['id']
789
+ assert_equal 'assistant[department_id]', radio_4['name']
790
+ assert_equal 'radio', radio_4['type']
791
+ assert_equal '4', radio_4['value']
792
+
793
+ assert_label :department_id, '4', 'Operations', classes: ["#{@brand}-radios__label"]
794
+ end
795
+
796
+ assert_select("div.#{@brand}-radios__item:nth-child(5)") do
797
+ radio_5 = assert_select("input.#{@brand}-radios__input").first
798
+ assert_equal 'assistant_department_id_5', radio_5['id']
799
+ assert_equal 'assistant[department_id]', radio_5['name']
800
+ assert_equal 'radio', radio_5['type']
801
+ assert_equal '5', radio_5['value']
802
+
803
+ assert_label :department_id, '5', 'Personnel', classes: ["#{@brand}-radios__label"]
804
+ end
805
+ end
806
+ end
807
+ end
808
+
809
+ test 'ds_collection_radio_buttons with html options' do
810
+ @output_buffer = ds_form_with(model: assistants(:one), builder: @builder) do |f|
811
+ f.ds_collection_radio_buttons(:department_id, Department.all, :id, :title, {}, { class: 'geoff', placeholder: 'bar' })
812
+ end
813
+
814
+ assert_form_group do
815
+ assert_select("div.#{@brand}-radios.geoff[placeholder=bar]") do
816
+ assert_select("div.#{@brand}-radios__item") do
817
+ radio_1 = assert_select("input.#{@brand}-radios__input").first
818
+ assert_equal 'assistant_department_id_1', radio_1['id']
819
+ assert_equal 'assistant[department_id]', radio_1['name']
820
+ assert_equal 'radio', radio_1['type']
821
+ assert_equal '1', radio_1['value']
822
+
823
+ assert_label :department_id, '1', 'Sales', classes: ["#{@brand}-radios__label"]
824
+ end
825
+ end
826
+ end
827
+ end
828
+
829
+ test 'ds_collection_radio_buttons with block' do
830
+ @output_buffer = ds_form_with(model: assistants(:one), builder: @builder) do |f|
831
+ f.ds_collection_radio_buttons(:department_id, Department.all, :id, :title) do
832
+ content_tag(:p, 'Hello')
833
+ end
834
+ end
835
+
836
+ assert_form_group do
837
+ assert_select("fieldset.#{@brand}-fieldset") do
838
+ assert_select('p', 'Hello')
839
+ end
840
+ end
841
+ end
842
+
843
+ test 'ds_select with options (hint and label)' do
844
+ @output_buffer = ds_form_with(model: assistants(:one), builder: @builder) do |f|
845
+ f.ds_select(:department_id,
846
+ options_for_select(Department.all.map { |department| [department.title, department.id] }),
847
+ hint: 'This is a hint', label: { size: 'l' })
848
+ end
849
+
850
+ assert_form_group do
851
+ assert_hint :department_id, nil, 'This is a hint'
852
+
853
+ select = assert_select("select.#{@brand}-select").first
854
+ assert_equal 'assistant_department_id_hint', select['aria-describedby']
855
+ assert_select("label.#{@brand}-label.#{@brand}-label--l", text: 'What is your department?')
856
+ end
857
+ end
858
+
859
+ test 'ds_select with html options' do
860
+ @output_buffer = ds_form_with(model: assistants(:one), builder: @builder) do |f|
861
+ f.ds_select(:department_id, options_for_select(Department.all.map { |department| [department.title, department.id] }), {}, { class: 'geoff', placeholder: 'bar' })
862
+ end
863
+
864
+ assert_form_group do
865
+ assert_label :department_id, nil, 'What is your department?'
866
+ assert_select("select.#{@brand}-select.geoff[placeholder=bar]")
867
+ end
868
+ end
869
+
870
+ test 'ds_select without choices' do
871
+ @output_buffer = ds_form_with(model: assistants(:one), builder: @builder) do |f|
872
+ f.ds_select(:department_id, { hint: 'This is a hint' }, { class: 'geoff', placeholder: 'bar' })
873
+ end
874
+
875
+ assert_form_group do
876
+ assert_hint :department_id, nil, 'This is a hint'
877
+ assert_select("select.#{@brand}-select.geoff[placeholder='bar']") do
878
+ assert_select 'option', count: 0
879
+ end
880
+ end
881
+ end
882
+
883
+ test 'ds_select with locale' do
884
+ I18n.with_locale :pirate do
885
+ @output_buffer = ds_form_with(model: assistants(:one), builder: @builder) do |f|
886
+ f.ds_select(:department_id, options_for_select(Department.all.map { |department| [department.title, department.id] }))
887
+ end
888
+ end
889
+
890
+ assert_form_group do
891
+ assert_label :department_id, nil, 'Department, yarr'
892
+ end
893
+ end
894
+
895
+ test 'ds_select with block' do
896
+ @output_buffer = ds_form_with(model: assistants(:one), builder: @builder) do |f|
897
+ f.ds_select(:department_id) do
898
+ options_for_select(Department.all.map { |department| [department.title, department.id] })
899
+ end
900
+ end
901
+
902
+ assert_form_group do
903
+ assert_label :department_id, nil, 'What is your department?'
904
+
905
+ select = assert_select("select.#{@brand}-select").first
906
+ assert_equal 'assistant_department_id', select['id']
907
+ assert_equal 'assistant[department_id]', select['name']
908
+
909
+ options = assert_select('option')
910
+ assert_equal '1', options[0]['value']
911
+ assert_equal 'Sales', options[0].text.strip
912
+ assert_equal '2', options[1]['value']
913
+ assert_equal 'Marketing', options[1].text.strip
914
+ assert_equal '3', options[2]['value']
915
+ assert_equal 'Finance', options[2].text.strip
916
+ end
917
+ end
918
+
919
+ test 'ds_submit' do
920
+ @output_buffer = ds_form_with(model: assistants(:one), builder: @builder, &:ds_submit)
921
+
922
+ assert_select('form') do
923
+ button = assert_select("button.#{@brand}-button[type=submit]").first
924
+ assert_equal 'formnovalidate', button['formnovalidate']
925
+ assert_equal "#{@brand}-button", button['data-module']
926
+ assert_equal 'true', button['data-prevent-double-click']
927
+ assert_equal 'Continue', button.text.strip
928
+ end
929
+ end
930
+
931
+ test 'ds_submit with secondary' do
932
+ @output_buffer = ds_form_with(model: assistants(:one), builder: @builder) do |f|
933
+ f.ds_submit('Draft', type: :secondary)
934
+ end
935
+
936
+ assert_select('form') do
937
+ button = assert_select("button.#{@brand}-button.#{@brand}-button--secondary[type=submit]").first
938
+ assert_equal 'formnovalidate', button['formnovalidate']
939
+ assert_equal "#{@brand}-button", button['data-module']
940
+ assert_equal 'true', button['data-prevent-double-click']
941
+ assert_equal 'Draft', button.text.strip
942
+ end
943
+ end
944
+
945
+ test 'ds_submit with warning' do
946
+ @output_buffer = ds_form_with(model: assistants(:one), builder: @builder) do |f|
947
+ f.ds_submit('Warning', type: :warning)
948
+ end
949
+
950
+ assert_select('form') do
951
+ button = assert_select("button.#{@brand}-button.#{@brand}-button--warning[type=submit]").first
952
+ assert_equal 'formnovalidate', button['formnovalidate']
953
+ assert_equal "#{@brand}-button", button['data-module']
954
+ end
955
+ end
956
+
957
+ test 'ds_submit with disabled' do
958
+ @output_buffer = ds_form_with(model: assistants(:one), builder: @builder) do |f|
959
+ f.ds_submit('Disabled', type: :secondary, disabled: true)
960
+ end
961
+
962
+ assert_select('form') do
963
+ button = assert_select("button.#{@brand}-button[type=submit]").first
964
+ assert_equal 'disabled', button['disabled']
965
+ end
966
+ end
967
+
968
+ test 'ds_text_area' do
969
+ @output_buffer = ds_form_with(model: assistants(:one), builder: @builder) do |f|
970
+ f.ds_text_area(:description)
971
+ end
972
+
973
+ assert_form_group do
974
+ assert_label :description, nil, 'Enter description'
975
+ assert_text_area :description
976
+ end
977
+ end
978
+
979
+ test 'ds_text_area with hint' do
980
+ @output_buffer = ds_form_with(model: assistants(:one), builder: @builder) do |f|
981
+ f.ds_text_area(:description, hint: 'This is a hint')
982
+ end
983
+
984
+ assert_form_group do
985
+ assert_label :description, nil, 'Enter description'
986
+ assert_hint :description, nil, 'This is a hint'
987
+ assert_text_area :description,
988
+ attributes: { 'aria-describedby' => 'assistant_description_hint' }
989
+ end
990
+ end
991
+
992
+ test 'ds_text_area with options' do
993
+ @output_buffer = ds_form_with(model: assistants(:one), builder: @builder) do |f|
994
+ f.ds_text_area(:description, class: 'geoff', placeholder: 'bar', rows: 2, max_words: 20)
995
+ end
996
+
997
+ assert_form_group(["#{@brand}-character-count[data-module='#{@brand}-character-count'][data-maxwords='20']"]) do
998
+ assert_label :description, nil, 'Enter description'
999
+ assert_text_area :description,
1000
+ classes: ['geoff'],
1001
+ attributes: { placeholder: 'bar', rows: 2, 'aria-describedby' => 'assistant_description-info' }
1002
+
1003
+ info = assert_select("span.#{@brand}-hint.#{@brand}-character-count__message").first
1004
+ assert_includes info.text.strip, '20 words'
1005
+ assert_equal 'assistant_description-info', info['id']
1006
+ end
1007
+ end
1008
+
1009
+ test 'ds_text_area with pirate locale' do
1010
+ I18n.with_locale :pirate do
1011
+ @output_buffer = ds_form_with(model: assistants(:one), builder: @builder) do |f|
1012
+ f.ds_text_area(:description)
1013
+ end
1014
+
1015
+ assert_form_group do
1016
+ assert_label :description, nil, 'Description, yarr'
1017
+ end
1018
+ end
1019
+ end
1020
+
1021
+ test 'ds_text_field' do
1022
+ @output_buffer = ds_form_with(model: assistants(:one), builder: @builder) do |f|
1023
+ f.ds_text_field(:title)
1024
+ end
1025
+
1026
+ assert_form_group do
1027
+ assert_label :title, nil, 'Title'
1028
+ assert_input :title, type: :text, value: 'Lorem ipsum dolor sit amet'
1029
+ end
1030
+ end
1031
+
1032
+ test 'ds_text_field with hint' do
1033
+ @output_buffer = ds_form_with(model: assistants(:one), builder: @builder) do |f|
1034
+ f.ds_text_field(:title, hint: 'This is a hint')
1035
+ end
1036
+
1037
+ assert_form_group do
1038
+ assert_label :title, nil, 'Title'
1039
+ assert_hint :title, nil, 'This is a hint'
1040
+ assert_input :title, type: :text, value: 'Lorem ipsum dolor sit amet', attributes: { 'aria-describedby' => 'assistant_title_hint' }
1041
+ end
1042
+ end
1043
+
1044
+ test 'ds_text_field with options' do
1045
+ @output_buffer = ds_form_with(model: assistants(:one), builder: @builder) do |f|
1046
+ f.ds_text_field(:title, class: 'geoff', placeholder: 'bar')
1047
+ end
1048
+
1049
+ assert_form_group do
1050
+ assert_label :title, nil, 'Title'
1051
+ assert_input :title, type: :text, value: 'Lorem ipsum dolor sit amet', classes: ['geoff'], attributes: { placeholder: 'bar' }
1052
+ end
1053
+ end
1054
+
1055
+ test 'ds_text_field with pirate locale' do
1056
+ I18n.with_locale :pirate do
1057
+ @output_buffer = ds_form_with(model: assistants(:one), builder: @builder) do |f|
1058
+ f.ds_text_field(:title)
1059
+ end
1060
+
1061
+ assert_form_group do
1062
+ assert_label :title, nil, 'Title, yarr'
1063
+ end
1064
+ end
1065
+ end
1066
+
1067
+ test 'ds_url_field' do
1068
+ @output_buffer = ds_form_with(model: assistants(:one), builder: @builder) do |f|
1069
+ f.ds_url_field(:website)
1070
+ end
1071
+
1072
+ assert_form_group do
1073
+ assert_label :website, nil, 'What is your website?'
1074
+ assert_input :website, type: :url, value: 'https://www.ab.com'
1075
+ end
1076
+ end
1077
+
1078
+ test 'ds_url_field with hint' do
1079
+ @output_buffer = ds_form_with(model: assistants(:one), builder: @builder) do |f|
1080
+ f.ds_url_field(:website, hint: 'This is a hint')
1081
+ end
1082
+
1083
+ assert_form_group do
1084
+ assert_label :website, nil, 'What is your website?'
1085
+ assert_hint :website, nil, 'This is a hint'
1086
+ assert_input :website, type: :url, value: 'https://www.ab.com',
1087
+ attributes: { 'aria-describedby' => 'assistant_website_hint' }
1088
+ end
1089
+ end
1090
+
1091
+ test 'ds_url_field with options' do
1092
+ @output_buffer = ds_form_with(model: assistants(:one), builder: @builder) do |f|
1093
+ f.ds_url_field(:website, class: 'geoff', placeholder: 'bar')
1094
+ end
1095
+
1096
+ assert_form_group do
1097
+ assert_label :website, nil, 'What is your website?'
1098
+ assert_input :website, type: :url, value: 'https://www.ab.com',
1099
+ classes: ['geoff'],
1100
+ attributes: { placeholder: 'bar' }
1101
+ end
1102
+ end
1103
+
1104
+ test 'ds_url_field with pirate locale' do
1105
+ I18n.with_locale :pirate do
1106
+ @output_buffer = ds_form_with(model: assistants(:one), builder: @builder) do |f|
1107
+ f.ds_url_field(:website)
1108
+ end
1109
+
1110
+ assert_form_group do
1111
+ assert_label :website, nil, 'Website, yarr'
1112
+ end
1113
+ end
1114
+ end
1115
+
1116
+ test 'suppresses inline error when suppress_error is true' do
1117
+ @assistant = Assistant.new
1118
+ assert_not @assistant.valid?
1119
+ assert @assistant.errors[:title].any?, 'Title should have errors'
1120
+
1121
+ @output_buffer = ds_form_with(model: @assistant, builder: @builder, url: '#') do |f|
1122
+ f.ds_text_field(:title, label: { text: 'Title' }, suppress_error: true)
1123
+ end
1124
+
1125
+ # Assert that the inline error message is NOT present
1126
+ assert_select_from(@output_buffer, "p.#{@brand}-error-message", count: 0)
1127
+ end
1128
+
1129
+ test 'shows inline error when suppress_error is false' do
1130
+ @assistant = Assistant.new
1131
+ assert_not @assistant.valid?
1132
+ assert @assistant.errors[:title].any?, 'Title should have errors'
1133
+
1134
+ @output_buffer = ds_form_with(model: @assistant, builder: @builder, url: '#') do |f|
1135
+ f.govuk_text_field(:title, label: { text: 'Title' }, suppress_error: false)
1136
+ end
1137
+
1138
+ # Assert that the inline error message IS present
1139
+ @assistant.errors[:title].first
1140
+ assert_select_from(@output_buffer, "p.#{@brand}-error-message", count: 1)
1141
+ end
1142
+
1143
+ test 'ds_method_name and method_name should produce equivalent elements' do
1144
+ %i[text_field email_field phone_field].each do |method_name|
1145
+ ds_output = ds_form_with(model: assistants(:one)) do |f|
1146
+ f.send("ds_#{method_name}", :title)
1147
+ end
1148
+
1149
+ rails_output = form_with(model: assistants(:one)) do |f|
1150
+ f.label(:title) + f.send(method_name, :title)
1151
+ end
1152
+
1153
+ ds_doc = Nokogiri::HTML(ds_output)
1154
+ rails_doc = Nokogiri::HTML(rails_output)
1155
+
1156
+ ds_input = ds_doc.at_css('input:not([type="hidden"])')
1157
+ rails_input = rails_doc.at_css('input:not([type="hidden"])')
1158
+
1159
+ assert_equal ds_input['id'], rails_input['id']
1160
+ assert_equal ds_input['name'], rails_input['name']
1161
+
1162
+ ds_label = ds_doc.at_css('label')
1163
+ rails_label = rails_doc.at_css('label')
1164
+
1165
+ assert_equal ds_label.text.strip, rails_label.text.strip
1166
+ end
1167
+ end
1168
+
1169
+ test 'ds_select and select should produce equivalent elements' do
1170
+ collection = Department.all.map { |d| [d.title, d.id] }
1171
+
1172
+ ds_output = ds_form_with(model: assistants(:one)) do |f|
1173
+ f.ds_select(:department_id, collection)
1174
+ end
1175
+
1176
+ rails_output = ds_form_with(model: assistants(:one)) do |f|
1177
+ f.label(:department_id) + f.select(:department_id, collection)
1178
+ end
1179
+
1180
+ ds_doc = Nokogiri::HTML(ds_output)
1181
+ rails_doc = Nokogiri::HTML(rails_output)
1182
+
1183
+ # Compare the select tags
1184
+ ds_select = ds_doc.at_css('select')
1185
+ rails_select = rails_doc.at_css('select')
1186
+ assert_equal ds_select['id'], rails_select['id']
1187
+ assert_equal ds_select['name'], rails_select['name']
1188
+
1189
+ # Compare the options
1190
+ ds_options = ds_doc.css('option').map { |o| [o['value'], o.text.strip] }
1191
+ rails_options = rails_doc.css('option').map { |o| [o['value'], o.text.strip] }
1192
+ assert_equal ds_options, rails_options
1193
+
1194
+ # Compare the labels
1195
+ ds_label = ds_doc.at_css('label')
1196
+ rails_label = rails_doc.at_css('label')
1197
+ assert_equal ds_label.text.strip, rails_label.text.strip
1198
+ end
1199
+
1200
+ test 'ds_check_box and check_box should produce equivalent elements' do
1201
+ choices = [[:pastrami, 'Pastrami'], [:cheddar, 'Cheddar']]
1202
+
1203
+ ds_output = ds_form_with(model: assistants(:one)) do |f|
1204
+ f.ds_check_boxes_fieldset(:desired_filling) do
1205
+ choices.map { |value, _text| f.ds_check_box(:desired_filling, {}, value) }.join.html_safe
1206
+ end
1207
+ end
1208
+
1209
+ rails_output = ds_form_with(model: assistants(:one)) do |f|
1210
+ choices.map do |value, text|
1211
+ f.check_box(:desired_filling, { multiple: true }, value, '') + f.label(:desired_filling, text, value: value)
1212
+ end.join.html_safe
1213
+ end
1214
+
1215
+ ds_doc = Nokogiri::HTML(ds_output)
1216
+ rails_doc = Nokogiri::HTML(rails_output)
1217
+
1218
+ # Compare the checkboxes
1219
+ ds_checkboxes = ds_doc.css('input[type=checkbox]')
1220
+ rails_checkboxes = rails_doc.css('input[type=checkbox]')
1221
+
1222
+ assert_equal ds_checkboxes.size, rails_checkboxes.size
1223
+
1224
+ ds_checkboxes.each_with_index do |ds_checkbox, i|
1225
+ rails_checkbox = rails_checkboxes[i]
1226
+ assert_equal ds_checkbox['id'], rails_checkbox['id']
1227
+ assert_equal ds_checkbox['name'], rails_checkbox['name']
1228
+ assert_equal ds_checkbox['value'], rails_checkbox['value']
1229
+ end
1230
+
1231
+ # Compare the labels
1232
+ ds_labels = ds_doc.css('label')
1233
+ rails_labels = rails_doc.css('label')
1234
+
1235
+ assert_equal ds_labels.size, rails_labels.size
1236
+
1237
+ ds_labels.each_with_index do |ds_label, i|
1238
+ rails_label = rails_labels[i]
1239
+ assert_equal ds_label['for'], rails_label['for']
1240
+ # We have stopped default humanize behaviour in DS labels for options in checkbox
1241
+ assert_equal ds_label.text.humanize.strip, rails_label.text.strip
1242
+ end
1243
+ end
1244
+
1245
+ test 'ds_radio_button and radio_button should produce equivalent elements' do
1246
+ choices = [[:pastrami, 'Pastrami'], [:cheddar, 'Cheddar']]
1247
+
1248
+ ds_output = ds_form_with(model: assistants(:one)) do |f|
1249
+ f.ds_radio_buttons_fieldset(:desired_filling) do
1250
+ choices.map { |value, _text| f.ds_radio_button(:desired_filling, value, {}) }.join.html_safe
1251
+ end
1252
+ end
1253
+
1254
+ rails_output = ds_form_with(model: assistants(:one)) do |f|
1255
+ choices.map do |value, text|
1256
+ f.radio_button(:desired_filling, value) + f.label(:desired_filling, text, value: value)
1257
+ end.join.html_safe
1258
+ end
1259
+
1260
+ ds_doc = Nokogiri::HTML(ds_output)
1261
+ rails_doc = Nokogiri::HTML(rails_output)
1262
+
1263
+ # Compare the radio buttons
1264
+ ds_radios = ds_doc.css('input[type=radio]')
1265
+ rails_radios = rails_doc.css('input[type=radio]')
1266
+
1267
+ assert_equal ds_radios.size, rails_radios.size, 'Should have the same number of radio buttons'
1268
+
1269
+ ds_radios.each_with_index do |ds_radio, i|
1270
+ rails_radio = rails_radios[i]
1271
+ assert_equal ds_radio['id'], rails_radio['id']
1272
+ assert_equal ds_radio['name'], rails_radio['name']
1273
+ assert_equal ds_radio['value'], rails_radio['value']
1274
+ end
1275
+
1276
+ # Compare the labels
1277
+ ds_labels = ds_doc.css('label')
1278
+ rails_labels = rails_doc.css('label')
1279
+
1280
+ assert_equal ds_labels.size, rails_labels.size, 'Should have the same number of labels'
1281
+
1282
+ ds_labels.each_with_index do |ds_label, i|
1283
+ rails_label = rails_labels[i]
1284
+ assert_equal ds_label['for'], rails_label['for']
1285
+ assert_equal ds_label.text.strip, rails_label.text.strip
1286
+ end
1287
+ end
1288
+
1289
+ private
1290
+
1291
+ # Helper to use assert_select on a string of HTML output
1292
+ def assert_select_from(html_output, ...)
1293
+ parsed_html = Nokogiri::HTML::DocumentFragment.parse(html_output)
1294
+ assert_select(parsed_html, ...)
1295
+ end
1296
+ end
1297
+ end
1298
+ end
1299
+ end
1300
+ end