Merge pull request #2959 from betagouv/dev

2018-11-06-01
This commit is contained in:
LeSim 2018-11-06 17:55:18 +01:00 committed by GitHub
commit 6c1909f66b
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
42 changed files with 417 additions and 295 deletions

View file

@ -467,7 +467,7 @@ GEM
railties (>= 4)
request_store (~> 1.0)
logstash-event (1.2.02)
loofah (2.2.2)
loofah (2.2.3)
crass (~> 1.0.2)
nokogiri (>= 1.5.9)
lumberjack (1.0.13)

View file

@ -0,0 +1,50 @@
module CreateAvisConcern
extend ActiveSupport::Concern
private
def create_avis_from_params(dossier, confidentiel = false)
confidentiel ||= create_avis_params[:confidentiel]
# Because of a limitation of the email_field rails helper,
# the :emails parameter is a 1-element array.
# Hence the call to first
# https://github.com/rails/rails/issues/17225
emails = create_avis_params[:emails].first.split(',').map(&:strip)
create_results = Avis.create(
emails.map do |email|
{
email: email,
introduction: create_avis_params[:introduction],
claimant: current_gestionnaire,
dossier: dossier,
confidentiel: confidentiel
}
end
)
persisted, failed = create_results.partition(&:persisted?)
if persisted.any?
sent_emails_addresses = persisted.map(&:email_to_display).join(", ")
flash.notice = "Une demande d'avis a été envoyée à #{sent_emails_addresses}"
end
if failed.any?
flash.now.alert = failed
.select { |avis| avis.errors.present? }
.map { |avis| "#{avis.email} : #{avis.errors.full_messages.join(', ')}" }
# When an error occurs, return the avis back to the controller
# to give the user a chance to correct and resubmit
Avis.new(create_avis_params.merge(emails: [failed.map(&:email).join(", ")]))
else
nil
end
end
def create_avis_params
params.require(:avis).permit(:introduction, :confidentiel, emails: [])
end
end

View file

@ -1,5 +1,7 @@
module NewGestionnaire
class AvisController < GestionnaireController
include CreateAvisConcern
before_action :authenticate_gestionnaire!, except: [:sign_up, :create_gestionnaire]
before_action :redirect_if_no_sign_up_needed, only: [:sign_up]
before_action :check_avis_exists_and_email_belongs_to_avis, only: [:sign_up, :create_gestionnaire]
@ -60,14 +62,11 @@ module NewGestionnaire
end
def create_avis
confidentiel = avis.confidentiel || params[:avis][:confidentiel]
@new_avis = Avis.new(create_avis_params.merge(claimant: current_gestionnaire, dossier: avis.dossier, confidentiel: confidentiel))
@new_avis = create_avis_from_params(avis.dossier, avis.confidentiel)
if @new_avis.save
flash.notice = "Une demande d'avis a été envoyée à #{@new_avis.email_to_display}"
if @new_avis.nil?
redirect_to instruction_gestionnaire_avis_path(avis)
else
flash.now.alert = @new_avis.errors.full_messages
set_avis_and_dossier
render :instruction
end
@ -141,9 +140,5 @@ module NewGestionnaire
def commentaire_params
params.require(:commentaire).permit(:body, :file)
end
def create_avis_params
params.require(:avis).permit(:email, :introduction)
end
end
end

View file

@ -2,6 +2,7 @@ module NewGestionnaire
class DossiersController < ProceduresController
include ActionView::Helpers::NumberHelper
include ActionView::Helpers::TextHelper
include CreateAvisConcern
after_action :mark_demande_as_read, only: :show
after_action :mark_messagerie_as_read, only: [:messagerie, :create_commentaire]
@ -130,12 +131,11 @@ module NewGestionnaire
end
def create_avis
@avis = Avis.new(avis_params.merge(claimant: current_gestionnaire, dossier: dossier))
if @avis.save
flash.notice = "Une demande d'avis a été envoyée à #{@avis.email_to_display}"
@avis = create_avis_from_params(dossier)
if @avis.nil?
redirect_to avis_gestionnaire_dossier_path(procedure, dossier)
else
flash.now.alert = @avis.errors.full_messages
@avis_seen_at = current_gestionnaire.follows.find_by(dossier: dossier)&.avis_seen_at
render :avis
end
@ -163,10 +163,6 @@ module NewGestionnaire
params.require(:commentaire).permit(:body, :file)
end
def avis_params
params.require(:avis).permit(:email, :introduction, :confidentiel)
end
def champs_private_params
params.require(:dossier).permit(champs_private_attributes: [
:id, :primary_value, :secondary_value, :piece_justificative_file, :value, value: [],

View file

@ -0,0 +1,25 @@
module NewUser
class CommencerController < ApplicationController
def commencer_test
procedure = Procedure.brouillons.find_by(path: params[:path])
if procedure.present?
redirect_to new_dossier_path(procedure_id: procedure.id, brouillon: true)
else
flash.alert = "La démarche est inconnue."
redirect_to root_path
end
end
def commencer
procedure = Procedure.publiees.find_by(path: params[:path])
if procedure.present?
redirect_to new_dossier_path(procedure_id: procedure.id)
else
flash.alert = "La démarche est inconnue, ou la création de nouveaux dossiers pour cette démarche est terminée."
redirect_to root_path
end
end
end
end

View file

@ -2,7 +2,8 @@ module NewUser
class DossiersController < UserController
include DossierHelper
ACTIONS_ALLOWED_TO_ANY_USER = [:index, :recherche]
SESSION_USER_RETURN_LOCATION = 'user_return_to'
ACTIONS_ALLOWED_TO_ANY_USER = [:index, :recherche, :new]
ACTIONS_ALLOWED_TO_OWNER_OR_INVITE = [:show, :demande, :messagerie, :brouillon, :update_brouillon, :modifier, :update, :create_commentaire]
before_action :ensure_ownership!, except: ACTIONS_ALLOWED_TO_ANY_USER + ACTIONS_ALLOWED_TO_OWNER_OR_INVITE
@ -11,6 +12,7 @@ module NewUser
before_action :forbid_invite_submission!, only: [:update_brouillon]
before_action :forbid_closed_submission!, only: [:update_brouillon]
before_action :show_demarche_en_test_banner
before_action :store_user_location!, only: :new
def index
@user_dossiers = current_user.dossiers.includes(:procedure).order_by_updated_at.page(page)
@ -194,7 +196,7 @@ module NewUser
redirect_to dossiers_path
else
flash.notice = "L'instruction de votre dossier a commencé, il n'est plus possible de supprimer votre dossier. Si vous souhaitez annuler l'instruction contactez votre administration par la messagerie de votre dossier."
redirect_to users_dossier_path(dossier)
redirect_to dossier_path(dossier)
end
end
@ -210,8 +212,38 @@ module NewUser
end
end
def new
erase_user_location!
if params[:brouillon]
procedure = Procedure.brouillon.find(params[:procedure_id])
else
procedure = Procedure.publiees.find(params[:procedure_id])
end
dossier = Dossier.create!(procedure: procedure, user: current_user, state: Dossier.states.fetch(:brouillon))
if dossier.procedure.for_individual
redirect_to identite_dossier_path(dossier)
else
redirect_to siret_dossier_path(id: dossier.id)
end
rescue ActiveRecord::RecordNotFound
flash.alert = t('errors.messages.procedure_not_found')
redirect_to url_for dossiers_path
end
private
def store_user_location!
store_location_for(:user, request.fullpath)
end
def erase_user_location!
session.delete(SESSION_USER_RETURN_LOCATION)
end
def show_demarche_en_test_banner
if @dossier.present? && @dossier.procedure.brouillon?
flash.now.notice = "Ce dossier est déposé sur une démarche en test. Il sera supprimé lors de la publication de la démarche."

View file

@ -1,81 +0,0 @@
class Users::DossiersController < UsersController
include SmartListing::Helper::ControllerExtensions
helper SmartListing::Helper
SESSION_USER_RETURN_LOCATION = 'user_return_to'
before_action :store_user_location!, only: :new
before_action :authenticate_user!, except: [:commencer, :commencer_test]
before_action only: [:show] do
authorized_routes? self.class
end
def commencer_test
procedure = Procedure.brouillons.find_by(path: params[:path])
if procedure.present?
redirect_to new_users_dossier_path(procedure_id: procedure.id, brouillon: true)
else
flash.alert = "La démarche est inconnue."
redirect_to root_path
end
end
def commencer
procedure = Procedure.publiees.find_by(path: params[:path])
if procedure.present?
redirect_to new_users_dossier_path(procedure_id: procedure.id)
else
flash.alert = "La démarche est inconnue, ou la création de nouveaux dossiers pour cette démarche est terminée."
redirect_to root_path
end
end
def new
erase_user_location!
if params[:brouillon]
procedure = Procedure.brouillon.find(params[:procedure_id])
else
procedure = Procedure.publiees.find(params[:procedure_id])
end
dossier = Dossier.create!(procedure: procedure, user: current_user, state: Dossier.states.fetch(:brouillon))
if dossier.procedure.for_individual
redirect_to identite_dossier_path(dossier)
else
redirect_to siret_dossier_path(id: dossier.id)
end
rescue ActiveRecord::RecordNotFound
error_procedure
end
def self.route_authorization
{
states: [Dossier.states.fetch(:brouillon)]
}
end
private
def error_procedure
flash.alert = t('errors.messages.procedure_not_found')
redirect_to url_for dossiers_path
end
def facade(id = params[:id])
DossierFacades.new id, current_user.email
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

@ -9,9 +9,9 @@ module ChampHelper
raw({
position: champ.position,
selection: champ.value.present? ? JSON.parse(champ.value) : [],
quartiersPrioritaires: champ.quartiers_prioritaires? ? champ.quartiers_prioritaires : [],
cadastres: champ.cadastres? ? champ.cadastres : [],
parcellesAgricoles: champ.parcelles_agricoles? ? champ.parcelles_agricoles : []
quartiersPrioritaires: champ.quartiers_prioritaires? ? champ.quartiers_prioritaires.as_json(except: :properties) : [],
cadastres: champ.cadastres? ? champ.cadastres.as_json(except: :properties) : [],
parcellesAgricoles: champ.parcelles_agricoles? ? champ.parcelles_agricoles.as_json(except: :properties) : []
}.to_json)
# rubocop:enable Rails/OutputSafety
end

View file

@ -3,7 +3,7 @@ module TypeDeChampHelper
TypeDeChamp.type_champs.fetch(:piece_justificative) => :champ_pj?,
TypeDeChamp.type_champs.fetch(:siret) => :champ_siret?,
TypeDeChamp.type_champs.fetch(:linked_drop_down_list) => :champ_linked_dropdown?,
TypeDeChamp.type_champs.fetch(:carte) => :champ_carte?
TypeDeChamp.type_champs.fetch(:integer_number) => :champ_integer_number?
}
def tdc_options

View file

@ -6,6 +6,7 @@ class Avis < ApplicationRecord
belongs_to :claimant, class_name: 'Gestionnaire'
validates :email, format: { with: Devise.email_regexp, message: "n'est pas valide" }, allow_nil: true
validates :claimant, presence: true
before_validation -> { sanitize_email(:email) }
before_create :try_to_assign_gestionnaire
@ -18,6 +19,10 @@ class Avis < ApplicationRecord
scope :by_latest, -> { order(updated_at: :desc) }
scope :updated_since?, -> (date) { where('avis.updated_at > ?', date) }
# The form allows subtmitting avis requests to several emails at once,
# hence this virtual attribute.
attr_accessor :emails
def email_to_display
gestionnaire&.email || email
end

View file

@ -0,0 +1,7 @@
class Champs::DecimalNumberChamp < Champ
validates :value, numericality: { allow_nil: true }
def value_for_export
value.to_f
end
end

View file

@ -0,0 +1,7 @@
class Champs::IntegerNumberChamp < Champ
validates :value, numericality: { only_integer: true, allow_nil: true }
def value_for_export
value.to_i
end
end

View file

@ -5,6 +5,10 @@ class Champs::YesNoChamp < Champs::CheckboxChamp
end
end
def to_s
value_for_export
end
private
def value_for_export

View file

@ -8,6 +8,8 @@ class TypeDeChamp < ApplicationRecord
date: 'date',
datetime: 'datetime',
number: 'number',
decimal_number: 'decimal_number',
integer_number: 'integer_number',
checkbox: 'checkbox',
civilite: 'civilite',
email: 'email',

View file

@ -0,0 +1,2 @@
class TypesDeChamp::DecimalNumberTypeDeChamp < TypesDeChamp::TypeDeChampBase
end

View file

@ -0,0 +1,2 @@
class TypesDeChamp::IntegerNumberTypeDeChamp < TypesDeChamp::TypeDeChampBase
end

View file

@ -0,0 +1,7 @@
class Champs::DecimalNumberChampSerializer < ChampSerializer
def value
if object.value.present?
object.value.to_f
end
end
end

View file

@ -0,0 +1,7 @@
class Champs::IntegerNumberChampSerializer < ChampSerializer
def value
if object.value.present?
object.value.to_i
end
end
end

View file

@ -2,4 +2,12 @@ class BaseUploader < CarrierWave::Uploader::Base
def cache_dir
Rails.application.secrets.carrierwave[:cache_dir]
end
# https://github.com/carrierwaveuploader/carrierwave/wiki/how-to:-silently-ignore-missing-files-on-destroy-or-overwrite
def remove!
begin
super
rescue Fog::Storage::OpenStack::NotFound
end
end
end

View file

@ -1,9 +1,9 @@
%section.ask-avis
%h1.tab-title Inviter une personne à donner son avis
%p.avis-notice L'invité pourra consulter, donner un avis sur le dossier et contribuer au fil de messagerie, mais il ne pourra le modifier.
%h1.tab-title Inviter des personnes à donner leur avis
%p.avis-notice Les invités pourront consulter, donner un avis sur le dossier et contribuer au fil de messagerie, mais ils ne pourront pas le modifier.
= form_for avis, url: url, html: { class: 'form' } do |f|
= f.email_field :email, placeholder: 'Adresse email', required: true
= f.email_field :emails, placeholder: 'Adresses email, séparées par des virgules', required: true, multiple: true
= f.text_area :introduction, rows: 3, value: avis.introduction || 'Bonjour, merci de me donner votre avis sur ce dossier.', required: true
.flex.justify-between.align-baseline
- if must_be_confidentiel

View file

@ -0,0 +1,4 @@
= form.number_field :value,
step: :any,
placeholder: champ.libelle,
required: champ.mandatory?

View file

@ -0,0 +1,3 @@
= form.number_field :value,
placeholder: champ.libelle,
required: champ.mandatory?

View file

@ -24,7 +24,9 @@ module TPS
config.i18n.load_path += Dir[Rails.root.join('config', 'locales', '**', '*.{rb,yml}')]
config.i18n.available_locales = [:fr]
config.autoload_paths += ["#{config.root}/lib", "#{config.root}/app/validators", "#{config.root}/app/facades"]
config.paths.add "#{config.root}/lib", eager_load: true
config.paths.add "#{config.root}/app/controllers/concerns", eager_load: true
config.assets.paths << Rails.root.join('app', 'assets', 'javascript')
config.assets.paths << Rails.root.join('app', 'assets', 'fonts')
config.assets.precompile += ['.woff']

View file

@ -13,8 +13,8 @@ Flipflop.configure do
title: "Champ SIRET"
feature :champ_linked_dropdown,
title: "Champ double menu déroulant"
feature :champ_carte,
title: "Champ Carte"
feature :champ_integer_number,
title: "Champ nombre entier"
end
feature :web_hook

View file

@ -2,7 +2,7 @@
API_ADRESSE_URL = "https://api-adresse.data.gouv.fr"
API_CARTO_URL = "https://apicarto.sgmap.fr"
API_ENTREPRISE_URL = "https://entreprise.api.gouv.fr/v2"
API_GEO_URL = "https://geo.api.gouv.fr"
API_GEO_URL = ENV.fetch("API_GEO_URL", "https://geo.api.gouv.fr")
API_GEO_SANDBOX_URL = "https://sandbox.geo.api.gouv.fr"
HELPSCOUT_API_URL = "https://api.helpscout.net/v2"
PIPEDRIVE_API_URL = "https://api.pipedrive.com/v1"

View file

@ -10,6 +10,8 @@ fr:
date: 'Date'
datetime: 'Date et Heure'
number: 'Nombre entier'
decimal_number: 'Nombre décimal'
integer_number: 'Nombre entier'
checkbox: 'Case à cocher'
civilite: 'Civilité'
email: 'Email'

View file

@ -127,11 +127,6 @@ Rails.application.routes.draw do
post ':position/carte', to: 'carte#show', as: :carte
end
namespace :commencer do
get '/test/:path' => '/users/dossiers#commencer_test', as: :test
get '/:path' => '/users/dossiers#commencer'
end
get "patron" => "root#patron"
get "contact", to: "support#index"
@ -149,7 +144,7 @@ Rails.application.routes.draw do
resources :invites, only: [:index, :show]
end
resources :dossiers do
resources :dossiers, only: [] do
post '/carte/zones' => 'carte#zones'
get '/carte' => 'carte#show'
post '/carte' => 'carte#save'
@ -267,7 +262,12 @@ Rails.application.routes.draw do
#
scope module: 'new_user' do
resources :dossiers, only: [:index, :show] do
namespace :commencer do
get '/test/:path', action: 'commencer_test', as: :test
get '/:path', action: 'commencer'
end
resources :dossiers, only: [:index, :show, :new] do
member do
get 'identite'
patch 'update_identite'

View file

@ -0,0 +1,5 @@
class DropProcedurePaths < ActiveRecord::Migration[5.2]
def change
drop_table :procedure_paths
end
end

View file

@ -10,7 +10,7 @@
#
# It's strongly recommended that you check this file into your version control system.
ActiveRecord::Schema.define(version: 2018_10_30_103913) do
ActiveRecord::Schema.define(version: 2018_10_30_141238) do
# These are extensions that must be enabled in order to support this database
enable_extension "plpgsql"
@ -421,17 +421,6 @@ ActiveRecord::Schema.define(version: 2018_10_30_103913) do
t.index ["type_de_piece_justificative_id"], name: "index_pieces_justificatives_on_type_de_piece_justificative_id"
end
create_table "procedure_paths", id: :serial, force: :cascade do |t|
t.string "path"
t.integer "procedure_id"
t.integer "administrateur_id"
t.datetime "created_at"
t.datetime "updated_at"
t.bigint "test_procedure_id"
t.index ["path"], name: "index_procedure_paths_on_path"
t.index ["test_procedure_id"], name: "index_procedure_paths_on_test_procedure_id"
end
create_table "procedure_presentations", id: :serial, force: :cascade do |t|
t.integer "assign_to_id"
t.jsonb "sort", default: {"order"=>"desc", "table"=>"notifications", "column"=>"notifications"}, null: false
@ -621,8 +610,6 @@ ActiveRecord::Schema.define(version: 2018_10_30_103913) do
add_foreign_key "feedbacks", "users"
add_foreign_key "geo_areas", "champs"
add_foreign_key "initiated_mails", "procedures"
add_foreign_key "procedure_paths", "administrateurs"
add_foreign_key "procedure_paths", "procedures"
add_foreign_key "procedure_presentations", "assign_tos"
add_foreign_key "procedures", "services"
add_foreign_key "received_mails", "procedures"

View file

@ -1,32 +0,0 @@
namespace :dev do
def run_and_stop_if_error(cmd)
sh cmd do |ok, res|
if !ok
abort "#{cmd} failed with result : #{res.exitstatus}"
end
end
end
task :import_db do
filename = "tps_prod_#{1.day.ago.strftime("%d-%m-%Y")}.sql"
local_file = "/tmp/#{filename}"
if !File.exist?(local_file)
run_and_stop_if_error "scp -C db1:/data/backup/#{filename} #{local_file}"
end
dev_env_param = "RAILS_ENV=development"
Rake::Task["db:drop"].invoke(dev_env_param)
Rake::Task["db:create"].invoke(dev_env_param)
run_and_stop_if_error "psql tps_development -f #{local_file}"
Rake::Task["db:migrate"].invoke(dev_env_param)
Rake::Task["db:environment:set"].invoke(dev_env_param)
Rake::Task["db:test:prepare"].invoke
end
task :console do
exec("ssh tps@sgmap_production1 -t 'source /etc/profile && cd current && bundle exec rails c -e production'")
end
end

View file

@ -43,7 +43,6 @@ describe Champs::CarteController, type: :controller do
let(:selection) { [[{ "lat": 48.87442541960633, "lng": 2.3859214782714844 }, { "lat": 48.87273183590832, "lng": 2.3850631713867183 }, { "lat": 48.87081237174292, "lng": 2.3809432983398438 }, { "lat": 48.8712640169951, "lng": 2.377510070800781 }, { "lat": 48.87510283703279, "lng": 2.3778533935546875 }, { "lat": 48.87544154230615, "lng": 2.382831573486328 }, { "lat": 48.87442541960633, "lng": 2.3859214782714844 }]] }
it { expect(response.body).not_to be_nil }
it { expect(response.body).to include('QPCODE1234') }
it { expect(response.body).to include('MultiPolygon') }
it { expect(response.body).to include('[2.38715792094576,48.8723062632126]') }
end

View file

@ -100,24 +100,37 @@ describe NewGestionnaire::AvisController, type: :controller do
describe '#create_avis' do
let!(:previous_avis) { Avis.create(dossier: dossier, claimant: claimant, gestionnaire: gestionnaire, confidentiel: previous_avis_confidentiel) }
let(:email) { 'a@b.com' }
let(:emails) { ['a@b.com'] }
let(:intro) { 'introduction' }
let(:created_avis) { Avis.last }
let!(:old_avis_count) { Avis.count }
before do
post :create_avis, params: { id: previous_avis.id, avis: { email: email, introduction: intro, confidentiel: asked_confidentiel } }
post :create_avis, params: { id: previous_avis.id, avis: { emails: emails, introduction: intro, confidentiel: asked_confidentiel } }
end
context 'when an invalid email' do
let(:previous_avis_confidentiel) { false }
let(:asked_confidentiel) { false }
let(:email) { "toto.fr" }
let(:emails) { ["toto.fr"] }
it { expect(response).to render_template :instruction }
it { expect(flash.alert).to eq(["Email n'est pas valide"]) }
it { expect(flash.alert).to eq(["toto.fr : Email n'est pas valide"]) }
it { expect(Avis.last).to eq(previous_avis) }
end
context 'with multiple emails' do
let(:asked_confidentiel) { false }
let(:previous_avis_confidentiel) { false }
let(:emails) { ["toto.fr,titi@titimail.com"] }
it { expect(response).to render_template :instruction }
it { expect(flash.alert).to eq(["toto.fr : Email n'est pas valide"]) }
it { expect(flash.notice).to eq("Une demande d'avis a été envoyée à titi@titimail.com") }
it { expect(Avis.count).to eq(old_avis_count + 1) }
it { expect(created_avis.email).to eq("titi@titimail.com") }
end
context 'when the previous avis is public' do
let(:previous_avis_confidentiel) { false }
@ -125,7 +138,7 @@ describe NewGestionnaire::AvisController, type: :controller do
let(:asked_confidentiel) { false }
it { expect(created_avis.confidentiel).to be(false) }
it { expect(created_avis.email).to eq(email) }
it { expect(created_avis.email).to eq(emails.last) }
it { expect(created_avis.introduction).to eq(intro) }
it { expect(created_avis.dossier).to eq(previous_avis.dossier) }
it { expect(created_avis.claimant).to eq(gestionnaire) }

View file

@ -308,12 +308,13 @@ describe NewGestionnaire::DossiersController, type: :controller do
describe "#create_avis" do
let(:saved_avis) { dossier.avis.first }
let!(:old_avis_count) { Avis.count }
subject do
post :create_avis, params: {
procedure_id: procedure.id,
dossier_id: dossier.id,
avis: { email: email, introduction: 'intro', confidentiel: true }
avis: { emails: emails, introduction: 'intro', confidentiel: true }
}
end
@ -321,7 +322,7 @@ describe NewGestionnaire::DossiersController, type: :controller do
subject
end
let(:email) { 'email@a.com' }
let(:emails) { ['email@a.com'] }
it { expect(saved_avis.email).to eq('email@a.com') }
it { expect(saved_avis.introduction).to eq('intro') }
@ -331,12 +332,22 @@ describe NewGestionnaire::DossiersController, type: :controller do
it { expect(response).to redirect_to(avis_gestionnaire_dossier_path(dossier.procedure, dossier)) }
context "with an invalid email" do
let(:email) { 'emaila.com' }
let(:emails) { ['emaila.com'] }
it { expect(response).to render_template :avis }
it { expect(flash.alert).to eq(["Email n'est pas valide"]) }
it { expect(flash.alert).to eq(["emaila.com : Email n'est pas valide"]) }
it { expect { subject }.not_to change(Avis, :count) }
end
context 'with multiple emails' do
let(:emails) { ["toto.fr,titi@titimail.com"] }
it { expect(response).to render_template :avis }
it { expect(flash.alert).to eq(["toto.fr : Email n'est pas valide"]) }
it { expect(flash.notice).to eq("Une demande d'avis a été envoyée à titi@titimail.com") }
it { expect(Avis.count).to eq(old_avis_count + 1) }
it { expect(saved_avis.email).to eq("titi@titimail.com") }
end
end
describe "#update_annotations" do

View file

@ -0,0 +1,40 @@
require 'spec_helper'
describe NewUser::CommencerController, type: :controller do
let(:user) { create(:user) }
let(:procedure) { create(:procedure, :published) }
let(:procedure_id) { procedure.id }
describe 'GET #commencer' do
subject { get :commencer, params: { path: path } }
let(:path) { procedure.path }
it { expect(subject.status).to eq 302 }
it { expect(subject).to redirect_to new_dossier_path(procedure_id: procedure.id) }
context 'when procedure path does not exist' do
let(:path) { 'hello' }
it { expect(subject).to redirect_to(root_path) }
end
end
describe 'GET #commencer_test' do
before do
Flipflop::FeatureSet.current.test!.switch!(:publish_draft, true)
end
subject { get :commencer_test, params: { path: path } }
let(:procedure) { create(:procedure, :with_path) }
let(:path) { procedure.path }
it { expect(subject.status).to eq 302 }
it { expect(subject).to redirect_to new_dossier_path(procedure_id: procedure.id, brouillon: true) }
context 'when procedure path does not exist' do
let(:path) { 'hello' }
it { expect(subject).to redirect_to(root_path) }
end
end
end

View file

@ -843,7 +843,7 @@ describe NewUser::DossiersController, type: :controller do
let(:dossier) { create(:dossier, :en_instruction, user: user, autorisation_donnees: true) }
it_behaves_like "the dossier can not be deleted"
it { is_expected.to redirect_to(users_dossier_path(dossier)) }
it { is_expected.to redirect_to(dossier_path(dossier)) }
end
end
@ -855,4 +855,63 @@ describe NewUser::DossiersController, type: :controller do
it { is_expected.to redirect_to(root_path) }
end
end
describe '#new' do
let(:procedure) { create(:procedure, :published) }
let(:procedure_id) { procedure.id }
subject { get :new, params: { procedure_id: procedure_id } }
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 { is_expected.to redirect_to siret_dossier_path(id: Dossier.last) }
it { expect { subject }.to change(Dossier, :count).by 1 }
context 'when procedure is archived' do
let(:procedure) { create(:procedure, :archived) }
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
end

View file

@ -1,99 +0,0 @@
require 'spec_helper'
describe Users::DossiersController, type: :controller do
let(:user) { create(:user) }
let(:procedure) { create(:procedure, :published) }
let(:procedure_id) { procedure.id }
let(:dossier) { create(:dossier, user: user, procedure: procedure) }
let(:dossier_id) { dossier.id }
describe 'GET #new' do
subject { get :new, params: { procedure_id: procedure_id } }
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 { is_expected.to redirect_to siret_dossier_path(id: Dossier.last) }
it { expect { subject }.to change(Dossier, :count).by 1 }
context 'when procedure is archived' do
let(:procedure) { create(:procedure, :archived) }
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
describe 'GET #commencer' do
subject { get :commencer, params: { path: path } }
let(:path) { procedure.path }
it { expect(subject.status).to eq 302 }
it { expect(subject).to redirect_to new_users_dossier_path(procedure_id: procedure.id) }
context 'when procedure path does not exist' do
let(:path) { 'hello' }
it { expect(subject).to redirect_to(root_path) }
end
end
describe 'GET #commencer_test' do
before do
Flipflop::FeatureSet.current.test!.switch!(:publish_draft, true)
end
subject { get :commencer_test, params: { path: path } }
let(:procedure) { create(:procedure, :with_path) }
let(:path) { procedure.path }
it { expect(subject.status).to eq 302 }
it { expect(subject).to redirect_to new_users_dossier_path(procedure_id: procedure.id, brouillon: true) }
context 'when procedure path does not exist' do
let(:path) { 'hello' }
it { expect(subject).to redirect_to(root_path) }
end
end
end

View file

@ -18,6 +18,12 @@ FactoryBot.define do
factory :type_de_champ_number do
type_champ { TypeDeChamp.type_champs.fetch(:number) }
end
factory :type_de_champ_decimal_number do
type_champ { TypeDeChamp.type_champs.fetch(:decimal_number) }
end
factory :type_de_champ_integer_number do
type_champ { TypeDeChamp.type_champs.fetch(:integer_number) }
end
factory :type_de_champ_checkbox do
type_champ { TypeDeChamp.type_champs.fetch(:checkbox) }
end

View file

@ -192,7 +192,7 @@ feature 'The gestionnaire part' do
end
def ask_confidential_avis(to, introduction)
fill_in 'avis_email', with: to
fill_in 'avis_emails', with: to
fill_in 'avis_introduction', with: introduction
select 'confidentiel', from: 'avis_confidentiel'
click_on 'Demander un avis'

View file

@ -0,0 +1,25 @@
require 'spec_helper'
describe Champs::DecimalNumberChamp do
subject { Champs::DecimalNumberChamp.new(value: value) }
describe '#valid?' do
context 'when the value is integer number' do
let(:value) { 2 }
it { is_expected.to be_valid }
end
context 'when the value is decimal number' do
let(:value) { 2.6 }
it { is_expected.to be_valid }
end
context 'when the value is not a number' do
let(:value) { 'toto' }
it { is_expected.to_not be_valid }
end
end
end

View file

@ -0,0 +1,25 @@
require 'spec_helper'
describe Champs::IntegerNumberChamp do
subject { Champs::IntegerNumberChamp.new(value: value) }
describe '#valid?' do
context 'when the value is integer number' do
let(:value) { 2 }
it { is_expected.to be_valid }
end
context 'when the value is decimal number' do
let(:value) { 2.6 }
it { is_expected.to_not be_valid }
end
context 'when the value is not a number' do
let(:value) { 'toto' }
it { is_expected.to_not be_valid }
end
end
end

View file

@ -0,0 +1,23 @@
describe Champs::YesNoChamp do
describe '#to_s' do
subject { Champs::YesNoChamp.new(value: value).to_s }
context 'when the value is false' do
let(:value) { "false" }
it { is_expected.to eq("non") }
end
context 'when the value is true' do
let(:value) { "true" }
it { is_expected.to eq("oui") }
end
context 'when the value is nil' do
let(:value) { nil }
it { is_expected.to eq("non") }
end
end
end

View file

@ -10,25 +10,6 @@ describe UserRoutesAuthorizationService do
subject { described_class.authorized_route? controller, dossier }
describe 'Users::DossiersController' do
let(:controller) { Users::DossiersController }
describe 'brouillon' do
let(:state) { Dossier.states.fetch(:brouillon) }
it { is_expected.to be_truthy }
end
describe 'en_construction' do
let(:state) { Dossier.states.fetch(:en_construction) }
it { is_expected.to be_falsey }
end
describe 'accepte' do
let(:state) { Dossier.states.fetch(:accepte) }
it { is_expected.to be_falsey }
end
end
describe 'carte' do
let(:controller) { Users::CarteController }