4288 - Gérer les groupes d'instructeurs (#4317)

Gestion des groupes d'instructeurs
This commit is contained in:
Pierre de La Morinerie 2019-10-24 10:46:37 +02:00 committed by GitHub
commit a1088599d1
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
22 changed files with 667 additions and 21 deletions

View file

@ -74,8 +74,8 @@ GEM
i18n (>= 0.7, < 2)
minitest (~> 5.1)
tzinfo (~> 1.1)
addressable (2.5.2)
public_suffix (>= 2.0.2, < 4.0)
addressable (2.7.0)
public_suffix (>= 2.0.2, < 5.0)
administrate (0.11.0)
actionpack (>= 4.2, < 6.0)
actionview (>= 4.2, < 6.0)
@ -119,18 +119,18 @@ GEM
browser (2.5.3)
builder (3.2.3)
byebug (10.0.2)
capybara (3.12.0)
capybara (3.29.0)
addressable
mini_mime (>= 0.1.3)
nokogiri (~> 1.8)
rack (>= 1.6.0)
rack-test (>= 0.6.3)
regexp_parser (~> 1.2)
regexp_parser (~> 1.5)
xpath (~> 3.2)
capybara-email (3.0.1)
capybara (>= 2.4, < 4.0)
mail
capybara-screenshot (1.0.22)
capybara-screenshot (1.0.23)
capybara (>= 1.0, < 4)
launchy
capybara-selenium (0.0.6)
@ -373,7 +373,7 @@ GEM
mime-types-data (~> 3.2015)
mime-types-data (3.2018.0812)
mimemagic (0.3.3)
mini_mime (1.0.1)
mini_mime (1.0.2)
mini_portile2 (2.4.0)
minitest (5.11.3)
momentjs-rails (2.20.1)
@ -448,7 +448,7 @@ GEM
pry-byebug (3.6.0)
byebug (~> 10.0)
pry (~> 0.10)
public_suffix (3.0.3)
public_suffix (4.0.1)
puma (3.12.0)
pundit (2.0.1)
activesupport (>= 3.0.0)
@ -512,7 +512,7 @@ GEM
execjs
railties (>= 3.2)
tilt
regexp_parser (1.3.0)
regexp_parser (1.6.0)
request_store (1.4.1)
rack (>= 1.4)
responders (3.0.0)

View file

@ -0,0 +1,6 @@
.groupe-instructeur {
.actions {
width: 200px;
text-align: center;
}
}

View file

@ -1,4 +1,5 @@
@import "colors";
@import "constants";
.pull-left {
float: left;
@ -48,3 +49,7 @@
background: $orange-bg;
color: $black;
}
.mt-2 {
margin-top: 2 * $default-spacer;
}

View file

@ -264,7 +264,7 @@ module Instructeurs
end
def ensure_ownership!
if !procedure.defaut_groupe_instructeur.instructeurs.include?(current_instructeur)
if !current_instructeur.procedures.include?(procedure)
flash[:alert] = "Vous n'avez pas accès à cette démarche"
redirect_to root_path
end

View file

@ -0,0 +1,145 @@
module NewAdministrateur
class GroupeInstructeursController < AdministrateurController
ITEMS_PER_PAGE = 25
def index
@procedure = procedure
@groupes_instructeurs = paginated_groupe_instructeurs
end
def show
@procedure = procedure
@groupe_instructeur = groupe_instructeur
@instructeurs = paginated_instructeurs
end
def create
@groupe_instructeur = procedure
.groupe_instructeurs
.new(label: label, instructeurs: [current_administrateur.instructeur])
if @groupe_instructeur.save
redirect_to procedure_groupe_instructeur_path(procedure, @groupe_instructeur),
notice: "Le groupe dinstructeurs « #{label} » a été créé."
else
@procedure = procedure
@groupes_instructeurs = paginated_groupe_instructeurs
flash[:alert] = "le nom « #{label} » est déjà pris par un autre groupe."
render :index
end
end
def update
@groupe_instructeur = groupe_instructeur
if @groupe_instructeur.update(label: label)
redirect_to procedure_groupe_instructeur_path(procedure, groupe_instructeur),
notice: "Le nom est à présent « #{label} »."
else
@procedure = procedure
@instructeurs = paginated_instructeurs
flash[:alert] = "le nom « #{label} » est déjà pris par un autre groupe."
render :show
end
end
def add_instructeur
@instructeur = Instructeur.find_by(email: instructeur_email) ||
create_instructeur(instructeur_email)
if groupe_instructeur.instructeurs.include?(@instructeur)
flash[:alert] = "Linstructeur « #{instructeur_email} » est déjà dans le groupe."
else
groupe_instructeur.instructeurs << @instructeur
flash[:notice] = "Linstructeur « #{instructeur_email} » a été affecté au groupe."
GroupeInstructeurMailer
.add_instructeur(groupe_instructeur, @instructeur, current_user.email)
.deliver_later
end
redirect_to procedure_groupe_instructeur_path(procedure, groupe_instructeur)
end
def remove_instructeur
if groupe_instructeur.instructeurs.one?
flash[:alert] = "Suppression impossible : il doit y avoir au moins un instructeur dans le groupe"
else
@instructeur = Instructeur.find(instructeur_id)
groupe_instructeur.instructeurs.destroy(@instructeur)
flash[:notice] = "Linstructeur « #{@instructeur.email} » a été retiré du groupe."
GroupeInstructeurMailer
.remove_instructeur(groupe_instructeur, @instructeur, current_user.email)
.deliver_later
end
redirect_to procedure_groupe_instructeur_path(procedure, groupe_instructeur)
end
def update_routing_criteria_name
procedure.update!(routing_criteria_name: routing_criteria_name)
redirect_to procedure_groupe_instructeurs_path(procedure),
notice: "Le libellé est maintenant « #{procedure.routing_criteria_name} »."
end
private
def create_instructeur(email)
user = User.create_or_promote_to_instructeur(
email,
SecureRandom.hex,
administrateurs: [current_administrateur]
)
user.invite!
user.instructeur
end
def procedure
current_administrateur
.procedures
.includes(:groupe_instructeurs)
.find(params[:procedure_id])
end
def groupe_instructeur
procedure.groupe_instructeurs.find(params[:id])
end
def instructeur_email
params[:instructeur][:email].strip.downcase
end
def instructeur_id
params[:instructeur][:id]
end
def label
params[:groupe_instructeur][:label]
end
def paginated_groupe_instructeurs
procedure
.groupe_instructeurs
.page(params[:page])
.per(ITEMS_PER_PAGE)
.order(:label)
end
def paginated_instructeurs
groupe_instructeur
.instructeurs
.page(params[:page])
.per(ITEMS_PER_PAGE)
.order(:email)
end
def routing_criteria_name
params[:procedure][:routing_criteria_name]
end
end
end

View file

@ -1,7 +1,7 @@
module DossierLinkHelper
def dossier_linked_path(user, dossier)
if user.is_a?(Instructeur)
if dossier.procedure.defaut_groupe_instructeur.instructeurs.include?(user)
if user.groupe_instructeurs.include?(dossier.groupe_instructeur)
instructeur_dossier_path(dossier.procedure, dossier)
else
avis = dossier.avis.find_by(instructeur: user)

View file

@ -0,0 +1,25 @@
class GroupeInstructeurMailer < ApplicationMailer
layout 'mailers/layout'
def add_instructeur(group, instructeur, current_instructeur_email)
@email = instructeur.email
@group = group
@current_instructeur_email = current_instructeur_email
subject = "Ajout dun instructeur dans le groupe \"#{group.label}\""
emails = @group.instructeurs.pluck(:email)
mail(bcc: emails, subject: subject)
end
def remove_instructeur(group, instructeur, current_instructeur_email)
@email = instructeur.email
@group = group
@current_instructeur_email = current_instructeur_email
subject = "Suppression dun instructeur dans le groupe \"#{group.label}\""
emails = @group.instructeurs.pluck(:email)
mail(bcc: emails, subject: subject)
end
end

View file

@ -4,4 +4,9 @@ class GroupeInstructeur < ApplicationRecord
has_many :assign_tos
has_many :instructeurs, through: :assign_tos, dependent: :destroy
has_many :dossiers
validates :label, presence: { message: 'doit être renseigné' }, allow_nil: false
validates :label, uniqueness: { scope: :procedure, message: 'existe déjà' }
before_validation -> { label&.strip! }
end

View file

@ -0,0 +1,11 @@
%p
Bonjour,
%p
Linstructeur « #{@email} » a été affecté au groupe « #{@group.label} » par « #{@current_instructeur_email} », en charge de la démarche « #{@group.procedure.libelle} ».
%p
Cliquez sur le lien ci-dessous pour voir la liste des instructeurs de ce groupe :
= link_to(@group.label, procedure_groupe_instructeur_url(@group.procedure, @group))
= render partial: "layouts/mailers/signature"

View file

@ -0,0 +1,11 @@
%p
Bonjour,
%p
Linstructeur « #{@email} » a été retiré du groupe « #{@group.label} » par « #{@current_instructeur_email} », en charge de la démarche « #{@group.procedure.libelle} ».
%p
Cliquez sur le lien ci-dessous pour voir la liste des instructeurs de ce groupe :
= link_to(@group.label, procedure_groupe_instructeur_url(@group.procedure, @group))
= render partial: "layouts/mailers/signature"

View file

@ -3,7 +3,7 @@
.container
.page-title
Résultat de la recherche :
= pluralize(@dossiers.count, "dossier trouvé", "dossiers trouvés")
= t('pluralize.dossier_trouve', count: @dossiers.count)
- if @dossiers.present?
%table.table.dossiers-table.hoverable

View file

@ -27,14 +27,20 @@
%p.missing-steps (à compléter)
%a#onglet-administrateurs{ href: url_for(procedure_administrateurs_path(@procedure)) }
.procedure-list-element{ class: ('active' if active == 'Administrateurs') }
.procedure-list-element
Administrateurs
%a#onglet-instructeurs{ href: url_for(admin_procedure_assigns_path(@procedure)) }
.procedure-list-element{ class: ('active' if active == 'Instructeurs') }
Instructeurs
- if @procedure.missing_steps.include?(:instructeurs)
%p.missing-steps (à compléter)
- if !feature_enabled?(:routage)
%a#onglet-instructeurs{ href: url_for(admin_procedure_assigns_path(@procedure)) }
.procedure-list-element{ class: ('active' if active == 'Instructeurs') }
Instructeurs
- if @procedure.missing_steps.include?(:instructeurs)
%p.missing-steps (à compléter)
- if feature_enabled?(:routage)
%a#onglet-instructeurs{ href: url_for(procedure_groupe_instructeurs_path(@procedure)) }
.procedure-list-element
Groupe d'instructeurs
- if !@procedure.locked?
%a#onglet-champs{ href: champs_procedure_path(@procedure) }

View file

@ -0,0 +1,38 @@
= render partial: 'new_administrateur/breadcrumbs',
locals: { steps: [link_to('Démarches', admin_procedures_path),
link_to(@procedure.libelle, admin_procedure_path(@procedure)),
'Groupes dinstructeurs'] }
.container.groupe-instructeur
.card
= form_for @procedure,
url: { action: :update_routing_criteria_name },
html: { class: 'form' } do |f|
= f.label :routing_criteria_name do
Libellé du routage
%span.notice Ce texte apparaitra sur le formulaire usager comme le libellé d'une liste
= f.text_field :routing_criteria_name, placeholder: 'Votre ville', required: true
= f.submit 'Renommer', class: 'button primary send'
.card
.card-title Gestion des Groupes
= form_for :groupe_instructeur, html: { class: 'form' } do |f|
= f.label :label do
Ajouter un groupe
%span.notice Ce groupe sera un choix de la liste « #{@procedure.routing_criteria_name} » .
= f.text_field :label, placeholder: 'Ville de Bordeaux', required: true
= f.submit 'Ajouter le groupe', class: 'button primary send'
%table.table.mt-2
%thead
%tr
%th{ colspan: 2 } Liste des groupes
%tbody
- @groupes_instructeurs.each do |group|
%tr
%td= group.label
%td.actions= link_to "voir", procedure_groupe_instructeur_path(@procedure, group)
= paginate @groupes_instructeurs

View file

@ -0,0 +1,47 @@
= render partial: 'new_administrateur/breadcrumbs',
locals: { steps: [link_to('Démarches', admin_procedures_path),
link_to(@procedure.libelle, admin_procedure_path(@procedure)),
link_to('Groupes dinstructeurs', procedure_groupe_instructeurs_path(@procedure)),
@groupe_instructeur.label] }
.container.groupe-instructeur
.rename_form_block
.flex.baseline-start
%h1 Groupe « #{@groupe_instructeur.label} »
.card.mt-2
= form_for @groupe_instructeur,
url: procedure_groupe_instructeur_path(@procedure, @groupe_instructeur),
html: { class: 'form' } do |f|
= f.label :label, 'Nom du groupe'
= f.text_field :label, placeholder: 'Ville de Bordeaux', required: true
= f.submit 'Renommer', class: 'button primary send'
.card
.card-title Gestion des instructeurs
= form_for :instructeur,
url: { action: :add_instructeur },
html: { class: 'form' } do |f|
= f.label :email do
Affecter un nouvel instructeur
= f.email_field :email, placeholder: 'marie.dupont@exemple.fr', required: true
= f.submit 'Affecter', class: 'button primary send'
%table.table.mt-2
%thead
%tr
%th{ colspan: 2 } Instructeurs affectés
%tbody
- @instructeurs.each do |instructeur|
%tr
%td= instructeur.email
%td.actions= button_to 'retirer',
{ action: :remove_instructeur },
{ method: :delete,
data: { confirm: "Êtes-vous sûr de vouloir retirer linstructeur « #{instructeur.email} » du groupe  « #{@groupe_instructeur.label} » ?" },
params: { instructeur: { id: instructeur.id }},
class: 'button' }
= paginate @instructeurs

View file

@ -313,3 +313,7 @@ fr:
zero: archivé
one: archivé
other: archivés
dossier_trouve:
zero: 0 dossier trouvé
one: 1 dossier trouvé
other: "%{count} dossiers trouvés"

View file

@ -350,6 +350,17 @@ Rails.application.routes.draw do
get 'annotations'
end
resources :groupe_instructeurs, only: [:index, :show, :create, :update] do
member do
post 'add_instructeur'
delete 'remove_instructeur'
end
collection do
patch 'update_routing_criteria_name'
end
end
resources :administrateurs, controller: 'procedure_administrateurs', only: [:index, :create, :destroy]
resources :types_de_champ, only: [:create, :update, :destroy] do

View file

@ -0,0 +1,5 @@
class AddDefaultValueToRoutingCriteriaName < ActiveRecord::Migration[5.2]
def change
change_column :procedures, :routing_criteria_name, :text, default: "Votre ville"
end
end

View file

@ -10,7 +10,7 @@
#
# It's strongly recommended that you check this file into your version control system.
ActiveRecord::Schema.define(version: 2019_10_14_160538) do
ActiveRecord::Schema.define(version: 2019_10_23_183120) do
# These are extensions that must be enabled in order to support this database
enable_extension "plpgsql"
@ -486,7 +486,7 @@ ActiveRecord::Schema.define(version: 2019_10_14_160538) do
t.string "path", null: false
t.string "declarative_with_state"
t.text "monavis_embed"
t.text "routing_criteria_name"
t.text "routing_criteria_name", default: "Votre ville"
t.boolean "csv_export_queued"
t.boolean "xlsx_export_queued"
t.boolean "ods_export_queued"

View file

@ -0,0 +1,162 @@
describe NewAdministrateur::GroupeInstructeursController, type: :controller do
render_views
let(:admin) { create(:administrateur) }
let(:procedure) { create(:procedure, :published, administrateurs: [admin]) }
let!(:gi_1_1) { procedure.defaut_groupe_instructeur }
let(:procedure2) { create(:procedure, :published) }
let!(:gi_2_2) { procedure2.groupe_instructeurs.create(label: 'groupe instructeur 2 2') }
before { sign_in(admin.user) }
describe '#index' do
context 'of a procedure I own' do
let!(:gi_1_2) { procedure.groupe_instructeurs.create(label: 'groupe instructeur 2') }
before { get :index, params: { procedure_id: procedure.id } }
context 'when a procedure has multiple groups' do
it { expect(response).to have_http_status(:ok) }
it { expect(response.body).to include(gi_1_1.label) }
it { expect(response.body).to include(gi_1_2.label) }
it { expect(response.body).not_to include(gi_2_2.label) }
end
end
end
describe '#show' do
context 'of a group I belong to' do
before { get :show, params: { procedure_id: procedure.id, id: gi_1_1.id } }
it { expect(response).to have_http_status(:ok) }
end
end
describe '#create' do
before do
post :create,
params: {
procedure_id: procedure.id,
groupe_instructeur: { label: label }
}
end
context 'with a valid name' do
let(:label) { "nouveau_groupe" }
it { expect(flash.notice).to be_present }
it { expect(response).to redirect_to(procedure_groupe_instructeur_path(procedure, procedure.groupe_instructeurs.last)) }
it { expect(procedure.groupe_instructeurs.count).to eq(2) }
end
context 'with an invalid group name' do
let(:label) { gi_1_1.label }
it { expect(response).to render_template(:index) }
it { expect(procedure.groupe_instructeurs.count).to eq(1) }
it { expect(flash.alert).to be_present }
end
end
describe '#update' do
let(:new_name) { 'nouveau nom du groupe' }
before do
patch :update,
params: {
procedure_id: procedure.id,
id: gi_1_1.id,
groupe_instructeur: { label: new_name }
}
end
it { expect(gi_1_1.reload.label).to eq(new_name) }
it { expect(response).to redirect_to(procedure_groupe_instructeur_path(procedure, gi_1_1)) }
it { expect(flash.notice).to be_present }
context 'when the name is already taken' do
let!(:gi_1_2) { procedure.groupe_instructeurs.create(label: 'groupe instructeur 2') }
let(:new_name) { gi_1_2.label }
it { expect(gi_1_1.reload.label).not_to eq(new_name) }
it { expect(flash.alert).to be_present }
end
end
describe '#add_instructeur' do
let!(:instructeur) { create(:instructeur) }
before do
gi_1_1.instructeurs << instructeur
post :add_instructeur,
params: {
procedure_id: procedure.id,
id: gi_1_1.id,
instructeur: { email: new_instructeur_email }
}
end
context 'of a new instructeur' do
let(:new_instructeur_email) { 'new_instructeur@mail.com' }
it { expect(gi_1_1.instructeurs.pluck(:email)).to include(new_instructeur_email) }
it { expect(flash.notice).to be_present }
it { expect(response).to redirect_to(procedure_groupe_instructeur_path(procedure, gi_1_1)) }
end
context 'of an instructeur already in the group' do
let(:new_instructeur_email) { instructeur.email }
it { expect(flash.alert).to be_present }
it { expect(response).to redirect_to(procedure_groupe_instructeur_path(procedure, procedure.defaut_groupe_instructeur)) }
end
end
describe '#remove_instructeur' do
let!(:instructeur) { create(:instructeur) }
before { gi_1_1.instructeurs << admin.instructeur << instructeur }
def remove_instructeur(email)
delete :remove_instructeur,
params: {
procedure_id: procedure.id,
id: gi_1_1.id,
instructeur: { id: admin.instructeur.id }
}
end
context 'when there are many instructeurs' do
before { remove_instructeur(admin.user.email) }
it { expect(gi_1_1.instructeurs).to include(instructeur) }
it { expect(gi_1_1.reload.instructeurs.count).to eq(1) }
it { expect(response).to redirect_to(procedure_groupe_instructeur_path(procedure, gi_1_1)) }
end
context 'when there is only one instructeur' do
before do
remove_instructeur(admin.user.email)
remove_instructeur(instructeur.email)
end
it { expect(gi_1_1.instructeurs).to include(instructeur) }
it { expect(gi_1_1.instructeurs.count).to eq(1) }
it { expect(flash.alert).to eq('Suppression impossible : il doit y avoir au moins un instructeur dans le groupe') }
it { expect(response).to redirect_to(procedure_groupe_instructeur_path(procedure, gi_1_1)) }
end
end
describe '#update_routing_criteria_name' do
before do
patch :update_routing_criteria_name,
params: {
procedure_id: procedure.id,
procedure: { routing_criteria_name: 'new name !' }
}
end
it { expect(procedure.reload.routing_criteria_name).to eq('new name !') }
end
end

View file

@ -0,0 +1,126 @@
require 'spec_helper'
feature 'The routing' do
let(:procedure) { create(:procedure, :with_service, :for_individual) }
let(:administrateur) { create(:administrateur, procedures: [procedure]) }
let(:scientifique_user) { create(:user) }
let(:litteraire_user) { create(:user) }
before { Flipper.enable_actor(:routage, administrateur.user) }
scenario 'works' do
login_as administrateur.user, scope: :user
visit admin_procedure_path(procedure.id)
click_on "Groupe d'instructeurs"
# rename routing criteria to spécialité
fill_in 'procedure_routing_criteria_name', with: 'spécialité'
click_on 'Renommer'
expect(procedure.reload.routing_criteria_name).to eq('spécialité')
# rename defaut groupe to littéraire
click_on 'voir'
fill_in 'groupe_instructeur_label', with: 'littéraire'
click_on 'Renommer'
# add victor to littéraire groupe
fill_in 'instructeur_email', with: 'victor@inst.com'
perform_enqueued_jobs { click_on 'Affecter' }
victor = User.find_by(email: 'victor@inst.com').instructeur
click_on "Groupes dinstructeurs"
# add scientifique groupe
fill_in 'groupe_instructeur_label', with: 'scientifique'
click_on 'Ajouter le groupe'
# add marie to scientifique groupe
fill_in 'instructeur_email', with: 'marie@inst.com'
perform_enqueued_jobs { click_on 'Affecter' }
marie = User.find_by(email: 'marie@inst.com').instructeur
# publish
publish_procedure(procedure)
log_out
# 2 users fill a dossier in each group
user_send_dossier(scientifique_user, 'scientifique')
user_send_dossier(litteraire_user, 'littéraire')
# the litteraires instructeurs only manage the litteraires dossiers
register_instructeur_and_log_in(victor.email)
click_on procedure.libelle
expect(page).to have_text(litteraire_user.email)
expect(page).not_to have_text(scientifique_user.email)
# the search only show litteraires dossiers
fill_in 'q', with: scientifique_user.email
click_on 'Rechercher'
expect(page).to have_text('0 dossier trouvé')
fill_in 'q', with: litteraire_user.email
click_on 'Rechercher'
expect(page).to have_text('1 dossier trouvé')
## and the result is clickable
click_on litteraire_user.email
expect(page).to have_current_path(instructeur_dossier_path(procedure, litteraire_user.dossiers.first))
log_out
# the scientifiques instructeurs only manage the scientifiques dossiers
register_instructeur_and_log_in(marie.email)
click_on procedure.libelle
expect(page).not_to have_text(litteraire_user.email)
expect(page).to have_text(scientifique_user.email)
log_out
# TODO: notifications tests
end
def publish_procedure(procedure)
click_on procedure.libelle
find('#publish-procedure').click
within '#publish-modal' do
fill_in 'lien_site_web', with: 'http://some.website'
click_on 'publish'
end
expect(page).to have_text('Démarche publiée')
end
def user_send_dossier(user, groupe)
login_as user, scope: :user
visit commencer_path(path: procedure.reload.path)
click_on 'Commencer la démarche'
fill_in 'individual_nom', with: 'Nom'
fill_in 'individual_prenom', with: 'Prenom'
click_button('Continuer')
select(groupe, from: 'dossier_groupe_instructeur_id')
click_on 'Déposer le dossier'
log_out
end
def register_instructeur_and_log_in(email)
confirmation_email = emails_sent_to(email)
.filter { |m| m.subject == 'Activez votre compte instructeur' }
.first
token_params = confirmation_email.body.match(/token=[^"]+/)
visit "users/activate?#{token_params}"
fill_in :user_password, with: 'démarches-simplifiées-pwd'
click_button 'Définir le mot de passe'
expect(page).to have_content 'Mot de passe enregistré'
end
def log_out
click_on 'Se déconnecter'
end
end

View file

@ -15,10 +15,11 @@ describe DossierLinkHelper do
end
context "when access as instructeur" do
let(:dossier) { create(:dossier) }
let(:procedure) { create(:procedure, :routee) }
let(:dossier) { create(:dossier, groupe_instructeur: procedure.groupe_instructeurs.last) }
let(:instructeur) { create(:instructeur) }
before { dossier.procedure.defaut_groupe_instructeur.instructeurs << instructeur }
before { procedure.groupe_instructeurs.last.instructeurs << instructeur }
it { expect(helper.dossier_linked_path(instructeur, dossier)).to eq(instructeur_dossier_path(dossier.procedure, dossier)) }
end

View file

@ -0,0 +1,38 @@
require 'spec_helper'
describe GroupeInstructeur, type: :model do
let(:procedure) { create(:procedure) }
subject { GroupeInstructeur.new(label: label, procedure: procedure) }
context 'with no label provided' do
let(:label) { '' }
it { is_expected.to be_invalid }
end
context 'with a valid label' do
let(:label) { 'Préfecture de la Marne' }
it { is_expected.to be_valid }
end
context 'with a label with extra spaces' do
let(:label) { 'Préfecture de la Marne ' }
before do
subject.save
subject.reload
end
it { is_expected.to be_valid }
it { expect(subject.label).to eq("Préfecture de la Marne") }
end
context 'with a label already used for this procedure' do
let(:label) { 'Préfecture de la Marne' }
before do
GroupeInstructeur.create!(label: label, procedure: procedure)
end
it { is_expected.to be_invalid }
end
end