feat(dossier): prefill drop down list champ (#8361)
* feat(dossier): prefill drop down list champ * decorate the types de champ to avoid if / else In order to avoid doing if this a drop down ? / else at several places, we decorate the types de champ and let the decorator give the possible and example values. * show all possible values when there are too many * allow to prefill 'other' option * review: remove duplicate * review: refactor for readability * validate that value is in options * review: exclude disabled options
This commit is contained in:
parent
91117fe97f
commit
5c7b2ba1f3
21 changed files with 402 additions and 18 deletions
17
app/controllers/prefill_type_de_champs_controller.rb
Normal file
17
app/controllers/prefill_type_de_champs_controller.rb
Normal file
|
@ -0,0 +1,17 @@
|
||||||
|
class PrefillTypeDeChampsController < ApplicationController
|
||||||
|
before_action :retrieve_procedure
|
||||||
|
before_action :set_prefill_type_de_champ
|
||||||
|
|
||||||
|
def show
|
||||||
|
end
|
||||||
|
|
||||||
|
private
|
||||||
|
|
||||||
|
def retrieve_procedure
|
||||||
|
@procedure = Procedure.publiees_ou_brouillons.opendata.find_by!(path: params[:path])
|
||||||
|
end
|
||||||
|
|
||||||
|
def set_prefill_type_de_champ
|
||||||
|
@type_de_champ = TypesDeChamp::PrefillTypeDeChamp.build(@procedure.active_revision.types_de_champ_public.fillable.find(params[:id]))
|
||||||
|
end
|
||||||
|
end
|
|
@ -25,6 +25,8 @@ class Champs::DropDownListChamp < Champ
|
||||||
OTHER = '__other__'
|
OTHER = '__other__'
|
||||||
delegate :options_without_empty_value_when_mandatory, to: :type_de_champ
|
delegate :options_without_empty_value_when_mandatory, to: :type_de_champ
|
||||||
|
|
||||||
|
validate :value_is_in_options, unless: -> { value.blank? || drop_down_other? }
|
||||||
|
|
||||||
def render_as_radios?
|
def render_as_radios?
|
||||||
enabled_non_empty_options.size <= THRESHOLD_NB_OPTIONS_AS_RADIO
|
enabled_non_empty_options.size <= THRESHOLD_NB_OPTIONS_AS_RADIO
|
||||||
end
|
end
|
||||||
|
@ -78,4 +80,12 @@ class Champs::DropDownListChamp < Champ
|
||||||
def remove_option(options)
|
def remove_option(options)
|
||||||
update_column(:value, nil)
|
update_column(:value, nil)
|
||||||
end
|
end
|
||||||
|
|
||||||
|
private
|
||||||
|
|
||||||
|
def value_is_in_options
|
||||||
|
return if enabled_non_empty_options.include?(value)
|
||||||
|
|
||||||
|
errors.add(:value, :not_in_options)
|
||||||
|
end
|
||||||
end
|
end
|
||||||
|
|
|
@ -15,7 +15,7 @@ class PrefillDescription < SimpleDelegator
|
||||||
end
|
end
|
||||||
|
|
||||||
def types_de_champ
|
def types_de_champ
|
||||||
active_revision.types_de_champ_public.fillable.partition(&:prefillable?).flatten
|
TypesDeChamp::PrefillTypeDeChamp.wrap(active_revision.types_de_champ_public.fillable.partition(&:prefillable?).flatten)
|
||||||
end
|
end
|
||||||
|
|
||||||
def include?(type_de_champ_id)
|
def include?(type_de_champ_id)
|
||||||
|
@ -40,21 +40,17 @@ class PrefillDescription < SimpleDelegator
|
||||||
end
|
end
|
||||||
|
|
||||||
def prefilled_champs
|
def prefilled_champs
|
||||||
@prefilled_champs ||= active_fillable_public_types_de_champ.where(id: selected_type_de_champ_ids)
|
@prefilled_champs ||= TypesDeChamp::PrefillTypeDeChamp.wrap(active_fillable_public_types_de_champ.where(id: selected_type_de_champ_ids))
|
||||||
end
|
end
|
||||||
|
|
||||||
private
|
private
|
||||||
|
|
||||||
def prefilled_champs_for_link
|
def prefilled_champs_for_link
|
||||||
prefilled_champs.map { |type_de_champ| ["champ_#{type_de_champ.to_typed_id}", example_value(type_de_champ)] }.to_h
|
prefilled_champs.map { |type_de_champ| ["champ_#{type_de_champ.to_typed_id}", type_de_champ.example_value] }.to_h
|
||||||
end
|
end
|
||||||
|
|
||||||
def prefilled_champs_for_query
|
def prefilled_champs_for_query
|
||||||
prefilled_champs.map { |type_de_champ| "\"champ_#{type_de_champ.to_typed_id}\": \"#{example_value(type_de_champ)}\"" } .join(', ')
|
prefilled_champs.map { |type_de_champ| "\"champ_#{type_de_champ.to_typed_id}\": \"#{type_de_champ.example_value}\"" } .join(', ')
|
||||||
end
|
|
||||||
|
|
||||||
def example_value(type_de_champ)
|
|
||||||
I18n.t("views.prefill_descriptions.edit.examples.#{type_de_champ.type_champ}")
|
|
||||||
end
|
end
|
||||||
|
|
||||||
def active_fillable_public_types_de_champ
|
def active_fillable_public_types_de_champ
|
||||||
|
|
|
@ -264,7 +264,8 @@ class TypeDeChamp < ApplicationRecord
|
||||||
TypeDeChamp.type_champs.fetch(:date),
|
TypeDeChamp.type_champs.fetch(:date),
|
||||||
TypeDeChamp.type_champs.fetch(:datetime),
|
TypeDeChamp.type_champs.fetch(:datetime),
|
||||||
TypeDeChamp.type_champs.fetch(:yes_no),
|
TypeDeChamp.type_champs.fetch(:yes_no),
|
||||||
TypeDeChamp.type_champs.fetch(:checkbox)
|
TypeDeChamp.type_champs.fetch(:checkbox),
|
||||||
|
TypeDeChamp.type_champs.fetch(:drop_down_list)
|
||||||
])
|
])
|
||||||
end
|
end
|
||||||
|
|
||||||
|
|
|
@ -0,0 +1,16 @@
|
||||||
|
class TypesDeChamp::PrefillDropDownListTypeDeChamp < TypesDeChamp::PrefillTypeDeChamp
|
||||||
|
def possible_values
|
||||||
|
if drop_down_other?
|
||||||
|
drop_down_list_enabled_non_empty_options.insert(
|
||||||
|
0,
|
||||||
|
I18n.t("views.prefill_descriptions.edit.possible_values.drop_down_list_other")
|
||||||
|
)
|
||||||
|
else
|
||||||
|
drop_down_list_enabled_non_empty_options
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
def example_value
|
||||||
|
possible_values.first
|
||||||
|
end
|
||||||
|
end
|
36
app/models/types_de_champ/prefill_type_de_champ.rb
Normal file
36
app/models/types_de_champ/prefill_type_de_champ.rb
Normal file
|
@ -0,0 +1,36 @@
|
||||||
|
class TypesDeChamp::PrefillTypeDeChamp < SimpleDelegator
|
||||||
|
POSSIBLE_VALUES_THRESHOLD = 10
|
||||||
|
|
||||||
|
def self.build(type_de_champ)
|
||||||
|
case type_de_champ.type_champ
|
||||||
|
when TypeDeChamp.type_champs.fetch(:drop_down_list)
|
||||||
|
TypesDeChamp::PrefillDropDownListTypeDeChamp.new(type_de_champ)
|
||||||
|
else
|
||||||
|
new(type_de_champ)
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
def self.wrap(collection)
|
||||||
|
collection.map { |type_de_champ| build(type_de_champ) }
|
||||||
|
end
|
||||||
|
|
||||||
|
def possible_values
|
||||||
|
return [] unless prefillable?
|
||||||
|
|
||||||
|
[I18n.t("views.prefill_descriptions.edit.possible_values.#{type_champ}")]
|
||||||
|
end
|
||||||
|
|
||||||
|
def example_value
|
||||||
|
return nil unless prefillable?
|
||||||
|
|
||||||
|
I18n.t("views.prefill_descriptions.edit.examples.#{type_champ}")
|
||||||
|
end
|
||||||
|
|
||||||
|
def too_many_possible_values?
|
||||||
|
possible_values.count > POSSIBLE_VALUES_THRESHOLD
|
||||||
|
end
|
||||||
|
|
||||||
|
def possible_values_sample
|
||||||
|
possible_values.first(POSSIBLE_VALUES_THRESHOLD)
|
||||||
|
end
|
||||||
|
end
|
|
@ -1,4 +1,4 @@
|
||||||
= turbo_frame_tag "#{dom_id(@prefill_description)}_types_de_champs" do
|
= turbo_frame_tag "#{dom_id(prefill_description)}_types_de_champs" do
|
||||||
.fr-grid-row.fr-grid-row--gutters.fr-py-5w
|
.fr-grid-row.fr-grid-row--gutters.fr-py-5w
|
||||||
- prefill_description.types_de_champ.each do |type_de_champ|
|
- prefill_description.types_de_champ.each do |type_de_champ|
|
||||||
- prefillable = type_de_champ.prefillable?
|
- prefillable = type_de_champ.prefillable?
|
||||||
|
@ -38,9 +38,14 @@
|
||||||
%th
|
%th
|
||||||
= t("views.prefill_descriptions.edit.possible_values.title")
|
= t("views.prefill_descriptions.edit.possible_values.title")
|
||||||
%td
|
%td
|
||||||
= t("views.prefill_descriptions.edit.possible_values.#{type_de_champ.type_champ}") if prefillable
|
- if type_de_champ.too_many_possible_values?
|
||||||
|
= "#{type_de_champ.possible_values_sample.join(", ")}..."
|
||||||
|
%br
|
||||||
|
= link_to "Voir toutes les valeurs possibles", prefill_type_de_champ_path(prefill_description.path, type_de_champ)
|
||||||
|
- else
|
||||||
|
= type_de_champ.possible_values.to_sentence
|
||||||
%tr{ class: prefillable ? "" : "fr-text-mention--grey" }
|
%tr{ class: prefillable ? "" : "fr-text-mention--grey" }
|
||||||
%th
|
%th
|
||||||
= t("views.prefill_descriptions.edit.examples.title")
|
= t("views.prefill_descriptions.edit.examples.title")
|
||||||
%td
|
%td
|
||||||
= t("views.prefill_descriptions.edit.examples.#{type_de_champ.type_champ}") if prefillable
|
= type_de_champ.example_value
|
||||||
|
|
36
app/views/prefill_type_de_champs/show.html.haml
Normal file
36
app/views/prefill_type_de_champs/show.html.haml
Normal file
|
@ -0,0 +1,36 @@
|
||||||
|
- content_for(:title, @procedure.libelle)
|
||||||
|
|
||||||
|
- content_for :footer do
|
||||||
|
= render partial: "root/footer"
|
||||||
|
|
||||||
|
.container.fr-py-5w
|
||||||
|
.card
|
||||||
|
.card-title.flex.justify-between.align-center
|
||||||
|
= @type_de_champ.libelle
|
||||||
|
= @type_de_champ.description
|
||||||
|
|
||||||
|
%table.table.vertical
|
||||||
|
%tbody
|
||||||
|
%tr
|
||||||
|
%th
|
||||||
|
= t("views.prefill_descriptions.edit.champ_id")
|
||||||
|
%td
|
||||||
|
= @type_de_champ.to_typed_id
|
||||||
|
%tr
|
||||||
|
%th
|
||||||
|
= t("views.prefill_descriptions.edit.champ_type")
|
||||||
|
%td
|
||||||
|
= t("activerecord.attributes.type_de_champ.type_champs.#{@type_de_champ.type_champ}")
|
||||||
|
%tr
|
||||||
|
%th
|
||||||
|
= t("views.prefill_descriptions.edit.possible_values.title")
|
||||||
|
%td
|
||||||
|
.fr-grid-row.fr-grid-row--gutters.fr-py-5w
|
||||||
|
- @type_de_champ.possible_values.each do |possible_value|
|
||||||
|
.fr-col-lg-3.fr-col-md-4.fr-col-sm-6.fr-col-12
|
||||||
|
= possible_value
|
||||||
|
%tr
|
||||||
|
%th
|
||||||
|
= t("views.prefill_descriptions.edit.examples.title")
|
||||||
|
%td
|
||||||
|
= @type_de_champ.example_value
|
|
@ -124,6 +124,7 @@ en:
|
||||||
date: ISO8601 date
|
date: ISO8601 date
|
||||||
datetime: ISO8601 datetime
|
datetime: ISO8601 datetime
|
||||||
checkbox: '"true" to check, "false" to uncheck'
|
checkbox: '"true" to check, "false" to uncheck'
|
||||||
|
drop_down_list_other: Any value
|
||||||
examples:
|
examples:
|
||||||
title: Example
|
title: Example
|
||||||
text: Short text
|
text: Short text
|
||||||
|
@ -439,6 +440,10 @@ en:
|
||||||
invalid: "must be 13 or 14 characters long"
|
invalid: "must be 13 or 14 characters long"
|
||||||
reference_avis:
|
reference_avis:
|
||||||
invalid: "must be 13 or 14 characters long"
|
invalid: "must be 13 or 14 characters long"
|
||||||
|
"champs/drop_down_list_champ":
|
||||||
|
attributes:
|
||||||
|
value:
|
||||||
|
not_in_options: "must be in the given options"
|
||||||
errors:
|
errors:
|
||||||
format: "Field « %{attribute} » %{message}"
|
format: "Field « %{attribute} » %{message}"
|
||||||
messages:
|
messages:
|
||||||
|
|
|
@ -116,6 +116,7 @@ fr:
|
||||||
date: Date au format ISO8601
|
date: Date au format ISO8601
|
||||||
datetime: Datetime au format ISO8601
|
datetime: Datetime au format ISO8601
|
||||||
checkbox: '"true" pour coché, "false" pour décoché'
|
checkbox: '"true" pour coché, "false" pour décoché'
|
||||||
|
drop_down_list_other: Toute valeur
|
||||||
examples:
|
examples:
|
||||||
title: Exemple
|
title: Exemple
|
||||||
text: Texte court
|
text: Texte court
|
||||||
|
@ -435,7 +436,10 @@ fr:
|
||||||
invalid: "doit posséder 13 ou 14 caractères"
|
invalid: "doit posséder 13 ou 14 caractères"
|
||||||
reference_avis:
|
reference_avis:
|
||||||
invalid: "doit posséder 13 ou 14 caractères"
|
invalid: "doit posséder 13 ou 14 caractères"
|
||||||
|
"champs/drop_down_list_champ":
|
||||||
|
attributes:
|
||||||
|
value:
|
||||||
|
not_in_options: "doit être dans les options proposées"
|
||||||
errors:
|
errors:
|
||||||
format: "Le champ « %{attribute} » %{message}"
|
format: "Le champ « %{attribute} » %{message}"
|
||||||
messages:
|
messages:
|
||||||
|
|
|
@ -198,6 +198,7 @@ Rails.application.routes.draw do
|
||||||
resources :procedures, only: [], param: :path do
|
resources :procedures, only: [], param: :path do
|
||||||
member do
|
member do
|
||||||
resource :prefill_description, only: :update
|
resource :prefill_description, only: :update
|
||||||
|
resources :prefill_type_de_champs, only: :show
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
|
|
63
spec/controllers/prefill_type_de_champs_controller_spec.rb
Normal file
63
spec/controllers/prefill_type_de_champs_controller_spec.rb
Normal file
|
@ -0,0 +1,63 @@
|
||||||
|
# frozen_string_literal: true
|
||||||
|
|
||||||
|
RSpec.describe PrefillTypeDeChampsController, type: :controller do
|
||||||
|
describe '#show' do
|
||||||
|
let(:type_de_champ) { create(:type_de_champ_text, procedure: procedure) }
|
||||||
|
subject(:show_request) { get :show, params: { path: procedure.path, id: type_de_champ.id } }
|
||||||
|
|
||||||
|
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(show_request).to render_template(:show) }
|
||||||
|
|
||||||
|
context 'when the type de champ is not found' do
|
||||||
|
let(:type_de_champ) { double(TypeDeChamp, id: -1) }
|
||||||
|
|
||||||
|
it { expect { show_request }.to raise_error(ActiveRecord::RecordNotFound) }
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
context 'when the procedure is not opendata' do
|
||||||
|
let(:procedure) { create(:procedure, :published, opendata: false) }
|
||||||
|
|
||||||
|
it { expect { show_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(show_request).to render_template(:show) }
|
||||||
|
|
||||||
|
context 'when the type de champ is not found' do
|
||||||
|
let(:type_de_champ) { double(TypeDeChamp, id: -1) }
|
||||||
|
|
||||||
|
it { expect { show_request }.to raise_error(ActiveRecord::RecordNotFound) }
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
context 'when the procedure is not opendata' do
|
||||||
|
let(:procedure) { create(:procedure, :draft, opendata: false) }
|
||||||
|
|
||||||
|
it { expect { show_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 { show_request }.to raise_error(ActiveRecord::RecordNotFound) }
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
context 'when the procedure is not found' do
|
||||||
|
let(:procedure) { create(:procedure, :published, opendata: true) }
|
||||||
|
subject(:show_request) { get :show, params: { path: "wrong path", id: type_de_champ.id } }
|
||||||
|
|
||||||
|
it { expect { show_request }.to raise_error(ActiveRecord::RecordNotFound) }
|
||||||
|
end
|
||||||
|
end
|
||||||
|
end
|
|
@ -92,7 +92,7 @@ FactoryBot.define do
|
||||||
end
|
end
|
||||||
|
|
||||||
type_de_champ { association :type_de_champ_drop_down_list, procedure: dossier.procedure, drop_down_other: other }
|
type_de_champ { association :type_de_champ_drop_down_list, procedure: dossier.procedure, drop_down_other: other }
|
||||||
value { 'choix 1' }
|
value { 'val1' }
|
||||||
end
|
end
|
||||||
|
|
||||||
factory :champ_multiple_drop_down_list, class: 'Champs::MultipleDropDownListChamp' do
|
factory :champ_multiple_drop_down_list, class: 'Champs::MultipleDropDownListChamp' do
|
||||||
|
|
|
@ -1,4 +1,54 @@
|
||||||
describe Champs::DropDownListChamp do
|
describe Champs::DropDownListChamp do
|
||||||
|
describe 'validations' do
|
||||||
|
describe 'inclusion' do
|
||||||
|
let(:drop_down) { build(:champ_drop_down_list, other: other, value: value) }
|
||||||
|
|
||||||
|
context 'when the other value is accepted' do
|
||||||
|
let(:other) { true }
|
||||||
|
|
||||||
|
context 'when the value is blank' do
|
||||||
|
let(:value) { '' }
|
||||||
|
|
||||||
|
it { expect(drop_down).to be_valid }
|
||||||
|
end
|
||||||
|
|
||||||
|
context 'when the value is included in the option list' do
|
||||||
|
let(:value) { 'val1' }
|
||||||
|
|
||||||
|
it { expect(drop_down).to be_valid }
|
||||||
|
end
|
||||||
|
|
||||||
|
context 'when the value is not included in the option list' do
|
||||||
|
let(:value) { 'something else' }
|
||||||
|
|
||||||
|
it { expect(drop_down).to be_valid }
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
context 'when the other value is not accepted' do
|
||||||
|
let(:other) { false }
|
||||||
|
|
||||||
|
context 'when the value is blank' do
|
||||||
|
let(:value) { '' }
|
||||||
|
|
||||||
|
it { expect(drop_down).to be_valid }
|
||||||
|
end
|
||||||
|
|
||||||
|
context 'when the value is included in the option list' do
|
||||||
|
let(:value) { 'val1' }
|
||||||
|
|
||||||
|
it { expect(drop_down).to be_valid }
|
||||||
|
end
|
||||||
|
|
||||||
|
context 'when the value is not included in the option list' do
|
||||||
|
let(:value) { 'something else' }
|
||||||
|
|
||||||
|
it { expect(drop_down).not_to be_valid }
|
||||||
|
end
|
||||||
|
end
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
describe '#drop_down_other?' do
|
describe '#drop_down_other?' do
|
||||||
let(:drop_down) { create(:champ_drop_down_list) }
|
let(:drop_down) { create(:champ_drop_down_list) }
|
||||||
|
|
||||||
|
|
|
@ -20,7 +20,11 @@ RSpec.describe PrefillDescription, type: :model do
|
||||||
let!(:type_de_champ) { create(:type_de_champ_text, procedure: procedure) }
|
let!(:type_de_champ) { create(:type_de_champ_text, procedure: procedure) }
|
||||||
let(:prefill_description) { described_class.new(procedure) }
|
let(:prefill_description) { described_class.new(procedure) }
|
||||||
|
|
||||||
it { expect(prefill_description.types_de_champ).to match([type_de_champ]) }
|
subject(:types_de_champ) { prefill_description.types_de_champ }
|
||||||
|
|
||||||
|
it { expect(types_de_champ.count).to eq(1) }
|
||||||
|
|
||||||
|
it { expect(types_de_champ.first).to eql(TypesDeChamp::PrefillTypeDeChamp.build(type_de_champ)) }
|
||||||
|
|
||||||
shared_examples "filters out non fillable types de champ" do |type_de_champ_name|
|
shared_examples "filters out non fillable types de champ" do |type_de_champ_name|
|
||||||
context "when the procedure has a #{type_de_champ_name} champ" do
|
context "when the procedure has a #{type_de_champ_name} champ" do
|
||||||
|
|
|
@ -116,6 +116,7 @@ RSpec.describe PrefillParams do
|
||||||
it_behaves_like "a champ public value that is authorized", :yes_no, "false"
|
it_behaves_like "a champ public value that is authorized", :yes_no, "false"
|
||||||
it_behaves_like "a champ public value that is authorized", :checkbox, "true"
|
it_behaves_like "a champ public value that is authorized", :checkbox, "true"
|
||||||
it_behaves_like "a champ public value that is authorized", :checkbox, "false"
|
it_behaves_like "a champ public value that is authorized", :checkbox, "false"
|
||||||
|
it_behaves_like "a champ public value that is authorized", :drop_down_list, "value"
|
||||||
|
|
||||||
it_behaves_like "a champ private value that is authorized", :text, "value"
|
it_behaves_like "a champ private value that is authorized", :text, "value"
|
||||||
it_behaves_like "a champ private value that is authorized", :textarea, "value"
|
it_behaves_like "a champ private value that is authorized", :textarea, "value"
|
||||||
|
@ -131,6 +132,7 @@ RSpec.describe PrefillParams do
|
||||||
it_behaves_like "a champ private value that is authorized", :yes_no, "false"
|
it_behaves_like "a champ private value that is authorized", :yes_no, "false"
|
||||||
it_behaves_like "a champ private value that is authorized", :checkbox, "true"
|
it_behaves_like "a champ private value that is authorized", :checkbox, "true"
|
||||||
it_behaves_like "a champ private value that is authorized", :checkbox, "false"
|
it_behaves_like "a champ private value that is authorized", :checkbox, "false"
|
||||||
|
it_behaves_like "a champ private value that is authorized", :drop_down_list, "value"
|
||||||
|
|
||||||
it_behaves_like "a champ public value that is unauthorized", :decimal_number, "non decimal string"
|
it_behaves_like "a champ public value that is unauthorized", :decimal_number, "non decimal string"
|
||||||
it_behaves_like "a champ public value that is unauthorized", :integer_number, "non integer string"
|
it_behaves_like "a champ public value that is unauthorized", :integer_number, "non integer string"
|
||||||
|
@ -142,7 +144,6 @@ RSpec.describe PrefillParams do
|
||||||
it_behaves_like "a champ public value that is unauthorized", :date, "value"
|
it_behaves_like "a champ public value that is unauthorized", :date, "value"
|
||||||
it_behaves_like "a champ public value that is unauthorized", :datetime, "value"
|
it_behaves_like "a champ public value that is unauthorized", :datetime, "value"
|
||||||
it_behaves_like "a champ public value that is unauthorized", :datetime, "12-22-2022T10:30"
|
it_behaves_like "a champ public value that is unauthorized", :datetime, "12-22-2022T10:30"
|
||||||
it_behaves_like "a champ public value that is unauthorized", :drop_down_list, "value"
|
|
||||||
it_behaves_like "a champ public value that is unauthorized", :multiple_drop_down_list, "value"
|
it_behaves_like "a champ public value that is unauthorized", :multiple_drop_down_list, "value"
|
||||||
it_behaves_like "a champ public value that is unauthorized", :linked_drop_down_list, "value"
|
it_behaves_like "a champ public value that is unauthorized", :linked_drop_down_list, "value"
|
||||||
it_behaves_like "a champ public value that is unauthorized", :header_section, "value"
|
it_behaves_like "a champ public value that is unauthorized", :header_section, "value"
|
||||||
|
|
|
@ -247,12 +247,12 @@ describe TypeDeChamp do
|
||||||
it_behaves_like "a prefillable type de champ", :type_de_champ_civilite
|
it_behaves_like "a prefillable type de champ", :type_de_champ_civilite
|
||||||
it_behaves_like "a prefillable type de champ", :type_de_champ_yes_no
|
it_behaves_like "a prefillable type de champ", :type_de_champ_yes_no
|
||||||
it_behaves_like "a prefillable type de champ", :type_de_champ_checkbox
|
it_behaves_like "a prefillable type de champ", :type_de_champ_checkbox
|
||||||
|
it_behaves_like "a prefillable type de champ", :type_de_champ_drop_down_list
|
||||||
|
|
||||||
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_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_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_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_titre_identite
|
||||||
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_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_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_header_section
|
||||||
|
|
|
@ -0,0 +1,30 @@
|
||||||
|
# frozen_string_literal: true
|
||||||
|
|
||||||
|
RSpec.describe TypesDeChamp::PrefillDropDownListTypeDeChamp do
|
||||||
|
describe '#possible_values' do
|
||||||
|
subject(:possible_values) { described_class.new(type_de_champ).possible_values }
|
||||||
|
|
||||||
|
context "when the drop down list accepts 'other'" do
|
||||||
|
let(:type_de_champ) { build(:type_de_champ_drop_down_list, :with_other) }
|
||||||
|
|
||||||
|
it {
|
||||||
|
expect(possible_values).to match(
|
||||||
|
[I18n.t("views.prefill_descriptions.edit.possible_values.drop_down_list_other")] + type_de_champ.drop_down_list_enabled_non_empty_options
|
||||||
|
)
|
||||||
|
}
|
||||||
|
end
|
||||||
|
|
||||||
|
context "when the drop down list does not accept 'other'" do
|
||||||
|
let(:type_de_champ) { build(:type_de_champ_drop_down_list) }
|
||||||
|
|
||||||
|
it { expect(possible_values).to match(type_de_champ.drop_down_list_enabled_non_empty_options) }
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
describe '#example_value' do
|
||||||
|
let(:type_de_champ) { build(:type_de_champ_drop_down_list) }
|
||||||
|
subject(:example_value) { described_class.new(type_de_champ).example_value }
|
||||||
|
|
||||||
|
it { expect(example_value).to eq(type_de_champ.drop_down_list_enabled_non_empty_options.first) }
|
||||||
|
end
|
||||||
|
end
|
85
spec/models/types_de_champ/prefill_type_de_champ_spec.rb
Normal file
85
spec/models/types_de_champ/prefill_type_de_champ_spec.rb
Normal file
|
@ -0,0 +1,85 @@
|
||||||
|
# frozen_string_literal: true
|
||||||
|
|
||||||
|
RSpec.describe TypesDeChamp::PrefillTypeDeChamp, type: :model do
|
||||||
|
describe '.build' do
|
||||||
|
subject(:built) { described_class.build(type_de_champ) }
|
||||||
|
|
||||||
|
context 'when the type de champ is a drop_down_list' do
|
||||||
|
let(:type_de_champ) { build(:type_de_champ_drop_down_list) }
|
||||||
|
|
||||||
|
it { expect(built).to be_kind_of(TypesDeChamp::PrefillDropDownListTypeDeChamp) }
|
||||||
|
end
|
||||||
|
|
||||||
|
context 'when any other type de champ' do
|
||||||
|
let(:type_de_champ) { build(:type_de_champ_date) }
|
||||||
|
|
||||||
|
it { expect(built).to be_kind_of(TypesDeChamp::PrefillTypeDeChamp) }
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
describe '.wrap' do
|
||||||
|
subject(:wrapped) { described_class.wrap([build(:type_de_champ_drop_down_list), build(:type_de_champ_email)]) }
|
||||||
|
|
||||||
|
it 'wraps the collection' do
|
||||||
|
expect(wrapped.first).to be_kind_of(TypesDeChamp::PrefillDropDownListTypeDeChamp)
|
||||||
|
expect(wrapped.last).to be_kind_of(TypesDeChamp::PrefillTypeDeChamp)
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
describe '#possible_values' do
|
||||||
|
subject(:possible_values) { described_class.build(type_de_champ).possible_values }
|
||||||
|
|
||||||
|
context 'when the type de champ is not prefillable' do
|
||||||
|
let(:type_de_champ) { build(:type_de_champ_mesri) }
|
||||||
|
|
||||||
|
it { expect(possible_values).to be_empty }
|
||||||
|
end
|
||||||
|
|
||||||
|
context 'when the type de champ is prefillable' do
|
||||||
|
let(:type_de_champ) { build(:type_de_champ_email) }
|
||||||
|
|
||||||
|
it { expect(possible_values).to match([I18n.t("views.prefill_descriptions.edit.possible_values.#{type_de_champ.type_champ}")]) }
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
describe '#example_value' do
|
||||||
|
subject(:example_value) { described_class.build(type_de_champ).example_value }
|
||||||
|
|
||||||
|
context 'when the type de champ is not prefillable' do
|
||||||
|
let(:type_de_champ) { build(:type_de_champ_mesri) }
|
||||||
|
|
||||||
|
it { expect(example_value).to be_nil }
|
||||||
|
end
|
||||||
|
|
||||||
|
context 'when the type de champ is prefillable' do
|
||||||
|
let(:type_de_champ) { build(:type_de_champ_email) }
|
||||||
|
|
||||||
|
it { expect(example_value).to eq(I18n.t("views.prefill_descriptions.edit.examples.#{type_de_champ.type_champ}")) }
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
describe '#too_many_possible_values?' do
|
||||||
|
let(:type_de_champ) { build(:type_de_champ_drop_down_list) }
|
||||||
|
subject(:too_many_possible_values) { described_class.build(type_de_champ).too_many_possible_values? }
|
||||||
|
|
||||||
|
context 'when there are too many possible values' do
|
||||||
|
before { type_de_champ.drop_down_options = (1..described_class::POSSIBLE_VALUES_THRESHOLD + 1).map(&:to_s) }
|
||||||
|
|
||||||
|
it { expect(too_many_possible_values).to eq(true) }
|
||||||
|
end
|
||||||
|
|
||||||
|
context 'when there are not too many possible values' do
|
||||||
|
before { type_de_champ.drop_down_options = (1..described_class::POSSIBLE_VALUES_THRESHOLD).map(&:to_s) }
|
||||||
|
|
||||||
|
it { expect(too_many_possible_values).to eq(false) }
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
describe '#possible_values_sample' do
|
||||||
|
let(:drop_down_options) { (1..described_class::POSSIBLE_VALUES_THRESHOLD + 1).map(&:to_s) }
|
||||||
|
let(:type_de_champ) { build(:type_de_champ_drop_down_list, drop_down_options: drop_down_options) }
|
||||||
|
subject(:possible_values_sample) { described_class.build(type_de_champ).possible_values_sample }
|
||||||
|
|
||||||
|
it { expect(possible_values_sample).to match(drop_down_options.first(described_class::POSSIBLE_VALUES_THRESHOLD)) }
|
||||||
|
end
|
||||||
|
end
|
|
@ -0,0 +1,22 @@
|
||||||
|
describe 'prefill_descriptions/types_de_champs.html.haml', type: :view do
|
||||||
|
let(:prefill_description) { PrefillDescription.new(create(:procedure)) }
|
||||||
|
let!(:type_de_champ) { create(:type_de_champ_drop_down_list, procedure: prefill_description, drop_down_options: options) }
|
||||||
|
|
||||||
|
subject { render('prefill_descriptions/types_de_champs.html.haml', prefill_description: prefill_description) }
|
||||||
|
|
||||||
|
context 'when a type de champ has too many values' do
|
||||||
|
let(:options) { (1..20).map(&:to_s) }
|
||||||
|
|
||||||
|
it { is_expected.to have_content(type_de_champ.libelle) }
|
||||||
|
|
||||||
|
it { is_expected.to have_link(text: "Voir toutes les valeurs possibles", href: prefill_type_de_champ_path(prefill_description.path, type_de_champ)) }
|
||||||
|
end
|
||||||
|
|
||||||
|
context 'when a type de champ does not have too many values' do
|
||||||
|
let(:options) { (1..2).map(&:to_s) }
|
||||||
|
|
||||||
|
it { is_expected.to have_content(type_de_champ.libelle) }
|
||||||
|
|
||||||
|
it { is_expected.not_to have_link(text: "Voir toutes les valeurs possibles", href: prefill_type_de_champ_path(prefill_description.path, type_de_champ)) }
|
||||||
|
end
|
||||||
|
end
|
|
@ -40,7 +40,7 @@ describe 'shared/dossiers/edit.html.haml', type: :view do
|
||||||
context 'with a single-value list' do
|
context 'with a single-value list' do
|
||||||
let(:dossier) { create(:dossier) }
|
let(:dossier) { create(:dossier) }
|
||||||
let(:type_de_champ) { create(:type_de_champ_drop_down_list, mandatory: mandatory, procedure: dossier.procedure) }
|
let(:type_de_champ) { create(:type_de_champ_drop_down_list, mandatory: mandatory, procedure: dossier.procedure) }
|
||||||
let(:champ) { create(:champ_drop_down_list, dossier: dossier, type_de_champ: type_de_champ) }
|
let(:champ) { create(:champ_drop_down_list, dossier: dossier, type_de_champ: type_de_champ, value: value) }
|
||||||
let(:options) { type_de_champ.drop_down_list_options }
|
let(:options) { type_de_champ.drop_down_list_options }
|
||||||
let(:enabled_options) { type_de_champ.drop_down_list_enabled_non_empty_options }
|
let(:enabled_options) { type_de_champ.drop_down_list_enabled_non_empty_options }
|
||||||
let(:mandatory) { true }
|
let(:mandatory) { true }
|
||||||
|
@ -48,6 +48,7 @@ describe 'shared/dossiers/edit.html.haml', type: :view do
|
||||||
before { dossier.champs_public << champ }
|
before { dossier.champs_public << champ }
|
||||||
|
|
||||||
context 'when the list is short' do
|
context 'when the list is short' do
|
||||||
|
let(:value) { 'val1' }
|
||||||
it 'renders the list as radio buttons' do
|
it 'renders the list as radio buttons' do
|
||||||
expect(subject).to have_selector('input[type=radio]', count: enabled_options.count)
|
expect(subject).to have_selector('input[type=radio]', count: enabled_options.count)
|
||||||
end
|
end
|
||||||
|
@ -63,6 +64,7 @@ describe 'shared/dossiers/edit.html.haml', type: :view do
|
||||||
end
|
end
|
||||||
|
|
||||||
context 'when the list is long' do
|
context 'when the list is long' do
|
||||||
|
let(:value) { 'alpha' }
|
||||||
let(:type_de_champ) { create(:type_de_champ_drop_down_list, :long, procedure: dossier.procedure) }
|
let(:type_de_champ) { create(:type_de_champ_drop_down_list, :long, procedure: dossier.procedure) }
|
||||||
|
|
||||||
it 'renders the list as a dropdown' do
|
it 'renders the list as a dropdown' do
|
||||||
|
|
Loading…
Reference in a new issue