amelioration(formulaire-usager): groupes les champs suivant un titre de section dans une balise html de type <fieldset> de sorte a améliorer l'accessibilite de la plateforme
This commit is contained in:
parent
b9faa26560
commit
ad77b9321b
21 changed files with 350 additions and 34 deletions
|
@ -438,14 +438,6 @@
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
.header-section {
|
|
||||||
display: inline-block;
|
|
||||||
color: $blue-france-500;
|
|
||||||
font-size: 30px;
|
|
||||||
margin-bottom: 3 * $default-padding;
|
|
||||||
border-bottom: 3px solid $blue-france-500;
|
|
||||||
}
|
|
||||||
|
|
||||||
.header-subsection {
|
.header-subsection {
|
||||||
font-size: 22px;
|
font-size: 22px;
|
||||||
color: $blue-france-500;
|
color: $blue-france-500;
|
||||||
|
|
|
@ -1,11 +1,54 @@
|
||||||
.counter-start-header-section {
|
.counter-start-header-section {
|
||||||
counter-reset: headerSectionCounter;
|
counter-reset: h1 h2 h3 h4 h5 h6;
|
||||||
}
|
|
||||||
|
|
||||||
.header-section {
|
.reset-h1 {
|
||||||
counter-increment: headerSectionCounter;
|
counter-reset: h2;
|
||||||
|
}
|
||||||
|
|
||||||
&.header-section-counter::before {
|
.reset-h2 {
|
||||||
content: counter(headerSectionCounter) ". ";
|
counter-reset: h3;
|
||||||
|
}
|
||||||
|
|
||||||
|
.reset-h3 {
|
||||||
|
counter-reset: h4;
|
||||||
|
}
|
||||||
|
|
||||||
|
.reset-h4 {
|
||||||
|
counter-reset: h5;
|
||||||
|
}
|
||||||
|
|
||||||
|
.reset-h5 {
|
||||||
|
counter-reset: h6;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
.header-section.fr-h1::before {
|
||||||
|
counter-increment: h1;
|
||||||
|
content: counter(h1) ". ";
|
||||||
|
}
|
||||||
|
|
||||||
|
.header-section.fr-h2::before {
|
||||||
|
counter-increment: h2;
|
||||||
|
content: counter(h1) "."counter(h2) ". ";
|
||||||
|
}
|
||||||
|
|
||||||
|
.header-section.fr-h3::before {
|
||||||
|
counter-increment: h3;
|
||||||
|
content: counter(h1) "."counter(h2) "." counter(h3) ". ";
|
||||||
|
}
|
||||||
|
|
||||||
|
.header-section.fr-h4::before {
|
||||||
|
counter-increment: h4;
|
||||||
|
content: counter(h1) "."counter(h2) "." counter(h3) "." counter(h4) ". ";
|
||||||
|
}
|
||||||
|
|
||||||
|
.header-section.fr-h5::before {
|
||||||
|
counter-increment: h5;
|
||||||
|
content: counter(h1) "."counter(h2) "." counter(h3) "." counter(h4) "." counter(h5) ". ";
|
||||||
|
}
|
||||||
|
|
||||||
|
.header-section.fr-h6::before {
|
||||||
|
counter-increment: h6;
|
||||||
|
content: counter(h1) "."counter(h2) "." counter(h3) "." counter(h4) "." counter(h5) "." counter(h6) ". ";
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
42
app/components/champs/treeable.rb
Normal file
42
app/components/champs/treeable.rb
Normal file
|
@ -0,0 +1,42 @@
|
||||||
|
module Champs::Treeable
|
||||||
|
extend ActiveSupport::Concern
|
||||||
|
|
||||||
|
MAX_DEPTH = 6 # deepest level for header_sections is 3.
|
||||||
|
# but a repetition can be nested an header_section, so 3+3=6=MAX_DEPTH
|
||||||
|
|
||||||
|
included do
|
||||||
|
# as we progress in the list of ordered champs
|
||||||
|
# we keep a reference to each level of nesting (depth_cache)
|
||||||
|
# when we encounter an header_section, it depends of its own depth of nesting minus 1, ie:
|
||||||
|
# h1 belongs to prior (root)
|
||||||
|
# h2 belongs to prior h1
|
||||||
|
# h3 belongs to prior h2
|
||||||
|
# h1 belongs to prior (root)
|
||||||
|
# then, each and every champs which are not an header_section
|
||||||
|
# are added to the most_recent_subtree
|
||||||
|
# given a root_depth at 0, we build a full tree
|
||||||
|
# given a root_depth > 0, we build a partial tree (aka, a repetition)
|
||||||
|
def to_tree(champs:, root_depth:, build_champs_subtree_component:)
|
||||||
|
root = build_champs_subtree_component(header_section: nil)
|
||||||
|
depth_cache = Array.new(MAX_DEPTH)
|
||||||
|
depth_cache[root_depth] = root
|
||||||
|
most_recent_subtree = root
|
||||||
|
|
||||||
|
champs.each do |champ|
|
||||||
|
if champ.header_section?
|
||||||
|
champs_subtree = build_champs_subtree_component(header_section: champ)
|
||||||
|
depth_cache[champs_subtree.level - 1].add_node(champs_subtree)
|
||||||
|
most_recent_subtree = depth_cache[champs_subtree.level] = champs_subtree
|
||||||
|
else
|
||||||
|
most_recent_subtree.add_node(champ)
|
||||||
|
end
|
||||||
|
end
|
||||||
|
root
|
||||||
|
end
|
||||||
|
|
||||||
|
# must be implemented to render subtree
|
||||||
|
def build_champs_subtree_component(header_section:)
|
||||||
|
raise NotImplementedError
|
||||||
|
end
|
||||||
|
end
|
||||||
|
end
|
41
app/components/editable_champ/champs_subtree_component.rb
Normal file
41
app/components/editable_champ/champs_subtree_component.rb
Normal file
|
@ -0,0 +1,41 @@
|
||||||
|
class EditableChamp::ChampsSubtreeComponent < ApplicationComponent
|
||||||
|
include ApplicationHelper
|
||||||
|
|
||||||
|
attr_reader :header_section, :nodes
|
||||||
|
|
||||||
|
def initialize(header_section:)
|
||||||
|
@header_section = header_section
|
||||||
|
@nodes = []
|
||||||
|
end
|
||||||
|
|
||||||
|
# a nodes can be either a champs, or a subtree
|
||||||
|
def add_node(node)
|
||||||
|
nodes.push(node)
|
||||||
|
end
|
||||||
|
|
||||||
|
def render_within_fieldset?
|
||||||
|
header_section && !empty_section?
|
||||||
|
end
|
||||||
|
|
||||||
|
def render_header_section_only?
|
||||||
|
header_section && empty_section?
|
||||||
|
end
|
||||||
|
|
||||||
|
def empty_section?
|
||||||
|
nodes.none? { |node| node.is_a?(Champ) }
|
||||||
|
end
|
||||||
|
|
||||||
|
def level
|
||||||
|
if header_section.parent.present?
|
||||||
|
header_section.header_section_level_value.to_i + header_section.parent.current_section_level
|
||||||
|
elsif header_section
|
||||||
|
header_section.header_section_level_value.to_i
|
||||||
|
else
|
||||||
|
0
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
def tag_for_depth
|
||||||
|
"h#{level + 1}"
|
||||||
|
end
|
||||||
|
end
|
|
@ -0,0 +1,17 @@
|
||||||
|
- if render_within_fieldset?
|
||||||
|
= tag.fieldset(class: "reset-#{tag_for_depth}") do
|
||||||
|
= tag.legend do
|
||||||
|
= render EditableChamp::HeaderSectionComponent.new(champ: header_section, form: nil, level: level)
|
||||||
|
- @nodes.each do |champ_or_section|
|
||||||
|
- if champ_or_section.is_a?(Champ)
|
||||||
|
= render EditableChamp::FieldsForChampComponent.new(champ: champ_or_section, seen_at: nil)
|
||||||
|
- else
|
||||||
|
= render champ_or_section
|
||||||
|
- elsif render_header_section_only?
|
||||||
|
= render EditableChamp::HeaderSectionComponent.new(champ: header_section, form: nil, level: level)
|
||||||
|
- else
|
||||||
|
- @nodes.each do |champ_or_section|
|
||||||
|
- if champ_or_section.is_a?(Champ)
|
||||||
|
= render EditableChamp::FieldsForChampComponent.new(champ: champ_or_section, seen_at: nil)
|
||||||
|
- else
|
||||||
|
= render champ_or_section
|
13
app/components/editable_champ/champs_tree_component.rb
Normal file
13
app/components/editable_champ/champs_tree_component.rb
Normal file
|
@ -0,0 +1,13 @@
|
||||||
|
class EditableChamp::ChampsTreeComponent < ApplicationComponent
|
||||||
|
include Champs::Treeable
|
||||||
|
|
||||||
|
attr_reader :root
|
||||||
|
|
||||||
|
def initialize(champs:, root_depth:)
|
||||||
|
@root = to_tree(champs:, root_depth:, build_champs_subtree_component: method(:build_champs_subtree_component))
|
||||||
|
end
|
||||||
|
|
||||||
|
def build_champs_subtree_component(header_section:)
|
||||||
|
EditableChamp::ChampsSubtreeComponent.new(header_section:)
|
||||||
|
end
|
||||||
|
end
|
|
@ -0,0 +1 @@
|
||||||
|
= render @root
|
|
@ -0,0 +1,5 @@
|
||||||
|
class EditableChamp::FieldsForChampComponent < ApplicationComponent
|
||||||
|
def initialize(champ:, seen_at: nil)
|
||||||
|
@champ, @seen_at = champ, seen_at
|
||||||
|
end
|
||||||
|
end
|
|
@ -0,0 +1,2 @@
|
||||||
|
= fields_for @champ.input_name, @champ do |form|
|
||||||
|
= render EditableChamp::EditableChampComponent.new form: form, champ: @champ, seen_at: @seen_at
|
|
@ -1,2 +1,22 @@
|
||||||
class EditableChamp::HeaderSectionComponent < EditableChamp::EditableChampBaseComponent
|
class EditableChamp::HeaderSectionComponent < ApplicationComponent
|
||||||
|
def initialize(form:, champ:, seen_at: nil, level: 1)
|
||||||
|
@champ = champ
|
||||||
|
@form = form
|
||||||
|
@level = level
|
||||||
|
end
|
||||||
|
|
||||||
|
def libelle
|
||||||
|
@champ.libelle
|
||||||
|
end
|
||||||
|
|
||||||
|
def header_section_classnames
|
||||||
|
class_names = ["fr-h#{@level}", 'header-section']
|
||||||
|
|
||||||
|
class_names << 'header-section-counter' if @champ.dossier.auto_numbering_section_headers_for?(@champ)
|
||||||
|
class_names
|
||||||
|
end
|
||||||
|
|
||||||
|
def tag_for_depth
|
||||||
|
"h#{@level + 1}"
|
||||||
|
end
|
||||||
end
|
end
|
||||||
|
|
|
@ -0,0 +1,2 @@
|
||||||
|
= tag.send(tag_for_depth, class: header_section_classnames) do
|
||||||
|
= libelle
|
|
@ -1,8 +1,6 @@
|
||||||
- row_id = "safe-row-selector-#{@row.first.row_id}"
|
- row_id = "safe-row-selector-#{@row.first.row_id}"
|
||||||
.row{ id: row_id }
|
.row{ id: row_id }
|
||||||
- @row.each do |champ|
|
= render EditableChamp::ChampsTreeComponent.new(champs: @row, root_depth: @champ.current_section_level)
|
||||||
= fields_for champ.input_name, champ do |form|
|
|
||||||
= render EditableChamp::EditableChampComponent.new form: form, champ: champ, seen_at: @seen_at
|
|
||||||
|
|
||||||
.flex.row-reverse{ 'data-turbo': 'true' }
|
.flex.row-reverse{ 'data-turbo': 'true' }
|
||||||
= render NestedForms::OwnedButtonComponent.new(formaction: champs_repetition_path(@champ.id, row_id: @row.first.row_id), http_method: :delete, opt: { class: "fr-btn fr-btn--sm fr-btn--tertiary fr-text-action-high--red-marianne", title: t(".delete_title", row_number: @champ.rows.find_index(@row))}) do
|
= render NestedForms::OwnedButtonComponent.new(formaction: champs_repetition_path(@champ.id, row_id: @row.first.row_id), http_method: :delete, opt: { class: "fr-btn fr-btn--sm fr-btn--tertiary fr-text-action-high--red-marianne", title: t(".delete_title", row_number: @champ.rows.find_index(@row))}) do
|
||||||
|
|
|
@ -9,7 +9,7 @@ class TypesDeChampEditor::HeaderSectionComponent < ApplicationComponent
|
||||||
|
|
||||||
def header_section_options_for_select
|
def header_section_options_for_select
|
||||||
closest_level = @tdc.previous_section_level(@upper_tdcs)
|
closest_level = @tdc.previous_section_level(@upper_tdcs)
|
||||||
next_level = [MAX_LEVEL, closest_level + 1].min
|
next_level = [closest_level + 1, MAX_LEVEL].min
|
||||||
|
|
||||||
available_levels = (1..next_level).map(&method(:option_for_level))
|
available_levels = (1..next_level).map(&method(:option_for_level))
|
||||||
disabled_levels = errors? ? (next_level + 1..MAX_LEVEL).map(&method(:option_for_level)) : []
|
disabled_levels = errors? ? (next_level + 1..MAX_LEVEL).map(&method(:option_for_level)) : []
|
||||||
|
@ -21,7 +21,7 @@ class TypesDeChampEditor::HeaderSectionComponent < ApplicationComponent
|
||||||
end
|
end
|
||||||
|
|
||||||
def errors
|
def errors
|
||||||
@tdc.check_nesting(@upper_tdcs)
|
@tdc.check_coherent_header_level(@upper_tdcs)
|
||||||
end
|
end
|
||||||
|
|
||||||
private
|
private
|
||||||
|
|
|
@ -83,7 +83,12 @@ class RootController < ApplicationController
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
@dossier.association(:revision).target = @dossier.procedure.build_draft_revision
|
draft_revision = @dossier.procedure.build_draft_revision(types_de_champ_public: all_champs.map(&:type_de_champ))
|
||||||
|
@dossier.association(:revision).target = draft_revision
|
||||||
|
@dossier.champs_public.map(&:type_de_champ).map do |tdc|
|
||||||
|
tdc.association(:revision_type_de_champ).target = tdc.build_revision_type_de_champ(revision: draft_revision)
|
||||||
|
tdc.association(:revision).target = draft_revision
|
||||||
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
def suivi
|
def suivi
|
||||||
|
|
|
@ -48,7 +48,7 @@ class Champ < ApplicationRecord
|
||||||
:drop_down_secondary_description,
|
:drop_down_secondary_description,
|
||||||
:collapsible_explanation_enabled?,
|
:collapsible_explanation_enabled?,
|
||||||
:collapsible_explanation_text,
|
:collapsible_explanation_text,
|
||||||
:header_section_level,
|
:header_section_level_value,
|
||||||
:current_section_level,
|
:current_section_level,
|
||||||
:exclude_from_export?,
|
:exclude_from_export?,
|
||||||
:exclude_from_view?,
|
:exclude_from_view?,
|
||||||
|
|
|
@ -418,7 +418,7 @@ class ProcedureRevision < ApplicationRecord
|
||||||
tdcs
|
tdcs
|
||||||
.map.with_index
|
.map.with_index
|
||||||
.filter_map { |tdc, i| tdc.header_section? ? [tdc, i] : nil }
|
.filter_map { |tdc, i| tdc.header_section? ? [tdc, i] : nil }
|
||||||
.map { |tdc, i| [tdc, tdc.check_nesting(tdcs.take(i))] }
|
.map { |tdc, i| [tdc, tdc.check_coherent_header_level(tdcs.take(i))] }
|
||||||
.filter { |_tdc, errors| errors.present? }
|
.filter { |_tdc, errors| errors.present? }
|
||||||
.each { |tdc, message| errors.add(:header_section, message, type_de_champ: tdc) }
|
.each { |tdc, message| errors.add(:header_section, message, type_de_champ: tdc) }
|
||||||
end
|
end
|
||||||
|
|
|
@ -423,7 +423,7 @@ class TypeDeChamp < ApplicationRecord
|
||||||
previous_header_section.header_section_level_value.to_i
|
previous_header_section.header_section_level_value.to_i
|
||||||
end
|
end
|
||||||
|
|
||||||
def check_nesting(upper_tdcs)
|
def check_coherent_header_level(upper_tdcs)
|
||||||
errs = []
|
errs = []
|
||||||
previous_level = previous_section_level(upper_tdcs)
|
previous_level = previous_section_level(upper_tdcs)
|
||||||
|
|
||||||
|
|
|
@ -42,9 +42,5 @@
|
||||||
= f.select :groupe_instructeur_id,
|
= f.select :groupe_instructeur_id,
|
||||||
dossier.procedure.groupe_instructeurs.active.map { |gi| [gi.label, gi.id] },
|
dossier.procedure.groupe_instructeurs.active.map { |gi| [gi.label, gi.id] },
|
||||||
{ include_blank: dossier.brouillon? }
|
{ include_blank: dossier.brouillon? }
|
||||||
|
= render EditableChamp::ChampsTreeComponent.new(champs: dossier.champs_public, root_depth: 0)
|
||||||
- dossier.champs_public.each do |champ|
|
|
||||||
= fields_for champ.input_name, champ do |form|
|
|
||||||
= render EditableChamp::EditableChampComponent.new form: form, champ: champ
|
|
||||||
|
|
||||||
= render Dossiers::EditFooterComponent.new(dossier: dossier, annotation: false)
|
= render Dossiers::EditFooterComponent.new(dossier: dossier, annotation: false)
|
||||||
|
|
|
@ -3,9 +3,7 @@
|
||||||
%section.counter-start-header-section
|
%section.counter-start-header-section
|
||||||
= render NestedForms::FormOwnerComponent.new
|
= render NestedForms::FormOwnerComponent.new
|
||||||
= form_for dossier, url: annotations_instructeur_dossier_path(dossier.procedure, dossier), html: { class: 'form', multipart: true } do |f|
|
= form_for dossier, url: annotations_instructeur_dossier_path(dossier.procedure, dossier), html: { class: 'form', multipart: true } do |f|
|
||||||
- dossier.champs_private.each do |champ|
|
= render EditableChamp::ChampsTreeComponent.new(champs: dossier.champs_private, root_depth: 0)
|
||||||
= fields_for champ.input_name, champ do |form|
|
|
||||||
= render EditableChamp::EditableChampComponent.new form: form, champ: champ, seen_at: seen_at
|
|
||||||
|
|
||||||
= render Dossiers::EditFooterComponent.new(dossier: dossier, annotation: true)
|
= render Dossiers::EditFooterComponent.new(dossier: dossier, annotation: true)
|
||||||
- else
|
- else
|
||||||
|
|
142
spec/components/editable_champ/champs_tree_component_spec.rb
Normal file
142
spec/components/editable_champ/champs_tree_component_spec.rb
Normal file
|
@ -0,0 +1,142 @@
|
||||||
|
describe EditableChamp::ChampsTreeComponent, type: :component do
|
||||||
|
let(:component) { described_class.new(champs: champs, root_depth: 0) }
|
||||||
|
subject { component.root }
|
||||||
|
describe "to_tree" do
|
||||||
|
let(:header_1) { build(:champ_header_section_level_1) }
|
||||||
|
let(:header_1_2) { build(:champ_header_section_level_2) }
|
||||||
|
let(:header_2) { build(:champ_header_section_level_1) }
|
||||||
|
let(:champ_text) { build(:champ_text) }
|
||||||
|
let(:champ_textarea) { build(:champ_textarea) }
|
||||||
|
let(:champ_explication) { build(:champ_explication) }
|
||||||
|
let(:champ_communes) { build(:champ_communes) }
|
||||||
|
|
||||||
|
context 'without section' do
|
||||||
|
let(:champs) do
|
||||||
|
[
|
||||||
|
champ_text, champ_textarea
|
||||||
|
]
|
||||||
|
end
|
||||||
|
it 'chunk by uniq champs' do
|
||||||
|
expect(subject.header_section).to eq(nil)
|
||||||
|
expect(subject.nodes.size).to eq(champs.size)
|
||||||
|
expect(subject.nodes).to eq(champs)
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
context 'with sections only' do
|
||||||
|
let(:champs) do
|
||||||
|
[
|
||||||
|
header_1,
|
||||||
|
champ_explication,
|
||||||
|
champ_text,
|
||||||
|
header_2,
|
||||||
|
champ_textarea
|
||||||
|
]
|
||||||
|
end
|
||||||
|
|
||||||
|
it 'chunk by uniq champs' do
|
||||||
|
expect(subject.nodes.size).to eq(2)
|
||||||
|
expect(subject.nodes[0].header_section).to eq(header_1)
|
||||||
|
expect(subject.nodes[0].nodes).to eq([champ_explication, champ_text])
|
||||||
|
expect(subject.nodes[1].header_section).to eq(header_2)
|
||||||
|
expect(subject.nodes[1].nodes).to eq([champ_textarea])
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
context 'leading champs, and in between sections only' do
|
||||||
|
let(:champs) do
|
||||||
|
[
|
||||||
|
champ_text,
|
||||||
|
champ_textarea,
|
||||||
|
header_1,
|
||||||
|
champ_explication,
|
||||||
|
champ_communes,
|
||||||
|
header_2,
|
||||||
|
champ_textarea
|
||||||
|
]
|
||||||
|
end
|
||||||
|
it 'chunk by uniq champs' do
|
||||||
|
expect(subject.nodes.size).to eq(4)
|
||||||
|
expect(subject.nodes[0]).to eq(champ_text)
|
||||||
|
expect(subject.nodes[1]).to eq(champ_textarea)
|
||||||
|
expect(subject.nodes[2].header_section).to eq(header_1)
|
||||||
|
expect(subject.nodes[2].nodes).to eq([champ_explication, champ_communes])
|
||||||
|
expect(subject.nodes[3].header_section).to eq(header_2)
|
||||||
|
expect(subject.nodes[3].nodes).to eq([champ_textarea])
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
context 'with one sub sections' do
|
||||||
|
let(:champs) do
|
||||||
|
[
|
||||||
|
header_1,
|
||||||
|
champ_explication,
|
||||||
|
header_1_2,
|
||||||
|
champ_communes,
|
||||||
|
header_2,
|
||||||
|
champ_textarea
|
||||||
|
]
|
||||||
|
end
|
||||||
|
it 'chunk by uniq champs' do
|
||||||
|
expect(subject.nodes.size).to eq(2)
|
||||||
|
expect(subject.nodes[0].header_section).to eq(header_1)
|
||||||
|
expect(subject.nodes[0].nodes.size).to eq(2)
|
||||||
|
expect(subject.nodes[0].nodes[1].header_section).to eq(header_1_2)
|
||||||
|
expect(subject.nodes[0].nodes[1].nodes).to eq([champ_communes])
|
||||||
|
expect(subject.nodes[1].header_section).to eq(header_2)
|
||||||
|
expect(subject.nodes[1].nodes).to eq([champ_textarea])
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
context 'with consecutive subsection' do
|
||||||
|
let(:header_1) { build(:champ_header_section_level_1) }
|
||||||
|
let(:header_1_2_1) { build(:champ_header_section_level_2) }
|
||||||
|
let(:header_1_2_2) { build(:champ_header_section_level_2) }
|
||||||
|
let(:header_1_2_3) { build(:champ_header_section_level_2) }
|
||||||
|
let(:champs) do
|
||||||
|
[
|
||||||
|
header_1,
|
||||||
|
header_1_2_1,
|
||||||
|
build(:champ_text),
|
||||||
|
header_1_2_2,
|
||||||
|
build(:champ_text),
|
||||||
|
header_1_2_3,
|
||||||
|
build(:champ_text)
|
||||||
|
]
|
||||||
|
end
|
||||||
|
it 'chunk by uniq champs' do
|
||||||
|
expect(subject.nodes.size).to eq(1)
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
context 'with one sub sections and one subsub section' do
|
||||||
|
let(:header_1_2_3) { build(:champ_header_section_level_3) }
|
||||||
|
|
||||||
|
let(:champs) do
|
||||||
|
[
|
||||||
|
header_1,
|
||||||
|
champ_explication,
|
||||||
|
header_1_2,
|
||||||
|
champ_communes,
|
||||||
|
header_1_2_3,
|
||||||
|
champ_text,
|
||||||
|
header_2,
|
||||||
|
champ_textarea
|
||||||
|
]
|
||||||
|
end
|
||||||
|
|
||||||
|
it 'chunk by uniq champs' do
|
||||||
|
expect(subject.nodes.size).to eq(2)
|
||||||
|
expect(subject.nodes[0].header_section).to eq(header_1)
|
||||||
|
expect(subject.nodes[0].nodes.size).to eq(2)
|
||||||
|
expect(subject.nodes[0].nodes[1].header_section).to eq(header_1_2)
|
||||||
|
expect(subject.nodes[0].nodes[1].nodes.size).to eq(2)
|
||||||
|
expect(subject.nodes[0].nodes[1].nodes.first).to eq(champ_communes)
|
||||||
|
expect(subject.nodes[0].nodes[1].nodes[1].header_section).to eq(header_1_2_3)
|
||||||
|
expect(subject.nodes[0].nodes[1].nodes[1].nodes).to eq([champ_text])
|
||||||
|
expect(subject.nodes[1].header_section).to eq(header_2)
|
||||||
|
expect(subject.nodes[1].nodes).to eq([champ_textarea])
|
||||||
|
end
|
||||||
|
end
|
||||||
|
end
|
||||||
|
end
|
|
@ -198,9 +198,8 @@ describe 'As an administrateur I can edit types de champ', js: true do
|
||||||
context 'header section' do
|
context 'header section' do
|
||||||
scenario 'invalid order, it pops up errors summary' do
|
scenario 'invalid order, it pops up errors summary' do
|
||||||
add_champ
|
add_champ
|
||||||
wait_until { procedure.active_revision.types_de_champ_public.size == 1 }
|
|
||||||
first_header = procedure.active_revision.types_de_champ_public.first
|
|
||||||
select('Titre de section', from: 'Type de champ')
|
select('Titre de section', from: 'Type de champ')
|
||||||
|
first_header = procedure.active_revision.types_de_champ_public.first
|
||||||
select('Titre de niveau 1', from: dom_id(first_header, :header_section_level))
|
select('Titre de niveau 1', from: dom_id(first_header, :header_section_level))
|
||||||
|
|
||||||
add_champ
|
add_champ
|
||||||
|
|
Loading…
Reference in a new issue