diff --git a/app/assets/javascripts/new_design/direct_uploads.js b/app/assets/javascripts/new_design/direct_uploads.js index 1ac788eec..47b5aa23c 100644 --- a/app/assets/javascripts/new_design/direct_uploads.js +++ b/app/assets/javascripts/new_design/direct_uploads.js @@ -42,4 +42,16 @@ addEventListener("direct-upload:end", function (event) { element = document.getElementById("direct-upload-" + id); element.classList.add("direct-upload--complete"); -}); \ No newline at end of file +}); + +addEventListener('load', function() { + var submitButtons = document.querySelectorAll('form button[type=submit][data-action]'); + var hiddenInput = document.querySelector('form input[type=hidden][name=submit_action]'); + submitButtons = [].slice.call(submitButtons); + + submitButtons.forEach(function(button) { + button.addEventListener('click', function() { + hiddenInput.value = button.getAttribute('data-action'); + }); + }); +}); diff --git a/app/assets/stylesheets/new_design/dossier-edit.scss b/app/assets/stylesheets/new_design/dossier-edit.scss new file mode 100644 index 000000000..e906c529b --- /dev/null +++ b/app/assets/stylesheets/new_design/dossier-edit.scss @@ -0,0 +1,20 @@ +@import "colors"; +@import "constants"; + +.dossier-edit { + .dossier-header { + background-color: $light-grey; + + .container { + padding: $default-padding; + } + + h1 { + font-size: 22px; + } + } + + .thanks { + padding: (1.5 * $default-padding) 0; + } +} diff --git a/app/assets/stylesheets/new_design/forms.scss b/app/assets/stylesheets/new_design/forms.scss index 13486ec9f..17ef315f6 100644 --- a/app/assets/stylesheets/new_design/forms.scss +++ b/app/assets/stylesheets/new_design/forms.scss @@ -15,6 +15,7 @@ label { margin-bottom: $default-padding; display: block; + font-weight: bold; .mandatory { color: $dark-red; @@ -115,7 +116,7 @@ input.touched:invalid, textarea.touched:invalid { - border-color: $dark-red; + border: 1px solid $dark-red; box-shadow: 0px 0px 5px $dark-red; } @@ -239,4 +240,15 @@ margin-right: 0; } } + + .pj-input { + input[type=file] { + margin: $default-padding 0 (2 * $default-padding); + padding: 2px; + } + + .piece-description { + margin-bottom: $default-padding; + } + } } diff --git a/app/controllers/new_user/dossiers_controller.rb b/app/controllers/new_user/dossiers_controller.rb index 02f02b5f2..b695bda67 100644 --- a/app/controllers/new_user/dossiers_controller.rb +++ b/app/controllers/new_user/dossiers_controller.rb @@ -23,7 +23,7 @@ module NewUser if @dossier.procedure.module_api_carto.use_api_carto redirect_to users_dossier_carte_path(@dossier.id) else - redirect_to users_dossier_description_path(@dossier) # Simon should replace this with dossier_path when done + redirect_to modifier_dossier_path(@dossier) end else flash.now.alert = @dossier.errors.full_messages @@ -31,12 +31,62 @@ module NewUser end end + def modifier + @dossier = dossier_with_champs + + # TODO: remove when the champs are unifed + if !@dossier.autorisation_donnees + if dossier.procedure.for_individual + redirect_to identite_dossier_path(@dossier) + else + redirect_to users_dossier_path(@dossier) + end + end + end + + # FIXME: remove PiecesJustificativesService + # delegate draft save logic to champ ? + def update + @dossier = dossier_with_champs + + errors = PiecesJustificativesService.upload!(@dossier, current_user, params) + + if !@dossier.update(champs_params) + errors += @dossier.errors.full_messages + end + + if !draft? + errors += @dossier.champs.select(&:mandatory_and_blank?) + .map { |c| "Le champ #{c.libelle.truncate(200)} doit être rempli." } + errors += PiecesJustificativesService.missing_pj_error_messages(@dossier) + end + + if errors.present? + flash.now.alert = errors + render :modifier + elsif draft? + flash.now.notice = 'Votre brouillon a bien été sauvegardé.' + render :modifier + else + @dossier.en_construction! + redirect_to users_dossier_recapitulatif_path(@dossier) + end + end + private + def champs_params + params.require(:dossier).permit(champs_attributes: [:id, :value, :piece_justificative_file, value: []]) + end + def dossier Dossier.find(params[:id] || params[:dossier_id]) end + def dossier_with_champs + @dossier_with_champs ||= current_user.dossiers.includes(champs: :type_de_champ).find(params[:id]) + end + def ensure_ownership! if dossier.user != current_user flash[:alert] = "Vous n'avez pas accès à ce dossier" @@ -51,5 +101,9 @@ module NewUser def dossier_params params.require(:dossier).permit(:autorisation_donnees) end + + def draft? + params[:submit_action] == 'draft' + end end end diff --git a/app/controllers/users/carte_controller.rb b/app/controllers/users/carte_controller.rb index 08f04f9cd..8ef350893 100644 --- a/app/controllers/users/carte_controller.rb +++ b/app/controllers/users/carte_controller.rb @@ -24,10 +24,7 @@ class Users::CarteController < UsersController dossier.update_attributes(json_latlngs: params[:json_latlngs]) - controller = :recapitulatif - controller = :description if dossier.brouillon? - - redirect_to url_for(controller: controller, action: :show, dossier_id: params[:dossier_id]) + redirect_to modifier_dossier_path(dossier) end def get_position diff --git a/app/controllers/users/dossiers_controller.rb b/app/controllers/users/dossiers_controller.rb index a5042fc7a..a93320573 100644 --- a/app/controllers/users/dossiers_controller.rb +++ b/app/controllers/users/dossiers_controller.rb @@ -154,7 +154,7 @@ class Users::DossiersController < UsersController if @facade.dossier.procedure.module_api_carto.use_api_carto redirect_to url_for(controller: :carte, action: :show, dossier_id: @facade.dossier.id) else - redirect_to url_for(controller: :description, action: :show, dossier_id: @facade.dossier.id) + redirect_to modifier_dossier_path(@facade.dossier) end end end diff --git a/app/decorators/dossier_decorator.rb b/app/decorators/dossier_decorator.rb index c8d71c0b9..532be3f41 100644 --- a/app/decorators/dossier_decorator.rb +++ b/app/decorators/dossier_decorator.rb @@ -16,14 +16,6 @@ class DossierDecorator < Draper::Decorator DossierDecorator.case_state_fr state end - def url(gestionnaire_signed_in) - if brouillon? - users_dossier_description_path(id) - else - users_dossier_recapitulatif_path(id) - end - end - def self.case_state_fr state = self.state h.t("activerecord.attributes.dossier.state.#{state}") end diff --git a/app/models/dossier.rb b/app/models/dossier.rb index e4f2be5ab..fe9da1f7a 100644 --- a/app/models/dossier.rb +++ b/app/models/dossier.rb @@ -108,6 +108,10 @@ class Dossier < ActiveRecord::Base champs.joins(', types_de_champ').where("champs.type_de_champ_id = types_de_champ.id AND types_de_champ.procedure_id = #{procedure.id}").order('order_place') end + def ordered_champs_v2 + champs.includes(:type_de_champ).order('types_de_champ.order_place') + end + def ordered_champs_private # TODO: use the line below when the procedure preview does not leak champ with dossier_id == 0 # champs_private.includes(:type_de_champ).order('types_de_champ.order_place') diff --git a/app/views/dossiers/_edit_dossier.html.haml b/app/views/dossiers/_edit_dossier.html.haml index 258bf2b4b..17356d1c7 100644 --- a/app/views/dossiers/_edit_dossier.html.haml +++ b/app/views/dossiers/_edit_dossier.html.haml @@ -1,5 +1,5 @@ - if !@facade.dossier.read_only? - if user_signed_in? && (@facade.dossier.owner?(current_user.email) || @facade.dossier.invite_by_user?(current_user.email)) - %a#maj_infos.action{ href: "/users/dossiers/#{@facade.dossier.id}/description" } + = link_to modifier_dossier_path(@facade.dossier), class: 'action', id: 'maj_infos' do #edit-dossier.col-lg-2.col-md-2.col-sm-2.col-xs-2.action = "éditer".upcase diff --git a/app/views/dossiers/_infos_dossier.html.haml b/app/views/dossiers/_infos_dossier.html.haml index de2ee2545..7fae0d674 100644 --- a/app/views/dossiers/_infos_dossier.html.haml +++ b/app/views/dossiers/_infos_dossier.html.haml @@ -41,7 +41,7 @@ - if champ.type_champ == 'dossier_link' - dossier = Dossier.includes(:procedure).find_by(id: champ.decorate.value) - if dossier - = link_to("Dossier #{dossier.id}", dossier.decorate.url(gestionnaire_signed_in?), target: '_blank') + = link_to("Dossier #{dossier.id}", modifier_dossier_path(dossier), target: '_blank') %br = sanitize(dossier.text_summary) - else diff --git a/app/views/layouts/_new_header.haml b/app/views/layouts/_new_header.haml index f4e088c14..b6718a0cb 100644 --- a/app/views/layouts/_new_header.haml +++ b/app/views/layouts/_new_header.haml @@ -30,6 +30,11 @@ %br – par email : contact@tps.apientreprise.fr + - if nav_bar_profile == :user + %ul.header-tabs + %li + = link_to "Mes dossiers", users_dossiers_path, class: 'tab-link' + %ul.header-right-content - if nav_bar_profile == :gestionnaire && gestionnaire_signed_in? %li diff --git a/app/views/new_gestionnaire/dossiers/editable_champs/_champ_label.html.haml b/app/views/new_gestionnaire/dossiers/editable_champs/_champ_label.html.haml index 38749d6da..cd38c8515 100644 --- a/app/views/new_gestionnaire/dossiers/editable_champs/_champ_label.html.haml +++ b/app/views/new_gestionnaire/dossiers/editable_champs/_champ_label.html.haml @@ -3,7 +3,7 @@ - if champ.mandatory? %span.mandatory * - - if champ.updated_at.present? + - if champ.updated_at.present? && seen_at.present? %span.updated-at{ class: highlight_if_unseen_class(seen_at, champ.updated_at) } = "modifié le #{champ.updated_at.strftime('%d/%m/%Y à %H:%M')}" diff --git a/app/views/new_gestionnaire/dossiers/editable_champs/_editable_champ.html.haml b/app/views/new_gestionnaire/dossiers/editable_champs/_editable_champ.html.haml index 6c37e74fd..f0f526b47 100644 --- a/app/views/new_gestionnaire/dossiers/editable_champs/_editable_champ.html.haml +++ b/app/views/new_gestionnaire/dossiers/editable_champs/_editable_champ.html.haml @@ -1,6 +1,6 @@ .editable-champ - if is_not_header_nor_explication?(champ) - = render partial: 'new_gestionnaire/dossiers/editable_champs/champ_label', locals: { form: form, champ: champ, seen_at: seen_at } + = render partial: 'new_gestionnaire/dossiers/editable_champs/champ_label', locals: { form: form, champ: champ, seen_at: defined?(seen_at) ? seen_at : nil } = render partial: "new_gestionnaire/dossiers/editable_champs/#{champ.type_champ}", locals: { champ: champ, form: form } diff --git a/app/views/new_user/dossiers/modifier.html.haml b/app/views/new_user/dossiers/modifier.html.haml new file mode 100644 index 000000000..907d67a43 --- /dev/null +++ b/app/views/new_user/dossiers/modifier.html.haml @@ -0,0 +1,62 @@ +.dossier-edit + .dossier-header + .container + %h1= @dossier.procedure.libelle + + .container + %p.thanks Les champs avec une asterisque (*) sont obligatoires. + + = form_for @dossier, html: { class: 'form', multipart: true } do |f| + = f.fields_for :champs, @dossier.ordered_champs_v2 do |champ_form| + - champ = champ_form.object + = render partial: "new_gestionnaire/dossiers/editable_champs/editable_champ", + locals: { champ: champ, form: champ_form } + + - tpjs = @dossier.types_de_piece_justificative.order('order_place ASC') + - if tpjs.present? + .card.featured + .card-title + Pièces-jointes + + - tpjs.each do |tpj| + .pj-input + %label{ for: "piece_justificative_#{tpj.id}" } + = tpj.libelle + - if tpj.mandatory? + %span.mandatory * + + %p.piece-description= tpj.description + + - if tpj.lien_demarche.present? + %p.piece-description + Récupérer le formulaire vierge pour mon dossier : + = link_to "Télécharger", tpj.lien_demarche, target: :blank + + - if @dossier.was_piece_justificative_uploaded_for_type_id?(tpj.id) + - pj = @dossier.retrieve_last_piece_justificative_by_type(tpj.id) + %p + Pièce-jointe déjà importée : + = link_to pj.original_filename, pj.content_url, target: :blank + + = file_field_tag "piece_justificative_#{tpj.id}", + accept: PieceJustificative.accept_format, + max_file_size: 6.megabytes, + required: (tpj.mandatory? && !@dossier.was_piece_justificative_uploaded_for_type_id?(tpj.id)) + + .send-wrapper + = hidden_field_tag 'submit_action', 'draft' + + - if @dossier.brouillon? + = f.button 'Enregistrer le brouillon', + formnovalidate: true, + class: 'button send', + data: { action: 'draft', disable_with: 'Envoi...' } + + = f.button 'Soumettre le dossier', + class: 'button send primary', + data: { action: 'submit', disable_with: 'Envoi...' } + + - else + = f.button 'Modifier le dossier', + class: 'button send primary', + data: { action: 'submit', disable_with: 'Envoi...' } diff --git a/app/views/users/dossiers/_list.html.haml b/app/views/users/dossiers/_list.html.haml index 592f5695e..32eeb0b42 100644 --- a/app/views/users/dossiers/_list.html.haml +++ b/app/views/users/dossiers/_list.html.haml @@ -17,7 +17,7 @@ - dossier_url = users_dossiers_invite_path(id: invite.id) if invite.present? - if invite.nil? - dossier_url = users_dossier_recapitulatif_path(dossier) if !dossier.brouillon? - - dossier_url = users_dossier_description_path(dossier) if dossier.brouillon? + - dossier_url = modifier_dossier_path(dossier) if dossier.brouillon? %tr{ id: "tr_dossier_#{dossier.id}", 'data-dossier_url' => dossier_url } %td.center diff --git a/config/routes.rb b/config/routes.rb index aece4acc4..bbdadc93c 100644 --- a/config/routes.rb +++ b/config/routes.rb @@ -202,10 +202,11 @@ Rails.application.routes.draw do get "patron" => "root#patron" scope module: 'new_user' do - resources :dossiers, only: [] do + resources :dossiers, only: [:update] do member do get 'identite' patch 'update_identite' + get 'modifier' end get 'attestation' end diff --git a/spec/controllers/new_user/dossiers_controller_spec.rb b/spec/controllers/new_user/dossiers_controller_spec.rb index 52795cd5c..98eb991fd 100644 --- a/spec/controllers/new_user/dossiers_controller_spec.rb +++ b/spec/controllers/new_user/dossiers_controller_spec.rb @@ -81,7 +81,7 @@ describe NewUser::DossiersController, type: :controller do let(:dossier_params) { { autorisation_donnees: true } } it do - expect(response).to redirect_to(users_dossier_description_path(dossier)) + expect(response).to redirect_to(modifier_dossier_path(dossier)) end context 'on a procedure with carto' do @@ -103,4 +103,114 @@ describe NewUser::DossiersController, type: :controller do end end end + + describe '#modifier' do + before { sign_in(user) } + let!(:dossier) { create(:dossier, user: user, autorisation_donnees: true) } + + subject { get :modifier, params: { id: dossier.id } } + + context 'when autorisation_donnees is checked' do + it { is_expected.to render_template(:modifier) } + end + + context 'when autorisation_donnees is not checked' do + before { dossier.update_columns(autorisation_donnees: false) } + + context 'when the dossier is for personne morale' do + it { is_expected.to redirect_to(users_dossier_path(dossier)) } + end + + context 'when the dossier is for an personne physique' do + before { dossier.procedure.update_attributes(for_individual: true) } + + it { is_expected.to redirect_to(identite_dossier_path(dossier)) } + end + end + end + + describe '#edit' do + before { sign_in(user) } + let!(:dossier) { create(:dossier, user: user) } + + it 'returns the edit page' do + get :modifier, params: { id: dossier.id } + expect(response).to have_http_status(:success) + end + end + + describe '#update' do + before { sign_in(user) } + let!(:dossier) { create(:dossier, user: user) } + let(:first_champ) { dossier.champs.first } + let(:value) { 'beautiful value' } + let(:submit_payload) do + { + id: dossier.id, + dossier: { + champs_attributes: { + id: first_champ.id, + value: value + } + } + } + end + let(:payload) { submit_payload } + + subject { patch :update, params: payload } + + it 'updates the champs' do + subject + + expect(response).to redirect_to(users_dossier_recapitulatif_path(dossier)) + expect(first_champ.reload.value).to eq('beautiful value') + expect(dossier.reload.state).to eq('en_construction') + end + + context 'when the update fails' do + before do + expect_any_instance_of(Dossier).to receive(:update).and_return(false) + expect_any_instance_of(Dossier).to receive(:errors) + .and_return(double(full_messages: ['nop'])) + + subject + end + + it { expect(response).to render_template(:modifier) } + it { expect(flash.alert).to eq(['nop']) } + end + + context 'when the pj service returns an error' do + before do + expect(PiecesJustificativesService).to receive(:upload!).and_return(['nop']) + + subject + end + + it { expect(response).to render_template(:modifier) } + it { expect(flash.alert).to eq(['nop']) } + end + + context 'when a mandatory champ is missing' do + let(:value) { nil } + + before do + first_champ.type_de_champ.update_attributes(mandatory: true, libelle: 'l') + allow(PiecesJustificativesService).to receive(:missing_pj_error_messages).and_return(['pj']) + + subject + end + + it { expect(response).to render_template(:modifier) } + it { expect(flash.alert).to eq(['Le champ l doit être rempli.', 'pj']) } + + context 'and the user saves a draft' do + let(:payload) { submit_payload.merge(submit_action: 'draft') } + + it { expect(response).to render_template(:modifier) } + it { expect(flash.notice).to eq('Votre brouillon a bien été sauvegardé.') } + it { expect(dossier.reload.state).to eq('brouillon') } + end + end + end end diff --git a/spec/controllers/users/carte_controller_shared_example.rb b/spec/controllers/users/carte_controller_shared_example.rb index 4e250c772..229d2d3a3 100644 --- a/spec/controllers/users/carte_controller_shared_example.rb +++ b/spec/controllers/users/carte_controller_shared_example.rb @@ -59,21 +59,14 @@ shared_examples 'carte_controller_spec' do end describe 'POST #save' do - context 'Aucune localisation n\'a jamais été enregistrée' do - it do - post :save, params: { 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: 'en_construction') } before do post :save, params: { 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") + it 'Redirection vers le formulaire de la procedure' do + expect(response).to redirect_to(modifier_dossier_path(dossier)) end end diff --git a/spec/controllers/users/dossiers_controller_spec.rb b/spec/controllers/users/dossiers_controller_spec.rb index 0525b1ec7..7da275a7c 100644 --- a/spec/controllers/users/dossiers_controller_spec.rb +++ b/spec/controllers/users/dossiers_controller_spec.rb @@ -398,7 +398,7 @@ describe Users::DossiersController, type: :controller do context 'procedure not use api carto' do it 'redirects to demande' do - expect(response).to redirect_to(controller: :description, action: :show, dossier_id: dossier.id) + expect(response).to redirect_to(modifier_dossier_path(dossier)) end end diff --git a/spec/decorators/dossier_decorator_spec.rb b/spec/decorators/dossier_decorator_spec.rb index b86fcf5c8..a6be8c83e 100644 --- a/spec/decorators/dossier_decorator_spec.rb +++ b/spec/decorators/dossier_decorator_spec.rb @@ -52,30 +52,4 @@ describe DossierDecorator do expect(subject).to eq('Refusé') end end - - describe '#url' do - context "when a gestionnaire is not signed_in" do - context "when the dossier is in brouillon state" do - before do - dossier.state = 'brouillon' - dossier.save - end - - subject { super().url(false) } - - it { is_expected.to eq("/users/dossiers/#{dossier.id}/description") } - end - - context "when the dossier is not in brouillon state" do - before do - dossier.state = 'en_construction' - dossier.save - end - - subject { super().url(false) } - - it { is_expected.to eq("/users/dossiers/#{dossier.id}/recapitulatif") } - end - end - end end diff --git a/spec/factories/procedure.rb b/spec/factories/procedure.rb index 656a0631b..bb2597ccd 100644 --- a/spec/factories/procedure.rb +++ b/spec/factories/procedure.rb @@ -110,5 +110,33 @@ FactoryBot.define do procedure.archived_at = Time.now end end + + trait :with_all_champs_mandatory do + after(:build) do |procedure, _evaluator| + tdcs = [] + tdcs << create(:type_de_champ, type_champ: 'text', mandatory: true, libelle: 'text') + tdcs << create(:type_de_champ, type_champ: 'textarea', mandatory: true, libelle: 'textarea') + tdcs << create(:type_de_champ, type_champ: 'date', mandatory: true, libelle: 'date') + tdcs << create(:type_de_champ, type_champ: 'datetime', mandatory: true, libelle: 'datetime') + tdcs << create(:type_de_champ, type_champ: 'number', mandatory: true, libelle: 'number') + tdcs << create(:type_de_champ, type_champ: 'checkbox', mandatory: true, libelle: 'checkbox') + tdcs << create(:type_de_champ, type_champ: 'civilite', mandatory: true, libelle: 'civilite') + tdcs << create(:type_de_champ, type_champ: 'email', mandatory: true, libelle: 'email') + tdcs << create(:type_de_champ, type_champ: 'phone', mandatory: true, libelle: 'phone') + tdcs << create(:type_de_champ, type_champ: 'yes_no', mandatory: true, libelle: 'yes_no') + tdcs << create(:type_de_champ, :type_drop_down_list, mandatory: true, libelle: 'simple_drop_down_list') + tdcs << create(:type_de_champ, :type_drop_down_list, type_champ: 'multiple_drop_down_list', mandatory: true, libelle: 'multiple_drop_down_list') + tdcs << create(:type_de_champ, type_champ: 'pays', mandatory: true, libelle: 'pays') + tdcs << create(:type_de_champ, type_champ: 'regions', mandatory: true, libelle: 'regions') + tdcs << create(:type_de_champ, type_champ: 'departements', mandatory: true, libelle: 'departements') + tdcs << create(:type_de_champ, type_champ: 'engagement', mandatory: true, libelle: 'engagement') + tdcs << create(:type_de_champ, type_champ: 'header_section', mandatory: true, libelle: 'header_section') + tdcs << create(:type_de_champ, type_champ: 'explication', mandatory: true, libelle: 'explication') + tdcs << create(:type_de_champ, :type_dossier_link, mandatory: true, libelle: 'dossier_link') + tdcs << create(:type_de_champ, type_champ: 'piece_justificative', mandatory: true, libelle: 'piece_justificative') + + procedure.types_de_champ = tdcs + end + end end end diff --git a/spec/features/new_user/dossier_spec.rb b/spec/features/new_user/dossier_spec.rb new file mode 100644 index 000000000..38d34ea86 --- /dev/null +++ b/spec/features/new_user/dossier_spec.rb @@ -0,0 +1,155 @@ +require 'spec_helper' + +feature 'The user' do + let(:password) { 'secret_password' } + let!(:user) { create(:user, password: password) } + + let!(:procedure) { create(:procedure, :published, :for_individual, :with_all_champs_mandatory) } + let(:user_dossier) { user.dossiers.first } + + # TODO: check + # the order + # there are no extraneous input + # attached file works + scenario 'fill a dossier', js: true do + allow(Champ).to receive(:regions).and_return(['region1', 'region2']).at_least(:once) + allow(Champ).to receive(:departements).and_return(['dep1', 'dep2']).at_least(:once) + + log_in(user.email, password, procedure) + + fill_individual + + # fill data + fill_in('text', with: 'super texte') + fill_in('textarea', with: 'super textarea') + fill_in('date', with: '12/12/2012') + select_date_and_time(DateTime.parse('06/01/1985 7h05'), form_id_for('datetime')) + fill_in('number', with: '42') + check('checkbox') + choose('Madame') + fill_in('email', with: 'loulou@yopmail.com') + fill_in('phone', with: '1234567890') + choose('Non') + select('val2', from: form_id_for('simple_drop_down_list')) + select('val1', from: form_id_for('multiple_drop_down_list')) + select('val3', from: form_id_for('multiple_drop_down_list')) + select('AUSTRALIE', from: 'pays') + select('region2', from: 'regions') + select('dep2', from: 'departements') + check('engagement') + fill_in('dossier_link', with: '123') + # do not know how to make it work... + # find('form input[type="file"]').set(Rails.root.join('spec/fixtures/white.png')) + + click_on 'Enregistrer le brouillon' + + # check data on the dossier + expect(user_dossier.brouillon?).to be true + expect(champ_value_for('text')).to eq('super texte') + expect(champ_value_for('textarea')).to eq('super textarea') + expect(champ_value_for('date')).to eq('2012-12-12') + expect(champ_value_for('datetime')).to eq('06/01/1985 07:05') + expect(champ_value_for('number')).to eq('42') + expect(champ_value_for('checkbox')).to eq('on') + expect(champ_value_for('civilite')).to eq('Mme.') + expect(champ_value_for('email')).to eq('loulou@yopmail.com') + expect(champ_value_for('phone')).to eq('1234567890') + expect(champ_value_for('yes_no')).to eq('false') + expect(champ_value_for('simple_drop_down_list')).to eq('val2') + expect(JSON.parse(champ_value_for('multiple_drop_down_list'))).to match(['val1', 'val3']) + expect(champ_value_for('pays')).to eq('AUSTRALIE') + expect(champ_value_for('regions')).to eq('region2') + expect(champ_value_for('departements')).to eq('dep2') + expect(champ_value_for('engagement')).to eq('on') + expect(champ_value_for('dossier_link')).to eq('123') + + ## check data on the gui + expect(page).to have_field('text', with: 'super texte') + expect(page).to have_field('textarea', with: 'super textarea') + expect(page).to have_field('date', with: '2012-12-12') + check_date_and_time(DateTime.parse('06/01/1985 7:05'), form_id_for('datetime')) + expect(page).to have_field('number', with: '42') + expect(page).to have_checked_field('checkbox') + expect(page).to have_checked_field('Madame') + expect(page).to have_field('email', with: 'loulou@yopmail.com') + expect(page).to have_field('phone', with: '1234567890') + expect(page).to have_checked_field('Non') + expect(page).to have_select('simple_drop_down_list', selected: 'val2') + expect(page).to have_select('multiple_drop_down_list', selected: ['val1', 'val3']) + expect(page).to have_select('pays', selected: 'AUSTRALIE') + expect(page).to have_select('regions', selected: 'region2') + expect(page).to have_select('departement', selected: 'dep2') + expect(page).to have_checked_field('engagement') + expect(page).to have_field('dossier_link', with: '123') + end + + let(:simple_procedure) do + tdcs = [create(:type_de_champ, type_champ: 'text', mandatory: true, libelle: 'text')] + create(:procedure, :published, :for_individual, types_de_champ: tdcs) + end + + scenario 'save an incomplete dossier as draft but cannot not submit it', js: true do + log_in(user.email, password, simple_procedure) + fill_individual + + click_on 'Enregistrer le brouillon' + expect(page).to have_content('Votre brouillon a bien été sauvegardé') + expect(page).to have_current_path(dossier_path(user_dossier)) + + click_on 'Soumettre le dossier' + expect(user_dossier.reload.brouillon?).to be(true) + expect(page).to have_current_path(dossier_path(user_dossier)) + + fill_in('text', with: 'super texte') + + click_on 'Soumettre le dossier' + expect(user_dossier.reload.en_construction?).to be(true) + expect(champ_value_for('text')).to eq('super texte') + expect(page).to have_current_path(users_dossier_recapitulatif_path(user_dossier)) + end + + private + + def log_in(email, password, procedure) + visit "/commencer/#{procedure.procedure_path.path}" + expect(page).to have_current_path(new_user_session_path) + + fill_in 'user_email', with: email + fill_in 'user_password', with: password + click_on 'Se connecter' + expect(page).to have_current_path(identite_dossier_path(user_dossier)) + end + + def form_id_for(libelle) + find(:xpath, ".//label[contains(text()[normalize-space()], '#{libelle}')]")[:for] + end + + def champ_value_for(libelle) + champs = user_dossier.champs + champs.find { |c| c.libelle == libelle }.value + end + + def fill_individual + fill_in('individual_prenom', with: 'prenom') + fill_in('individual_nom', with: 'nom') + check 'dossier_autorisation_donnees' + click_on 'Continuer' + expect(page).to have_current_path(modifier_dossier_path(user_dossier)) + end + + def select_date_and_time(date, field) + select date.strftime('%Y'), from: "#{field}_1i" # year + select I18n.l(date, format: '%B'), from: "#{field}_2i" # month + select date.strftime('%-d'), from: "#{field}_3i" # day + select date.strftime('%H'), from: "#{field}_4i" # hour + select date.strftime('%M'), from: "#{field}_5i" # minute + end + + def check_date_and_time(date, field) + expect(page).to have_select("#{field}_1i", selected: date.strftime('%Y')) + expect(page).to have_select("#{field}_2i", selected: I18n.l(date, format: '%B')) + expect(page).to have_select("#{field}_3i", selected: date.strftime('%-d')) + expect(page).to have_select("#{field}_4i", selected: date.strftime('%H')) + expect(page).to have_select("#{field}_5i", selected: date.strftime('%M')) + end +end diff --git a/spec/features/users/complete_demande_spec.rb b/spec/features/users/complete_demande_spec.rb index d763ec450..cdccbe89a 100644 --- a/spec/features/users/complete_demande_spec.rb +++ b/spec/features/users/complete_demande_spec.rb @@ -63,13 +63,13 @@ feature 'user path for dossier creation' do page.check('dossier_autorisation_donnees') page.find_by_id('etape_suivante').click end - scenario 'user is on description page' do - expect(page).to have_css('#description-page') + scenario 'user is on edition page' do + expect(page).to have_current_path(modifier_dossier_path(Dossier.last)) end context 'user fill and validate description page' do before do - page.find_by_id("champs_#{Dossier.last.champs.first.id}").set 'Mon super projet' - page.find_by_id('suivant').click + page.find_by_id("dossier_champs_attributes_0_value").set 'Mon super projet' + click_on 'Soumettre le dossier' end scenario 'user is on recap page' do expect(page).to have_css('#users-recapitulatif-dossier-show') diff --git a/spec/features/users/dossier_creation_spec.rb b/spec/features/users/dossier_creation_spec.rb index 19f7fb6fa..989822067 100644 --- a/spec/features/users/dossier_creation_spec.rb +++ b/spec/features/users/dossier_creation_spec.rb @@ -28,13 +28,9 @@ feature 'As a User I wanna create a dossier' do expect(page).to have_current_path(users_dossier_carte_path(procedure_for_individual.dossiers.last.id)) click_button('Etape suivante') - expect(page).to have_current_path(users_dossier_description_path(procedure_for_individual.dossiers.last.id)) - fill_in "champs_#{procedure_for_individual.dossiers.last.champs.first.id}", with: 'contenu du champ 1' - find(:css, '[name=submit_action]').set('nouveaux') - click_button('suivant') + expect(page).to have_current_path(modifier_dossier_path(procedure_for_individual.dossiers.last)) expect(user.dossiers.first.individual.birthdate).to eq("1987-10-14") - expect(page).to have_current_path(users_dossier_recapitulatif_path(procedure_for_individual.dossiers.last.id.to_s)) end scenario "with a basic text input field for birthdate (type='date' unsupported)" do @@ -44,12 +40,9 @@ feature 'As a User I wanna create a dossier' do expect(page).to have_current_path(users_dossier_carte_path(procedure_for_individual.dossiers.last.id.to_s)) click_button('Etape suivante') - fill_in "champs_#{procedure_for_individual.dossiers.last.champs.first.id}", with: 'contenu du champ 1' - find(:css, '[name=submit_action]').set('nouveaux') - page.find_by_id('suivant').click + expect(page).to have_current_path(modifier_dossier_path(procedure_for_individual.dossiers.last)) expect(user.dossiers.first.individual.birthdate).to eq("1987-10-14") - expect(page).to have_current_path(users_dossier_recapitulatif_path(procedure_for_individual.dossiers.last.id.to_s)) end end @@ -59,15 +52,12 @@ feature 'As a User I wanna create a dossier' do scenario "no need for birthday" do click_button('Continuer') - expect(page).to have_current_path(users_dossier_carte_path(procedure_for_individual.dossiers.last.id.to_s)) + expect(page).to have_current_path(users_dossier_carte_path(procedure_for_individual.dossiers.last)) click_button('Etape suivante') - fill_in "champs_#{procedure_for_individual.dossiers.last.champs.first.id}", with: 'contenu du champ 1' - find(:css, '[name=submit_action]').set('nouveaux') - click_button('suivant') + expect(page).to have_current_path(modifier_dossier_path(procedure_for_individual.dossiers.last)) expect(user.dossiers.first.individual.birthdate).to eq(nil) - expect(page).to have_current_path(users_dossier_recapitulatif_path(procedure_for_individual.dossiers.last.id.to_s)) end end end @@ -92,9 +82,7 @@ feature 'As a User I wanna create a dossier' do page.find_by_id('etape_suivante').click expect(page).to have_current_path(users_dossier_carte_path(procedure_with_siret.dossiers.last.id.to_s)) page.find_by_id('etape_suivante').click - fill_in "champs_#{procedure_with_siret.dossiers.last.champs.first.id}", with: 'contenu du champ 1' - page.find_by_id('suivant').click - expect(page).to have_current_path(users_dossier_recapitulatif_path(procedure_with_siret.dossiers.last.id.to_s)) + expect(page).to have_current_path(modifier_dossier_path(procedure_with_siret.dossiers.last)) end end end diff --git a/spec/features/users/dossier_edition_spec.rb b/spec/features/users/dossier_edition_spec.rb deleted file mode 100644 index 3de44ef52..000000000 --- a/spec/features/users/dossier_edition_spec.rb +++ /dev/null @@ -1,49 +0,0 @@ -require 'spec_helper' - -feature 'As a User I want to edit a dossier I own' do - let(:user) { create(:user) } - let(:procedure_for_individual) { create(:procedure, :published, :for_individual, :with_type_de_champ, :with_two_type_de_piece_justificative, :with_dossier_link) } - let!(:dossier) { create(:dossier, :with_entreprise, :for_individual, :with_dossier_link, procedure: procedure_for_individual, user: user, autorisation_donnees: true, state: 'en_construction') } - - before "Create dossier and visit root path" do - login_as user, scope: :user - visit root_path - end - - context 'After sign_in, I can navigate through dossiers indexes and edit a dossier' do - scenario 'After sign_in, I can see dossiers "à traiter" (default), and other indexes' do - expect(page.find('#a_traiter')['class']).to eq('active procedure-list-element') - page.find_by_id('brouillon').click - page.find_by_id('a_traiter').click - page.find_by_id('en_instruction').click - page.find_by_id('termine').click - page.find_by_id('invite').click - end - - scenario 'Getting a dossier, I want to create a new message on', js: true do - page.find_by_id("tr_dossier_#{dossier.id.to_s}").click - expect(page).to have_current_path(users_dossier_recapitulatif_path(Dossier.first.id.to_s)) - page.find_by_id('open-message').click - page.execute_script("$('#texte_commentaire').data('wysihtml5').editor.setValue('Contenu du nouveau message')") - page.find_by_id('save-message').click - expect(page.find('.last-commentaire .content').text).to eq('Contenu du nouveau message') - end - - scenario 'On the same dossier, I want to edit informations', js: true do - page.find_by_id("tr_dossier_#{dossier.id.to_s}").click - expect(page).to have_current_path(users_dossier_recapitulatif_path(dossier.id.to_s)) - - # Linked Dossier - linked_dossier_id = dossier.champs.find { |c| c.type_de_champ.type_champ == 'dossier_link' }.value - expect(page).to have_link("Dossier #{linked_dossier_id}") - - page.find_by_id('edit-dossier').click - expect(page).to have_current_path(users_dossier_description_path(dossier.id.to_s)) - champ_id = dossier.champs.find { |t| t.type_champ == "text" }.id - fill_in "champs_#{champ_id.to_s}", with: 'Contenu du champ 1' - page.find_by_id('modification_terminee').click - expect(page).to have_current_path(users_dossier_recapitulatif_path(dossier.id.to_s)) - expect(page.find("#champ-#{champ_id}-value").text).to eq('Contenu du champ 1') - 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 27c86c652..0681bd895 100644 --- a/spec/views/users/recapitulatif/show.html.haml_spec.rb +++ b/spec/views/users/recapitulatif/show.html.haml_spec.rb @@ -30,8 +30,8 @@ describe 'users/recapitulatif/show.html.haml', type: :view do expect(rendered).to have_css('#maj_infos') end - it 'le lien vers description est correct' do - expect(rendered).to have_selector("a[id=maj_infos][href='/users/dossiers/#{dossier_id}/description']") + it 'le lien vers l édition est correct' do + expect(rendered).to have_selector("a[id=maj_infos][href='/dossiers/#{dossier_id}/modifier']") end end