2019-03-25 10:53:45 +01:00
|
|
|
|
describe Users::DossiersController, type: :controller do
|
2023-06-06 10:50:46 +02:00
|
|
|
|
include ActiveSupport::Testing::TimeHelpers
|
|
|
|
|
|
2017-06-29 14:18:12 +02:00
|
|
|
|
let(:user) { create(:user) }
|
|
|
|
|
|
2018-03-29 16:49:01 +02:00
|
|
|
|
describe 'before_actions' do
|
|
|
|
|
it 'are present' do
|
2019-03-25 10:53:45 +01:00
|
|
|
|
before_actions = Users::DossiersController
|
2017-06-29 14:18:12 +02:00
|
|
|
|
._process_action_callbacks
|
2019-09-12 11:26:22 +02:00
|
|
|
|
.filter { |process_action_callbacks| process_action_callbacks.kind == :before }
|
2017-06-29 14:18:12 +02:00
|
|
|
|
.map(&:filter)
|
|
|
|
|
|
2018-03-29 16:49:01 +02:00
|
|
|
|
expect(before_actions).to include(:ensure_ownership!, :ensure_ownership_or_invitation!, :forbid_invite_submission!)
|
2017-06-29 14:18:12 +02:00
|
|
|
|
end
|
|
|
|
|
end
|
|
|
|
|
|
2018-03-29 15:25:05 +02:00
|
|
|
|
shared_examples_for 'does not redirect nor flash' do
|
|
|
|
|
before { @controller.send(ensure_authorized) }
|
|
|
|
|
|
|
|
|
|
it { expect(@controller).not_to have_received(:redirect_to) }
|
|
|
|
|
it { expect(flash.alert).to eq(nil) }
|
|
|
|
|
end
|
|
|
|
|
|
|
|
|
|
shared_examples_for 'redirects and flashes' do
|
|
|
|
|
before { @controller.send(ensure_authorized) }
|
|
|
|
|
|
|
|
|
|
it { expect(@controller).to have_received(:redirect_to).with(root_path) }
|
2023-07-19 11:50:38 +02:00
|
|
|
|
it { expect(flash.alert).to include("Vous n’avez pas accès à ce dossier") }
|
2018-03-29 15:25:05 +02:00
|
|
|
|
end
|
|
|
|
|
|
|
|
|
|
describe '#ensure_ownership!' do
|
2017-06-29 14:18:12 +02:00
|
|
|
|
let(:user) { create(:user) }
|
2018-03-29 15:25:05 +02:00
|
|
|
|
let(:asked_dossier) { create(:dossier) }
|
|
|
|
|
let(:ensure_authorized) { :ensure_ownership! }
|
2017-06-29 14:18:12 +02:00
|
|
|
|
|
|
|
|
|
before do
|
2018-01-23 18:28:09 +01:00
|
|
|
|
@controller.params = @controller.params.merge(dossier_id: asked_dossier.id)
|
2017-06-29 14:18:12 +02:00
|
|
|
|
allow(@controller).to receive(:redirect_to)
|
2018-03-29 15:25:05 +02:00
|
|
|
|
end
|
|
|
|
|
|
|
|
|
|
context 'when a user asks for their own dossier' do
|
2023-07-19 11:50:38 +02:00
|
|
|
|
before do
|
|
|
|
|
expect(@controller).to receive(:current_user).and_return(user)
|
|
|
|
|
end
|
|
|
|
|
|
2018-03-29 15:25:05 +02:00
|
|
|
|
let(:asked_dossier) { create(:dossier, user: user) }
|
|
|
|
|
|
|
|
|
|
it_behaves_like 'does not redirect nor flash'
|
|
|
|
|
end
|
|
|
|
|
|
|
|
|
|
context 'when a user asks for another dossier' do
|
2023-07-19 11:50:38 +02:00
|
|
|
|
before do
|
|
|
|
|
expect(@controller).to receive(:current_user).twice.and_return(user)
|
|
|
|
|
end
|
|
|
|
|
|
2018-03-29 15:25:05 +02:00
|
|
|
|
it_behaves_like 'redirects and flashes'
|
|
|
|
|
end
|
|
|
|
|
|
|
|
|
|
context 'when an invite asks for a dossier where they were invited' do
|
2023-07-19 11:50:38 +02:00
|
|
|
|
before do
|
|
|
|
|
expect(@controller).to receive(:current_user).twice.and_return(user)
|
|
|
|
|
create(:invite, dossier: asked_dossier, user: user)
|
|
|
|
|
end
|
2018-03-29 15:25:05 +02:00
|
|
|
|
|
|
|
|
|
it_behaves_like 'redirects and flashes'
|
|
|
|
|
end
|
2017-06-29 14:18:12 +02:00
|
|
|
|
|
2018-03-29 15:25:05 +02:00
|
|
|
|
context 'when an invite asks for another dossier' do
|
2023-07-19 11:50:38 +02:00
|
|
|
|
before do
|
|
|
|
|
expect(@controller).to receive(:current_user).twice.and_return(user)
|
|
|
|
|
create(:invite, dossier: create(:dossier), user: user)
|
|
|
|
|
end
|
2018-03-29 15:25:05 +02:00
|
|
|
|
|
|
|
|
|
it_behaves_like 'redirects and flashes'
|
2017-06-29 14:18:12 +02:00
|
|
|
|
end
|
2018-03-29 15:25:05 +02:00
|
|
|
|
end
|
2017-06-29 14:18:12 +02:00
|
|
|
|
|
2018-03-29 15:25:05 +02:00
|
|
|
|
describe '#ensure_ownership_or_invitation!' do
|
|
|
|
|
let(:user) { create(:user) }
|
|
|
|
|
let(:asked_dossier) { create(:dossier) }
|
|
|
|
|
let(:ensure_authorized) { :ensure_ownership_or_invitation! }
|
|
|
|
|
|
|
|
|
|
before do
|
|
|
|
|
@controller.params = @controller.params.merge(dossier_id: asked_dossier.id)
|
|
|
|
|
allow(@controller).to receive(:redirect_to)
|
|
|
|
|
end
|
|
|
|
|
|
|
|
|
|
context 'when a user asks for their own dossier' do
|
2023-07-19 11:50:38 +02:00
|
|
|
|
before do
|
|
|
|
|
expect(@controller).to receive(:current_user).and_return(user)
|
|
|
|
|
end
|
|
|
|
|
|
2017-06-29 14:18:12 +02:00
|
|
|
|
let(:asked_dossier) { create(:dossier, user: user) }
|
|
|
|
|
|
2018-03-29 15:25:05 +02:00
|
|
|
|
it_behaves_like 'does not redirect nor flash'
|
2017-06-29 14:18:12 +02:00
|
|
|
|
end
|
|
|
|
|
|
|
|
|
|
context 'when a user asks for another dossier' do
|
2023-07-19 11:50:38 +02:00
|
|
|
|
before do
|
|
|
|
|
expect(@controller).to receive(:current_user).twice.and_return(user)
|
|
|
|
|
end
|
|
|
|
|
|
2018-03-29 15:25:05 +02:00
|
|
|
|
it_behaves_like 'redirects and flashes'
|
|
|
|
|
end
|
2017-06-29 14:18:12 +02:00
|
|
|
|
|
2018-03-29 15:25:05 +02:00
|
|
|
|
context 'when an invite asks for a dossier where they were invited' do
|
2023-07-19 11:50:38 +02:00
|
|
|
|
before do
|
|
|
|
|
expect(@controller).to receive(:current_user).and_return(user)
|
|
|
|
|
create(:invite, dossier: asked_dossier, user: user)
|
|
|
|
|
end
|
2018-03-29 15:25:05 +02:00
|
|
|
|
|
|
|
|
|
it_behaves_like 'does not redirect nor flash'
|
|
|
|
|
end
|
|
|
|
|
|
|
|
|
|
context 'when an invite asks for another dossier' do
|
2023-07-19 11:50:38 +02:00
|
|
|
|
before do
|
|
|
|
|
expect(@controller).to receive(:current_user).twice.and_return(user)
|
|
|
|
|
create(:invite, dossier: create(:dossier), user: user)
|
|
|
|
|
end
|
2018-03-29 15:25:05 +02:00
|
|
|
|
|
2018-07-31 17:25:39 +02:00
|
|
|
|
it_behaves_like 'redirects and flashes'
|
|
|
|
|
end
|
|
|
|
|
end
|
|
|
|
|
|
|
|
|
|
describe "#forbid_invite_submission!" do
|
|
|
|
|
let(:user) { create(:user) }
|
|
|
|
|
let(:asked_dossier) { create(:dossier) }
|
|
|
|
|
let(:ensure_authorized) { :forbid_invite_submission! }
|
|
|
|
|
|
|
|
|
|
before do
|
2022-10-11 12:21:06 +02:00
|
|
|
|
@controller.params = @controller.params.merge(dossier_id: asked_dossier.id)
|
2018-07-31 17:25:39 +02:00
|
|
|
|
allow(@controller).to receive(:current_user).and_return(user)
|
|
|
|
|
allow(@controller).to receive(:redirect_to)
|
|
|
|
|
end
|
|
|
|
|
|
|
|
|
|
context 'when a user submit their own dossier' do
|
|
|
|
|
let(:asked_dossier) { create(:dossier, user: user) }
|
|
|
|
|
|
|
|
|
|
it_behaves_like 'does not redirect nor flash'
|
|
|
|
|
end
|
|
|
|
|
|
|
|
|
|
context 'when an invite submit a dossier where they where invited' do
|
2018-10-10 09:23:08 +02:00
|
|
|
|
before { create(:invite, dossier: asked_dossier, user: user) }
|
2018-07-31 17:25:39 +02:00
|
|
|
|
|
2018-03-29 15:25:05 +02:00
|
|
|
|
it_behaves_like 'redirects and flashes'
|
2017-06-29 14:18:12 +02:00
|
|
|
|
end
|
|
|
|
|
end
|
2017-06-29 14:18:59 +02:00
|
|
|
|
|
|
|
|
|
describe 'attestation' do
|
|
|
|
|
before { sign_in(user) }
|
|
|
|
|
|
|
|
|
|
context 'when a dossier has an attestation' do
|
2019-09-10 11:09:51 +02:00
|
|
|
|
let(:dossier) { create(:dossier, :accepte, attestation: create(:attestation, :with_pdf), user: user) }
|
2017-06-29 14:18:59 +02:00
|
|
|
|
|
2019-09-10 11:09:51 +02:00
|
|
|
|
it 'redirects to attestation pdf' do
|
2018-07-17 11:26:41 +02:00
|
|
|
|
get :attestation, params: { id: dossier.id }
|
2019-12-19 18:29:01 +01:00
|
|
|
|
expect(response.location).to match '/rails/active_storage/disk/'
|
2017-06-29 14:18:59 +02:00
|
|
|
|
end
|
|
|
|
|
end
|
|
|
|
|
end
|
2018-02-08 17:13:15 +01:00
|
|
|
|
|
|
|
|
|
describe 'update_identite' do
|
|
|
|
|
let(:procedure) { create(:procedure, :for_individual) }
|
|
|
|
|
let(:dossier) { create(:dossier, user: user, procedure: procedure) }
|
2021-10-04 10:04:07 +02:00
|
|
|
|
let(:now) { Time.zone.parse('01/01/2100') }
|
2018-02-08 17:13:15 +01:00
|
|
|
|
|
2018-10-02 13:51:56 +02:00
|
|
|
|
subject { post :update_identite, params: { id: dossier.id, individual: individual_params } }
|
2018-02-08 17:13:15 +01:00
|
|
|
|
|
|
|
|
|
before do
|
|
|
|
|
sign_in(user)
|
2021-10-04 10:04:07 +02:00
|
|
|
|
Timecop.freeze(now) do
|
|
|
|
|
subject
|
|
|
|
|
end
|
2018-02-08 17:13:15 +01:00
|
|
|
|
end
|
|
|
|
|
|
|
|
|
|
context 'with correct individual and dossier params' do
|
|
|
|
|
let(:individual_params) { { gender: 'M', nom: 'Mouse', prenom: 'Mickey' } }
|
|
|
|
|
|
|
|
|
|
it do
|
2018-09-06 09:09:23 +02:00
|
|
|
|
expect(response).to redirect_to(brouillon_dossier_path(dossier))
|
2021-10-04 10:04:07 +02:00
|
|
|
|
expect(dossier.reload.identity_updated_at).to eq(now)
|
2018-02-08 17:13:15 +01:00
|
|
|
|
end
|
|
|
|
|
end
|
|
|
|
|
|
2018-06-08 15:51:46 +02:00
|
|
|
|
context 'when the identite cannot be updated by the user' do
|
2020-01-07 17:47:22 +01:00
|
|
|
|
let(:dossier) { create(:dossier, :with_individual, :en_instruction, user: user, procedure: procedure) }
|
2018-06-08 15:51:46 +02:00
|
|
|
|
let(:individual_params) { { gender: 'M', nom: 'Mouse', prenom: 'Mickey' } }
|
|
|
|
|
|
2018-06-27 14:47:02 +02:00
|
|
|
|
it 'redirects to the dossiers list' do
|
2023-04-26 16:54:50 +02:00
|
|
|
|
expect(response).to redirect_to(dossier_path(dossier))
|
2018-06-08 15:51:46 +02:00
|
|
|
|
expect(flash.alert).to eq('Votre dossier ne peut plus être modifié')
|
|
|
|
|
end
|
|
|
|
|
end
|
|
|
|
|
|
2018-02-08 17:13:15 +01:00
|
|
|
|
context 'with incorrect individual and dossier params' do
|
|
|
|
|
let(:individual_params) { { gender: '', nom: '', prenom: '' } }
|
|
|
|
|
|
|
|
|
|
it do
|
|
|
|
|
expect(response).not_to have_http_status(:redirect)
|
2022-12-20 17:51:36 +01:00
|
|
|
|
expect(flash[:alert]).to include("Le champ « Civilité » doit être rempli", "Le champ « Nom » doit être rempli", "Le champ « Prénom » doit être rempli")
|
2018-02-08 17:13:15 +01:00
|
|
|
|
end
|
|
|
|
|
end
|
|
|
|
|
end
|
2018-02-21 18:32:07 +01:00
|
|
|
|
|
2018-10-04 09:43:19 +02:00
|
|
|
|
describe '#siret' do
|
|
|
|
|
before { sign_in(user) }
|
|
|
|
|
let!(:dossier) { create(:dossier, user: user) }
|
|
|
|
|
|
|
|
|
|
subject { get :siret, params: { id: dossier.id } }
|
|
|
|
|
|
|
|
|
|
it { is_expected.to render_template(:siret) }
|
|
|
|
|
end
|
|
|
|
|
|
2018-10-15 18:41:53 +02:00
|
|
|
|
describe '#update_siret' do
|
|
|
|
|
let(:dossier) { create(:dossier, user: user) }
|
|
|
|
|
let(:siret) { params_siret.delete(' ') }
|
|
|
|
|
let(:siren) { siret[0..8] }
|
|
|
|
|
let(:api_etablissement_status) { 200 }
|
2023-04-27 17:17:38 +02:00
|
|
|
|
let(:api_etablissement_body) { Rails.root.join('spec/fixtures/files/api_entreprise/etablissements.json').read }
|
2020-05-05 16:06:18 +02:00
|
|
|
|
let(:token_expired) { false }
|
2022-09-15 18:53:41 +02:00
|
|
|
|
let(:api_current_status_response) { nil }
|
2020-05-05 16:06:18 +02:00
|
|
|
|
|
2018-10-15 18:41:53 +02:00
|
|
|
|
before do
|
|
|
|
|
sign_in(user)
|
2023-05-30 16:27:20 +02:00
|
|
|
|
stub_request(:get, /https:\/\/entreprise.api.gouv.fr\/v3\/insee\/sirene\/etablissements\/#{siret}/)
|
2020-05-18 10:30:08 +02:00
|
|
|
|
.to_return(status: api_etablissement_status, body: api_etablissement_body)
|
2023-05-25 11:15:26 +02:00
|
|
|
|
stub_request(:get, /https:\/\/entreprise.api.gouv.fr\/v3\/insee\/sirene\/unites_legales\/#{siren}/)
|
2023-04-27 17:17:38 +02:00
|
|
|
|
.to_return(body: Rails.root.join('spec/fixtures/files/api_entreprise/status.json').read, status: 200)
|
2020-08-05 18:40:47 +02:00
|
|
|
|
allow_any_instance_of(APIEntrepriseToken).to receive(:roles)
|
2020-04-30 08:43:34 +02:00
|
|
|
|
.and_return(["attestations_fiscales", "attestations_sociales", "bilans_entreprise_bdf"])
|
2020-08-05 18:40:47 +02:00
|
|
|
|
allow_any_instance_of(APIEntrepriseToken).to receive(:expired?).and_return(token_expired)
|
2022-09-15 18:53:41 +02:00
|
|
|
|
|
|
|
|
|
if api_current_status_response
|
2023-04-27 17:17:38 +02:00
|
|
|
|
stub_request(:get, "https://status.entreprise.api.gouv.fr/summary.json")
|
2022-09-15 18:53:41 +02:00
|
|
|
|
.to_return(body: api_current_status_response)
|
|
|
|
|
end
|
2018-10-15 18:41:53 +02:00
|
|
|
|
end
|
|
|
|
|
|
|
|
|
|
subject! { post :update_siret, params: { id: dossier.id, user: { siret: params_siret } } }
|
|
|
|
|
|
|
|
|
|
shared_examples 'SIRET informations are successfully saved' do
|
|
|
|
|
it do
|
|
|
|
|
dossier.reload
|
|
|
|
|
user.reload
|
|
|
|
|
|
|
|
|
|
expect(dossier.etablissement).to be_present
|
|
|
|
|
expect(dossier.autorisation_donnees).to be(true)
|
|
|
|
|
expect(user.siret).to eq(siret)
|
|
|
|
|
|
|
|
|
|
expect(response).to redirect_to(etablissement_dossier_path)
|
|
|
|
|
end
|
|
|
|
|
end
|
|
|
|
|
|
|
|
|
|
shared_examples 'the request fails with an error' do |error|
|
|
|
|
|
it 'doesn’t save an etablissement' do
|
|
|
|
|
expect(dossier.reload.etablissement).to be_nil
|
|
|
|
|
end
|
|
|
|
|
|
|
|
|
|
it 'displays the SIRET that was sent by the user in the form' do
|
|
|
|
|
expect(controller.current_user.siret).to eq(siret)
|
|
|
|
|
end
|
|
|
|
|
|
|
|
|
|
it 'renders an error' do
|
|
|
|
|
expect(flash.alert).to eq(error)
|
|
|
|
|
expect(response).to render_template(:siret)
|
|
|
|
|
end
|
|
|
|
|
end
|
|
|
|
|
|
|
|
|
|
context 'with an invalid SIRET' do
|
|
|
|
|
let(:params_siret) { '000 000' }
|
|
|
|
|
|
2022-12-20 17:51:36 +01:00
|
|
|
|
it_behaves_like 'the request fails with an error', ['Le champ « Siret » est invalide. Saisir un numéro SIRET avec 14 chiffres']
|
2018-10-15 18:41:53 +02:00
|
|
|
|
end
|
|
|
|
|
|
|
|
|
|
context 'with a valid SIRET' do
|
2020-04-07 19:29:14 +02:00
|
|
|
|
let(:params_siret) { '418 166 096 00051' }
|
2022-09-15 18:53:41 +02:00
|
|
|
|
|
|
|
|
|
context 'When API-Entreprise is ponctually down' do
|
2019-05-02 11:24:22 +02:00
|
|
|
|
let(:api_etablissement_status) { 502 }
|
2023-04-27 17:17:38 +02:00
|
|
|
|
let(:api_current_status_response) { Rails.root.join('spec/fixtures/files/api_entreprise/status.json').read }
|
2019-05-02 11:24:22 +02:00
|
|
|
|
|
|
|
|
|
it_behaves_like 'the request fails with an error', I18n.t('errors.messages.siret_network_error')
|
|
|
|
|
end
|
|
|
|
|
|
2022-09-15 18:53:41 +02:00
|
|
|
|
context 'When API-Entreprise is globally down' do
|
|
|
|
|
let(:api_etablissement_status) { 502 }
|
2023-04-27 17:17:38 +02:00
|
|
|
|
let(:api_current_status_response) { Rails.root.join('spec/fixtures/files/api_entreprise/status.json').read.gsub('UP', 'HASISSUES') }
|
2022-09-15 18:53:41 +02:00
|
|
|
|
|
2022-09-16 00:32:17 +02:00
|
|
|
|
it "create an etablissement only with SIRET as degraded mode" do
|
|
|
|
|
dossier.reload
|
|
|
|
|
expect(dossier.etablissement.siret).to eq(siret)
|
|
|
|
|
expect(dossier.etablissement).to be_as_degraded_mode
|
|
|
|
|
end
|
2022-09-15 18:53:41 +02:00
|
|
|
|
end
|
|
|
|
|
|
2018-10-15 18:41:53 +02:00
|
|
|
|
context 'when API-Entreprise doesn’t know this SIRET' do
|
|
|
|
|
let(:api_etablissement_status) { 404 }
|
|
|
|
|
|
|
|
|
|
it_behaves_like 'the request fails with an error', I18n.t('errors.messages.siret_unknown')
|
|
|
|
|
end
|
|
|
|
|
|
2020-05-05 16:06:18 +02:00
|
|
|
|
context 'when default token has expired' do
|
|
|
|
|
let(:api_etablissement_status) { 200 }
|
2023-04-27 17:17:38 +02:00
|
|
|
|
let(:api_current_status_response) { Rails.root.join('spec/fixtures/files/api_entreprise/status.json').read }
|
2020-05-05 16:06:18 +02:00
|
|
|
|
let(:token_expired) { true }
|
|
|
|
|
|
2022-07-12 19:06:20 +02:00
|
|
|
|
it_behaves_like 'the request fails with an error', I18n.t('errors.messages.siret_network_error')
|
2020-05-05 16:06:18 +02:00
|
|
|
|
end
|
|
|
|
|
|
2018-10-15 18:41:53 +02:00
|
|
|
|
context 'when all API informations available' do
|
|
|
|
|
it_behaves_like 'SIRET informations are successfully saved'
|
|
|
|
|
|
|
|
|
|
it 'saves the associated informations on the etablissement' do
|
|
|
|
|
dossier.reload
|
|
|
|
|
expect(dossier.etablissement.entreprise).to be_present
|
|
|
|
|
end
|
|
|
|
|
end
|
|
|
|
|
end
|
|
|
|
|
end
|
|
|
|
|
|
2018-10-15 12:25:25 +02:00
|
|
|
|
describe '#etablissement' do
|
|
|
|
|
let(:dossier) { create(:dossier, :with_entreprise, user: user) }
|
|
|
|
|
|
|
|
|
|
before { sign_in(user) }
|
|
|
|
|
|
|
|
|
|
subject { get :etablissement, params: { id: dossier.id } }
|
|
|
|
|
|
|
|
|
|
it { is_expected.to render_template(:etablissement) }
|
|
|
|
|
|
|
|
|
|
context 'when the dossier has no etablissement yet' do
|
|
|
|
|
let(:dossier) { create(:dossier, user: user) }
|
|
|
|
|
it { is_expected.to redirect_to siret_dossier_path(dossier) }
|
|
|
|
|
end
|
|
|
|
|
end
|
|
|
|
|
|
2018-09-06 09:09:23 +02:00
|
|
|
|
describe '#brouillon' do
|
2018-02-21 18:32:07 +01:00
|
|
|
|
before { sign_in(user) }
|
|
|
|
|
let!(:dossier) { create(:dossier, user: user, autorisation_donnees: true) }
|
|
|
|
|
|
2018-09-06 09:09:23 +02:00
|
|
|
|
subject { get :brouillon, params: { id: dossier.id } }
|
2018-02-21 18:32:07 +01:00
|
|
|
|
|
|
|
|
|
context 'when autorisation_donnees is checked' do
|
2018-09-06 09:09:23 +02:00
|
|
|
|
it { is_expected.to render_template(:brouillon) }
|
2018-02-21 18:32:07 +01:00
|
|
|
|
end
|
|
|
|
|
|
|
|
|
|
context 'when autorisation_donnees is not checked' do
|
|
|
|
|
before { dossier.update_columns(autorisation_donnees: false) }
|
|
|
|
|
|
|
|
|
|
context 'when the dossier is for personne morale' do
|
2018-10-04 09:43:19 +02:00
|
|
|
|
it { is_expected.to redirect_to(siret_dossier_path(dossier)) }
|
2018-02-21 18:32:07 +01:00
|
|
|
|
end
|
|
|
|
|
|
|
|
|
|
context 'when the dossier is for an personne physique' do
|
2018-03-02 16:27:03 +01:00
|
|
|
|
before { dossier.procedure.update(for_individual: true) }
|
2018-02-21 18:32:07 +01:00
|
|
|
|
|
|
|
|
|
it { is_expected.to redirect_to(identite_dossier_path(dossier)) }
|
|
|
|
|
end
|
|
|
|
|
end
|
|
|
|
|
end
|
|
|
|
|
|
|
|
|
|
describe '#edit' do
|
|
|
|
|
before { sign_in(user) }
|
|
|
|
|
let!(:dossier) { create(:dossier, user: user) }
|
|
|
|
|
|
|
|
|
|
it 'returns the edit page' do
|
2018-09-06 09:09:23 +02:00
|
|
|
|
get :brouillon, params: { id: dossier.id }
|
2018-02-21 18:32:07 +01:00
|
|
|
|
expect(response).to have_http_status(:success)
|
|
|
|
|
end
|
|
|
|
|
end
|
|
|
|
|
|
2022-10-11 12:21:06 +02:00
|
|
|
|
describe '#submit_brouillon' do
|
2018-02-21 18:32:07 +01:00
|
|
|
|
before { sign_in(user) }
|
|
|
|
|
let!(:dossier) { create(:dossier, user: user) }
|
2022-11-10 22:21:14 +01:00
|
|
|
|
let(:first_champ) { dossier.champs_public.first }
|
2023-09-19 11:07:50 +02:00
|
|
|
|
let(:anchor_to_first_champ) { controller.helpers.link_to first_champ.libelle, brouillon_dossier_path(anchor: first_champ.labelledby_id), class: 'error-anchor' }
|
2018-02-21 18:32:07 +01:00
|
|
|
|
let(:value) { 'beautiful value' }
|
2019-05-29 18:28:27 +02:00
|
|
|
|
let(:now) { Time.zone.parse('01/01/2100') }
|
2022-10-11 12:21:06 +02:00
|
|
|
|
let(:payload) { { id: dossier.id } }
|
2018-02-21 18:32:07 +01:00
|
|
|
|
|
2019-05-29 18:28:27 +02:00
|
|
|
|
subject do
|
2023-06-06 10:50:46 +02:00
|
|
|
|
travel_to now
|
|
|
|
|
post :submit_brouillon, params: payload
|
2019-05-29 18:28:27 +02:00
|
|
|
|
end
|
2018-02-21 18:32:07 +01:00
|
|
|
|
|
2018-06-08 15:51:46 +02:00
|
|
|
|
context 'when the dossier cannot be updated by the user' do
|
|
|
|
|
let!(:dossier) { create(:dossier, :en_instruction, user: user) }
|
|
|
|
|
|
2018-06-27 14:47:02 +02:00
|
|
|
|
it 'redirects to the dossiers list' do
|
2018-06-08 15:51:46 +02:00
|
|
|
|
subject
|
|
|
|
|
|
2023-04-26 16:54:50 +02:00
|
|
|
|
expect(response).to redirect_to(dossier_path(dossier))
|
2018-06-08 15:51:46 +02:00
|
|
|
|
expect(flash.alert).to eq('Votre dossier ne peut plus être modifié')
|
|
|
|
|
end
|
|
|
|
|
end
|
|
|
|
|
|
2018-09-06 10:49:26 +02:00
|
|
|
|
it 'sends an email only on the first #update_brouillon' do
|
2018-03-05 17:59:45 +01:00
|
|
|
|
delivery = double
|
2018-05-25 18:05:28 +02:00
|
|
|
|
expect(delivery).to receive(:deliver_later).with(no_args)
|
2018-03-05 17:59:45 +01:00
|
|
|
|
|
2021-04-29 19:10:22 +02:00
|
|
|
|
expect(NotificationMailer).to receive(:send_en_construction_notification)
|
2018-03-05 17:59:45 +01:00
|
|
|
|
.and_return(delivery)
|
|
|
|
|
|
|
|
|
|
subject
|
|
|
|
|
|
2021-04-29 19:10:22 +02:00
|
|
|
|
expect(NotificationMailer).not_to receive(:send_en_construction_notification)
|
2018-03-05 17:59:45 +01:00
|
|
|
|
|
|
|
|
|
subject
|
|
|
|
|
end
|
|
|
|
|
|
2018-02-21 18:32:07 +01:00
|
|
|
|
context 'when the update fails' do
|
2023-09-19 11:07:50 +02:00
|
|
|
|
render_views
|
|
|
|
|
let(:error_message) { 'nop' }
|
2018-02-21 18:32:07 +01:00
|
|
|
|
before do
|
2023-10-26 16:02:23 +02:00
|
|
|
|
expect_any_instance_of(Dossier).to receive(:validate).and_return(false)
|
2023-04-28 15:32:34 +02:00
|
|
|
|
expect_any_instance_of(Dossier).to receive(:errors).and_return(
|
2023-09-19 11:07:50 +02:00
|
|
|
|
[double(inner_error: double(base: first_champ), message: 'nop')]
|
2023-04-28 15:32:34 +02:00
|
|
|
|
)
|
2018-02-21 18:32:07 +01:00
|
|
|
|
subject
|
|
|
|
|
end
|
|
|
|
|
|
2018-09-06 09:09:23 +02:00
|
|
|
|
it { expect(response).to render_template(:brouillon) }
|
2023-09-19 11:07:50 +02:00
|
|
|
|
it { expect(response.body).to have_link(first_champ.libelle, href: "##{first_champ.labelledby_id}") }
|
|
|
|
|
it { expect(response.body).to have_content(error_message) }
|
2018-03-05 17:59:45 +01:00
|
|
|
|
|
|
|
|
|
it 'does not send an email' do
|
2021-04-29 19:10:22 +02:00
|
|
|
|
expect(NotificationMailer).not_to receive(:send_en_construction_notification)
|
2018-03-05 17:59:45 +01:00
|
|
|
|
|
|
|
|
|
subject
|
|
|
|
|
end
|
2018-02-21 18:32:07 +01:00
|
|
|
|
end
|
|
|
|
|
|
|
|
|
|
context 'when a mandatory champ is missing' do
|
2023-09-19 11:07:50 +02:00
|
|
|
|
render_views
|
|
|
|
|
|
2018-02-21 18:32:07 +01:00
|
|
|
|
let(:value) { nil }
|
|
|
|
|
|
|
|
|
|
before do
|
2018-03-02 16:27:03 +01:00
|
|
|
|
first_champ.type_de_champ.update(mandatory: true, libelle: 'l')
|
2018-02-21 18:32:07 +01:00
|
|
|
|
subject
|
|
|
|
|
end
|
|
|
|
|
|
2018-09-06 09:09:23 +02:00
|
|
|
|
it { expect(response).to render_template(:brouillon) }
|
2023-09-19 11:07:50 +02:00
|
|
|
|
it { expect(response.body).to have_link(first_champ.libelle, href: "##{first_champ.labelledby_id}") }
|
|
|
|
|
it { expect(response.body).to have_content("doit être rempli") }
|
2023-04-28 15:32:34 +02:00
|
|
|
|
end
|
|
|
|
|
|
2018-02-27 17:25:45 +01:00
|
|
|
|
context 'when dossier has no champ' do
|
|
|
|
|
let(:submit_payload) { { id: dossier.id } }
|
|
|
|
|
|
|
|
|
|
it 'does not raise any errors' do
|
|
|
|
|
subject
|
|
|
|
|
|
2018-02-27 09:49:58 +01:00
|
|
|
|
expect(response).to redirect_to(merci_dossier_path(dossier))
|
2018-02-27 17:25:45 +01:00
|
|
|
|
end
|
|
|
|
|
end
|
2018-03-29 16:45:24 +02:00
|
|
|
|
|
|
|
|
|
context 'when the user has an invitation but is not the owner' do
|
|
|
|
|
let(:dossier) { create(:dossier) }
|
2018-10-10 09:23:08 +02:00
|
|
|
|
let!(:invite) { create(:invite, dossier: dossier, user: user) }
|
2018-03-29 16:45:24 +02:00
|
|
|
|
|
2022-10-11 12:21:06 +02:00
|
|
|
|
context 'and the invite tries to submit the dossier' do
|
|
|
|
|
before { subject }
|
2018-03-29 16:45:24 +02:00
|
|
|
|
|
2022-10-11 12:21:06 +02:00
|
|
|
|
it { expect(response).to redirect_to(root_path) }
|
2023-07-19 11:50:38 +02:00
|
|
|
|
it { expect(flash.alert).to include("Vous n’avez pas accès à ce dossier") }
|
2022-10-11 12:21:06 +02:00
|
|
|
|
end
|
|
|
|
|
end
|
2023-06-06 10:50:46 +02:00
|
|
|
|
|
|
|
|
|
context 'when procedure has sva enabled' do
|
|
|
|
|
let(:procedure) { create(:procedure, :sva) }
|
|
|
|
|
let!(:dossier) { create(:dossier, :brouillon, procedure:, user:) }
|
|
|
|
|
|
|
|
|
|
it 'passe automatiquement en instruction' do
|
|
|
|
|
delivery = double.tap { expect(_1).to receive(:deliver_later).with(no_args).twice }
|
|
|
|
|
expect(NotificationMailer).to receive(:send_en_construction_notification).and_return(delivery)
|
|
|
|
|
expect(NotificationMailer).to receive(:send_en_instruction_notification).and_return(delivery)
|
|
|
|
|
|
|
|
|
|
subject
|
|
|
|
|
dossier.reload
|
|
|
|
|
|
|
|
|
|
expect(dossier).to be_en_instruction
|
|
|
|
|
expect(dossier.pending_correction?).to be_falsey
|
|
|
|
|
expect(dossier.en_instruction_at).to within(5.seconds).of(Time.current)
|
|
|
|
|
end
|
|
|
|
|
end
|
2022-10-11 12:21:06 +02:00
|
|
|
|
end
|
|
|
|
|
|
2023-03-21 18:24:39 +01:00
|
|
|
|
describe '#submit_en_construction' do
|
2022-10-11 12:21:06 +02:00
|
|
|
|
before { sign_in(user) }
|
|
|
|
|
|
2023-03-21 18:24:39 +01:00
|
|
|
|
let!(:dossier) { create(:dossier, :en_construction, user: user) }
|
|
|
|
|
let(:first_champ) { dossier.owner_editing_fork.champs_public.first }
|
2023-05-13 06:44:58 +02:00
|
|
|
|
let(:anchor_to_first_champ) { controller.helpers.link_to I18n.t('views.users.dossiers.fix_champ'), modifier_dossier_path(anchor: first_champ.labelledby_id), class: 'error-anchor' }
|
2023-03-21 18:24:39 +01:00
|
|
|
|
let(:value) { 'beautiful value' }
|
|
|
|
|
let(:now) { Time.zone.parse('01/01/2100') }
|
|
|
|
|
let(:payload) { { id: dossier.id } }
|
|
|
|
|
|
|
|
|
|
before { dossier.owner_editing_fork }
|
|
|
|
|
|
|
|
|
|
subject do
|
|
|
|
|
Timecop.freeze(now) do
|
|
|
|
|
post :submit_en_construction, params: payload
|
|
|
|
|
end
|
|
|
|
|
end
|
|
|
|
|
|
|
|
|
|
context 'when the dossier cannot be updated by the user' do
|
|
|
|
|
let!(:dossier) { create(:dossier, :en_instruction, user: user) }
|
|
|
|
|
|
|
|
|
|
it 'redirects to the dossiers list' do
|
|
|
|
|
subject
|
|
|
|
|
|
|
|
|
|
expect(response).to redirect_to(dossier_path(dossier))
|
|
|
|
|
expect(flash.alert).to eq('Votre dossier ne peut plus être modifié')
|
|
|
|
|
end
|
|
|
|
|
end
|
|
|
|
|
|
|
|
|
|
context 'when the update fails' do
|
2023-05-09 18:04:34 +02:00
|
|
|
|
render_views
|
|
|
|
|
|
2023-03-21 18:24:39 +01:00
|
|
|
|
before do
|
2023-10-26 16:02:23 +02:00
|
|
|
|
expect_any_instance_of(Dossier).to receive(:validate).and_return(false)
|
2023-03-21 18:24:39 +01:00
|
|
|
|
expect_any_instance_of(Dossier).to receive(:errors).and_return(
|
2023-09-19 11:07:50 +02:00
|
|
|
|
[double(inner_error: double(base: first_champ), message: 'nop')]
|
2023-03-21 18:24:39 +01:00
|
|
|
|
)
|
2023-05-09 18:04:34 +02:00
|
|
|
|
|
2023-03-21 18:24:39 +01:00
|
|
|
|
subject
|
|
|
|
|
end
|
|
|
|
|
|
|
|
|
|
it { expect(response).to render_template(:modifier) }
|
|
|
|
|
end
|
|
|
|
|
|
|
|
|
|
context 'when a mandatory champ is missing' do
|
|
|
|
|
let(:value) { nil }
|
2023-09-19 11:07:50 +02:00
|
|
|
|
render_views
|
2023-03-21 18:24:39 +01:00
|
|
|
|
before do
|
|
|
|
|
first_champ.type_de_champ.update(mandatory: true, libelle: 'l')
|
|
|
|
|
subject
|
|
|
|
|
end
|
|
|
|
|
|
|
|
|
|
it { expect(response).to render_template(:modifier) }
|
2023-09-19 11:07:50 +02:00
|
|
|
|
it { expect(response.body).to have_content("doit être rempli") }
|
|
|
|
|
it { expect(response.body).to have_link(first_champ.libelle, href: "##{first_champ.labelledby_id}") }
|
2023-03-21 18:24:39 +01:00
|
|
|
|
end
|
|
|
|
|
|
|
|
|
|
context 'when dossier has no champ' do
|
|
|
|
|
let(:submit_payload) { { id: dossier.id } }
|
|
|
|
|
|
|
|
|
|
it 'does not raise any errors' do
|
|
|
|
|
subject
|
|
|
|
|
|
|
|
|
|
expect(response).to redirect_to(dossier_path(dossier))
|
|
|
|
|
end
|
|
|
|
|
end
|
2023-05-11 16:52:10 +02:00
|
|
|
|
|
|
|
|
|
context 'when dossier was already submitted' do
|
|
|
|
|
before { post :submit_en_construction, params: payload }
|
|
|
|
|
|
|
|
|
|
it 'redirects to the dossier' do
|
|
|
|
|
subject
|
|
|
|
|
|
|
|
|
|
expect(response).to redirect_to(dossier_path(dossier))
|
|
|
|
|
expect(flash.alert).to eq("Les modifications ont déjà été déposées")
|
|
|
|
|
end
|
|
|
|
|
end
|
2023-04-11 18:31:16 +02:00
|
|
|
|
|
|
|
|
|
context "when there are pending correction" do
|
|
|
|
|
let!(:correction) { create(:dossier_correction, dossier: dossier) }
|
|
|
|
|
|
|
|
|
|
subject { post :submit_en_construction, params: { id: dossier.id, dossier: { pending_correction_confirm: "1" } } }
|
|
|
|
|
|
|
|
|
|
it "resolve correction" do
|
|
|
|
|
expect { subject }.to change { correction.reload.resolved_at }.to be_truthy
|
|
|
|
|
end
|
2023-06-02 17:51:02 +02:00
|
|
|
|
|
|
|
|
|
context 'when procedure has sva enabled' do
|
|
|
|
|
let(:procedure) { create(:procedure, :sva) }
|
|
|
|
|
let!(:dossier) { create(:dossier, :en_construction, procedure:, user:) }
|
|
|
|
|
|
|
|
|
|
it 'passe automatiquement en instruction' do
|
|
|
|
|
expect(dossier.pending_correction?).to be_truthy
|
|
|
|
|
|
|
|
|
|
subject
|
|
|
|
|
dossier.reload
|
|
|
|
|
|
|
|
|
|
expect(dossier).to be_en_instruction
|
|
|
|
|
expect(dossier.pending_correction?).to be_falsey
|
|
|
|
|
expect(dossier.en_instruction_at).to within(5.seconds).of(Time.current)
|
|
|
|
|
end
|
|
|
|
|
end
|
|
|
|
|
end
|
|
|
|
|
|
|
|
|
|
context 'when there is sva without confirming correction' do
|
|
|
|
|
let!(:correction) { create(:dossier_correction, dossier: dossier) }
|
|
|
|
|
|
|
|
|
|
subject { post :submit_en_construction, params: { id: dossier.id } }
|
|
|
|
|
|
|
|
|
|
it "does not resolve correction" do
|
|
|
|
|
expect { subject }.not_to change { correction.reload.resolved_at }
|
|
|
|
|
end
|
|
|
|
|
|
|
|
|
|
context 'when procedure has sva enabled' do
|
|
|
|
|
let(:procedure) { create(:procedure, :sva) }
|
|
|
|
|
let!(:dossier) { create(:dossier, :en_construction, procedure:, user:) }
|
|
|
|
|
|
|
|
|
|
it 'does not passe automatiquement en instruction' do
|
|
|
|
|
expect(dossier.pending_correction?).to be_truthy
|
|
|
|
|
|
|
|
|
|
subject
|
|
|
|
|
dossier.reload
|
|
|
|
|
|
|
|
|
|
expect(dossier).to be_en_construction
|
|
|
|
|
expect(dossier.pending_correction?).to be_truthy
|
|
|
|
|
end
|
|
|
|
|
end
|
2023-04-11 18:31:16 +02:00
|
|
|
|
end
|
2023-03-21 18:24:39 +01:00
|
|
|
|
end
|
|
|
|
|
|
|
|
|
|
describe '#update brouillon' do
|
|
|
|
|
before { sign_in(user) }
|
|
|
|
|
|
|
|
|
|
let(:procedure) { create(:procedure, :published, types_de_champ_public: [{}, { type: :piece_justificative }]) }
|
|
|
|
|
let(:dossier) { create(:dossier, user:, procedure:) }
|
2022-11-10 22:21:14 +01:00
|
|
|
|
let(:first_champ) { dossier.champs_public.first }
|
|
|
|
|
let(:piece_justificative_champ) { dossier.champs_public.last }
|
2022-10-11 12:21:06 +02:00
|
|
|
|
let(:value) { 'beautiful value' }
|
|
|
|
|
let(:file) { fixture_file_upload('spec/fixtures/files/piece_justificative_0.pdf', 'application/pdf') }
|
|
|
|
|
let(:now) { Time.zone.parse('01/01/2100') }
|
|
|
|
|
|
|
|
|
|
let(:submit_payload) do
|
|
|
|
|
{
|
|
|
|
|
id: dossier.id,
|
|
|
|
|
dossier: {
|
|
|
|
|
groupe_instructeur_id: dossier.groupe_instructeur_id,
|
2023-03-21 18:24:39 +01:00
|
|
|
|
champs_public_attributes: {
|
|
|
|
|
first_champ.id => {
|
2022-10-11 12:21:06 +02:00
|
|
|
|
id: first_champ.id,
|
|
|
|
|
value: value
|
|
|
|
|
},
|
2023-03-21 18:24:39 +01:00
|
|
|
|
piece_justificative_champ.id => {
|
2022-10-11 12:21:06 +02:00
|
|
|
|
id: piece_justificative_champ.id,
|
|
|
|
|
piece_justificative_file: file
|
|
|
|
|
}
|
2023-03-21 18:24:39 +01:00
|
|
|
|
}
|
2022-10-11 12:21:06 +02:00
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
end
|
|
|
|
|
let(:payload) { submit_payload }
|
|
|
|
|
|
|
|
|
|
subject do
|
|
|
|
|
Timecop.freeze(now) do
|
2023-03-21 18:24:39 +01:00
|
|
|
|
patch :update, params: payload, format: :turbo_stream
|
2022-10-11 12:21:06 +02:00
|
|
|
|
end
|
|
|
|
|
end
|
|
|
|
|
|
|
|
|
|
context 'when the dossier cannot be updated by the user' do
|
2023-03-21 18:24:39 +01:00
|
|
|
|
let(:dossier) { create(:dossier, :en_instruction, user:, procedure:) }
|
2022-10-11 12:21:06 +02:00
|
|
|
|
|
|
|
|
|
it 'redirects to the dossiers list' do
|
|
|
|
|
subject
|
|
|
|
|
|
2023-04-26 16:54:50 +02:00
|
|
|
|
expect(response).to redirect_to(dossier_path(dossier))
|
2022-10-11 12:21:06 +02:00
|
|
|
|
expect(flash.alert).to eq('Votre dossier ne peut plus être modifié')
|
|
|
|
|
end
|
|
|
|
|
end
|
|
|
|
|
|
|
|
|
|
context 'when dossier can be updated by the owner' do
|
|
|
|
|
it 'updates the champs' do
|
|
|
|
|
subject
|
|
|
|
|
|
|
|
|
|
expect(response).to have_http_status(:ok)
|
|
|
|
|
expect(dossier.reload.updated_at.year).to eq(2100)
|
|
|
|
|
expect(dossier.reload.state).to eq(Dossier.states.fetch(:brouillon))
|
|
|
|
|
end
|
|
|
|
|
|
|
|
|
|
context 'without new values for champs' do
|
|
|
|
|
let(:submit_payload) do
|
|
|
|
|
{
|
|
|
|
|
id: dossier.id,
|
|
|
|
|
dossier: {
|
2023-03-21 18:24:39 +01:00
|
|
|
|
champs_public_attributes: { first_champ.id => { id: first_champ.id } }
|
2022-10-11 12:21:06 +02:00
|
|
|
|
}
|
|
|
|
|
}
|
2018-03-29 16:45:24 +02:00
|
|
|
|
end
|
|
|
|
|
|
2022-10-11 12:21:06 +02:00
|
|
|
|
it "doesn't set last_champ_updated_at" do
|
|
|
|
|
subject
|
|
|
|
|
expect(dossier.reload.last_champ_updated_at).to eq(nil)
|
|
|
|
|
end
|
2018-03-29 16:45:24 +02:00
|
|
|
|
end
|
2022-10-11 12:21:06 +02:00
|
|
|
|
end
|
2018-03-29 16:45:24 +02:00
|
|
|
|
|
2022-10-11 12:21:06 +02:00
|
|
|
|
context 'when the user has an invitation but is not the owner' do
|
2023-03-21 18:24:39 +01:00
|
|
|
|
let(:dossier) { create(:dossier, procedure: procedure) }
|
2022-10-11 12:21:06 +02:00
|
|
|
|
let!(:invite) { create(:invite, dossier: dossier, user: user) }
|
|
|
|
|
|
|
|
|
|
before { subject }
|
|
|
|
|
|
|
|
|
|
it { expect(first_champ.reload.value).to eq('beautiful value') }
|
|
|
|
|
it { expect(response).to have_http_status(:ok) }
|
|
|
|
|
end
|
2023-09-26 16:31:35 +02:00
|
|
|
|
|
|
|
|
|
context 'decimal number champ separator' do
|
|
|
|
|
let (:procedure) { create(:procedure, :published, types_de_champ_public: [{ type: :decimal_number }]) }
|
|
|
|
|
let (:submit_payload) do
|
|
|
|
|
{
|
|
|
|
|
id: dossier.id,
|
|
|
|
|
dossier: {
|
|
|
|
|
champs_public_attributes: { first_champ.id => { id: first_champ.id, value: value } }
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
end
|
|
|
|
|
|
|
|
|
|
context 'when spearator is dot' do
|
|
|
|
|
let(:value) { '3.14' }
|
|
|
|
|
|
|
|
|
|
it "saves the value" do
|
|
|
|
|
subject
|
|
|
|
|
expect(first_champ.reload.value).to eq('3.14')
|
|
|
|
|
end
|
|
|
|
|
end
|
|
|
|
|
|
|
|
|
|
context 'when spearator is comma' do
|
|
|
|
|
let(:value) { '3,14' }
|
|
|
|
|
|
|
|
|
|
it "saves the value" do
|
|
|
|
|
subject
|
|
|
|
|
expect(first_champ.reload.value).to eq('3.14')
|
|
|
|
|
end
|
|
|
|
|
end
|
|
|
|
|
end
|
2018-02-21 18:32:07 +01:00
|
|
|
|
end
|
2018-04-03 10:49:16 +02:00
|
|
|
|
|
2023-03-21 18:24:39 +01:00
|
|
|
|
describe '#update en_construction' do
|
2018-09-06 11:39:46 +02:00
|
|
|
|
before { sign_in(user) }
|
2019-05-29 18:28:27 +02:00
|
|
|
|
|
2023-03-21 18:24:39 +01:00
|
|
|
|
let(:procedure) { create(:procedure, :published, types_de_champ_public: [{}, { type: :piece_justificative }]) }
|
|
|
|
|
let!(:dossier) { create(:dossier, :en_construction, user:, procedure:) }
|
2022-11-10 22:21:14 +01:00
|
|
|
|
let(:first_champ) { dossier.champs_public.first }
|
2023-05-13 06:44:58 +02:00
|
|
|
|
let(:anchor_to_first_champ) { controller.helpers.link_to I18n.t('views.users.dossiers.fix_champ'), brouillon_dossier_path(anchor: first_champ.labelledby_id), class: 'error-anchor' }
|
2022-11-10 22:21:14 +01:00
|
|
|
|
let(:piece_justificative_champ) { dossier.champs_public.last }
|
2018-09-06 11:39:46 +02:00
|
|
|
|
let(:value) { 'beautiful value' }
|
2020-06-30 17:53:54 +02:00
|
|
|
|
let(:file) { fixture_file_upload('spec/fixtures/files/piece_justificative_0.pdf', 'application/pdf') }
|
2019-05-29 18:28:27 +02:00
|
|
|
|
let(:now) { Time.zone.parse('01/01/2100') }
|
|
|
|
|
|
2018-09-06 11:39:46 +02:00
|
|
|
|
let(:submit_payload) do
|
|
|
|
|
{
|
|
|
|
|
id: dossier.id,
|
|
|
|
|
dossier: {
|
2021-03-09 11:21:30 +01:00
|
|
|
|
groupe_instructeur_id: dossier.groupe_instructeur_id,
|
2023-03-21 18:24:39 +01:00
|
|
|
|
champs_public_attributes: {
|
|
|
|
|
first_champ.id => {
|
2020-06-29 17:30:02 +02:00
|
|
|
|
id: first_champ.id,
|
|
|
|
|
value: value
|
|
|
|
|
},
|
2023-03-21 18:24:39 +01:00
|
|
|
|
piece_justificative_champ.id => {
|
2020-06-29 17:30:02 +02:00
|
|
|
|
id: piece_justificative_champ.id,
|
|
|
|
|
piece_justificative_file: file
|
|
|
|
|
}
|
2023-03-21 18:24:39 +01:00
|
|
|
|
}
|
2018-09-06 11:39:46 +02:00
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
end
|
|
|
|
|
let(:payload) { submit_payload }
|
|
|
|
|
|
2019-05-29 18:28:27 +02:00
|
|
|
|
subject do
|
|
|
|
|
Timecop.freeze(now) do
|
2023-03-21 18:24:39 +01:00
|
|
|
|
patch :update, params: payload, format: :turbo_stream
|
2019-05-29 18:28:27 +02:00
|
|
|
|
end
|
|
|
|
|
end
|
2018-09-06 11:39:46 +02:00
|
|
|
|
|
|
|
|
|
context 'when the dossier cannot be updated by the user' do
|
2023-03-21 18:24:39 +01:00
|
|
|
|
let!(:dossier) { create(:dossier, :en_instruction, user:, procedure:) }
|
2018-09-06 11:39:46 +02:00
|
|
|
|
|
|
|
|
|
it 'redirects to the dossiers list' do
|
|
|
|
|
subject
|
2023-04-26 16:54:50 +02:00
|
|
|
|
expect(response).to redirect_to(dossier_path(dossier))
|
2018-09-06 11:39:46 +02:00
|
|
|
|
expect(flash.alert).to eq('Votre dossier ne peut plus être modifié')
|
|
|
|
|
end
|
|
|
|
|
end
|
|
|
|
|
|
|
|
|
|
context 'when dossier can be updated by the owner' do
|
|
|
|
|
it 'updates the champs' do
|
|
|
|
|
subject
|
|
|
|
|
expect(first_champ.reload.value).to eq('beautiful value')
|
2020-06-29 17:30:02 +02:00
|
|
|
|
expect(piece_justificative_champ.reload.piece_justificative_file).to be_attached
|
|
|
|
|
end
|
|
|
|
|
|
2021-04-01 16:48:12 +02:00
|
|
|
|
it 'updates the dossier timestamps' do
|
2020-06-29 17:30:02 +02:00
|
|
|
|
subject
|
2021-04-01 16:48:12 +02:00
|
|
|
|
dossier.reload
|
|
|
|
|
expect(dossier.updated_at).to eq(now)
|
|
|
|
|
expect(dossier.last_champ_updated_at).to eq(now)
|
2020-06-29 17:30:02 +02:00
|
|
|
|
end
|
|
|
|
|
|
|
|
|
|
it 'updates the dossier state' do
|
|
|
|
|
subject
|
2018-09-06 11:39:46 +02:00
|
|
|
|
expect(dossier.reload.state).to eq(Dossier.states.fetch(:en_construction))
|
|
|
|
|
end
|
2019-05-29 18:28:27 +02:00
|
|
|
|
|
2022-09-08 11:26:18 +02:00
|
|
|
|
it { is_expected.to have_http_status(:ok) }
|
2020-06-29 17:30:02 +02:00
|
|
|
|
|
2021-04-01 16:48:12 +02:00
|
|
|
|
context 'when only a single file champ are modified' do
|
|
|
|
|
# A bug in ActiveRecord causes records changed through grand-parent <-> parent <-> child
|
|
|
|
|
# relationships do not touch the grand-parent record on change.
|
|
|
|
|
# This situation is hit when updating just the attachment of a champ (and not the
|
|
|
|
|
# champ itself).
|
|
|
|
|
#
|
|
|
|
|
# This test ensures that, whatever workaround we wrote for this, it still works properly.
|
|
|
|
|
#
|
|
|
|
|
# See https://github.com/rails/rails/issues/26726
|
2019-05-29 18:28:27 +02:00
|
|
|
|
let(:submit_payload) do
|
|
|
|
|
{
|
|
|
|
|
id: dossier.id,
|
|
|
|
|
dossier: {
|
2023-03-21 18:24:39 +01:00
|
|
|
|
champs_public_attributes: {
|
|
|
|
|
piece_justificative_champ.id => {
|
2021-04-01 16:48:12 +02:00
|
|
|
|
id: piece_justificative_champ.id,
|
|
|
|
|
piece_justificative_file: file
|
|
|
|
|
}
|
2023-03-21 18:24:39 +01:00
|
|
|
|
}
|
2019-05-29 18:28:27 +02:00
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
end
|
|
|
|
|
|
2021-04-01 16:48:12 +02:00
|
|
|
|
it 'updates the dossier timestamps' do
|
2019-05-29 18:28:27 +02:00
|
|
|
|
subject
|
2021-04-01 16:48:12 +02:00
|
|
|
|
dossier.reload
|
|
|
|
|
expect(dossier.updated_at).to eq(now)
|
|
|
|
|
expect(dossier.last_champ_updated_at).to eq(now)
|
2019-05-29 18:28:27 +02:00
|
|
|
|
end
|
|
|
|
|
end
|
2018-09-06 11:39:46 +02:00
|
|
|
|
end
|
|
|
|
|
|
|
|
|
|
context 'when the update fails' do
|
2023-09-19 11:07:50 +02:00
|
|
|
|
render_views
|
2018-09-06 11:39:46 +02:00
|
|
|
|
|
2023-09-19 11:07:50 +02:00
|
|
|
|
context 'classic error' do
|
|
|
|
|
before do
|
|
|
|
|
expect_any_instance_of(Dossier).to receive(:save).and_return(false)
|
|
|
|
|
expect_any_instance_of(Dossier).to receive(:errors).and_return(
|
|
|
|
|
[message: 'nop', inner_error: double(base: first_champ)]
|
|
|
|
|
)
|
|
|
|
|
subject
|
|
|
|
|
end
|
2018-09-06 11:39:46 +02:00
|
|
|
|
|
2023-09-19 11:07:50 +02:00
|
|
|
|
it { expect(response).to render_template(:update) }
|
2021-04-01 16:48:12 +02:00
|
|
|
|
|
2023-09-19 11:07:50 +02:00
|
|
|
|
it 'does not update the dossier timestamps' do
|
|
|
|
|
dossier.reload
|
|
|
|
|
expect(dossier.updated_at).not_to eq(now)
|
|
|
|
|
expect(dossier.last_champ_updated_at).not_to eq(now)
|
|
|
|
|
end
|
2018-09-06 11:39:46 +02:00
|
|
|
|
|
2023-09-19 11:07:50 +02:00
|
|
|
|
it 'does not send an email' do
|
|
|
|
|
expect(NotificationMailer).not_to receive(:send_en_construction_notification)
|
|
|
|
|
|
|
|
|
|
subject
|
|
|
|
|
end
|
2018-09-06 11:39:46 +02:00
|
|
|
|
end
|
|
|
|
|
|
2023-09-19 11:07:50 +02:00
|
|
|
|
context 'iban error' do
|
|
|
|
|
let(:value) { 'abc' }
|
2023-04-28 15:32:34 +02:00
|
|
|
|
|
2023-09-19 11:07:50 +02:00
|
|
|
|
before do
|
|
|
|
|
first_champ.type_de_champ.update!(type_champ: :iban, mandatory: true, libelle: 'l')
|
|
|
|
|
dossier.champs_public.first.becomes!(Champs::IbanChamp).save!
|
2023-04-28 15:32:34 +02:00
|
|
|
|
|
2023-09-19 11:07:50 +02:00
|
|
|
|
subject
|
|
|
|
|
end
|
2023-04-28 15:32:34 +02:00
|
|
|
|
|
2023-09-19 11:07:50 +02:00
|
|
|
|
it { expect(response).to have_http_status(:success) }
|
|
|
|
|
end
|
2018-09-06 11:39:46 +02:00
|
|
|
|
end
|
|
|
|
|
|
|
|
|
|
context 'when the user has an invitation but is not the owner' do
|
2023-03-21 18:24:39 +01:00
|
|
|
|
let(:dossier) { create(:dossier, :en_construction, procedure:) }
|
|
|
|
|
let!(:invite) { create(:invite, dossier:, user:) }
|
2018-09-06 11:39:46 +02:00
|
|
|
|
|
2022-10-11 12:21:06 +02:00
|
|
|
|
before { subject }
|
2018-09-06 11:39:46 +02:00
|
|
|
|
|
|
|
|
|
it { expect(first_champ.reload.value).to eq('beautiful value') }
|
2022-09-08 11:26:18 +02:00
|
|
|
|
it { expect(response).to have_http_status(:ok) }
|
2018-09-06 11:39:46 +02:00
|
|
|
|
end
|
2020-09-07 16:12:29 +02:00
|
|
|
|
|
|
|
|
|
context 'when the dossier is followed by an instructeur' do
|
2023-03-21 18:24:39 +01:00
|
|
|
|
let(:dossier) { create(:dossier, procedure:) }
|
2020-09-07 16:12:29 +02:00
|
|
|
|
let(:instructeur) { create(:instructeur) }
|
2023-03-21 18:24:39 +01:00
|
|
|
|
let!(:invite) { create(:invite, dossier:, user:) }
|
2020-09-07 16:12:29 +02:00
|
|
|
|
|
|
|
|
|
before do
|
|
|
|
|
instructeur.follow(dossier)
|
|
|
|
|
end
|
|
|
|
|
|
|
|
|
|
it 'the follower has a notification' do
|
2020-09-18 15:40:26 +02:00
|
|
|
|
expect(instructeur.reload.followed_dossiers.with_notifications).to eq([])
|
2020-09-07 16:12:29 +02:00
|
|
|
|
subject
|
2020-09-18 15:40:26 +02:00
|
|
|
|
expect(instructeur.reload.followed_dossiers.with_notifications).to eq([dossier.reload])
|
2020-09-07 16:12:29 +02:00
|
|
|
|
end
|
|
|
|
|
end
|
2020-09-08 15:31:06 +02:00
|
|
|
|
|
|
|
|
|
context 'when the champ is a phone number' do
|
2023-03-21 18:24:39 +01:00
|
|
|
|
let(:procedure) { create(:procedure, :published, types_de_champ_public: [{ type: :phone }]) }
|
|
|
|
|
let!(:dossier) { create(:dossier, :en_construction, user:, procedure:) }
|
2022-11-10 22:21:14 +01:00
|
|
|
|
let(:first_champ) { dossier.champs_public.first }
|
2020-09-08 15:31:06 +02:00
|
|
|
|
let(:now) { Time.zone.parse('01/01/2100') }
|
|
|
|
|
|
|
|
|
|
let(:submit_payload) do
|
|
|
|
|
{
|
|
|
|
|
id: dossier.id,
|
|
|
|
|
dossier: {
|
2023-03-21 18:24:39 +01:00
|
|
|
|
champs_public_attributes: {
|
|
|
|
|
first_champ.id => {
|
2020-09-08 15:31:06 +02:00
|
|
|
|
id: first_champ.id,
|
|
|
|
|
value: value
|
|
|
|
|
}
|
2023-03-21 18:24:39 +01:00
|
|
|
|
}
|
2020-09-08 15:31:06 +02:00
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
end
|
|
|
|
|
|
|
|
|
|
context 'with a valid value sent as string' do
|
|
|
|
|
let(:value) { '0612345678' }
|
|
|
|
|
it 'updates the value' do
|
|
|
|
|
subject
|
|
|
|
|
expect(first_champ.reload.value).to eq('0612345678')
|
|
|
|
|
end
|
|
|
|
|
end
|
|
|
|
|
|
|
|
|
|
context 'with a valid value sent as number' do
|
|
|
|
|
let(:value) { '45187272'.to_i }
|
|
|
|
|
it 'updates the value' do
|
|
|
|
|
subject
|
|
|
|
|
expect(first_champ.reload.value).to eq('45187272')
|
|
|
|
|
end
|
|
|
|
|
end
|
|
|
|
|
end
|
2018-09-06 11:39:46 +02:00
|
|
|
|
end
|
|
|
|
|
|
2018-04-03 10:49:16 +02:00
|
|
|
|
describe '#index' do
|
|
|
|
|
before { sign_in(user) }
|
|
|
|
|
|
|
|
|
|
context 'when the user does not have any dossiers' do
|
|
|
|
|
before { get(:index) }
|
|
|
|
|
|
2021-11-10 17:36:42 +01:00
|
|
|
|
it { expect(assigns(:statut)).to eq('en-cours') }
|
2018-04-03 10:49:16 +02:00
|
|
|
|
end
|
|
|
|
|
|
|
|
|
|
context 'when the user only have its own dossiers' do
|
|
|
|
|
let!(:own_dossier) { create(:dossier, user: user) }
|
|
|
|
|
|
|
|
|
|
before { get(:index) }
|
2021-11-10 17:36:42 +01:00
|
|
|
|
it { expect(assigns(:statut)).to eq('en-cours') }
|
2020-11-17 13:25:35 +01:00
|
|
|
|
it { expect(assigns(:user_dossiers)).to match([own_dossier]) }
|
2018-04-03 10:49:16 +02:00
|
|
|
|
end
|
|
|
|
|
|
|
|
|
|
context 'when the user only have some dossiers invites' do
|
2018-10-10 09:23:08 +02:00
|
|
|
|
let!(:invite) { create(:invite, dossier: create(:dossier), user: user) }
|
2018-04-03 10:49:16 +02:00
|
|
|
|
|
|
|
|
|
before { get(:index) }
|
|
|
|
|
|
2020-11-26 15:13:32 +01:00
|
|
|
|
it { expect(assigns(:statut)).to eq('dossiers-invites') }
|
2020-11-17 13:25:35 +01:00
|
|
|
|
it { expect(assigns(:dossiers_invites)).to match([invite.dossier]) }
|
2018-04-03 10:49:16 +02:00
|
|
|
|
end
|
|
|
|
|
|
2021-11-10 17:36:42 +01:00
|
|
|
|
context 'when the user has dossiers invites, own and traites' do
|
|
|
|
|
let!(:procedure) { create(:procedure, :published) }
|
2018-04-03 10:49:16 +02:00
|
|
|
|
let!(:own_dossier) { create(:dossier, user: user) }
|
2021-11-10 17:36:42 +01:00
|
|
|
|
let!(:own_dossier2) { create(:dossier, user: user, state: "accepte", procedure: procedure) }
|
2018-10-10 09:23:08 +02:00
|
|
|
|
let!(:invite) { create(:invite, dossier: create(:dossier), user: user) }
|
2018-04-03 10:49:16 +02:00
|
|
|
|
|
2020-11-17 13:25:35 +01:00
|
|
|
|
context 'and there is no statut param' do
|
2018-04-03 10:49:16 +02:00
|
|
|
|
before { get(:index) }
|
|
|
|
|
|
2021-11-10 17:36:42 +01:00
|
|
|
|
it { expect(assigns(:statut)).to eq('en-cours') }
|
2018-04-03 10:49:16 +02:00
|
|
|
|
end
|
|
|
|
|
|
|
|
|
|
context 'and there is "dossiers-invites" param' do
|
2020-11-17 13:25:35 +01:00
|
|
|
|
before { get(:index, params: { statut: 'dossiers-invites' }) }
|
2018-04-03 10:49:16 +02:00
|
|
|
|
|
2020-11-17 13:25:35 +01:00
|
|
|
|
it { expect(assigns(:statut)).to eq('dossiers-invites') }
|
2018-04-03 10:49:16 +02:00
|
|
|
|
end
|
|
|
|
|
|
2021-11-10 17:36:42 +01:00
|
|
|
|
context 'and there is "en-cours" param' do
|
|
|
|
|
before { get(:index, params: { statut: 'en-cours' }) }
|
2018-04-03 10:49:16 +02:00
|
|
|
|
|
2021-11-10 17:36:42 +01:00
|
|
|
|
it { expect(assigns(:statut)).to eq('en-cours') }
|
|
|
|
|
end
|
|
|
|
|
|
|
|
|
|
context 'and there is "traites" param' do
|
|
|
|
|
before { get(:index, params: { statut: 'traites' }) }
|
|
|
|
|
|
|
|
|
|
it { expect(assigns(:statut)).to eq('traites') }
|
|
|
|
|
end
|
|
|
|
|
|
|
|
|
|
context 'and the traité dossier has been hidden by user' do
|
|
|
|
|
before do
|
|
|
|
|
own_dossier2.update!(hidden_by_user_at: Time.zone.now)
|
|
|
|
|
get(:index, params: { statut: 'traites' })
|
|
|
|
|
end
|
|
|
|
|
it { expect(assigns(:statut)).to eq('en-cours') }
|
2018-04-03 10:49:16 +02:00
|
|
|
|
end
|
2021-11-29 11:34:42 +01:00
|
|
|
|
|
|
|
|
|
context 'when the instructeur archive the dossier' do
|
|
|
|
|
before do
|
|
|
|
|
own_dossier2.update!(archived: true)
|
|
|
|
|
get(:index, params: { statut: 'en-cours' })
|
|
|
|
|
end
|
|
|
|
|
it { expect(assigns(:statut)).to eq('en-cours') }
|
|
|
|
|
it { expect(assigns(:dossiers_traites).map(&:id)).to eq([own_dossier2.id]) }
|
|
|
|
|
it { expect(own_dossier2.archived).to be_truthy }
|
|
|
|
|
end
|
2018-04-03 10:49:16 +02:00
|
|
|
|
end
|
2018-06-27 17:03:13 +02:00
|
|
|
|
|
2023-04-18 12:03:10 +02:00
|
|
|
|
context 'when the user has dossier in brouillon recently updated' do
|
2023-04-11 15:50:17 +02:00
|
|
|
|
let!(:own_dossier) { create(:dossier, user: user) }
|
2023-04-18 12:03:10 +02:00
|
|
|
|
let!(:own_dossier_2) { create(:dossier, user: user) }
|
2023-04-11 15:50:17 +02:00
|
|
|
|
|
|
|
|
|
before { get(:index) }
|
|
|
|
|
|
2023-04-18 12:03:10 +02:00
|
|
|
|
it { expect(assigns(:first_brouillon_recently_updated)).to match(own_dossier_2) }
|
2023-04-11 15:50:17 +02:00
|
|
|
|
end
|
|
|
|
|
|
2018-06-27 17:03:13 +02:00
|
|
|
|
describe 'sort order' do
|
|
|
|
|
before do
|
|
|
|
|
Timecop.freeze(4.days.ago) { create(:dossier, user: user) }
|
|
|
|
|
Timecop.freeze(2.days.ago) { create(:dossier, user: user) }
|
2018-10-10 09:23:08 +02:00
|
|
|
|
Timecop.freeze(4.days.ago) { create(:invite, dossier: create(:dossier), user: user) }
|
|
|
|
|
Timecop.freeze(2.days.ago) { create(:invite, dossier: create(:dossier), user: user) }
|
2018-06-27 17:03:13 +02:00
|
|
|
|
get(:index)
|
|
|
|
|
end
|
|
|
|
|
|
|
|
|
|
it 'displays the most recently updated dossiers first' do
|
|
|
|
|
expect(assigns(:user_dossiers).first.updated_at.to_date).to eq(2.days.ago.to_date)
|
|
|
|
|
expect(assigns(:user_dossiers).second.updated_at.to_date).to eq(4.days.ago.to_date)
|
|
|
|
|
expect(assigns(:dossiers_invites).first.updated_at.to_date).to eq(2.days.ago.to_date)
|
|
|
|
|
expect(assigns(:dossiers_invites).second.updated_at.to_date).to eq(4.days.ago.to_date)
|
|
|
|
|
end
|
|
|
|
|
end
|
2023-06-08 17:28:08 +02:00
|
|
|
|
|
|
|
|
|
context 'when the user has a deleted dossier on a discarded procedure' do
|
|
|
|
|
render_views
|
|
|
|
|
|
|
|
|
|
let!(:deleted_dossier) { create(:deleted_dossier, user_id: user.id) }
|
|
|
|
|
|
|
|
|
|
before { deleted_dossier.procedure.discard! }
|
|
|
|
|
|
|
|
|
|
subject { get(:index, params: { statut: 'dossiers-supprimes-definitivement' }) }
|
|
|
|
|
|
|
|
|
|
it { is_expected.to have_http_status(200) }
|
|
|
|
|
end
|
2018-04-03 10:49:16 +02:00
|
|
|
|
end
|
2018-05-24 15:55:47 +02:00
|
|
|
|
|
2018-08-07 11:58:10 +02:00
|
|
|
|
describe '#show' do
|
2018-08-07 16:32:11 +02:00
|
|
|
|
before do
|
|
|
|
|
sign_in(user)
|
|
|
|
|
end
|
|
|
|
|
|
2019-12-16 15:32:59 +01:00
|
|
|
|
context 'with default output' do
|
|
|
|
|
subject! { get(:show, params: { id: dossier.id }) }
|
2018-08-07 11:58:10 +02:00
|
|
|
|
|
2019-12-16 15:32:59 +01:00
|
|
|
|
context 'when the dossier is a brouillon' do
|
|
|
|
|
let(:dossier) { create(:dossier, user: user) }
|
|
|
|
|
it { is_expected.to redirect_to(brouillon_dossier_path(dossier)) }
|
|
|
|
|
end
|
|
|
|
|
|
|
|
|
|
context 'when the dossier has been submitted' do
|
|
|
|
|
let(:dossier) { create(:dossier, :en_construction, user: user) }
|
|
|
|
|
it { expect(assigns(:dossier)).to eq(dossier) }
|
|
|
|
|
it { is_expected.to render_template(:show) }
|
|
|
|
|
end
|
2018-08-07 11:58:10 +02:00
|
|
|
|
end
|
|
|
|
|
|
2019-12-16 15:32:59 +01:00
|
|
|
|
context "with PDF output" do
|
|
|
|
|
let(:procedure) { create(:procedure) }
|
2021-03-09 12:12:28 +01:00
|
|
|
|
let(:dossier) do
|
|
|
|
|
create(:dossier,
|
|
|
|
|
:accepte,
|
2021-11-03 15:52:53 +01:00
|
|
|
|
:with_populated_champs,
|
2021-03-09 12:12:28 +01:00
|
|
|
|
:with_motivation,
|
|
|
|
|
:with_commentaires,
|
|
|
|
|
procedure: procedure,
|
|
|
|
|
user: user)
|
|
|
|
|
end
|
|
|
|
|
|
2019-12-16 15:32:59 +01:00
|
|
|
|
subject! { get(:show, params: { id: dossier.id, format: :pdf }) }
|
|
|
|
|
|
2020-01-29 10:26:26 +01:00
|
|
|
|
context 'when the dossier is a brouillon' do
|
|
|
|
|
let(:dossier) { create(:dossier, user: user) }
|
|
|
|
|
it { is_expected.to redirect_to(brouillon_dossier_path(dossier)) }
|
|
|
|
|
end
|
|
|
|
|
|
|
|
|
|
context 'when the dossier has been submitted' do
|
|
|
|
|
it { expect(assigns(:include_infos_administration)).to eq(false) }
|
|
|
|
|
it { expect(response).to render_template 'dossiers/show' }
|
|
|
|
|
end
|
2018-08-07 11:58:10 +02:00
|
|
|
|
end
|
|
|
|
|
end
|
|
|
|
|
|
2018-08-14 15:06:44 +02:00
|
|
|
|
describe '#formulaire' do
|
|
|
|
|
let(:dossier) { create(:dossier, :en_construction, user: user) }
|
|
|
|
|
|
|
|
|
|
before do
|
|
|
|
|
sign_in(user)
|
|
|
|
|
end
|
|
|
|
|
|
2018-08-29 16:57:01 +02:00
|
|
|
|
subject! { get(:demande, params: { id: dossier.id }) }
|
2018-08-14 15:06:44 +02:00
|
|
|
|
|
|
|
|
|
it { expect(assigns(:dossier)).to eq(dossier) }
|
2018-08-29 16:57:01 +02:00
|
|
|
|
it { is_expected.to render_template(:demande) }
|
2018-08-14 15:06:44 +02:00
|
|
|
|
end
|
|
|
|
|
|
2018-09-05 13:56:12 +02:00
|
|
|
|
describe "#create_commentaire" do
|
2020-04-02 10:18:23 +02:00
|
|
|
|
let(:instructeur_with_instant_message) { create(:instructeur) }
|
|
|
|
|
let(:instructeur_without_instant_message) { create(:instructeur) }
|
|
|
|
|
let(:procedure) { create(:procedure, :published) }
|
2020-04-01 16:23:03 +02:00
|
|
|
|
let(:dossier) { create(:dossier, :en_construction, procedure: procedure, user: user) }
|
2018-09-05 13:56:12 +02:00
|
|
|
|
let(:saved_commentaire) { dossier.commentaires.first }
|
|
|
|
|
let(:body) { "avant\napres" }
|
2020-06-30 17:53:54 +02:00
|
|
|
|
let(:file) { fixture_file_upload('spec/fixtures/files/piece_justificative_0.pdf', 'application/pdf') }
|
2018-09-05 13:56:12 +02:00
|
|
|
|
let(:scan_result) { true }
|
2020-07-22 16:34:33 +02:00
|
|
|
|
let(:now) { Time.zone.parse("18/09/1981") }
|
2018-09-05 13:56:12 +02:00
|
|
|
|
|
|
|
|
|
subject {
|
|
|
|
|
post :create_commentaire, params: {
|
|
|
|
|
id: dossier.id,
|
|
|
|
|
commentaire: {
|
|
|
|
|
body: body,
|
2019-06-25 17:12:44 +02:00
|
|
|
|
piece_jointe: file
|
2018-09-05 13:56:12 +02:00
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
before do
|
2020-07-22 16:34:33 +02:00
|
|
|
|
Timecop.freeze(now)
|
2018-09-05 13:56:12 +02:00
|
|
|
|
sign_in(user)
|
|
|
|
|
allow(ClamavService).to receive(:safe_file?).and_return(scan_result)
|
2020-04-02 10:18:23 +02:00
|
|
|
|
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)
|
2020-07-20 16:13:51 +02:00
|
|
|
|
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)
|
2018-09-05 13:56:12 +02:00
|
|
|
|
end
|
|
|
|
|
|
2020-07-22 16:34:33 +02:00
|
|
|
|
after { Timecop.return }
|
|
|
|
|
|
2020-09-07 15:37:40 +02:00
|
|
|
|
context 'commentaire creation' do
|
|
|
|
|
it "creates a commentaire" do
|
|
|
|
|
expect { subject }.to change(Commentaire, :count).by(1)
|
2018-09-05 13:56:12 +02:00
|
|
|
|
|
2020-09-07 15:37:40 +02:00
|
|
|
|
expect(response).to redirect_to(messagerie_dossier_path(dossier))
|
|
|
|
|
expect(DossierMailer).to have_received(:notify_new_commentaire_to_instructeur).with(dossier, instructeur_with_instant_message.email)
|
|
|
|
|
expect(DossierMailer).not_to have_received(:notify_new_commentaire_to_instructeur).with(dossier, instructeur_without_instant_message.email)
|
|
|
|
|
expect(flash.notice).to be_present
|
|
|
|
|
expect(dossier.reload.last_commentaire_updated_at).to eq(now)
|
|
|
|
|
end
|
|
|
|
|
end
|
|
|
|
|
|
|
|
|
|
context 'notification' do
|
|
|
|
|
before 'instructeurs have no notification before the message' do
|
2020-09-18 15:40:26 +02:00
|
|
|
|
expect(instructeur_with_instant_message.followed_dossiers.with_notifications).to eq([])
|
|
|
|
|
expect(instructeur_without_instant_message.followed_dossiers.with_notifications).to eq([])
|
2020-09-07 15:37:40 +02:00
|
|
|
|
Timecop.travel(now + 1.day)
|
|
|
|
|
subject
|
|
|
|
|
end
|
|
|
|
|
|
|
|
|
|
it 'adds them a notification' do
|
2020-09-18 15:40:26 +02:00
|
|
|
|
expect(instructeur_with_instant_message.reload.followed_dossiers.with_notifications).to eq([dossier.reload])
|
|
|
|
|
expect(instructeur_without_instant_message.reload.followed_dossiers.with_notifications).to eq([dossier.reload])
|
2020-09-07 15:37:40 +02:00
|
|
|
|
end
|
2018-09-05 13:56:12 +02:00
|
|
|
|
end
|
|
|
|
|
end
|
|
|
|
|
|
2022-05-04 08:57:14 +02:00
|
|
|
|
describe "#papertrail" do
|
|
|
|
|
before { sign_in(user) }
|
|
|
|
|
|
|
|
|
|
subject do
|
|
|
|
|
get :papertrail, format: :pdf, params: { id: dossier.id }
|
|
|
|
|
end
|
|
|
|
|
|
|
|
|
|
context 'when the dossier has been submitted' do
|
|
|
|
|
let(:dossier) { create(:dossier, :en_construction, user: user) }
|
|
|
|
|
|
|
|
|
|
it 'renders a PDF document' do
|
|
|
|
|
subject
|
|
|
|
|
expect(response).to render_template(:papertrail)
|
|
|
|
|
end
|
|
|
|
|
end
|
|
|
|
|
|
|
|
|
|
context 'when the dossier is still a draft' do
|
|
|
|
|
let(:dossier) { create(:dossier, :brouillon, user: user) }
|
|
|
|
|
|
|
|
|
|
it 'raises an error' do
|
|
|
|
|
expect { subject }.to raise_error(ActionController::BadRequest)
|
|
|
|
|
end
|
|
|
|
|
end
|
|
|
|
|
end
|
|
|
|
|
|
2023-04-03 20:00:52 +02:00
|
|
|
|
describe '#destroy' do
|
2018-05-24 15:55:47 +02:00
|
|
|
|
before { sign_in(user) }
|
|
|
|
|
|
2023-04-03 20:00:52 +02:00
|
|
|
|
subject { delete :destroy, params: { id: dossier.id } }
|
2018-05-24 15:55:47 +02:00
|
|
|
|
|
2018-06-13 13:58:14 +02:00
|
|
|
|
shared_examples_for "the dossier can not be deleted" do
|
2019-02-06 19:12:04 +01:00
|
|
|
|
it "doesn’t notify the deletion" do
|
2022-02-08 11:19:50 +01:00
|
|
|
|
expect(DossierMailer).not_to receive(:notify_en_construction_deletion_to_administration)
|
2018-06-13 13:58:14 +02:00
|
|
|
|
subject
|
|
|
|
|
end
|
|
|
|
|
|
2019-02-06 19:12:04 +01:00
|
|
|
|
it "doesn’t delete the dossier" do
|
2018-06-13 13:58:14 +02:00
|
|
|
|
subject
|
|
|
|
|
expect(Dossier.find_by(id: dossier.id)).not_to eq(nil)
|
|
|
|
|
expect(dossier.procedure.deleted_dossiers.count).to eq(0)
|
|
|
|
|
end
|
|
|
|
|
end
|
|
|
|
|
|
2018-05-24 15:55:47 +02:00
|
|
|
|
context 'when dossier is owned by signed in user' do
|
2018-08-02 16:36:50 +02:00
|
|
|
|
let(:dossier) { create(:dossier, :en_construction, user: user, autorisation_donnees: true) }
|
2018-05-24 15:55:47 +02:00
|
|
|
|
|
2019-02-06 19:12:04 +01:00
|
|
|
|
it "notifies the user and the admin of the deletion" do
|
2022-02-08 11:19:50 +01:00
|
|
|
|
expect(DossierMailer).to receive(:notify_en_construction_deletion_to_administration).with(kind_of(Dossier), dossier.procedure.administrateurs.first.email).and_return(double(deliver_later: nil))
|
2018-05-24 15:55:47 +02:00
|
|
|
|
subject
|
|
|
|
|
end
|
|
|
|
|
|
2022-02-08 11:19:50 +01:00
|
|
|
|
it "hide the dossier and does not create a deleted dossier" do
|
2018-05-30 11:36:48 +02:00
|
|
|
|
procedure = dossier.procedure
|
|
|
|
|
dossier_id = dossier.id
|
|
|
|
|
subject
|
2022-01-05 10:43:20 +01:00
|
|
|
|
expect(Dossier.find_by(id: dossier_id)).to be_present
|
|
|
|
|
expect(Dossier.find_by(id: dossier_id).hidden_by_user_at).to be_present
|
2022-02-08 11:19:50 +01:00
|
|
|
|
expect(procedure.deleted_dossiers.count).to eq(0)
|
|
|
|
|
end
|
|
|
|
|
|
|
|
|
|
it "fill hidden by reason" do
|
|
|
|
|
subject
|
|
|
|
|
expect(dossier.reload.hidden_by_reason).not_to eq(nil)
|
|
|
|
|
expect(dossier.reload.hidden_by_reason).to eq("user_request")
|
2018-05-30 11:36:48 +02:00
|
|
|
|
end
|
2018-06-13 13:58:14 +02:00
|
|
|
|
|
2018-06-27 14:47:02 +02:00
|
|
|
|
it { is_expected.to redirect_to(dossiers_path) }
|
2018-06-13 13:58:14 +02:00
|
|
|
|
|
|
|
|
|
context "and the instruction has started" do
|
|
|
|
|
let(:dossier) { create(:dossier, :en_instruction, user: user, autorisation_donnees: true) }
|
|
|
|
|
|
|
|
|
|
it_behaves_like "the dossier can not be deleted"
|
2021-12-08 12:27:12 +01:00
|
|
|
|
it { is_expected.to redirect_to(dossiers_path) }
|
2018-06-13 13:58:14 +02:00
|
|
|
|
end
|
2018-05-24 15:55:47 +02:00
|
|
|
|
end
|
|
|
|
|
|
|
|
|
|
context 'when dossier is not owned by signed in user' do
|
|
|
|
|
let(:user2) { create(:user) }
|
|
|
|
|
let(:dossier) { create(:dossier, user: user2, autorisation_donnees: true) }
|
|
|
|
|
|
2018-06-13 13:58:14 +02:00
|
|
|
|
it_behaves_like "the dossier can not be deleted"
|
2018-05-24 15:55:47 +02:00
|
|
|
|
it { is_expected.to redirect_to(root_path) }
|
2023-04-03 20:00:52 +02:00
|
|
|
|
|
|
|
|
|
context 'but user is invited' do
|
|
|
|
|
before { dossier.invites.create(user:, email: user.email, message: 'Salut', email_sender: user2.email) }
|
|
|
|
|
|
|
|
|
|
it do
|
|
|
|
|
procedure = dossier.procedure
|
|
|
|
|
dossier_id = dossier.id
|
|
|
|
|
|
|
|
|
|
expect(user.invite?(dossier)).to be_truthy
|
|
|
|
|
is_expected.to redirect_to(dossiers_path)
|
|
|
|
|
expect(Dossier.find_by(id: dossier_id)).to be_present
|
|
|
|
|
expect(Dossier.find_by(id: dossier_id).hidden_by_user_at).to be_nil
|
|
|
|
|
expect(procedure.deleted_dossiers.count).to eq(0)
|
|
|
|
|
expect(user.invite?(dossier)).to be_falsy
|
|
|
|
|
end
|
|
|
|
|
end
|
2018-05-24 15:55:47 +02:00
|
|
|
|
end
|
|
|
|
|
end
|
2018-11-01 13:00:35 +01:00
|
|
|
|
|
2022-01-05 10:43:20 +01:00
|
|
|
|
describe '#restore' do
|
|
|
|
|
before { sign_in(user) }
|
|
|
|
|
subject { patch :restore, params: { id: dossier.id } }
|
|
|
|
|
|
|
|
|
|
context 'when the user want to restore his dossier' do
|
2022-06-11 12:41:47 +02:00
|
|
|
|
let!(:dossier) { create(:dossier, :accepte, :with_individual, en_construction_at: Time.zone.yesterday.beginning_of_day.utc, hidden_by_user_at: Time.zone.yesterday.beginning_of_day.utc, user: user, autorisation_donnees: true) }
|
2022-01-05 10:43:20 +01:00
|
|
|
|
|
|
|
|
|
before { subject }
|
|
|
|
|
|
|
|
|
|
it 'must have hidden_by_user_at nil' do
|
|
|
|
|
expect(dossier.reload.hidden_by_user_at).to be_nil
|
|
|
|
|
end
|
|
|
|
|
end
|
|
|
|
|
end
|
|
|
|
|
|
2018-11-01 13:00:35 +01:00
|
|
|
|
describe '#new' do
|
|
|
|
|
let(:procedure) { create(:procedure, :published) }
|
|
|
|
|
let(:procedure_id) { procedure.id }
|
2022-11-28 15:42:39 +01:00
|
|
|
|
let(:params) { { procedure_id: procedure_id } }
|
2018-11-01 13:00:35 +01:00
|
|
|
|
|
2022-11-28 15:42:39 +01:00
|
|
|
|
subject { get :new, params: params }
|
2018-11-01 13:00:35 +01:00
|
|
|
|
|
2019-01-14 16:16:23 +01:00
|
|
|
|
it 'clears the stored procedure context' do
|
|
|
|
|
subject
|
|
|
|
|
expect(controller.stored_location_for(:user)).to be nil
|
|
|
|
|
end
|
|
|
|
|
|
2018-11-01 13:00:35 +01:00
|
|
|
|
context 'when params procedure_id is present' do
|
|
|
|
|
context 'when procedure_id is valid' do
|
|
|
|
|
context 'when user is logged in' do
|
|
|
|
|
before do
|
|
|
|
|
sign_in user
|
|
|
|
|
end
|
|
|
|
|
|
|
|
|
|
it { is_expected.to have_http_status(302) }
|
|
|
|
|
it { expect { subject }.to change(Dossier, :count).by 1 }
|
2019-07-31 15:57:37 +02:00
|
|
|
|
context 'when procedure is for entreprise' do
|
|
|
|
|
it { is_expected.to redirect_to siret_dossier_path(id: Dossier.last) }
|
|
|
|
|
end
|
|
|
|
|
|
|
|
|
|
context 'when procedure is for particulier' do
|
|
|
|
|
let(:procedure) { create(:procedure, :published, :for_individual) }
|
|
|
|
|
it { is_expected.to redirect_to identite_dossier_path(id: Dossier.last) }
|
|
|
|
|
end
|
2018-11-01 13:00:35 +01:00
|
|
|
|
|
2019-11-14 09:43:45 +01:00
|
|
|
|
context 'when procedure is closed' do
|
|
|
|
|
let(:procedure) { create(:procedure, :closed) }
|
2018-11-01 13:00:35 +01:00
|
|
|
|
|
|
|
|
|
it { is_expected.to redirect_to dossiers_path }
|
|
|
|
|
end
|
|
|
|
|
end
|
|
|
|
|
context 'when user is not logged' do
|
|
|
|
|
it { is_expected.to have_http_status(302) }
|
|
|
|
|
it { is_expected.to redirect_to new_user_session_path }
|
|
|
|
|
end
|
|
|
|
|
end
|
|
|
|
|
|
|
|
|
|
context 'when procedure_id is not valid' do
|
|
|
|
|
let(:procedure_id) { 0 }
|
|
|
|
|
|
|
|
|
|
before do
|
|
|
|
|
sign_in user
|
|
|
|
|
end
|
|
|
|
|
|
|
|
|
|
it { is_expected.to redirect_to dossiers_path }
|
|
|
|
|
end
|
|
|
|
|
|
|
|
|
|
context 'when procedure is not published' do
|
|
|
|
|
let(:procedure) { create(:procedure) }
|
|
|
|
|
|
|
|
|
|
before do
|
|
|
|
|
sign_in user
|
|
|
|
|
end
|
|
|
|
|
|
|
|
|
|
it { is_expected.to redirect_to dossiers_path }
|
|
|
|
|
|
|
|
|
|
context 'and brouillon param is passed' do
|
|
|
|
|
subject { get :new, params: { procedure_id: procedure_id, brouillon: true } }
|
|
|
|
|
|
|
|
|
|
it { is_expected.to have_http_status(302) }
|
|
|
|
|
it { is_expected.to redirect_to siret_dossier_path(id: Dossier.last) }
|
|
|
|
|
end
|
|
|
|
|
end
|
|
|
|
|
end
|
|
|
|
|
end
|
2018-11-08 10:19:52 +01:00
|
|
|
|
|
2019-03-13 16:48:38 +01:00
|
|
|
|
describe "#dossier_for_help" do
|
|
|
|
|
before do
|
|
|
|
|
sign_in(user)
|
|
|
|
|
controller.params[:dossier_id] = dossier_id.to_s
|
|
|
|
|
end
|
|
|
|
|
|
|
|
|
|
subject { controller.dossier_for_help }
|
|
|
|
|
|
|
|
|
|
context 'when the id matches an existing dossier' do
|
|
|
|
|
let(:dossier) { create(:dossier) }
|
|
|
|
|
let(:dossier_id) { dossier.id }
|
|
|
|
|
|
|
|
|
|
it { is_expected.to eq dossier }
|
|
|
|
|
end
|
|
|
|
|
|
|
|
|
|
context 'when the id doesn’t match an existing dossier' do
|
|
|
|
|
let(:dossier_id) { 9999999 }
|
|
|
|
|
it { is_expected.to be nil }
|
|
|
|
|
end
|
|
|
|
|
|
|
|
|
|
context 'when the id is empty' do
|
|
|
|
|
let(:dossier_id) { nil }
|
|
|
|
|
it { is_expected.to be_falsy }
|
|
|
|
|
end
|
|
|
|
|
end
|
2021-11-19 15:14:39 +01:00
|
|
|
|
|
|
|
|
|
describe '#index' do
|
|
|
|
|
before do
|
|
|
|
|
sign_in(user)
|
|
|
|
|
end
|
|
|
|
|
it 'works' do
|
|
|
|
|
get :index
|
|
|
|
|
expect(response).to have_http_status(:ok)
|
|
|
|
|
end
|
|
|
|
|
end
|
2021-12-03 16:09:51 +01:00
|
|
|
|
|
|
|
|
|
describe '#extend_conservation' do
|
|
|
|
|
let(:procedure) { create(:procedure, duree_conservation_dossiers_dans_ds: 3) }
|
|
|
|
|
let(:dossier) { create(:dossier, procedure: procedure, user: user) }
|
|
|
|
|
subject { post :extend_conservation, params: { dossier_id: dossier.id } }
|
|
|
|
|
context 'when user logged in' do
|
|
|
|
|
before { sign_in(user) }
|
|
|
|
|
it 'works' do
|
|
|
|
|
expect(subject).to redirect_to(dossier_path(dossier))
|
|
|
|
|
end
|
|
|
|
|
|
|
|
|
|
it 'extends conservation_extension by duree_conservation_dossiers_dans_ds' do
|
|
|
|
|
subject
|
|
|
|
|
expect(dossier.reload.conservation_extension).to eq(procedure.duree_conservation_dossiers_dans_ds.months)
|
|
|
|
|
end
|
|
|
|
|
|
|
|
|
|
it 'flashed notice success' do
|
|
|
|
|
subject
|
|
|
|
|
expect(flash[:notice]).to eq(I18n.t('views.users.dossiers.archived_dossier', duree_conservation_dossiers_dans_ds: procedure.duree_conservation_dossiers_dans_ds))
|
|
|
|
|
end
|
|
|
|
|
end
|
|
|
|
|
|
|
|
|
|
context 'when not logged in' do
|
|
|
|
|
it 'fails' do
|
2022-12-01 11:17:48 +01:00
|
|
|
|
subject
|
|
|
|
|
expect { expect(response).to redirect_to(new_user_session_path) }
|
|
|
|
|
end
|
2021-12-03 16:09:51 +01:00
|
|
|
|
end
|
|
|
|
|
end
|
2022-11-08 16:26:03 +01:00
|
|
|
|
|
|
|
|
|
describe '#clone' do
|
|
|
|
|
let(:procedure) { create(:procedure, :with_all_champs) }
|
|
|
|
|
let(:dossier) { create(:dossier, procedure: procedure) }
|
|
|
|
|
subject { post :clone, params: { id: dossier.id } }
|
|
|
|
|
|
|
|
|
|
context 'not signed in' do
|
|
|
|
|
it { expect(subject).to redirect_to(new_user_session_path) }
|
|
|
|
|
end
|
|
|
|
|
|
|
|
|
|
context 'signed with user dossier' do
|
|
|
|
|
before { sign_in dossier.user }
|
|
|
|
|
|
|
|
|
|
it { expect(subject).to redirect_to(brouillon_dossier_path(Dossier.last)) }
|
|
|
|
|
it { expect { subject }.to change { dossier.user.dossiers.count }.by(1) }
|
|
|
|
|
end
|
|
|
|
|
end
|
2022-12-01 11:17:48 +01:00
|
|
|
|
|
|
|
|
|
private
|
|
|
|
|
|
|
|
|
|
def find_champ_by_stable_id(dossier, stable_id)
|
2023-06-14 11:23:04 +02:00
|
|
|
|
dossier.champs.joins(:type_de_champ).find_by(types_de_champ: { stable_id: stable_id })
|
2022-12-01 11:17:48 +01:00
|
|
|
|
end
|
2017-06-29 14:18:12 +02:00
|
|
|
|
end
|