Merge pull request #5398 from betagouv/belongs-to-required-by-default

Rails : les relations `belongs_to` sont maintenant requises par défaut. (Pour une relation optionnelle, mentionner explicitement `belongs_to :table, optional: true`)
This commit is contained in:
Pierre de La Morinerie 2020-08-18 17:43:32 +02:00 committed by GitHub
commit be0e71c6c2
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
73 changed files with 449 additions and 400 deletions

View file

@ -14,8 +14,8 @@
# procedure_id :integer
#
class AssignTo < ApplicationRecord
belongs_to :instructeur
belongs_to :groupe_instructeur
belongs_to :instructeur, optional: false
belongs_to :groupe_instructeur, optional: false
has_one :procedure_presentation, dependent: :destroy
has_one :procedure, through: :groupe_instructeur

View file

@ -9,7 +9,7 @@
# dossier_id :integer not null
#
class Attestation < ApplicationRecord
belongs_to :dossier
belongs_to :dossier, optional: false
has_one_attached :pdf

View file

@ -15,7 +15,7 @@ class AttestationTemplate < ApplicationRecord
include ActionView::Helpers::NumberHelper
include TagsSubstitutionConcern
belongs_to :procedure
belongs_to :procedure, optional: false
has_one_attached :logo
has_one_attached :signature

View file

@ -17,9 +17,9 @@
class Avis < ApplicationRecord
include EmailSanitizableConcern
belongs_to :dossier, inverse_of: :avis, touch: true
belongs_to :instructeur
belongs_to :claimant, class_name: 'Instructeur'
belongs_to :dossier, inverse_of: :avis, touch: true, optional: false
belongs_to :instructeur, optional: true
belongs_to :claimant, class_name: 'Instructeur', optional: false
has_one_attached :piece_justificative_file
has_one_attached :introduction_file

View file

@ -15,16 +15,16 @@
# type_de_champ_id :integer
#
class Champ < ApplicationRecord
belongs_to :dossier, -> { with_discarded }, inverse_of: :champs, touch: true
belongs_to :type_de_champ, inverse_of: :champ
belongs_to :parent, class_name: 'Champ'
belongs_to :dossier, -> { with_discarded }, inverse_of: :champs, touch: true, optional: false
belongs_to :type_de_champ, inverse_of: :champ, optional: false
belongs_to :parent, class_name: 'Champ', optional: true
has_many :commentaires
has_one_attached :piece_justificative_file
# We declare champ specific relationships (Champs::CarteChamp, Champs::SiretChamp and Champs::RepetitionChamp)
# here because otherwise we can't easily use includes in our queries.
has_many :geo_areas, dependent: :destroy
belongs_to :etablissement, dependent: :destroy
belongs_to :etablissement, optional: true, dependent: :destroy
has_many :champs, -> { ordered }, foreign_key: :parent_id, inverse_of: :parent, dependent: :destroy
delegate :libelle,
@ -49,7 +49,7 @@ class Champ < ApplicationRecord
scope :ordered, -> { includes(:type_de_champ).order(:row, 'types_de_champ.order_place') }
scope :root, -> { where(parent_id: nil) }
before_create :set_dossier_id, if: :needs_dossier_id?
before_validation :set_dossier_id, if: :needs_dossier_id?
validates :type_de_champ_id, uniqueness: { scope: [:dossier_id, :row] }

View file

@ -12,10 +12,10 @@
# user_id :bigint
#
class Commentaire < ApplicationRecord
belongs_to :dossier, inverse_of: :commentaires, touch: true
belongs_to :dossier, inverse_of: :commentaires, touch: true, optional: false
belongs_to :user
belongs_to :instructeur
belongs_to :user, optional: true
belongs_to :instructeur, optional: true
validate :messagerie_available?, on: :create

View file

@ -12,7 +12,7 @@
# procedure_id :bigint
#
class DeletedDossier < ApplicationRecord
belongs_to :procedure, -> { with_discarded }, inverse_of: :deleted_dossiers
belongs_to :procedure, -> { with_discarded }, inverse_of: :deleted_dossiers, optional: false
validates :dossier_id, uniqueness: true

View file

@ -75,10 +75,10 @@ class Dossier < ApplicationRecord
has_many :dossier_operation_logs, -> { order(:created_at) }, dependent: :nullify, inverse_of: :dossier
belongs_to :groupe_instructeur
belongs_to :groupe_instructeur, optional: false
has_one :procedure, through: :groupe_instructeur
belongs_to :revision, class_name: 'ProcedureRevision', optional: true
belongs_to :user
belongs_to :user, optional: false
accepts_nested_attributes_for :champs
accepts_nested_attributes_for :champs_private

View file

@ -47,7 +47,7 @@
# entreprise_id :integer
#
class Etablissement < ApplicationRecord
belongs_to :dossier
belongs_to :dossier, optional: true
has_one :champ, class_name: 'Champs::SiretChamp'
has_many :exercices, dependent: :destroy

View file

@ -12,7 +12,7 @@
# etablissement_id :integer
#
class Exercice < ApplicationRecord
belongs_to :etablissement
belongs_to :etablissement, optional: false
validates :ca, presence: true, allow_blank: false, allow_nil: false
end

View file

@ -9,7 +9,7 @@
# user_id :bigint
#
class Feedback < ApplicationRecord
belongs_to :user
belongs_to :user, optional: false
enum rating: {
happy: 'happy',

View file

@ -14,8 +14,8 @@
# instructeur_id :integer not null
#
class Follow < ApplicationRecord
belongs_to :instructeur
belongs_to :dossier
belongs_to :instructeur, optional: false
belongs_to :dossier, optional: false
validates :instructeur_id, uniqueness: { scope: [:dossier_id, :unfollowed_at] }

View file

@ -15,7 +15,7 @@
# user_id :integer
#
class FranceConnectInformation < ApplicationRecord
belongs_to :user
belongs_to :user, optional: true
validates :france_connect_particulier_id, presence: true, allow_blank: false, allow_nil: false
end

View file

@ -12,7 +12,7 @@
# geo_reference_id :string
#
class GeoArea < ApplicationRecord
belongs_to :champ
belongs_to :champ, optional: false
store :properties, accessors: [
:description,

View file

@ -10,7 +10,7 @@
#
class GroupeInstructeur < ApplicationRecord
DEFAULT_LABEL = 'défaut'
belongs_to :procedure, -> { with_discarded }, inverse_of: :groupe_instructeurs
belongs_to :procedure, -> { with_discarded }, inverse_of: :groupe_instructeurs, optional: false
has_many :assign_tos, dependent: :destroy
has_many :instructeurs, through: :assign_tos
has_many :dossiers

View file

@ -12,7 +12,7 @@
# dossier_id :integer
#
class Individual < ApplicationRecord
belongs_to :dossier
belongs_to :dossier, optional: false
validates :dossier_id, uniqueness: true
validates :gender, presence: true, allow_nil: false, on: :update

View file

@ -14,8 +14,8 @@
class Invite < ApplicationRecord
include EmailSanitizableConcern
belongs_to :dossier
belongs_to :user
belongs_to :dossier, optional: false
belongs_to :user, optional: true
before_validation -> { sanitize_email(:email) }

View file

@ -13,7 +13,7 @@ module Mails
class ClosedMail < ApplicationRecord
include MailTemplateConcern
belongs_to :procedure
belongs_to :procedure, optional: false
SLUG = "closed_mail"
DISPLAYED_NAME = "Accusé d'acceptation"

View file

@ -13,7 +13,7 @@ module Mails
class InitiatedMail < ApplicationRecord
include MailTemplateConcern
belongs_to :procedure
belongs_to :procedure, optional: false
SLUG = "initiated_mail"
DEFAULT_TEMPLATE_NAME = "notification_mailer/default_templates/initiated_mail"

View file

@ -13,7 +13,7 @@ module Mails
class ReceivedMail < ApplicationRecord
include MailTemplateConcern
belongs_to :procedure
belongs_to :procedure, optional: false
SLUG = "received_mail"
DEFAULT_TEMPLATE_NAME = "notification_mailer/default_templates/received_mail"

View file

@ -13,7 +13,7 @@ module Mails
class RefusedMail < ApplicationRecord
include MailTemplateConcern
belongs_to :procedure
belongs_to :procedure, optional: false
SLUG = "refused_mail"
DEFAULT_TEMPLATE_NAME = "notification_mailer/default_templates/refused_mail"

View file

@ -13,7 +13,7 @@ module Mails
class WithoutContinuationMail < ApplicationRecord
include MailTemplateConcern
belongs_to :procedure
belongs_to :procedure, optional: false
SLUG = "without_continuation"
DEFAULT_TEMPLATE_NAME = "notification_mailer/default_templates/without_continuation_mail"

View file

@ -12,5 +12,5 @@
# procedure_id :integer
#
class ModuleAPICarto < ApplicationRecord
belongs_to :procedure
belongs_to :procedure, optional: false
end

View file

@ -66,9 +66,9 @@ class Procedure < ApplicationRecord
has_one :module_api_carto, dependent: :destroy
has_one :attestation_template, dependent: :destroy
belongs_to :parent_procedure, class_name: 'Procedure'
belongs_to :canonical_procedure, class_name: 'Procedure'
belongs_to :service
belongs_to :parent_procedure, class_name: 'Procedure', optional: true
belongs_to :canonical_procedure, class_name: 'Procedure', optional: true
belongs_to :service, optional: true
def active_revision
brouillon? ? draft_revision : published_revision

View file

@ -16,7 +16,7 @@ class ProcedurePresentation < ApplicationRecord
'self' => ['id', 'state']
}
belongs_to :assign_to
belongs_to :assign_to, optional: false
delegate :procedure, to: :assign_to

View file

@ -16,7 +16,7 @@
#
class Service < ApplicationRecord
has_many :procedures
belongs_to :administrateur
belongs_to :administrateur, optional: false
scope :ordered, -> { order(nom: :asc) }

View file

@ -10,7 +10,7 @@
# dossier_id :bigint
#
class Traitement < ApplicationRecord
belongs_to :dossier
belongs_to :dossier, optional: false
scope :termine_close_to_expiration, -> do
joins(dossier: :procedure)

View file

@ -12,7 +12,7 @@ class TrustedDeviceToken < ApplicationRecord
LOGIN_TOKEN_VALIDITY = 1.week
LOGIN_TOKEN_YOUTH = 15.minutes
belongs_to :instructeur
belongs_to :instructeur, optional: false
has_secure_token
def token_valid?

View file

@ -49,10 +49,10 @@ class TypeDeChamp < ApplicationRecord
repetition: 'repetition'
}
belongs_to :procedure
belongs_to :procedure, optional: false
belongs_to :revision, class_name: 'ProcedureRevision', optional: true
belongs_to :parent, class_name: 'TypeDeChamp'
belongs_to :parent, class_name: 'TypeDeChamp', optional: true
has_many :types_de_champ, -> { ordered }, foreign_key: :parent_id, class_name: 'TypeDeChamp', inverse_of: :parent, dependent: :destroy
store_accessor :options, :cadastres, :quartiers_prioritaires, :parcelles_agricoles, :old_pj, :drop_down_options, :skip_pj_validation
@ -73,8 +73,8 @@ class TypeDeChamp < ApplicationRecord
serialize :options, WithIndifferentAccess
after_initialize :set_dynamic_type
before_validation :setup_procedure
after_create :populate_stable_id
before_save :setup_procedure
attr_reader :dynamic_type

View file

@ -45,8 +45,8 @@ class User < ApplicationRecord
has_many :dossiers_invites, through: :invites, source: :dossier
has_many :feedbacks, dependent: :destroy
has_one :france_connect_information, dependent: :destroy
belongs_to :instructeur
belongs_to :administrateur
belongs_to :instructeur, optional: true
belongs_to :administrateur, optional: true
accepts_nested_attributes_for :france_connect_information

View file

@ -45,12 +45,6 @@ module TPS
default_allowed_tags = ['strong', 'em', 'b', 'i', 'p', 'code', 'pre', 'tt', 'samp', 'kbd', 'var', 'sub', 'sup', 'dfn', 'cite', 'big', 'small', 'address', 'hr', 'br', 'div', 'span', 'h1', 'h2', 'h3', 'h4', 'h5', 'h6', 'ul', 'ol', 'li', 'dl', 'dt', 'dd', 'abbr', 'acronym', 'a', 'img', 'blockquote', 'del', 'ins']
config.action_view.sanitized_allowed_tags = default_allowed_tags + ['u']
# Since Rails 5.0, this option is enabled by default.
# However we keep it disabled for now, because many of our specs and fatories
# do not build the required associations properly.
# TODO: fix the specs, and enable this option.
config.active_record.belongs_to_required_by_default = false
# Some mobile browsers have a behaviour where, although they will delete the session
# cookie when the browser shutdowns, they will still serve a cached version
# of the page on relaunch.

View file

@ -1,14 +1,14 @@
describe Champs::SiretController, type: :controller do
let(:user) { create(:user) }
let(:procedure) { create(:procedure, :published) }
let(:procedure) do
tdc_siret = build(:type_de_champ_siret, procedure: nil)
create(:procedure, :published, types_de_champ: [tdc_siret])
end
describe '#show' do
let(:dossier) { create(:dossier, user: user, procedure: procedure) }
let(:champ) do
d = dossier
type_de_champ = create(:type_de_champ_siret, procedure: procedure)
type_de_champ.champ.create(dossier: d, value: nil, etablissement: nil)
end
let(:champ) { dossier.champs.first }
let(:params) do
{
champ_id: champ.id,
@ -27,6 +27,7 @@ describe Champs::SiretController, type: :controller do
let(:api_etablissement_status) { 200 }
let(:api_etablissement_body) { File.read('spec/fixtures/files/api_entreprise/etablissements.json') }
let(:token_expired) { false }
before do
sign_in user
stub_request(:get, /https:\/\/entreprise.api.gouv.fr\/v2\/etablissements\/#{siret}?.*token=/)
@ -112,7 +113,7 @@ describe Champs::SiretController, type: :controller do
champ.reload
expect(champ.value).to eq(siret)
expect(champ.etablissement.siret).to eq(siret)
expect(champ.reload.etablissement.naf).to eq("6202A")
expect(champ.etablissement.naf).to eq("6202A")
expect(dossier.reload.etablissement).to eq(nil)
end
end

View file

@ -561,32 +561,35 @@ describe Instructeurs::DossiersController, type: :controller do
describe "#update_annotations" do
let(:champ_multiple_drop_down_list) do
create(:type_de_champ_multiple_drop_down_list, :private, libelle: 'libelle').champ.create
tdc = create(:type_de_champ_multiple_drop_down_list, :private, procedure: procedure, libelle: 'libelle')
create(:champ_multiple_drop_down_list, :private, type_de_champ: tdc, dossier: dossier)
end
let(:champ_linked_drop_down_list) do
create(:type_de_champ_linked_drop_down_list, :private, libelle: 'libelle').champ.create
tdc = create(:type_de_champ_linked_drop_down_list, :private, procedure: procedure, libelle: 'libelle')
create(:champ_linked_drop_down_list, :private, type_de_champ: tdc, dossier: dossier)
end
let(:champ_datetime) do
create(:type_de_champ_datetime, :private, libelle: 'libelle').champ.create
tdc = create(:type_de_champ_datetime, :private, procedure: procedure, libelle: 'libelle')
create(:champ_datetime, :private, type_de_champ: tdc, dossier: dossier)
end
let(:champ_repetition) do
tdc = create(:type_de_champ_repetition, :private, libelle: 'libelle')
tdc.types_de_champ << create(:type_de_champ_text, libelle: 'libelle')
champ = tdc.champ.create
tdc = create(:type_de_champ_repetition, :private, :with_types_de_champ, procedure: procedure, libelle: 'libelle')
tdc.types_de_champ << create(:type_de_champ_text, procedure: procedure, libelle: 'libelle')
champ = create(:champ_repetition, :private, type_de_champ: tdc, dossier: dossier)
champ.add_row
champ
end
let(:dossier) do
create(:dossier, :en_construction, procedure: procedure, champs_private: [champ_multiple_drop_down_list, champ_linked_drop_down_list, champ_datetime, champ_repetition])
end
let(:dossier) { create(:dossier, :en_construction, procedure: procedure) }
let(:now) { Time.zone.parse('01/01/2100') }
before do
dossier.champs_private << [champ_multiple_drop_down_list, champ_linked_drop_down_list, champ_datetime, champ_repetition]
Timecop.freeze(now)
patch :update_annotations, params: params

View file

@ -400,8 +400,8 @@ describe Users::DossiersController, type: :controller do
before do
allow(DossierMailer).to receive(:notify_new_dossier_depose_to_instructeur).and_return(double(deliver_later: nil))
create(:assign_to, instructeur: instructeur_with_instant_email_dossier, procedure: dossier.procedure, instant_email_dossier_notifications_enabled: true, groupe_instructeur: dossier.procedure.defaut_groupe_instructeur)
create(:assign_to, instructeur: instructeur_without_instant_email_dossier, procedure: dossier.procedure, instant_email_dossier_notifications_enabled: false, groupe_instructeur: dossier.procedure.defaut_groupe_instructeur)
create(:assign_to, instructeur: instructeur_with_instant_email_dossier, procedure: dossier.procedure, instant_email_dossier_notifications_enabled: true)
create(:assign_to, instructeur: instructeur_without_instant_email_dossier, procedure: dossier.procedure, instant_email_dossier_notifications_enabled: false)
end
it "sends notification mail to instructeurs" do
@ -838,8 +838,8 @@ describe Users::DossiersController, type: :controller do
allow(DossierMailer).to receive(:notify_new_commentaire_to_instructeur).and_return(double(deliver_later: nil))
instructeur_with_instant_message.follow(dossier)
instructeur_without_instant_message.follow(dossier)
create(:assign_to, instructeur: instructeur_with_instant_message, procedure: procedure, instant_email_message_notifications_enabled: true, groupe_instructeur: procedure.defaut_groupe_instructeur)
create(:assign_to, instructeur: instructeur_without_instant_message, procedure: procedure, instant_email_message_notifications_enabled: false, groupe_instructeur: procedure.defaut_groupe_instructeur)
create(:assign_to, instructeur: instructeur_with_instant_message, procedure: procedure, instant_email_message_notifications_enabled: true)
create(:assign_to, instructeur: instructeur_without_instant_message, procedure: procedure, instant_email_message_notifications_enabled: false)
end
after { Timecop.return }

View file

@ -1,11 +1,5 @@
FactoryBot.define do
factory :assign_to do
after(:build) do |assign_to, evaluator|
if evaluator.groupe_instructeur.persisted?
assign_to.groupe_instructeur = evaluator.groupe_instructeur
else
assign_to.groupe_instructeur = assign_to.procedure.defaut_groupe_instructeur
end
end
groupe_instructeur { procedure.defaut_groupe_instructeur }
end
end

View file

@ -1,7 +1,7 @@
FactoryBot.define do
factory :attestation do
title { 'title' }
dossier { create(:dossier) }
association :dossier
end
trait :with_pdf do

View file

@ -4,6 +4,8 @@ FactoryBot.define do
body { 'body' }
footer { 'footer' }
activated { true }
association :procedure
end
trait :with_files do

View file

@ -9,6 +9,11 @@ FactoryBot.define do
association :dossier
association :claimant, factory: :instructeur
trait :with_instructeur do
email { nil }
instructeur { association :instructeur, email: generate(:expert_email) }
end
trait :with_answer do
answer { "Mon avis se décompose en deux points :\n- La demande semble pertinente\n- Le demandeur remplit les conditions." }
end

View file

@ -1,197 +1,220 @@
FactoryBot.define do
factory :champ do
type_de_champ { create(:type_de_champ) }
add_attribute(:private) { false }
trait :checkbox do
type_de_champ { create(:type_de_champ_checkbox) }
end
dossier { association :dossier }
type_de_champ { association :type_de_champ, procedure: dossier.procedure }
trait :header_section do
type_de_champ { create(:type_de_champ_header_section) }
end
trait :explication do
type_de_champ { create(:type_de_champ_explication) }
end
trait :dossier_link do
type_de_champ { create(:type_de_champ_dossier_link) }
end
trait :piece_justificative do
type_de_champ { create(:type_de_champ_piece_justificative) }
trait :private do
add_attribute(:private) { true }
end
trait :with_piece_justificative_file do
after(:create) do |champ, _evaluator|
after(:build) do |champ, _evaluator|
champ.piece_justificative_file.attach(io: StringIO.new("toto"), filename: "toto.txt", content_type: "text/plain")
end
end
end
factory :champ_text, class: 'Champs::TextChamp' do
type_de_champ { create(:type_de_champ_text) }
value { 'text' }
end
factory :champ_textarea, class: 'Champs::TextareaChamp' do
type_de_champ { create(:type_de_champ_textarea) }
value { 'textarea' }
end
factory :champ_date, class: 'Champs::DateChamp' do
type_de_champ { create(:type_de_champ_date) }
value { '2019-07-10' }
end
factory :champ_datetime, class: 'Champs::DatetimeChamp' do
type_de_champ { create(:type_de_champ_datetime) }
value { '15/09/1962 15:35' }
end
factory :champ_number, class: 'Champs::NumberChamp' do
type_de_champ { create(:type_de_champ_number) }
value { '42' }
end
factory :champ_decimal_number, class: 'Champs::DecimalNumberChamp' do
type_de_champ { create(:type_de_champ_decimal_number) }
value { '42.1' }
end
factory :champ_integer_number, class: 'Champs::IntegerNumberChamp' do
type_de_champ { create(:type_de_champ_integer_number) }
value { '42' }
end
factory :champ_checkbox, class: 'Champs::CheckboxChamp' do
type_de_champ { create(:type_de_champ_checkbox) }
value { 'on' }
end
factory :champ_civilite, class: 'Champs::CiviliteChamp' do
type_de_champ { create(:type_de_champ_civilite) }
value { 'M.' }
end
factory :champ_email, class: 'Champs::EmailChamp' do
type_de_champ { create(:type_de_champ_email) }
value { 'yoda@beta.gouv.fr' }
end
factory :champ_phone, class: 'Champs::PhoneChamp' do
type_de_champ { create(:type_de_champ_phone) }
value { '0666666666' }
end
factory :champ_address, class: 'Champs::AddressChamp' do
type_de_champ { create(:type_de_champ_address) }
value { '2 rue des Démarches' }
end
factory :champ_yes_no, class: 'Champs::YesNoChamp' do
type_de_champ { create(:type_de_champ_yes_no) }
value { 'true' }
end
factory :champ_drop_down_list, class: 'Champs::DropDownListChamp' do
type_de_champ { create(:type_de_champ_drop_down_list) }
value { 'choix 1' }
end
factory :champ_multiple_drop_down_list, class: 'Champs::MultipleDropDownListChamp' do
type_de_champ { create(:type_de_champ_multiple_drop_down_list) }
value { '["choix 1", "choix 2"]' }
end
factory :champ_linked_drop_down_list, class: 'Champs::LinkedDropDownListChamp' do
type_de_champ { create(:type_de_champ_linked_drop_down_list) }
value { '["categorie 1", "choix 1"]' }
end
factory :champ_pays, class: 'Champs::PaysChamp' do
type_de_champ { create(:type_de_champ_pays) }
value { 'France' }
end
factory :champ_regions, class: 'Champs::RegionChamp' do
type_de_champ { create(:type_de_champ_regions) }
value { 'Guadeloupe' }
end
factory :champ_departements, class: 'Champs::DepartementChamp' do
type_de_champ { create(:type_de_champ_departements) }
value { '971 - Guadeloupe' }
end
factory :champ_communes, class: 'Champs::CommuneChamp' do
type_de_champ { create(:type_de_champ_communes) }
value { 'Paris' }
end
factory :champ_engagement, class: 'Champs::EngagementChamp' do
type_de_champ { create(:type_de_champ_engagement) }
value { 'true' }
end
factory :champ_header_section, class: 'Champs::HeaderSectionChamp' do
type_de_champ { create(:type_de_champ_header_section) }
value { 'une section' }
end
factory :champ_explication, class: 'Champs::ExplicationChamp' do
type_de_champ { create(:type_de_champ_explication) }
value { '' }
end
factory :champ_dossier_link, class: 'Champs::DossierLinkChamp' do
type_de_champ { create(:type_de_champ_dossier_link) }
value { create(:dossier).id }
end
factory :champ_piece_justificative, class: 'Champs::PieceJustificativeChamp' do
type_de_champ { create(:type_de_champ_piece_justificative) }
after(:build) do |champ, _evaluator|
champ.piece_justificative_file.attach(io: StringIO.new("toto"), filename: "toto.txt", content_type: "text/plain")
factory :champ_text, class: 'Champs::TextChamp' do
type_de_champ { association :type_de_champ_text, procedure: dossier.procedure }
value { 'text' }
end
end
factory :champ_carte, class: 'Champs::CarteChamp' do
type_de_champ { create(:type_de_champ_carte) }
end
factory :champ_siret, class: 'Champs::SiretChamp' do
association :type_de_champ, factory: [:type_de_champ_siret]
association :etablissement, factory: [:etablissement]
value { '44011762001530' }
end
factory :champ_repetition, class: 'Champs::RepetitionChamp' do
type_de_champ { create(:type_de_champ_repetition) }
after(:build) do |champ_repetition, _evaluator|
type_de_champ_text = create(:type_de_champ_text, order_place: 0, parent: champ_repetition.type_de_champ, libelle: 'Nom')
type_de_champ_number = create(:type_de_champ_number, order_place: 1, parent: champ_repetition.type_de_champ, libelle: 'Age')
create(:champ_text, row: 0, type_de_champ: type_de_champ_text, parent: champ_repetition)
create(:champ_number, row: 0, type_de_champ: type_de_champ_number, parent: champ_repetition)
create(:champ_text, row: 1, type_de_champ: type_de_champ_text, parent: champ_repetition)
create(:champ_number, row: 1, type_de_champ: type_de_champ_number, parent: champ_repetition)
factory :champ_textarea, class: 'Champs::TextareaChamp' do
type_de_champ { association :type_de_champ_textarea, procedure: dossier.procedure }
value { 'textarea' }
end
end
factory :champ_repetition_with_piece_jointe, class: 'Champs::RepetitionChamp' do
type_de_champ { create(:type_de_champ_repetition) }
factory :champ_date, class: 'Champs::DateChamp' do
type_de_champ { association :type_de_champ_date, procedure: dossier.procedure }
value { '2019-07-10' }
end
after(:build) do |champ_repetition, _evaluator|
type_de_champ_pj0 = create(:type_de_champ_piece_justificative, order_place: 0, parent: champ_repetition.type_de_champ, libelle: 'Justificatif de domicile')
type_de_champ_pj1 = create(:type_de_champ_piece_justificative, order_place: 1, parent: champ_repetition.type_de_champ, libelle: 'Carte d\'identité')
factory :champ_datetime, class: 'Champs::DatetimeChamp' do
type_de_champ { association :type_de_champ_datetime, procedure: dossier.procedure }
value { '15/09/1962 15:35' }
end
create(:champ_piece_justificative, row: 0, type_de_champ: type_de_champ_pj0, parent: champ_repetition)
create(:champ_piece_justificative, row: 0, type_de_champ: type_de_champ_pj1, parent: champ_repetition)
create(:champ_piece_justificative, row: 1, type_de_champ: type_de_champ_pj0, parent: champ_repetition)
create(:champ_piece_justificative, row: 1, type_de_champ: type_de_champ_pj1, parent: champ_repetition)
factory :champ_number, class: 'Champs::NumberChamp' do
type_de_champ { association :type_de_champ_number, procedure: dossier.procedure }
value { '42' }
end
factory :champ_decimal_number, class: 'Champs::DecimalNumberChamp' do
type_de_champ { association :type_de_champ_decimal_number, procedure: dossier.procedure }
value { '42.1' }
end
factory :champ_integer_number, class: 'Champs::IntegerNumberChamp' do
type_de_champ { association :type_de_champ_integer_number, procedure: dossier.procedure }
value { '42' }
end
factory :champ_checkbox, class: 'Champs::CheckboxChamp' do
type_de_champ { association :type_de_champ_checkbox, procedure: dossier.procedure }
value { 'on' }
end
factory :champ_civilite, class: 'Champs::CiviliteChamp' do
type_de_champ { association :type_de_champ_civilite, procedure: dossier.procedure }
value { 'M.' }
end
factory :champ_email, class: 'Champs::EmailChamp' do
type_de_champ { association :type_de_champ_email, procedure: dossier.procedure }
value { 'yoda@beta.gouv.fr' }
end
factory :champ_phone, class: 'Champs::PhoneChamp' do
type_de_champ { association :type_de_champ_phone, procedure: dossier.procedure }
value { '0666666666' }
end
factory :champ_address, class: 'Champs::AddressChamp' do
type_de_champ { association :type_de_champ_address, procedure: dossier.procedure }
value { '2 rue des Démarches' }
end
factory :champ_yes_no, class: 'Champs::YesNoChamp' do
type_de_champ { association :type_de_champ_yes_no, procedure: dossier.procedure }
value { 'true' }
end
factory :champ_drop_down_list, class: 'Champs::DropDownListChamp' do
type_de_champ { association :type_de_champ_drop_down_list, procedure: dossier.procedure }
value { 'choix 1' }
end
factory :champ_multiple_drop_down_list, class: 'Champs::MultipleDropDownListChamp' do
type_de_champ { association :type_de_champ_multiple_drop_down_list, procedure: dossier.procedure }
value { '["choix 1", "choix 2"]' }
end
factory :champ_linked_drop_down_list, class: 'Champs::LinkedDropDownListChamp' do
type_de_champ { association :type_de_champ_linked_drop_down_list, procedure: dossier.procedure }
value { '["categorie 1", "choix 1"]' }
end
factory :champ_pays, class: 'Champs::PaysChamp' do
type_de_champ { association :type_de_champ_pays, procedure: dossier.procedure }
value { 'France' }
end
factory :champ_regions, class: 'Champs::RegionChamp' do
type_de_champ { association :type_de_champ_regions, procedure: dossier.procedure }
value { 'Guadeloupe' }
end
factory :champ_departements, class: 'Champs::DepartementChamp' do
type_de_champ { association :type_de_champ_departements, procedure: dossier.procedure }
value { '971 - Guadeloupe' }
end
factory :champ_communes, class: 'Champs::CommuneChamp' do
type_de_champ { association :type_de_champ_communes, procedure: dossier.procedure }
value { 'Paris' }
end
factory :champ_engagement, class: 'Champs::EngagementChamp' do
type_de_champ { association :type_de_champ_engagement, procedure: dossier.procedure }
value { 'true' }
end
factory :champ_header_section, class: 'Champs::HeaderSectionChamp' do
type_de_champ { association :type_de_champ_header_section, procedure: dossier.procedure }
value { 'une section' }
end
factory :champ_explication, class: 'Champs::ExplicationChamp' do
type_de_champ { association :type_de_champ_explication, procedure: dossier.procedure }
value { '' }
end
factory :champ_dossier_link, class: 'Champs::DossierLinkChamp' do
type_de_champ { association :type_de_champ_dossier_link, procedure: dossier.procedure }
value { create(:dossier).id }
end
factory :champ_piece_justificative, class: 'Champs::PieceJustificativeChamp' do
type_de_champ { association :type_de_champ_piece_justificative, procedure: dossier.procedure }
after(:build) do |champ, _evaluator|
champ.piece_justificative_file.attach(io: StringIO.new("toto"), filename: "toto.txt", content_type: "text/plain")
end
end
factory :champ_carte, class: 'Champs::CarteChamp' do
type_de_champ { association :type_de_champ_carte, procedure: dossier.procedure }
end
factory :champ_siret, class: 'Champs::SiretChamp' do
association :type_de_champ, factory: [:type_de_champ_siret]
association :etablissement, factory: [:etablissement]
value { '44011762001530' }
end
factory :champ_repetition, class: 'Champs::RepetitionChamp' do
type_de_champ { association :type_de_champ_repetition, procedure: dossier.procedure }
after(:build) do |champ_repetition, _evaluator|
types_de_champ = champ_repetition.type_de_champ.types_de_champ
existing_type_de_champ_text = types_de_champ.find { |tdc| tdc.libelle == 'Nom' }
type_de_champ_text = existing_type_de_champ_text || build(
:type_de_champ_text,
order_place: 0,
procedure: champ_repetition.dossier.procedure,
parent: champ_repetition.type_de_champ,
libelle: 'Nom'
)
types_de_champ << type_de_champ_text
existing_type_de_champ_number = types_de_champ.find { |tdc| tdc.libelle == 'Age' }
type_de_champ_number = existing_type_de_champ_number || build(
:type_de_champ_number,
order_place: 1,
procedure: champ_repetition.dossier.procedure,
parent: champ_repetition.type_de_champ,
libelle: 'Age'
)
types_de_champ << type_de_champ_number
champ_repetition.champs << [
build(:champ_text, dossier: champ_repetition.dossier, row: 0, type_de_champ: type_de_champ_text, parent: champ_repetition),
build(:champ_number, dossier: champ_repetition.dossier, row: 0, type_de_champ: type_de_champ_number, parent: champ_repetition),
build(:champ_text, dossier: champ_repetition.dossier, row: 1, type_de_champ: type_de_champ_text, parent: champ_repetition),
build(:champ_number, dossier: champ_repetition.dossier, row: 1, type_de_champ: type_de_champ_number, parent: champ_repetition)
]
end
trait :without_champs do
after(:build) do |champ_repetition, _evaluator|
champ_repetition.champs = []
end
end
end
factory :champ_repetition_with_piece_jointe, class: 'Champs::RepetitionChamp' do
type_de_champ { association :type_de_champ_repetition, procedure: dossier.procedure }
after(:build) do |champ_repetition, _evaluator|
type_de_champ_pj0 = build(:type_de_champ_piece_justificative,
procedure: champ_repetition.dossier.procedure,
order_place: 0,
parent: champ_repetition.type_de_champ,
libelle: 'Justificatif de domicile')
type_de_champ_pj1 = build(:type_de_champ_piece_justificative,
procedure: champ_repetition.dossier.procedure,
order_place: 1,
parent: champ_repetition.type_de_champ,
libelle: 'Carte d\'identité')
champ_repetition.champs << [
build(:champ_piece_justificative, dossier: champ_repetition.dossier, row: 0, type_de_champ: type_de_champ_pj0),
build(:champ_piece_justificative, dossier: champ_repetition.dossier, row: 0, type_de_champ: type_de_champ_pj1),
build(:champ_piece_justificative, dossier: champ_repetition.dossier, row: 1, type_de_champ: type_de_champ_pj0),
build(:champ_piece_justificative, dossier: champ_repetition.dossier, row: 1, type_de_champ: type_de_champ_pj1)
]
end
end
end
end

View file

@ -1,12 +1,8 @@
FactoryBot.define do
factory :commentaire do
body { 'plop' }
association :dossier, :en_construction
before(:create) do |commentaire, _evaluator|
if !commentaire.dossier
commentaire.dossier = create :dossier, :en_construction
end
end
body { 'plop' }
trait :with_file do
piece_jointe { Rack::Test::UploadedFile.new('spec/fixtures/files/logo_test_procedure.png', 'image/png') }

View file

@ -2,7 +2,7 @@ FactoryBot.define do
factory :dossier do
autorisation_donnees { true }
state { Dossier.states.fetch(:brouillon) }
association :user, factory: [:user]
association :user
transient do
procedure { nil }
@ -49,7 +49,7 @@ FactoryBot.define do
if !dossier.procedure.for_individual?
raise 'Inconsistent factory: attempting to create a dossier :with_individual on a procedure that is not `for_individual?`'
end
dossier.individual = create(:individual)
dossier.individual = build(:individual, dossier: dossier)
end
end
@ -183,9 +183,9 @@ FactoryBot.define do
end
trait :with_attestation do
after(:create) do |dossier, _evaluator|
after(:build) do |dossier, _evaluator|
if dossier.procedure.attestation_template.blank?
dossier.procedure.attestation_template = create(:attestation_template)
dossier.procedure.attestation_template = build(:attestation_template)
end
dossier.attestation = dossier.build_attestation
end
@ -203,7 +203,7 @@ FactoryBot.define do
trait :with_all_champs do
after(:create) do |dossier, _evaluator|
dossier.champs = dossier.procedure.types_de_champ.map do |type_de_champ|
build(:"champ_#{type_de_champ.type_champ}", type_de_champ: type_de_champ)
build(:"champ_#{type_de_champ.type_champ}", dossier: dossier, type_de_champ: type_de_champ)
end
dossier.save!
end
@ -212,7 +212,7 @@ FactoryBot.define do
trait :with_all_annotations do
after(:create) do |dossier, _evaluator|
dossier.champs = dossier.procedure.types_de_champ.map do |type_de_champ|
build(:"champ_#{type_de_champ.type_champ}", type_de_champ: type_de_champ)
build(:"champ_#{type_de_champ.type_champ}", dossier: dossier, type_de_champ: type_de_champ)
end
dossier.save!
end

View file

@ -25,9 +25,7 @@ FactoryBot.define do
entreprise_date_creation { "1990-04-24" }
trait :with_exercices do
after(:create) do |etablissement, _evaluator|
create(:exercice, etablissement: etablissement)
end
exercices { [association(:exercice)] }
end
trait :with_effectif_mensuel do

View file

@ -3,6 +3,6 @@ FactoryBot.define do
ca { '12345678' }
date_fin_exercice { "2014-12-30 23:00:00" }
date_fin_exercice_timestamp { 1419980400 }
association :etablissement, factory: [:etablissement]
association :etablissement
end
end

View file

@ -1,6 +1,6 @@
FactoryBot.define do
factory :export do
format { :csv }
groupe_instructeurs { [create(:groupe_instructeur)] }
groupe_instructeurs { [association(:groupe_instructeur)] }
end
end

View file

@ -1,6 +1,7 @@
FactoryBot.define do
factory :feedback do
rating { Feedback.ratings.fetch(:happy) }
association :user
trait :happy do
rating { Feedback.ratings.fetch(:happy) }

View file

@ -1,4 +1,6 @@
FactoryBot.define do
factory :follow do
association :instructeur
association :dossier
end
end

View file

@ -1,5 +1,7 @@
FactoryBot.define do
factory :geo_area do
association :champ
trait :cadastre do
source { GeoArea.sources.fetch(:cadastre) }
numero { '42' }

View file

@ -3,6 +3,6 @@ FactoryBot.define do
factory :groupe_instructeur do
label { generate(:groupe_label) }
procedure { create(:procedure) }
association :procedure
end
end

View file

@ -4,5 +4,6 @@ FactoryBot.define do
nom { 'Julien' }
prenom { 'Xavier' }
birthdate { Date.new(1991, 11, 01) }
association :dossier
end
end

View file

@ -1,24 +1,17 @@
FactoryBot.define do
factory :invite do
email { 'plop@octo.com' }
user { nil }
association :dossier
after(:build) do |invite, _evaluator|
if invite.dossier.nil?
invite.dossier = create(:dossier)
end
if invite.user.present?
invite.email = invite.user.email
end
end
trait :with_user do
after(:build) do |invite, _evaluator|
if invite.user.nil?
invite.user = create(:user)
invite.email = invite.user.email
end
end
association :user
end
end
end

View file

@ -2,6 +2,7 @@ FactoryBot.define do
factory :closed_mail, class: Mails::ClosedMail do
subject { "Subject, voila voila" }
body { "Blabla ceci est mon body" }
association :procedure
factory :received_mail, class: Mails::ReceivedMail

View file

@ -70,7 +70,7 @@ FactoryBot.define do
trait :with_instructeur do
after(:create) do |procedure, _evaluator|
procedure.defaut_groupe_instructeur.instructeurs << create(:instructeur)
procedure.defaut_groupe_instructeur.instructeurs << build(:instructeur)
end
end
@ -232,10 +232,10 @@ FactoryBot.define do
if libelle == 'drop_down_list'
libelle = 'simple_drop_down_list'
end
build(:"type_de_champ_#{type_champ}", mandatory: true, libelle: libelle, order_place: index)
build(:"type_de_champ_#{type_champ}", procedure: procedure, mandatory: true, libelle: libelle, order_place: index)
end
procedure.types_de_champ << build(:type_de_champ_drop_down_list, :long, mandatory: true, libelle: 'simple_choice_drop_down_list_long')
procedure.types_de_champ << build(:type_de_champ_multiple_drop_down_list, :long, mandatory: true, libelle: 'multiple_choice_drop_down_list_long')
procedure.types_de_champ << build(:type_de_champ_drop_down_list, :long, procedure: procedure, mandatory: true, libelle: 'simple_choice_drop_down_list_long')
procedure.types_de_champ << build(:type_de_champ_multiple_drop_down_list, :long, procedure: procedure, mandatory: true, libelle: 'multiple_choice_drop_down_list_long')
end
end
@ -245,7 +245,7 @@ FactoryBot.define do
if libelle == 'drop_down_list'
libelle = 'simple_drop_down_list'
end
build(:"type_de_champ_#{type_champ}", libelle: libelle, order_place: index)
build(:"type_de_champ_#{type_champ}", procedure: procedure, libelle: libelle, order_place: index)
end
end
end
@ -256,7 +256,7 @@ FactoryBot.define do
if libelle == 'drop_down_list'
libelle = 'simple_drop_down_list'
end
build(:"type_de_champ_#{type_champ}", private: true, libelle: libelle, order_place: index)
build(:"type_de_champ_#{type_champ}", procedure: procedure, private: true, libelle: libelle, order_place: index)
end
end
end

View file

@ -1,6 +1,10 @@
FactoryBot.define do
factory :procedure_presentation do
assign_to { create(:assign_to, procedure: create(:procedure, :with_type_de_champ)) }
transient do
procedure { create(:procedure, :with_instructeur, :with_type_de_champ) }
end
assign_to { association :assign_to, procedure: procedure, instructeur: procedure.instructeurs.first }
sort { { "table" => "user", "column" => "email", "order" => "asc" } }
end
end

View file

@ -3,10 +3,11 @@ FactoryBot.define do
nom { 'service' }
organisme { 'organisme' }
type_organisme { Service.type_organismes.fetch(:association) }
administrateur { create(:administrateur) }
email { 'email@toto.com' }
telephone { '1234' }
horaires { 'de 9 h à 18 h' }
adresse { 'adresse' }
association :administrateur
end
end

View file

@ -0,0 +1,5 @@
FactoryBot.define do
factory :trusted_device_token do
association :instructeur
end
end

View file

@ -7,6 +7,8 @@ FactoryBot.define do
mandatory { false }
add_attribute(:private) { false }
association :procedure
factory :type_de_champ_text do
type_champ { TypeDeChamp.type_champs.fetch(:text) }
end
@ -94,7 +96,7 @@ FactoryBot.define do
factory :type_de_champ_piece_justificative do
type_champ { TypeDeChamp.type_champs.fetch(:piece_justificative) }
after(:create) do |tc, _evaluator|
after(:build) do |tc, _evaluator|
tc.piece_justificative_template.attach(io: StringIO.new("toto"), filename: "toto.txt", content_type: "text/plain")
end
end
@ -109,7 +111,7 @@ FactoryBot.define do
trait :with_types_de_champ do
after(:build) do |type_de_champ, _evaluator|
type_de_champ.types_de_champ << create(:type_de_champ, libelle: 'sub type de champ')
type_de_champ.types_de_champ << build(:type_de_champ, procedure: type_de_champ.procedure, libelle: 'sub type de champ')
end
end
end

View file

@ -41,8 +41,8 @@ RSpec.describe DossierHelper, type: :helper do
describe ".demandeur_dossier" do
subject { demandeur_dossier(dossier) }
let(:individual) { create(:individual) }
let(:etablissement) { create(:etablissement) }
let(:individual) { build(:individual, dossier: nil) }
let(:etablissement) { build(:etablissement) }
let(:dossier) { create(:dossier, procedure: procedure, individual: individual, etablissement: etablissement) }
context "when the dossier is for an individual" do

View file

@ -2,7 +2,7 @@ RSpec.describe VirusScannerJob, type: :job do
include ActiveJob::TestHelper
let(:champ) do
champ = create(:champ, :piece_justificative)
champ = create(:champ_piece_justificative)
champ.piece_justificative_file.attach(io: StringIO.new("toto"), filename: "toto.txt", content_type: "text/plain")
champ.save
champ

View file

@ -1,5 +1,5 @@
describe ActiveStorage::DownloadableFile do
let(:dossier) { create(:dossier) }
let(:dossier) { create(:dossier, :en_construction) }
subject(:list) { ActiveStorage::DownloadableFile.create_list_from_dossier(dossier) }
@ -10,7 +10,7 @@ describe ActiveStorage::DownloadableFile do
context 'when there is a piece_justificative' do
before do
dossier.champs << create(:champ, :piece_justificative, :with_piece_justificative_file)
dossier.champs << create(:champ_piece_justificative, :with_piece_justificative_file, dossier: dossier)
end
it { expect(list.length).to eq 1 }
@ -18,15 +18,16 @@ describe ActiveStorage::DownloadableFile do
context 'when there is a private piece_justificative' do
before do
dossier.champs_private << create(:champ, :piece_justificative, :with_piece_justificative_file, private: true)
dossier.champs_private << create(:champ_piece_justificative, :with_piece_justificative_file, private: true, dossier: dossier)
end
it { expect(list.length).to eq 1 }
end
context 'when there is a repetition bloc' do
let(:champ) { build(:champ_repetition_with_piece_jointe) }
let(:dossier) { create(:dossier, :en_construction, champs: [champ]) }
before do
dossier.champs << build(:champ_repetition_with_piece_jointe, dossier: dossier)
end
it 'should have 4 piece_justificatives' do
expect(list.size).to eq 4
@ -34,15 +35,17 @@ describe ActiveStorage::DownloadableFile do
end
context 'when there is a message with no attachment' do
let(:commentaire) { create(:commentaire) }
let(:dossier) { commentaire.dossier }
before do
dossier.commentaires << create(:commentaire, dossier: dossier)
end
it { expect(list.length).to eq 0 }
end
context 'when there is a message with an attachment' do
let(:commentaire) { create(:commentaire, :with_file) }
let(:dossier) { commentaire.dossier }
before do
dossier.commentaires << create(:commentaire, :with_file, dossier: dossier)
end
it { expect(list.length).to eq 1 }
end

View file

@ -1,7 +1,7 @@
describe AssignTo, type: :model do
describe '#procedure_presentation_or_default_and_errors' do
let(:procedure) { create(:procedure) }
let(:assign_to) { create(:assign_to, procedure: procedure) }
let(:assign_to) { create(:assign_to, procedure: procedure, instructeur: create(:instructeur)) }
let(:procedure_presentation_and_errors) { assign_to.procedure_presentation_or_default_and_errors }
let(:procedure_presentation_or_default) { procedure_presentation_and_errors.first }

View file

@ -87,7 +87,7 @@ RSpec.describe Avis, type: :model do
describe '#try_to_assign_instructeur' do
let!(:instructeur) { create(:instructeur) }
let(:avis) { Avis.create(claimant: claimant, email: email, dossier: create(:dossier)) }
let(:avis) { create(:avis, claimant: claimant, email: email, dossier: create(:dossier)) }
context 'when the email belongs to a instructeur' do
let(:email) { instructeur.email }

View file

@ -1,7 +1,7 @@
shared_examples 'champ_spec' do
describe 'mandatory_and_blank?' do
let(:type_de_champ) { build(:type_de_champ, mandatory: mandatory) }
let(:champ) { type_de_champ.champ.build(value: value) }
let(:champ) { build(:champ, type_de_champ: type_de_champ, value: value) }
let(:value) { '' }
let(:mandatory) { true }
@ -33,8 +33,7 @@ shared_examples 'champ_spec' do
end
context "when type_champ=date" do
let(:type_de_champ) { create(:type_de_champ_date) }
let(:champ) { type_de_champ.champ.create }
let(:champ) { build(:champ_date) }
it "should convert %d/%m/%Y format to ISO" do
champ.value = "31/12/2017"

View file

@ -47,7 +47,7 @@ describe Champ do
let(:public_champ) { dossier.champs.first }
let(:private_champ) { dossier.champs_private.first }
let(:champ_in_repetition) { dossier.champs.find(&:repetition?).champs.first }
let(:standalone_champ) { create(:champ, dossier: nil) }
let(:standalone_champ) { build(:champ, type_de_champ: build(:type_de_champ), dossier: nil) }
it 'returns the sibling champs of a champ' do
expect(public_champ.siblings).to eq(dossier.champs)
@ -58,10 +58,9 @@ describe Champ do
end
describe '#format_datetime' do
let(:type_de_champ) { build(:type_de_champ_datetime) }
let(:champ) { type_de_champ.champ.build(value: value) }
let(:champ) { build(:champ_datetime, value: value) }
before { champ.save }
before { champ.save! }
context 'when the value is sent by a modern browser' do
let(:value) { '2017-12-31 10:23' }
@ -77,10 +76,9 @@ describe Champ do
end
describe '#multiple_select_to_string' do
let(:type_de_champ) { build(:type_de_champ_multiple_drop_down_list) }
let(:champ) { type_de_champ.champ.build(value: value) }
let(:champ) { build(:champ_multiple_drop_down_list, value: value) }
before { champ.save }
before { champ.save! }
# when using the old form, and the ChampsService Class
# TODO: to remove
@ -412,7 +410,7 @@ describe Champ do
end
describe '#enqueue_virus_check' do
let(:champ) { type_de_champ.champ.build(value: nil) }
let(:champ) { build(:champ_piece_justificative, type_de_champ: type_de_champ) }
context 'when type_champ is type_de_champ_piece_justificative' do
let(:type_de_champ) { create(:type_de_champ_piece_justificative) }
@ -420,7 +418,7 @@ describe Champ do
context 'and there is a blob' do
before do
champ.piece_justificative_file.attach(io: StringIO.new("toto"), filename: "toto.txt", content_type: "text/plain")
champ.save
champ.save!
end
it { expect(champ.piece_justificative_file.virus_scanner.started?).to be_truthy }
@ -428,50 +426,69 @@ describe Champ do
end
end
describe "repetition" do
let(:dossier) { create(:dossier) }
let(:champ) { Champs::RepetitionChamp.create(dossier: dossier) }
let(:champ_text) { create(:champ_text, row: 0) }
let(:champ_integer_number) { create(:champ_integer_number, row: 0) }
let(:champ_text_attrs) { attributes_for(:champ_text, row: 1) }
let(:champ_text_row_1) { create(:champ_text, row: 1, parent: champ) }
describe 'repetition' do
let(:procedure) { build(:procedure, :published, :with_type_de_champ, :with_type_de_champ_private) }
let(:tdc_text) { build(:type_de_champ_text, procedure: procedure) }
let(:tdc_integer) { build(:type_de_champ_integer_number, procedure: procedure) }
let(:tdc_repetition) { build(:type_de_champ_repetition, procedure: procedure, types_de_champ: [tdc_text, tdc_integer]) }
it "associates nested champs to the parent dossier" do
expect(champ.rows.size).to eq(0)
dossier.reload
expect(dossier.champs.size).to eq(2)
let(:dossier) { create(:dossier, procedure: procedure) }
let(:champ) { dossier.champs.find(&:repetition?) }
let(:champ_text) { champ.champs.find { |c| c.type_champ == 'text' } }
let(:champ_integer) { champ.champs.find { |c| c.type_champ == 'integer_number' } }
let(:champ_text_attrs) { attributes_for(:champ_text, type_de_champ: tdc_text, row: 1) }
dossier.update(champs_attributes: [
{
id: champ.id,
champs_attributes: [champ_text_attrs]
}
])
before do
procedure.types_de_champ << tdc_repetition
procedure.save!
procedure.reload
end
champ.reload
dossier.reload
expect(dossier.champs.size).to eq(2)
expect(champ.rows.size).to eq(1)
context 'when creating the model directly' do
let(:champ_text_row_1) { create(:champ_text, type_de_champ: tdc_text, row: 2, parent: champ, dossier: nil) }
expect(champ.champs.first.dossier).to eq(dossier)
it 'associates nested champs to the parent dossier' do
expect(champ_text_row_1.dossier_id).to eq(champ.dossier_id)
end
end
# Make champs ordered
champ_integer_number.type_de_champ.update(order_place: 0)
champ_text.type_de_champ.update(order_place: 1)
context 'when updating using nested attributes' do
subject do
dossier.update!(champs_attributes: [
{
id: champ.id,
champs_attributes: [champ_text_attrs]
}
])
champ.reload
dossier.reload
end
champ.champs << champ_integer_number
row = champ.reload.rows.first
expect(row.size).to eq(1)
expect(row.first).to eq(champ_integer_number)
it 'associates nested champs to the parent dossier' do
subject
champ.champs << champ_text
row = champ.reload.rows.first
expect(row.size).to eq(2)
expect(row.second).to eq(champ_text)
expect(dossier.champs.size).to eq(2)
expect(champ.rows.size).to eq(2)
second_row = champ.rows.second
expect(second_row.size).to eq(1)
expect(second_row.first.dossier).to eq(dossier)
expect(champ.rows.size).to eq(2)
# Make champs ordered
champ_integer.type_de_champ.update(order_place: 0)
champ_text.type_de_champ.update(order_place: 1)
expect(champ_text_row_1.dossier_id).to eq(champ.dossier_id)
champ.champs << champ_integer
first_row = champ.reload.rows.first
expect(first_row.size).to eq(2)
expect(first_row.first).to eq(champ_integer)
champ.champs << champ_text
first_row = champ.reload.rows.first
expect(first_row.size).to eq(2)
expect(first_row.second).to eq(champ_text)
expect(champ.rows.size).to eq(2)
end
end
end
end

View file

@ -563,7 +563,7 @@ describe Dossier do
# - with a dash in the champ libelle / tag
let(:title) { "voici --specified champ-in-title-- un --unspecified champ-in-title-- beau --specified annotation privée-in-title-- titre --unspecified annotation privée-in-title-- non --numéro du dossier--" }
let(:body) { "voici --specified champ-in-body-- un --unspecified champ-in-body-- beau --specified annotation privée-in-body-- body --unspecified annotation privée-in-body-- non ?" }
let(:attestation_template) { create(:attestation_template, title: title, body: body, activated: activated) }
let(:attestation_template) { build(:attestation_template, title: title, body: body, activated: activated) }
context "which is disabled" do
let(:activated) { false }

View file

@ -1,24 +1,24 @@
RSpec.describe GeoArea, type: :model do
describe '#area' do
let(:geo_area) { create(:geo_area, :polygon) }
let(:geo_area) { build(:geo_area, :polygon) }
it { expect(geo_area.area).to eq(219.0) }
end
describe '#length' do
let(:geo_area) { create(:geo_area, :line_string) }
let(:geo_area) { build(:geo_area, :line_string) }
it { expect(geo_area.length).to eq(30.8) }
end
describe '#location' do
let(:geo_area) { create(:geo_area, :point) }
let(:geo_area) { build(:geo_area, :point) }
it { expect(geo_area.location).to eq("2°25'42\"N 46°32'19\"E") }
end
describe '#rgeo_geometry' do
let(:geo_area) { create(:geo_area, geometry: geometry) }
let(:geo_area) { build(:geo_area, geometry: geometry) }
context 'invalid' do
let(:geometry) do

View file

@ -2,7 +2,7 @@ describe Individual do
it { is_expected.to have_db_column(:gender) }
it { is_expected.to have_db_column(:nom) }
it { is_expected.to have_db_column(:prenom) }
it { is_expected.to belong_to(:dossier) }
it { is_expected.to belong_to(:dossier).required }
describe "#save" do
let(:individual) { build(:individual) }

View file

@ -389,7 +389,7 @@ describe Instructeur, type: :model do
let(:procedure_to_assign) { create(:procedure) }
before do
create(:assign_to, instructeur: instructeur, procedure: procedure_to_assign, daily_email_notifications_enabled: true, groupe_instructeur: procedure_to_assign.defaut_groupe_instructeur)
create(:assign_to, instructeur: instructeur, procedure: procedure_to_assign, daily_email_notifications_enabled: true)
end
context 'when a dossier in construction exists' do

View file

@ -1,18 +1,18 @@
describe ProcedurePresentation do
let(:procedure) { create(:procedure, :with_type_de_champ, :with_type_de_champ_private) }
let(:assign_to) { create(:assign_to, procedure: procedure) }
let(:instructeur) { create(:instructeur) }
let(:assign_to) { create(:assign_to, procedure: procedure, instructeur: instructeur) }
let(:first_type_de_champ) { assign_to.procedure.types_de_champ.first }
let(:first_type_de_champ_id) { first_type_de_champ.id.to_s }
let(:procedure_presentation) {
ProcedurePresentation.create(
create(:procedure_presentation,
assign_to: assign_to,
displayed_fields: [
{ "label" => "test1", "table" => "user", "column" => "email" },
{ "label" => "test2", "table" => "type_de_champ", "column" => first_type_de_champ_id }
],
sort: { "table" => "user", "column" => "email", "order" => "asc" },
filters: filters
)
filters: filters)
}
let(:procedure_presentation_id) { procedure_presentation.id }
let(:filters) { { "a-suivre" => [], "suivis" => [{ "label" => "label1", "table" => "self", "column" => "created_at" }] } }
@ -86,7 +86,7 @@ describe ProcedurePresentation do
procedure.types_de_champ_private[3].update_attribute(:type_champ, TypeDeChamp.type_champs.fetch(:explication))
end
subject { create(:procedure_presentation, assign_to: create(:assign_to, procedure: procedure)) }
subject { create(:procedure_presentation, assign_to: assign_to) }
it { expect(subject.fields).to eq(expected) }
end
@ -96,7 +96,7 @@ describe ProcedurePresentation do
let(:surname_field) { { "label" => "Nom", "table" => "individual", "column" => "nom" } }
let(:gender_field) { { "label" => "Civilité", "table" => "individual", "column" => "gender" } }
let(:procedure) { create(:procedure, :for_individual) }
let(:procedure_presentation) { create(:procedure_presentation, assign_to: create(:assign_to, procedure: procedure)) }
let(:procedure_presentation) { create(:procedure_presentation, assign_to: assign_to) }
subject { procedure_presentation.fields }
@ -105,7 +105,7 @@ describe ProcedurePresentation do
end
describe "#fields_for_select" do
subject { create(:procedure_presentation) }
subject { create(:procedure_presentation, assign_to: assign_to) }
before do
allow(subject).to receive(:fields).and_return([
@ -126,7 +126,7 @@ describe ProcedurePresentation do
end
describe '#get_value' do
let(:procedure_presentation) { ProcedurePresentation.create(assign_to: assign_to, displayed_fields: [{ 'table' => table, 'column' => column }]) }
let(:procedure_presentation) { create(:procedure_presentation, procedure: procedure, assign_to: assign_to, displayed_fields: [{ 'table' => table, 'column' => column }]) }
subject { procedure_presentation.displayed_field_values(dossier).first }
@ -168,6 +168,7 @@ describe ProcedurePresentation do
context 'for individual table' do
let(:table) { 'individual' }
let(:procedure) { create(:procedure, :for_individual, :with_type_de_champ, :with_type_de_champ_private) }
let(:dossier) { create(:dossier, procedure: procedure, individual: create(:individual, nom: 'Martin', prenom: 'Jacques', gender: 'M.')) }
context 'for prenom column' do
@ -248,7 +249,7 @@ describe ProcedurePresentation do
let(:instructeur) { create(:instructeur) }
let(:assign_to) { create(:assign_to, procedure: procedure, instructeur: instructeur) }
let(:sort) { { 'table' => table, 'column' => column, 'order' => order } }
let(:procedure_presentation) { ProcedurePresentation.create(assign_to: assign_to, sort: sort) }
let(:procedure_presentation) { create(:procedure_presentation, assign_to: assign_to, sort: sort) }
subject { procedure_presentation.sorted_ids(procedure.dossiers, instructeur) }
@ -416,7 +417,7 @@ describe ProcedurePresentation do
end
describe '#filtered_ids' do
let(:procedure_presentation) { create(:procedure_presentation, assign_to: create(:assign_to, procedure: procedure), filters: { "suivis" => filter }) }
let(:procedure_presentation) { create(:procedure_presentation, assign_to: assign_to, filters: { "suivis" => filter }) }
subject { procedure_presentation.filtered_ids(procedure.dossiers.joins(:user), 'suivis') }
@ -755,13 +756,13 @@ describe ProcedurePresentation do
end
describe '#eager_load_displayed_fields' do
let(:procedure_presentation) { ProcedurePresentation.create(assign_to: assign_to, displayed_fields: [{ 'table' => table, 'column' => column }]) }
let(:procedure_presentation) { create(:procedure_presentation, procedure: procedure, assign_to: assign_to, displayed_fields: [{ 'table' => table, 'column' => column }]) }
let!(:dossier) { create(:dossier, :en_construction, procedure: procedure) }
let(:displayed_dossier) { procedure_presentation.eager_load_displayed_fields(procedure.dossiers).first }
context 'for type de champ' do
let(:table) { 'type_de_champ' }
let(:column) { procedure.types_de_champ.first.id }
let(:column) { procedure.types_de_champ.first.id.to_s }
it 'preloads the champs relation' do
# Ideally, we would only preload the champs for the matching column
@ -778,7 +779,7 @@ describe ProcedurePresentation do
context 'for type de champ private' do
let(:table) { 'type_de_champ_private' }
let(:column) { procedure.types_de_champ_private.first.id }
let(:column) { procedure.types_de_champ_private.first.id.to_s }
it 'preloads the champs relation' do
# Ideally, we would only preload the champs for the matching column
@ -809,6 +810,7 @@ describe ProcedurePresentation do
end
context 'for individual' do
let(:procedure) { create(:procedure, :for_individual, :with_type_de_champ, :with_type_de_champ_private) }
let(:table) { 'individual' }
let(:column) { 'nom' }
@ -855,9 +857,9 @@ describe ProcedurePresentation do
context 'for groupe_instructeur' do
let(:table) { 'groupe_instructeur' }
let(:column) { 'email' }
let(:column) { 'label' }
it 'preloads the followers_instructeurs relation' do
it 'preloads the groupe_instructeur relation' do
expect(displayed_dossier.association(:champs)).not_to be_loaded
expect(displayed_dossier.association(:champs_private)).not_to be_loaded
expect(displayed_dossier.association(:user)).not_to be_loaded

View file

@ -82,7 +82,7 @@ describe Procedure do
context 'with a custom mail template' do
context 'that contains a lien attestation tag' do
let(:closed_mail) { create(:closed_mail, body: '--lien attestation--') }
let(:closed_mail) { build(:closed_mail, body: '--lien attestation--') }
context 'when the procedure doesnt have an attestation' do
let(:procedure) { procedure_without_attestation }
@ -104,7 +104,7 @@ describe Procedure do
end
context 'that doesnt contain a lien attestation tag' do
let(:closed_mail) { create(:closed_mail) }
let(:closed_mail) { build(:closed_mail) }
context 'when the procedure doesnt have an attestation' do
let(:procedure) { procedure_without_attestation }
@ -342,7 +342,7 @@ describe Procedure do
let!(:type_de_champ_private_0) { create(:type_de_champ, :private, procedure: procedure, order_place: 0) }
let!(:type_de_champ_private_1) { create(:type_de_champ, :private, procedure: procedure, order_place: 1) }
let!(:type_de_champ_private_2) { create(:type_de_champ_drop_down_list, :private, procedure: procedure, order_place: 2) }
let(:received_mail) { create(:received_mail) }
let(:received_mail) { build(:received_mail) }
let(:from_library) { false }
let(:administrateur) { procedure.administrateurs.first }

View file

@ -1,6 +1,6 @@
RSpec.describe TrustedDeviceToken, type: :model do
describe '#token_valid?' do
let(:token) { TrustedDeviceToken.create }
let(:token) { create(:trusted_device_token) }
context 'when the token is create after login_token_validity' do
it { expect(token.token_valid?).to be true }
@ -14,7 +14,7 @@ RSpec.describe TrustedDeviceToken, type: :model do
end
describe '#token_young?' do
let(:token) { TrustedDeviceToken.create }
let(:token) { create(:trusted_device_token) }
context 'when the token is create after login_token_youth' do
it { expect(token.token_young?).to be true }

View file

@ -156,14 +156,14 @@ shared_examples 'type_de_champ_spec' do
describe "repetition" do
let(:procedure) { create(:procedure) }
let(:type_de_champ) { create(:type_de_champ_repetition, procedure: procedure) }
let(:type_de_champ_text) { create(:type_de_champ_text) }
let(:type_de_champ_text) { create(:type_de_champ_text, procedure: procedure) }
let(:type_de_champ_integer_number_attrs) { attributes_for(:type_de_champ_integer_number) }
it "associates nested types_de_champ to the parent procedure" do
expect(type_de_champ.types_de_champ.size).to eq(0)
expect(procedure.types_de_champ.size).to eq(1)
procedure.update(types_de_champ_attributes: [
procedure.update!(types_de_champ_attributes: [
{
id: type_de_champ.id,
libelle: type_de_champ.libelle,

View file

@ -21,11 +21,11 @@ describe DossierSerializer do
let(:dossier) { create(:dossier, :en_construction, procedure: create(:procedure, :published, :with_type_de_champ)) }
before do
dossier.champs << create(:champ_carte)
dossier.champs << create(:champ_siret)
dossier.champs << create(:champ_integer_number)
dossier.champs << create(:champ_decimal_number)
dossier.champs << create(:champ_linked_drop_down_list)
dossier.champs << build(:champ_carte)
dossier.champs << build(:champ_siret)
dossier.champs << build(:champ_integer_number)
dossier.champs << build(:champ_decimal_number)
dossier.champs << build(:champ_linked_drop_down_list)
end
it {

View file

@ -13,11 +13,11 @@ describe 'shared/dossiers/champs.html.haml', type: :view do
context "there are some champs" do
let(:dossier) { create(:dossier) }
let(:avis) { create :avis, dossier: dossier, instructeur: instructeur }
let(:champ1) { create(:champ, :checkbox, value: "on") }
let(:champ2) { create(:champ, :header_section, value: "Section") }
let(:champ3) { create(:champ, :explication, value: "mazette") }
let(:champ4) { create(:champ, :dossier_link, value: dossier.id) }
let(:champ5) { create(:champ_textarea, value: "Some long text in a textarea.") }
let(:champ1) { create(:champ_checkbox, dossier: dossier, value: "on") }
let(:champ2) { create(:champ_header_section, dossier: dossier, value: "Section") }
let(:champ3) { create(:champ_explication, dossier: dossier, value: "mazette") }
let(:champ4) { create(:champ_dossier_link, dossier: dossier, value: dossier.id) }
let(:champ5) { create(:champ_textarea, dossier: dossier, value: "Some long text in a textarea.") }
let(:champs) { [champ1, champ2, champ3, champ4, champ5] }
before { dossier.avis << avis }
@ -71,7 +71,7 @@ describe 'shared/dossiers/champs.html.haml', type: :view do
context "with seen_at" do
let(:dossier) { create(:dossier) }
let(:nouveau_groupe_instructeur) { create(:groupe_instructeur, procedure: dossier.procedure) }
let(:champ1) { create(:champ, :checkbox, value: "on") }
let(:champ1) { create(:champ_checkbox, dossier: dossier, value: "on") }
let(:champs) { [champ1] }
context "with a demande_seen_at after groupe_instructeur_updated_at" do
@ -96,7 +96,7 @@ describe 'shared/dossiers/champs.html.haml', type: :view do
context "with a dossier champ, but we are not authorized to acces the dossier" do
let(:dossier) { create(:dossier) }
let(:champ) { create(:champ, :dossier_link, value: dossier.id) }
let(:champ) { create(:champ_dossier_link, dossier: dossier, value: dossier.id) }
let(:champs) { [champ] }
it { is_expected.not_to have_link("Dossier nº #{dossier.id}") }
@ -106,7 +106,7 @@ describe 'shared/dossiers/champs.html.haml', type: :view do
context "with a dossier_link champ but without value" do
let(:dossier) { create(:dossier) }
let(:champ) { create(:champ, :dossier_link, value: nil) }
let(:champ) { create(:champ_dossier_link, dossier: dossier, value: nil) }
let(:champs) { [champ] }
it { is_expected.to include("Pas de dossier associé") }
@ -114,7 +114,7 @@ describe 'shared/dossiers/champs.html.haml', type: :view do
context "with seen_at" do
let(:dossier) { create(:dossier) }
let(:champ1) { create(:champ, :checkbox, value: "on") }
let(:champ1) { create(:champ_checkbox, dossier: dossier, value: "on") }
let(:champs) { [champ1] }
context "with a demande_seen_at after champ updated_at" do