Merge pull request #3290 from betagouv/sign-up-procedure-context

[Page de garde] Ajout du contexte de la démarche sur la page de sign-up
This commit is contained in:
Pierre de La Morinerie 2019-01-17 11:20:21 +01:00 committed by GitHub
commit 8d70a67bc2
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
16 changed files with 246 additions and 78 deletions

View file

@ -0,0 +1,34 @@
module ProcedureContextConcern
extend ActiveSupport::Concern
include Devise::Controllers::StoreLocation
include Devise::StoreLocationExtension
def restore_procedure_context
if stored_procedure_id.present?
@procedure = Procedure.publiees.find_by(id: stored_procedure_id)
if @procedure.blank?
invalid_procedure_context
end
end
end
private
def stored_procedure_id
stored_location = get_stored_location_for(:user)
if stored_location.present? && stored_location.include?('procedure_id=')
stored_location.split('procedure_id=').second
else
nil
end
end
def invalid_procedure_context
clear_stored_location_for(:user)
flash.alert = t('errors.messages.procedure_not_found')
redirect_to root_path
end
end

View file

@ -0,0 +1,19 @@
module Devise
# Useful helpers additions to Devise::Controllers::StoreLocation
module StoreLocationExtension
# A variant of `stored_location_key_for` which doesn't delete the stored path.
def get_stored_location_for(resource_or_scope)
location = stored_location_for(resource_or_scope)
if location
store_location_for(resource_or_scope, location)
end
location
end
# Delete the url stored in the session for the given scope.
def clear_stored_location_for(resource_or_scope)
session_key = send(:stored_location_key_for, resource_or_scope)
session.delete(session_key)
end
end
end

View file

@ -1,5 +1,5 @@
class InvitesController < ApplicationController class InvitesController < ApplicationController
SESSION_USER_RETURN_LOCATION = 'user_return_to' include Devise::StoreLocationExtension
before_action :authenticate_user!, only: [:create] before_action :authenticate_user!, only: [:create]
before_action :store_user_location!, only: [:show] before_action :store_user_location!, only: [:show]
@ -62,6 +62,6 @@ class InvitesController < ApplicationController
end end
def erase_user_location! def erase_user_location!
session.delete(SESSION_USER_RETURN_LOCATION) clear_stored_location_for(:user)
end end
end end

View file

@ -1,10 +1,10 @@
module NewUser module NewUser
class DossiersController < UserController class DossiersController < UserController
include Devise::StoreLocationExtension
include DossierHelper include DossierHelper
layout 'procedure_context', only: [:identite, :update_identite, :siret, :update_siret] layout 'procedure_context', only: [:identite, :update_identite, :siret, :update_siret]
SESSION_USER_RETURN_LOCATION = 'user_return_to'
ACTIONS_ALLOWED_TO_ANY_USER = [:index, :recherche, :new] ACTIONS_ALLOWED_TO_ANY_USER = [:index, :recherche, :new]
ACTIONS_ALLOWED_TO_OWNER_OR_INVITE = [:show, :demande, :messagerie, :brouillon, :update_brouillon, :modifier, :update, :create_commentaire, :purge_champ_piece_justificative] ACTIONS_ALLOWED_TO_OWNER_OR_INVITE = [:show, :demande, :messagerie, :brouillon, :update_brouillon, :modifier, :update, :create_commentaire, :purge_champ_piece_justificative]
@ -247,7 +247,7 @@ module NewUser
end end
def erase_user_location! def erase_user_location!
session.delete(SESSION_USER_RETURN_LOCATION) clear_stored_location_for(:user)
end end
def show_demarche_en_test_banner def show_demarche_en_test_banner

View file

@ -1,10 +1,9 @@
class Users::RegistrationsController < Devise::RegistrationsController class Users::RegistrationsController < Devise::RegistrationsController
include ProcedureContextConcern
# before_action :configure_sign_up_params, only: [:create] # before_action :configure_sign_up_params, only: [:create]
# before_action :configure_account_update_params, only: [:update] # before_action :configure_account_update_params, only: [:update]
before_action :restore_procedure_context, only: [:new, :create]
# def after_sign_up_path_for(resource_or_scope)
# super
# end
layout 'procedure_context', only: [:new, :create] layout 'procedure_context', only: [:new, :create]

View file

@ -1,18 +1,15 @@
class Users::SessionsController < Sessions::SessionsController class Users::SessionsController < Sessions::SessionsController
include ProcedureContextConcern
include TrustedDeviceConcern include TrustedDeviceConcern
include ActionView::Helpers::DateHelper include ActionView::Helpers::DateHelper
layout 'procedure_context', only: [:new, :create] layout 'procedure_context', only: [:new, :create]
before_action :restore_procedure_context, only: [:new, :create]
# GET /resource/sign_in # GET /resource/sign_in
def new def new
if user_return_to_procedure_id.present?
@procedure = Procedure.active(user_return_to_procedure_id)
end
@user = User.new @user = User.new
rescue ActiveRecord::RecordNotFound
error_procedure
end end
# POST /resource/sign_in # POST /resource/sign_in
@ -80,7 +77,7 @@ class Users::SessionsController < Sessions::SessionsController
end end
def no_procedure def no_procedure
session['user_return_to'] = nil clear_stored_location_for(:user)
redirect_to new_user_session_path redirect_to new_user_session_path
end end
@ -112,20 +109,6 @@ class Users::SessionsController < Sessions::SessionsController
end end
end end
def error_procedure
session["user_return_to"] = nil
flash.alert = t('errors.messages.procedure_not_found')
redirect_to url_for root_path
end
def user_return_to_procedure_id
if session["user_return_to"].nil?
return nil
end
NumberService.to_number session["user_return_to"].split("?procedure_id=").second
end
def try_to_authenticate(klass, remember_me = false) def try_to_authenticate(klass, remember_me = false)
resource = klass.find_for_database_authentication(email: params[:user][:email]) resource = klass.find_for_database_authentication(email: params[:user][:email])

View file

@ -1,5 +0,0 @@
class NumberService
def self.to_number(string)
string.to_s
end
end

View file

@ -0,0 +1,77 @@
require 'rails_helper'
RSpec.describe ProcedureContextConcern, type: :controller do
class TestController < ActionController::Base
include ProcedureContextConcern
before_action :restore_procedure_context
def index
head :ok
end
end
controller TestController do
end
describe '#restore_procedure_context' do
subject { get :index }
context 'when no return location has been stored' do
it 'succeeds, without defining a procedure on the controller' do
expect(subject.status).to eq 200
expect(assigns(:procedure)).to be nil
end
end
context 'when no procedure_id is present in the stored return location' do
before do
controller.store_location_for(:user, dossiers_path)
end
it 'succeeds, without assigns a procedure on the controller' do
expect(subject.status).to eq 200
expect(assigns(:procedure)).to be nil
end
end
context 'when a procedure location has been stored' do
context 'when the stored procedure does not exist' do
before do
controller.store_location_for(:user, new_dossier_path(procedure_id: '0'))
end
it 'redirects with an error' do
expect(subject.status).to eq 302
expect(subject).to redirect_to root_path
end
end
context 'when the stored procedure is not published' do
let(:procedure) { create :procedure }
before do
controller.store_location_for(:user, new_dossier_path(procedure_id: procedure.id))
end
it 'redirects with an error' do
expect(subject.status).to eq 302
expect(subject).to redirect_to root_path
end
end
context 'when the stored procedure exists' do
let(:procedure) { create :procedure, :published }
before do
controller.store_location_for(:user, new_dossier_path(procedure_id: procedure.id))
end
it 'succeeds, and assigns the procedure on the controller' do
expect(subject.status).to eq 200
expect(assigns(:procedure)).to eq procedure
end
end
end
end
end

View file

@ -0,0 +1,41 @@
require 'rails_helper'
RSpec.describe Devise::StoreLocationExtension, type: :controller do
class TestController < ActionController::Base
include Devise::Controllers::StoreLocation
include Devise::StoreLocationExtension
end
controller TestController do
end
describe '#get_stored_location_for' do
context 'when a location has been previously stored' do
before { subject.store_location_for(:user, dossiers_path) }
it 'returns the stored location without clearing it' do
expect(subject.get_stored_location_for(:user)).to eq dossiers_path
expect(subject.stored_location_for(:user)).to eq dossiers_path
end
end
context 'when no location has been stored' do
it { expect(subject.get_stored_location_for(:user)).to be nil }
end
end
describe "#clear_stored_location_for" do
context 'when a location has been previously stored' do
before { subject.store_location_for(:user, dossiers_path) }
it 'delete the stored location' do
subject.clear_stored_location_for(:user)
expect(subject.stored_location_for(:user)).to be nil
end
end
context 'when no location has been stored' do
it { expect(subject.clear_stored_location_for(:user)).to be nil }
end
end
end

View file

@ -171,7 +171,10 @@ describe InvitesController, type: :controller do
let(:email) { nil } let(:email) { nil }
context 'and user is not connected' do context 'and user is not connected' do
it { is_expected.to redirect_to new_user_session_path } it 'redirects to the sign-in page' do
expect(subject).to redirect_to new_user_session_path
expect(controller.stored_location_for(:user)).to be_present
end
end end
context 'and user is connected' do context 'and user is connected' do
@ -186,20 +189,29 @@ describe InvitesController, type: :controller do
context 'when email is blank' do context 'when email is blank' do
let(:email) { '' } let(:email) { '' }
it { is_expected.to redirect_to new_user_session_path } it 'redirects to the sign-in page' do
expect(subject).to redirect_to new_user_session_path
expect(controller.stored_location_for(:user)).to be_present
end
end end
context 'when email is not blank' do context 'when email is not blank' do
context 'when email is affected at an user' do context 'when email is affected at an user' do
let(:email) { user.email } let(:email) { user.email }
it { is_expected.to redirect_to new_user_session_path } it 'redirects to the sign-in page' do
expect(subject).to redirect_to new_user_session_path
expect(controller.stored_location_for(:user)).to be_present
end
end end
context 'when email is not affected at an user' do context 'when email is not affected at an user' do
let(:email) { 'new_user@octo.com' } let(:email) { 'new_user@octo.com' }
it { is_expected.to redirect_to new_user_registration_path(user: { email: email }) } it 'redirects to the sign-up page' do
expect(subject).to redirect_to new_user_registration_path(user: { email: email })
expect(controller.stored_location_for(:user)).to be_present
end
end end
end end
end end
@ -213,6 +225,10 @@ describe InvitesController, type: :controller do
subject! { get :show, params: { id: invite.id } } subject! { get :show, params: { id: invite.id } }
it 'clears the stored return location' do
expect(controller.stored_location_for(:user)).to be nil
end
context 'when invitation ID is attached at the user email account' do context 'when invitation ID is attached at the user email account' do
let(:email) { user.email } let(:email) { user.email }

View file

@ -854,6 +854,11 @@ describe NewUser::DossiersController, type: :controller do
subject { get :new, params: { procedure_id: procedure_id } } subject { get :new, params: { procedure_id: procedure_id } }
it 'clears the stored procedure context' do
subject
expect(controller.stored_location_for(:user)).to be nil
end
context 'when params procedure_id is present' do context 'when params procedure_id is present' do
context 'when procedure_id is valid' do context 'when procedure_id is valid' do
context 'when user is logged in' do context 'when user is logged in' do

View file

@ -9,17 +9,30 @@ describe Users::RegistrationsController, type: :controller do
end end
describe '#new' do describe '#new' do
subject! { get :new } subject { get :new }
it { expect(response).to have_http_status(:ok) } it { expect(subject).to have_http_status(:ok) }
it { expect(response).to render_template(:new) } it { expect(subject).to render_template(:new) }
context 'when an email address is provided' do context 'when an email address is provided' do
render_views true render_views true
subject! { get :new, params: { user: { email: 'test@exemple.fr' } } } subject { get :new, params: { user: { email: 'test@exemple.fr' } } }
it 'prefills the form with the email address' do it 'prefills the form with the email address' do
expect(response.body).to include('test@exemple.fr') expect(subject.body).to include('test@exemple.fr')
end
end
context 'when a procedure location has been stored' do
let(:procedure) { create :procedure, :published }
before do
controller.store_location_for(:user, new_dossier_path(procedure_id: procedure.id))
end
it 'makes the saved procedure available' do
expect(subject.status).to eq 200
expect(assigns(:procedure)).to eq procedure
end end
end end
end end

View file

@ -173,38 +173,18 @@ describe Users::SessionsController, type: :controller do
describe '#new' do describe '#new' do
subject { get :new } subject { get :new }
context 'when procedure_id is not present in user_return_to session params' do
it { expect(subject.status).to eq 200 } it { expect(subject.status).to eq 200 }
end
context 'when procedure_id is present in user_return_to session params' do context 'when a procedure location has been stored' do
context 'when procedure_id does not exist' do
before do
session["user_return_to"] = '?procedure_id=0'
end
it { expect(subject.status).to eq 302 }
it { expect(subject).to redirect_to root_path }
end
context 'when procedure is not published' do
let(:procedure) { create :procedure }
before do
session["user_return_to"] = "?procedure_id=#{procedure.id}"
end
it { expect(subject.status).to eq 302 }
it { expect(subject).to redirect_to root_path }
end
context 'when procedure_id exist' do
let(:procedure) { create :procedure, :published } let(:procedure) { create :procedure, :published }
before do before do
session["user_return_to"] = "?procedure_id=#{procedure.id}" controller.store_location_for(:user, new_dossier_path(procedure_id: procedure.id))
end end
it { expect(subject.status).to eq 200 } it 'makes the saved procedure available' do
expect(subject.status).to eq 200
expect(assigns(:procedure)).to eq procedure
end end
end end
end end

View file

@ -34,7 +34,7 @@ feature 'Signing up:' do
end end
context 'when visiting a procedure' do context 'when visiting a procedure' do
let(:procedure) { create :simple_procedure } let(:procedure) { create :simple_procedure, :with_service }
before do before do
visit commencer_path(path: procedure.path) visit commencer_path(path: procedure.path)
@ -43,13 +43,14 @@ feature 'Signing up:' do
scenario 'a new user can sign-up and fill the procedure' do scenario 'a new user can sign-up and fill the procedure' do
expect(page).to have_current_path new_user_session_path expect(page).to have_current_path new_user_session_path
click_on 'Créer un compte' click_on 'Créer un compte'
expect_page_to_have_procedure_description(procedure)
sign_up_with user_email, user_password sign_up_with user_email, user_password
expect(page).to have_content "nous avons besoin de vérifier votre adresse #{user_email}" expect(page).to have_content "nous avons besoin de vérifier votre adresse #{user_email}"
click_confirmation_link_for user_email click_confirmation_link_for user_email
expect(page).to have_content 'Votre compte a été activé' expect(page).to have_content 'Votre compte a été activé'
expect(page).to have_content procedure.libelle expect_page_to_have_procedure_description(procedure)
end end
end end

View file

@ -22,15 +22,12 @@ feature 'Signin in:' do
scenario 'an existing user can sign-in and fill the procedure' do scenario 'an existing user can sign-in and fill the procedure' do
expect(page).to have_current_path new_user_session_path expect(page).to have_current_path new_user_session_path
expect(page).to have_content procedure.libelle expect_page_to_have_procedure_description(procedure)
expect(page).to have_content procedure.description
expect(page).to have_content procedure.service.email
sign_in_with user.email, password sign_in_with user.email, password
expect(page).to have_current_path identite_dossier_path(user.reload.dossiers.last) expect(page).to have_current_path identite_dossier_path(user.reload.dossiers.last)
expect(page).to have_content procedure.libelle expect_page_to_have_procedure_description(procedure)
expect(page).to have_content procedure.description
expect(page).to have_content "Données d'identité" expect(page).to have_content "Données d'identité"
end end
end end

View file

@ -50,6 +50,14 @@ module FeatureHelpers
visit "/users/confirmation?#{token_params}" visit "/users/confirmation?#{token_params}"
end end
def expect_page_to_have_procedure_description(procedure)
# Procedure context on the page
expect(page).to have_content(procedure.libelle)
expect(page).to have_content(procedure.description)
# Procedure contact infos in the footer
expect(page).to have_content(procedure.service.email)
end
end end
RSpec.configure do |config| RSpec.configure do |config|