Merge pull request #10250 from mfo/US/add-missing-validators

tech(champs.validators): dry and standardize champs.validations
This commit is contained in:
Paul Chavard 2024-04-17 15:06:47 +00:00 committed by GitHub
commit 2c9f809a46
No known key found for this signature in database
GPG key ID: B5690EEEBB952194
31 changed files with 156 additions and 170 deletions

View file

@ -1,5 +1,6 @@
class Champ < ApplicationRecord
include ChampConditionalConcern
include ChampsValidateConcern
belongs_to :dossier, inverse_of: false, touch: true, optional: false
belongs_to :type_de_champ, inverse_of: :champ, optional: false
@ -249,27 +250,6 @@ class Champ < ApplicationRecord
end
end
protected
def valid_champ_value?
valid?(public? ? :champs_public_value : :champs_private_value)
end
private
def validate_champ_value?
return false unless visible?
case validation_context
when :champs_public_value
public?
when :champs_private_value
private?
else
false
end
end
def html_id
"champ-#{public_id}"
end

View file

@ -5,11 +5,7 @@ class Champs::BooleanChamp < Champ
before_validation :set_value_to_nil, if: -> { value.blank? }
before_validation :set_value_to_false, unless: -> { ([nil, TRUE_VALUE, FALSE_VALUE]).include?(value) }
# TODO: if: -> { validate_champ_value? || validation_context == :prefill }
validates :value, inclusion: [TRUE_VALUE, FALSE_VALUE],
allow_nil: true,
allow_blank: false,
if: :validate_champ_value?
validates :value, inclusion: [TRUE_VALUE, FALSE_VALUE], allow_nil: true, allow_blank: false, if: :validate_champ_value_or_prefill?
def true?
value == TRUE_VALUE

View file

@ -1,8 +1,5 @@
class Champs::CiviliteChamp < Champ
validates :value, inclusion: ["M.", "Mme"],
allow_nil: true,
allow_blank: false,
if: -> { validate_champ_value? || validation_context == :prefill }
validates :value, inclusion: ["M.", "Mme"], allow_nil: true, allow_blank: false, if: :validate_champ_value_or_prefill?
def legend_label?
true

View file

@ -1,8 +1,8 @@
class Champs::CnafChamp < Champs::TextChamp
# see https://github.com/betagouv/api-particulier/blob/master/src/presentation/middlewares/cnaf-input-validation.middleware.ts
# TODO: if: -> { validate_champ_value? || validation_context == :prefill }
validates :numero_allocataire, format: { with: /\A\d{1,7}\z/ }, if: -> { code_postal.present? && validate_champ_value? }
validates :code_postal, format: { with: /\A\w{5}\z/ }, if: -> { numero_allocataire.present? && validate_champ_value? }
validates :numero_allocataire, format: { with: /\A\d{1,7}\z/ }, if: -> { code_postal.present? && validate_champ_value_or_prefill? }
validates :code_postal, format: { with: /\A\w{5}\z/ }, if: -> { numero_allocataire.present? && validate_champ_value_or_prefill? }
store_accessor :value_json, :numero_allocataire, :code_postal

View file

@ -1,5 +1,6 @@
class Champs::DecimalNumberChamp < Champ
before_validation :format_value
validates :value, format: {
with: /\A-?[0-9]+([\.,][0-9]{1,3})?\z/,
allow_nil: true,
@ -14,7 +15,7 @@ class Champs::DecimalNumberChamp < Champ
message: -> (object, _data) {
object.errors.generate_message(:value, :not_a_number)
}
}, if: -> { validate_champ_value? || validation_context == :prefill }
}, if: :validate_champ_value_or_prefill?
def for_export(path = :value)
processed_value

View file

@ -1,8 +1,8 @@
class Champs::DepartementChamp < Champs::TextChamp
store_accessor :value_json, :code_region
# TODO: if: -> { validate_champ_value? || validation_context == :prefill }
validate :value_in_departement_names, unless: -> { value.nil? }
validate :external_id_in_departement_codes, unless: -> { external_id.nil? }
validate :value_in_departement_names, if: -> { validate_champ_value_or_prefill? && !value.nil? }
validate :external_id_in_departement_codes, if: -> { validate_champ_value_or_prefill? && !external_id.nil? }
before_save :store_code_region
def for_export(path = :value)

View file

@ -1,8 +1,7 @@
class Champs::DgfipChamp < Champs::TextChamp
# see https://github.com/betagouv/api-particulier/blob/master/src/presentation/middlewares/dgfip-input-validation.middleware.ts
# TODO: if: -> { validate_champ_value? || validation_context == :prefill }
validates :numero_fiscal, format: { with: /\A\w{13,14}\z/ }, if: -> { reference_avis.present? && validate_champ_value? }
validates :reference_avis, format: { with: /\A\w{13,14}\z/ }, if: -> { numero_fiscal.present? && validate_champ_value? }
validates :numero_fiscal, format: { with: /\A\w{13,14}\z/ }, if: -> { reference_avis.present? && validate_champ_value_or_prefill? }
validates :reference_avis, format: { with: /\A\w{13,14}\z/ }, if: -> { numero_fiscal.present? && validate_champ_value_or_prefill? }
store_accessor :value_json, :numero_fiscal, :reference_avis

View file

@ -1,5 +1,4 @@
class Champs::DossierLinkChamp < Champ
# TODO: if: -> { validate_champ_value? || validation_context == :prefill }
validate :value_integerable, if: -> { value.present? }, on: :prefill
private

View file

@ -4,9 +4,7 @@ class Champs::DropDownListChamp < Champ
THRESHOLD_NB_OPTIONS_AS_AUTOCOMPLETE = 20
OTHER = '__other__'
delegate :options_without_empty_value_when_mandatory, to: :type_de_champ
# TODO: if: -> { validate_champ_value? || validation_context == :prefill }
validate :value_is_in_options, unless: -> { value.blank? || drop_down_other? }
validate :value_is_in_options, if: -> { !(value.blank? || drop_down_other?) && validate_champ_value_or_prefill? }
def render_as_radios?
enabled_non_empty_options.size <= THRESHOLD_NB_OPTIONS_AS_RADIO

View file

@ -1,6 +1,6 @@
class Champs::EmailChamp < Champs::TextChamp
include EmailSanitizableConcern
before_validation -> { sanitize_email(:value) }
# TODO: if: -> { validate_champ_value? || validation_context == :prefill }
validates :value, allow_blank: true, format: { with: StrictEmailValidator::REGEXP }, if: :validate_champ_value?
validates :value, allow_blank: true, format: { with: StrictEmailValidator::REGEXP }, if: :validate_champ_value_or_prefill?
end

View file

@ -1,8 +1,7 @@
class Champs::EngagementJuridiqueChamp < Champ
# cf: https://communaute.chorus-pro.gouv.fr/documentation/creer-un-engagement/#1522314752186-a34f3662-0644b5d1-16c22add-8ea097de-3a0a
# TODO: if: -> { validate_champ_value? || validation_context == :prefill }
validates_with ExpressionReguliereValidator,
expression_reguliere: /([A-Z]|[0-9]|\-|\_|\+|\/)+/,
expression_reguliere_error_message: "Le numéro d'EJ ne peut contenir que des caractères alphanumérique et les caractères spéciaux suivant : “-“ ; “_“ ; “+“ ; “/“",
if: :validate_champ_value?
expression_reguliere: /([A-Z]|[0-9]|\-|\_|\+|\/)+/,
expression_reguliere_error_message: "Le numéro d'EJ ne peut contenir que des caractères alphanumérique et les caractères spéciaux suivant : “-“ ; “_“ ; “+“ ; “/“",
if: :validate_champ_value_or_prefill?
end

View file

@ -3,10 +3,9 @@ class Champs::EpciChamp < Champs::TextChamp
before_validation :on_departement_change
before_validation :on_epci_name_changes
# TODO: if: -> { validate_champ_value? || validation_context == :prefill }
validate :code_departement_in_departement_codes, unless: -> { code_departement.nil? }
validate :external_id_in_departement_epci_codes, unless: -> { code_departement.nil? || external_id.nil? }
validate :value_in_departement_epci_names, unless: -> { code_departement.nil? || external_id.nil? || value.nil? }
validate :code_departement_in_departement_codes, if: -> { !(code_departement.nil?) && validate_champ_value_or_prefill? }
validate :external_id_in_departement_epci_codes, if: -> { !(code_departement.nil? || external_id.nil?) && validate_champ_value_or_prefill? }
validate :value_in_departement_epci_names, if: -> { !(code_departement.nil? || external_id.nil? || value.nil?) && validate_champ_value_or_prefill? }
def for_export(path = :value)
case path

View file

@ -1,4 +1,3 @@
class Champs::ExpressionReguliereChamp < Champ
# TODO: if: -> { validate_champ_value? || validation_context == :prefill }
validates_with ExpressionReguliereValidator, if: :validate_champ_value?
validates_with ExpressionReguliereValidator, if: :validate_champ_value_or_prefill?
end

View file

@ -1,6 +1,5 @@
class Champs::IbanChamp < Champ
# TODO: if: -> { validate_champ_value? || validation_context == :prefill }
validates_with IbanValidator, if: :validate_champ_value?
validates_with IbanValidator, if: :validate_champ_value_or_prefill?
after_validation :format_iban
def for_api

View file

@ -7,7 +7,7 @@ class Champs::IntegerNumberChamp < Champ
# i18n-tasks-use t('errors.messages.not_an_integer')
object.errors.generate_message(:value, :not_an_integer)
}
}, if: -> { validate_champ_value? || validation_context == :prefill }
}, if: :validate_champ_value_or_prefill?
def for_export(path = :value)
processed_value

View file

@ -1,6 +1,5 @@
class Champs::MultipleDropDownListChamp < Champ
# TODO: if: -> { validate_champ_value? || validation_context == :prefill }
validate :values_are_in_options, if: -> { value.present? }
validate :values_are_in_options, if: -> { value.present? && validate_champ_value_or_prefill? }
def options?
drop_down_list_options?

View file

@ -19,14 +19,13 @@ class Champs::PhoneChamp < Champs::TextChamp
#
# See issue #6996.
DEFAULT_COUNTRY_CODES = [:FR, :GP, :GF, :MQ, :RE, :YT, :NC, :PF].freeze
validates :value,
phone: {
possible: true,
allow_blank: true,
message: I18n.t(:not_a_phone, scope: 'activerecord.errors.messages')
},
if: -> { (validate_champ_value? || validation_context == :prefill) && !Phonelib.valid_for_countries?(value, DEFAULT_COUNTRY_CODES) }
if: -> { !Phonelib.valid_for_countries?(value, DEFAULT_COUNTRY_CODES) && validate_champ_value_or_prefill? }
def to_s
return '' if value.blank?

View file

@ -1,7 +1,6 @@
class Champs::RegionChamp < Champs::TextChamp
# TODO: if: -> { validate_champ_value? || validation_context == :prefill }
validate :value_in_region_names, unless: -> { value.nil? }
validate :external_id_in_region_codes, unless: -> { external_id.nil? }
validate :value_in_region_names, if: -> { !value.nil? && validate_champ_value_or_prefill? }
validate :external_id_in_region_codes, if: -> { !external_id.nil? && validate_champ_value_or_prefill? }
def for_export(path = :value)
case path

View file

@ -1,10 +1,9 @@
class Champs::RNAChamp < Champ
include RNAChampAssociationFetchableConcern
# TODO: if: -> { validate_champ_value? || validation_context == :prefill }
validates :value, allow_blank: true, format: {
with: /\AW[0-9A-Z]{9}\z/, message: I18n.t(:not_a_rna, scope: 'activerecord.errors.messages')
}, if: :validate_champ_value?
}, if: :validate_champ_value_or_prefill?
delegate :id, to: :procedure, prefix: true

View file

@ -0,0 +1,31 @@
module ChampsValidateConcern
extend ActiveSupport::Concern
included do
protected
# Champs public/private must be validated depending on the context
def valid_champ_value?
valid?(public? ? :champs_public_value : :champs_private_value)
end
private
def validate_champ_value?
return false unless visible?
case validation_context
when :champs_public_value
public?
when :champs_private_value
private?
else
false
end
end
def validate_champ_value_or_prefill?
validate_champ_value? || validation_context == :prefill
end
end
end

View file

@ -105,8 +105,12 @@ module DossierCloneConcern
end
transaction do
cloned_dossier.save!(validate: !fork)
if fork
cloned_dossier.save!(validate: false)
else
cloned_dossier.validate(:champs_public_value)
cloned_dossier.save!
end
cloned_dossier.rebase!
end

View file

@ -7,7 +7,7 @@ module RNAChampAssociationFetchableConcern
self.value = rna
return clear_association!(:empty) if rna.empty?
return clear_association!(:invalid) unless valid?(:champs_public_value)
return clear_association!(:invalid) unless valid_champ_value?
return clear_association!(:not_found) if (data = APIEntreprise::RNAAdapter.new(rna, procedure_id).to_params).blank?
update!(data: data)
@ -21,7 +21,7 @@ module RNAChampAssociationFetchableConcern
def clear_association!(error)
@association_fetch_error_key = error
self.data = nil
save!
save(validate: false)
false
end
end

View file

@ -83,12 +83,6 @@ describe Champs::CnafChamp, type: :model do
is_expected.to be false
expect(champ.errors.full_messages).to eq(["Le champ « Numero allocataire » doit être composé au maximum de 7 chiffres"])
end
context 'and the validation_context is :brouillon' do
let(:validation_context) { :brouillon }
it { is_expected.to be true }
end
end
context 'when code_postal is invalid' do

View file

@ -1,60 +1,61 @@
describe Champs::DepartementChamp, type: :model do
describe 'validations' do
describe 'external link' do
subject { build(:champ_departements, external_id: external_id) }
let(:champ) { build(:champ_departements, external_id: external_id) }
subject { champ.validate(:champs_public_value) }
context 'when nil' do
let(:external_id) { nil }
it { is_expected.to be_valid }
it { is_expected.to be_truthy }
end
context 'when blank' do
let(:external_id) { '' }
it { is_expected.not_to be_valid }
it { is_expected.to be_falsey }
end
context 'when included in the departement codes' do
let(:external_id) { "01" }
it { is_expected.to be_valid }
it { is_expected.to be_truthy }
end
context 'when not included in the departement codes' do
let(:external_id) { "totoro" }
it { is_expected.not_to be_valid }
it { is_expected.to be_falsey }
end
end
describe 'value' do
subject { create(:champ_departements) }
before { subject.update_columns(value: value) }
let(:champ) { create(:champ_departements) }
subject { champ.validate(:champs_public_value) }
before { champ.update_columns(value: value) }
context 'when nil' do
let(:value) { nil }
it { is_expected.to be_valid }
it { is_expected.to be_truthy }
end
context 'when blank' do
let(:value) { '' }
it { is_expected.not_to be_valid }
it { is_expected.to be_falsey }
end
context 'when included in the departement names' do
let(:value) { "Ain" }
it { is_expected.to be_valid }
it { is_expected.to be_truthy }
end
context 'when not included in the departement names' do
let(:value) { "totoro" }
it { is_expected.not_to be_valid }
it { is_expected.to be_falsey }
end
end
end

View file

@ -83,12 +83,6 @@ describe Champs::DgfipChamp, type: :model do
is_expected.to be false
expect(champ.errors.full_messages).to eq(["Le champ « Numero fiscal » doit posséder 13 ou 14 caractères"])
end
context 'and the validation_context is :brouillon' do
let(:validation_context) { :brouillon }
it { is_expected.to be true }
end
end
context 'when reference_avis is invalid' do

View file

@ -1,7 +1,8 @@
describe Champs::DropDownListChamp do
describe 'validations' do
describe 'inclusion' do
let(:drop_down) { build(:champ_drop_down_list, other: other, value: value) }
let(:champ) { build(:champ_drop_down_list, other: other, value: value) }
subject { champ.validate(:champs_public_value) }
context 'when the other value is accepted' do
let(:other) { true }
@ -9,19 +10,19 @@ describe Champs::DropDownListChamp do
context 'when the value is blank' do
let(:value) { '' }
it { expect(drop_down).to be_valid }
it { is_expected.to be_truthy }
end
context 'when the value is included in the option list' do
let(:value) { 'val1' }
it { expect(drop_down).to be_valid }
it { is_expected.to be_truthy }
end
context 'when the value is not included in the option list' do
let(:value) { 'something else' }
it { expect(drop_down).to be_valid }
it { is_expected.to be_truthy }
end
end
@ -31,19 +32,19 @@ describe Champs::DropDownListChamp do
context 'when the value is blank' do
let(:value) { '' }
it { expect(drop_down).to be_valid }
it { is_expected.to be_truthy }
end
context 'when the value is included in the option list' do
let(:value) { 'val1' }
it { expect(drop_down).to be_valid }
it { is_expected.to be_truthy }
end
context 'when the value is not included in the option list' do
let(:value) { 'something else' }
it { expect(drop_down).not_to be_valid }
it { is_expected.to be_falsey }
end
end
end

View file

@ -1,40 +1,40 @@
describe Champs::EpciChamp, type: :model do
describe 'validations' do
subject { champ.validate(:champs_public_value) }
describe 'code_departement' do
subject { build(:champ_epci, code_departement: code_departement) }
let(:champ) { build(:champ_epci, code_departement: code_departement) }
context 'when nil' do
let(:code_departement) { nil }
it { is_expected.to be_valid }
it { is_expected.to be_truthy }
end
context 'when empty' do
let(:code_departement) { '' }
it { is_expected.not_to be_valid }
it { is_expected.to be_falsey }
end
context 'when included in the departement codes' do
let(:code_departement) { "01" }
it { is_expected.to be_valid }
it { is_expected.to be_truthy }
end
context 'when not included in the departement codes' do
let(:code_departement) { "totoro" }
it { is_expected.not_to be_valid }
it { is_expected.to be_falsey }
end
end
describe 'external_id' do
let(:champ) { build(:champ_epci, code_departement: code_departement, external_id: nil) }
subject { champ }
before do
champ.save!
champ.save!(validate: false)
champ.update_columns(external_id: external_id)
end
@ -42,7 +42,7 @@ describe Champs::EpciChamp, type: :model do
let(:code_departement) { nil }
let(:external_id) { nil }
it { is_expected.to be_valid }
it { is_expected.to be_truthy }
end
context 'when code_departement is not nil and valid' do
@ -51,36 +51,36 @@ describe Champs::EpciChamp, type: :model do
context 'when external_id is nil' do
let(:external_id) { nil }
it { is_expected.to be_valid }
it { is_expected.to be_truthy }
end
context 'when external_id is empty' do
let(:external_id) { '' }
it { is_expected.not_to be_valid }
it { is_expected.to be_falsey }
end
context 'when external_id is included in the epci codes of the departement' do
let(:external_id) { '200042935' }
it { is_expected.to be_valid }
it { is_expected.to be_truthy }
end
context 'when external_id is not included in the epci codes of the departement' do
let(:external_id) { 'totoro' }
it { is_expected.not_to be_valid }
it { is_expected.to be_falsey }
end
end
end
describe 'value' do
subject { champ.validate(:champs_public_value) }
let(:champ) { build(:champ_epci, code_departement: code_departement, external_id: nil, value: nil) }
subject { champ }
before do
champ.save!
champ.save!(validate: false)
champ.update_columns(external_id: external_id, value: value)
end
@ -89,7 +89,7 @@ describe Champs::EpciChamp, type: :model do
let(:external_id) { nil }
let(:value) { nil }
it { is_expected.to be_valid }
it { is_expected.to be_truthy }
end
context 'when external_id is nil' do
@ -97,7 +97,7 @@ describe Champs::EpciChamp, type: :model do
let(:external_id) { nil }
let(:value) { nil }
it { is_expected.to be_valid }
it { is_expected.to be_truthy }
end
context 'when code_departement and external_id are not nil and valid' do
@ -107,27 +107,27 @@ describe Champs::EpciChamp, type: :model do
context 'when value is nil' do
let(:value) { nil }
it { is_expected.to be_valid }
it { is_expected.to be_truthy }
end
context 'when value is in departement epci names' do
let(:value) { 'CA Haut - Bugey Agglomération' }
it { is_expected.to be_valid }
it { is_expected.to be_truthy }
end
context 'when value is in departement epci names' do
let(:value) { 'CA Haut - Bugey Agglomération' }
it { is_expected.to be_valid }
it { is_expected.to be_truthy }
end
context 'when epci name had been renamed' do
let(:value) { 'totoro' }
it 'is valid and updates its own value' do
expect(subject).to be_valid
expect(subject.value).to eq('CA Haut - Bugey Agglomération')
expect(subject).to be_truthy
expect(champ.value).to eq('CA Haut - Bugey Agglomération')
end
end
@ -136,7 +136,7 @@ describe Champs::EpciChamp, type: :model do
it 'is invalid' do
allow(APIGeoService).to receive(:epcis).with(champ.code_departement).and_return([])
expect(subject).not_to be_valid
expect(subject).to be_falsey
end
end
end

View file

@ -1,54 +1,56 @@
describe Champs::MultipleDropDownListChamp do
let(:type_de_champ) { build(:type_de_champ_multiple_drop_down_list, drop_down_list_value: "val1\r\nval2\r\nval3\r\n[brackets] val4") }
let(:value) { nil }
subject { build(:champ_multiple_drop_down_list, type_de_champ:, value:) }
let(:champ) { build(:champ_multiple_drop_down_list, type_de_champ:, value:) }
describe 'validations' do
subject { champ.validate(:champs_public_value) }
describe 'inclusion' do
context 'when the value is nil' do
it { is_expected.to be_valid }
it { is_expected.to be_truthy }
end
context 'when the value is an empty string' do
let(:value) { '' }
it { is_expected.to be_valid }
it { is_expected.to be_truthy }
end
context 'when the value is an empty array' do
let(:value) { [] }
it { is_expected.to be_valid }
it { is_expected.to be_truthy }
end
context 'when the value is included in the option list' do
let(:value) { ["val3", "val1"] }
it { is_expected.to be_valid }
it { is_expected.to be_truthy }
end
context 'when the value is not included in the option list' do
let(:value) { ["totoro", "val1"] }
it { is_expected.not_to be_valid }
it { is_expected.to be_falsey }
end
context 'set value' do
it {
subject.value = ["val1"]
expect(subject.value).to eq("[\"val1\"]")
subject.value = 'val2'
expect(subject.value).to eq("[\"val1\",\"val2\"]")
subject.value = ''
expect(subject.value).to eq("[\"val1\",\"val2\"]")
subject.value = "[brackets] val4"
expect(subject.value).to eq("[\"val1\",\"val2\",\"[brackets] val4\"]")
subject.value = nil
expect(subject.value).to be_nil
subject.value = ["val1"]
expect(subject.value).to eq("[\"val1\"]")
subject.value = []
expect(subject.value).to be_nil
champ.value = ["val1"]
expect(champ.value).to eq("[\"val1\"]")
champ.value = 'val2'
expect(champ.value).to eq("[\"val1\",\"val2\"]")
champ.value = ''
expect(champ.value).to eq("[\"val1\",\"val2\"]")
champ.value = "[brackets] val4"
expect(champ.value).to eq("[\"val1\",\"val2\",\"[brackets] val4\"]")
champ.value = nil
expect(champ.value).to be_nil
champ.value = ["val1"]
expect(champ.value).to eq("[\"val1\"]")
champ.value = []
expect(champ.value).to be_nil
}
end
end
@ -59,22 +61,22 @@ describe Champs::MultipleDropDownListChamp do
context 'when the value has next value' do
it {
expect(subject.next_checkbox_id("val1")).to eq(subject.checkbox_id("val2"))
expect(subject.next_checkbox_id("val2")).to eq(subject.checkbox_id("val3"))
expect(champ.next_checkbox_id("val1")).to eq(champ.checkbox_id("val2"))
expect(champ.next_checkbox_id("val2")).to eq(champ.checkbox_id("val3"))
}
end
context 'when the value is last' do
it { expect(subject.next_checkbox_id("val3")).to eq(subject.checkbox_id("val2")) }
it { expect(champ.next_checkbox_id("val3")).to eq(champ.checkbox_id("val2")) }
end
context 'when the value is invalid' do
it { expect(subject.next_checkbox_id("val4")).to eq(nil) }
it { expect(champ.next_checkbox_id("val4")).to eq(nil) }
end
context 'when the values are empty' do
let(:value) { [] }
it { expect(subject.next_checkbox_id("val1")).to eq(nil) }
it { expect(champ.next_checkbox_id("val1")).to eq(nil) }
end
end
end

View file

@ -1,6 +1,5 @@
describe Champs::PhoneChamp do
let(:champ) { build(:champ_phone) }
# subject { champ }
describe '#validate' do
it do

View file

@ -1,60 +1,61 @@
describe Champs::RegionChamp, type: :model do
describe 'validations' do
describe 'external link' do
subject { build(:champ_regions, external_id: external_id) }
let(:champ) { build(:champ_regions, external_id: external_id) }
subject { champ.validate(:champs_public_value) }
context 'when nil' do
let(:external_id) { nil }
it { is_expected.to be_valid }
it { is_expected.to be_truthy }
end
context 'when blank' do
let(:external_id) { '' }
it { is_expected.not_to be_valid }
it { is_expected.to be_falsey }
end
context 'when included in the region codes' do
let(:external_id) { "01" }
it { is_expected.to be_valid }
it { is_expected.to be_truthy }
end
context 'when not included in the region codes' do
let(:external_id) { "totoro" }
it { is_expected.not_to be_valid }
it { is_expected.to be_falsey }
end
end
describe 'value' do
subject { create(:champ_regions) }
let(:champ) { create(:champ_regions) }
subject { champ.validate(:champs_public_value) }
before { subject.update_columns(value: value) }
before { champ.update_columns(value: value) }
context 'when nil' do
let(:value) { nil }
it { is_expected.to be_valid }
it { is_expected.to be_truthy }
end
context 'when blank' do
let(:value) { '' }
it { is_expected.not_to be_valid }
it { is_expected.to be_falsey }
end
context 'when included in the region names' do
let(:value) { "Guyane" }
it { is_expected.to be_valid }
it { is_expected.to be_truthy }
end
context 'when not included in the region names' do
let(:value) { "totoro" }
it { is_expected.not_to be_valid }
it { is_expected.to be_falsey }
end
end
end

View file

@ -209,15 +209,12 @@ RSpec.describe DossierCloneConcern do
end
it 'can still fork' do
# rubocop:disable Lint/BooleanSymbol
expect(dossier.valid?(context: :false)).to be_falsey
expect(dossier.validate(:champs_public_value)).to be_falsey
new_dossier.champs.load # load relation so champs are validated below
expect(new_dossier.valid?(context: :false)).to be_falsey
expect(new_dossier.validate(:champs_public_value)).to be_falsey
expect(new_dossier.champs.find { _1.stable_id == 992 }.value).to eq("Je ne sais pas")
# rubocop:enable Lint/BooleanSymbol
end
context 'when associated record is invalid' do