Merge pull request #9535 from demarches-simplifiees/feat/9411
ETQ administrateur, je veux pouvoir valider des champs avec des règles simples (Regexp)
This commit is contained in:
commit
870efba29b
36 changed files with 381 additions and 12 deletions
|
@ -0,0 +1,5 @@
|
|||
class EditableChamp::ExpressionReguliereComponent < EditableChamp::EditableChampBaseComponent
|
||||
def dsfr_input_classname
|
||||
'fr-input'
|
||||
end
|
||||
end
|
|
@ -0,0 +1 @@
|
|||
= @form.text_field(:value, input_opts(id: @champ.input_id, placeholder: @champ.expression_reguliere_exemple_text, required: @champ.required?, aria: { describedby: @champ.describedby_id }))
|
|
@ -40,6 +40,12 @@ fr:
|
|||
update_condition: La condition du champ « %{label} » a été modifiée. La nouvelle condition est « %{to} ».
|
||||
update_character_limit: La limite de caractères du champ texte « %{label} » a été modifiée. La nouvelle limite est « %{to} ».
|
||||
remove_character_limit: La limite de caractères du champ texte « %{label} » a été supprimée.
|
||||
remove_expression_reguliere: L’expression régulière du champ « %{label} » a été supprimée.
|
||||
update_expression_reguliere: L’expression régulière du champ « %{label} » a été modifiée. La nouvelle expression est « %{to} ».
|
||||
remove_expression_reguliere_exemple_text: L’exemple d’expression régulière du champ « %{label} » a été supprimé.
|
||||
update_expression_reguliere_exemple_text: L’exemple d’expression régulière du champ « %{label} » a été modifié. Le nouvel exemple est « %{to} ».
|
||||
remove_expression_reguliere_error_message: Le message d’erreur de l’expression régulière du champ « %{label} » a été supprimé.
|
||||
update_expression_reguliere_error_message: Le message d’erreur de l’expression régulière du champ « %{label} » a été modifié. Le nouveau message est « %{to} ».
|
||||
private:
|
||||
add: L’annotation privée « %{label} » a été ajoutée.
|
||||
remove: L’annotation privée « %{label} » a été supprimée.
|
||||
|
|
|
@ -141,6 +141,27 @@
|
|||
- else
|
||||
- list.with_item do
|
||||
= t(".#{prefix}.update_character_limit", label: change.label, to: change.to)
|
||||
- when :expression_reguliere
|
||||
- if change.to.blank?
|
||||
- list.with_item do
|
||||
= t(".#{prefix}.remove_expression_reguliere", label: change.label, to: change.to)
|
||||
- else
|
||||
- list.with_item do
|
||||
= t(".#{prefix}.update_expression_reguliere", label: change.label, to: change.to)
|
||||
- when :expression_reguliere_exemple_text
|
||||
- if change.to.blank?
|
||||
- list.with_item do
|
||||
= t(".#{prefix}.remove_expression_reguliere_exemple_text", label: change.label, to: change.to)
|
||||
- else
|
||||
- list.with_item do
|
||||
= t(".#{prefix}.update_expression_reguliere_exemple_text", label: change.label, to: change.to)
|
||||
- when :expression_reguliere_error_message
|
||||
- if change.to.blank?
|
||||
- list.with_item do
|
||||
= t(".#{prefix}.remove_expression_reguliere_error_message", label: change.label, to: change.to)
|
||||
- else
|
||||
- list.with_item do
|
||||
= t(".#{prefix}.update_expression_reguliere_error_message", label: change.label, to: change.to)
|
||||
|
||||
- if @public_move_changes.present?
|
||||
- list.with_item do
|
||||
|
|
|
@ -13,3 +13,8 @@ fr:
|
|||
character_limit:
|
||||
unlimited: Pas de limite de caractères
|
||||
limit: Limité à %{limit} caractères
|
||||
expression_reguliere:
|
||||
labels:
|
||||
regex: Saisissez votre expression régulière, essayez-la sur https://rubular.com
|
||||
valid_exemple: Exemple valide qui passe l'expression régulière
|
||||
error_message: Message d'erreur à afficher à l'usager en cas de saisie invalide
|
||||
|
|
|
@ -46,6 +46,23 @@
|
|||
%p
|
||||
%small Nous numérotons automatiquement les titres lorsqu’aucun de vos titres ne commence par un chiffre.
|
||||
|
||||
- if type_de_champ.expression_reguliere?
|
||||
.cell.mt-1
|
||||
= form.label :expression_reguliere, for: dom_id(type_de_champ, :expression_reguliere) do
|
||||
= t('.expression_reguliere.labels.regex')
|
||||
= form.text_field :expression_reguliere, class: "fr-input small-margin small", id: dom_id(type_de_champ, :expression_reguliere)
|
||||
|
||||
.cell.mt-1
|
||||
= form.label :expression_reguliere_exemple_text, for: dom_id(type_de_champ, :expression_reguliere_exemple_text) do
|
||||
= t('.expression_reguliere.labels.valid_exemple')
|
||||
= form.text_field :expression_reguliere_exemple_text, class: "fr-input small-margin small", id: dom_id(type_de_champ, :expression_reguliere_exemple_text)
|
||||
- if type_de_champ.invalid_regexp?
|
||||
%p.fr-message.fr-message--error
|
||||
= type_de_champ.errors[:expression_reguliere_exemple_text].join(", ")
|
||||
.cell.mt-1
|
||||
= form.label :expression_reguliere_error_message, for: dom_id(type_de_champ, :expression_reguliere_error_message) do
|
||||
= t('.expression_reguliere.labels.error_message')
|
||||
= form.text_field :expression_reguliere_error_message, class: "fr-input small-margin small", id: dom_id(type_de_champ, :expression_reguliere_error_message)
|
||||
- if !type_de_champ.header_section? && !type_de_champ.titre_identite?
|
||||
.cell.mt-1
|
||||
= form.label :description, "Description du champ (optionnel)", for: dom_id(type_de_champ, :description)
|
||||
|
|
|
@ -15,6 +15,10 @@ class TypesDeChampEditor::ErrorsSummary < ApplicationComponent
|
|||
@revision.errors.include?(:header_section)
|
||||
end
|
||||
|
||||
def expression_reguliere_errors?
|
||||
@revision.errors.include?(:expression_reguliere)
|
||||
end
|
||||
|
||||
private
|
||||
|
||||
def errors_for(key)
|
||||
|
|
|
@ -6,3 +6,7 @@ fr:
|
|||
fix_header_section:
|
||||
one: 'Le titre de section suivant est invalide, veuillez le corriger :'
|
||||
other: 'Les titres de section suivants sont invalides, veuillez les corriger :'
|
||||
|
||||
fix_expressions_regulieres:
|
||||
one: "L'expression régulière suivante est invalide, veuillez la corriger :"
|
||||
other: 'Les expressions régulières suivantes sont invalides, veuillez les corriger :'
|
||||
|
|
|
@ -9,3 +9,7 @@
|
|||
- if header_section_errors?
|
||||
%p= t('.fix_header_section', count: errors_for(:header_section).size)
|
||||
= error_message_for(:header_section)
|
||||
|
||||
- if expression_reguliere_errors?
|
||||
%p= t('.fix_expressions_regulieres', count: errors_for(:expression_reguliere).size)
|
||||
= error_message_for(:expression_reguliere)
|
||||
|
|
|
@ -130,6 +130,9 @@ module Administrateurs
|
|||
:collapsible_explanation_text,
|
||||
:header_section_level,
|
||||
:character_limit,
|
||||
:expression_reguliere,
|
||||
:expression_reguliere_exemple_text,
|
||||
:expression_reguliere_error_message,
|
||||
editable_options: [
|
||||
:cadastres,
|
||||
:unesco,
|
||||
|
|
|
@ -114,7 +114,8 @@ class API::V2::Schema < GraphQL::Schema
|
|||
Types::Champs::Descriptor::TextareaChampDescriptorType,
|
||||
Types::Champs::Descriptor::TextChampDescriptorType,
|
||||
Types::Champs::Descriptor::TitreIdentiteChampDescriptorType,
|
||||
Types::Champs::Descriptor::YesNoChampDescriptorType
|
||||
Types::Champs::Descriptor::YesNoChampDescriptorType,
|
||||
Types::Champs::Descriptor::ExpressionReguliereChampDescriptorType
|
||||
|
||||
def self.unauthorized_object(error)
|
||||
# Add a top-level error to the response instead of returning nil:
|
||||
|
|
|
@ -2284,6 +2284,34 @@ type ExplicationChampDescriptor implements ChampDescriptor {
|
|||
type: TypeDeChamp! @deprecated(reason: "Utilisez le champ `__typename` à la place.")
|
||||
}
|
||||
|
||||
type ExpressionReguliereChampDescriptor implements ChampDescriptor {
|
||||
"""
|
||||
Description des champs d’un bloc répétable.
|
||||
"""
|
||||
champDescriptors: [ChampDescriptor!] @deprecated(reason: "Utilisez le champ `RepetitionChampDescriptor.champ_descriptors` à la place.")
|
||||
|
||||
"""
|
||||
Description du champ.
|
||||
"""
|
||||
description: String
|
||||
id: ID!
|
||||
|
||||
"""
|
||||
Libellé du champ.
|
||||
"""
|
||||
label: String!
|
||||
|
||||
"""
|
||||
Est-ce que le champ est obligatoire ?
|
||||
"""
|
||||
required: Boolean!
|
||||
|
||||
"""
|
||||
Type de la valeur du champ.
|
||||
"""
|
||||
type: TypeDeChamp! @deprecated(reason: "Utilisez le champ `__typename` à la place.")
|
||||
}
|
||||
|
||||
type File {
|
||||
byteSize: Int! @deprecated(reason: "Utilisez le champ `byteSizeBigInt` à la place.")
|
||||
byteSizeBigInt: BigInt!
|
||||
|
@ -3945,6 +3973,11 @@ enum TypeDeChamp {
|
|||
"""
|
||||
explication
|
||||
|
||||
"""
|
||||
Expression régulière
|
||||
"""
|
||||
expression_reguliere
|
||||
|
||||
"""
|
||||
Titre de section
|
||||
"""
|
||||
|
|
|
@ -96,6 +96,8 @@ module Types
|
|||
Types::Champs::Descriptor::EpciChampDescriptorType
|
||||
when TypeDeChamp.type_champs.fetch(:cojo)
|
||||
Types::Champs::Descriptor::COJOChampDescriptorType
|
||||
when TypeDeChamp.type_champs.fetch(:expression_reguliere)
|
||||
Types::Champs::Descriptor::ExpressionReguliereChampDescriptorType
|
||||
end
|
||||
end
|
||||
end
|
||||
|
|
|
@ -0,0 +1,5 @@
|
|||
module Types::Champs::Descriptor
|
||||
class ExpressionReguliereChampDescriptorType < Types::BaseObject
|
||||
implements Types::ChampDescriptorType
|
||||
end
|
||||
end
|
|
@ -58,6 +58,9 @@ class Champ < ApplicationRecord
|
|||
:character_limit?,
|
||||
:character_limit,
|
||||
:yes_no?,
|
||||
:expression_reguliere,
|
||||
:expression_reguliere_exemple_text,
|
||||
:expression_reguliere_error_message,
|
||||
to: :type_de_champ
|
||||
|
||||
delegate :to_typed_id, :to_typed_id_for_query, to: :type_de_champ, prefix: true
|
||||
|
|
3
app/models/champs/expression_reguliere_champ.rb
Normal file
3
app/models/champs/expression_reguliere_champ.rb
Normal file
|
@ -0,0 +1,3 @@
|
|||
class Champs::ExpressionReguliereChamp < Champ
|
||||
validates_with ExpressionReguliereValidator, if: -> { validation_context != :brouillon }
|
||||
end
|
|
@ -32,6 +32,10 @@ module DossierRebaseConcern
|
|||
!champs.filter { _1.stable_id == stable_id }.any? { _1.in?(options) }
|
||||
end
|
||||
|
||||
def can_rebase_expression_reguliere_change?(stable_id, expression_reguliere)
|
||||
false
|
||||
end
|
||||
|
||||
private
|
||||
|
||||
def accepted_en_construction_changes?
|
||||
|
|
|
@ -19,6 +19,7 @@ class ProcedureRevision < ApplicationRecord
|
|||
|
||||
validate :conditions_are_valid?
|
||||
validate :header_sections_are_valid?
|
||||
validate :expressions_regulieres_are_valid?
|
||||
|
||||
delegate :path, to: :procedure, prefix: true
|
||||
|
||||
|
@ -375,6 +376,25 @@ class ProcedureRevision < ApplicationRecord
|
|||
from_type_de_champ.character_limit,
|
||||
to_type_de_champ.character_limit)
|
||||
end
|
||||
elsif to_type_de_champ.expression_reguliere?
|
||||
if from_type_de_champ.expression_reguliere != to_type_de_champ.expression_reguliere
|
||||
changes << ProcedureRevisionChange::UpdateChamp.new(from_type_de_champ,
|
||||
:expression_reguliere,
|
||||
from_type_de_champ.expression_reguliere,
|
||||
to_type_de_champ.expression_reguliere)
|
||||
end
|
||||
if from_type_de_champ.expression_reguliere_exemple_text != to_type_de_champ.expression_reguliere_exemple_text
|
||||
changes << ProcedureRevisionChange::UpdateChamp.new(from_type_de_champ,
|
||||
:expression_reguliere_exemple_text,
|
||||
from_type_de_champ.expression_reguliere_exemple_text,
|
||||
to_type_de_champ.expression_reguliere_exemple_text)
|
||||
end
|
||||
if from_type_de_champ.expression_reguliere_error_message != to_type_de_champ.expression_reguliere_error_message
|
||||
changes << ProcedureRevisionChange::UpdateChamp.new(from_type_de_champ,
|
||||
:expression_reguliere_error_message,
|
||||
from_type_de_champ.expression_reguliere_error_message,
|
||||
to_type_de_champ.expression_reguliere_error_message)
|
||||
end
|
||||
end
|
||||
changes
|
||||
end
|
||||
|
@ -412,6 +432,16 @@ class ProcedureRevision < ApplicationRecord
|
|||
repetition_tdcs_errors + root_tdcs_errors
|
||||
end
|
||||
|
||||
def expressions_regulieres_are_valid?
|
||||
types_de_champ_public.to_a
|
||||
.flat_map { _1.repetition? ? children_of(_1) : _1 }
|
||||
.each do |tdc|
|
||||
if tdc.expression_reguliere? && tdc.invalid_regexp?
|
||||
errors.add(:expression_reguliere, type_de_champ: tdc)
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
def errors_for_header_sections_order(tdcs)
|
||||
tdcs
|
||||
.map.with_index
|
||||
|
|
|
@ -60,7 +60,6 @@ class ProcedureRevisionChange
|
|||
|
||||
def can_rebase?(dossier = nil)
|
||||
return true if private?
|
||||
|
||||
case attribute
|
||||
when :drop_down_options
|
||||
(from - to).empty? || dossier&.can_rebase_drop_down_options_change?(stable_id, from - to)
|
||||
|
@ -68,7 +67,7 @@ class ProcedureRevisionChange
|
|||
!from && to
|
||||
when :mandatory
|
||||
(from && !to) || dossier&.can_rebase_mandatory_change?(stable_id)
|
||||
when :type_champ, :condition
|
||||
when :type_champ, :condition, :expression_reguliere
|
||||
false
|
||||
else
|
||||
true
|
||||
|
|
|
@ -3,7 +3,8 @@ class TypeDeChamp < ApplicationRecord
|
|||
|
||||
FILE_MAX_SIZE = 200.megabytes
|
||||
FEATURE_FLAGS = {
|
||||
cojo: :cojo_type_de_champ
|
||||
cojo: :cojo_type_de_champ,
|
||||
expression_reguliere: :expression_reguliere_type_de_champ
|
||||
}
|
||||
MINIMUM_TEXTAREA_CHARACTER_LIMIT_LENGTH = 400
|
||||
|
||||
|
@ -55,7 +56,8 @@ class TypeDeChamp < ApplicationRecord
|
|||
dgfip: REFERENTIEL_EXTERNE,
|
||||
pole_emploi: REFERENTIEL_EXTERNE,
|
||||
mesri: REFERENTIEL_EXTERNE,
|
||||
cojo: REFERENTIEL_EXTERNE
|
||||
cojo: REFERENTIEL_EXTERNE,
|
||||
expression_reguliere: STANDARD
|
||||
}
|
||||
|
||||
enum type_champs: {
|
||||
|
@ -95,7 +97,8 @@ class TypeDeChamp < ApplicationRecord
|
|||
pole_emploi: 'pole_emploi',
|
||||
mesri: 'mesri',
|
||||
epci: 'epci',
|
||||
cojo: 'cojo'
|
||||
cojo: 'cojo',
|
||||
expression_reguliere: 'expression_reguliere'
|
||||
}
|
||||
|
||||
ROUTABLE_TYPES = [
|
||||
|
@ -116,6 +119,9 @@ class TypeDeChamp < ApplicationRecord
|
|||
:drop_down_secondary_description,
|
||||
:drop_down_other,
|
||||
:character_limit,
|
||||
:expression_reguliere,
|
||||
:expression_reguliere_exemple_text,
|
||||
:expression_reguliere_error_message,
|
||||
:collapsible_explanation_enabled,
|
||||
:collapsible_explanation_text,
|
||||
:header_section_level
|
||||
|
@ -184,6 +190,7 @@ class TypeDeChamp < ApplicationRecord
|
|||
|
||||
before_validation :check_mandatory
|
||||
before_validation :normalize_libelle
|
||||
|
||||
before_save :remove_piece_justificative_template, if: -> { type_champ_changed? }
|
||||
before_validation :remove_drop_down_list, if: -> { type_champ_changed? }
|
||||
before_save :remove_block, if: -> { type_champ_changed? }
|
||||
|
@ -414,6 +421,10 @@ class TypeDeChamp < ApplicationRecord
|
|||
type_champ == TypeDeChamp.type_champs.fetch(:checkbox)
|
||||
end
|
||||
|
||||
def expression_reguliere?
|
||||
type_champ == TypeDeChamp.type_champs.fetch(:expression_reguliere)
|
||||
end
|
||||
|
||||
def public?
|
||||
!private?
|
||||
end
|
||||
|
@ -604,6 +615,21 @@ class TypeDeChamp < ApplicationRecord
|
|||
type_champ.in?(ROUTABLE_TYPES)
|
||||
end
|
||||
|
||||
def invalid_regexp?
|
||||
return false if expression_reguliere.blank?
|
||||
return false if expression_reguliere_exemple_text.blank?
|
||||
return false if expression_reguliere_exemple_text.match?(Regexp.new(expression_reguliere, timeout: 2.0))
|
||||
|
||||
self.errors.add(:expression_reguliere_exemple_text, I18n.t('errors.messages.mismatch_regexp'))
|
||||
true
|
||||
rescue Regexp::TimeoutError
|
||||
self.errors.add(:expression_reguliere, I18n.t('errors.messages.evil_regexp'))
|
||||
true
|
||||
rescue RegexpError
|
||||
self.errors.add(:expression_reguliere, I18n.t('errors.messages.syntax_error_regexp'))
|
||||
true
|
||||
end
|
||||
|
||||
private
|
||||
|
||||
DEFAULT_EMPTY = ['']
|
||||
|
|
|
@ -0,0 +1,2 @@
|
|||
class TypesDeChamp::ExpressionReguliereTypeDeChamp < TypesDeChamp::TypeDeChampBase
|
||||
end
|
11
app/validators/expression_reguliere_validator.rb
Normal file
11
app/validators/expression_reguliere_validator.rb
Normal file
|
@ -0,0 +1,11 @@
|
|||
class ExpressionReguliereValidator < ActiveModel::Validator
|
||||
def validate(record)
|
||||
if record.value.present?
|
||||
if !record.value.match?(Regexp.new(record.expression_reguliere, timeout: 5.0))
|
||||
record.errors.add(:value, :invalid_regexp)
|
||||
end
|
||||
end
|
||||
rescue Regexp::TimeoutError
|
||||
record.errors.add(:expression_reguliere, :evil_regexp)
|
||||
end
|
||||
end
|
|
@ -684,6 +684,9 @@ en:
|
|||
procedure_archived:
|
||||
with_service_and_phone_email: This procedure has been closed, it is no longer possible to submit a file. For more information, please contact the service %{service_name}, available at %{service_phone_number} or by email %{service_email}
|
||||
with_organisation_only: This procedure has been closed, it is no longer possible to submit a file. For more information, please contact the organisation %{organisation_name}
|
||||
evil_regexp: The regular expression you have entered is potentially dangerous and could lead to performance issues.
|
||||
mismatch_regexp: The provided example must match the regular expression
|
||||
syntax_error_regexp: The syntax of the regular expression is invalid
|
||||
# # procedure_not_draft: "This procedure is not a draft anymore."
|
||||
# cadastres_empty:
|
||||
# one: "Aucune parcelle cadastrale sur la zone sélectionnée"
|
||||
|
|
|
@ -689,7 +689,9 @@ fr:
|
|||
procedure_archived:
|
||||
with_service_and_phone_email: Cette démarche en ligne a été close, il n’est plus possible de déposer de dossier. Pour plus d’informations veuillez contacter le service %{service_name} au %{service_phone_number} ou par email à %{service_email}
|
||||
with_organisation_only: Cette démarche en ligne a été close, il n’est plus possible de déposer de dossier. Pour plus d’informations veuillez contacter le service %{organisation_name}
|
||||
|
||||
evil_regexp: L'expression régulière que vous avez entrée est potentiellement dangereuse et pourrait entraîner des problèmes de performance
|
||||
mismatch_regexp: L'exemple doit correspondre à l'expression régulière fournie
|
||||
syntax_error_regexp: La syntaxe de l'expression régulière n'est pas valide
|
||||
empty_repetition: '« %{value} » doit comporter au moins un champ répétable'
|
||||
empty_drop_down: '« %{value} » doit comporter au moins un choix sélectionnable'
|
||||
# procedure_not_draft: "Cette démarche n’est maintenant plus en brouillon."
|
||||
|
|
|
@ -0,0 +1,8 @@
|
|||
en:
|
||||
activerecord:
|
||||
errors:
|
||||
models:
|
||||
champs/expression_reguliere_champ:
|
||||
attributes:
|
||||
value:
|
||||
invalid_regexp: does not match expected format
|
|
@ -0,0 +1,8 @@
|
|||
fr:
|
||||
activerecord:
|
||||
errors:
|
||||
models:
|
||||
champs/expression_reguliere_champ:
|
||||
attributes:
|
||||
value:
|
||||
invalid_regexp: ne correspond pas au format attendu
|
|
@ -55,6 +55,7 @@ en:
|
|||
mesri: "Data from Ministère de l’Enseignement Supérieur, de la Recherche et de l’Innovation"
|
||||
epci: "EPCI"
|
||||
cojo: "Accreditation Paris 2024"
|
||||
expression_reguliere: 'Regular expression'
|
||||
errors:
|
||||
type_de_champ:
|
||||
attributes:
|
||||
|
|
|
@ -55,6 +55,7 @@ fr:
|
|||
mesri: "Données du Ministère de l’Enseignement Supérieur, de la Recherche et de l’Innovation"
|
||||
epci: "EPCI"
|
||||
cojo: "Accréditation Paris 2024"
|
||||
expression_reguliere: 'Expression régulière'
|
||||
errors:
|
||||
type_de_champ:
|
||||
attributes:
|
||||
|
|
|
@ -243,6 +243,10 @@ FactoryBot.define do
|
|||
type_de_champ { association :type_de_champ_cojo, procedure: dossier.procedure }
|
||||
end
|
||||
|
||||
factory :champ_expression_reguliere, class: 'Champs::ExpressionReguliereChamp' do
|
||||
type_de_champ { association :type_de_champ_expression_reguliere, procedure: dossier.procedure }
|
||||
end
|
||||
|
||||
factory :champ_repetition, class: 'Champs::RepetitionChamp' do
|
||||
type_de_champ { association :type_de_champ_repetition, procedure: dossier.procedure }
|
||||
|
||||
|
|
|
@ -99,6 +99,9 @@ FactoryBot.define do
|
|||
type_champ { TypeDeChamp.type_champs.fetch(:linked_drop_down_list) }
|
||||
drop_down_list_value { "--primary--\nsecondary\n" }
|
||||
end
|
||||
factory :type_de_champ_expression_reguliere do
|
||||
type_champ { TypeDeChamp.type_champs.fetch(:expression_reguliere) }
|
||||
end
|
||||
factory :type_de_champ_pays do
|
||||
type_champ { TypeDeChamp.type_champs.fetch(:pays) }
|
||||
end
|
||||
|
|
|
@ -14,9 +14,9 @@ describe '20220705164551_remove_unused_champs' do
|
|||
|
||||
describe 'remove_unused_champs' do
|
||||
it "with bad champs" do
|
||||
expect(Champ.where(dossier: dossier).count).to eq(41)
|
||||
expect(Champ.where(dossier: dossier).count).to eq(42)
|
||||
run_task
|
||||
expect(Champ.where(dossier: dossier).count).to eq(40)
|
||||
expect(Champ.where(dossier: dossier).count).to eq(41)
|
||||
end
|
||||
end
|
||||
end
|
||||
|
|
|
@ -124,6 +124,21 @@ describe DossierRebaseConcern do
|
|||
end
|
||||
end
|
||||
|
||||
context 'with type de champ regexp and regexp change' do
|
||||
let(:procedure) { create(:procedure, types_de_champ_public: [{ mandatory: true }, { type: :expression_reguliere }], types_de_champ_private: [{}]) }
|
||||
|
||||
before do
|
||||
procedure.draft_revision.find_and_ensure_exclusive_use(type_de_champ.stable_id).update(expression_reguliere: /\d+/)
|
||||
procedure.publish_revision!
|
||||
dossier.reload
|
||||
end
|
||||
|
||||
it 'should be false' do
|
||||
expect(dossier.pending_changes).not_to be_empty
|
||||
expect(dossier.can_rebase?).to be_falsey
|
||||
end
|
||||
end
|
||||
|
||||
context 'with removed type de champ' do
|
||||
before do
|
||||
procedure.draft_revision.remove_type_de_champ(type_de_champ.stable_id)
|
||||
|
|
|
@ -1575,6 +1575,44 @@ describe Dossier, type: :model do
|
|||
end
|
||||
end
|
||||
|
||||
describe "#check_expressions_regulieres_champs" do
|
||||
let(:procedure) { create(:procedure, types_de_champ_public: types_de_champ) }
|
||||
let(:dossier) { create(:dossier, procedure: procedure) }
|
||||
let(:types_de_champ) { [type_de_champ] }
|
||||
let(:type_de_champ) { { type: :expression_reguliere, expression_reguliere:, expression_reguliere_exemple_text: } }
|
||||
|
||||
context "with bad example" do
|
||||
let(:expression_reguliere_exemple_text) { "01234567" }
|
||||
let(:expression_reguliere) { "[A-Z]+" }
|
||||
|
||||
before do
|
||||
champ = dossier.champs_public.first
|
||||
champ.value = expression_reguliere_exemple_text
|
||||
dossier.save
|
||||
end
|
||||
|
||||
it 'should have errors' do
|
||||
expect(dossier.errors).not_to be_empty
|
||||
expect(dossier.errors.full_messages.join(',')).to include("ne correspond pas au format attendu")
|
||||
end
|
||||
end
|
||||
|
||||
context "with good example" do
|
||||
let(:expression_reguliere_exemple_text) { "AZERTY" }
|
||||
let(:expression_reguliere) { "[A-Z]+" }
|
||||
|
||||
before do
|
||||
champ = dossier.champs_public.first
|
||||
champ.value = expression_reguliere_exemple_text
|
||||
dossier.save
|
||||
end
|
||||
|
||||
it 'should not have errors' do
|
||||
expect(dossier.errors).to be_empty
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
describe 'index_for_section_header' do
|
||||
let(:procedure) { create(:procedure, types_de_champ_public: types_de_champ) }
|
||||
let(:dossier) { create(:dossier, procedure: procedure) }
|
||||
|
|
|
@ -908,6 +908,75 @@ describe ProcedureRevision do
|
|||
end
|
||||
end
|
||||
|
||||
describe "expressions_regulieres_are_valid" do
|
||||
let(:procedure) do
|
||||
create(:procedure).tap do |p|
|
||||
p.draft_revision.add_type_de_champ(type_champ: :expression_reguliere, libelle: 'exemple', expression_reguliere:, expression_reguliere_exemple_text:)
|
||||
end
|
||||
end
|
||||
let(:draft_revision) { procedure.draft_revision }
|
||||
|
||||
subject do
|
||||
draft_revision.save
|
||||
draft_revision.errors
|
||||
end
|
||||
|
||||
context "When no regexp and no example" do
|
||||
let(:expression_reguliere_exemple_text) { nil }
|
||||
let(:expression_reguliere) { nil }
|
||||
|
||||
it { is_expected.to be_empty }
|
||||
end
|
||||
|
||||
context "When expression_reguliere but no example" do
|
||||
let(:expression_reguliere) { "[A-Z]+" }
|
||||
let(:expression_reguliere_exemple_text) { nil }
|
||||
|
||||
it { is_expected.to be_empty }
|
||||
end
|
||||
|
||||
context "When expression_reguliere and bad example" do
|
||||
let(:expression_reguliere_exemple_text) { "01234567" }
|
||||
let(:expression_reguliere) { "[A-Z]+" }
|
||||
|
||||
it { is_expected.not_to be_empty }
|
||||
end
|
||||
|
||||
context "When expression_reguliere and good example" do
|
||||
let(:expression_reguliere_exemple_text) { "A" }
|
||||
let(:expression_reguliere) { "[A-Z]+" }
|
||||
it { is_expected.to be_empty }
|
||||
end
|
||||
|
||||
context "When bad expression_reguliere" do
|
||||
let(:expression_reguliere_exemple_text) { "0123456789" }
|
||||
let(:expression_reguliere) { "(" }
|
||||
|
||||
it { is_expected.not_to be_empty }
|
||||
end
|
||||
|
||||
context "When repetition" do
|
||||
let(:procedure) do
|
||||
create(:procedure,
|
||||
types_de_champ_public: [{ type: :repetition, children: [{ type: :expression_reguliere, expression_reguliere:, expression_reguliere_exemple_text: }] }])
|
||||
end
|
||||
|
||||
context "When bad expression_reguliere" do
|
||||
let(:expression_reguliere_exemple_text) { "0123456789" }
|
||||
let(:expression_reguliere) { "(" }
|
||||
|
||||
it { is_expected.not_to be_empty }
|
||||
end
|
||||
|
||||
context "When expression_reguliere and bad example" do
|
||||
let(:expression_reguliere_exemple_text) { "01234567" }
|
||||
let(:expression_reguliere) { "[A-Z]+" }
|
||||
|
||||
it { is_expected.not_to be_empty }
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
describe "#dependent_conditions" do
|
||||
include Logic
|
||||
|
||||
|
|
|
@ -166,6 +166,31 @@ describe TypeDeChamp do
|
|||
end
|
||||
end
|
||||
|
||||
describe "validate_regexp" do
|
||||
let(:tdc) { create(:type_de_champ_expression_reguliere, expression_reguliere:, expression_reguliere_exemple_text:) }
|
||||
subject { tdc.invalid_regexp? }
|
||||
|
||||
context "expression_reguliere and bad example" do
|
||||
let(:expression_reguliere_exemple_text) { "01234567" }
|
||||
let(:expression_reguliere) { "[A-Z]+" }
|
||||
|
||||
it "should add error message" do
|
||||
expect(subject).to be_truthy
|
||||
expect(tdc.errors.messages[:expression_reguliere_exemple_text]).to be_present
|
||||
end
|
||||
end
|
||||
|
||||
context "Bad expression_reguliere" do
|
||||
let(:expression_reguliere_exemple_text) { "0123456789" }
|
||||
let(:expression_reguliere) { "(" }
|
||||
|
||||
it "should add error message" do
|
||||
expect(subject).to be_truthy
|
||||
expect(tdc.errors.messages[:expression_reguliere]).to be_present
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
describe '#drop_down_list_options' do
|
||||
let(:value) do
|
||||
<<~EOS
|
||||
|
|
|
@ -89,7 +89,8 @@ describe ProcedureExportService do
|
|||
"epci",
|
||||
"epci (Code)",
|
||||
"epci (Département)",
|
||||
"cojo"
|
||||
"cojo",
|
||||
"expression_reguliere"
|
||||
]
|
||||
end
|
||||
|
||||
|
@ -200,7 +201,8 @@ describe ProcedureExportService do
|
|||
"epci",
|
||||
"epci (Code)",
|
||||
"epci (Département)",
|
||||
"cojo"
|
||||
"cojo",
|
||||
"expression_reguliere"
|
||||
]
|
||||
end
|
||||
|
||||
|
@ -294,7 +296,8 @@ describe ProcedureExportService do
|
|||
"epci",
|
||||
"epci (Code)",
|
||||
"epci (Département)",
|
||||
"cojo"
|
||||
"cojo",
|
||||
"expression_reguliere"
|
||||
]
|
||||
end
|
||||
|
||||
|
|
Loading…
Reference in a new issue