models: refactor the types_de_champ validators

Context: we want to validate public and private types_de_champ
separately.

Before we validated the whole revision (and then validators themselves
enumerated all champs, public and private).

Now we validate the actual public types_de_champ, which will let us
validate separately the private types_de_champ.
This commit is contained in:
Pierre de La Morinerie 2022-01-26 16:52:32 +00:00
parent 64d75360d0
commit e8e37cce15
8 changed files with 22 additions and 30 deletions

View file

@ -245,7 +245,7 @@ class Procedure < ApplicationRecord
validates :description, presence: true, allow_blank: false, allow_nil: false validates :description, presence: true, allow_blank: false, allow_nil: false
validates :administrateurs, presence: true validates :administrateurs, presence: true
validates :lien_site_web, presence: true, if: :publiee? validates :lien_site_web, presence: true, if: :publiee?
validates :draft_revision, validates :draft_types_de_champ,
'revisions/no_empty_repetition': true, 'revisions/no_empty_repetition': true,
'revisions/no_empty_drop_down': true, 'revisions/no_empty_drop_down': true,
if: :validate_for_publication? if: :validate_for_publication?

View file

@ -1,10 +1,6 @@
class Revisions::NoEmptyDropDownValidator < ActiveModel::EachValidator class Revisions::NoEmptyDropDownValidator < ActiveModel::EachValidator
def validate_each(procedure, attribute, revision) def validate_each(procedure, attribute, types_de_champ)
return if revision.nil? types_de_champ.filter(&:drop_down_list?).each do |drop_down|
tdcs = revision.types_de_champ + revision.types_de_champ_private
drop_downs = tdcs.filter(&:drop_down_list?)
drop_downs.each do |drop_down|
validate_drop_down_not_empty(procedure, attribute, drop_down) validate_drop_down_not_empty(procedure, attribute, drop_down)
end end
end end

View file

@ -1,10 +1,6 @@
class Revisions::NoEmptyRepetitionValidator < ActiveModel::EachValidator class Revisions::NoEmptyRepetitionValidator < ActiveModel::EachValidator
def validate_each(procedure, attribute, revision) def validate_each(procedure, attribute, types_de_champ)
return if revision.nil? types_de_champ.filter(&:repetition?).each do |repetition|
revision_tdcs = revision.types_de_champ + revision.types_de_champ_private
repetitions = revision_tdcs.filter(&:repetition?)
repetitions.each do |repetition|
validate_repetition_not_empty(procedure, attribute, repetition) validate_repetition_not_empty(procedure, attribute, repetition)
end end
end end

View file

@ -53,7 +53,7 @@
- if !@procedure.locked? || @procedure.feature_enabled?(:procedure_revisions) - if !@procedure.locked? || @procedure.feature_enabled?(:procedure_revisions)
- @procedure.validate(:publication) - @procedure.validate(:publication)
- error_messages = @procedure.errors.messages_for(:draft_revision).to_sentence - error_messages = @procedure.errors.messages_for(:draft_types_de_champ).to_sentence
= link_to champs_admin_procedure_path(@procedure), class: 'card-admin', title: error_messages do = link_to champs_admin_procedure_path(@procedure), class: 'card-admin', title: error_messages do
- if @procedure.draft_types_de_champ.count == 0 - if @procedure.draft_types_de_champ.count == 0

View file

@ -328,8 +328,8 @@ fr:
connexion: "Erreur lors de la connexion à France Connect." connexion: "Erreur lors de la connexion à France Connect."
forbidden_html: "Seul-e-s les usagers peuvent se connecter via France Connect. En tant quinstructeur ou administrateur, nous vous invitons à <a href='%{reset_link}'>réininitialiser votre mot de passe</a>." forbidden_html: "Seul-e-s les usagers peuvent se connecter via France Connect. En tant quinstructeur ou administrateur, nous vous invitons à <a href='%{reset_link}'>réininitialiser votre mot de passe</a>."
procedure_archived: "Cette démarche en ligne a été close, il nest plus possible de déposer de dossier." procedure_archived: "Cette démarche en ligne a été close, il nest plus possible de déposer de dossier."
empty_repetition: 'Le bloc répétable « %{value} » doit comporter au moins un champ' empty_repetition: '« %{value} » doit comporter au moins un champ répétable'
empty_drop_down: 'La liste de choix « %{value} » doit comporter au moins un choix sélectionnable' empty_drop_down: '« %{value} » doit comporter au moins un choix sélectionnable'
# procedure_not_draft: "Cette démarche nest maintenant plus en brouillon." # procedure_not_draft: "Cette démarche nest maintenant plus en brouillon."
cadastres_empty: cadastres_empty:
one: "Aucune parcelle cadastrale sur la zone sélectionnée" one: "Aucune parcelle cadastrale sur la zone sélectionnée"

View file

@ -23,5 +23,5 @@ fr:
attributes: attributes:
api_particulier_token: api_particulier_token:
invalid: 'na pas le bon format' invalid: 'na pas le bon format'
draft_revision: draft_types_de_champ:
format: '%{message}' format: 'Le champ %{message}'

View file

@ -302,17 +302,17 @@ describe Procedure do
describe 'draft_revision' do describe 'draft_revision' do
let(:repetition) { build(:type_de_champ_repetition, libelle: 'Enfants') } let(:repetition) { build(:type_de_champ_repetition, libelle: 'Enfants') }
let(:text_field) { build(:type_de_champ_text) } let(:text_field) { build(:type_de_champ_text) }
let(:invalid_repetition_error_message) { 'Le bloc répétable « Enfants » doit comporter au moins un champ' } let(:invalid_repetition_error_message) { 'Le champ « Enfants » doit comporter au moins un champ répétable' }
let(:drop_down) { build(:type_de_champ_drop_down_list, :without_selectable_values, libelle: 'Civilité') } let(:drop_down) { build(:type_de_champ_drop_down_list, :without_selectable_values, libelle: 'Civilité') }
let(:invalid_drop_down_error_message) { 'La liste de choix « Civilité » doit comporter au moins un choix sélectionnable' } let(:invalid_drop_down_error_message) { 'Le champ « Civilité » doit comporter au moins un choix sélectionnable' }
let(:procedure) { create(:procedure, types_de_champ: [repetition, drop_down]) } let(:procedure) { create(:procedure, types_de_champ: [repetition, drop_down]) }
context 'on a draft procedure' do context 'on a draft procedure' do
it 'doesnt validate the draft revision' do it 'doesnt validate the draft revision' do
procedure.validate procedure.validate
expect(procedure.errors[:draft_revision]).not_to be_present expect(procedure.errors[:draft_types_de_champ]).not_to be_present
end end
end end
@ -321,35 +321,35 @@ describe Procedure do
it 'validates that no repetition type de champ is empty' do it 'validates that no repetition type de champ is empty' do
procedure.validate procedure.validate
expect(procedure.errors.full_messages_for(:draft_revision)).to include(invalid_repetition_error_message) expect(procedure.errors.full_messages_for(:draft_types_de_champ)).to include(invalid_repetition_error_message)
text_field.revision = repetition.revision text_field.revision = repetition.revision
text_field.order_place = repetition.types_de_champ.size text_field.order_place = repetition.types_de_champ.size
procedure.draft_revision.types_de_champ.find(&:repetition?).types_de_champ << text_field procedure.draft_types_de_champ.find(&:repetition?).types_de_champ << text_field
procedure.validate procedure.validate
expect(procedure.errors.full_messages_for(:draft_revision)).not_to include(invalid_repetition_error_message) expect(procedure.errors.full_messages_for(:draft_types_de_champ)).not_to include(invalid_repetition_error_message)
end end
it 'validates that no drop-down type de champ is empty' do it 'validates that no drop-down type de champ is empty' do
procedure.validate procedure.validate
expect(procedure.errors.full_messages_for(:draft_revision)).to include(invalid_drop_down_error_message) expect(procedure.errors.full_messages_for(:draft_types_de_champ)).to include(invalid_drop_down_error_message)
drop_down.update!(drop_down_list_value: "--title--\r\nsome value") drop_down.update!(drop_down_list_value: "--title--\r\nsome value")
procedure.reload.validate procedure.reload.validate
expect(procedure.errors.full_messages_for(:draft_revision)).not_to include(invalid_drop_down_error_message) expect(procedure.errors.full_messages_for(:draft_types_de_champ)).not_to include(invalid_drop_down_error_message)
end end
end end
context 'when validating for publication' do context 'when validating for publication' do
it 'validates that no repetition type de champ is empty' do it 'validates that no repetition type de champ is empty' do
procedure.validate(:publication) procedure.validate(:publication)
expect(procedure.errors.full_messages_for(:draft_revision)).to include(invalid_repetition_error_message) expect(procedure.errors.full_messages_for(:draft_types_de_champ)).to include(invalid_repetition_error_message)
end end
it 'validates that no drop-down type de champ is empty' do it 'validates that no drop-down type de champ is empty' do
procedure.validate(:publication) procedure.validate(:publication)
expect(procedure.errors.full_messages_for(:draft_revision)).to include(invalid_drop_down_error_message) expect(procedure.errors.full_messages_for(:draft_types_de_champ)).to include(invalid_drop_down_error_message)
end end
end end
end end

View file

@ -47,7 +47,7 @@ describe 'Publishing a procedure', js: true do
end end
context 'when the procedure has invalid champs' do context 'when the procedure has invalid champs' do
let(:empty_repetition) { build(:type_de_champ_repetition, types_de_champ: []) } let(:empty_repetition) { build(:type_de_champ_repetition, types_de_champ: [], libelle: 'Enfants') }
let!(:procedure) do let!(:procedure) do
create(:procedure, create(:procedure,
:with_path, :with_path,
@ -59,7 +59,7 @@ describe 'Publishing a procedure', js: true do
scenario 'an error message prevents the publication' do scenario 'an error message prevents the publication' do
expect(page).to have_content('Des problèmes empêchent la publication de la démarche') expect(page).to have_content('Des problèmes empêchent la publication de la démarche')
expect(page).to have_content("Le bloc répétable « #{empty_repetition.libelle} » doit comporter au moins un champ") expect(page).to have_content("Le champ « Enfants » doit comporter au moins un champ répétable")
expect(find_field('procedure_path').value).to eq procedure.path expect(find_field('procedure_path').value).to eq procedure.path
fill_in 'lien_site_web', with: 'http://some.website' fill_in 'lien_site_web', with: 'http://some.website'