diff --git a/app/controllers/invites_controller.rb b/app/controllers/invites_controller.rb index ee82d2bf3..3c550f6d4 100644 --- a/app/controllers/invites_controller.rb +++ b/app/controllers/invites_controller.rb @@ -1,9 +1,13 @@ class InvitesController < ApplicationController + before_action :gestionnaire_or_user? + def create - email_sender = current_gestionnaire.email + email_sender = @current_devise_profil.email + + class_var = @current_devise_profil.class == User ? InviteUser : InviteGestionnaire user = User.find_by_email(params[:email]) - invite = Invite.create(dossier_id: params[:dossier_id], user: user, email: params[:email].downcase, email_sender: email_sender) + invite = class_var.create(dossier_id: params[:dossier_id], user: user, email: params[:email].downcase, email_sender: email_sender) if invite.valid? InviteMailer.invite_user(invite).deliver_now! unless invite.user.nil? @@ -16,8 +20,17 @@ class InvitesController < ApplicationController if gestionnaire_signed_in? redirect_to url_for(controller: 'backoffice/dossiers', action: :show, id: params['dossier_id']) - # else - # redirect_to url_for(controller: :recapitulatif, action: :show, dossier_id: params['dossier_id']) + else + redirect_to url_for(controller: 'users/recapitulatif', action: :show, dossier_id: params['dossier_id']) end end + + private + + def gestionnaire_or_user? + return redirect_to root_path unless user_signed_in? || gestionnaire_signed_in? + + @current_devise_profil = current_user if user_signed_in? + @current_devise_profil = current_gestionnaire if gestionnaire_signed_in? + end end diff --git a/app/controllers/users/dossiers_controller.rb b/app/controllers/users/dossiers_controller.rb index 891bf600b..bf81eae8c 100644 --- a/app/controllers/users/dossiers_controller.rb +++ b/app/controllers/users/dossiers_controller.rb @@ -10,8 +10,10 @@ class Users::DossiersController < UsersController end def index - cookies[:liste] = params[:liste] || cookies[:liste] || 'a_traiter' - @dossiers_list_facade = DossiersListFacades.new current_user, cookies[:liste] + liste = params[:liste] || cookies[:liste] || 'a_traiter' + cookies[:liste] = liste + + @dossiers_list_facade = DossiersListFacades.new current_user, liste @dossiers = smart_listing_create :dossiers, @dossiers_list_facade.dossiers_to_display, diff --git a/app/controllers/users_controller.rb b/app/controllers/users_controller.rb index 982b2f72c..dfc3689f3 100644 --- a/app/controllers/users_controller.rb +++ b/app/controllers/users_controller.rb @@ -8,7 +8,11 @@ class UsersController < ApplicationController def current_user_dossier dossier_id=nil dossier_id ||= params[:dossier_id] || params[:id] - current_user.dossiers.find(dossier_id) + dossier = Dossier.find(dossier_id) + + return dossier if dossier.owner?(current_user.email) || dossier.invite_by_user?(current_user.email) + + raise ActiveRecord::RecordNotFound end def authorized_routes? controller diff --git a/app/models/dossier.rb b/app/models/dossier.rb index e94ffa375..9306e2e3e 100644 --- a/app/models/dossier.rb +++ b/app/models/dossier.rb @@ -24,6 +24,7 @@ class Dossier < ActiveRecord::Base has_many :cadastres, dependent: :destroy has_many :commentaires, dependent: :destroy has_many :invites, dependent: :destroy + has_many :invites_user, class_name: 'InviteUser', dependent: :destroy has_many :follows belongs_to :procedure @@ -307,4 +308,16 @@ class Dossier < ActiveRecord::Base next_step! 'user', 'submit' NotificationMailer.dossier_submitted(self).deliver_now! end + + def read_only? + validated? || received? || submitted? || closed? || refused? || without_continuation? + end + + def owner? email + user.email == email + end + + def invite_by_user? email + (invites_user.pluck :email).include? email + end end diff --git a/app/models/invite_gestionnaire.rb b/app/models/invite_gestionnaire.rb new file mode 100644 index 000000000..6021286da --- /dev/null +++ b/app/models/invite_gestionnaire.rb @@ -0,0 +1,3 @@ +class InviteGestionnaire < Invite + +end diff --git a/app/models/invite_user.rb b/app/models/invite_user.rb new file mode 100644 index 000000000..05ec141e9 --- /dev/null +++ b/app/models/invite_user.rb @@ -0,0 +1,3 @@ +class InviteUser < Invite + +end diff --git a/app/views/dossiers/_infos_dossier.html.haml b/app/views/dossiers/_infos_dossier.html.haml index 3947d592e..d04d0187f 100644 --- a/app/views/dossiers/_infos_dossier.html.haml +++ b/app/views/dossiers/_infos_dossier.html.haml @@ -41,10 +41,10 @@ %br .row{style: 'text-align:right'} - - if !@facade.dossier.validated? && !@facade.dossier.received? && !@facade.dossier.submitted? && !@facade.dossier.closed? && !@facade.dossier.refused? && !@facade.dossier.without_continuation? - - if user_signed_in? && (current_user.email == @facade.dossier.user.email) + - unless @facade.dossier.read_only? + - if user_signed_in? && (@facade.dossier.owner?(current_user.email) || @facade.dossier.invite_by_user?(current_user.email)) - if @facade.procedure.cerfa_flag? || @facade.dossier.types_de_piece_justificative.size > 0 - %a.btn.btn-success{"data-target" => "#UploadPJmodal", + %a#maj_pj.btn.btn-success{"data-target" => "#UploadPJmodal", "data-toggle" => "modal", :type => "button", style: 'margin-bottom: 15px; margin-top: -30px'} @@ -55,12 +55,12 @@ -if @facade.dossier.procedure.module_api_carto.use_api_carto %a#maj_carte.btn.btn-primary{href: "/users/dossiers/#{@facade.dossier.id}/carte"} - = 'Modifier ma carte' + = 'Modifier la carte' %a#maj_infos.btn.btn-info{href: "/users/dossiers/#{@facade.dossier.id}/description"} - = 'Modifier mon dossier' + = 'Modifier le dossier' -if gestionnaire_signed_in? - -if !@facade.dossier.validated? && !@facade.dossier.received? && !@facade.dossier.submitted? && !@facade.dossier.closed? && !@facade.dossier.refused? && !@facade.dossier.without_continuation? + -if !@facade.dossier.read_only? = form_tag(url_for({controller: 'backoffice/dossiers', action: :valid, dossier_id: @facade.dossier.id}), class: 'form-inline', method: 'POST') do %button#action_button.btn.btn-success = 'Valider le dossier' diff --git a/app/views/dossiers/_invites.html.haml b/app/views/dossiers/_invites.html.haml index 788619476..8328ef5c4 100644 --- a/app/views/dossiers/_invites.html.haml +++ b/app/views/dossiers/_invites.html.haml @@ -12,7 +12,7 @@ Aucune personne invité .col-md-3.col-lg-3 - =form_tag backoffice_dossier_invites_path(dossier_id: @facade.dossier.id), method: :post, class: 'form-inline' do + =form_tag invites_dossier_path(dossier_id: @facade.dossier.id), method: :post, class: 'form-inline' do =text_field_tag :email, '', class: 'form-control', placeholder: 'Envoyer une invitation' =submit_tag 'Ajouter', class: 'btn btn-success' diff --git a/app/views/dossiers/_tab_objects_dossier.html.haml b/app/views/dossiers/_tab_objects_dossier.html.haml index a478f0dbe..b95c33a60 100644 --- a/app/views/dossiers/_tab_objects_dossier.html.haml +++ b/app/views/dossiers/_tab_objects_dossier.html.haml @@ -6,10 +6,12 @@ %a{href: "#commentaires_files", 'aria-controls' => "commentaires_files", role: "tab", 'data-toggle' => "tab"} Fichiers - - if gestionnaire_signed_in? + - if gestionnaire_signed_in? || @facade.dossier.owner?(current_user.email) %li{role: "presentation"} %a{href: "#invites", 'aria-controls' => "invites", role: "tab", 'data-toggle' => "tab"} Invités + + - if gestionnaire_signed_in? %li{role: "presentation"} %a{href: "#followers", 'aria-controls' => "followers", role: "tab", 'data-toggle' => "tab"} Abonnés @@ -25,9 +27,10 @@ %div{role: "tabpanel", class: "tab-pane fade", id:"commentaires_files"} = render partial: '/dossiers/commentaires_files' - - if gestionnaire_signed_in? + - if gestionnaire_signed_in? || @facade.dossier.owner?(current_user.email) %div{role: "tabpanel", class: "tab-pane fade", id:"invites"} = render partial: '/dossiers/invites' + - if gestionnaire_signed_in? %div{role: "tabpanel", class: "tab-pane fade", id:"followers"} = render partial: 'followers' %div{role: "tabpanel", class: "tab-pane fade", id:"champs_private"} diff --git a/app/views/users/dossiers/_list.html.haml b/app/views/users/dossiers/_list.html.haml index e8bdcc86d..61121ff96 100644 --- a/app/views/users/dossiers/_list.html.haml +++ b/app/views/users/dossiers/_list.html.haml @@ -6,9 +6,9 @@ %th.col-md-2.col-lg-2= smart_listing.sortable 'État', 'state' %th.col-md-2.col-lg-2= smart_listing.sortable 'Date de mise à jour', 'updated_at' - @dossiers.each do |dossier| - - if dossier.class == Invite + - if dossier.kind_of? Invite -invite = dossier - -dossier = dossier.dossier.decorate + -dossier = invite.dossier.decorate - else - dossier = dossier.decorate %tr diff --git a/config/routes.rb b/config/routes.rb index 13e67732a..9f3d48777 100644 --- a/config/routes.rb +++ b/config/routes.rb @@ -1,4 +1,5 @@ Rails.application.routes.draw do + default_url_options protocol: :https get "/ping" => "ping#index", :constraints => {:ip => /127.0.0.1/} @@ -140,6 +141,10 @@ Rails.application.routes.draw do get 'address_point' => 'search#get_address_point' end + namespace :invites do + post 'dossier/:dossier_id' => '/invites#create', as: 'dossier' + end + namespace :backoffice do get 'sign_in' => '/gestionnaires/sessions#new' get 'dossiers/search' => 'dossiers#search' @@ -154,8 +159,6 @@ Rails.application.routes.draw do post 'without_continuation' => 'dossiers#without_continuation' post 'close' => 'dossiers#close' - post 'invites' => '/invites#create' - put 'follow' => 'dossiers#follow' end diff --git a/db/migrate/20160913093948_add_type_attr_in_invite_table.rb b/db/migrate/20160913093948_add_type_attr_in_invite_table.rb new file mode 100644 index 000000000..a71813a9b --- /dev/null +++ b/db/migrate/20160913093948_add_type_attr_in_invite_table.rb @@ -0,0 +1,5 @@ +class AddTypeAttrInInviteTable < ActiveRecord::Migration + def change + add_column :invites, :type, :string, default: 'InviteGestionnaire' + end +end diff --git a/db/schema.rb b/db/schema.rb index 7533be06e..837be6fb9 100644 --- a/db/schema.rb +++ b/db/schema.rb @@ -11,7 +11,7 @@ # # It's strongly recommended that you check this file into your version control system. -ActiveRecord::Schema.define(version: 20160906134155) do +ActiveRecord::Schema.define(version: 20160913093948) do # These are extensions that must be enabled in order to support this database enable_extension "plpgsql" @@ -225,6 +225,7 @@ ActiveRecord::Schema.define(version: 20160906134155) do t.string "email_sender" t.integer "dossier_id" t.integer "user_id" + t.string "type", default: "InviteGestionnaire" end create_table "mail_templates", force: :cascade do |t| diff --git a/spec/controllers/invites_controller_spec.rb b/spec/controllers/invites_controller_spec.rb index 4d8cba09b..e528188cd 100644 --- a/spec/controllers/invites_controller_spec.rb +++ b/spec/controllers/invites_controller_spec.rb @@ -13,7 +13,15 @@ describe InvitesController, type: :controller do subject { post :create, dossier_id: dossier.id, email: email } - it { expect { subject }.to change(Invite, :count).by(1) } + it { expect { subject }.to change(InviteGestionnaire, :count).by(1) } + + context 'when is a user who is loged' do + before do + sign_in create(:user) + end + + it { expect { subject }.to change(InviteGestionnaire, :count).by(1) } + end context 'when email is assign to an user' do let! (:user) { create(:user, email: email) } diff --git a/spec/controllers/user_controller_shared_example.rb b/spec/controllers/user_controller_shared_example.rb new file mode 100644 index 000000000..efe90eb88 --- /dev/null +++ b/spec/controllers/user_controller_shared_example.rb @@ -0,0 +1,43 @@ +shared_examples 'current_user_dossier_spec' do + context 'when no dossier_id is filled' do + it { expect { subject.current_user_dossier }.to raise_error } + end + + context 'when dossier_id is given as a param' do + context 'when dossier id is valid' do + it 'returns current user dossier' do + expect(subject.current_user_dossier dossier.id).to eq(dossier) + end + end + + context 'when dossier id is incorrect' do + it { expect { subject.current_user_dossier 1 }.to raise_error } + end + end + + context 'when no params[] is given' do + context 'when dossier id is valid' do + before do + subject.params[:dossier_id] = dossier.id + end + + it 'returns current user dossier' do + expect(subject.current_user_dossier).to eq(dossier) + end + end + + context 'when dossier id is incorrect' do + it { expect { subject.current_user_dossier }.to raise_error } + end + + context 'when dossier_id is given as a param' do + before do + subject.params[:dossier_id] = 1 + end + + it 'returns dossier with the id on params past' do + expect(subject.current_user_dossier dossier.id).to eq(dossier) + end + end + end +end diff --git a/spec/controllers/users/carte_controller_shared_example.rb b/spec/controllers/users/carte_controller_shared_example.rb new file mode 100644 index 000000000..eaacbddab --- /dev/null +++ b/spec/controllers/users/carte_controller_shared_example.rb @@ -0,0 +1,256 @@ +shared_examples 'carte_controller_spec' do + describe 'GET #show' do + describe 'before_action authorized_routes?' do + context 'when dossier’s procedure have api carto actived' do + context 'when dossier does not have a valid state' do + before do + dossier.state = 'validated' + dossier.save + + get :show, dossier_id: dossier.id + end + + it { is_expected.to redirect_to root_path} + end + end + + context 'when dossier’s procedure does not have api carto actived' do + let(:dossier) { create(:dossier) } + + before do + get :show, dossier_id: dossier.id + end + + it { is_expected.to redirect_to(root_path) } + end + end + + context 'user is not connected' do + before do + sign_out user + end + + it 'redirects to users/sign_in' do + get :show, dossier_id: dossier.id + expect(response).to redirect_to('/users/sign_in') + end + end + + it 'returns http success if carto is activated' do + get :show, dossier_id: dossier.id + expect(response).to have_http_status(:success) + end + + context 'when procedure not have activate api carto' do + it 'redirection on user dossier list' do + get :show, dossier_id: dossier_with_no_carto.id + expect(response).to redirect_to(root_path) + end + end + + context 'when dossier id not exist' do + it 'redirection on user dossier list' do + get :show, dossier_id: bad_dossier_id + expect(response).to redirect_to(root_path) + end + end + + it_behaves_like "not owner of dossier", :show + end + + describe 'POST #save' do + context 'Aucune localisation n\'a jamais été enregistrée' do + it do + post :save, dossier_id: dossier.id, json_latlngs: '' + expect(response).to redirect_to("/users/dossiers/#{dossier.id}/description") + end + end + + context 'En train de modifier la localisation' do + let(:dossier) { create(:dossier, state: 'initiated') } + before do + post :save, dossier_id: dossier.id, json_latlngs: '' + end + + it 'Redirection vers la page récapitulatif' do + expect(response).to redirect_to("/users/dossiers/#{dossier.id}/recapitulatif") + end + end + + describe 'Save quartier prioritaire' do + let(:module_api_carto) { create(:module_api_carto, :with_quartiers_prioritaires) } + + before do + allow_any_instance_of(CARTO::SGMAP::QuartiersPrioritaires::Adapter). + to receive(:to_params). + and_return({"QPCODE1234" => {:code => "QPCODE1234", :nom => "QP de test", :commune => "Paris", :geometry => {:type => "MultiPolygon", :coordinates => [[[[2.38715792094576, 48.8723062632126], [2.38724851642619, 48.8721392348061]]]]}}}) + + post :save, dossier_id: dossier.id, json_latlngs: json_latlngs + end + + context 'when json_latlngs params is empty' do + context 'when dossier have quartier prioritaire in database' do + let!(:dossier) { create(:dossier, :with_two_quartier_prioritaires) } + + before do + dossier.reload + end + + context 'when value is empty' do + let(:json_latlngs) { '' } + it { expect(dossier.quartier_prioritaires.size).to eq(0) } + end + + context 'when value is empty array' do + let(:json_latlngs) { '[]' } + it { expect(dossier.quartier_prioritaires.size).to eq(0) } + end + end + end + + context 'when json_latlngs params is informed' do + let(:json_latlngs) { '[[{"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(dossier.quartier_prioritaires.size).to eq(1) } + + describe 'Quartier Prioritaire' do + subject { QuartierPrioritaire.last } + + it { expect(subject.code).to eq('QPCODE1234') } + it { expect(subject.commune).to eq('Paris') } + it { expect(subject.nom).to eq('QP de test') } + it { expect(subject.dossier_id).to eq(dossier.id) } + end + end + end + + describe 'Save cadastre' do + let(:module_api_carto) { create(:module_api_carto, :with_cadastre) } + + before do + allow_any_instance_of(CARTO::SGMAP::Cadastre::Adapter). + to receive(:to_params). + and_return([{:surface_intersection => "0.0006", :surface_parcelle => 11252.692583090324, :numero => "0013", :feuille => 1, :section => "CD", :code_dep => "30", :nom_com => "Le Grau-du-Roi", :code_com => "133", :code_arr => "000", :geometry => {:type => "MultiPolygon", :coordinates => [[[[4.134084, 43.5209193], [4.1346615, 43.5212035], [4.1346984, 43.521189], [4.135096, 43.5213848], [4.1350839, 43.5214122], [4.1352697, 43.521505], [4.1356278, 43.5211065], [4.1357402, 43.5207188], [4.1350935, 43.5203936], [4.135002, 43.5204366], [4.1346051, 43.5202412], [4.134584, 43.5202472], [4.1345572, 43.5202551], [4.134356, 43.5203137], [4.1342488, 43.5203448], [4.134084, 43.5209193]]]]}}]) + + post :save, dossier_id: dossier.id, json_latlngs: json_latlngs + end + + context 'when json_latlngs params is empty' do + context 'when dossier have cadastres in database' do + let!(:dossier) { create(:dossier, :with_two_cadastres) } + + before do + dossier.reload + end + + context 'when value is empty' do + let(:json_latlngs) { '' } + it { expect(dossier.cadastres.size).to eq(0) } + end + + context 'when value is empty array' do + let(:json_latlngs) { '[]' } + it { expect(dossier.cadastres.size).to eq(0) } + end + end + end + + context 'when json_latlngs params is informed' do + let(:json_latlngs) { '[[{"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(dossier.cadastres.size).to eq(1) } + + describe 'Cadastre' do + subject { Cadastre.last } + + it { expect(subject.surface_intersection).to eq('0.0006') } + it { expect(subject.surface_parcelle).to eq(11252.6925830903) } + it { expect(subject.numero).to eq('0013') } + it { expect(subject.feuille).to eq(1) } + it { expect(subject.section).to eq('CD') } + it { expect(subject.code_dep).to eq('30') } + it { expect(subject.nom_com).to eq('Le Grau-du-Roi') } + it { expect(subject.code_com).to eq('133') } + it { expect(subject.code_arr).to eq('000') } + it { expect(subject.geometry).to eq({"type" => "MultiPolygon", "coordinates" => [[[[4.134084, 43.5209193], [4.1346615, 43.5212035], [4.1346984, 43.521189], [4.135096, 43.5213848], [4.1350839, 43.5214122], [4.1352697, 43.521505], [4.1356278, 43.5211065], [4.1357402, 43.5207188], [4.1350935, 43.5203936], [4.135002, 43.5204366], [4.1346051, 43.5202412], [4.134584, 43.5202472], [4.1345572, 43.5202551], [4.134356, 43.5203137], [4.1342488, 43.5203448], [4.134084, 43.5209193]]]]}) } + end + end + end + end + + describe '#get_position' do + context 'Geocodeur renvoie les positions par defaut' do + let(:etablissement) { create(:etablissement, adresse: bad_adresse, numero_voie: 'dzj', type_voie: 'fzjfk', nom_voie: 'hdidjkz', complement_adresse: 'fjef', code_postal: 'fjeiefk', localite: 'zjfkfz') } + let(:dossier) { create(:dossier, etablissement: etablissement) } + + before do + stub_request(:get, /http:\/\/api-adresse[.]data[.]gouv[.]fr\/search[?]limit=1&q=/) + .to_return(status: 200, body: '{"query": "babouba", "version": "draft", "licence": "ODbL 1.0", "features": [], "type": "FeatureCollection", "attribution": "BAN"}', headers: {}) + get :get_position, dossier_id: dossier.id + end + + subject { JSON.parse(response.body) } + + it 'on enregistre des coordonnées lat et lon avec les valeurs par defaut' do + expect(subject['lat']).to eq('46.538192') + expect(subject['lon']).to eq('2.428462') + end + end + + context 'retour d\'un fichier JSON avec 3 attributs' do + before do + stub_request(:get, "http://api-adresse.data.gouv.fr/search?limit=1&q=#{adresse}") + .to_return(status: 200, body: '{"query": "50 avenue des champs u00e9lysu00e9es Paris 75008", "version": "draft", "licence": "ODbL 1.0", "features": [{"geometry": {"coordinates": [2.306888, 48.870374], "type": "Point"}, "type": "Feature", "properties": {"city": "Paris", "label": "50 Avenue des Champs u00c9lysu00e9es 75008 Paris", "housenumber": "50", "id": "ADRNIVX_0000000270748251", "postcode": "75008", "name": "50 Avenue des Champs u00c9lysu00e9es", "citycode": "75108", "context": "75, u00cele-de-France", "score": 0.9054545454545454, "type": "housenumber"}}], "type": "FeatureCollection", "attribution": "BAN"}', headers: {}) + + get :get_position, dossier_id: dossier.id + end + subject { JSON.parse(response.body) } + + it 'format JSON valide' do + expect(response.content_type).to eq('application/json') + end + + it 'latitude' do + expect(subject['lat']).to eq('48.870374') + end + + it 'longitude' do + expect(subject['lon']).to eq('2.306888') + end + + it 'dossier_id' do + expect(subject['dossier_id']).to eq(dossier.id.to_s) + end + end + end + + describe 'POST #get_qp' do + before do + allow_any_instance_of(CARTO::SGMAP::QuartiersPrioritaires::Adapter). + to receive(:to_params). + and_return({"QPCODE1234" => {:code => "QPCODE1234", :geometry => {:type => "MultiPolygon", :coordinates => [[[[2.38715792094576, 48.8723062632126], [2.38724851642619, 48.8721392348061]]]]}}}) + + post :get_qp, dossier_id: dossier.id, coordinates: coordinates + end + + context 'when coordinates are empty' do + let(:coordinates) { '[]' } + + subject { JSON.parse(response.body) } + + it 'Quartier Prioritaire Adapter does not call' do + expect(subject['quartier_prioritaires']).to eq({}) + end + end + + context 'when coordinates are informed' do + let(:coordinates) { '[[{"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}]]' } + + subject { JSON.parse(response.body)['quartier_prioritaires'] } + it { expect(subject).not_to be_nil } + it { expect(subject['QPCODE1234']['code']).to eq('QPCODE1234') } + it { expect(subject['QPCODE1234']['geometry']['type']).to eq('MultiPolygon') } + it { expect(subject['QPCODE1234']['geometry']['coordinates']).to eq([[[[2.38715792094576, 48.8723062632126], [2.38724851642619, 48.8721392348061]]]]) } + end + end +end \ No newline at end of file diff --git a/spec/controllers/users/carte_controller_spec.rb b/spec/controllers/users/carte_controller_spec.rb index 3d25ef4c6..8fbb7216b 100644 --- a/spec/controllers/users/carte_controller_spec.rb +++ b/spec/controllers/users/carte_controller_spec.rb @@ -1,4 +1,5 @@ require 'spec_helper' +require 'controllers/users/carte_controller_shared_example' RSpec.describe Users::CarteController, type: :controller do let(:bad_adresse) { 'babouba' } @@ -7,6 +8,9 @@ RSpec.describe Users::CarteController, type: :controller do let(:procedure) { create(:procedure, module_api_carto: module_api_carto) } let(:dossier) { create(:dossier, procedure: procedure) } + let(:owner_user) { dossier.user } + let(:invite_by_user) { create :user, email: 'invite@plop.com' } + let(:dossier_with_no_carto) { create(:dossier) } let!(:entreprise) { create(:entreprise, dossier: dossier) } let!(:etablissement) { create(:etablissement, dossier: dossier) } @@ -14,262 +18,20 @@ RSpec.describe Users::CarteController, type: :controller do let(:adresse) { etablissement.geo_adresse } before do - sign_in dossier.user + create :invite, dossier: dossier, user: invite_by_user, email: invite_by_user.email, type: 'InviteUser' + + sign_in user end - describe 'GET #show' do + context 'when sign in user is the owner' do + let(:user) { owner_user } - describe 'before_action authorized_routes?' do - context 'when dossier’s procedure have api carto actived' do - context 'when dossier does not have a valid state' do - before do - dossier.state = 'validated' - dossier.save - - get :show, dossier_id: dossier.id - end - - it { is_expected.to redirect_to root_path} - end - end - - context 'when dossier’s procedure does not have api carto actived' do - let(:dossier) { create(:dossier) } - - before do - get :show, dossier_id: dossier.id - end - - it { is_expected.to redirect_to(root_path) } - end - end - - context 'user is not connected' do - before do - sign_out dossier.user - end - - it 'redirects to users/sign_in' do - get :show, dossier_id: dossier.id - expect(response).to redirect_to('/users/sign_in') - end - end - - it 'returns http success if carto is activated' do - get :show, dossier_id: dossier.id - expect(response).to have_http_status(:success) - end - - context 'when procedure not have activate api carto' do - it 'redirection on user dossier list' do - get :show, dossier_id: dossier_with_no_carto.id - expect(response).to redirect_to(root_path) - end - end - - context 'when dossier id not exist' do - it 'redirection on user dossier list' do - get :show, dossier_id: bad_dossier_id - expect(response).to redirect_to(root_path) - end - end - - it_behaves_like "not owner of dossier", :show + it_should_behave_like "carte_controller_spec" end - describe 'POST #save' do - context 'Aucune localisation n\'a jamais été enregistrée' do - it do - post :save, dossier_id: dossier.id, json_latlngs: '' - expect(response).to redirect_to("/users/dossiers/#{dossier.id}/description") - end - end + context 'when sign in user is an invite by owner' do + let(:user) { invite_by_user } - context 'En train de modifier la localisation' do - let(:dossier) { create(:dossier, state: 'initiated') } - before do - post :save, dossier_id: dossier.id, json_latlngs: '' - end - - it 'Redirection vers la page récapitulatif' do - expect(response).to redirect_to("/users/dossiers/#{dossier.id}/recapitulatif") - end - end - - describe 'Save quartier prioritaire' do - let(:module_api_carto) { create(:module_api_carto, :with_quartiers_prioritaires) } - - before do - allow_any_instance_of(CARTO::SGMAP::QuartiersPrioritaires::Adapter). - to receive(:to_params). - and_return({"QPCODE1234" => {:code => "QPCODE1234", :nom => "QP de test", :commune => "Paris", :geometry => {:type => "MultiPolygon", :coordinates => [[[[2.38715792094576, 48.8723062632126], [2.38724851642619, 48.8721392348061]]]]}}}) - - post :save, dossier_id: dossier.id, json_latlngs: json_latlngs - end - - context 'when json_latlngs params is empty' do - context 'when dossier have quartier prioritaire in database' do - let!(:dossier) { create(:dossier, :with_two_quartier_prioritaires) } - - before do - dossier.reload - end - - context 'when value is empty' do - let(:json_latlngs) { '' } - it { expect(dossier.quartier_prioritaires.size).to eq(0) } - end - - context 'when value is empty array' do - let(:json_latlngs) { '[]' } - it { expect(dossier.quartier_prioritaires.size).to eq(0) } - end - end - end - - context 'when json_latlngs params is informed' do - let(:json_latlngs) { '[[{"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(dossier.quartier_prioritaires.size).to eq(1) } - - describe 'Quartier Prioritaire' do - subject { QuartierPrioritaire.last } - - it { expect(subject.code).to eq('QPCODE1234') } - it { expect(subject.commune).to eq('Paris') } - it { expect(subject.nom).to eq('QP de test') } - it { expect(subject.dossier_id).to eq(dossier.id) } - end - end - end - - describe 'Save cadastre' do - let(:module_api_carto) { create(:module_api_carto, :with_cadastre) } - - before do - allow_any_instance_of(CARTO::SGMAP::Cadastre::Adapter). - to receive(:to_params). - and_return([{:surface_intersection => "0.0006", :surface_parcelle => 11252.692583090324, :numero => "0013", :feuille => 1, :section => "CD", :code_dep => "30", :nom_com => "Le Grau-du-Roi", :code_com => "133", :code_arr => "000", :geometry => {:type => "MultiPolygon", :coordinates => [[[[4.134084, 43.5209193], [4.1346615, 43.5212035], [4.1346984, 43.521189], [4.135096, 43.5213848], [4.1350839, 43.5214122], [4.1352697, 43.521505], [4.1356278, 43.5211065], [4.1357402, 43.5207188], [4.1350935, 43.5203936], [4.135002, 43.5204366], [4.1346051, 43.5202412], [4.134584, 43.5202472], [4.1345572, 43.5202551], [4.134356, 43.5203137], [4.1342488, 43.5203448], [4.134084, 43.5209193]]]]}}]) - - post :save, dossier_id: dossier.id, json_latlngs: json_latlngs - end - - context 'when json_latlngs params is empty' do - context 'when dossier have cadastres in database' do - let!(:dossier) { create(:dossier, :with_two_cadastres) } - - before do - dossier.reload - end - - context 'when value is empty' do - let(:json_latlngs) { '' } - it { expect(dossier.cadastres.size).to eq(0) } - end - - context 'when value is empty array' do - let(:json_latlngs) { '[]' } - it { expect(dossier.cadastres.size).to eq(0) } - end - end - end - - context 'when json_latlngs params is informed' do - let(:json_latlngs) { '[[{"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(dossier.cadastres.size).to eq(1) } - - describe 'Cadastre' do - subject { Cadastre.last } - - it { expect(subject.surface_intersection).to eq('0.0006') } - it { expect(subject.surface_parcelle).to eq(11252.6925830903) } - it { expect(subject.numero).to eq('0013') } - it { expect(subject.feuille).to eq(1) } - it { expect(subject.section).to eq('CD') } - it { expect(subject.code_dep).to eq('30') } - it { expect(subject.nom_com).to eq('Le Grau-du-Roi') } - it { expect(subject.code_com).to eq('133') } - it { expect(subject.code_arr).to eq('000') } - it { expect(subject.geometry).to eq({"type" => "MultiPolygon", "coordinates" => [[[[4.134084, 43.5209193], [4.1346615, 43.5212035], [4.1346984, 43.521189], [4.135096, 43.5213848], [4.1350839, 43.5214122], [4.1352697, 43.521505], [4.1356278, 43.5211065], [4.1357402, 43.5207188], [4.1350935, 43.5203936], [4.135002, 43.5204366], [4.1346051, 43.5202412], [4.134584, 43.5202472], [4.1345572, 43.5202551], [4.134356, 43.5203137], [4.1342488, 43.5203448], [4.134084, 43.5209193]]]]}) } - end - end - end - end - - describe '#get_position' do - context 'Geocodeur renvoie les positions par defaut' do - let(:etablissement) { create(:etablissement, adresse: bad_adresse, numero_voie: 'dzj', type_voie: 'fzjfk', nom_voie: 'hdidjkz', complement_adresse: 'fjef', code_postal: 'fjeiefk', localite: 'zjfkfz') } - let(:dossier) { create(:dossier, etablissement: etablissement) } - - before do - stub_request(:get, /http:\/\/api-adresse[.]data[.]gouv[.]fr\/search[?]limit=1&q=/) - .to_return(status: 200, body: '{"query": "babouba", "version": "draft", "licence": "ODbL 1.0", "features": [], "type": "FeatureCollection", "attribution": "BAN"}', headers: {}) - get :get_position, dossier_id: dossier.id - end - - subject { JSON.parse(response.body) } - - it 'on enregistre des coordonnées lat et lon avec les valeurs par defaut' do - expect(subject['lat']).to eq('46.538192') - expect(subject['lon']).to eq('2.428462') - end - end - - context 'retour d\'un fichier JSON avec 3 attributs' do - before do - stub_request(:get, "http://api-adresse.data.gouv.fr/search?limit=1&q=#{adresse}") - .to_return(status: 200, body: '{"query": "50 avenue des champs u00e9lysu00e9es Paris 75008", "version": "draft", "licence": "ODbL 1.0", "features": [{"geometry": {"coordinates": [2.306888, 48.870374], "type": "Point"}, "type": "Feature", "properties": {"city": "Paris", "label": "50 Avenue des Champs u00c9lysu00e9es 75008 Paris", "housenumber": "50", "id": "ADRNIVX_0000000270748251", "postcode": "75008", "name": "50 Avenue des Champs u00c9lysu00e9es", "citycode": "75108", "context": "75, u00cele-de-France", "score": 0.9054545454545454, "type": "housenumber"}}], "type": "FeatureCollection", "attribution": "BAN"}', headers: {}) - - get :get_position, dossier_id: dossier.id - end - subject { JSON.parse(response.body) } - - it 'format JSON valide' do - expect(response.content_type).to eq('application/json') - end - - it 'latitude' do - expect(subject['lat']).to eq('48.870374') - end - - it 'longitude' do - expect(subject['lon']).to eq('2.306888') - end - - it 'dossier_id' do - expect(subject['dossier_id']).to eq(dossier.id.to_s) - end - end - end - - describe 'POST #get_qp' do - before do - allow_any_instance_of(CARTO::SGMAP::QuartiersPrioritaires::Adapter). - to receive(:to_params). - and_return({"QPCODE1234" => {:code => "QPCODE1234", :geometry => {:type => "MultiPolygon", :coordinates => [[[[2.38715792094576, 48.8723062632126], [2.38724851642619, 48.8721392348061]]]]}}}) - - post :get_qp, dossier_id: dossier.id, coordinates: coordinates - end - - context 'when coordinates are empty' do - let(:coordinates) { '[]' } - - subject { JSON.parse(response.body) } - - it 'Quartier Prioritaire Adapter does not call' do - expect(subject['quartier_prioritaires']).to eq({}) - end - end - - context 'when coordinates are informed' do - let(:coordinates) { '[[{"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}]]' } - - subject { JSON.parse(response.body)['quartier_prioritaires'] } - it { expect(subject).not_to be_nil } - it { expect(subject['QPCODE1234']['code']).to eq('QPCODE1234') } - it { expect(subject['QPCODE1234']['geometry']['type']).to eq('MultiPolygon') } - it { expect(subject['QPCODE1234']['geometry']['coordinates']).to eq([[[[2.38715792094576, 48.8723062632126], [2.38724851642619, 48.8721392348061]]]]) } - end + it_should_behave_like "carte_controller_spec" end end diff --git a/spec/controllers/users/description_controller_shared_example.rb b/spec/controllers/users/description_controller_shared_example.rb new file mode 100644 index 000000000..b11cb12bb --- /dev/null +++ b/spec/controllers/users/description_controller_shared_example.rb @@ -0,0 +1,345 @@ +shared_examples 'description_controller_spec' do + describe 'GET #show' do + context 'user is not connected' do + before do + sign_out dossier.user + end + + it 'redirects to users/sign_in' do + get :show, dossier_id: dossier_id + expect(response).to redirect_to('/users/sign_in') + end + end + + it 'returns http success' do + get :show, dossier_id: dossier_id + expect(response).to have_http_status(:success) + end + + it 'redirection vers start si mauvais dossier ID' do + get :show, dossier_id: bad_dossier_id + expect(response).to redirect_to(root_path) + end + + it_behaves_like "not owner of dossier", :show + + describe 'before_action authorized_routes?' do + context 'when dossier does not have a valid state' do + before do + dossier.state = 'validated' + dossier.save + + get :show, dossier_id: dossier.id + end + + it { is_expected.to redirect_to root_path } + end + end + end + + describe 'POST #create' do + let(:timestamp) { Time.now } + let(:description) { 'Description de test Coucou, je suis un saut à la ligne Je suis un double saut la ligne.' } + + context 'Tous les attributs sont bons' do + describe 'Premier enregistrement des données' do + before do + dossier.draft! + post :create, dossier_id: dossier_id + dossier.reload + end + + it "redirection vers la page recapitulative" do + expect(response).to redirect_to("/users/dossiers/#{dossier_id}/recapitulatif") + end + + it 'etat du dossier est soumis' do + expect(dossier.state).to eq('initiated') + end + end + + context 'En train de manipuler un dossier non brouillon' do + before do + dossier.initiated! + post :create, dossier_id: dossier_id + dossier.reload + end + + it 'Redirection vers la page récapitulatif' do + expect(response).to redirect_to("/users/dossiers/#{dossier_id}/recapitulatif") + end + + it 'etat du dossier n\'est pas soumis' do + expect(dossier.state).not_to eq('draft') + end + end + end + + context 'Quand la procédure accepte les CERFA' do + context 'Sauvegarde du CERFA PDF', vcr: {cassette_name: 'controllers_users_description_controller_save_cerfa'} do + before do + post :create, dossier_id: dossier_id, + cerfa_pdf: cerfa_pdf + dossier.reload + end + + context 'when a CERFA PDF is sent', vcr: {cassette_name: 'controllers_users_description_controller_cerfa_is_sent'} do + subject { dossier.cerfa.first } + + it 'content' do + if Features.remote_storage + expect(subject['content']).to eq('cerfa-3dbb3535-5388-4a37-bc2d-778327b9f999.pdf') + else + expect(subject['content']).to eq('cerfa.pdf') + end + end + + it 'dossier_id' do + expect(subject.dossier_id).to eq(dossier_id) + end + + it { expect(subject.user).to eq user } + end + + context 'les anciens CERFA PDF ne sont pas écrasées' do + let(:cerfas) { Cerfa.where(dossier_id: dossier_id) } + + before do + post :create, dossier_id: dossier_id, cerfa_pdf: cerfa_pdf + end + + it "il y a deux CERFA PDF pour ce dossier" do + expect(cerfas.size).to eq 2 + end + end + end + end + + context 'Quand la procédure n\'accepte pas les CERFA' do + context 'Sauvegarde du CERFA PDF' do + let!(:procedure) { create(:procedure) } + before do + post :create, dossier_id: dossier_id, + cerfa_pdf: cerfa_pdf + dossier.reload + end + + context 'un CERFA PDF est envoyé' do + it { expect(dossier.cerfa_available?).to be_falsey } + end + end + end + + describe 'Sauvegarde des champs' do + let(:champs_dossier) { dossier.champs } + let(:dossier_champs_first) { 'test value' } + let(:dossier_date_value) { '23/06/2016' } + let(:dossier_hour_value) { '17' } + let(:dossier_minute_value) { '00' } + + before do + post :create, {dossier_id: dossier_id, + champs: { + "'#{dossier.champs.first.id}'" => dossier_champs_first, + "'#{dossier.champs.second.id}'" => dossier_date_value + }, + time_hour: { + "'#{dossier.champs.second.id}'" => dossier_hour_value, + }, + time_minute: { + "'#{dossier.champs.second.id}'" => dossier_minute_value, + } + } + dossier.reload + end + + it { expect(dossier.champs.first.value).to eq(dossier_champs_first) } + it { expect(response).to redirect_to users_dossier_recapitulatif_path } + + context 'when champs is type_de_champ datetime' do + it { expect(dossier.champs.second.value).to eq(dossier_date_value+' '+dossier_hour_value+':'+dossier_minute_value) } + end + + context 'when champs value is empty' do + let(:dossier_champs_first) { '' } + + it { expect(dossier.champs.first.value).to eq(dossier_champs_first) } + it { expect(response).to redirect_to users_dossier_recapitulatif_path } + + context 'when champs is mandatory' do + let(:procedure) { create(:procedure, :with_two_type_de_piece_justificative, :with_type_de_champ_mandatory, :with_datetime, cerfa_flag: true) } + + it { expect(response).not_to redirect_to users_dossier_recapitulatif_path } + it { expect(flash[:alert]).to be_present } + end + end + end + + context 'Sauvegarde des pièces justificatives', vcr: {cassette_name: 'controllers_users_description_controller_sauvegarde_pj'} do + let(:all_pj_type) { dossier.procedure.type_de_piece_justificative_ids } + before do + post :create, {dossier_id: dossier_id, + 'piece_justificative_'+all_pj_type[0].to_s => piece_justificative_0, + 'piece_justificative_'+all_pj_type[1].to_s => piece_justificative_1} + dossier.reload + end + + describe 'clamav anti-virus presence', vcr: {cassette_name: 'controllers_users_description_controller_clamav_presence'} do + it 'ClamavService safe_file? is call' do + expect(ClamavService).to receive(:safe_file?).twice + + post :create, {dossier_id: dossier_id, + 'piece_justificative_'+all_pj_type[0].to_s => piece_justificative_0, + 'piece_justificative_'+all_pj_type[1].to_s => piece_justificative_1} + end + end + + context 'for piece 0' do + subject { dossier.retrieve_last_piece_justificative_by_type all_pj_type[0].to_s } + it { expect(subject.content).not_to be_nil } + it { expect(subject.user).to eq user } + end + context 'for piece 1' do + subject { dossier.retrieve_last_piece_justificative_by_type all_pj_type[1].to_s } + it { expect(subject.content).not_to be_nil } + it { expect(subject.user).to eq user } + end + end + end + + describe 'POST #pieces_justificatives', vcr: {cassette_name: 'controllers_users_description_controller_pieces_justificatives'} do + let(:all_pj_type) { dossier.procedure.type_de_piece_justificative_ids } + + subject { patch :pieces_justificatives, {dossier_id: dossier.id, + 'piece_justificative_'+all_pj_type[0].to_s => piece_justificative_0, + 'piece_justificative_'+all_pj_type[1].to_s => piece_justificative_1} } + + context 'when user is a guest' do + let(:guest) { create :user } + + before do + create :invite, dossier: dossier, email: guest.email, user: guest + + sign_in guest + end + + context 'when PJ have no documents' do + it { expect(dossier.pieces_justificatives.size).to eq 0 } + + context 'when upload two PJ' do + before do + subject + dossier.reload + end + + it { expect(dossier.pieces_justificatives.size).to eq 2 } + it { expect(flash[:notice]).to be_present } + it { is_expected.to redirect_to users_dossiers_invite_path(id: guest.invites.find_by_dossier_id(dossier.id).id) } + end + end + + context 'when PJ have already a document' do + before do + create :piece_justificative, :rib, dossier: dossier, type_de_piece_justificative_id: all_pj_type[0] + create :piece_justificative, :contrat, dossier: dossier, type_de_piece_justificative_id: all_pj_type[1] + end + + it { expect(dossier.pieces_justificatives.size).to eq 2 } + + context 'when upload two PJ', vcr: {cassette_name: 'controllers_users_description_controller_upload_2pj'} do + before do + subject + dossier.reload + end + + it { expect(dossier.pieces_justificatives.size).to eq 4 } + it { expect(flash[:notice]).to be_present } + it { is_expected.to redirect_to users_dossiers_invite_path(id: guest.invites.find_by_dossier_id(dossier.id).id) } + end + end + + context 'when one of PJs is not valid' do + let(:piece_justificative_0) { Rack::Test::UploadedFile.new("./spec/support/files/entreprise.json", 'application/json') } + + it { expect(dossier.pieces_justificatives.size).to eq 0 } + + context 'when upload two PJ' do + before do + subject + dossier.reload + end + + it { expect(dossier.pieces_justificatives.size).to eq 1 } + it { expect(flash[:alert]).to be_present } + it { is_expected.to redirect_to users_dossiers_invite_path(id: guest.invites.find_by_dossier_id(dossier.id).id) } + end + end + end + end +end + +shared_examples 'description_controller_spec_POST_piece_justificatives_for_owner' do + let(:all_pj_type) { dossier.procedure.type_de_piece_justificative_ids } + + subject { patch :pieces_justificatives, {dossier_id: dossier.id, + 'piece_justificative_'+all_pj_type[0].to_s => piece_justificative_0, + 'piece_justificative_'+all_pj_type[1].to_s => piece_justificative_1} } + + context 'when user is the owner' do + before do + sign_in user + end + + context 'when PJ have no documents' do + it { expect(dossier.pieces_justificatives.size).to eq 0 } + + context 'when upload two PJ' do + before do + subject + dossier.reload + end + + it { expect(dossier.pieces_justificatives.size).to eq 2 } + it { expect(flash[:notice]).to be_present } + it { is_expected.to redirect_to recapitulatif_path } + end + end + + context 'when PJ have already a document', vcr: {cassette_name: 'controllers_users_description_controller_pj_already_exist'} do + before do + create :piece_justificative, :rib, dossier: dossier, type_de_piece_justificative_id: all_pj_type[0] + create :piece_justificative, :contrat, dossier: dossier, type_de_piece_justificative_id: all_pj_type[1] + end + + it { expect(dossier.pieces_justificatives.size).to eq 2 } + + context 'when upload two PJ', vcr: {cassette_name: 'controllers_users_description_controller_pj_already_exist_upload_2pj'} do + before do + subject + dossier.reload + end + + it { expect(dossier.pieces_justificatives.size).to eq 4 } + it { expect(flash[:notice]).to be_present } + it { is_expected.to redirect_to recapitulatif_path } + end + end + + context 'when one of PJs is not valid' do + let(:piece_justificative_0) { Rack::Test::UploadedFile.new("./spec/support/files/entreprise.json", 'application/json') } + + it { expect(dossier.pieces_justificatives.size).to eq 0 } + + context 'when upload two PJ' do + before do + subject + dossier.reload + end + + it { expect(dossier.pieces_justificatives.size).to eq 1 } + it { expect(flash[:alert]).to be_present } + it { is_expected.to redirect_to recapitulatif_path } + end + end + end +end diff --git a/spec/controllers/users/description_controller_spec.rb b/spec/controllers/users/description_controller_spec.rb index 58d0f9f2a..b459d6341 100644 --- a/spec/controllers/users/description_controller_spec.rb +++ b/spec/controllers/users/description_controller_spec.rb @@ -1,10 +1,13 @@ require 'spec_helper' +require 'controllers/users/description_controller_shared_example' + describe Users::DescriptionController, type: :controller, vcr: {cassette_name: 'controllers_users_description_controller'} do - let(:user) { create(:user) } + let(:owner_user) { create(:user) } + let(:invite_by_user) { create :user, email: 'invite@plop.com' } let(:procedure) { create(:procedure, :with_two_type_de_piece_justificative, :with_type_de_champ, :with_datetime, cerfa_flag: true) } - let(:dossier) { create(:dossier, procedure: procedure, user: user) } + let(:dossier) { create(:dossier, procedure: procedure, user: owner_user) } let(:dossier_id) { dossier.id } let(:bad_dossier_id) { Dossier.count + 10000 } @@ -20,342 +23,23 @@ describe Users::DescriptionController, type: :controller, vcr: {cassette_name: ' before do allow(ClamavService).to receive(:safe_file?).and_return(true) - sign_in dossier.user + create :invite, dossier: dossier, user: invite_by_user, email: invite_by_user.email, type: 'InviteUser' + + sign_in user end - describe 'GET #show' do - context 'user is not connected' do - before do - sign_out dossier.user - end + context 'when sign in user is the owner' do + let(:user) { owner_user } + let(:recapitulatif_path) { users_dossier_recapitulatif_path } - it 'redirects to users/sign_in' do - get :show, dossier_id: dossier_id - expect(response).to redirect_to('/users/sign_in') - end - end - - it 'returns http success' do - get :show, dossier_id: dossier_id - expect(response).to have_http_status(:success) - end - - it 'redirection vers start si mauvais dossier ID' do - get :show, dossier_id: bad_dossier_id - expect(response).to redirect_to(root_path) - end - - it_behaves_like "not owner of dossier", :show - - describe 'before_action authorized_routes?' do - context 'when dossier does not have a valid state' do - before do - dossier.state = 'validated' - dossier.save - - get :show, dossier_id: dossier.id - end - - it { is_expected.to redirect_to root_path } - end - end + it_should_behave_like "description_controller_spec" + it_should_behave_like "description_controller_spec_POST_piece_justificatives_for_owner" end - describe 'POST #create' do - let(:timestamp) { Time.now } - let(:description) { 'Description de test Coucou, je suis un saut à la ligne Je suis un double saut la ligne.' } + context 'when sign in user is an invite by owner' do + let(:user) { invite_by_user } + let(:recapitulatif_path) { users_dossiers_invite_path(id: dossier_id) } - context 'Tous les attributs sont bons' do - describe 'Premier enregistrement des données' do - before do - dossier.draft! - post :create, dossier_id: dossier_id - dossier.reload - end - - it "redirection vers la page recapitulative" do - expect(response).to redirect_to("/users/dossiers/#{dossier_id}/recapitulatif") - end - - it 'etat du dossier est soumis' do - expect(dossier.state).to eq('initiated') - end - end - - context 'En train de manipuler un dossier non brouillon' do - before do - dossier.initiated! - post :create, dossier_id: dossier_id - dossier.reload - end - - it 'Redirection vers la page récapitulatif' do - expect(response).to redirect_to("/users/dossiers/#{dossier_id}/recapitulatif") - end - - it 'etat du dossier n\'est pas soumis' do - expect(dossier.state).not_to eq('draft') - end - end - end - - context 'Quand la procédure accepte les CERFA' do - context 'Sauvegarde du CERFA PDF', vcr: {cassette_name: 'controllers_users_description_controller_save_cerfa'} do - before do - post :create, dossier_id: dossier_id, - cerfa_pdf: cerfa_pdf - dossier.reload - end - - context 'when a CERFA PDF is sent', vcr: {cassette_name: 'controllers_users_description_controller_cerfa_is_sent'} do - subject { dossier.cerfa.first } - - it 'content' do - if Features.remote_storage - expect(subject['content']).to eq('cerfa-3dbb3535-5388-4a37-bc2d-778327b9f999.pdf') - else - expect(subject['content']).to eq('cerfa.pdf') - end - end - - it 'dossier_id' do - expect(subject.dossier_id).to eq(dossier_id) - end - - it { expect(subject.user).to eq user } - end - - context 'les anciens CERFA PDF ne sont pas écrasées' do - let(:cerfas) { Cerfa.where(dossier_id: dossier_id) } - - before do - post :create, dossier_id: dossier_id, cerfa_pdf: cerfa_pdf - end - - it "il y a deux CERFA PDF pour ce dossier" do - expect(cerfas.size).to eq 2 - end - end - end - end - - context 'Quand la procédure n\'accepte pas les CERFA' do - context 'Sauvegarde du CERFA PDF' do - let!(:procedure) { create(:procedure) } - before do - post :create, dossier_id: dossier_id, - cerfa_pdf: cerfa_pdf - dossier.reload - end - - context 'un CERFA PDF est envoyé' do - it { expect(dossier.cerfa_available?).to be_falsey } - end - end - end - - describe 'Sauvegarde des champs' do - let(:champs_dossier) { dossier.champs } - let(:dossier_champs_first) { 'test value' } - let(:dossier_date_value) { '23/06/2016' } - let(:dossier_hour_value) { '17' } - let(:dossier_minute_value) { '00' } - - before do - post :create, {dossier_id: dossier_id, - champs: { - "'#{dossier.champs.first.id}'" => dossier_champs_first, - "'#{dossier.champs.second.id}'" => dossier_date_value - }, - time_hour: { - "'#{dossier.champs.second.id}'" => dossier_hour_value, - }, - time_minute: { - "'#{dossier.champs.second.id}'" => dossier_minute_value, - } - } - dossier.reload - end - - it { expect(dossier.champs.first.value).to eq(dossier_champs_first) } - it { expect(response).to redirect_to users_dossier_recapitulatif_path } - - context 'when champs is type_de_champ datetime' do - it { expect(dossier.champs.second.value).to eq(dossier_date_value+' '+dossier_hour_value+':'+dossier_minute_value) } - end - - context 'when champs value is empty' do - let(:dossier_champs_first) { '' } - - it { expect(dossier.champs.first.value).to eq(dossier_champs_first) } - it { expect(response).to redirect_to users_dossier_recapitulatif_path } - - context 'when champs is mandatory' do - let(:procedure) { create(:procedure, :with_two_type_de_piece_justificative, :with_type_de_champ_mandatory, :with_datetime, cerfa_flag: true) } - - it { expect(response).not_to redirect_to users_dossier_recapitulatif_path } - it { expect(flash[:alert]).to be_present } - end - end - end - - context 'Sauvegarde des pièces justificatives', vcr: {cassette_name: 'controllers_users_description_controller_sauvegarde_pj'} do - let(:all_pj_type) { dossier.procedure.type_de_piece_justificative_ids } - before do - post :create, {dossier_id: dossier_id, - 'piece_justificative_'+all_pj_type[0].to_s => piece_justificative_0, - 'piece_justificative_'+all_pj_type[1].to_s => piece_justificative_1} - dossier.reload - end - - describe 'clamav anti-virus presence', vcr: {cassette_name: 'controllers_users_description_controller_clamav_presence'} do - it 'ClamavService safe_file? is call' do - expect(ClamavService).to receive(:safe_file?).twice - - post :create, {dossier_id: dossier_id, - 'piece_justificative_'+all_pj_type[0].to_s => piece_justificative_0, - 'piece_justificative_'+all_pj_type[1].to_s => piece_justificative_1} - end - end - - context 'for piece 0' do - subject { dossier.retrieve_last_piece_justificative_by_type all_pj_type[0].to_s } - it { expect(subject.content).not_to be_nil } - it { expect(subject.user).to eq user } - end - context 'for piece 1' do - subject { dossier.retrieve_last_piece_justificative_by_type all_pj_type[1].to_s } - it { expect(subject.content).not_to be_nil } - it { expect(subject.user).to eq user } - end - end - end - - describe 'POST #pieces_justificatives', vcr: {cassette_name: 'controllers_users_description_controller_pieces_justificatives'} do - let(:all_pj_type) { dossier.procedure.type_de_piece_justificative_ids } - - subject { patch :pieces_justificatives, {dossier_id: dossier.id, - 'piece_justificative_'+all_pj_type[0].to_s => piece_justificative_0, - 'piece_justificative_'+all_pj_type[1].to_s => piece_justificative_1} } - - context 'when user is the owner' do - before do - sign_in user - end - - context 'when PJ have no documents' do - it { expect(dossier.pieces_justificatives.size).to eq 0 } - - context 'when upload two PJ' do - before do - subject - dossier.reload - end - - it { expect(dossier.pieces_justificatives.size).to eq 2 } - it { expect(flash[:notice]).to be_present } - it { is_expected.to redirect_to users_dossier_recapitulatif_path } - end - end - - context 'when PJ have already a document', vcr: {cassette_name: 'controllers_users_description_controller_pj_already_exist'} do - before do - create :piece_justificative, :rib, dossier: dossier, type_de_piece_justificative_id: all_pj_type[0] - create :piece_justificative, :contrat, dossier: dossier, type_de_piece_justificative_id: all_pj_type[1] - end - - it { expect(dossier.pieces_justificatives.size).to eq 2 } - - context 'when upload two PJ', vcr: {cassette_name: 'controllers_users_description_controller_pj_already_exist_upload_2pj'} do - before do - subject - dossier.reload - end - - it { expect(dossier.pieces_justificatives.size).to eq 4 } - it { expect(flash[:notice]).to be_present } - it { is_expected.to redirect_to users_dossier_recapitulatif_path } - end - end - - context 'when one of PJs is not valid' do - let(:piece_justificative_0) { Rack::Test::UploadedFile.new("./spec/support/files/entreprise.json", 'application/json') } - - it { expect(dossier.pieces_justificatives.size).to eq 0 } - - context 'when upload two PJ' do - before do - subject - dossier.reload - end - - it { expect(dossier.pieces_justificatives.size).to eq 1 } - it { expect(flash[:alert]).to be_present } - it { is_expected.to redirect_to users_dossier_recapitulatif_path } - end - end - end - - context 'when user is a guest' do - let(:guest) { create :user } - - before do - create :invite, dossier: dossier, email: guest.email, user: guest - - sign_in guest - end - - context 'when PJ have no documents' do - it { expect(dossier.pieces_justificatives.size).to eq 0 } - - context 'when upload two PJ' do - before do - subject - dossier.reload - end - - it { expect(dossier.pieces_justificatives.size).to eq 2 } - it { expect(flash[:notice]).to be_present } - it { is_expected.to redirect_to users_dossiers_invite_path(id: guest.invites.find_by_dossier_id(dossier.id).id) } - end - end - - context 'when PJ have already a document' do - before do - create :piece_justificative, :rib, dossier: dossier, type_de_piece_justificative_id: all_pj_type[0] - create :piece_justificative, :contrat, dossier: dossier, type_de_piece_justificative_id: all_pj_type[1] - end - - it { expect(dossier.pieces_justificatives.size).to eq 2 } - - context 'when upload two PJ', vcr: {cassette_name: 'controllers_users_description_controller_upload_2pj'} do - before do - subject - dossier.reload - end - - it { expect(dossier.pieces_justificatives.size).to eq 4 } - it { expect(flash[:notice]).to be_present } - it { is_expected.to redirect_to users_dossiers_invite_path(id: guest.invites.find_by_dossier_id(dossier.id).id) } - end - end - - context 'when one of PJs is not valid' do - let(:piece_justificative_0) { Rack::Test::UploadedFile.new("./spec/support/files/entreprise.json", 'application/json') } - - it { expect(dossier.pieces_justificatives.size).to eq 0 } - - context 'when upload two PJ' do - before do - subject - dossier.reload - end - - it { expect(dossier.pieces_justificatives.size).to eq 1 } - it { expect(flash[:alert]).to be_present } - it { is_expected.to redirect_to users_dossiers_invite_path(id: guest.invites.find_by_dossier_id(dossier.id).id) } - end - end - end + it_should_behave_like "description_controller_spec" end end diff --git a/spec/controllers/users_controller_spec.rb b/spec/controllers/users_controller_spec.rb index 9d483a0a4..eee59c898 100644 --- a/spec/controllers/users_controller_spec.rb +++ b/spec/controllers/users_controller_spec.rb @@ -1,55 +1,31 @@ require 'spec_helper' +require 'controllers/user_controller_shared_example' + describe UsersController, type: :controller do - describe '#current_user_dossier' do - let(:user) { create(:user) } - let(:dossier) { create(:dossier, user: user)} + let(:owner_user) { create(:user) } + let(:invite_user) { create :user, email: 'invite@plop.com' } + let(:not_invite_user) { create :user, email: 'not_invite@plop.com' } - before do - sign_in user + let(:dossier) { create(:dossier, user: owner_user) } + + context 'when user is the owner' do + before do + sign_in owner_user + end + + it_should_behave_like "current_user_dossier_spec" end - context 'when no dossier_id is filled' do - it { expect{ subject.current_user_dossier }.to raise_error } - end - - context 'when dossier_id is given as a param' do - context 'when dossier id is valid' do - it 'returns current user dossier' do - expect(subject.current_user_dossier dossier.id).to eq(dossier) - end + context 'when user is invite by the owner' do + before do + create :invite, email: invite_user.email, dossier: dossier, user: invite_user, type: 'InviteUser' + sign_in invite_user end - context 'when dossier id is incorrect' do - it { expect{ subject.current_user_dossier 1 }.to raise_error } - end - end - - context 'when no params[] is given' do - context 'when dossier id is valid' do - before do - subject.params[:dossier_id] = dossier.id - end - - it 'returns current user dossier' do - expect(subject.current_user_dossier).to eq(dossier) - end - end - - context 'when dossier id is incorrect' do - it { expect{ subject.current_user_dossier }.to raise_error } - end - - context 'when dossier_id is given as a param' do - before do - subject.params[:dossier_id] = 1 - end - - it 'returns dossier with the id on params past' do - expect(subject.current_user_dossier dossier.id).to eq(dossier) - end - end + it_should_behave_like "current_user_dossier_spec" end end -end \ No newline at end of file +end + diff --git a/spec/models/dossier_spec.rb b/spec/models/dossier_spec.rb index 21ac74bd0..24fa351e6 100644 --- a/spec/models/dossier_spec.rb +++ b/spec/models/dossier_spec.rb @@ -829,4 +829,31 @@ describe Dossier do it { expect(subject).to eq 2 } end end + + describe '#invite_by_user?' do + let(:dossier) { create :dossier } + let(:invite_user) { create :user, email: user_invite_email } + let(:invite_gestionnaire) { create :user, email: gestionnaire_invite_email } + let(:user_invite_email) { 'plup@plop.com' } + let(:gestionnaire_invite_email) { 'plap@plip.com' } + + before do + create :invite, dossier: dossier, user: invite_user, email: invite_user.email, type: 'InviteUser' + create :invite, dossier: dossier, user: invite_gestionnaire, email: invite_gestionnaire.email, type: 'InviteGestionnaire' + end + + subject { dossier.invite_by_user? email } + + context 'when email is present on invite list' do + let(:email) { user_invite_email } + + it { is_expected.to be_truthy } + end + + context 'when email is present on invite list' do + let(:email) { gestionnaire_invite_email } + + it { is_expected.to be_falsey } + end + end end diff --git a/spec/views/users/recapitulatif/show.html.haml_spec.rb b/spec/views/users/recapitulatif/show.html.haml_spec.rb index a687bb94e..f5a7bd92a 100644 --- a/spec/views/users/recapitulatif/show.html.haml_spec.rb +++ b/spec/views/users/recapitulatif/show.html.haml_spec.rb @@ -40,6 +40,12 @@ describe 'users/recapitulatif/show.html.haml', type: :view do end end + context 'lien carte' do + it 'le lien vers carte est présent' do + expect(rendered).to have_css('#maj_pj') + end + end + context 'lien carte' do it 'le lien vers carte est présent' do expect(rendered).to have_css('#maj_carte') @@ -169,43 +175,88 @@ describe 'users/recapitulatif/show.html.haml', type: :view do end context 'when invite is logged' do - let!(:invite_user) { create(:user, email: 'invite@octo.com') } - before do - create(:invite) { create(:invite, email: invite_user.email, user: invite_user, dossier: dossier) } - sign_out dossier.user - - sign_in invite_user - - render - end - - describe 'les liens de modifications' do - it 'describe link is not present' do - expect(rendered).not_to have_css('#maj_infos') - end - - it 'map link is not present' do - expect(rendered).not_to have_css('#maj_carte') - end - - it 'archive link is not present' do - expect(rendered).not_to have_content('Archiver') - end - end - - context 'when dossier is validated' do - let(:state) { 'validated' } + context 'when invite is by Gestionnaire' do + let!(:invite_user) { create(:user, email: 'invite@octo.com') } before do + create(:invite) { create(:invite, email: invite_user.email, user: invite_user, dossier: dossier) } + sign_out dossier.user + sign_in invite_user render end - it 'submitted link is not present' do - expect(rendered).not_to have_content('Déposer mon dossier') + describe 'les liens de modifications' do + it 'describe link is not present' do + expect(rendered).not_to have_css('#maj_infos') + end + + it 'map link is not present' do + expect(rendered).not_to have_css('#maj_carte') + end + + it 'PJ link is not present' do + expect(rendered).not_to have_css('#maj_pj') + end + + it 'archive link is not present' do + expect(rendered).not_to have_content('Archiver') + end + end + + context 'when dossier is validated' do + let(:state) { 'validated' } + + before do + render + end + + it 'submitted link is not present' do + expect(rendered).not_to have_content('Déposer mon dossier') + end end end + context 'invite is by User' do + let!(:invite_user) { create(:user, email: 'invite@octo.com') } + + before do + create(:invite) { create(:invite, email: invite_user.email, user: invite_user, dossier: dossier, type: 'InviteUser') } + sign_out dossier.user + sign_in invite_user + render + end + + describe 'les liens de modifications' do + it 'describe link is not present' do + expect(rendered).to have_css('#maj_infos') + end + + it 'map link is present' do + expect(rendered).to have_css('#maj_carte') + end + + it 'PJ link is present' do + expect(rendered).to have_css('#maj_pj') + end + + it 'archive link is present' do + expect(rendered).not_to have_content('Archiver') + end + end + + context 'when dossier is validated' do + let(:state) { 'validated' } + + before do + render + end + + it 'submitted link is not present' do + expect(rendered).not_to have_content('Déposer mon dossier') + end + end + end end end end