demarches-normaliennes/spec/views/shared/dossiers/_edit.html.haml_spec.rb
Pierre de La Morinerie 0800bf68d0 views: allow unselecting all values from a multiple dropdown
Currently, deselecting all values from a multiple dropdown rendered as
checkboxes doesn't have any effect when submitting the form (the
previous values are still there, instead of being deselected).

This is because unchecked checkboxes are not sent by the browser – so
the "empty selection" never gets sent.

Rails `form.check_box` usually works around this by inserting an empty
hidden checkbox element, that will be sent even if all others are
de-selected. But the documentation warns that this is not possible when
iterating over an array (rather than a model). Which is our case here.

To fix this, this commit uses `collection_check_boxes` instead. It will
insert the proper hidden checkboxes in all cases, and fix our use case.

See https://api.rubyonrails.org/classes/ActionView/Helpers/FormOptionsHelper.html#method-i-collection_check_boxes
2020-08-27 11:13:40 +02:00

104 lines
4.3 KiB
Ruby

describe 'shared/dossiers/edit.html.haml', type: :view do
before do
allow(controller).to receive(:current_user).and_return(dossier.user)
end
subject { render 'shared/dossiers/edit.html.haml', dossier: dossier, apercu: false }
context 'when there are some champs' do
let(:dossier) { create(:dossier) }
let(:champ_checkbox) { create(:champ_checkbox, dossier: dossier, value: 'on') }
let(:champ_header_section) { create(:champ_header_section, dossier: dossier, value: 'Section') }
let(:champ_explication) { create(:champ_explication, dossier: dossier, value: 'mazette') }
let(:champ_dossier_link) { create(:champ_dossier_link, dossier: dossier, value: dossier.id) }
let(:champ_textarea) { create(:champ_textarea, dossier: dossier, value: 'Some long text in a textarea.') }
let(:champs) { [champ_checkbox, champ_header_section, champ_explication, champ_dossier_link, champ_textarea] }
before { dossier.champs << champs }
it 'renders labels and editable values of champs' do
expect(subject).to have_field(champ_checkbox.libelle, checked: true)
expect(subject).to have_css(".header-section", text: champ_header_section.libelle)
expect(subject).to have_text(champ_explication.libelle)
expect(subject).to have_field(champ_dossier_link.libelle, with: champ_dossier_link.value)
expect(subject).to have_field(champ_textarea.libelle, with: champ_textarea.value)
end
end
context 'with a single-value list' do
let(:dossier) { create(:dossier) }
let(:type_de_champ) { create(:type_de_champ_drop_down_list, mandatory: mandatory, procedure: dossier.procedure) }
let(:champ) { create(:champ_drop_down_list, dossier: dossier, type_de_champ: type_de_champ) }
let(:options) { type_de_champ.drop_down_list_options }
let(:enabled_options) { type_de_champ.drop_down_list_enabled_non_empty_options }
let(:mandatory) { true }
before { dossier.champs << champ }
context 'when the list is short' do
it 'renders the list as radio buttons' do
expect(subject).to have_selector('input[type=radio]', count: enabled_options.count)
end
context 'when the champ is optional' do
let(:mandatory) { false }
it 'allows unselecting a previously selected value' do
expect(subject).to have_selector('input[type=radio]', count: enabled_options.count + 1)
expect(subject).to have_unchecked_field('Non renseigné', count: 1)
end
end
end
context 'when the list is long' do
let(:type_de_champ) { create(:type_de_champ_drop_down_list, :long, procedure: dossier.procedure) }
it 'renders the list as a dropdown' do
expect(subject).to have_select(type_de_champ.libelle, options: options)
end
end
end
context 'with a multiple-values list' do
let(:dossier) { create(:dossier) }
let(:type_de_champ) { create(:type_de_champ_multiple_drop_down_list, procedure: dossier.procedure) }
let(:champ) { create(:champ_multiple_drop_down_list, dossier: dossier, type_de_champ: type_de_champ) }
let(:options) { type_de_champ.drop_down_list_options }
let(:enabled_options) { type_de_champ.drop_down_list_enabled_non_empty_options }
before { dossier.champs << champ }
context 'when the list is short' do
it 'renders the list as checkboxes' do
expect(subject).to have_selector('input[type=checkbox]', count: enabled_options.count)
end
it 'adds an extra hidden input, to send a blank value even when all checkboxes are unchecked' do
expect(subject).to have_selector('input[type=hidden][value=""]')
end
end
context 'when the list is long' do
let(:type_de_champ) { create(:type_de_champ_multiple_drop_down_list, :long, procedure: dossier.procedure) }
it 'renders the list as a multiple-selection dropdown' do
expect(subject).to have_selector('select.select2')
end
end
end
context 'with a routed procedure' do
let(:procedure) do
create(:procedure,
:routee,
routing_criteria_name: 'departement')
end
let(:dossier) { create(:dossier, procedure: procedure) }
let(:champs) { [] }
it 'renders the routing criteria name and its value' do
expect(subject).to have_field(procedure.routing_criteria_name)
expect(subject).to include(dossier.groupe_instructeur.label)
end
end
end