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