diff --git a/app/controllers/api/public/v1/base_controller.rb b/app/controllers/api/public/v1/base_controller.rb
new file mode 100644
index 000000000..3aabeef32
--- /dev/null
+++ b/app/controllers/api/public/v1/base_controller.rb
@@ -0,0 +1,29 @@
+class API::Public::V1::BaseController < APIController
+ skip_forgery_protection
+
+ before_action :check_content_type_is_json
+
+ protected
+
+ def render_missing_param(param_name)
+ render_error("#{param_name} is missing", :bad_request)
+ end
+
+ def render_bad_request(error_message)
+ render_error(error_message, :bad_request)
+ end
+
+ def render_not_found(resource_name, resource_id)
+ render_error("#{resource_name} #{resource_id} is not found", :not_found)
+ end
+
+ private
+
+ def check_content_type_is_json
+ render_error("Content-Type should be json", :bad_request) unless request.headers['Content-Type'] == 'application/json'
+ end
+
+ def render_error(message, status)
+ render json: { error: message }, status: status
+ end
+end
diff --git a/app/controllers/api/public/v1/dossiers_controller.rb b/app/controllers/api/public/v1/dossiers_controller.rb
new file mode 100644
index 000000000..cffe7aa66
--- /dev/null
+++ b/app/controllers/api/public/v1/dossiers_controller.rb
@@ -0,0 +1,26 @@
+class API::Public::V1::DossiersController < API::Public::V1::BaseController
+ before_action :retrieve_procedure
+
+ def create
+ dossier = Dossier.new(
+ revision: @procedure.active_revision,
+ groupe_instructeur: @procedure.defaut_groupe_instructeur_for_new_dossier,
+ state: Dossier.states.fetch(:brouillon),
+ prefilled: true
+ )
+ dossier.build_default_individual
+ if dossier.save
+ dossier.prefill!(PrefillParams.new(dossier, params.to_unsafe_h).to_a)
+ render json: { dossier_url: commencer_url(@procedure.path, prefill_token: dossier.prefill_token) }, status: :created
+ else
+ render_bad_request(dossier.errors.full_messages.to_sentence)
+ end
+ end
+
+ private
+
+ def retrieve_procedure
+ @procedure = Procedure.publiees_ou_brouillons.find_by(id: params[:id])
+ render_not_found("procedure", params[:id]) if @procedure.blank?
+ end
+end
diff --git a/app/controllers/concerns/procedure_context_concern.rb b/app/controllers/concerns/procedure_context_concern.rb
index d2d7b5a2c..670df54c9 100644
--- a/app/controllers/concerns/procedure_context_concern.rb
+++ b/app/controllers/concerns/procedure_context_concern.rb
@@ -5,12 +5,14 @@ module ProcedureContextConcern
include Devise::StoreLocationExtension
def restore_procedure_context
- if has_stored_procedure_path?
- @procedure = find_procedure_in_context
+ return unless has_stored_procedure_path?
- if @procedure.blank?
- invalid_procedure_context
- end
+ @procedure = find_procedure_in_context
+
+ if @procedure.blank?
+ invalid_procedure_context
+ else
+ @prefill_token = find_prefill_token_in_context
end
end
@@ -33,6 +35,11 @@ module ProcedureContextConcern
end
end
+ def find_prefill_token_in_context
+ uri = URI(get_stored_location_for(:user))
+ CGI.parse(uri.query).dig("prefill_token")&.first if uri.query
+ end
+
def invalid_procedure_context
clear_stored_location_for(:user)
flash.alert = t('errors.messages.procedure_not_found')
diff --git a/app/controllers/users/commencer_controller.rb b/app/controllers/users/commencer_controller.rb
index c336738da..c416c98f8 100644
--- a/app/controllers/users/commencer_controller.rb
+++ b/app/controllers/users/commencer_controller.rb
@@ -4,6 +4,10 @@ module Users
layout 'procedure_context'
+ before_action :retrieve_prefilled_dossier, if: -> { params[:prefill_token].present? }, only: :commencer
+ before_action :set_prefilled_dossier_ownership, if: -> { user_signed_in? && @prefilled_dossier&.orphan? }, only: :commencer
+ before_action :check_prefilled_dossier_ownership, if: -> { user_signed_in? && @prefilled_dossier }, only: :commencer
+
def commencer
@procedure = retrieve_procedure
return procedure_not_found if @procedure.blank? || @procedure.brouillon?
@@ -74,6 +78,21 @@ module Users
Procedure.publiees.or(Procedure.brouillons).or(Procedure.closes).find_by(path: params[:path])
end
+ def retrieve_prefilled_dossier
+ @prefilled_dossier = Dossier.state_brouillon.prefilled.find_by!(prefill_token: params[:prefill_token])
+ end
+
+ # The prefilled dossier is not owned yet, and the user is signed in: they become the new owner
+ def set_prefilled_dossier_ownership
+ @prefilled_dossier.update!(user: current_user)
+ DossierMailer.with(dossier: @prefilled_dossier).notify_new_draft.deliver_later
+ end
+
+ # The prefilled dossier is owned by another user: raise an exception
+ def check_prefilled_dossier_ownership
+ raise ActiveRecord::RecordNotFound unless @prefilled_dossier.owned_by?(current_user)
+ end
+
def procedure_not_found
procedure = Procedure.find_by(path: params[:path])
@@ -92,7 +111,7 @@ module Users
end
def store_user_location!(procedure)
- store_location_for(:user, helpers.procedure_lien(procedure))
+ store_location_for(:user, helpers.procedure_lien(procedure, prefill_token: params[:prefill_token]))
end
def generate_empty_pdf(revision)
diff --git a/app/controllers/users/confirmations_controller.rb b/app/controllers/users/confirmations_controller.rb
index ea3a1c37b..257456af0 100644
--- a/app/controllers/users/confirmations_controller.rb
+++ b/app/controllers/users/confirmations_controller.rb
@@ -45,7 +45,7 @@ class Users::ConfirmationsController < Devise::ConfirmationsController
end
if procedure_from_params
- commencer_path(path: procedure_from_params.path)
+ commencer_path(path: procedure_from_params.path, prefill_token: params[:prefill_token])
elsif signed_in?
# Will try to use `stored_location_for` to find a path
after_sign_in_path_for(resource_name)
diff --git a/app/controllers/users/registrations_controller.rb b/app/controllers/users/registrations_controller.rb
index 557050554..9136649cd 100644
--- a/app/controllers/users/registrations_controller.rb
+++ b/app/controllers/users/registrations_controller.rb
@@ -26,6 +26,7 @@ class Users::RegistrationsController < Devise::RegistrationsController
# all Devise code.
# So instead we use a per-request global variable.
CurrentConfirmation.procedure_after_confirmation = @procedure
+ CurrentConfirmation.prefill_token = @prefill_token
# Handle existing user trying to sign up again
existing_user = User.find_by(email: params[:user][:email])
diff --git a/app/helpers/procedure_helper.rb b/app/helpers/procedure_helper.rb
index 7152824ba..23af7da97 100644
--- a/app/helpers/procedure_helper.rb
+++ b/app/helpers/procedure_helper.rb
@@ -1,9 +1,9 @@
module ProcedureHelper
- def procedure_lien(procedure)
+ def procedure_lien(procedure, prefill_token: nil)
if procedure.brouillon?
- commencer_test_url(path: procedure.path)
+ commencer_test_url(path: procedure.path, prefill_token: prefill_token)
else
- commencer_url(path: procedure.path)
+ commencer_url(path: procedure.path, prefill_token: prefill_token)
end
end
diff --git a/app/mailers/devise_user_mailer.rb b/app/mailers/devise_user_mailer.rb
index bc548c166..964fa2c5e 100644
--- a/app/mailers/devise_user_mailer.rb
+++ b/app/mailers/devise_user_mailer.rb
@@ -23,6 +23,7 @@ class DeviseUserMailer < Devise::Mailer
def confirmation_instructions(record, token, opts = {})
opts[:from] = NO_REPLY_EMAIL
@procedure = opts[:procedure_after_confirmation] || nil
+ @prefill_token = opts[:prefill_token]
super
end
end
diff --git a/app/models/concerns/dossier_prefillable_concern.rb b/app/models/concerns/dossier_prefillable_concern.rb
index ce88bc01b..35cf970ed 100644
--- a/app/models/concerns/dossier_prefillable_concern.rb
+++ b/app/models/concerns/dossier_prefillable_concern.rb
@@ -3,10 +3,11 @@
module DossierPrefillableConcern
extend ActiveSupport::Concern
- def prefill!(champs_attributes)
- return if champs_attributes.empty?
+ def prefill!(champs_public_attributes)
+ attr = { prefilled: true }
+ attr[:champs_public_attributes] = champs_public_attributes.map { |h| h.merge(prefilled: true) } if champs_public_attributes.any?
- assign_attributes(champs_attributes: champs_attributes.map { |h| h.merge(prefilled: true) })
+ assign_attributes(attr)
save(validate: false)
end
end
diff --git a/app/models/current_confirmation.rb b/app/models/current_confirmation.rb
index c25314d7b..ce9853ee2 100644
--- a/app/models/current_confirmation.rb
+++ b/app/models/current_confirmation.rb
@@ -1,3 +1,4 @@
class CurrentConfirmation < ActiveSupport::CurrentAttributes
attribute :procedure_after_confirmation
+ attribute :prefill_token
end
diff --git a/app/models/dossier.rb b/app/models/dossier.rb
index d61596475..fa490d13e 100644
--- a/app/models/dossier.rb
+++ b/app/models/dossier.rb
@@ -28,6 +28,8 @@
# last_champ_updated_at :datetime
# last_commentaire_updated_at :datetime
# motivation :text
+# prefill_token :string
+# prefilled :boolean
# private_search_terms :text
# processed_at :datetime
# search_terms :text
@@ -70,6 +72,8 @@ class Dossier < ApplicationRecord
DAYS_AFTER_EXPIRATION = 5
INTERVAL_EXPIRATION = "#{MONTHS_AFTER_EXPIRATION} month #{DAYS_AFTER_EXPIRATION} days"
+ has_secure_token :prefill_token
+
has_one :etablissement, dependent: :destroy
has_one :individual, validate: false, dependent: :destroy
has_one :attestation, dependent: :destroy
@@ -218,11 +222,12 @@ class Dossier < ApplicationRecord
scope :state_termine, -> { where(state: TERMINE) }
scope :state_not_termine, -> { where.not(state: TERMINE) }
- scope :archived, -> { where(archived: true) }
- scope :not_archived, -> { where(archived: false) }
- scope :hidden_by_user, -> { where.not(hidden_by_user_at: nil) }
- scope :hidden_by_administration, -> { where.not(hidden_by_administration_at: nil) }
- scope :visible_by_user, -> { where(for_procedure_preview: false).or(where(for_procedure_preview: nil)).where(hidden_by_user_at: nil) }
+ scope :archived, -> { where(archived: true) }
+ scope :not_archived, -> { where(archived: false) }
+ scope :prefilled, -> { where(prefilled: true) }
+ scope :hidden_by_user, -> { where.not(hidden_by_user_at: nil) }
+ scope :hidden_by_administration, -> { where.not(hidden_by_administration_at: nil) }
+ scope :visible_by_user, -> { where(for_procedure_preview: false).or(where(for_procedure_preview: nil)).where(hidden_by_user_at: nil) }
scope :visible_by_administration, -> {
state_not_brouillon
.where(hidden_by_administration_at: nil)
@@ -435,7 +440,7 @@ class Dossier < ApplicationRecord
after_save :send_web_hook
- validates :user, presence: true, if: -> { deleted_user_email_never_send.nil? }
+ validates :user, presence: true, if: -> { deleted_user_email_never_send.nil? }, unless: -> { prefilled }
validates :individual, presence: true, if: -> { revision.procedure.for_individual? }
validates :groupe_instructeur, presence: true, if: -> { !brouillon? }
@@ -718,6 +723,17 @@ class Dossier < ApplicationRecord
end
end
+ def orphan?
+ prefilled? && user.nil?
+ end
+
+ def owned_by?(a_user)
+ return false if a_user.nil?
+ return false if orphan?
+
+ user == a_user
+ end
+
def log_operations?
!procedure.brouillon? && !brouillon?
end
diff --git a/app/models/procedure.rb b/app/models/procedure.rb
index 34ea5f432..e2d783a92 100644
--- a/app/models/procedure.rb
+++ b/app/models/procedure.rb
@@ -206,7 +206,7 @@ class Procedure < ApplicationRecord
scope :brouillons, -> { where(aasm_state: :brouillon) }
scope :publiees, -> { where(aasm_state: :publiee) }
- scope :publiees_ou_brouillons, -> { publiees.or(brouillons) }
+ scope :publiees_ou_brouillons, -> { where(aasm_state: [:publiee, :brouillon]) }
scope :closes, -> { where(aasm_state: [:close, :depubliee]) }
scope :opendata, -> { where(opendata: true) }
scope :publiees_ou_closes, -> { where(aasm_state: [:publiee, :close, :depubliee]) }
diff --git a/app/models/user.rb b/app/models/user.rb
index 5d6589829..0163890b7 100644
--- a/app/models/user.rb
+++ b/app/models/user.rb
@@ -80,6 +80,7 @@ class User < ApplicationRecord
# Make our procedure_after_confirmation available to the Mailer
opts[:procedure_after_confirmation] = CurrentConfirmation.procedure_after_confirmation
+ opts[:prefill_token] = CurrentConfirmation.prefill_token
send_devise_notification(:confirmation_instructions, @raw_confirmation_token, opts)
end
diff --git a/app/views/commencer/show.html.haml b/app/views/commencer/show.html.haml
index 0b755b554..553f1198e 100644
--- a/app/views/commencer/show.html.haml
+++ b/app/views/commencer/show.html.haml
@@ -3,12 +3,12 @@
.commencer.form
- if !user_signed_in?
%h2.huge-title= t('views.commencer.show.start_procedure')
- = render partial: 'shared/france_connect_login', locals: { url: commencer_france_connect_path(path: @procedure.path) }
- = link_to commencer_sign_up_path(path: @procedure.path), class: 'fr-btn fr-btn--lg fr-my-2w' do
+ = render partial: 'shared/france_connect_login', locals: { url: commencer_france_connect_path(path: @procedure.path, prefill_token: @prefilled_dossier&.prefill_token) }
+ = link_to commencer_sign_up_path(path: @procedure.path, prefill_token: @prefilled_dossier&.prefill_token), class: 'fr-btn fr-btn--lg fr-my-2w' do
= t('views.shared.account.create')
%span.optional-on-small-screens.fr-ml-1v
#{APPLICATION_NAME}
- = link_to t('views.shared.account.already_user'), commencer_sign_in_path(path: @procedure.path), class: 'fr-btn fr-btn--secondary fr-btn--lg fr-my-2w'
+ = link_to t('views.shared.account.already_user'), commencer_sign_in_path(path: @procedure.path, prefill_token: @prefilled_dossier&.prefill_token), class: 'fr-btn fr-btn--secondary fr-btn--lg fr-my-2w'
- else
- revision = @revision.draft? ? @revision : @procedure.revisions.where.not(id: @procedure.draft_revision_id)
@@ -19,6 +19,13 @@
- if dossiers.empty?
= link_to t('views.commencer.show.start_procedure'), url_for_new_dossier(@revision), class: 'fr-btn fr-btn--lg fr-my-2w'
+ - elsif @prefilled_dossier
+ %h2.huge-title= t('views.commencer.show.prefilled_draft')
+ %p
+ = t('views.commencer.show.prefilled_draft_detail_html', time_ago: time_ago_in_words(@prefilled_dossier.created_at), procedure: @prefilled_dossier.procedure.libelle)
+ = link_to t('views.commencer.show.continue_file'), brouillon_dossier_path(@prefilled_dossier), class: 'fr-btn fr-btn--lg fr-my-2w'
+ = link_to t('views.commencer.show.start_new_file'), url_for_new_dossier(@revision), class: 'fr-btn fr-btn--lg fr-btn--secondary fr-my-2w'
+
- elsif drafts.size == 1 && not_drafts.empty?
- dossier = drafts.first
%h2.huge-title= t('views.commencer.show.already_draft')
diff --git a/app/views/devise_mailer/confirmation_instructions.html.haml b/app/views/devise_mailer/confirmation_instructions.html.haml
index cab00c327..ba4904207 100644
--- a/app/views/devise_mailer/confirmation_instructions.html.haml
+++ b/app/views/devise_mailer/confirmation_instructions.html.haml
@@ -6,7 +6,7 @@
%p
Pour activer votre compte sur #{APPLICATION_NAME}, veuillez cliquer sur le lien suivant :
- - link = confirmation_url(@user, confirmation_token: @token, procedure_id: @procedure&.id)
+ - link = confirmation_url(@user, confirmation_token: @token, procedure_id: @procedure&.id, prefill_token: @prefill_token)
= link_to(link, link)
- else
diff --git a/config/locales/en.yml b/config/locales/en.yml
index 20be22169..8f5a48112 100644
--- a/config/locales/en.yml
+++ b/config/locales/en.yml
@@ -92,6 +92,8 @@ en:
start_procedure: Start the procedure
existing_dossiers: You already have files for this procedure
show_dossiers: View my current files
+ prefilled_draft: "You have a prefilled file"
+ prefilled_draft_detail_html: "You prefilled a file for the \"%{procedure}\" procedure %{time_ago} ago"
already_draft: "You already started to fill a file"
already_draft_detail_html: "You started to fill a file for the \"%{procedure}\" procedure %{time_ago} ago"
already_not_draft: "You already submitted a file"
diff --git a/config/locales/fr.yml b/config/locales/fr.yml
index 8367c0ca5..f73bd0001 100644
--- a/config/locales/fr.yml
+++ b/config/locales/fr.yml
@@ -82,6 +82,8 @@ fr:
start_procedure: Commencer la démarche
existing_dossiers: Vous avez déjà des dossiers pour cette démarche
show_dossiers: Voir mes dossiers en cours
+ prefilled_draft: "Vous avez un dossier prérempli"
+ prefilled_draft_detail_html: "Il y a %{time_ago}, vous avez prérempli un dossier sur la démarche « %{procedure} »."
already_draft: "Vous avez déjà commencé à remplir un dossier"
already_draft_detail_html: "Il y a %{time_ago}, vous avez commencé à remplir un dossier sur la démarche « %{procedure} »."
already_not_draft: "Vous avez déjà déposé un dossier"
diff --git a/config/routes.rb b/config/routes.rb
index d7a66e23f..4d165b3e7 100644
--- a/config/routes.rb
+++ b/config/routes.rb
@@ -263,7 +263,11 @@ Rails.application.routes.draw do
namespace :public do
namespace :v1 do
- resources :dossiers, only: :create
+ resources :demarches, only: [] do
+ member do
+ resources :dossiers, only: :create
+ end
+ end
end
end
end
diff --git a/db/migrate/20221213084333_add_prefill_fields_to_dossiers.rb b/db/migrate/20221213084333_add_prefill_fields_to_dossiers.rb
new file mode 100644
index 000000000..28c34a296
--- /dev/null
+++ b/db/migrate/20221213084333_add_prefill_fields_to_dossiers.rb
@@ -0,0 +1,6 @@
+class AddPrefillFieldsToDossiers < ActiveRecord::Migration[6.1]
+ def change
+ add_column :dossiers, :prefill_token, :string
+ add_column :dossiers, :prefilled, :boolean
+ end
+end
diff --git a/db/migrate/20221213084442_add_prefill_token_index_to_dossiers.rb b/db/migrate/20221213084442_add_prefill_token_index_to_dossiers.rb
new file mode 100644
index 000000000..349224504
--- /dev/null
+++ b/db/migrate/20221213084442_add_prefill_token_index_to_dossiers.rb
@@ -0,0 +1,7 @@
+class AddPrefillTokenIndexToDossiers < ActiveRecord::Migration[6.1]
+ disable_ddl_transaction!
+
+ def change
+ add_index :dossiers, :prefill_token, unique: true, algorithm: :concurrently
+ end
+end
diff --git a/db/schema.rb b/db/schema.rb
index 309bb650c..313080e07 100644
--- a/db/schema.rb
+++ b/db/schema.rb
@@ -10,7 +10,7 @@
#
# It's strongly recommended that you check this file into your version control system.
-ActiveRecord::Schema.define(version: 2022_12_05_144624) do
+ActiveRecord::Schema.define(version: 2022_12_13_084442) do
# These are extensions that must be enabled in order to support this database
enable_extension "pgcrypto"
@@ -298,13 +298,13 @@ ActiveRecord::Schema.define(version: 2022_12_05_144624) do
t.boolean "automatic_operation", default: false, null: false
t.bigint "bill_signature_id"
t.datetime "created_at", null: false
+ t.jsonb "data"
t.text "digest"
t.bigint "dossier_id"
t.datetime "executed_at"
t.datetime "keep_until"
t.string "operation", null: false
t.datetime "updated_at", null: false
- t.jsonb "data"
t.index ["bill_signature_id"], name: "index_dossier_operation_logs_on_bill_signature_id"
t.index ["dossier_id"], name: "index_dossier_operation_logs_on_dossier_id"
t.index ["keep_until"], name: "index_dossier_operation_logs_on_keep_until"
@@ -363,6 +363,8 @@ ActiveRecord::Schema.define(version: 2022_12_05_144624) do
t.datetime "last_commentaire_updated_at"
t.text "motivation"
t.bigint "parent_dossier_id"
+ t.string "prefill_token"
+ t.boolean "prefilled"
t.string "private_search_terms"
t.datetime "processed_at"
t.bigint "revision_id"
@@ -376,6 +378,7 @@ ActiveRecord::Schema.define(version: 2022_12_05_144624) do
t.index ["dossier_transfer_id"], name: "index_dossiers_on_dossier_transfer_id"
t.index ["groupe_instructeur_id"], name: "index_dossiers_on_groupe_instructeur_id"
t.index ["hidden_at"], name: "index_dossiers_on_hidden_at"
+ t.index ["prefill_token"], name: "index_dossiers_on_prefill_token", unique: true
t.index ["revision_id"], name: "index_dossiers_on_revision_id"
t.index ["state"], name: "index_dossiers_on_state"
t.index ["user_id"], name: "index_dossiers_on_user_id"
@@ -807,6 +810,7 @@ ActiveRecord::Schema.define(version: 2022_12_05_144624) do
t.datetime "reset_password_sent_at"
t.string "reset_password_token"
t.integer "sign_in_count", default: 0, null: false
+ t.boolean "team_account", default: false
t.string "unlock_token"
t.datetime "updated_at"
t.index ["email"], name: "index_super_admins_on_email", unique: true
@@ -885,7 +889,6 @@ ActiveRecord::Schema.define(version: 2022_12_05_144624) do
t.string "reset_password_token"
t.integer "sign_in_count", default: 0, null: false
t.string "siret"
- t.boolean "team_account", default: false
t.text "unconfirmed_email"
t.string "unlock_token"
t.datetime "updated_at"
diff --git a/spec/controllers/api/public/v1/dossiers_controller_spec.rb b/spec/controllers/api/public/v1/dossiers_controller_spec.rb
new file mode 100644
index 000000000..e4cc80de9
--- /dev/null
+++ b/spec/controllers/api/public/v1/dossiers_controller_spec.rb
@@ -0,0 +1,135 @@
+RSpec.describe API::Public::V1::DossiersController, type: :controller do
+ include Rails.application.routes.url_helpers
+
+ describe '#create' do
+ # Request prototype:
+ # curl --request POST 'http://localhost:3000/api/public/v1/demarches/2/dossiers' \
+ # --header 'Content-Type: application/json' \
+ # --data '{"champ_Q2hhbXAtMjI=": "personne@fournisseur.fr"}'
+
+ context 'when the request content type is json' do
+ let(:params) { { id: procedure.id } }
+ subject(:create_request) do
+ request.headers["Content-Type"] = "application/json"
+ post :create, params: params
+ end
+
+ shared_examples 'the procedure is found' do
+ context 'when the dossier can be saved' do
+ it { expect(create_request).to have_http_status(:created) }
+
+ it { expect { create_request }.to change { Dossier.count }.by(1) }
+
+ it "marks the created dossier as prefilled" do
+ create_request
+ expect(Dossier.last.prefilled).to eq(true)
+ end
+
+ it "creates the dossier without a user" do
+ create_request
+ expect(Dossier.last.user).to eq(nil)
+ end
+
+ it "responds with the brouillon dossier path" do
+ create_request
+ expect(JSON.parse(response.body)["dossier_url"]).to eq(
+ "http://test.host#{commencer_path(procedure.path, prefill_token: Dossier.last.prefill_token)}"
+ )
+ end
+
+ context 'when prefill values are given' do
+ let!(:type_de_champ_1) { create(:type_de_champ_text, procedure: procedure) }
+ let(:value_1) { "any value" }
+
+ let!(:type_de_champ_2) { create(:type_de_champ_textarea, procedure: procedure) }
+ let(:value_2) { "another value" }
+
+ let(:params) {
+ {
+ id: procedure.id,
+ "champ_#{type_de_champ_1.to_typed_id}" => value_1,
+ "champ_#{type_de_champ_2.to_typed_id}" => value_2
+ }
+ }
+
+ it "prefills the dossier's champs with the given values" do
+ create_request
+
+ dossier = Dossier.last
+ expect(find_champ_by_stable_id(dossier, type_de_champ_1.stable_id).value).to eq(value_1)
+ expect(find_champ_by_stable_id(dossier, type_de_champ_2.stable_id).value).to eq(value_2)
+ end
+ end
+ end
+
+ context 'when the dossier can not be saved' do
+ before do
+ allow_any_instance_of(Dossier).to receive(:save).and_return(false)
+ allow_any_instance_of(Dossier).to receive(:errors).and_return(
+ ActiveModel::Errors.new(Dossier.new).tap { |e| e.add(:base, "something went wrong") }
+ )
+
+ create_request
+ end
+
+ it { expect(response).to have_http_status(:bad_request) }
+
+ it { expect(response).to have_failed_with("something went wrong") }
+ end
+ end
+
+ shared_examples 'the procedure is not found' do
+ before { create_request }
+
+ it { expect(response).to have_http_status(:not_found) }
+
+ it { expect(response).to have_failed_with("procedure #{procedure.id} is not found") }
+ end
+
+ context 'when the procedure is found' do
+ context 'when the procedure is publiee' do
+ it_behaves_like 'the procedure is found' do
+ let(:procedure) { create(:procedure, :published) }
+ end
+ end
+
+ context 'when the procedure is brouillon' do
+ it_behaves_like 'the procedure is found' do
+ let(:procedure) { create(:procedure, :draft) }
+ end
+ end
+
+ context 'when the procedure is not publiee and not brouillon' do
+ it_behaves_like 'the procedure is not found' do
+ let(:procedure) { create(:procedure, :closed) }
+ end
+ end
+ end
+
+ context 'when the procedure is not found' do
+ it_behaves_like 'the procedure is not found' do
+ let(:procedure) { double(Procedure, id: -1) }
+ end
+ end
+ end
+
+ context 'when the request content type is not json' do
+ subject(:create_request) do
+ request.headers["Content-Type"] = "application/xhtml+xml"
+ post :create, params: { id: 0 }
+ end
+
+ before { create_request }
+
+ it { expect(response).to have_http_status(:bad_request) }
+
+ it { expect(response).to have_failed_with("Content-Type should be json") }
+ end
+ end
+
+ private
+
+ def find_champ_by_stable_id(dossier, stable_id)
+ dossier.champs_public.joins(:type_de_champ).find_by(types_de_champ: { stable_id: stable_id })
+ end
+end
diff --git a/spec/controllers/concerns/procedure_context_concern_spec.rb b/spec/controllers/concerns/procedure_context_concern_spec.rb
index 9a3f81e25..10f6a185d 100644
--- a/spec/controllers/concerns/procedure_context_concern_spec.rb
+++ b/spec/controllers/concerns/procedure_context_concern_spec.rb
@@ -69,6 +69,19 @@ RSpec.describe ProcedureContextConcern, type: :controller do
expect(subject.status).to eq 200
expect(assigns(:procedure)).to eq test_procedure
end
+
+ context 'when a prefill token has been stored' do
+ let(:dossier) { create :dossier, :prefilled, procedure: test_procedure }
+
+ before do
+ controller.store_location_for(:user, commencer_test_path(path: test_procedure.path, prefill_token: dossier.prefill_token))
+ end
+
+ it 'succeeds, and assigns the prefill token on the controller' do
+ expect(subject.status).to eq 200
+ expect(assigns(:prefill_token)).to eq dossier.prefill_token
+ end
+ end
end
context 'when the stored procedure is published' do
@@ -82,6 +95,19 @@ RSpec.describe ProcedureContextConcern, type: :controller do
expect(subject.status).to eq 200
expect(assigns(:procedure)).to eq published_procedure
end
+
+ context 'when a prefill token has been stored' do
+ let(:dossier) { create :dossier, :prefilled, procedure: published_procedure }
+
+ before do
+ controller.store_location_for(:user, commencer_path(path: published_procedure.path, prefill_token: dossier.prefill_token))
+ end
+
+ it 'succeeds, and assigns the prefill token on the controller' do
+ expect(subject.status).to eq 200
+ expect(assigns(:prefill_token)).to eq dossier.prefill_token
+ end
+ end
end
end
end
diff --git a/spec/controllers/users/commencer_controller_spec.rb b/spec/controllers/users/commencer_controller_spec.rb
index d64094521..f4370c526 100644
--- a/spec/controllers/users/commencer_controller_spec.rb
+++ b/spec/controllers/users/commencer_controller_spec.rb
@@ -72,6 +72,85 @@ describe Users::CommencerController, type: :controller do
expect(subject).to redirect_to(commencer_path(path: replaced_by_procedure.path))
end
end
+
+ context 'when a dossier has been prefilled' do
+ let(:dossier) { create(:dossier, :brouillon, :prefilled, user: user) }
+ let(:path) { dossier.procedure.path }
+
+ subject { get :commencer, params: { path: path, prefill_token: dossier.prefill_token } }
+
+ shared_examples 'a prefilled brouillon dossier retriever' do
+ context 'when the dossier is a prefilled brouillon and the prefill token is present' do
+ it 'retrieves the dossier' do
+ subject
+ expect(assigns(:prefilled_dossier)).to eq(dossier)
+ end
+ end
+
+ context 'when the dossier is not prefilled' do
+ before do
+ dossier.prefilled = false
+ dossier.save(validate: false)
+ end
+
+ it { expect { subject }.to raise_error(ActiveRecord::RecordNotFound) }
+ end
+
+ context 'when the dossier is not a brouillon' do
+ before { dossier.en_construction! }
+
+ it { expect { subject }.to raise_error(ActiveRecord::RecordNotFound) }
+ end
+
+ context 'when the prefill token does not match any dossier' do
+ before { dossier.prefill_token = "totoro" }
+
+ it { expect { subject }.to raise_error(ActiveRecord::RecordNotFound) }
+ end
+ end
+
+ context 'when the user is unauthenticated' do
+ let(:user) { nil }
+
+ it_behaves_like 'a prefilled brouillon dossier retriever'
+ end
+
+ context 'when the user is authenticated' do
+ context 'when the dossier already has an owner' do
+ let(:user) { create(:user) }
+
+ context 'when the user is the dossier owner' do
+ before { sign_in user }
+
+ it_behaves_like 'a prefilled brouillon dossier retriever'
+ end
+
+ context 'when the user is not the dossier owner' do
+ before { sign_in create(:user) }
+
+ it { expect { subject }.to raise_error(ActiveRecord::RecordNotFound) }
+ end
+ end
+
+ context 'when the dossier does not have an owner yet' do
+ let(:user) { nil }
+ let(:newly_authenticated_user) { create(:user) }
+
+ before { sign_in newly_authenticated_user }
+
+ it { expect { subject }.to change { dossier.reload.user }.from(nil).to(newly_authenticated_user) }
+
+ it 'sends the notify_new_draft email' do
+ expect { perform_enqueued_jobs { subject } }.to change { ActionMailer::Base.deliveries.count }.by(1)
+
+ dossier = Dossier.last
+ mail = ActionMailer::Base.deliveries.last
+ expect(mail.subject).to eq("Retrouvez votre brouillon pour la démarche « #{dossier.procedure.libelle} »")
+ expect(mail.html_part.body).to include(dossier_path(dossier))
+ end
+ end
+ end
+ end
end
describe '#commencer_test' do
@@ -105,6 +184,13 @@ describe Users::CommencerController, type: :controller do
end
end
+ shared_examples 'a prefill token storage' do
+ it 'stores the prefill token' do
+ subject
+ expect(controller.stored_location_for(:user)).to include('prefill_token')
+ end
+ end
+
describe '#sign_in' do
context 'for a published procedure' do
subject { get :sign_in, params: { path: published_procedure.path } }
@@ -115,6 +201,12 @@ describe Users::CommencerController, type: :controller do
end
it { expect(subject).to redirect_to(new_user_session_path) }
+
+ context 'when a prefill token is given' do
+ subject { get :sign_in, params: { path: published_procedure.path, prefill_token: 'prefill_token' } }
+
+ it_behaves_like 'a prefill token storage'
+ end
end
context 'for a draft procedure' do
@@ -126,6 +218,12 @@ describe Users::CommencerController, type: :controller do
end
it { expect(subject).to redirect_to(new_user_session_path) }
+
+ context 'when a prefill token is given' do
+ subject { get :sign_in, params: { path: draft_procedure.path, prefill_token: 'prefill_token' } }
+
+ it_behaves_like 'a prefill token storage'
+ end
end
context 'when the path doesn’t exist' do
@@ -147,6 +245,12 @@ describe Users::CommencerController, type: :controller do
end
it { expect(subject).to redirect_to(new_user_registration_path) }
+
+ context 'when a prefill token is given' do
+ subject { get :sign_up, params: { path: published_procedure.path, prefill_token: 'prefill_token' } }
+
+ it_behaves_like 'a prefill token storage'
+ end
end
context 'for a draft procedure' do
@@ -158,6 +262,12 @@ describe Users::CommencerController, type: :controller do
end
it { expect(subject).to redirect_to(new_user_registration_path) }
+
+ context 'when a prefill token is given' do
+ subject { get :sign_up, params: { path: draft_procedure.path, prefill_token: 'prefill_token' } }
+
+ it_behaves_like 'a prefill token storage'
+ end
end
context 'when the path doesn’t exist' do
@@ -179,6 +289,12 @@ describe Users::CommencerController, type: :controller do
end
it { expect(subject).to redirect_to(france_connect_particulier_path) }
+
+ context 'when a prefill token is given' do
+ subject { get :france_connect, params: { path: published_procedure.path, prefill_token: 'prefill_token' } }
+
+ it_behaves_like 'a prefill token storage'
+ end
end
context 'for a draft procedure' do
@@ -190,6 +306,12 @@ describe Users::CommencerController, type: :controller do
end
it { expect(subject).to redirect_to(france_connect_particulier_path) }
+
+ context 'when a prefill token is given' do
+ subject { get :france_connect, params: { path: draft_procedure.path, prefill_token: 'prefill_token' } }
+
+ it_behaves_like 'a prefill token storage'
+ end
end
context 'when the path doesn’t exist' do
diff --git a/spec/factories/dossier.rb b/spec/factories/dossier.rb
index 56a4d36d9..c766505cd 100644
--- a/spec/factories/dossier.rb
+++ b/spec/factories/dossier.rb
@@ -256,5 +256,9 @@ FactoryBot.define do
dossier.save!
end
end
+
+ trait :prefilled do
+ prefilled { true }
+ end
end
end
diff --git a/spec/mailers/previews/devise_user_mailer_preview.rb b/spec/mailers/previews/devise_user_mailer_preview.rb
index e79fc17fc..1f0869098 100644
--- a/spec/mailers/previews/devise_user_mailer_preview.rb
+++ b/spec/mailers/previews/devise_user_mailer_preview.rb
@@ -8,6 +8,10 @@ class DeviseUserMailerPreview < ActionMailer::Preview
DeviseUserMailer.confirmation_instructions(user, "faketoken", {})
end
+ def confirmation_instructions___with_procedure_and_prefill_token
+ DeviseUserMailer.confirmation_instructions(user, "faketoken", procedure_after_confirmation: procedure, prefill_token: "prefill_token")
+ end
+
def reset_password_instructions
DeviseUserMailer.reset_password_instructions(user, "faketoken", {})
end
diff --git a/spec/models/concern/dossier_prefillable_concern_spec.rb b/spec/models/concern/dossier_prefillable_concern_spec.rb
index e6c8e6bfa..58de07d7d 100644
--- a/spec/models/concern/dossier_prefillable_concern_spec.rb
+++ b/spec/models/concern/dossier_prefillable_concern_spec.rb
@@ -8,12 +8,19 @@ RSpec.describe DossierPrefillableConcern do
subject(:fill) { dossier.prefill!(values); dossier.reload }
+ shared_examples 'a dossier marked as prefilled' do
+ it 'marks the dossier as prefilled' do
+ expect { fill }.to change { dossier.reload.prefilled }.from(nil).to(true)
+ end
+ end
+
context 'when champs_public_attributes is empty' do
let(:values) { [] }
- it "does nothing" do
- expect(dossier).not_to receive(:save)
- fill
+ it_behaves_like 'a dossier marked as prefilled'
+
+ it "doesn't change champs_public" do
+ expect { fill }.not_to change { dossier.champs_public.to_a }
end
end
@@ -30,6 +37,8 @@ RSpec.describe DossierPrefillableConcern do
let(:values) { [{ id: champ_id_1, value: value_1 }, { id: champ_id_2, value: value_2 }] }
+ it_behaves_like 'a dossier marked as prefilled'
+
it "updates the champs with the new values and mark them as prefilled" do
fill
@@ -48,6 +57,8 @@ RSpec.describe DossierPrefillableConcern do
let(:values) { [{ id: champ_id, value: value }] }
+ it_behaves_like 'a dossier marked as prefilled'
+
it "still updates the champ" do
expect { fill }.to change { dossier.champs_public.first.value }.from(nil).to(value)
end
diff --git a/spec/models/dossier_spec.rb b/spec/models/dossier_spec.rb
index 165870ec8..9b1f509df 100644
--- a/spec/models/dossier_spec.rb
+++ b/spec/models/dossier_spec.rb
@@ -25,6 +25,20 @@ describe Dossier do
subject(:dossier) { create(:dossier, procedure: procedure) }
it { is_expected.to validate_presence_of(:individual) }
+
+ it { is_expected.to validate_presence_of(:user) }
+
+ context 'when dossier has deleted_user_email_never_send' do
+ subject(:dossier) { create(:dossier, procedure: procedure, deleted_user_email_never_send: "seb@totoro.org") }
+
+ it { is_expected.not_to validate_presence_of(:user) }
+ end
+
+ context 'when dossier is prefilled' do
+ subject(:dossier) { create(:dossier, procedure: procedure, prefilled: true) }
+
+ it { is_expected.not_to validate_presence_of(:user) }
+ end
end
describe 'with_champs' do
@@ -1928,6 +1942,70 @@ describe Dossier do
it { is_expected.to belong_to(:batch_operation).optional }
end
+ describe '#orphan?' do
+ subject(:orphan) { dossier.orphan? }
+
+ context 'when the dossier is prefilled' do
+ context 'when the dossier has a user' do
+ let(:dossier) { build(:dossier, :prefilled) }
+
+ it { expect(orphan).to be_falsey }
+ end
+
+ context 'when the dossier does not have a user' do
+ let(:dossier) { build(:dossier, :prefilled, user: nil) }
+
+ it { expect(orphan).to be_truthy }
+ end
+ end
+
+ context 'when the dossier is not prefilled' do
+ context 'when the dossier has a user' do
+ let(:dossier) { build(:dossier) }
+
+ it { expect(orphan).to be_falsey }
+ end
+
+ context 'when the dossier does not have a user' do
+ let(:dossier) { build(:dossier, user: nil) }
+
+ it { expect(orphan).to be_falsey }
+ end
+ end
+ end
+
+ describe '#owned_by?' do
+ subject(:owned_by) { dossier.owned_by?(user) }
+
+ context 'when the dossier is orphan' do
+ let(:dossier) { build(:dossier, user: nil) }
+ let(:user) { build(:user) }
+
+ it { expect(owned_by).to be_falsey }
+ end
+
+ context 'when the given user is nil' do
+ let(:dossier) { build(:dossier) }
+ let(:user) { nil }
+
+ it { expect(owned_by).to be_falsey }
+ end
+
+ context 'when the dossier has a user and it is not the given user' do
+ let(:dossier) { build(:dossier) }
+ let(:user) { build(:user) }
+
+ it { expect(owned_by).to be_falsey }
+ end
+
+ context 'when the dossier has a user and it is the given user' do
+ let(:dossier) { build(:dossier, user: user) }
+ let(:user) { build(:user) }
+
+ it { expect(owned_by).to be_truthy }
+ end
+ end
+
private
def count_for_month(processed_by_month, month)
diff --git a/spec/support/public_api_matchers.rb b/spec/support/public_api_matchers.rb
new file mode 100644
index 000000000..bf856520c
--- /dev/null
+++ b/spec/support/public_api_matchers.rb
@@ -0,0 +1,5 @@
+RSpec::Matchers.define :have_failed_with do |expected|
+ match do |response|
+ JSON.parse(response.body).with_indifferent_access.dig(:error) == expected
+ end
+end
diff --git a/spec/support/shared_examples_for_prefilled_dossier.rb b/spec/support/shared_examples_for_prefilled_dossier.rb
new file mode 100644
index 000000000..f5a8faaf8
--- /dev/null
+++ b/spec/support/shared_examples_for_prefilled_dossier.rb
@@ -0,0 +1,22 @@
+shared_examples "the user has got a prefilled dossier, owned by themselves" do
+ scenario "the user has got a prefilled dossier, owned by themselves" do
+ siret = '41816609600051'
+ stub_request(:get, /https:\/\/entreprise.api.gouv.fr\/v2\/etablissements\/#{siret}/)
+ .to_return(status: 200, body: File.read('spec/fixtures/files/api_entreprise/etablissements.json'))
+
+ expect(dossier.user).to eq(user)
+
+ expect(page).to have_current_path siret_dossier_path(procedure.dossiers.last)
+ fill_in 'Numéro SIRET', with: siret
+ click_on 'Valider'
+
+ expect(page).to have_current_path(etablissement_dossier_path(dossier))
+ expect(page).to have_content('OCTO TECHNOLOGY')
+ click_on 'Continuer avec ces informations'
+
+ expect(page).to have_current_path(brouillon_dossier_path(dossier))
+ expect(page).to have_field(type_de_champ_text.libelle, with: text_value)
+ expect(page).to have_field(type_de_champ_phone.libelle, with: phone_value)
+ expect(page).to have_css('.field_with_errors', text: type_de_champ_phone.libelle)
+ end
+end
diff --git a/spec/system/users/dossier_prefill_get_spec.rb b/spec/system/users/dossier_prefill_get_spec.rb
new file mode 100644
index 000000000..d7b9eed35
--- /dev/null
+++ b/spec/system/users/dossier_prefill_get_spec.rb
@@ -0,0 +1,87 @@
+describe 'Prefilling a dossier (with a GET request):' do
+ let(:password) { 'my-s3cure-p4ssword' }
+
+ let(:procedure) { create(:procedure, :published, opendata: true) }
+ let(:dossier) { procedure.dossiers.last }
+
+ let(:type_de_champ_text) { create(:type_de_champ_text, procedure: procedure) }
+ let(:type_de_champ_phone) { create(:type_de_champ_phone, procedure: procedure) }
+ let(:text_value) { "My Neighbor Totoro is the best movie ever" }
+ let(:phone_value) { "invalid phone value" }
+
+ context 'when authenticated' do
+ it_behaves_like "the user has got a prefilled dossier, owned by themselves" do
+ let(:user) { create(:user, password: password) }
+
+ before do
+ visit "/users/sign_in"
+ sign_in_with user.email, password
+
+ visit commencer_path(
+ path: procedure.path,
+ "champ_#{type_de_champ_text.to_typed_id}" => text_value,
+ "champ_#{type_de_champ_phone.to_typed_id}" => phone_value
+ )
+
+ click_on "Commencer la démarche"
+ end
+ end
+ end
+
+ context 'when unauthenticated' do
+ before do
+ visit commencer_path(
+ path: procedure.path,
+ "champ_#{type_de_champ_text.to_typed_id}" => text_value,
+ "champ_#{type_de_champ_phone.to_typed_id}" => phone_value
+ )
+ end
+
+ context 'when the user signs in with email and password' do
+ it_behaves_like "the user has got a prefilled dossier, owned by themselves" do
+ let!(:user) { create(:user, password: password) }
+
+ before do
+ click_on "J’ai déjà un compte"
+ sign_in_with user.email, password
+
+ click_on "Commencer la démarche"
+ end
+ end
+ end
+
+ context 'when the user signs up with email and password' do
+ it_behaves_like "the user has got a prefilled dossier, owned by themselves" do
+ let(:user_email) { generate :user_email }
+ let(:user) { User.find_by(email: user_email) }
+
+ before do
+ click_on "Créer un compte #{APPLICATION_NAME}"
+
+ sign_up_with user_email, password
+ expect(page).to have_content "nous avons besoin de vérifier votre adresse #{user_email}"
+
+ click_confirmation_link_for user_email
+ expect(page).to have_content('Votre compte a bien été confirmé.')
+
+ click_on "Commencer la démarche"
+ end
+ end
+ end
+
+ context 'when the user signs up with FranceConnect' do
+ it_behaves_like "the user has got a prefilled dossier, owned by themselves" do
+ let(:user) { User.last }
+
+ before do
+ allow_any_instance_of(FranceConnectParticulierClient).to receive(:authorization_uri).and_return(france_connect_particulier_callback_path(code: "c0d3"))
+ allow(FranceConnectService).to receive(:retrieve_user_informations_particulier).and_return(build(:france_connect_information))
+
+ page.find('.fr-connect').click
+
+ click_on "Commencer la démarche"
+ end
+ end
+ end
+ end
+end
diff --git a/spec/system/users/dossier_prefill_post_spec.rb b/spec/system/users/dossier_prefill_post_spec.rb
new file mode 100644
index 000000000..8b495da8d
--- /dev/null
+++ b/spec/system/users/dossier_prefill_post_spec.rb
@@ -0,0 +1,102 @@
+describe 'Prefilling a dossier (with a POST request):' do
+ let(:password) { 'my-s3cure-p4ssword' }
+
+ let(:procedure) { create(:procedure, :published) }
+ let(:dossier) { procedure.dossiers.last }
+
+ let(:type_de_champ_text) { create(:type_de_champ_text, procedure: procedure) }
+ let(:type_de_champ_phone) { create(:type_de_champ_phone, procedure: procedure) }
+ let(:text_value) { "My Neighbor Totoro is the best movie ever" }
+ let(:phone_value) { "invalid phone value" }
+
+ scenario "the user get the URL of a prefilled orphan brouillon dossier" do
+ dossier_url = create_and_prefill_dossier_with_post_request
+
+ expect(dossier_url).to eq(commencer_path(procedure.path, prefill_token: dossier.prefill_token))
+ end
+
+ describe 'visit the dossier URL' do
+ context 'when authenticated' do
+ it_behaves_like "the user has got a prefilled dossier, owned by themselves" do
+ let(:user) { create(:user, password: password) }
+
+ before do
+ visit "/users/sign_in"
+ sign_in_with user.email, password
+
+ visit create_and_prefill_dossier_with_post_request
+
+ expect(page).to have_content('Vous avez un dossier prérempli')
+ click_on 'Continuer à remplir mon dossier'
+ end
+ end
+ end
+
+ context 'when unauthenticated' do
+ before { visit create_and_prefill_dossier_with_post_request }
+
+ context 'when the user signs in with email and password' do
+ it_behaves_like "the user has got a prefilled dossier, owned by themselves" do
+ let(:user) { create(:user, password: password) }
+
+ before do
+ click_on "J’ai déjà un compte"
+ sign_in_with user.email, password
+
+ expect(page).to have_content('Vous avez un dossier prérempli')
+ click_on 'Continuer à remplir mon dossier'
+ end
+ end
+ end
+
+ context 'when the user signs up with email and password' do
+ it_behaves_like "the user has got a prefilled dossier, owned by themselves" do
+ let(:user_email) { generate :user_email }
+ let(:user) { User.find_by(email: user_email) }
+
+ before do
+ click_on "Créer un compte #{APPLICATION_NAME}"
+
+ sign_up_with user_email, password
+ expect(page).to have_content "nous avons besoin de vérifier votre adresse #{user_email}"
+
+ click_confirmation_link_for user_email
+ expect(page).to have_content('Votre compte a bien été confirmé.')
+
+ expect(page).to have_content('Vous avez un dossier prérempli')
+ click_on 'Continuer à remplir mon dossier'
+ end
+ end
+ end
+
+ context 'when the user signs up with FranceConnect' do
+ it_behaves_like "the user has got a prefilled dossier, owned by themselves" do
+ let(:user) { User.last }
+
+ before do
+ allow_any_instance_of(FranceConnectParticulierClient).to receive(:authorization_uri).and_return(france_connect_particulier_callback_path(code: "c0d3"))
+ allow(FranceConnectService).to receive(:retrieve_user_informations_particulier).and_return(build(:france_connect_information))
+
+ page.find('.fr-connect').click
+
+ expect(page).to have_content('Vous avez un dossier prérempli')
+ click_on 'Continuer à remplir mon dossier'
+ end
+ end
+ end
+ end
+ end
+
+ private
+
+ def create_and_prefill_dossier_with_post_request
+ session = ActionDispatch::Integration::Session.new(Rails.application)
+ session.post api_public_v1_dossiers_path(procedure),
+ headers: { "Content-Type" => "application/json" },
+ params: {
+ "champ_#{type_de_champ_text.to_typed_id}" => text_value,
+ "champ_#{type_de_champ_phone.to_typed_id}" => phone_value
+ }.to_json
+ JSON.parse(session.response.body)["dossier_url"].gsub("http://www.example.com", "")
+ end
+end
diff --git a/spec/system/users/dossier_prefill_spec.rb b/spec/system/users/dossier_prefill_spec.rb
deleted file mode 100644
index 386feeba5..000000000
--- a/spec/system/users/dossier_prefill_spec.rb
+++ /dev/null
@@ -1,80 +0,0 @@
-describe 'Prefilling a dossier:' do
- let(:password) { 'my-s3cure-p4ssword' }
- let(:siret) { '41816609600051' }
-
- let(:procedure) { create(:procedure, :published, opendata: true) }
- let(:dossier) { procedure.dossiers.last }
-
- let(:type_de_champ_text) { create(:type_de_champ_text, procedure: procedure) }
- let(:type_de_champ_phone) { create(:type_de_champ_phone, procedure: procedure) }
- let(:text_value) { "My Neighbor Totoro is the best movie ever" }
- let(:phone_value) { "invalid phone value" }
-
- before do
- stub_request(:get, /https:\/\/entreprise.api.gouv.fr\/v2\/etablissements\/#{siret}/)
- .to_return(status: 200, body: File.read('spec/fixtures/files/api_entreprise/etablissements.json'))
-
- visit commencer_path(
- path: procedure.path,
- "champ_#{type_de_champ_text.to_typed_id}" => text_value,
- "champ_#{type_de_champ_phone.to_typed_id}" => phone_value
- )
- end
-
- shared_examples "the user has got a prefilled dossier" do
- scenario "the user has got a prefilled dossier" do
- click_on "Commencer la démarche"
-
- expect(page).to have_current_path siret_dossier_path(procedure.dossiers.last)
- fill_in 'Numéro SIRET', with: siret
- click_on 'Valider'
-
- expect(page).to have_current_path(etablissement_dossier_path(dossier))
- expect(page).to have_content('OCTO TECHNOLOGY')
- click_on 'Continuer avec ces informations'
-
- expect(page).to have_current_path(brouillon_dossier_path(dossier))
- expect(page).to have_field(type_de_champ_text.libelle, with: text_value)
- expect(page).to have_field(type_de_champ_phone.libelle, with: phone_value)
- expect(page).to have_css('.field_with_errors', text: type_de_champ_phone.libelle)
- end
- end
-
- context 'when the user signs in with email and password' do
- it_behaves_like "the user has got a prefilled dossier" do
- let!(:user) { create(:user, password: password) }
-
- before do
- click_on "J’ai déjà un compte"
- sign_in_with user.email, password
- end
- end
- end
-
- context 'when the user signs up with email and password' do
- it_behaves_like "the user has got a prefilled dossier" do
- let(:user_email) { generate :user_email }
-
- before do
- click_on "Créer un compte #{APPLICATION_NAME}"
-
- sign_up_with user_email, password
- expect(page).to have_content "nous avons besoin de vérifier votre adresse #{user_email}"
-
- click_confirmation_link_for user_email
- expect(page).to have_content('Votre compte a bien été confirmé.')
- end
- end
- end
-
- context 'when the user signs up with FranceConnect' do
- it_behaves_like "the user has got a prefilled dossier" do
- before do
- allow_any_instance_of(FranceConnectParticulierClient).to receive(:authorization_uri).and_return(france_connect_particulier_callback_path(code: "c0d3"))
- allow(FranceConnectService).to receive(:retrieve_user_informations_particulier).and_return(build(:france_connect_information))
-
- page.find('.fr-connect').click
- end
- end
- end
-end