From 0a10a08c21ce0657d58eae6835b5282c88df0a63 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?S=C3=A9bastien=20Carceles?= Date: Mon, 19 Dec 2022 12:32:09 +0100 Subject: [PATCH] feat(demarche): describe procedure prefilling (#8187) * feat(demarche): description Show the description of an opendata procedure (published or draft), with help about how to prefill a dossier for this procedure. Co-authored-by: Damien Le Thiec --- app/assets/stylesheets/code_blocks.scss | 13 +++ app/assets/stylesheets/confirmations.scss | 1 + .../prefill_descriptions_controller.rb | 32 ++++++ app/models/champ.rb | 1 + app/models/prefill_description.rb | 46 ++++++++ app/models/prefill_params.rb | 16 +-- app/models/procedure.rb | 19 ++-- app/models/type_de_champ.rb | 12 +++ .../_prefill_link.html.haml | 15 +++ .../_types_de_champs.html.haml | 44 ++++++++ app/views/prefill_descriptions/edit.html.haml | 19 ++++ .../update.turbo_stream.haml | 5 + config/locales/en.yml | 17 +++ config/locales/fr.yml | 19 +++- config/routes.rb | 13 +++ .../prefillings_controller_spec.rb | 100 ++++++++++++++++++ spec/factories/procedure.rb | 4 + spec/models/prefill_description_spec.rb | 79 ++++++++++++++ spec/models/type_de_champ_spec.rb | 47 ++++++++ .../integrateurs/procedure_prefilling_spec.rb | 21 ++++ 20 files changed, 497 insertions(+), 26 deletions(-) create mode 100644 app/assets/stylesheets/code_blocks.scss create mode 100644 app/controllers/prefill_descriptions_controller.rb create mode 100644 app/models/prefill_description.rb create mode 100644 app/views/prefill_descriptions/_prefill_link.html.haml create mode 100644 app/views/prefill_descriptions/_types_de_champs.html.haml create mode 100644 app/views/prefill_descriptions/edit.html.haml create mode 100644 app/views/prefill_descriptions/update.turbo_stream.haml create mode 100644 spec/controllers/prefillings_controller_spec.rb create mode 100644 spec/models/prefill_description_spec.rb create mode 100644 spec/system/integrateurs/procedure_prefilling_spec.rb diff --git a/app/assets/stylesheets/code_blocks.scss b/app/assets/stylesheets/code_blocks.scss new file mode 100644 index 000000000..cfae3c2b5 --- /dev/null +++ b/app/assets/stylesheets/code_blocks.scss @@ -0,0 +1,13 @@ +@import "colors"; + +.code-block { + background-color: $black; + color: $white; + border-radius: 3px; + padding: 2rem; + display: flex; + align-items: center; + font-weight: bold; + justify-content: center; + overflow: auto; +} diff --git a/app/assets/stylesheets/confirmations.scss b/app/assets/stylesheets/confirmations.scss index 2936770e0..b028d4419 100644 --- a/app/assets/stylesheets/confirmations.scss +++ b/app/assets/stylesheets/confirmations.scss @@ -37,6 +37,7 @@ } .confirmation-resend { + p, label { margin-bottom: $default-padding; diff --git a/app/controllers/prefill_descriptions_controller.rb b/app/controllers/prefill_descriptions_controller.rb new file mode 100644 index 000000000..801a7753c --- /dev/null +++ b/app/controllers/prefill_descriptions_controller.rb @@ -0,0 +1,32 @@ +class PrefillDescriptionsController < ApplicationController + before_action :retrieve_procedure + before_action :set_prefill_description + + def edit + end + + def update + @prefill_description.update(prefill_description_params) + + respond_to do |format| + format.turbo_stream + format.html { render :edit } + end + end + + private + + def retrieve_procedure + @procedure = Procedure.publiees_ou_brouillons.opendata.find_by!(path: params[:path]) + end + + def set_prefill_description + @prefill_description = PrefillDescription.new(@procedure) + end + + def prefill_description_params + params.require(:procedure).permit(selected_type_de_champ_ids: []) + rescue ActionController::ParameterMissing + { selected_type_de_champ_ids: [] } + end +end diff --git a/app/models/champ.rb b/app/models/champ.rb index 5b9f0b4e6..1833f5cde 100644 --- a/app/models/champ.rb +++ b/app/models/champ.rb @@ -66,6 +66,7 @@ class Champ < ApplicationRecord :carte?, :stable_id, :mandatory?, + :prefillable?, to: :type_de_champ scope :updated_since?, -> (date) { where('champs.updated_at > ?', date) } diff --git a/app/models/prefill_description.rb b/app/models/prefill_description.rb new file mode 100644 index 000000000..255ad3adb --- /dev/null +++ b/app/models/prefill_description.rb @@ -0,0 +1,46 @@ +class PrefillDescription < SimpleDelegator + include Rails.application.routes.url_helpers + + MAX_PREFILL_LINK_LENGTH = 2000 + + attr_reader :selected_type_de_champ_ids + + def initialize(procedure) + super(procedure) + @selected_type_de_champ_ids = [] + end + + def update(attributes) + @selected_type_de_champ_ids = attributes[:selected_type_de_champ_ids].presence || [] + end + + def types_de_champ + active_revision.types_de_champ_public + end + + def include?(type_de_champ_id) + selected_type_de_champ_ids.include?(type_de_champ_id.to_s) + end + + def link_too_long? + prefill_link.length > MAX_PREFILL_LINK_LENGTH + end + + def prefill_link + @prefill_link ||= commencer_url({ path: path }.merge(prefilled_champs_for_link)) + end + + def prefilled_champs + @prefilled_champs ||= types_de_champ.where(id: selected_type_de_champ_ids) + end + + private + + def prefilled_champs_for_link + prefilled_champs.map { |type_de_champ| ["champ_#{type_de_champ.to_typed_id}", type_de_champ.libelle] }.to_h + end + + def prefilled_champs_for_query + prefilled_champs.map { |type_de_champ| "\"champ_#{type_de_champ.to_typed_id}\": \"#{type_de_champ.libelle}\"" } .join(', ') + end +end diff --git a/app/models/prefill_params.rb b/app/models/prefill_params.rb index 8e94828c8..d536deed5 100644 --- a/app/models/prefill_params.rb +++ b/app/models/prefill_params.rb @@ -31,16 +31,6 @@ class PrefillParams end class PrefillValue - AUTHORIZED_TYPES_DE_CHAMPS = [ - TypeDeChamp.type_champs.fetch(:text), - TypeDeChamp.type_champs.fetch(:textarea), - TypeDeChamp.type_champs.fetch(:decimal_number), - TypeDeChamp.type_champs.fetch(:integer_number), - TypeDeChamp.type_champs.fetch(:email), - TypeDeChamp.type_champs.fetch(:phone), - TypeDeChamp.type_champs.fetch(:iban) - ] - NEED_VALIDATION_TYPES_DE_CHAMPS = [ TypeDeChamp.type_champs.fetch(:decimal_number), TypeDeChamp.type_champs.fetch(:integer_number) @@ -54,7 +44,7 @@ class PrefillParams end def prefillable? - authorized? && valid? + champ.prefillable? && valid? end def to_h @@ -66,10 +56,6 @@ class PrefillParams private - def authorized? - AUTHORIZED_TYPES_DE_CHAMPS.include?(champ.type_champ) - end - def valid? return true unless NEED_VALIDATION_TYPES_DE_CHAMPS.include?(champ.type_champ) diff --git a/app/models/procedure.rb b/app/models/procedure.rb index 708b6bf4d..ede8d11bc 100644 --- a/app/models/procedure.rb +++ b/app/models/procedure.rb @@ -204,15 +204,16 @@ class Procedure < ApplicationRecord has_one_attached :notice has_one_attached :deliberation - scope :brouillons, -> { where(aasm_state: :brouillon) } - scope :publiees, -> { where(aasm_state: :publiee) } - scope :closes, -> { where(aasm_state: [:close, :depubliee]) } - scope :opendata, -> { where(opendata: true) } - scope :publiees_ou_closes, -> { where(aasm_state: [:publiee, :close, :depubliee]) } - scope :by_libelle, -> { order(libelle: :asc) } - scope :created_during, -> (range) { where(created_at: range) } - scope :cloned_from_library, -> { where(cloned_from_library: true) } - scope :declarative, -> { where.not(declarative_with_state: nil) } + scope :brouillons, -> { where(aasm_state: :brouillon) } + scope :publiees, -> { where(aasm_state: :publiee) } + scope :publiees_ou_brouillons, -> { publiees.or(brouillons) } + scope :closes, -> { where(aasm_state: [:close, :depubliee]) } + scope :opendata, -> { where(opendata: true) } + scope :publiees_ou_closes, -> { where(aasm_state: [:publiee, :close, :depubliee]) } + scope :by_libelle, -> { order(libelle: :asc) } + scope :created_during, -> (range) { where(created_at: range) } + scope :cloned_from_library, -> { where(cloned_from_library: true) } + scope :declarative, -> { where.not(declarative_with_state: nil) } scope :discarded_expired, -> do with_discarded diff --git a/app/models/type_de_champ.rb b/app/models/type_de_champ.rb index 6f5c1b478..774dd9e50 100644 --- a/app/models/type_de_champ.rb +++ b/app/models/type_de_champ.rb @@ -251,6 +251,18 @@ class TypeDeChamp < ApplicationRecord collapsible_explanation_enabled == "1" end + def prefillable? + type_champ.in?([ + TypeDeChamp.type_champs.fetch(:text), + TypeDeChamp.type_champs.fetch(:textarea), + TypeDeChamp.type_champs.fetch(:decimal_number), + TypeDeChamp.type_champs.fetch(:integer_number), + TypeDeChamp.type_champs.fetch(:email), + TypeDeChamp.type_champs.fetch(:phone), + TypeDeChamp.type_champs.fetch(:iban) + ]) + end + def fillable? !non_fillable? end diff --git a/app/views/prefill_descriptions/_prefill_link.html.haml b/app/views/prefill_descriptions/_prefill_link.html.haml new file mode 100644 index 000000000..07a0f2811 --- /dev/null +++ b/app/views/prefill_descriptions/_prefill_link.html.haml @@ -0,0 +1,15 @@ += turbo_frame_tag "#{dom_id(prefill_description)}_url" do + - theme = prefill_description.link_too_long? ? :warning : :success + - icon = prefill_description.link_too_long? ? "fr-icon-warning-fill" : "fr-icon-paint-fill" + - body = prefill_description.link_too_long? ? t("views.prefill_descriptions.edit.prefill_link_too_long") : t("views.prefill_descriptions.edit.prefill_link_info") + + - if prefill_description.prefilled_champs.any? + = render Dsfr::CalloutComponent.new(title: t("views.prefill_descriptions.edit.prefill_link_title"), theme: theme, icon: icon) do |c| + - c.with_body do + = body + %pre + %code.code-block + = prefill_description.prefill_link + - unless prefill_description.link_too_long? + - c.with_bottom do + = render Dsfr::CopyButtonComponent.new(title: t("views.prefill_descriptions.edit.prefill_link_copy"), text: prefill_description.prefill_link) diff --git a/app/views/prefill_descriptions/_types_de_champs.html.haml b/app/views/prefill_descriptions/_types_de_champs.html.haml new file mode 100644 index 000000000..6c877878d --- /dev/null +++ b/app/views/prefill_descriptions/_types_de_champs.html.haml @@ -0,0 +1,44 @@ += turbo_frame_tag "#{dom_id(@prefill_description)}_types_de_champs" do + .card + .card-title + %span.icon.edit + = t("views.prefill_descriptions.edit.champs_title") + + %table.table.hoverable + %thead + %tr + %th + = t("views.prefill_descriptions.edit.champ_id") + %th + = t("views.prefill_descriptions.edit.champ_type") + %th + = t("views.prefill_descriptions.edit.champ_libelle") + %th + = t("views.prefill_descriptions.edit.champ_description") + %th + = t("views.prefill_descriptions.edit.champ_prefill") + + %tbody + - prefill_description.types_de_champ.each do |type_de_champ| + %tr + %td + = type_de_champ.to_typed_id + %td + = t("activerecord.attributes.type_de_champ.type_champs.#{type_de_champ.type_champ}") + %td + = type_de_champ.libelle + %td + = type_de_champ.description + %td.text-center + = form_for prefill_description, url: prefill_description_path(prefill_description.path), data: { turbo: true } do |f| + - if prefill_description.include?(type_de_champ.id) + - (prefill_description.selected_type_de_champ_ids - [type_de_champ.id.to_s]).each do |id| + = f.hidden_field :selected_type_de_champ_ids, value: id, multiple: true + = f.submit t("views.prefill_descriptions.edit.champ_remove"), class: 'fr-btn fr-btn--secondary fr-btn--md' + - elsif type_de_champ.prefillable? + - (prefill_description.selected_type_de_champ_ids + [type_de_champ.id.to_s]).each do |id| + = f.hidden_field :selected_type_de_champ_ids, value: id, multiple: true + = f.submit t("views.prefill_descriptions.edit.champ_add"), class: 'fr-btn fr-btn--md' + - else + %button.fr-btn.fr-btn--secondary{ disabled: true } + = t("views.prefill_descriptions.edit.champ_unavailable") diff --git a/app/views/prefill_descriptions/edit.html.haml b/app/views/prefill_descriptions/edit.html.haml new file mode 100644 index 000000000..48299b171 --- /dev/null +++ b/app/views/prefill_descriptions/edit.html.haml @@ -0,0 +1,19 @@ +- content_for(:title, @prefill_description.libelle) + +- content_for :footer do + = render partial: "root/footer" + +.container + .two-columns.procedure-context + .columns-container + .column.procedure-preview + = render partial: 'shared/procedure_description', locals: { procedure: @prefill_description } + .column.procedure-context-content + %p + = t("views.prefill_descriptions.edit.intro_html", libelle: @prefill_description.libelle) + %p + = t("views.prefill_descriptions.edit.info") + + = render "types_de_champs", prefill_description: @prefill_description + + = render "prefill_link", prefill_description: @prefill_description diff --git a/app/views/prefill_descriptions/update.turbo_stream.haml b/app/views/prefill_descriptions/update.turbo_stream.haml new file mode 100644 index 000000000..711bdeceb --- /dev/null +++ b/app/views/prefill_descriptions/update.turbo_stream.haml @@ -0,0 +1,5 @@ += turbo_stream.replace "#{dom_id(@prefill_description)}_types_de_champs" do + = render "types_de_champs", prefill_description: @prefill_description + += turbo_stream.replace "#{dom_id(@prefill_description)}_url" do + = render "prefill_link", prefill_description: @prefill_description diff --git a/config/locales/en.yml b/config/locales/en.yml index a8968b54b..4d9bcc818 100644 --- a/config/locales/en.yml +++ b/config/locales/en.yml @@ -101,6 +101,23 @@ en: show_my_submitted_file: 'Show my submitted file' want_empty_pdf: "You prefer to submit a paper form? You can download an empty PDF file, and send it to the right administration : %{service} - %{adresse}" download_empty_pdf: 'Download an empty PDF file' + prefill_descriptions: + edit: + intro_html: "You'd like to allow your users to create a prefilled file, with data you already have, for the procedure « %{libelle} »." + info: Add the fields you want to prefill, thanks to the table below. Once it's over, copy the prefill link, replace the values and share the link. + champs_title: Fields + champ_id: ID + champ_type: Type + champ_libelle: Label + champ_description: Description + champ_prefill: Prefillable + champ_add: Add + champ_remove: Remove + champ_unavailable: Unavailable + prefill_link_title: Prefill link (GET) + prefill_link_info: Use the button to copy the link, then remplace the values with your data. + prefill_link_too_long: Warning, the prefill link is too long and may not work on all browsers. + prefill_link_copy: Copy prefill link registrations: new: title: "Create an account %{name}" diff --git a/config/locales/fr.yml b/config/locales/fr.yml index fe5867b28..1a30c82c6 100644 --- a/config/locales/fr.yml +++ b/config/locales/fr.yml @@ -91,6 +91,23 @@ fr: show_my_submitted_file: 'Voir mon dossier déposé' want_empty_pdf: "Vous souhaitez effectuer une demande par papier ? Vous pouvez télécharger un dossier vide au format PDF, et l’envoyer à l’administration concernée : %{service} - %{adresse}" download_empty_pdf: 'Télécharger un dossier vide au format PDF' + prefill_descriptions: + edit: + intro_html: "Vous souhaitez permettre à vos usager·ères la création d'un dossier prérempli, à partir de données dont vous disposez déjà, pour la démarche « %{libelle} »." + info: Pour cela, ajoutez les champs que vous souhaitez préremplir, grâce au tableau ci-dessous. Lorsque vous avez terminé, il ne vous reste plus qu'à copier le lien de préremplissage, à remplacer les valeurs et à le partager. + champs_title: Champs de la démarche + champ_id: ID + champ_type: Type + champ_libelle: Libellé + champ_description: Description + champ_prefill: Préremplissable + champ_add: Ajouter + champ_remove: Retirer + champ_unavailable: Indisponible + prefill_link_title: Lien de préremplissage (GET) + prefill_link_info: Copiez le lien grâce au bouton ci-dessous et remplacez les valeurs par les données dont vous disposez. + prefill_link_too_long: Attention, ce lien de préremplissage est trop long et risque de ne pas fonctionner sur certains navigateurs. + prefill_link_copy: Copier le lien de préremplissage registrations: new: title: "Créez-vous un compte %{name}" @@ -99,8 +116,6 @@ fr: wanna_say: 'Voulez-vous dire' password_label: "Mot de passe (%{min_length} caractères minimum)" password_placeholder: "%{min_length} caractères minimum" - - invites: dropdown: invite_to_edit: Inviter une personne à modifier ce dossier diff --git a/config/routes.rb b/config/routes.rb index bc7bc71b4..e762ae61b 100644 --- a/config/routes.rb +++ b/config/routes.rb @@ -189,6 +189,13 @@ Rails.application.routes.draw do post "webhooks/helpscout_support_dev", to: "webhook#helpscout_support_dev" match "webhooks/helpscout", to: lambda { |_| [204, {}, nil] }, via: :head + get '/preremplir/:path', to: 'prefill_descriptions#edit' + resources :procedures, only: [], param: :path do + member do + resource :prefill_description, only: :update + end + end + # # Deprecated UI # @@ -251,6 +258,12 @@ Rails.application.routes.draw do end resources :pays, only: :index + + namespace :public do + namespace :v1 do + resources :dossiers, only: :create + end + end end # diff --git a/spec/controllers/prefillings_controller_spec.rb b/spec/controllers/prefillings_controller_spec.rb new file mode 100644 index 000000000..75e776a4e --- /dev/null +++ b/spec/controllers/prefillings_controller_spec.rb @@ -0,0 +1,100 @@ +describe PrefillDescriptionsController, type: :controller do + describe '#edit' do + subject(:edit_request) do + get :edit, params: { path: procedure.path } + end + + context 'when the procedure is found' do + context 'when the procedure is publiee' do + context 'when the procedure is opendata' do + let(:procedure) { create(:procedure, :published, opendata: true) } + + it { expect(edit_request).to render_template(:edit) } + end + + context 'when the procedure is not opendata' do + let(:procedure) { create(:procedure, :published, opendata: false) } + + it { expect { edit_request }.to raise_error(ActiveRecord::RecordNotFound) } + end + end + + context 'when the procedure is brouillon' do + context 'when the procedure is opendata' do + let(:procedure) { create(:procedure, :draft, opendata: true) } + + it { expect(edit_request).to render_template(:edit) } + end + + context 'when the procedure is not opendata' do + let(:procedure) { create(:procedure, :draft, opendata: false) } + + it { expect { edit_request }.to raise_error(ActiveRecord::RecordNotFound) } + end + end + + context 'when the procedure is not publiee and not brouillon' do + let(:procedure) { create(:procedure, :closed) } + + it { expect { edit_request }.to raise_error(ActiveRecord::RecordNotFound) } + end + end + + context 'when the procedure is not found' do + let(:procedure) { double(Procedure, path: "wrong path") } + + it { expect { edit_request }.to raise_error(ActiveRecord::RecordNotFound) } + end + end + + describe "#update" do + render_views + + let(:procedure) { create(:procedure, :published, opendata: true) } + let(:type_de_champ) { create(:type_de_champ_text, procedure: procedure) } + let(:type_de_champ2) { create(:type_de_champ_text, procedure: procedure) } + + subject(:update_request) do + patch :update, params: { path: procedure.path, procedure: params }, format: :turbo_stream + end + + before { update_request } + + context 'when adding a type_de_champ_id' do + let(:type_de_champ_to_add) { create(:type_de_champ_text, procedure: procedure) } + let(:params) { { selected_type_de_champ_ids: [type_de_champ.id, type_de_champ_to_add.id] } } + + it { expect(response).to render_template(:update) } + + it "includes the prefill URL" do + expect(response.body).to include(commencer_path(path: procedure.path)) + expect(response.body).to include({ "champ_#{type_de_champ.to_typed_id}" => type_de_champ.libelle }.to_query) + expect(response.body).to include({ "champ_#{type_de_champ_to_add.to_typed_id}" => type_de_champ_to_add.libelle }.to_query) + end + end + + context 'when removing a type_de_champ_id' do + let(:type_de_champ_to_remove) { type_de_champ2 } + let(:params) { { selected_type_de_champ_ids: [type_de_champ] } } + + it { expect(response).to render_template(:update) } + + it "includes the prefill URL" do + expect(response.body).to include(commencer_path(path: procedure.path)) + expect(response.body).to include({ "champ_#{type_de_champ.to_typed_id}" => type_de_champ.libelle }.to_query) + expect(response.body).not_to include({ "champ_#{type_de_champ_to_remove.to_typed_id}" => type_de_champ_to_remove.libelle }.to_query) + end + end + + context 'when removing the last type de champ' do + let(:type_de_champ_to_remove) { type_de_champ } + let(:params) { { selected_type_de_champ_ids: [] } } + + it { expect(response).to render_template(:update) } + + it "does not include the prefill URL" do + expect(response.body).not_to include(commencer_path(path: procedure.path)) + end + end + end +end diff --git a/spec/factories/procedure.rb b/spec/factories/procedure.rb index 380fa69ce..544029c75 100644 --- a/spec/factories/procedure.rb +++ b/spec/factories/procedure.rb @@ -279,6 +279,10 @@ FactoryBot.define do end end + trait :draft do + aasm_state { :brouillon } + end + trait :published do aasm_state { :publiee } path { generate(:published_path) } diff --git a/spec/models/prefill_description_spec.rb b/spec/models/prefill_description_spec.rb new file mode 100644 index 000000000..630dc3290 --- /dev/null +++ b/spec/models/prefill_description_spec.rb @@ -0,0 +1,79 @@ +RSpec.describe PrefillDescription, type: :model do + include Rails.application.routes.url_helpers + + describe '#update' do + let(:prefill_description) { described_class.new(build(:procedure)) } + let(:selected_type_de_champ_ids) { ["1", "2"] } + subject(:update) { prefill_description.update(attributes) } + + context 'when selected_type_de_champ_ids are given' do + let(:attributes) { { selected_type_de_champ_ids: selected_type_de_champ_ids } } + + it 'populate selected_type_de_champ_ids' do + expect { update }.to change { prefill_description.selected_type_de_champ_ids }.from([]).to(selected_type_de_champ_ids) + end + end + end + + describe '#types_de_champ' do + let(:procedure) { create(:procedure) } + let(:type_de_champ) { create(:type_de_champ_text, procedure: procedure) } + let(:prefill_description) { described_class.new(procedure) } + + it { expect(prefill_description.types_de_champ).to match([type_de_champ]) } + end + + describe '#include?' do + let(:prefill_description) { described_class.new(build(:procedure)) } + let(:type_de_champ_id) { 1 } + subject(:included) { prefill_description.include?(type_de_champ_id) } + + context 'when the id has been added to the prefill_description' do + before { prefill_description.update(selected_type_de_champ_ids: ["1"]) } + + it { expect(included).to eq(true) } + end + + context 'when the id has not be added to the prefill_description' do + it { expect(included).to eq(false) } + end + end + + describe '#link_too_long?' do + let(:procedure) { create(:procedure) } + let(:prefill_description) { described_class.new(procedure) } + + subject(:too_long) { prefill_description.link_too_long? } + + before { prefill_description.update(selected_type_de_champ_ids: create_list(:type_de_champ_text, type_de_champs_count, procedure: procedure).map(&:id)) } + + context 'when the prefill link is too long' do + let(:type_de_champs_count) { 60 } + + it { expect(too_long).to eq(true) } + end + + context 'when the prefill link is not too long' do + let(:type_de_champs_count) { 2 } + + it { expect(too_long).to eq(false) } + end + end + + describe '#prefill_link' do + let(:procedure) { create(:procedure) } + let(:type_de_champ) { create(:type_de_champ_text, procedure: procedure) } + let(:prefill_description) { described_class.new(procedure) } + + before { prefill_description.update(selected_type_de_champ_ids: [type_de_champ.id]) } + + it "builds the URL to create a new prefilled dossier" do + expect(prefill_description.prefill_link).to eq( + commencer_url( + path: procedure.path, + "champ_#{type_de_champ.to_typed_id}" => type_de_champ.libelle + ) + ) + end + end +end diff --git a/spec/models/type_de_champ_spec.rb b/spec/models/type_de_champ_spec.rb index 2b96be0cb..9c57ce6d2 100644 --- a/spec/models/type_de_champ_spec.rb +++ b/spec/models/type_de_champ_spec.rb @@ -225,4 +225,51 @@ describe TypeDeChamp do expect(type_de_champ.condition).to eq(condition) end end + + describe '#prefillable?' do + shared_examples 'a prefillable type de champ' do |factory| + it { expect(build(factory).prefillable?).to eq(true) } + end + + shared_examples 'a non-prefillable type de champ' do |factory| + it { expect(build(factory).prefillable?).to eq(false) } + end + + it_behaves_like "a prefillable type de champ", :type_de_champ_text + it_behaves_like "a prefillable type de champ", :type_de_champ_textarea + it_behaves_like "a prefillable type de champ", :type_de_champ_decimal_number + it_behaves_like "a prefillable type de champ", :type_de_champ_integer_number + it_behaves_like "a prefillable type de champ", :type_de_champ_email + it_behaves_like "a prefillable type de champ", :type_de_champ_phone + it_behaves_like "a prefillable type de champ", :type_de_champ_iban + + it_behaves_like "a non-prefillable type de champ", :type_de_champ_number + it_behaves_like "a non-prefillable type de champ", :type_de_champ_communes + it_behaves_like "a non-prefillable type de champ", :type_de_champ_dossier_link + it_behaves_like "a non-prefillable type de champ", :type_de_champ_titre_identite + it_behaves_like "a non-prefillable type de champ", :type_de_champ_checkbox + it_behaves_like "a non-prefillable type de champ", :type_de_champ_civilite + it_behaves_like "a non-prefillable type de champ", :type_de_champ_yes_no + it_behaves_like "a non-prefillable type de champ", :type_de_champ_date + it_behaves_like "a non-prefillable type de champ", :type_de_champ_datetime + it_behaves_like "a non-prefillable type de champ", :type_de_champ_drop_down_list + it_behaves_like "a non-prefillable type de champ", :type_de_champ_multiple_drop_down_list + it_behaves_like "a non-prefillable type de champ", :type_de_champ_linked_drop_down_list + it_behaves_like "a non-prefillable type de champ", :type_de_champ_header_section + it_behaves_like "a non-prefillable type de champ", :type_de_champ_explication + it_behaves_like "a non-prefillable type de champ", :type_de_champ_piece_justificative + it_behaves_like "a non-prefillable type de champ", :type_de_champ_repetition + it_behaves_like "a non-prefillable type de champ", :type_de_champ_cnaf + it_behaves_like "a non-prefillable type de champ", :type_de_champ_dgfip + it_behaves_like "a non-prefillable type de champ", :type_de_champ_pole_emploi + it_behaves_like "a non-prefillable type de champ", :type_de_champ_mesri + it_behaves_like "a non-prefillable type de champ", :type_de_champ_carte + it_behaves_like "a non-prefillable type de champ", :type_de_champ_address + it_behaves_like "a non-prefillable type de champ", :type_de_champ_pays + it_behaves_like "a non-prefillable type de champ", :type_de_champ_regions + it_behaves_like "a non-prefillable type de champ", :type_de_champ_departements + it_behaves_like "a non-prefillable type de champ", :type_de_champ_siret + it_behaves_like "a non-prefillable type de champ", :type_de_champ_rna + it_behaves_like "a non-prefillable type de champ", :type_de_champ_annuaire_education + end end diff --git a/spec/system/integrateurs/procedure_prefilling_spec.rb b/spec/system/integrateurs/procedure_prefilling_spec.rb new file mode 100644 index 000000000..59cabefb3 --- /dev/null +++ b/spec/system/integrateurs/procedure_prefilling_spec.rb @@ -0,0 +1,21 @@ +describe 'As an integrator:', js: true do + let(:procedure) { create(:procedure, :published, opendata: true) } + let!(:type_de_champ) { create(:type_de_champ_text, procedure: procedure) } + + before { visit "/preremplir/#{procedure.path}" } + + scenario 'I can read the procedure prefilling (aka public champs)' do + expect(page).to have_content(type_de_champ.to_typed_id) + expect(page).to have_content(I18n.t("activerecord.attributes.type_de_champ.type_champs.#{type_de_champ.type_champ}")) + expect(page).to have_content(type_de_champ.libelle) + expect(page).to have_content(type_de_champ.description) + end + + scenario 'I can select champs to prefill' do + click_on 'Ajouter' + + prefill_description = PrefillDescription.new(procedure) + prefill_description.update(selected_type_de_champ_ids: [type_de_champ.id.to_s]) + expect(page).to have_content(prefill_description.prefill_link) + end +end