Merge pull request #11127 from tchak/fix-champ-validation
fix(champ): always check if a champ is in dossier revision before validate
This commit is contained in:
commit
bd185b4fdb
32 changed files with 112 additions and 79 deletions
|
@ -27,7 +27,8 @@ class Champs::PieceJustificativeController < Champs::ChampController
|
||||||
|
|
||||||
ActiveStorage::Attachment.transaction do
|
ActiveStorage::Attachment.transaction do
|
||||||
@champ.piece_justificative_file.attach(params[:blob_signed_id])
|
@champ.piece_justificative_file.attach(params[:blob_signed_id])
|
||||||
save_succeed = @champ.save
|
context = @champ.public? ? :champs_public_value : :champs_private_value
|
||||||
|
save_succeed = @champ.save(context:)
|
||||||
end
|
end
|
||||||
|
|
||||||
if save_succeed && dossier.brouillon?
|
if save_succeed && dossier.brouillon?
|
||||||
|
|
|
@ -89,7 +89,8 @@ class Champ < ApplicationRecord
|
||||||
end
|
end
|
||||||
|
|
||||||
def blank?
|
def blank?
|
||||||
type_de_champ.champ_blank?(self)
|
# FIXME: temporary fix to avoid breaking validation
|
||||||
|
in_dossier_revision? ? type_de_champ.champ_blank?(self) : value.blank?
|
||||||
end
|
end
|
||||||
|
|
||||||
def used_by_routing_rules?
|
def used_by_routing_rules?
|
||||||
|
|
|
@ -7,7 +7,7 @@ class Champs::BooleanChamp < Champ
|
||||||
before_validation :set_value_to_nil, if: -> { value.blank? }
|
before_validation :set_value_to_nil, if: -> { value.blank? }
|
||||||
before_validation :set_value_to_false, unless: -> { ([nil, TRUE_VALUE, FALSE_VALUE]).include?(value) }
|
before_validation :set_value_to_false, unless: -> { ([nil, TRUE_VALUE, FALSE_VALUE]).include?(value) }
|
||||||
|
|
||||||
validates :value, inclusion: [TRUE_VALUE, FALSE_VALUE], allow_nil: true, allow_blank: false, if: :validate_champ_value_or_prefill?
|
validates :value, inclusion: [TRUE_VALUE, FALSE_VALUE], allow_nil: true, allow_blank: false, if: :validate_champ_value?
|
||||||
|
|
||||||
def true?
|
def true?
|
||||||
value == TRUE_VALUE
|
value == TRUE_VALUE
|
||||||
|
|
|
@ -1,7 +1,7 @@
|
||||||
# frozen_string_literal: true
|
# frozen_string_literal: true
|
||||||
|
|
||||||
class Champs::CiviliteChamp < Champ
|
class Champs::CiviliteChamp < Champ
|
||||||
validates :value, inclusion: ["M.", "Mme"], allow_nil: true, allow_blank: false, if: :validate_champ_value_or_prefill?
|
validates :value, inclusion: ["M.", "Mme"], allow_nil: true, allow_blank: false, if: :validate_champ_value?
|
||||||
|
|
||||||
def legend_label?
|
def legend_label?
|
||||||
true
|
true
|
||||||
|
|
|
@ -3,8 +3,8 @@
|
||||||
class Champs::CnafChamp < Champs::TextChamp
|
class Champs::CnafChamp < Champs::TextChamp
|
||||||
# see https://github.com/betagouv/api-particulier/blob/master/src/presentation/middlewares/cnaf-input-validation.middleware.ts
|
# see https://github.com/betagouv/api-particulier/blob/master/src/presentation/middlewares/cnaf-input-validation.middleware.ts
|
||||||
|
|
||||||
validates :numero_allocataire, format: { with: /\A\d{1,7}\z/ }, if: -> { code_postal.present? && validate_champ_value_or_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_or_prefill? }
|
validates :code_postal, format: { with: /\A\w{5}\z/ }, if: -> { numero_allocataire.present? && validate_champ_value? }
|
||||||
|
|
||||||
store_accessor :value_json, :numero_allocataire, :code_postal
|
store_accessor :value_json, :numero_allocataire, :code_postal
|
||||||
|
|
||||||
|
|
|
@ -4,7 +4,7 @@ class Champs::CommuneChamp < Champs::TextChamp
|
||||||
store_accessor :value_json, :code_departement, :code_postal, :code_region
|
store_accessor :value_json, :code_departement, :code_postal, :code_region
|
||||||
before_save :on_codes_change, if: :should_refresh_after_code_change?
|
before_save :on_codes_change, if: :should_refresh_after_code_change?
|
||||||
|
|
||||||
validates :external_id, presence: true, if: -> { validate_champ_value_or_prefill? && value.present? }
|
validates :external_id, presence: true, if: -> { value.present? && validate_champ_value? }
|
||||||
after_validation :instrument_external_id_error, if: -> { errors.include?(:external_id) }
|
after_validation :instrument_external_id_error, if: -> { errors.include?(:external_id) }
|
||||||
|
|
||||||
def departement_name
|
def departement_name
|
||||||
|
|
|
@ -17,7 +17,7 @@ class Champs::DecimalNumberChamp < Champ
|
||||||
message: -> (object, _data) {
|
message: -> (object, _data) {
|
||||||
object.errors.generate_message(:value, :not_a_number)
|
object.errors.generate_message(:value, :not_a_number)
|
||||||
}
|
}
|
||||||
}, if: :validate_champ_value_or_prefill?
|
}, if: :validate_champ_value?
|
||||||
|
|
||||||
private
|
private
|
||||||
|
|
||||||
|
|
|
@ -3,8 +3,8 @@
|
||||||
class Champs::DepartementChamp < Champs::TextChamp
|
class Champs::DepartementChamp < Champs::TextChamp
|
||||||
store_accessor :value_json, :code_region
|
store_accessor :value_json, :code_region
|
||||||
|
|
||||||
validate :value_in_departement_names, if: -> { validate_champ_value_or_prefill? && !value.nil? }
|
validate :value_in_departement_names, if: -> { !value.nil? && validate_champ_value? }
|
||||||
validate :external_id_in_departement_codes, if: -> { validate_champ_value_or_prefill? && !external_id.nil? }
|
validate :external_id_in_departement_codes, if: -> { !external_id.nil? && validate_champ_value? }
|
||||||
before_save :store_code_region
|
before_save :store_code_region
|
||||||
|
|
||||||
def selected
|
def selected
|
||||||
|
|
|
@ -2,8 +2,8 @@
|
||||||
|
|
||||||
class Champs::DgfipChamp < Champs::TextChamp
|
class Champs::DgfipChamp < Champs::TextChamp
|
||||||
# see https://github.com/betagouv/api-particulier/blob/master/src/presentation/middlewares/dgfip-input-validation.middleware.ts
|
# see https://github.com/betagouv/api-particulier/blob/master/src/presentation/middlewares/dgfip-input-validation.middleware.ts
|
||||||
validates :numero_fiscal, format: { with: /\A\w{13,14}\z/ }, if: -> { reference_avis.present? && validate_champ_value_or_prefill? }
|
validates :numero_fiscal, format: { with: /\A\w{13,14}\z/ }, if: -> { validate_champ_value? && reference_avis.present? }
|
||||||
validates :reference_avis, format: { with: /\A\w{13,14}\z/ }, if: -> { numero_fiscal.present? && validate_champ_value_or_prefill? }
|
validates :reference_avis, format: { with: /\A\w{13,14}\z/ }, if: -> { validate_champ_value? && numero_fiscal.present? }
|
||||||
|
|
||||||
store_accessor :value_json, :numero_fiscal, :reference_avis
|
store_accessor :value_json, :numero_fiscal, :reference_avis
|
||||||
|
|
||||||
|
|
|
@ -6,7 +6,7 @@ class Champs::DropDownListChamp < Champ
|
||||||
THRESHOLD_NB_OPTIONS_AS_AUTOCOMPLETE = 20
|
THRESHOLD_NB_OPTIONS_AS_AUTOCOMPLETE = 20
|
||||||
OTHER = '__other__'
|
OTHER = '__other__'
|
||||||
delegate :options_without_empty_value_when_mandatory, to: :type_de_champ
|
delegate :options_without_empty_value_when_mandatory, to: :type_de_champ
|
||||||
validate :value_is_in_options, if: -> { !(value.blank? || drop_down_other?) && validate_champ_value_or_prefill? }
|
validate :value_is_in_options, if: -> { validate_champ_value? && !(value.blank? || drop_down_other?) }
|
||||||
|
|
||||||
def render_as_radios?
|
def render_as_radios?
|
||||||
drop_down_options.size <= THRESHOLD_NB_OPTIONS_AS_RADIO
|
drop_down_options.size <= THRESHOLD_NB_OPTIONS_AS_RADIO
|
||||||
|
|
|
@ -4,5 +4,5 @@ class Champs::EmailChamp < Champs::TextChamp
|
||||||
include EmailSanitizableConcern
|
include EmailSanitizableConcern
|
||||||
before_validation -> { sanitize_email(:value) }
|
before_validation -> { sanitize_email(:value) }
|
||||||
|
|
||||||
validates :value, allow_blank: true, format: { with: StrictEmailValidator::REGEXP }, if: :validate_champ_value_or_prefill?
|
validates :value, allow_blank: true, format: { with: StrictEmailValidator::REGEXP }, if: :validate_champ_value?
|
||||||
end
|
end
|
||||||
|
|
|
@ -5,5 +5,5 @@ class Champs::EngagementJuridiqueChamp < Champ
|
||||||
validates_with ExpressionReguliereValidator,
|
validates_with ExpressionReguliereValidator,
|
||||||
expression_reguliere: /([A-Z]|[0-9]|\-|\_|\+|\/)+/,
|
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 : “-“ ; “_“ ; “+“ ; “/“",
|
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?
|
if: :validate_champ_value?
|
||||||
end
|
end
|
||||||
|
|
|
@ -5,9 +5,9 @@ class Champs::EpciChamp < Champs::TextChamp
|
||||||
before_validation :on_departement_change
|
before_validation :on_departement_change
|
||||||
before_validation :on_epci_name_changes
|
before_validation :on_epci_name_changes
|
||||||
|
|
||||||
validate :code_departement_in_departement_codes, if: -> { !(code_departement.nil?) && validate_champ_value_or_prefill? }
|
validate :code_departement_in_departement_codes, if: -> { !(code_departement.nil?) && validate_champ_value? }
|
||||||
validate :external_id_in_departement_epci_codes, if: -> { !(code_departement.nil? || external_id.nil?) && validate_champ_value_or_prefill? }
|
validate :external_id_in_departement_epci_codes, if: -> { !(code_departement.nil? || external_id.nil?) && validate_champ_value? }
|
||||||
validate :value_in_departement_epci_names, if: -> { !(code_departement.nil? || external_id.nil? || value.nil?) && validate_champ_value_or_prefill? }
|
validate :value_in_departement_epci_names, if: -> { !(code_departement.nil? || external_id.nil? || value.nil?) && validate_champ_value? }
|
||||||
|
|
||||||
def departement_name
|
def departement_name
|
||||||
APIGeoService.departement_name(code_departement)
|
APIGeoService.departement_name(code_departement)
|
||||||
|
|
|
@ -1,5 +1,5 @@
|
||||||
# frozen_string_literal: true
|
# frozen_string_literal: true
|
||||||
|
|
||||||
class Champs::ExpressionReguliereChamp < Champ
|
class Champs::ExpressionReguliereChamp < Champ
|
||||||
validates_with ExpressionReguliereValidator, if: :validate_champ_value_or_prefill?
|
validates_with ExpressionReguliereValidator, if: :validate_champ_value?
|
||||||
end
|
end
|
||||||
|
|
|
@ -1,7 +1,7 @@
|
||||||
# frozen_string_literal: true
|
# frozen_string_literal: true
|
||||||
|
|
||||||
class Champs::IbanChamp < Champ
|
class Champs::IbanChamp < Champ
|
||||||
validates_with IbanValidator, if: :validate_champ_value_or_prefill?
|
validates_with IbanValidator, if: :validate_champ_value?
|
||||||
after_validation :format_iban
|
after_validation :format_iban
|
||||||
|
|
||||||
private
|
private
|
||||||
|
|
|
@ -11,7 +11,7 @@ class Champs::IntegerNumberChamp < Champ
|
||||||
# i18n-tasks-use t('errors.messages.not_an_integer')
|
# i18n-tasks-use t('errors.messages.not_an_integer')
|
||||||
object.errors.generate_message(:value, :not_an_integer)
|
object.errors.generate_message(:value, :not_an_integer)
|
||||||
}
|
}
|
||||||
}, if: :validate_champ_value_or_prefill?
|
}, if: :validate_champ_value?
|
||||||
|
|
||||||
def format_value
|
def format_value
|
||||||
return if value.blank?
|
return if value.blank?
|
||||||
|
|
|
@ -1,7 +1,7 @@
|
||||||
# frozen_string_literal: true
|
# frozen_string_literal: true
|
||||||
|
|
||||||
class Champs::MultipleDropDownListChamp < Champ
|
class Champs::MultipleDropDownListChamp < Champ
|
||||||
validate :values_are_in_options, if: -> { value.present? && validate_champ_value_or_prefill? }
|
validate :values_are_in_options, if: -> { value.present? && validate_champ_value? }
|
||||||
|
|
||||||
THRESHOLD_NB_OPTIONS_AS_CHECKBOX = 5
|
THRESHOLD_NB_OPTIONS_AS_CHECKBOX = 5
|
||||||
|
|
||||||
|
|
|
@ -7,5 +7,5 @@ class Champs::PhoneChamp < Champs::TextChamp
|
||||||
allow_blank: true,
|
allow_blank: true,
|
||||||
message: I18n.t(:not_a_phone, scope: 'activerecord.errors.messages')
|
message: I18n.t(:not_a_phone, scope: 'activerecord.errors.messages')
|
||||||
},
|
},
|
||||||
if: -> { !Phonelib.valid_for_countries?(value, TypesDeChamp::PhoneTypeDeChamp::DEFAULT_COUNTRY_CODES) && validate_champ_value_or_prefill? }
|
if: -> { validate_champ_value? && !Phonelib.valid_for_countries?(value, TypesDeChamp::PhoneTypeDeChamp::DEFAULT_COUNTRY_CODES) }
|
||||||
end
|
end
|
||||||
|
|
|
@ -5,14 +5,13 @@ class Champs::PieceJustificativeChamp < Champ
|
||||||
|
|
||||||
has_many_attached :piece_justificative_file
|
has_many_attached :piece_justificative_file
|
||||||
|
|
||||||
# TODO: if: -> { validate_champ_value? || validation_context == :prefill }
|
|
||||||
validates :piece_justificative_file,
|
validates :piece_justificative_file,
|
||||||
size: { less_than: FILE_MAX_SIZE },
|
size: { less_than: FILE_MAX_SIZE },
|
||||||
if: -> { !type_de_champ.skip_pj_validation }
|
if: -> { can_validate? && !type_de_champ.skip_pj_validation }
|
||||||
|
|
||||||
validates :piece_justificative_file,
|
validates :piece_justificative_file,
|
||||||
content_type: AUTHORIZED_CONTENT_TYPES,
|
content_type: AUTHORIZED_CONTENT_TYPES,
|
||||||
if: -> { !type_de_champ.skip_content_type_pj_validation }
|
if: -> { can_validate? && !type_de_champ.skip_content_type_pj_validation }
|
||||||
|
|
||||||
def main_value_name
|
def main_value_name
|
||||||
:piece_justificative_file
|
:piece_justificative_file
|
||||||
|
|
|
@ -1,8 +1,8 @@
|
||||||
# frozen_string_literal: true
|
# frozen_string_literal: true
|
||||||
|
|
||||||
class Champs::RegionChamp < Champs::TextChamp
|
class Champs::RegionChamp < Champs::TextChamp
|
||||||
validate :value_in_region_names, if: -> { !value.nil? && validate_champ_value_or_prefill? }
|
validate :value_in_region_names, if: -> { !value.nil? && validate_champ_value? }
|
||||||
validate :external_id_in_region_codes, if: -> { !external_id.nil? && validate_champ_value_or_prefill? }
|
validate :external_id_in_region_codes, if: -> { !external_id.nil? && validate_champ_value? }
|
||||||
|
|
||||||
def selected
|
def selected
|
||||||
code
|
code
|
||||||
|
|
|
@ -5,7 +5,7 @@ class Champs::RNAChamp < Champ
|
||||||
|
|
||||||
validates :value, allow_blank: true, format: {
|
validates :value, allow_blank: true, format: {
|
||||||
with: /\AW[0-9A-Z]{9}\z/, message: I18n.t(:not_a_rna, scope: 'activerecord.errors.messages')
|
with: /\AW[0-9A-Z]{9}\z/, message: I18n.t(:not_a_rna, scope: 'activerecord.errors.messages')
|
||||||
}, if: :validate_champ_value_or_prefill?
|
}, if: :validate_champ_value?
|
||||||
|
|
||||||
delegate :id, to: :procedure, prefix: true
|
delegate :id, to: :procedure, prefix: true
|
||||||
|
|
||||||
|
|
|
@ -6,8 +6,10 @@ class Champs::TitreIdentiteChamp < Champ
|
||||||
|
|
||||||
has_many_attached :piece_justificative_file
|
has_many_attached :piece_justificative_file
|
||||||
|
|
||||||
# TODO: if: -> { validate_champ_value? || validation_context == :prefill }
|
validates :piece_justificative_file,
|
||||||
validates :piece_justificative_file, content_type: ACCEPTED_FORMATS, size: { less_than: FILE_MAX_SIZE }
|
content_type: ACCEPTED_FORMATS,
|
||||||
|
size: { less_than: FILE_MAX_SIZE },
|
||||||
|
if: :validate_champ_value?
|
||||||
|
|
||||||
def main_value_name
|
def main_value_name
|
||||||
:piece_justificative_file
|
:piece_justificative_file
|
||||||
|
|
|
@ -19,6 +19,8 @@ module ChampValidateConcern
|
||||||
public? && can_validate? && visible?
|
public? && can_validate? && visible?
|
||||||
when :champs_private_value
|
when :champs_private_value
|
||||||
private? && can_validate? && visible?
|
private? && can_validate? && visible?
|
||||||
|
when :prefill
|
||||||
|
true
|
||||||
else
|
else
|
||||||
false
|
false
|
||||||
end
|
end
|
||||||
|
@ -27,9 +29,5 @@ module ChampValidateConcern
|
||||||
def can_validate?
|
def can_validate?
|
||||||
in_dossier_revision? && is_same_type_as_revision? && !row? && !in_discarded_row?
|
in_dossier_revision? && is_same_type_as_revision? && !row? && !in_discarded_row?
|
||||||
end
|
end
|
||||||
|
|
||||||
def validate_champ_value_or_prefill?
|
|
||||||
validate_champ_value? || validation_context == :prefill
|
|
||||||
end
|
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
|
@ -295,7 +295,7 @@ def dossier_factory_create_champ_or_repetition(type_de_champ, dossier)
|
||||||
types_de_champ = dossier.revision.children_of(type_de_champ)
|
types_de_champ = dossier.revision.children_of(type_de_champ)
|
||||||
2.times do
|
2.times do
|
||||||
row_id = ULID.generate
|
row_id = ULID.generate
|
||||||
type_de_champ.build_champ(dossier:, row_id:).save!
|
dossier.champs << type_de_champ.build_champ(row_id:)
|
||||||
types_de_champ.each do |type_de_champ|
|
types_de_champ.each do |type_de_champ|
|
||||||
dossier_factory_create_champ(type_de_champ, dossier, row_id:)
|
dossier_factory_create_champ(type_de_champ, dossier, row_id:)
|
||||||
end
|
end
|
||||||
|
@ -313,6 +313,6 @@ def dossier_factory_create_champ(type_de_champ, dossier, row_id: nil)
|
||||||
elsif type_de_champ.multiple_drop_down_list?
|
elsif type_de_champ.multiple_drop_down_list?
|
||||||
type_de_champ.drop_down_options.first(2).to_json
|
type_de_champ.drop_down_options.first(2).to_json
|
||||||
end
|
end
|
||||||
attrs = { stable_id: type_de_champ.stable_id, private: type_de_champ.private?, row_id:, dossier:, value: }.compact
|
attrs = { stable_id: type_de_champ.stable_id, private: type_de_champ.private?, row_id:, value: }.compact
|
||||||
create(:"champ_do_not_use_#{type_de_champ.type_champ}", **attrs)
|
dossier.champs << build(:"champ_do_not_use_#{type_de_champ.type_champ}", **attrs)
|
||||||
end
|
end
|
||||||
|
|
|
@ -1,9 +1,18 @@
|
||||||
# frozen_string_literal: true
|
# frozen_string_literal: true
|
||||||
|
|
||||||
describe Champs::DossierLinkChamp, type: :model do
|
describe Champs::DossierLinkChamp, type: :model do
|
||||||
|
let(:champ) { Champs::DossierLinkChamp.new(value:, dossier: build(:dossier)) }
|
||||||
|
let(:mandatory) { false }
|
||||||
|
|
||||||
|
before do
|
||||||
|
allow(champ).to receive(:type_de_champ).and_return(build(:type_de_champ_dossier_link, mandatory:))
|
||||||
|
allow(champ).to receive(:in_dossier_revision?).and_return(true)
|
||||||
|
end
|
||||||
|
|
||||||
describe 'prefilling validations' do
|
describe 'prefilling validations' do
|
||||||
|
let(:linked_dossier) { create(:dossier) }
|
||||||
describe 'value' do
|
describe 'value' do
|
||||||
subject { described_class.new(value:, dossier: build(:dossier)).valid?(:prefill) }
|
subject { champ.valid?(:prefill) }
|
||||||
|
|
||||||
context 'when nil' do
|
context 'when nil' do
|
||||||
let(:value) { nil }
|
let(:value) { nil }
|
||||||
|
@ -18,13 +27,13 @@ describe Champs::DossierLinkChamp, type: :model do
|
||||||
end
|
end
|
||||||
|
|
||||||
context 'when an integer' do
|
context 'when an integer' do
|
||||||
let(:value) { 42 }
|
let(:value) { linked_dossier.id }
|
||||||
|
|
||||||
it { expect(subject).to eq(true) }
|
it { expect(subject).to eq(true) }
|
||||||
end
|
end
|
||||||
|
|
||||||
context 'when a string representing an integer' do
|
context 'when a string representing an integer' do
|
||||||
let(:value) { "42" }
|
let(:value) { linked_dossier.id.to_s }
|
||||||
|
|
||||||
it { expect(subject).to eq(true) }
|
it { expect(subject).to eq(true) }
|
||||||
end
|
end
|
||||||
|
@ -38,14 +47,7 @@ describe Champs::DossierLinkChamp, type: :model do
|
||||||
end
|
end
|
||||||
|
|
||||||
describe 'validation' do
|
describe 'validation' do
|
||||||
let(:champ) { Champs::DossierLinkChamp.new(value:, dossier: build(:dossier)) }
|
before { champ.run_callbacks(:validation) }
|
||||||
|
|
||||||
before do
|
|
||||||
allow(champ).to receive(:type_de_champ).and_return(build(:type_de_champ_dossier_link, mandatory:))
|
|
||||||
allow(champ).to receive(:in_dossier_revision?).and_return(true)
|
|
||||||
champ.run_callbacks(:validation)
|
|
||||||
end
|
|
||||||
|
|
||||||
subject { champ.validate(:champs_public_value) }
|
subject { champ.validate(:champs_public_value) }
|
||||||
|
|
||||||
context 'when not mandatory' do
|
context 'when not mandatory' do
|
||||||
|
|
|
@ -1,15 +1,18 @@
|
||||||
# frozen_string_literal: true
|
# frozen_string_literal: true
|
||||||
|
|
||||||
describe Champs::EpciChamp, type: :model do
|
describe Champs::EpciChamp, type: :model do
|
||||||
|
let(:champ) { Champs::EpciChamp.new(code_departement: code_departement, dossier: build(:dossier)) }
|
||||||
|
let(:code_departement) { nil }
|
||||||
|
|
||||||
|
before do
|
||||||
|
allow(champ).to receive(:visible?).and_return(true)
|
||||||
|
allow(champ).to receive(:can_validate?).and_return(true)
|
||||||
|
end
|
||||||
|
|
||||||
describe 'validations' do
|
describe 'validations' do
|
||||||
subject { champ.validate(:champs_public_value) }
|
subject { champ.validate(:champs_public_value) }
|
||||||
|
|
||||||
describe 'code_departement' do
|
describe 'code_departement' do
|
||||||
let(:champ) { Champs::EpciChamp.new(code_departement: code_departement, dossier: build(:dossier)) }
|
|
||||||
before do
|
|
||||||
allow(champ).to receive(:visible?).and_return(true)
|
|
||||||
allow(champ).to receive(:can_validate?).and_return(true)
|
|
||||||
end
|
|
||||||
context 'when nil' do
|
context 'when nil' do
|
||||||
let(:code_departement) { nil }
|
let(:code_departement) { nil }
|
||||||
|
|
||||||
|
@ -156,7 +159,6 @@ describe Champs::EpciChamp, type: :model do
|
||||||
end
|
end
|
||||||
|
|
||||||
describe 'value' do
|
describe 'value' do
|
||||||
let(:champ) { described_class.new }
|
|
||||||
let(:epci) { APIGeoService.epcis('01').first }
|
let(:epci) { APIGeoService.epcis('01').first }
|
||||||
|
|
||||||
it 'with departement and code' do
|
it 'with departement and code' do
|
||||||
|
|
|
@ -5,10 +5,12 @@ require 'active_storage_validations/matchers'
|
||||||
describe Champs::PieceJustificativeChamp do
|
describe Champs::PieceJustificativeChamp do
|
||||||
include ActiveStorageValidations::Matchers
|
include ActiveStorageValidations::Matchers
|
||||||
|
|
||||||
|
let(:procedure) { create(:procedure, types_de_champ_public: [{ type: :piece_justificative }]) }
|
||||||
|
let(:dossier) { create(:dossier, :with_populated_champs, procedure:) }
|
||||||
|
let(:champ) { dossier.champs.first }
|
||||||
|
|
||||||
describe "validations" do
|
describe "validations" do
|
||||||
let(:champ) { Champs::PieceJustificativeChamp.new }
|
|
||||||
subject { champ }
|
subject { champ }
|
||||||
before { allow(champ).to receive(:type_de_champ).and_return(build(:type_de_champ_piece_justificative)) }
|
|
||||||
|
|
||||||
context "by default" do
|
context "by default" do
|
||||||
it { is_expected.to validate_size_of(:piece_justificative_file).less_than(Champs::PieceJustificativeChamp::FILE_MAX_SIZE) }
|
it { is_expected.to validate_size_of(:piece_justificative_file).less_than(Champs::PieceJustificativeChamp::FILE_MAX_SIZE) }
|
||||||
|
@ -19,20 +21,17 @@ describe Champs::PieceJustificativeChamp do
|
||||||
context "when validation is disabled" do
|
context "when validation is disabled" do
|
||||||
before { champ.type_de_champ.update(skip_pj_validation: true) }
|
before { champ.type_de_champ.update(skip_pj_validation: true) }
|
||||||
|
|
||||||
it { is_expected.not_to validate_size_of(:piece_justificative_file).less_than(Champs::PieceJustificativeChamp::FILE_MAX_SIZE) }
|
it { is_expected.not_to validate_size_of(:piece_justificative_file).on(:champs_public_value).less_than(Champs::PieceJustificativeChamp::FILE_MAX_SIZE) }
|
||||||
end
|
end
|
||||||
|
|
||||||
context "when content-type validation is disabled" do
|
context "when content-type validation is disabled" do
|
||||||
before { champ.type_de_champ.update(skip_content_type_pj_validation: true) }
|
before { champ.type_de_champ.update(skip_content_type_pj_validation: true) }
|
||||||
|
|
||||||
it { is_expected.not_to validate_content_type_of(:piece_justificative_file).rejecting('application/x-ms-dos-executable') }
|
it { is_expected.not_to validate_content_type_of(:piece_justificative_file).on(:champs_public_value).rejecting('application/x-ms-dos-executable') }
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
describe "#for_export" do
|
describe "#for_export" do
|
||||||
let(:procedure) { create(:procedure, types_de_champ_public: [{ type: :piece_justificative }]) }
|
|
||||||
let(:dossier) { create(:dossier, :with_populated_champs, procedure:) }
|
|
||||||
let(:champ) { dossier.champs.first }
|
|
||||||
subject { champ.type_de_champ.champ_value_for_export(champ) }
|
subject { champ.type_de_champ.champ_value_for_export(champ) }
|
||||||
|
|
||||||
it { is_expected.to eq('toto.txt') }
|
it { is_expected.to eq('toto.txt') }
|
||||||
|
@ -44,10 +43,6 @@ describe Champs::PieceJustificativeChamp do
|
||||||
end
|
end
|
||||||
|
|
||||||
describe '#for_api' do
|
describe '#for_api' do
|
||||||
let(:procedure) { create(:procedure, types_de_champ_public: [{ type: :piece_justificative }]) }
|
|
||||||
let(:dossier) { create(:dossier, :with_populated_champs, procedure:) }
|
|
||||||
let(:champ) { dossier.champs.first }
|
|
||||||
|
|
||||||
before { champ.piece_justificative_file.first.blob.update(virus_scan_result:) }
|
before { champ.piece_justificative_file.first.blob.update(virus_scan_result:) }
|
||||||
|
|
||||||
subject { champ.type_de_champ.champ_value_for_api(champ, version: 1) }
|
subject { champ.type_de_champ.champ_value_for_api(champ, version: 1) }
|
||||||
|
|
|
@ -51,6 +51,34 @@ RSpec.describe ChampValidateConcern do
|
||||||
expect(dossier.errors).to be_empty
|
expect(dossier.errors).to be_empty
|
||||||
}
|
}
|
||||||
end
|
end
|
||||||
|
|
||||||
|
context 'attachments' do
|
||||||
|
let(:types_de_champ_public) { [{ type: :piece_justificative }, { type: :titre_identite }] }
|
||||||
|
|
||||||
|
before {
|
||||||
|
dossier.revision.revision_types_de_champ.delete_all
|
||||||
|
dossier.validate(:champs_public_value)
|
||||||
|
}
|
||||||
|
it {
|
||||||
|
expect(dossier.revision.revision_types_de_champ).to be_empty
|
||||||
|
expect(dossier.champs).not_to be_empty
|
||||||
|
expect(dossier.errors).to be_empty
|
||||||
|
}
|
||||||
|
end
|
||||||
|
|
||||||
|
context 'drop_down_list' do
|
||||||
|
let(:types_de_champ_public) { [{ type: :drop_down_list }] }
|
||||||
|
|
||||||
|
before {
|
||||||
|
dossier.revision.revision_types_de_champ.delete_all
|
||||||
|
dossier.validate(:champs_public_value)
|
||||||
|
}
|
||||||
|
it {
|
||||||
|
expect(dossier.revision.revision_types_de_champ).to be_empty
|
||||||
|
expect(dossier.champs).not_to be_empty
|
||||||
|
expect(dossier.errors).to be_empty
|
||||||
|
}
|
||||||
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
context 'when type changed' do
|
context 'when type changed' do
|
||||||
|
|
|
@ -2133,21 +2133,21 @@ describe Dossier, type: :model do
|
||||||
expect(champ_titre_identite.piece_justificative_file.attached?).to be_truthy
|
expect(champ_titre_identite.piece_justificative_file.attached?).to be_truthy
|
||||||
expect(champ_titre_identite_vide.piece_justificative_file.attached?).to be_falsey
|
expect(champ_titre_identite_vide.piece_justificative_file.attached?).to be_falsey
|
||||||
dossier.accepter!(instructeur: dossier.followers_instructeurs.first, motivation: "yolo!")
|
dossier.accepter!(instructeur: dossier.followers_instructeurs.first, motivation: "yolo!")
|
||||||
expect(champ_titre_identite.piece_justificative_file.attached?).to be_falsey
|
expect(Champ.exists?(champ_titre_identite.id)).to be_falsey
|
||||||
end
|
end
|
||||||
|
|
||||||
it "clean up titres identite on refuser" do
|
it "clean up titres identite on refuser" do
|
||||||
expect(champ_titre_identite.piece_justificative_file.attached?).to be_truthy
|
expect(champ_titre_identite.piece_justificative_file.attached?).to be_truthy
|
||||||
expect(champ_titre_identite_vide.piece_justificative_file.attached?).to be_falsey
|
expect(champ_titre_identite_vide.piece_justificative_file.attached?).to be_falsey
|
||||||
dossier.refuser!(instructeur: dossier.followers_instructeurs.first, motivation: "yolo!")
|
dossier.refuser!(instructeur: dossier.followers_instructeurs.first, motivation: "yolo!")
|
||||||
expect(champ_titre_identite.piece_justificative_file.attached?).to be_falsey
|
expect(Champ.exists?(champ_titre_identite.id)).to be_falsey
|
||||||
end
|
end
|
||||||
|
|
||||||
it "clean up titres identite on classer_sans_suite" do
|
it "clean up titres identite on classer_sans_suite" do
|
||||||
expect(champ_titre_identite.piece_justificative_file.attached?).to be_truthy
|
expect(champ_titre_identite.piece_justificative_file.attached?).to be_truthy
|
||||||
expect(champ_titre_identite_vide.piece_justificative_file.attached?).to be_falsey
|
expect(champ_titre_identite_vide.piece_justificative_file.attached?).to be_falsey
|
||||||
dossier.classer_sans_suite!(instructeur: dossier.followers_instructeurs.first, motivation: "yolo!")
|
dossier.classer_sans_suite!(instructeur: dossier.followers_instructeurs.first, motivation: "yolo!")
|
||||||
expect(champ_titre_identite.piece_justificative_file.attached?).to be_falsey
|
expect(Champ.exists?(champ_titre_identite.id)).to be_falsey
|
||||||
end
|
end
|
||||||
|
|
||||||
context 'en_construction' do
|
context 'en_construction' do
|
||||||
|
@ -2158,7 +2158,7 @@ describe Dossier, type: :model do
|
||||||
expect(champ_titre_identite.piece_justificative_file.attached?).to be_truthy
|
expect(champ_titre_identite.piece_justificative_file.attached?).to be_truthy
|
||||||
expect(champ_titre_identite_vide.piece_justificative_file.attached?).to be_falsey
|
expect(champ_titre_identite_vide.piece_justificative_file.attached?).to be_falsey
|
||||||
dossier.accepter_automatiquement!
|
dossier.accepter_automatiquement!
|
||||||
expect(champ_titre_identite.piece_justificative_file.attached?).to be_falsey
|
expect(Champ.exists?(champ_titre_identite.id)).to be_falsey
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
|
@ -3,7 +3,8 @@
|
||||||
RSpec.describe PrefillChamps do
|
RSpec.describe PrefillChamps do
|
||||||
describe "#to_a", vcr: { cassette_name: 'api_geo_all' } do
|
describe "#to_a", vcr: { cassette_name: 'api_geo_all' } do
|
||||||
let(:procedure) { create(:procedure, :published, types_de_champ_public:, types_de_champ_private:) }
|
let(:procedure) { create(:procedure, :published, types_de_champ_public:, types_de_champ_private:) }
|
||||||
let(:dossier) { create(:dossier, :brouillon, procedure: procedure) }
|
let(:dossier) { create(:dossier, :brouillon, procedure:) }
|
||||||
|
let(:linked_dossier) { create(:dossier, :en_construction, procedure:) }
|
||||||
let(:types_de_champ_public) { [] }
|
let(:types_de_champ_public) { [] }
|
||||||
let(:types_de_champ_private) { [] }
|
let(:types_de_champ_private) { [] }
|
||||||
|
|
||||||
|
@ -68,11 +69,12 @@ RSpec.describe PrefillChamps do
|
||||||
let(:types_de_champ_public) { [{ type: type_de_champ_type }] }
|
let(:types_de_champ_public) { [{ type: type_de_champ_type }] }
|
||||||
let(:type_de_champ) { procedure.published_revision.types_de_champ_public.first }
|
let(:type_de_champ) { procedure.published_revision.types_de_champ_public.first }
|
||||||
let(:champ) { find_champ_by_stable_id(dossier, type_de_champ.stable_id) }
|
let(:champ) { find_champ_by_stable_id(dossier, type_de_champ.stable_id) }
|
||||||
|
let(:champ_value) { value == 'linked_dossier_id' ? linked_dossier.id : value }
|
||||||
|
|
||||||
let(:params) { { "champ_#{type_de_champ.to_typed_id_for_query}" => value } }
|
let(:params) { { "champ_#{type_de_champ.to_typed_id_for_query}" => champ_value } }
|
||||||
|
|
||||||
it "builds an array of hash matching the given params" do
|
it "builds an array of hash matching the given params" do
|
||||||
expect(prefill_champs_array).to match([{ id: champ.id }.merge(attributes(champ, value))])
|
expect(prefill_champs_array).to match([{ id: champ.id }.merge(attributes(champ, champ_value))])
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
@ -82,11 +84,12 @@ RSpec.describe PrefillChamps do
|
||||||
let(:types_de_champ_private) { [{ type: type_de_champ_type }] }
|
let(:types_de_champ_private) { [{ type: type_de_champ_type }] }
|
||||||
let(:type_de_champ) { procedure.published_revision.types_de_champ_private.first }
|
let(:type_de_champ) { procedure.published_revision.types_de_champ_private.first }
|
||||||
let(:champ) { find_champ_by_stable_id(dossier, type_de_champ.stable_id) }
|
let(:champ) { find_champ_by_stable_id(dossier, type_de_champ.stable_id) }
|
||||||
|
let(:champ_value) { value == 'linked_dossier_id' ? linked_dossier.id : value }
|
||||||
|
|
||||||
let(:params) { { "champ_#{type_de_champ.to_typed_id_for_query}" => value } }
|
let(:params) { { "champ_#{type_de_champ.to_typed_id_for_query}" => champ_value } }
|
||||||
|
|
||||||
it "builds an array of hash matching the given params" do
|
it "builds an array of hash matching the given params" do
|
||||||
expect(prefill_champs_array).to match([{ id: champ.id }.merge(attributes(champ, value))])
|
expect(prefill_champs_array).to match([{ id: champ.id }.merge(attributes(champ, champ_value))])
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
@ -125,7 +128,7 @@ RSpec.describe PrefillChamps do
|
||||||
it_behaves_like "a champ public value that is authorized", :communes, ['01540', '01457']
|
it_behaves_like "a champ public value that is authorized", :communes, ['01540', '01457']
|
||||||
it_behaves_like "a champ public value that is authorized", :address, "20 avenue de Ségur 75007 Paris"
|
it_behaves_like "a champ public value that is authorized", :address, "20 avenue de Ségur 75007 Paris"
|
||||||
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", :multiple_drop_down_list, ["val1", "val2"]
|
||||||
it_behaves_like "a champ public value that is authorized", :dossier_link, "1"
|
it_behaves_like "a champ public value that is authorized", :dossier_link, 'linked_dossier_id'
|
||||||
it_behaves_like "a champ public value that is authorized", :epci, ['01', '200042935']
|
it_behaves_like "a champ public value that is authorized", :epci, ['01', '200042935']
|
||||||
it_behaves_like "a champ public value that is authorized", :siret, "13002526500013"
|
it_behaves_like "a champ public value that is authorized", :siret, "13002526500013"
|
||||||
|
|
||||||
|
@ -167,7 +170,7 @@ RSpec.describe PrefillChamps do
|
||||||
it_behaves_like "a champ private value that is authorized", :communes, ['01540', '01457']
|
it_behaves_like "a champ private value that is authorized", :communes, ['01540', '01457']
|
||||||
it_behaves_like "a champ private value that is authorized", :address, "20 avenue de Ségur 75007 Paris"
|
it_behaves_like "a champ private value that is authorized", :address, "20 avenue de Ségur 75007 Paris"
|
||||||
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", :multiple_drop_down_list, ["val1", "val2"]
|
||||||
it_behaves_like "a champ private value that is authorized", :dossier_link, "1"
|
it_behaves_like "a champ private value that is authorized", :dossier_link, 'linked_dossier_id'
|
||||||
it_behaves_like "a champ private value that is authorized", :epci, ['01', '200042935']
|
it_behaves_like "a champ private value that is authorized", :epci, ['01', '200042935']
|
||||||
|
|
||||||
context "when the private type de champ is authorized (repetition)" do
|
context "when the private type de champ is authorized (repetition)" do
|
||||||
|
|
|
@ -19,6 +19,7 @@ describe 'Prefilling a dossier (with a GET request):', js: true do
|
||||||
end
|
end
|
||||||
let(:procedure) { create(:procedure, :for_individual, :published, opendata: true, types_de_champ_public:) }
|
let(:procedure) { create(:procedure, :for_individual, :published, opendata: true, types_de_champ_public:) }
|
||||||
let(:dossier) { procedure.dossiers.last }
|
let(:dossier) { procedure.dossiers.last }
|
||||||
|
let(:linked_dossier) { create(:dossier, :en_construction, procedure:) }
|
||||||
let(:types_de_champ) { procedure.active_revision.types_de_champ_public }
|
let(:types_de_champ) { procedure.active_revision.types_de_champ_public }
|
||||||
|
|
||||||
let(:type_de_champ_text) { types_de_champ[0] }
|
let(:type_de_champ_text) { types_de_champ[0] }
|
||||||
|
@ -43,7 +44,7 @@ describe 'Prefilling a dossier (with a GET request):', js: true do
|
||||||
]
|
]
|
||||||
}
|
}
|
||||||
let(:epci_value) { ['01', '200029999'] }
|
let(:epci_value) { ['01', '200029999'] }
|
||||||
let(:dossier_link_value) { '42' }
|
let(:dossier_link_value) { linked_dossier.id }
|
||||||
let(:commune_value) { ['01540', '01457'] }
|
let(:commune_value) { ['01540', '01457'] }
|
||||||
let(:commune_libelle) { 'Vonnas (01540)' }
|
let(:commune_libelle) { 'Vonnas (01540)' }
|
||||||
let(:address_value) { "20 Avenue de Ségur 75007 Paris" }
|
let(:address_value) { "20 Avenue de Ségur 75007 Paris" }
|
||||||
|
|
|
@ -19,6 +19,7 @@ describe 'Prefilling a dossier (with a POST request):', js: true do
|
||||||
end
|
end
|
||||||
let(:procedure) { create(:procedure, :for_individual, :published, types_de_champ_public:) }
|
let(:procedure) { create(:procedure, :for_individual, :published, types_de_champ_public:) }
|
||||||
let(:dossier) { procedure.dossiers.last }
|
let(:dossier) { procedure.dossiers.last }
|
||||||
|
let(:linked_dossier) { create(:dossier, :en_construction, procedure:) }
|
||||||
let(:types_de_champ) { procedure.active_revision.types_de_champ_public }
|
let(:types_de_champ) { procedure.active_revision.types_de_champ_public }
|
||||||
|
|
||||||
let(:type_de_champ_text) { types_de_champ[0] }
|
let(:type_de_champ_text) { types_de_champ[0] }
|
||||||
|
@ -51,7 +52,7 @@ describe 'Prefilling a dossier (with a POST request):', js: true do
|
||||||
let(:integer_repetition_libelle) { sub_type_de_champs_repetition.second.libelle }
|
let(:integer_repetition_libelle) { sub_type_de_champs_repetition.second.libelle }
|
||||||
let(:text_repetition_value) { "First repetition text" }
|
let(:text_repetition_value) { "First repetition text" }
|
||||||
let(:integer_repetition_value) { "42" }
|
let(:integer_repetition_value) { "42" }
|
||||||
let(:dossier_link_value) { '42' }
|
let(:dossier_link_value) { linked_dossier.id }
|
||||||
let(:prenom_value) { 'Jean' }
|
let(:prenom_value) { 'Jean' }
|
||||||
let(:nom_value) { 'Dupont' }
|
let(:nom_value) { 'Dupont' }
|
||||||
let(:genre_value) { 'M.' }
|
let(:genre_value) { 'M.' }
|
||||||
|
|
Loading…
Reference in a new issue