Merge pull request #8479 from demarches-simplifiees/prefill/multiple

prefill(dossier): prefill multiple drop down list champ
This commit is contained in:
Sébastien Carceles 2023-02-16 11:02:25 +01:00 committed by GitHub
commit 8aece28f75
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
18 changed files with 152 additions and 28 deletions

View file

@ -23,6 +23,8 @@
class Champs::MultipleDropDownListChamp < Champ
before_save :format_before_save
validate :values_are_in_options, if: -> { value.present? }
def options?
drop_down_list_options?
end
@ -90,4 +92,12 @@ class Champs::MultipleDropDownListChamp < Champ
end
end
end
def values_are_in_options
json = selected_options.reject(&:blank?)
return if json.empty?
return if (json - enabled_non_empty_options).empty?
errors.add(:value, :not_in_options)
end
end

View file

@ -42,6 +42,7 @@ class PrefillParams
TypeDeChamp.type_champs.fetch(:pays),
TypeDeChamp.type_champs.fetch(:regions),
TypeDeChamp.type_champs.fetch(:departements),
TypeDeChamp.type_champs.fetch(:multiple_drop_down_list),
TypeDeChamp.type_champs.fetch(:epci)
]

View file

@ -262,13 +262,14 @@ class TypeDeChamp < ApplicationRecord
TypeDeChamp.type_champs.fetch(:iban),
TypeDeChamp.type_champs.fetch(:civilite),
TypeDeChamp.type_champs.fetch(:pays),
TypeDeChamp.type_champs.fetch(:regions),
TypeDeChamp.type_champs.fetch(:date),
TypeDeChamp.type_champs.fetch(:datetime),
TypeDeChamp.type_champs.fetch(:yes_no),
TypeDeChamp.type_champs.fetch(:checkbox),
TypeDeChamp.type_champs.fetch(:drop_down_list),
TypeDeChamp.type_champs.fetch(:regions),
TypeDeChamp.type_champs.fetch(:departements),
TypeDeChamp.type_champs.fetch(:multiple_drop_down_list),
TypeDeChamp.type_champs.fetch(:epci)
])
end

View file

@ -0,0 +1,8 @@
class TypesDeChamp::PrefillMultipleDropDownListTypeDeChamp < TypesDeChamp::PrefillDropDownListTypeDeChamp
def example_value
return nil if possible_values.empty?
return possible_values.first if possible_values.one?
[possible_values.first, possible_values.second]
end
end

View file

@ -5,6 +5,8 @@ class TypesDeChamp::PrefillTypeDeChamp < SimpleDelegator
case type_de_champ.type_champ
when TypeDeChamp.type_champs.fetch(:drop_down_list)
TypesDeChamp::PrefillDropDownListTypeDeChamp.new(type_de_champ)
when TypeDeChamp.type_champs.fetch(:multiple_drop_down_list)
TypesDeChamp::PrefillMultipleDropDownListTypeDeChamp.new(type_de_champ)
when TypeDeChamp.type_champs.fetch(:pays)
TypesDeChamp::PrefillPaysTypeDeChamp.new(type_de_champ)
when TypeDeChamp.type_champs.fetch(:regions)

View file

@ -471,6 +471,10 @@ en:
attributes:
value:
not_in_options: "must be in the given options"
"champs/multiple_drop_down_list_champ":
attributes:
value:
not_in_options: "must be in the given options"
"champs/region_champ":
attributes:
value:

View file

@ -466,6 +466,10 @@ fr:
attributes:
value:
not_in_options: "doit être dans les options proposées"
"champs/multiple_drop_down_list_champ":
attributes:
value:
not_in_options: "doit être dans les options proposées"
"champs/region_champ":
attributes:
value:

View file

@ -792,7 +792,7 @@ describe Instructeurs::DossiersController, type: :controller do
champs_private_attributes: {
'0': {
id: champ_multiple_drop_down_list.id,
value: ['', 'un', 'deux']
value: ['', 'val1', 'val2']
},
'1': {
id: champ_datetime.id,
@ -813,7 +813,7 @@ describe Instructeurs::DossiersController, type: :controller do
end
it {
expect(champ_multiple_drop_down_list.value).to eq('["un", "deux"]')
expect(champ_multiple_drop_down_list.value).to eq('["val1", "val2"]')
expect(champ_linked_drop_down_list.primary_value).to eq('primary')
expect(champ_linked_drop_down_list.secondary_value).to eq('secondary')
expect(champ_datetime.value).to eq('2019-12-21T13:17:00+01:00')
@ -839,7 +839,7 @@ describe Instructeurs::DossiersController, type: :controller do
champs_public_attributes: {
'0': {
id: champ_multiple_drop_down_list.id,
value: ['', 'un', 'deux']
value: ['', 'val1', 'val2']
}
}
}

View file

@ -97,7 +97,7 @@ FactoryBot.define do
factory :champ_multiple_drop_down_list, class: 'Champs::MultipleDropDownListChamp' do
type_de_champ { association :type_de_champ_multiple_drop_down_list, procedure: dossier.procedure }
value { '["choix 1", "choix 2"]' }
value { '["val1", "val2"]' }
end
factory :champ_linked_drop_down_list, class: 'Champs::LinkedDropDownListChamp' do

View file

@ -117,7 +117,7 @@ describe Champ do
# when using the old form, and the ChampsService Class
# TODO: to remove
context 'when the value is already deserialized' do
let(:value) { '["1", "2"]' }
let(:value) { '["val1", "val2"]' }
it { expect(champ.value).to eq(value) }
@ -133,9 +133,9 @@ describe Champ do
# GOTCHA
context 'when the value is not already deserialized' do
context 'when a choice is selected' do
let(:value) { '["", "1", "2"]' }
let(:value) { '["", "val1", "val2"]' }
it { expect(champ.value).to eq('["1", "2"]') }
it { expect(champ.value).to eq('["val1", "val2"]') }
end
context 'when all choices are removed' do

View file

@ -0,0 +1,38 @@
describe Champs::MultipleDropDownListChamp do
describe 'validations' do
describe 'inclusion' do
let(:type_de_champ) { build(:type_de_champ_multiple_drop_down_list, drop_down_list_value: "val1\r\nval2\r\nval3") }
subject { build(:champ_multiple_drop_down_list, type_de_champ:, value:) }
context 'when the value is nil' do
let(:value) { nil }
it { is_expected.to be_valid }
end
context 'when the value is an empty string' do
let(:value) { '' }
it { is_expected.to be_valid }
end
context 'when the value is an empty array' do
let(:value) { [] }
it { is_expected.to be_valid }
end
context 'when the value is included in the option list' do
let(:value) { ["val3", "val1"] }
it { is_expected.to be_valid }
end
context 'when the value is not included in the option list' do
let(:value) { ["totoro", "val1"] }
it { is_expected.not_to be_valid }
end
end
end
end

View file

@ -128,6 +128,7 @@ RSpec.describe PrefillParams do
it_behaves_like "a champ public value that is authorized", :iban, "value"
it_behaves_like "a champ public value that is authorized", :civilite, "M."
it_behaves_like "a champ public value that is authorized", :pays, "FR"
it_behaves_like "a champ public value that is authorized", :regions, "03"
it_behaves_like "a champ public value that is authorized", :date, "2022-12-22"
it_behaves_like "a champ public value that is authorized", :datetime, "2022-12-22T10:30"
it_behaves_like "a champ public value that is authorized", :yes_no, "true"
@ -135,8 +136,8 @@ RSpec.describe PrefillParams do
it_behaves_like "a champ public value that is authorized", :checkbox, "true"
it_behaves_like "a champ public value that is authorized", :checkbox, "false"
it_behaves_like "a champ public value that is authorized", :drop_down_list, "value"
it_behaves_like "a champ public value that is authorized", :regions, "03"
it_behaves_like "a champ public value that is authorized", :departements, "03"
it_behaves_like "a champ public value that is authorized", :multiple_drop_down_list, ["val1", "val2"]
it_behaves_like "a champ public value that is authorized", :epci, ['01', '200042935']
it_behaves_like "a champ private value that is authorized", :text, "value"
@ -148,6 +149,7 @@ RSpec.describe PrefillParams do
it_behaves_like "a champ private value that is authorized", :iban, "value"
it_behaves_like "a champ private value that is authorized", :civilite, "M."
it_behaves_like "a champ private value that is authorized", :pays, "FR"
it_behaves_like "a champ private value that is authorized", :regions, "93"
it_behaves_like "a champ private value that is authorized", :date, "2022-12-22"
it_behaves_like "a champ private value that is authorized", :datetime, "2022-12-22T10:30"
it_behaves_like "a champ private value that is authorized", :yes_no, "true"
@ -157,6 +159,7 @@ RSpec.describe PrefillParams do
it_behaves_like "a champ private value that is authorized", :drop_down_list, "value"
it_behaves_like "a champ private value that is authorized", :regions, "93"
it_behaves_like "a champ private value that is authorized", :departements, "03"
it_behaves_like "a champ private value that is authorized", :multiple_drop_down_list, ["val1", "val2"]
it_behaves_like "a champ private value that is authorized", :epci, ['01', '200042935']
it_behaves_like "a champ public value that is unauthorized", :decimal_number, "non decimal string"
@ -169,7 +172,6 @@ RSpec.describe PrefillParams do
it_behaves_like "a champ public value that is unauthorized", :date, "value"
it_behaves_like "a champ public value that is unauthorized", :datetime, "value"
it_behaves_like "a champ public value that is unauthorized", :datetime, "12-22-2022T10:30"
it_behaves_like "a champ public value that is unauthorized", :multiple_drop_down_list, "value"
it_behaves_like "a champ public value that is unauthorized", :linked_drop_down_list, "value"
it_behaves_like "a champ public value that is unauthorized", :header_section, "value"
it_behaves_like "a champ public value that is unauthorized", :explication, "value"
@ -187,6 +189,7 @@ RSpec.describe PrefillParams do
it_behaves_like "a champ public value that is unauthorized", :siret, "value"
it_behaves_like "a champ public value that is unauthorized", :rna, "value"
it_behaves_like "a champ public value that is unauthorized", :annuaire_education, "value"
it_behaves_like "a champ public value that is unauthorized", :multiple_drop_down_list, ["value"]
end
private

View file

@ -246,18 +246,18 @@ describe TypeDeChamp do
it_behaves_like "a prefillable type de champ", :type_de_champ_datetime
it_behaves_like "a prefillable type de champ", :type_de_champ_civilite
it_behaves_like "a prefillable type de champ", :type_de_champ_pays
it_behaves_like "a prefillable type de champ", :type_de_champ_regions
it_behaves_like "a prefillable type de champ", :type_de_champ_yes_no
it_behaves_like "a prefillable type de champ", :type_de_champ_checkbox
it_behaves_like "a prefillable type de champ", :type_de_champ_drop_down_list
it_behaves_like "a prefillable type de champ", :type_de_champ_regions
it_behaves_like "a prefillable type de champ", :type_de_champ_departements
it_behaves_like "a prefillable type de champ", :type_de_champ_multiple_drop_down_list
it_behaves_like "a prefillable type de champ", :type_de_champ_epci
it_behaves_like "a non-prefillable type de champ", :type_de_champ_number
it_behaves_like "a non-prefillable type de champ", :type_de_champ_communes
it_behaves_like "a non-prefillable type de champ", :type_de_champ_dossier_link
it_behaves_like "a non-prefillable type de champ", :type_de_champ_titre_identite
it_behaves_like "a non-prefillable type de champ", :type_de_champ_multiple_drop_down_list
it_behaves_like "a non-prefillable type de champ", :type_de_champ_linked_drop_down_list
it_behaves_like "a non-prefillable type de champ", :type_de_champ_header_section
it_behaves_like "a non-prefillable type de champ", :type_de_champ_explication

View file

@ -0,0 +1,32 @@
# frozen_string_literal: true
RSpec.describe TypesDeChamp::PrefillMultipleDropDownListTypeDeChamp do
describe 'ancestors' do
subject { described_class.new(build(:type_de_champ_multiple_drop_down_list)) }
it { is_expected.to be_kind_of(TypesDeChamp::PrefillDropDownListTypeDeChamp) }
end
describe '#example_value' do
let(:type_de_champ) { build(:type_de_champ_multiple_drop_down_list, drop_down_list_value: drop_down_list_value) }
subject(:example_value) { described_class.new(type_de_champ).example_value }
context 'when the multiple drop down list has no option' do
let(:drop_down_list_value) { "" }
it { expect(example_value).to eq(nil) }
end
context 'when the multiple drop down list only has one option' do
let(:drop_down_list_value) { "value" }
it { expect(example_value).to eq("value") }
end
context 'when the multiple drop down list has two options or more' do
let(:drop_down_list_value) { "value1\r\nvalue2\r\nvalue3" }
it { expect(example_value).to eq(["value1", "value2"]) }
end
end
end

View file

@ -10,6 +10,12 @@ RSpec.describe TypesDeChamp::PrefillTypeDeChamp, type: :model do
it { expect(built).to be_kind_of(TypesDeChamp::PrefillDropDownListTypeDeChamp) }
end
context 'when the type de champ is a multiple_drop_down_list' do
let(:type_de_champ) { build(:type_de_champ_multiple_drop_down_list) }
it { expect(built).to be_kind_of(TypesDeChamp::PrefillMultipleDropDownListTypeDeChamp) }
end
context 'when the type de champ is a pays' do
let(:type_de_champ) { build(:type_de_champ_pays) }

View file

@ -19,6 +19,9 @@ shared_examples "the user has got a prefilled dossier, owned by themselves" do
expect(page).to have_field(type_de_champ_phone.libelle, with: phone_value)
expect(page).to have_css('label', text: type_de_champ_phone.libelle)
expect(page).to have_field(type_de_champ_datetime.libelle, with: datetime_value)
expect(page).to have_css('label', text: type_de_champ_multiple_drop_down_list.libelle)
expect(page).to have_content(multiple_drop_down_list_values.first)
expect(page).to have_content(multiple_drop_down_list_values.last)
expect(page).to have_field(type_de_champ_epci.libelle, with: epci_value.last)
end
end

View file

@ -9,12 +9,30 @@ describe 'Prefilling a dossier (with a GET request):' do
let(:type_de_champ_text) { create(:type_de_champ_text, procedure: procedure) }
let(:type_de_champ_phone) { create(:type_de_champ_phone, procedure: procedure) }
let(:type_de_champ_datetime) { create(:type_de_champ_datetime, procedure: procedure) }
let(:type_de_champ_multiple_drop_down_list) { create(:type_de_champ_multiple_drop_down_list, procedure: procedure) }
let(:type_de_champ_epci) { create(:type_de_champ_epci, procedure: procedure) }
let(:text_value) { "My Neighbor Totoro is the best movie ever" }
let(:phone_value) { "invalid phone value" }
let(:datetime_value) { "2023-02-01T10:32" }
let(:multiple_drop_down_list_values) {
[
type_de_champ_multiple_drop_down_list.drop_down_list_enabled_non_empty_options.first,
type_de_champ_multiple_drop_down_list.drop_down_list_enabled_non_empty_options.last
]
}
let(:epci_value) { ['01', '200029999'] }
let(:entry_path) {
commencer_path(
path: procedure.path,
"champ_#{type_de_champ_text.to_typed_id}" => text_value,
"champ_#{type_de_champ_phone.to_typed_id}" => phone_value,
"champ_#{type_de_champ_datetime.to_typed_id}" => datetime_value,
"champ_#{type_de_champ_multiple_drop_down_list.to_typed_id}" => multiple_drop_down_list_values,
"champ_#{type_de_champ_epci.to_typed_id}" => epci_value
)
}
before do
allow(Rails).to receive(:cache).and_return(memory_store)
Rails.cache.clear
@ -36,13 +54,7 @@ describe 'Prefilling a dossier (with a GET request):' do
visit "/users/sign_in"
sign_in_with user.email, password
visit commencer_path(
path: procedure.path,
"champ_#{type_de_champ_text.to_typed_id}" => text_value,
"champ_#{type_de_champ_phone.to_typed_id}" => phone_value,
"champ_#{type_de_champ_datetime.to_typed_id}" => datetime_value,
"champ_#{type_de_champ_epci.to_typed_id}" => epci_value
)
visit entry_path
click_on "Poursuivre mon dossier prérempli"
end
@ -50,15 +62,7 @@ describe 'Prefilling a dossier (with a GET request):' do
end
context 'when unauthenticated' do
before do
visit commencer_path(
path: procedure.path,
"champ_#{type_de_champ_text.to_typed_id}" => text_value,
"champ_#{type_de_champ_phone.to_typed_id}" => phone_value,
"champ_#{type_de_champ_datetime.to_typed_id}" => datetime_value,
"champ_#{type_de_champ_epci.to_typed_id}" => epci_value
)
end
before { visit entry_path }
context 'when the user signs in with email and password' do
it_behaves_like "the user has got a prefilled dossier, owned by themselves" do

View file

@ -9,10 +9,17 @@ describe 'Prefilling a dossier (with a POST request):' do
let(:type_de_champ_text) { create(:type_de_champ_text, procedure: procedure) }
let(:type_de_champ_phone) { create(:type_de_champ_phone, procedure: procedure) }
let(:type_de_champ_datetime) { create(:type_de_champ_datetime, procedure: procedure) }
let(:type_de_champ_multiple_drop_down_list) { create(:type_de_champ_multiple_drop_down_list, procedure: procedure) }
let(:type_de_champ_epci) { create(:type_de_champ_epci, procedure: procedure) }
let(:text_value) { "My Neighbor Totoro is the best movie ever" }
let(:phone_value) { "invalid phone value" }
let(:datetime_value) { "2023-02-01T10:32" }
let(:multiple_drop_down_list_values) {
[
type_de_champ_multiple_drop_down_list.drop_down_list_enabled_non_empty_options.first,
type_de_champ_multiple_drop_down_list.drop_down_list_enabled_non_empty_options.last
]
}
let(:epci_value) { ['01', '200029999'] }
before do
@ -116,6 +123,7 @@ describe 'Prefilling a dossier (with a POST request):' do
"champ_#{type_de_champ_text.to_typed_id}" => text_value,
"champ_#{type_de_champ_phone.to_typed_id}" => phone_value,
"champ_#{type_de_champ_datetime.to_typed_id}" => datetime_value,
"champ_#{type_de_champ_multiple_drop_down_list.to_typed_id}" => multiple_drop_down_list_values,
"champ_#{type_de_champ_epci.to_typed_id}" => epci_value
}.to_json
JSON.parse(session.response.body)["dossier_url"].gsub("http://www.example.com", "")