From 94736e4f270859de044a8117f2e0c47407f0dd24 Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Wed, 18 Dec 2019 23:28:28 +0000 Subject: [PATCH 1/4] build(deps): bump rack from 2.0.7 to 2.0.8 Bumps [rack](https://github.com/rack/rack) from 2.0.7 to 2.0.8. - [Release notes](https://github.com/rack/rack/releases) - [Changelog](https://github.com/rack/rack/blob/master/CHANGELOG.md) - [Commits](https://github.com/rack/rack/compare/2.0.7...2.0.8) Signed-off-by: dependabot[bot] --- Gemfile.lock | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Gemfile.lock b/Gemfile.lock index b74054adf..98b4576bf 100644 --- a/Gemfile.lock +++ b/Gemfile.lock @@ -446,7 +446,7 @@ GEM puma (3.12.2) pundit (2.0.1) activesupport (>= 3.0.0) - rack (2.0.7) + rack (2.0.8) rack-attack (6.0.0) rack (>= 1.0, < 3) rack-mini-profiler (1.0.1) From c7a307553c2c334904fa2caedf387bf9a1a000eb Mon Sep 17 00:00:00 2001 From: Pierre de La Morinerie Date: Thu, 19 Dec 2019 13:22:40 +0100 Subject: [PATCH 2/4] helpers: allow `dossier_display_state` to take a state as input This allow to use either: - `dossier_display_state(dossier)` - `dossier_display_state(:en_construction)` --- app/helpers/dossier_helper.rb | 7 ++++--- spec/helpers/dossier_helper_spec.rb | 31 +++++++---------------------- 2 files changed, 11 insertions(+), 27 deletions(-) diff --git a/app/helpers/dossier_helper.rb b/app/helpers/dossier_helper.rb index e279f199b..f4dabce51 100644 --- a/app/helpers/dossier_helper.rb +++ b/app/helpers/dossier_helper.rb @@ -47,9 +47,10 @@ module DossierHelper dossier.brouillon? && dossier.procedure.close? end - def dossier_display_state(dossier, lower: false) - state = I18n.t(dossier.state, scope: [:activerecord, :attributes, :dossier, :state]) - lower ? state.downcase : state + def dossier_display_state(dossier_or_state, lower: false) + state = dossier_or_state.is_a?(Dossier) ? dossier_or_state.state : dossier_or_state + display_state = I18n.t(state, scope: [:activerecord, :attributes, :dossier, :state]) + lower ? display_state.downcase : display_state end def dossier_legacy_state(dossier) diff --git a/spec/helpers/dossier_helper_spec.rb b/spec/helpers/dossier_helper_spec.rb index e327ca095..2296235f9 100644 --- a/spec/helpers/dossier_helper_spec.rb +++ b/spec/helpers/dossier_helper_spec.rb @@ -132,37 +132,20 @@ RSpec.describe DossierHelper, type: :helper do expect(subject).to eq('Refusé') end - context "lower: true" do + context 'when requesting lowercase' do subject { dossier_display_state(dossier, lower: true) } - it 'brouillon is brouillon' do + it 'lowercases the display name' do dossier.brouillon! expect(subject).to eq('brouillon') end + end - it 'en_construction is En construction' do - dossier.en_construction! - expect(subject).to eq('en construction') - end + context 'when providing directly a state name' do + subject { dossier_display_state(:brouillon) } - it 'accepte is traité' do - dossier.accepte! - expect(subject).to eq('accepté') - end - - it 'en_instruction is reçu' do - dossier.en_instruction! - expect(subject).to eq('en instruction') - end - - it 'sans_suite is traité' do - dossier.sans_suite! - expect(subject).to eq('sans suite') - end - - it 'refuse is traité' do - dossier.refuse! - expect(subject).to eq('refusé') + it 'generates a display name for the given state' do + expect(subject).to eq('Brouillon') end end end From 8eb295d67e32af510d9658103b4eb6d6b51de3cf Mon Sep 17 00:00:00 2001 From: Pierre de La Morinerie Date: Thu, 19 Dec 2019 13:25:32 +0100 Subject: [PATCH 3/4] dossiers: avoid exceptions on invalid AASM transitions When attempting an invalid transition on a dossier, provide a meaningful error message (instead of letting an `AASM::InvalidTransition` exception propagate). This handles not only the case where the same state is applied twice (which was already handled manually), but all cases where the transition is invalid. --- .../instructeurs/dossiers_controller.rb | 35 ++++++++++++------- .../instructeurs/dossiers_controller_spec.rb | 29 ++++++++++++--- 2 files changed, 47 insertions(+), 17 deletions(-) diff --git a/app/controllers/instructeurs/dossiers_controller.rb b/app/controllers/instructeurs/dossiers_controller.rb index e02d91a49..caa08f48a 100644 --- a/app/controllers/instructeurs/dossiers_controller.rb +++ b/app/controllers/instructeurs/dossiers_controller.rb @@ -88,33 +88,33 @@ module Instructeurs end def passer_en_instruction - if dossier.en_instruction? - flash.notice = 'Le dossier est déjà en instruction.' - else + begin dossier.passer_en_instruction!(current_instructeur) flash.notice = 'Dossier passé en instruction.' + rescue AASM::InvalidTransition => e + flash.alert = aasm_error_message(e, target_state: :en_instruction) end render partial: 'state_button_refresh', locals: { dossier: dossier } end def repasser_en_construction - if dossier.en_construction? - flash.notice = 'Le dossier est déjà en construction.' - else + begin dossier.repasser_en_construction!(current_instructeur) flash.notice = 'Dossier repassé en construction.' + rescue AASM::InvalidTransition => e + flash.alert = aasm_error_message(e, target_state: :en_construction) end render partial: 'state_button_refresh', locals: { dossier: dossier } end def repasser_en_instruction - if dossier.en_instruction? - flash.notice = 'Le dossier est déjà en instruction.' - else + begin flash.notice = "Le dossier #{dossier.id} a été repassé en instruction." dossier.repasser_en_instruction!(current_instructeur) + rescue AASM::InvalidTransition => e + flash.alert = aasm_error_message(e, target_state: :en_instruction) end render partial: 'state_button_refresh', locals: { dossier: dossier } @@ -124,20 +124,23 @@ module Instructeurs motivation = params[:dossier] && params[:dossier][:motivation] justificatif = params[:dossier] && params[:dossier][:justificatif_motivation] - if dossier.termine? - flash.notice = "Le dossier est déjà #{dossier_display_state(dossier, lower: true)}" - else + begin case params[:process_action] when "refuser" + target_state = :refuse dossier.refuser!(current_instructeur, motivation, justificatif) flash.notice = "Dossier considéré comme refusé." when "classer_sans_suite" + target_state = :sans_suite dossier.classer_sans_suite!(current_instructeur, motivation, justificatif) flash.notice = "Dossier considéré comme sans suite." when "accepter" + target_state = :accepte dossier.accepter!(current_instructeur, motivation, justificatif) flash.notice = "Dossier traité avec succès." end + rescue AASM::InvalidTransition => e + flash.alert = aasm_error_message(e, target_state: target_state) end render partial: 'state_button_refresh', locals: { dossier: dossier } @@ -219,5 +222,13 @@ module Instructeurs def mark_annotations_privees_as_read current_instructeur.mark_tab_as_seen(dossier, :annotations_privees) end + + def aasm_error_message(exception, target_state:) + if exception.originating_state == target_state + "Le dossier est déjà #{dossier_display_state(target_state, lower: true)}." + else + "Le dossier est en ce moment #{dossier_display_state(exception.originating_state, lower: true)} : il n’est pas possible de le passer #{dossier_display_state(target_state, lower: true)}." + end + end end end diff --git a/spec/controllers/instructeurs/dossiers_controller_spec.rb b/spec/controllers/instructeurs/dossiers_controller_spec.rb index 71e808cb1..db3e30ef0 100644 --- a/spec/controllers/instructeurs/dossiers_controller_spec.rb +++ b/spec/controllers/instructeurs/dossiers_controller_spec.rb @@ -112,9 +112,23 @@ describe Instructeurs::DossiersController, type: :controller do context 'when the dossier has already been put en_instruction' do let(:dossier) { create(:dossier, :en_instruction, procedure: procedure) } - it 'warns about the error, but doesn’t raise' do + it 'warns about the error' do expect(dossier.reload.state).to eq(Dossier.states.fetch(:en_instruction)) expect(response).to have_http_status(:ok) + expect(response.body).to have_text('Le dossier est déjà en instruction.') + end + end + + context 'when the dossier has already been closed' do + let(:dossier) { create(:dossier, :accepte, procedure: procedure) } + + it 'doesn’t change the dossier state' do + expect(dossier.reload.state).to eq(Dossier.states.fetch(:accepte)) + end + + it 'warns about the error' do + expect(response).to have_http_status(:ok) + expect(response.body).to have_text('Le dossier est en ce moment accepté : il n’est pas possible de le passer en instruction.') end end end @@ -136,9 +150,10 @@ describe Instructeurs::DossiersController, type: :controller do context 'when the dossier has already been put en_construction' do let(:dossier) { create(:dossier, :en_construction, procedure: procedure) } - it 'warns about the error, but doesn’t raise' do + it 'warns about the error' do expect(dossier.reload.state).to eq(Dossier.states.fetch(:en_construction)) expect(response).to have_http_status(:ok) + expect(response.body).to have_text('Le dossier est déjà en construction.') end end end @@ -161,9 +176,10 @@ describe Instructeurs::DossiersController, type: :controller do context 'when the dossier has already been put en_instruction' do let(:dossier) { create(:dossier, :en_instruction, procedure: procedure) } - it 'warns about the error, but doesn’t raise' do + it 'warns about the error' do expect(dossier.reload.state).to eq(Dossier.states.fetch(:en_instruction)) expect(response).to have_http_status(:ok) + expect(response.body).to have_text('Le dossier est déjà en instruction.') end end @@ -355,15 +371,18 @@ describe Instructeurs::DossiersController, type: :controller do context 'when a dossier is already closed' do let(:dossier) { create(:dossier, :accepte, procedure: procedure) } - before { allow(dossier).to receive(:accepter!) } + before { allow(dossier).to receive(:after_accepter) } subject { post :terminer, params: { process_action: "accepter", procedure_id: procedure.id, dossier_id: dossier.id, dossier: { justificatif_motivation: fake_justificatif } }, format: 'js' } it 'does not close it again' do subject - expect(dossier).not_to have_received(:accepter!) + expect(dossier).not_to have_received(:after_accepter) + expect(dossier.state).to eq(Dossier.states.fetch(:accepte)) + expect(response).to have_http_status(:ok) + expect(response.body).to have_text('Le dossier est déjà accepté.') end end end From a5f2c84cbf02f243a5a4bad74f42671dc404d953 Mon Sep 17 00:00:00 2001 From: Pierre de La Morinerie Date: Thu, 19 Dec 2019 17:45:14 +0100 Subject: [PATCH 4/4] sign_up: fix suggestions error when navigating away MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit When navigating away from the page, the field receives the 'focusout' event – but stops to be present in the DOM. Thus we need to check that the DOM element is actually present. --- app/javascript/new_design/user-sign_up.js | 2 +- app/views/users/registrations/new.html.haml | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/app/javascript/new_design/user-sign_up.js b/app/javascript/new_design/user-sign_up.js index c2a8c4d70..e3c1666b9 100644 --- a/app/javascript/new_design/user-sign_up.js +++ b/app/javascript/new_design/user-sign_up.js @@ -13,7 +13,7 @@ delegate('focusout', userNewEmailSelector, () => { const suggestedEmailSpan = document.querySelector(emailSuggestionSelector); const suggestion = suggest(userEmailInput.value); - if (suggestion && suggestion.full) { + if (suggestion && suggestion.full && suggestedEmailSpan) { suggestedEmailSpan.innerHTML = suggestion.full; show(document.querySelector(suggestionsSelector)); } else { diff --git a/app/views/users/registrations/new.html.haml b/app/views/users/registrations/new.html.haml index 37bcc2387..7a83cc034 100644 --- a/app/views/users/registrations/new.html.haml +++ b/app/views/users/registrations/new.html.haml @@ -8,7 +8,7 @@ = f.label :email, "Email" = f.text_field :email, autofocus: true, placeholder: "Votre adresse email" - .suspect-email + .suspect-email.hidden .email-suggestion-title Voulez-vous dire %span.email-suggestion-address blabla@gmail.com