Merge branch 'dev'

This commit is contained in:
gregoirenovel 2018-11-15 16:20:49 +01:00
commit c24c542cb0
19 changed files with 167 additions and 133 deletions

View file

@ -74,11 +74,13 @@ jobs:
DATABASE_URL: "postgres://tps_test@localhost:5432/tps_test"
name: Run Tests, Splitted by Timings
command: |
bundle exec rspec --profile 10 \
COMMAND="bundle exec rspec --profile 10 \
--format RspecJunitFormatter \
--out ~/test_results/rspec.xml \
--format progress \
$(circleci tests glob "spec/**/*_spec.rb" | circleci tests split --split-by=timings)
$(circleci tests glob "spec/**/*_spec.rb" | circleci tests split --split-by=timings)"
echo $COMMAND
eval $COMMAND
- store_test_results:
path: ~/test_results/rspec.xml
lint:

View file

@ -37,7 +37,7 @@
.close-icon {
vertical-align: top;
margin-top: 12px;
margin-left: 6px;
margin-right: 6px;
display: inline-block;
}
}

View file

@ -1,5 +1,8 @@
class InvitesController < ApplicationController
before_action :ensure_user_signed_in
SESSION_USER_RETURN_LOCATION = 'user_return_to'
before_action :authenticate_user!, only: [:create]
before_action :store_user_location!, only: [:show]
def create
email = params[:invite_email].downcase
@ -30,11 +33,35 @@ class InvitesController < ApplicationController
end
end
def show
if user_signed_in?
erase_user_location!
dossier = Dossier.joins(:invites)
.find_by!(invites: { email: current_user.email, id: params[:id] })
if dossier.brouillon?
redirect_to brouillon_dossier_path(dossier)
else
redirect_to dossier_path(dossier)
end
elsif params[:email].present? && !User.find_by(email: params[:email])
redirect_to new_user_registration_path(user: { email: params[:email] })
else
authenticate_user!
end
rescue ActiveRecord::RecordNotFound
flash.alert = t('errors.messages.dossier_not_found')
redirect_to dossiers_path
end
private
def ensure_user_signed_in
if !user_signed_in?
return redirect_to root_path
end
def store_user_location!
store_location_for(:user, request.fullpath)
end
def erase_user_location!
session.delete(SESSION_USER_RETURN_LOCATION)
end
end

View file

@ -1,26 +0,0 @@
class Users::Dossiers::InvitesController < UsersController
def authenticate_user!
session["user_return_to"] = request.fullpath
email = params[:email]
if email.present? && User.find_by(email: email).nil?
redirect_to new_user_registration_path(user: { email: email })
else
super
end
end
def show
invite = Invite.where(email: current_user.email, id: params[:id].to_i).first!
dossier = invite.dossier
if dossier.brouillon?
redirect_to brouillon_dossier_path(dossier)
else
redirect_to dossier_path(dossier)
end
rescue ActiveRecord::RecordNotFound
flash.alert = t('errors.messages.dossier_not_found')
redirect_to url_for dossiers_path
end
end

View file

@ -426,6 +426,7 @@ class Procedure < ApplicationRecord
def percentile_time(start_attribute, end_attribute, p)
times = dossiers
.state_termine
.where(end_attribute => 1.month.ago..DateTime.current)
.pluck(start_attribute, end_attribute)
.map { |(start_date, end_date)| end_date - start_date }

View file

@ -6,9 +6,9 @@
end
%table#features
- Flipflop.feature_set.features.each do |feature|
- if !feature.group || feature.group.key != :production
%tr
%td= feature.title
%td
= check_box_tag "enable-feature", "enable", field.data[feature.name], data: { url: url, key: feature.key }
- admin_features = Flipflop.feature_set.features.reject{ |f| f.group.try(:key) == :production }
- admin_features.each do |feature|
%tr
%td= feature.title
%td
= check_box_tag "enable-feature", "enable", field.data[feature.name], data: { url: url, key: feature.key }

View file

@ -13,7 +13,7 @@
Afin de répondre à cette invitation, merci de vous inscrire avec l'adresse email
= @invite.email
sur
= users_dossiers_invite_url(@invite.id, params: { email: @invite.email })
= invite_url(@invite, params: { email: @invite.email })
%p
Bonne journée,

View file

@ -8,7 +8,7 @@
%p
Pour le consulter, merci de suivre ce lien :
= users_dossiers_invite_url(@invite.id)
= invite_url(@invite)
%p
Bonne journée,

View file

@ -12,6 +12,6 @@
%p Vous pouvez inviter quelquun à remplir ce dossier avec vous.
%p Cette personne aura le droit de modifier votre dossier.
= form_tag invites_dossier_path(dossier_id: dossier.id), remote: true, method: :post, class: 'form' do
= form_tag dossier_invites_path(dossier), remote: true, method: :post, class: 'form' do
= email_field_tag :invite_email, '', class: 'small', placeholder: 'adresse email', required: true
= submit_tag 'Envoyer une invitation', class: 'button accepted'

View file

@ -59,10 +59,9 @@
- @current_filters.each do |filter|
%span.filter
= "#{filter['label']} : #{filter['value']}"
= link_to remove_filter_gestionnaire_procedure_path(@procedure, statut: @statut, table: filter['table'], column: filter['column']) do
%img.close-icon{ src: image_url("close.svg") }
= "#{filter['label'].truncate(50)} : #{filter['value']}"
%table.table.dossiers-table.hoverable
%thead
%tr

View file

@ -27,8 +27,7 @@ Flipflop.configure do
default: ENV['FOG_ENABLED'] == 'enabled'
feature :weekly_overview,
default: ENV['APP_NAME'] == 'tps'
feature :pre_maintenance_mode
feature :maintenance_mode
end
feature :pre_maintenance_mode
feature :maintenance_mode
end

View file

@ -0,0 +1,6 @@
fr:
activerecord:
models:
gestionnaire:
one: Instructeur
other: Instructeurs

View file

@ -1,5 +1,9 @@
fr:
activerecord:
models:
procedure:
one: Démarche
other: Démarches
attributes:
procedure:
path: Lien public

View file

@ -144,10 +144,6 @@ Rails.application.routes.draw do
#
namespace :users do
namespace :dossiers do
resources :invites, only: [:index, :show]
end
resources :dossiers, only: [] do
post '/carte/zones' => 'carte#zones'
get '/carte' => 'carte#show'
@ -159,6 +155,7 @@ Rails.application.routes.draw do
# Redirection of legacy "/users/dossiers" route to "/dossiers"
get 'dossiers', to: redirect('/dossiers')
get 'dossiers/:id/recapitulatif', to: redirect('/dossiers/%{id}')
get 'dossiers/invites/:id', to: redirect(path: '/invites/%{id}')
end
namespace :gestionnaire do
@ -241,8 +238,10 @@ Rails.application.routes.draw do
get 'address/suggestions' => 'address#suggestions'
get 'address/geocode' => 'address#geocode'
namespace :invites do
post 'dossier/:dossier_id' => '/invites#create', as: 'dossier'
resources :invites, only: [:show] do
collection do
post 'dossier/:dossier_id', to: 'invites#create', as: :dossier
end
end
#

View file

@ -158,4 +158,81 @@ describe InvitesController, type: :controller do
end
end
end
describe '#GET show' do
let(:user) { create :user }
context "when invite without email exists" do
let(:invite) { create(:invite, dossier: dossier) }
subject { get :show, params: { id: invite.id, email: email } }
context 'when email is not set' do
let(:email) { nil }
context 'and user is not connected' do
it { is_expected.to redirect_to new_user_session_path }
end
context 'and user is connected' do
let(:invite) { create :invite, dossier: dossier, user: user }
before { sign_in user }
it { is_expected.to redirect_to(dossier_path(dossier)) }
end
end
context 'when email is blank' do
let(:email) { '' }
it { is_expected.to redirect_to new_user_session_path }
end
context 'when email is not blank' do
context 'when email is affected at an user' do
let(:email) { user.email }
it { is_expected.to redirect_to new_user_session_path }
end
context 'when email is not affected at an user' do
let(:email) { 'new_user@octo.com' }
it { is_expected.to redirect_to new_user_registration_path(user: { email: email }) }
end
end
end
context "when invite with email exists" do
let(:invite) { create :invite, email: email, dossier: dossier }
before do
sign_in user
end
subject! { get :show, params: { id: invite.id } }
context 'when invitation ID is attached at the user email account' do
let(:email) { user.email }
context 'and dossier is a brouillon' do
let(:dossier) { create :dossier, state: Dossier.states.fetch(:brouillon) }
it { is_expected.to redirect_to brouillon_dossier_path(dossier) }
end
context 'and dossier is not a brouillon' do
let(:dossier) { create :dossier, :en_construction }
it { is_expected.to redirect_to(dossier_path(dossier)) }
end
end
context 'when invitation ID is not attached at the user email account' do
let(:email) { 'fake@email.com' }
it { is_expected.to redirect_to dossiers_path }
it { expect(flash[:alert]).to be_present }
end
end
end
end

View file

@ -1,72 +0,0 @@
describe Users::Dossiers::InvitesController, type: :controller do
describe '#authenticate_user!' do
let(:user) { create :user }
let(:dossier) { create(:dossier, :en_construction) }
let(:invite) { create(:invite, dossier: dossier) }
subject { get :show, params: { id: invite.id, email: email } }
context 'when email is not set' do
let(:email) { nil }
context 'and user is not connected' do
it { is_expected.to redirect_to new_user_session_path }
end
context 'and user is connected' do
let(:invite) { create :invite, dossier: dossier, user: user }
before { sign_in invite.user }
it { is_expected.to redirect_to(dossier_path(dossier)) }
end
end
context 'when email is blank' do
let(:email) { '' }
it { is_expected.to redirect_to new_user_session_path }
end
context 'when email is not blank' do
context 'when email is affected at an user' do
let(:email) { user.email }
it { is_expected.to redirect_to new_user_session_path }
end
context 'when email is not affected at an user' do
let(:email) { 'new_user@octo.com' }
it { is_expected.to redirect_to new_user_registration_path(user: { email: email }) }
end
end
end
describe '#GET show' do
let(:user) { create :user }
let(:dossier) { create :dossier }
let(:invite) { create :invite, email: email, dossier: dossier }
before do
sign_in user
end
subject! { get :show, params: { id: invite.id } }
context 'when invitation ID is attached at the user email account' do
let(:email) { user.email }
context 'and dossier is a brouillon' do
let(:dossier) { create :dossier, state: Dossier.states.fetch(:brouillon) }
it { is_expected.to redirect_to brouillon_dossier_path(dossier) }
end
context 'and dossier is not a brouillon' do
let(:dossier) { create :dossier, :en_construction }
it { is_expected.to redirect_to(dossier_path(dossier)) }
end
end
context 'when invitation ID is not attached at the user email account' do
let(:email) { 'fake@email.com' }
it { is_expected.to redirect_to dossiers_path }
it { expect(flash[:alert]).to be_present }
end
end
end

View file

@ -31,7 +31,7 @@ feature 'Invitations' do
scenario 'an invited user can register using the registration link sent in the invitation email' do
# Click the invitation link
visit users_dossiers_invite_path(invite.id, params: { email: invite.email })
visit invite_path(invite, params: { email: invite.email })
expect(page).to have_current_path(new_user_registration_path, ignore_query: true)
expect(page).to have_field('user_email', with: invite.email)
@ -115,7 +115,7 @@ feature 'Invitations' do
end
def navigate_to_invited_dossier(invite)
visit users_dossiers_invite_path(invite)
visit invite_path(invite)
expect(page).to have_current_path(new_user_session_path)
sign_in_with(invited_user.email, invited_user.password)
end

View file

@ -626,6 +626,7 @@ describe Procedure do
describe "#export_filename" do
before { Timecop.freeze(Time.zone.local(2018, 1, 2, 23, 11, 14)) }
after { Timecop.return }
subject { procedure.export_filename }
@ -708,12 +709,14 @@ describe Procedure do
describe '#usual_instruction_time' do
let(:procedure) { create(:procedure) }
def create_dossier(instruction_date:, processed_date:)
dossier = create(:dossier, :accepte, procedure: procedure)
dossier.update!(en_instruction_at: instruction_date, processed_at: processed_date)
end
before do
processed_delays.each do |delay|
dossier = create :dossier, :accepte, procedure: procedure
instruction_date = 1.month.ago
processed_date = instruction_date + delay
dossier.update!(en_instruction_at: instruction_date, processed_at: processed_date)
create_dossier(instruction_date: 1.week.ago - delay, processed_date: 1.week.ago)
end
end
@ -725,9 +728,18 @@ describe Procedure do
end
end
context 'when there are very old dossiers' do
let(:processed_delays) { [2.days, 2.days] }
let!(:old_dossier) { create_dossier(instruction_date: 3.months.ago, processed_date: 2.months.ago) }
it 'ignores dossiers older than 1 month' do
expect(procedure.usual_instruction_time).to be_within(10.seconds).of(2.days)
end
end
context 'when there is only one processed dossier' do
let(:processed_delays) { [1.day] }
it { expect(procedure.usual_instruction_time).to eq(1.day) }
it { expect(procedure.usual_instruction_time).to be_within(10.seconds).of(1.day) }
end
context 'where there is no processed dossier' do

View file

@ -81,6 +81,7 @@ end
DatabaseCleaner.strategy = :transaction
TPS::Application.load_tasks
Rake.application.options.trace = false
include Warden::Test::Helpers
@ -103,6 +104,11 @@ RSpec.configure do |config|
config.infer_spec_type_from_file_location!
config.tty = true
# Since rspec 3.8.0, bisect uses fork to improve bisection speed.
# This however fails as soon as we're running feature tests (which uses many processes).
# Default to the :shell bisect runner, so that bisecting over feature tests works.
config.bisect_runner = :shell
config.include Shoulda::Matchers::ActiveRecord, type: :model
config.include Shoulda::Matchers::ActiveModel, type: :model
config.include Shoulda::Matchers::Independent, type: :model