Merge pull request #6452 from betagouv/main
This commit is contained in:
commit
45845b6233
19 changed files with 165 additions and 45 deletions
|
@ -151,15 +151,15 @@ module Instructeurs
|
|||
case params[:process_action]
|
||||
when "refuser"
|
||||
target_state = :refuse
|
||||
dossier.refuser!(current_instructeur, motivation, justificatif)
|
||||
dossier.refuser!(current_instructeur, motivation, justificatif: justificatif)
|
||||
flash.notice = "Dossier considéré comme refusé."
|
||||
when "classer_sans_suite"
|
||||
target_state = :sans_suite
|
||||
dossier.classer_sans_suite!(current_instructeur, motivation, justificatif)
|
||||
dossier.classer_sans_suite!(current_instructeur, motivation, justificatif: justificatif)
|
||||
flash.notice = "Dossier considéré comme sans suite."
|
||||
when "accepter"
|
||||
target_state = :accepte
|
||||
dossier.accepter!(current_instructeur, motivation, justificatif)
|
||||
dossier.accepter!(current_instructeur, motivation, justificatif: justificatif)
|
||||
flash.notice = "Dossier traité avec succès."
|
||||
end
|
||||
rescue AASM::InvalidTransition => e
|
||||
|
|
|
@ -8,12 +8,13 @@ module Mutations
|
|||
argument :instructeur_id, ID, "Instructeur qui prend la décision sur le dossier.", required: true, loads: Types::ProfileType
|
||||
argument :motivation, String, required: false
|
||||
argument :justificatif, ID, required: false
|
||||
argument :disable_notification, Boolean, "Désactiver l’envoi de l’email de notification après l’opération", required: false, default_value: false
|
||||
|
||||
field :dossier, Types::DossierType, null: true
|
||||
field :errors, [Types::ValidationErrorType], null: true
|
||||
|
||||
def resolve(dossier:, instructeur:, motivation: nil, justificatif: nil)
|
||||
dossier.accepter!(instructeur, motivation, justificatif)
|
||||
def resolve(dossier:, instructeur:, motivation: nil, justificatif: nil, disable_notification:)
|
||||
dossier.accepter!(instructeur, motivation, justificatif: justificatif, disable_notification: disable_notification)
|
||||
|
||||
{ dossier: dossier }
|
||||
end
|
||||
|
|
|
@ -8,12 +8,13 @@ module Mutations
|
|||
argument :instructeur_id, ID, "Instructeur qui prend la décision sur le dossier.", required: true, loads: Types::ProfileType
|
||||
argument :motivation, String, required: true
|
||||
argument :justificatif, ID, required: false
|
||||
argument :disable_notification, Boolean, "Désactiver l’envoi de l’email de notification après l’opération", required: false, default_value: false
|
||||
|
||||
field :dossier, Types::DossierType, null: true
|
||||
field :errors, [Types::ValidationErrorType], null: true
|
||||
|
||||
def resolve(dossier:, instructeur:, motivation:, justificatif: nil)
|
||||
dossier.classer_sans_suite!(instructeur, motivation, justificatif)
|
||||
def resolve(dossier:, instructeur:, motivation:, justificatif: nil, disable_notification:)
|
||||
dossier.classer_sans_suite!(instructeur, motivation, justificatif: justificatif, disable_notification: disable_notification)
|
||||
|
||||
{ dossier: dossier }
|
||||
end
|
||||
|
|
|
@ -6,17 +6,18 @@ module Mutations
|
|||
|
||||
argument :dossier_id, ID, "Dossier ID", required: true, loads: Types::DossierType
|
||||
argument :instructeur_id, ID, "Instructeur qui prend la décision sur le dossier.", required: true, loads: Types::ProfileType
|
||||
argument :disable_notification, Boolean, "Désactiver l’envoi de l’email de notification après l’opération", required: false, default_value: false
|
||||
|
||||
field :dossier, Types::DossierType, null: true
|
||||
field :errors, [Types::ValidationErrorType], null: true
|
||||
|
||||
def resolve(dossier:, instructeur:)
|
||||
dossier.passer_en_instruction!(instructeur)
|
||||
def resolve(dossier:, instructeur:, disable_notification:)
|
||||
dossier.passer_en_instruction!(instructeur, disable_notification: disable_notification)
|
||||
|
||||
{ dossier: dossier }
|
||||
end
|
||||
|
||||
def authorized?(dossier:, instructeur:)
|
||||
def authorized?(dossier:, instructeur:, **args)
|
||||
if !dossier.en_construction?
|
||||
return false, { errors: ["Le dossier est déjà #{dossier_display_state(dossier, lower: true)}"] }
|
||||
end
|
||||
|
|
|
@ -8,12 +8,13 @@ module Mutations
|
|||
argument :instructeur_id, ID, "Instructeur qui prend la décision sur le dossier.", required: true, loads: Types::ProfileType
|
||||
argument :motivation, String, required: true
|
||||
argument :justificatif, ID, required: false
|
||||
argument :disable_notification, Boolean, "Désactiver l’envoi de l’email de notification après l’opération", required: false, default_value: false
|
||||
|
||||
field :dossier, Types::DossierType, null: true
|
||||
field :errors, [Types::ValidationErrorType], null: true
|
||||
|
||||
def resolve(dossier:, instructeur:, motivation:, justificatif: nil)
|
||||
dossier.refuser!(instructeur, motivation, justificatif)
|
||||
def resolve(dossier:, instructeur:, motivation:, justificatif: nil, disable_notification:)
|
||||
dossier.refuser!(instructeur, motivation, justificatif: justificatif, disable_notification: disable_notification)
|
||||
|
||||
{ dossier: dossier }
|
||||
end
|
||||
|
|
|
@ -748,6 +748,11 @@ input DossierAccepterInput {
|
|||
"""
|
||||
clientMutationId: String
|
||||
|
||||
"""
|
||||
Désactiver l’envoi de l’email de notification après l’opération
|
||||
"""
|
||||
disableNotification: Boolean = false
|
||||
|
||||
"""
|
||||
Dossier ID
|
||||
"""
|
||||
|
@ -846,6 +851,11 @@ input DossierClasserSansSuiteInput {
|
|||
"""
|
||||
clientMutationId: String
|
||||
|
||||
"""
|
||||
Désactiver l’envoi de l’email de notification après l’opération
|
||||
"""
|
||||
disableNotification: Boolean = false
|
||||
|
||||
"""
|
||||
Dossier ID
|
||||
"""
|
||||
|
@ -1164,6 +1174,11 @@ input DossierPasserEnInstructionInput {
|
|||
"""
|
||||
clientMutationId: String
|
||||
|
||||
"""
|
||||
Désactiver l’envoi de l’email de notification après l’opération
|
||||
"""
|
||||
disableNotification: Boolean = false
|
||||
|
||||
"""
|
||||
Dossier ID
|
||||
"""
|
||||
|
@ -1196,6 +1211,11 @@ input DossierRefuserInput {
|
|||
"""
|
||||
clientMutationId: String
|
||||
|
||||
"""
|
||||
Désactiver l’envoi de l’email de notification après l’opération
|
||||
"""
|
||||
disableNotification: Boolean = false
|
||||
|
||||
"""
|
||||
Dossier ID
|
||||
"""
|
||||
|
|
|
@ -30,6 +30,7 @@ class BillSignature < ApplicationRecord
|
|||
io: StringIO.new(operations_bill_json),
|
||||
filename: "demarches-simplifiees-operations-#{day.to_date.iso8601}.json",
|
||||
content_type: 'application/json',
|
||||
# we don't want to run virus scanner on this file
|
||||
metadata: { virus_scan_result: ActiveStorage::VirusScanner::SAFE }
|
||||
)
|
||||
|
||||
|
@ -52,7 +53,9 @@ class BillSignature < ApplicationRecord
|
|||
self.signature.attach(
|
||||
io: StringIO.new(signature),
|
||||
filename: "demarches-simplifiees-signature-#{day.to_date.iso8601}.der",
|
||||
content_type: 'application/x-x509-ca-cert'
|
||||
content_type: 'application/x-x509-ca-cert',
|
||||
# we don't want to run virus scanner on this file
|
||||
metadata: { virus_scan_result: ActiveStorage::VirusScanner::SAFE }
|
||||
)
|
||||
end
|
||||
|
||||
|
|
|
@ -20,7 +20,7 @@
|
|||
class Champs::PaysChamp < Champs::TextChamp
|
||||
def localized_value
|
||||
if external_id
|
||||
I18nData.countries(I18n.locale)[external_id]
|
||||
I18nData.countries(I18n.locale)[external_id].to_s
|
||||
else
|
||||
value.present? ? value.to_s : ''
|
||||
end
|
||||
|
|
|
@ -374,7 +374,6 @@ class Dossier < ApplicationRecord
|
|||
before_save :build_default_champs, if: Proc.new { revision_id_was.nil? }
|
||||
before_save :update_search_terms
|
||||
|
||||
after_save :send_dossier_en_instruction
|
||||
after_save :send_web_hook
|
||||
after_create_commit :send_draft_notification_email
|
||||
|
||||
|
@ -676,10 +675,13 @@ class Dossier < ApplicationRecord
|
|||
update!(en_construction_at: Time.zone.now) if self.en_construction_at.nil?
|
||||
end
|
||||
|
||||
def after_passer_en_instruction(instructeur)
|
||||
def after_passer_en_instruction(instructeur, disable_notification: false)
|
||||
instructeur.follow(self)
|
||||
|
||||
update!(en_instruction_at: Time.zone.now) if self.en_instruction_at.nil?
|
||||
if !procedure.declarative_accepte? && !disable_notification
|
||||
NotificationMailer.send_en_instruction_notification(self).deliver_later
|
||||
end
|
||||
log_dossier_operation(instructeur, :passer_en_instruction)
|
||||
end
|
||||
|
||||
|
@ -695,17 +697,19 @@ class Dossier < ApplicationRecord
|
|||
log_dossier_operation(instructeur, :repasser_en_construction)
|
||||
end
|
||||
|
||||
def after_repasser_en_instruction(instructeur)
|
||||
def after_repasser_en_instruction(instructeur, disable_notification: false)
|
||||
self.archived = false
|
||||
self.en_instruction_at = Time.zone.now
|
||||
attestation&.destroy
|
||||
|
||||
save!
|
||||
DossierMailer.notify_revert_to_instruction(self).deliver_later
|
||||
if !disable_notification
|
||||
DossierMailer.notify_revert_to_instruction(self).deliver_later
|
||||
end
|
||||
log_dossier_operation(instructeur, :repasser_en_instruction)
|
||||
end
|
||||
|
||||
def after_accepter(instructeur, motivation, justificatif = nil)
|
||||
def after_accepter(instructeur, motivation, justificatif: nil, disable_notification: false)
|
||||
self.traitements.accepter(motivation: motivation, instructeur: instructeur)
|
||||
|
||||
if justificatif
|
||||
|
@ -718,7 +722,9 @@ class Dossier < ApplicationRecord
|
|||
|
||||
save!
|
||||
remove_titres_identite!
|
||||
NotificationMailer.send_accepte_notification(self).deliver_later
|
||||
if !disable_notification
|
||||
NotificationMailer.send_accepte_notification(self).deliver_later
|
||||
end
|
||||
send_dossier_decision_to_experts(self)
|
||||
log_dossier_operation(instructeur, :accepter, self)
|
||||
end
|
||||
|
@ -738,7 +744,7 @@ class Dossier < ApplicationRecord
|
|||
log_automatic_dossier_operation(:accepter, self)
|
||||
end
|
||||
|
||||
def after_refuser(instructeur, motivation, justificatif = nil)
|
||||
def after_refuser(instructeur, motivation, justificatif: nil, disable_notification: false)
|
||||
self.traitements.refuser(motivation: motivation, instructeur: instructeur)
|
||||
|
||||
if justificatif
|
||||
|
@ -747,12 +753,14 @@ class Dossier < ApplicationRecord
|
|||
|
||||
save!
|
||||
remove_titres_identite!
|
||||
NotificationMailer.send_refuse_notification(self).deliver_later
|
||||
if !disable_notification
|
||||
NotificationMailer.send_refuse_notification(self).deliver_later
|
||||
end
|
||||
send_dossier_decision_to_experts(self)
|
||||
log_dossier_operation(instructeur, :refuser, self)
|
||||
end
|
||||
|
||||
def after_classer_sans_suite(instructeur, motivation, justificatif = nil)
|
||||
def after_classer_sans_suite(instructeur, motivation, justificatif: nil, disable_notification: false)
|
||||
self.traitements.classer_sans_suite(motivation: motivation, instructeur: instructeur)
|
||||
|
||||
if justificatif
|
||||
|
@ -761,7 +769,9 @@ class Dossier < ApplicationRecord
|
|||
|
||||
save!
|
||||
remove_titres_identite!
|
||||
NotificationMailer.send_sans_suite_notification(self).deliver_later
|
||||
if !disable_notification
|
||||
NotificationMailer.send_sans_suite_notification(self).deliver_later
|
||||
end
|
||||
send_dossier_decision_to_experts(self)
|
||||
log_dossier_operation(instructeur, :classer_sans_suite, self)
|
||||
end
|
||||
|
@ -968,12 +978,6 @@ class Dossier < ApplicationRecord
|
|||
end
|
||||
end
|
||||
|
||||
def send_dossier_en_instruction
|
||||
if saved_change_to_state? && en_instruction? && !procedure.declarative_accepte?
|
||||
NotificationMailer.send_en_instruction_notification(self).deliver_later
|
||||
end
|
||||
end
|
||||
|
||||
def send_draft_notification_email
|
||||
if brouillon? && !procedure.declarative?
|
||||
DossierMailer.notify_new_draft(self).deliver_later
|
||||
|
|
|
@ -176,6 +176,7 @@ class Etablissement < ApplicationRecord
|
|||
attestation.attach(
|
||||
io: StringIO.new(response.body),
|
||||
filename: filename,
|
||||
# we don't want to run virus scanner on this file
|
||||
metadata: { virus_scan_result: ActiveStorage::VirusScanner::SAFE }
|
||||
)
|
||||
end
|
||||
|
|
|
@ -40,7 +40,12 @@ class ProcedureArchiveService
|
|||
end
|
||||
end
|
||||
|
||||
archive.file.attach(io: File.open(tmp_file), filename: archive.filename(@procedure))
|
||||
archive.file.attach(
|
||||
io: File.open(tmp_file),
|
||||
filename: archive.filename(@procedure),
|
||||
# we don't want to run virus scanner on this file
|
||||
metadata: { virus_scan_result: ActiveStorage::VirusScanner::SAFE }
|
||||
)
|
||||
tmp_file.delete
|
||||
archive.make_available!
|
||||
InstructeurMailer.send_archive(instructeur, @procedure, archive).deliver_later
|
||||
|
|
|
@ -34,7 +34,9 @@ describe API::V2::GraphqlController do
|
|||
filename: file.original_filename,
|
||||
byte_size: file.size,
|
||||
checksum: compute_checksum_in_chunks(file),
|
||||
content_type: file.content_type
|
||||
content_type: file.content_type,
|
||||
# we don't want to run virus scanner on this file
|
||||
metadata: { virus_scan_result: ActiveStorage::VirusScanner::SAFE }
|
||||
}
|
||||
end
|
||||
let(:blob) do
|
||||
|
@ -902,11 +904,13 @@ describe API::V2::GraphqlController do
|
|||
describe 'dossierPasserEnInstruction' do
|
||||
let(:dossier) { create(:dossier, :en_construction, :with_individual, procedure: procedure) }
|
||||
let(:instructeur_id) { instructeur.to_typed_id }
|
||||
let(:disable_notification) { false }
|
||||
let(:query) do
|
||||
"mutation {
|
||||
dossierPasserEnInstruction(input: {
|
||||
dossierId: \"#{dossier.to_typed_id}\",
|
||||
instructeurId: \"#{instructeur_id}\"
|
||||
instructeurId: \"#{instructeur_id}\",
|
||||
disableNotification: #{disable_notification}
|
||||
}) {
|
||||
dossier {
|
||||
id
|
||||
|
@ -932,6 +936,9 @@ describe API::V2::GraphqlController do
|
|||
},
|
||||
errors: nil
|
||||
})
|
||||
|
||||
perform_enqueued_jobs
|
||||
expect(ActionMailer::Base.deliveries.size).to eq(4)
|
||||
end
|
||||
end
|
||||
|
||||
|
@ -958,6 +965,25 @@ describe API::V2::GraphqlController do
|
|||
})
|
||||
end
|
||||
end
|
||||
|
||||
context 'disable notification' do
|
||||
let(:disable_notification) { true }
|
||||
it "should passer en instruction dossier without notification" do
|
||||
expect(gql_errors).to eq(nil)
|
||||
|
||||
expect(gql_data).to eq(dossierPasserEnInstruction: {
|
||||
dossier: {
|
||||
id: dossier.to_typed_id,
|
||||
state: "en_instruction",
|
||||
motivation: nil
|
||||
},
|
||||
errors: nil
|
||||
})
|
||||
|
||||
perform_enqueued_jobs
|
||||
expect(ActionMailer::Base.deliveries.size).to eq(3)
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
describe 'dossierClasserSansSuite' do
|
||||
|
|
|
@ -11,7 +11,13 @@ FactoryBot.define do
|
|||
|
||||
trait :with_piece_justificative_file do
|
||||
after(:build) do |champ, _evaluator|
|
||||
champ.piece_justificative_file.attach(io: StringIO.new("toto"), filename: "toto.txt", content_type: "text/plain")
|
||||
champ.piece_justificative_file.attach(
|
||||
io: StringIO.new("toto"),
|
||||
filename: "toto.txt",
|
||||
content_type: "text/plain",
|
||||
# we don't want to run virus scanner on this file
|
||||
metadata: { virus_scan_result: ActiveStorage::VirusScanner::SAFE }
|
||||
)
|
||||
end
|
||||
end
|
||||
|
||||
|
@ -143,7 +149,13 @@ FactoryBot.define do
|
|||
end
|
||||
|
||||
after(:build) do |champ, evaluator|
|
||||
champ.piece_justificative_file.attach(io: StringIO.new("x" * evaluator.size), filename: "toto.txt", content_type: "text/plain")
|
||||
champ.piece_justificative_file.attach(
|
||||
io: StringIO.new("x" * evaluator.size),
|
||||
filename: "toto.txt",
|
||||
content_type: "text/plain",
|
||||
# we don't want to run virus scanner on this file
|
||||
metadata: { virus_scan_result: ActiveStorage::VirusScanner::SAFE }
|
||||
)
|
||||
end
|
||||
end
|
||||
|
||||
|
@ -151,7 +163,13 @@ FactoryBot.define do
|
|||
type_de_champ { association :type_de_champ_titre_identite, procedure: dossier.procedure }
|
||||
|
||||
after(:build) do |champ, _evaluator|
|
||||
champ.piece_justificative_file.attach(io: StringIO.new("toto"), filename: "toto.png", content_type: "image/png")
|
||||
champ.piece_justificative_file.attach(
|
||||
io: StringIO.new("toto"),
|
||||
filename: "toto.png",
|
||||
content_type: "image/png",
|
||||
# we don't want to run virus scanner on this file
|
||||
metadata: { virus_scan_result: ActiveStorage::VirusScanner::SAFE }
|
||||
)
|
||||
end
|
||||
end
|
||||
|
||||
|
|
|
@ -205,7 +205,9 @@ FactoryBot.define do
|
|||
after(:create) do |dossier, _evaluator|
|
||||
dossier.justificatif_motivation.attach(
|
||||
io: StringIO.new('Hello World'),
|
||||
filename: 'hello.txt'
|
||||
filename: 'hello.txt',
|
||||
# we don't want to run virus scanner on this file
|
||||
metadata: { virus_scan_result: ActiveStorage::VirusScanner::SAFE }
|
||||
)
|
||||
end
|
||||
end
|
||||
|
|
|
@ -248,7 +248,9 @@ FactoryBot.define do
|
|||
after(:create) do |procedure, _evaluator|
|
||||
procedure.notice.attach(
|
||||
io: StringIO.new('Hello World'),
|
||||
filename: 'hello.txt'
|
||||
filename: 'hello.txt',
|
||||
# we don't want to run virus scanner on this file
|
||||
metadata: { virus_scan_result: ActiveStorage::VirusScanner::SAFE }
|
||||
)
|
||||
end
|
||||
end
|
||||
|
@ -257,7 +259,9 @@ FactoryBot.define do
|
|||
after(:create) do |procedure, _evaluator|
|
||||
procedure.deliberation.attach(
|
||||
io: StringIO.new('Hello World'),
|
||||
filename: 'hello.txt'
|
||||
filename: 'hello.txt',
|
||||
# we don't want to run virus scanner on this file
|
||||
metadata: { virus_scan_result: ActiveStorage::VirusScanner::SAFE }
|
||||
)
|
||||
end
|
||||
end
|
||||
|
|
|
@ -130,7 +130,13 @@ FactoryBot.define do
|
|||
type_champ { TypeDeChamp.type_champs.fetch(:piece_justificative) }
|
||||
|
||||
after(:build) do |type_de_champ, _evaluator|
|
||||
type_de_champ.piece_justificative_template.attach(io: StringIO.new("toto"), filename: "toto.txt", content_type: "text/plain")
|
||||
type_de_champ.piece_justificative_template.attach(
|
||||
io: StringIO.new("toto"),
|
||||
filename: "toto.txt",
|
||||
content_type: "text/plain",
|
||||
# we don't want to run virus scanner on this file
|
||||
metadata: { virus_scan_result: ActiveStorage::VirusScanner::SAFE }
|
||||
)
|
||||
end
|
||||
end
|
||||
factory :type_de_champ_titre_identite do
|
||||
|
|
|
@ -320,7 +320,7 @@ describe TagsSubstitutionConcern, type: :model do
|
|||
Timecop.freeze(Time.zone.local(2004, 5, 6))
|
||||
dossier.passer_en_instruction!(instructeur)
|
||||
Timecop.freeze(Time.zone.local(2007, 8, 9))
|
||||
dossier.accepter!(instructeur, nil, nil)
|
||||
dossier.accepter!(instructeur, nil)
|
||||
Timecop.return
|
||||
end
|
||||
|
||||
|
|
|
@ -239,7 +239,7 @@ describe Dossier do
|
|||
Timecop.freeze(date2)
|
||||
d.passer_en_instruction!(instructeur)
|
||||
Timecop.freeze(date3)
|
||||
d.accepter!(instructeur, "Motivation", nil)
|
||||
d.accepter!(instructeur, "Motivation")
|
||||
Timecop.return
|
||||
d
|
||||
end
|
||||
|
@ -422,7 +422,7 @@ describe Dossier do
|
|||
let(:dossier) { create(:dossier, :en_instruction, :with_individual) }
|
||||
|
||||
before do
|
||||
dossier.accepter!(instructeur, nil, nil)
|
||||
dossier.accepter!(instructeur, nil)
|
||||
dossier.reload
|
||||
end
|
||||
|
||||
|
@ -435,7 +435,7 @@ describe Dossier do
|
|||
let(:dossier) { create(:dossier, :en_instruction, :with_individual) }
|
||||
|
||||
before do
|
||||
dossier.refuser!(instructeur, nil, nil)
|
||||
dossier.refuser!(instructeur, nil)
|
||||
dossier.reload
|
||||
end
|
||||
|
||||
|
@ -447,7 +447,7 @@ describe Dossier do
|
|||
let(:dossier) { create(:dossier, :en_instruction, :with_individual) }
|
||||
|
||||
before do
|
||||
dossier.classer_sans_suite!(instructeur, nil, nil)
|
||||
dossier.classer_sans_suite!(instructeur, nil)
|
||||
dossier.reload
|
||||
end
|
||||
|
||||
|
|
|
@ -184,6 +184,33 @@ describe DossierProjectionService do
|
|||
|
||||
it { is_expected.to eq('18 a la bonne rue') }
|
||||
end
|
||||
|
||||
context 'for type_de_champ table: type_de_champ pays which needs external_id field' do
|
||||
let(:table) { 'type_de_champ' }
|
||||
let(:procedure) { create(:procedure, types_de_champ: [build(:type_de_champ_pays)]) }
|
||||
let(:dossier) { create(:dossier, procedure: procedure) }
|
||||
let(:column) { dossier.procedure.types_de_champ.first.stable_id.to_s }
|
||||
let!(:previous_locale) { I18n.locale }
|
||||
|
||||
before { I18n.locale = :fr }
|
||||
after { I18n.locale = previous_locale }
|
||||
|
||||
context 'when external id is set' do
|
||||
before do
|
||||
dossier.champs.first.update(external_id: 'GB')
|
||||
end
|
||||
|
||||
it { is_expected.to eq('Royaume-Uni') }
|
||||
end
|
||||
|
||||
context 'when no external id is set' do
|
||||
before do
|
||||
dossier.champs.first.update(value: "qu'il est beau mon pays")
|
||||
end
|
||||
|
||||
it { is_expected.to eq("qu'il est beau mon pays") }
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
|
|
Loading…
Reference in a new issue