Merge branch 'demarches-simplifiees:main' into poc-self_hosted_runners

This commit is contained in:
kleph 2023-08-31 18:55:57 +02:00 committed by GitHub
commit dd4d60fdfe
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
83 changed files with 331 additions and 382 deletions

View file

@ -41,11 +41,11 @@ demarches-simplifiees.fr est **compliqué à héberger**. Parmi les problématiq
- **Utilisation de services externes** : demarches-simplifiees.fr sinterconnecte à de nombreux services externes : des APIs (API Entreprise, API Carto, la Base Adresse Nationale, etc.) mais aussi des services pour le stockage externe des pièces-jointes, lanalyse anti-virus ou lenvoi des emails. Le fonctionnement de demarches-simplifiees.fr dépend de la disponibilité de ces services externes.
- **Mises à jour** : le schéma de la base de données change régulièrement. Nous codons également des scripts pour harmoniser les anciennes données. Parfois des modifications ponctuelles sont effectuées sur des démarches anciennes, pour les mettre en conformité avec de nouvelles règles métiers. Nous maintenons également les dépendances logicielles utilisées notamment en réagissant rapidement lorsquune faille de sécurité est signalée. Ces mises à jour fréquentes en production sont indispensables au bon fonctionnement de loutil.
Si vous souhaitez adapter demarches-simplifiees.fr à votre besoin, nous vous recommandons de **proposer vos modifications à la base de code principale** (par exemple en créant une issue) **plutôt que dhéberger une autre instance vous-même**.
Si vous souhaitez adapter demarches-simplifiees.fr à vos besoins, nous vous recommandons de **proposer vos modifications à la base de code principale** (par exemple en créant une issue) **plutôt que dhéberger une autre instance vous-même**.
Dans le cas où vous envisagez dhéberger une instance de demarches-simplifiees.fr vous-même, nous n'avons malheureusement pas les moyens de vous accompagner, ni dassurer de support technique concernant votre installation.
Dans le cas où vous envisagez dhéberger une instance de demarches-simplifiees.fr vous-même, nous ne disposons malheureusement pas des moyens pour vous accompagner, ni dassurer de support technique concernant votre installation.
Toutefois, certains acteurs (le ministère des armées, ladministration autonome en Polynésie française) ont déployé des instances séparées. Nous proposons aux personnes intéressées de les mettre en relation avec ces acteurs existants, afin de disposer dun retour dexpérience, et de bénéficier de leur retour.
Toutefois, certains acteurs (le ministère des armées, ladministration autonome en Polynésie française, l'association Adullact) ont déployé des instances séparées. Nous proposons aux personnes intéressées de les mettre en relation avec ces acteurs existants, pour obtenir un retour dexpérience et bénéficier de leur retour.
## Bonnes pratiques de code

View file

@ -28,7 +28,7 @@ Vous souhaitez y apporter des changements ou des améliorations ? Lisez notre [
- Chrome
- chromedriver :
* Mac : `brew install chromedriver`
* Linux : voir https://sites.google.com/a/chromium.org/chromedriver/downloads
* Linux : voir https://developer.chrome.com/blog/chrome-for-testing
Si l'emplacement d'installation de Chrome n'est pas standard, ou que vous utilisez Brave ou Chromium à la place,
il peut être nécessaire d'overrider pour votre machine le path vers le binaire Chrome, par exemple :
@ -42,8 +42,7 @@ Selenium::WebDriver::Chrome.path = "/Applications/Brave Browser.app/Contents/Mac
Webdrivers::Chromedriver.required_version = "103.0.5060.53"
```
Il peut être également pertinent de désactiver la mise à jour automatique du webdriver
en définissant une variable d'environnement `SKIP_UPDATE_WEBDRIVER` lors de l'exécution de `bin/update`.
Il est également possible de faire une installation et mise à jour automatique lors de l'exécution de `bin/update` en définissant la variable d'environnement `UPDATE_WEBDRIVER`. Les binaires seront installés dans le repertoire `~/.local/bin/` qui doit être rajouté manuellement dans le path.
### Création des rôles de la base de données

View file

@ -49,7 +49,7 @@
}
}
:not(.fr-downloads-group) > ul {
:not(.fr-downloads-group):not(.fr-pagination) > ul {
list-style-type: disc;
list-style-position: inside;
padding-left: $default-padding;

View file

@ -18,6 +18,8 @@
= render partial: "shared/champs/carte/show", locals: { champ: champ }
- when TypeDeChamp.type_champs.fetch(:dossier_link)
= render partial: "shared/champs/dossier_link/show", locals: { champ: champ }
- when TypeDeChamp.type_champs.fetch(:drop_down_list)
= render partial: "shared/champs/drop_down_list/show", locals: { champ: champ }
- when TypeDeChamp.type_champs.fetch(:multiple_drop_down_list)
= render partial: "shared/champs/multiple_drop_down_list/show", locals: { champ: champ }
- when TypeDeChamp.type_champs.fetch(:piece_justificative), TypeDeChamp.type_champs.fetch(:titre_identite)

View file

@ -7,6 +7,7 @@ class Dsfr::InputComponent < ApplicationComponent
# use it to indicate detailed about the inputs, ex: https://www.systeme-de-design.gouv.fr/elements-d-interface/modeles-et-blocs-fonctionnels/demande-de-mot-de-passe
# it uses aria-describedby on input and link it to yielded content
renders_one :describedby
renders_one :label
def initialize(form:, attribute:, input_type: :text_field, opts: {}, required: true)
@form = form
@ -46,7 +47,7 @@ class Dsfr::InputComponent < ApplicationComponent
# i18n lookups
def label
object.class.human_attribute_name(@attribute)
get_slot(:label).presence || default_label
end
# kind of input helpers
@ -63,4 +64,8 @@ class Dsfr::InputComponent < ApplicationComponent
end
private
def default_label
object.class.human_attribute_name(@attribute)
end
end

View file

@ -159,20 +159,13 @@ module Administrateurs
def update_state
@groupe_instructeur = procedure.groupe_instructeurs.find(params[:groupe_instructeur_id])
if closed_params? && @groupe_instructeur.id == procedure.defaut_groupe_instructeur.id
redirect_to admin_procedure_groupe_instructeur_path(procedure, @groupe_instructeur),
alert: "Il est impossible de désactiver le groupe dinstructeurs par défaut."
elsif @groupe_instructeur.update(closed: params[:closed])
if @groupe_instructeur.update(closed: params[:closed])
state_for_notice = @groupe_instructeur.closed ? 'désactivé' : 'activé'
redirect_to admin_procedure_groupe_instructeur_path(procedure, @groupe_instructeur),
notice: "Le groupe #{@groupe_instructeur.label} est #{state_for_notice}."
else
@procedure = procedure
@instructeurs = paginated_instructeurs
@available_instructeur_emails = available_instructeur_emails
flash.now[:alert] = @groupe_instructeur.errors.full_messages
render :show
redirect_to admin_procedure_groupe_instructeur_path(procedure, @groupe_instructeur),
alert: @groupe_instructeur.errors.messages_for(:closed).to_sentence
end
end

View file

@ -5,8 +5,9 @@ class Champs::OptionsController < ApplicationController
def remove
champ = policy_scope(Champ).includes(:champs).find(params[:champ_id])
champ.remove_option([params[:option]].compact)
champ.remove_option([params[:option]].compact, true)
champs = champ.private? ? champ.dossier.champs_private_all : champ.dossier.champs_public_all
@dossier = champ.private? ? nil : champ.dossier
@to_show, @to_hide, @to_update = champs_to_turbo_update({ params[:champ_id] => true }, champs)
end
end

View file

@ -35,7 +35,7 @@ class RechercheController < ApplicationController
# to make it simpler we only do it if the @search_terms is an id
return if !DossierSearchService.id_compatible?(@search_terms)
dossier_instructeur_searched_for = Dossier.find_by(id: @search_terms)
dossier_instructeur_searched_for = Dossier.state_not_brouillon.find_by(id: @search_terms)
return if dossier_instructeur_searched_for.nil?
return if current_instructeur&.groupe_instructeur_ids&.include?(dossier_instructeur_searched_for.groupe_instructeur_id)

View file

@ -1348,6 +1348,11 @@ type Dossier {
"""
datePassageEnInstruction: ISO8601DateTime
"""
Date prévisionnelle de décision automatique par le SVA/SVR.
"""
datePrevisionnelleDecisionSVASVR: ISO8601Date
"""
Date de la suppression par ladministration.
"""
@ -1362,6 +1367,11 @@ type Dossier {
Date du dernier traitement.
"""
dateTraitement: ISO8601DateTime
"""
Date du traitement automatique par le SVA/SVR.
"""
dateTraitementSVASVR: ISO8601DateTime
demandeur: Demandeur!
demarche: DemarcheDescriptor!

View file

@ -32,6 +32,9 @@ module Types
field :date_derniere_correction_en_attente, GraphQL::Types::ISO8601DateTime, "Date de la dernière demande de correction qui na pas encore été traitée par lusager.", null: true
field :date_previsionnelle_decision_sva_svr, GraphQL::Types::ISO8601Date, "Date prévisionnelle de décision automatique par le SVA/SVR.", null: true, method: :sva_svr_decision_on
field :date_traitement_sva_svr, GraphQL::Types::ISO8601DateTime, "Date du traitement automatique par le SVA/SVR.", null: true, method: :sva_svr_decision_triggered_at
field :archived, Boolean, null: false
field :connection_usager, ConnectionUsager, null: false

View file

@ -84,7 +84,8 @@ export class AutoUpload {
return {
title:
'Le fichier na pas pu être envoyé. Vérifiez votre connexion à Internet, puis ré-essayez. Vérifiez aussi que le pare-feu de votre appareil ou votre réseau autorise lenvoi de fichier vers ' +
window.location.host,
window.location.host +
' et static.demarches-simplifiees.fr.',
retry: true
};
} else if (error.code == ERROR_CODE_READ) {

View file

@ -62,6 +62,7 @@ class Champ < ApplicationRecord
delegate :to_typed_id, :to_typed_id_for_query, to: :type_de_champ, prefix: true
delegate :revision, to: :dossier, prefix: true
delegate :used_by_routing_rules?, to: :type_de_champ
scope :updated_since?, -> (date) { where('champs.updated_at > ?', date) }
scope :public_only, -> { where(private: false) }

View file

@ -62,9 +62,13 @@ class Champs::DropDownListChamp < Champ
options.include?(value)
end
def remove_option(options)
def remove_option(options, touch = false)
if touch
update(value: nil)
else
update_column(:value, nil)
end
end
private

View file

@ -70,9 +70,13 @@ class Champs::LinkedDropDownListChamp < Champ
options.include?(primary_value) || options.include?(secondary_value)
end
def remove_option(options)
def remove_option(options, touch = false)
if touch
update(value: nil)
else
update_column(:value, nil)
end
end
private

View file

@ -51,8 +51,13 @@ class Champs::MultipleDropDownListChamp < Champ
(selected_options - options).size != selected_options.size
end
def remove_option(options)
update_column(:value, (selected_options - options).to_json)
def remove_option(options, touch = false)
value = (selected_options - options).to_json
if touch
update(value:)
else
update_columns(value:)
end
end
def focusable_input_id

View file

@ -34,6 +34,7 @@ class Expert < ApplicationRecord
procedure_with_new, procedure_without_new = old_expert
.procedures
.with_discarded
.partition { |p| p.experts.exists?(id) }
ExpertsProcedure

View file

@ -16,13 +16,7 @@ class GroupeInstructeur < ApplicationRecord
validates :label, presence: true, allow_nil: false
validates :label, uniqueness: { scope: :procedure }
validates :closed, acceptance: { accept: [false] }, if: -> do
if closed
(other_groupe_instructeurs.map(&:closed) + [closed]).all?
else
false
end
end
validates :closed, acceptance: { accept: [false] }, if: -> { (self == procedure.defaut_groupe_instructeur) }
before_validation -> { label&.strip! }

View file

@ -7,7 +7,7 @@
= hidden_field_tag 'statuses[]', status, id: "status_#{status}"
= hidden_field_tag 'from_publication_date', @filter.from_publication_date if @filter.from_publication_date.present?
= f.label 'email', 'Recercher des administrateurs par email', class: 'fr-label'
= f.label 'email', 'Rechercher des administrateurs par email', class: 'fr-label'
= f.search_field 'email', size: 40, class: 'fr-input', data: { turbo_force: :server }
.actions= link_to 'Voir la liste des démarches', all_admin_procedures_path(@filter.params), class: 'fr-btn fr-btn--secondary'
.fr-table.fr-table--bordered

View file

@ -14,7 +14,7 @@
= link_to t('.citizen_page'), new_user_session_path, class: "fr-btn fr-btn--secondary"
.column
%h1.fr-my-2
%h1.fr-my-2w
= t('.connect')
.fr-connect-group.fr-my-2w
@ -29,20 +29,30 @@
%p.fr-hr-or= t('views.shared.france_connect_login.separator')
#session-new.auth-form.sign-in-form
= form_for User.new, url: user_session_path, html: { class: "form" } do |f|
= f.label :email, t('.pro_email')
= f.text_field :email, type: :email, autocomplete: 'username', autofocus: true
= form_for User.new, url: user_session_path do |f|
= f.label :password, t('views.users.sessions.new.password', min_length: PASSWORD_MIN_LENGTH)
= f.password_field :password, autocomplete: 'current-password'
%fieldset.fr-mb-0.fr-fieldset{ aria: { labelledby: 'new-account-legend' } }
%legend.fr-fieldset__legend#new-account-legend
%h2.fr-h6= I18n.t('views.users.sessions.new.subtitle')
.fr-fieldset__element
%p.fr-text--sm= t('utils.mandatory_champs')
.fr-fieldset__element
= render Dsfr::InputComponent.new(form: f, attribute: :email, input_type: :email_field, opts: { autocomplete: 'email', autofocus: true }) do |c|
- c.with_label { t('.pro_email') }
.fr-fieldset__element
= render Dsfr::InputComponent.new(form: f, attribute: :password, input_type: :password_field, opts: { autocomplete: 'current-password' })
%p= link_to t('views.users.sessions.new.reset_password'), new_user_password_path, class: "link"
.fr-fieldset__element
.auth-options
.flex-no-shrink
= f.check_box :remember_me
= f.label :remember_me, t('views.users.sessions.new.remember_me'), class: 'remember-me'
.text-right
= link_to t('views.users.sessions.new.reset_password'), new_user_password_path, class: "link"
= f.submit t('views.users.sessions.new.connection'), class: "fr-btn fr-btn--lg"

View file

@ -1 +1 @@
= render partial: 'shared/dossiers/update_champs', locals: { to_show: @to_show, to_hide: @to_hide, to_update: @to_update }
= render partial: 'shared/dossiers/update_champs', locals: { to_show: @to_show, to_hide: @to_hide, to_update: @to_update, dossier: @dossier }

View file

@ -3,17 +3,20 @@
- content_for :footer do
= render partial: 'root/footer'
.container.devise-container
.one-column-centered
.fr-container.fr-my-5w
.fr-grid-row.fr-grid-row--center
.fr-col-lg-6
= devise_error_messages!
= form_for(resource, as: resource_name, url: password_path(resource_name), html: { class: 'form' }) do |f|
= form_for(resource, as: resource_name, url: password_path(resource_name)) do |f|
%fieldset.fr-mb-0.fr-fieldset{ aria: { labelledby: 'new-password-legend' } }
%legend.fr-fieldset__legend#new-password-legend
%h1.fr-h2= t('devise.passwords.new.forgot_your_password')
%h1= t('devise.passwords.new.forgot_your_password')
.fr-fieldset__element
%p.fr-text--sm= t('devise.passwords.new.send_me_reset_password_instructions')
%p.notice= t('devise.passwords.new.send_me_reset_password_instructions')
.fr-fieldset__element
= render Dsfr::InputComponent.new(form: f, attribute: :email, input_type: :email_field, opts: { autocomplete: 'email', autofocus: true })
= f.label :email, 'Email'
= f.email_field :email, autofocus: true
= f.submit t('devise.passwords.new.request_new_password'), class: 'fr-btn fr-btn--lg'
= f.submit t('devise.passwords.new.request_new_password'), class: 'fr-btn fr-btn--lg fr-mt-4w'

View file

@ -1 +1 @@
= render partial: 'shared/dossiers/update_champs', locals: { to_show: @to_show, to_hide: @to_hide, to_update: @to_update }
= render partial: 'shared/dossiers/update_champs', locals: { to_show: @to_show, to_hide: @to_hide, to_update: @to_update, dossier: nil }

View file

@ -0,0 +1,6 @@
- if champ.used_by_routing_rules? && champ.dossier.forced_groupe_instructeur
%p
%span= champ.value
%span.fr-badge.fr-badge--warning.fr-badge--sm dossier réaffecté au groupe « #{champ.dossier.groupe_instructeur.label} »
- else
%p= champ.value

View file

@ -13,3 +13,7 @@
= turbo_stream.remove_all(".editable-champ .spinner-removable")
= turbo_stream.hide_all(".editable-champ .spinner")
- if dossier.present?
= turbo_stream.replace_all '.dossier-edit-sticky-footer' do
= render Dossiers::EditFooterComponent.new(dossier:, annotation: false)

View file

@ -1,20 +1,22 @@
.super-admin.flex.justify-center
%div
%h2.huge-title Espace Manager
.auth-form.sign-in-form
.fr-container.fr-my-5w
.fr-grid-row.fr-grid-row--center
.fr-col-lg-6
%h1.fr-h2 Espace Manager
= devise_error_messages!
= form_for SuperAdmin.new, url: super_admin_session_path, html: { class: "form" } do |f|
%h1.fr-h2 Connectez-vous
= form_for SuperAdmin.new, url: super_admin_session_path do |f|
%fieldset.fr-mb-0.fr-fieldset
.fr-fieldset__element
= render Dsfr::InputComponent.new(form: f, attribute: :email, input_type: :email_field, opts: { autocomplete: 'email', autofocus: true })
= f.label :email, "Email"
= f.text_field :email, type: :email, autocomplete: 'username', autofocus: true
= f.label :password, "Mot de passe (#{PASSWORD_MIN_LENGTH} caractères minimum)"
= f.password_field :password, autocomplete: 'current-password'
.fr-fieldset__element
= render Dsfr::InputComponent.new(form: f, attribute: :password, input_type: :password_field, opts: { autocomplete: 'current-password' })
- if SUPER_ADMIN_OTP_ENABLED
= f.label :otp_attempt, 'Code OTP (uniquement si vous avez déjà activé 2FA)'
= f.text_field :otp_attempt
.fr-fieldset__element
= render Dsfr::InputComponent.new(form: f, attribute: :otp_attempt, input_type: :number_field, opts: { inputmode: :numeric }, required: false)
%p= link_to "Mot de passe oublié ou réinitialisation 2FA ?", new_super_admin_password_path, class: "link"
= f.submit "Se connecter", class: "fr-btn fr-btn--lg"
.fr-fieldset__element
%p= link_to "Mot de passe oublié ou réinitialisation 2FA ?", new_super_admin_password_path, class: "link"
= f.submit t('views.users.sessions.new.connection'), class: "fr-btn fr-btn--lg"

View file

@ -1,4 +1 @@
= render partial: 'shared/dossiers/update_champs', locals: { to_show: @to_show, to_hide: @to_hide, to_update: @to_update, dossier: @dossier, annotation: false }
= turbo_stream.replace_all '.dossier-edit-sticky-footer' do
= render Dossiers::EditFooterComponent.new(dossier: @dossier, annotation: false)
= render partial: 'shared/dossiers/update_champs', locals: { to_show: @to_show, to_hide: @to_hide, to_update: @to_update, dossier: @dossier }

View file

@ -19,11 +19,16 @@ FileUtils.chdir APP_ROOT do
system! 'bin/yarn install'
system! 'bin/yarn clean'
if ENV["SKIP_UPDATE_WEBDRIVER"]
puts "\n== Ignoring webdrivers update because of local configuration. You may need to update it manually.=="
else
if ENV["UPDATE_WEBDRIVER"]
puts "\n== Updating webdrivers =="
system! 'RAILS_ENV=test bin/rails webdrivers:chromedriver:update'
puts "\nyou must add ~/.local/bin to your path"
system! 'npx @puppeteer/browsers clear --path ~/.local/bin/headless_browsers'
system! 'npx @puppeteer/browsers install chromedriver --path ~/.local/bin/headless_browsers'
system! 'npx @puppeteer/browsers install chrome --path ~/.local/bin/headless_browsers'
system! 'rm -f ~/.local/bin/chromedriver && ln -s $(find ~/.local/bin/headless_browsers -type f -name chromedriver) ~/.local/bin/chromedriver'
system! 'rm -f ~/.local/bin/chrome && ln -s $(find ~/.local/bin/headless_browsers -type f -name chrome) ~/.local/bin/chrome'
end
puts "\n== Updating database =="

View file

@ -26,7 +26,7 @@ features = [
def database_exists?
ActiveRecord::Base.connection
true
rescue ActiveRecord::NoDatabaseError, PG::ConnectionBad
rescue ActiveRecord::ConnectionNotEstablished, ActiveRecord::NoDatabaseError, PG::ConnectionBad
false
end

View file

@ -251,7 +251,7 @@ en:
pays_html: An <a href="https://en.wikipedia.org/wiki/ISO_3166-2" target="_blank" rel="noopener noreferrer">ISO 3166-2 country code</a>
regions_html: An <a href="https://fr.wikipedia.org/wiki/R%C3%A9gion_fran%C3%A7aise" target="_blank" rel="noopener noreferrer">INSEE region code</a>
departements_html: A <a href="https://fr.wikipedia.org/wiki/Num%C3%A9rotation_des_d%C3%A9partements_fran%C3%A7ais" target="_blank">department number</a>
communes_html: An array of the department code and the <a href="https://geo.api.gouv.fr/communes" target="_blank" rel="noopener noreferrer">INSEE commune code</a>
communes_html: An array of the postal code and the <a href="https://geo.api.gouv.fr/communes" target="_blank" rel="noopener noreferrer">INSEE commune code</a>
address_html: An address EXACTLY formated as the label returned by <a href="https://adresse.data.gouv.fr" target="_blank" rel="noopener noreferrer">the Base Adresse Nationale</a>
drop_down_list_html: A choice among those selected when the procedure was created
date_html: ISO8601 date
@ -491,7 +491,6 @@ en:
sessions:
new:
sign_in: Sign in on %{application_name}
password: Password (minimum length %{min_length} characters)
remember_me: Remember me
reset_password: Forgot password?
connection: Sign in
@ -548,6 +547,7 @@ en:
<< : *default_attributes
super_admin:
<< : *default_attributes
otp_attempt: 'OTP code (only if you have already activated 2FA)'
procedure:
zone: This procedure is run by
champs:

View file

@ -247,7 +247,7 @@ fr:
pays_html: Un <a href="https://en.wikipedia.org/wiki/ISO_3166-2" target="_blank" rel="noopener noreferrer">code pays ISO 3166-2</a>
regions_html: Un <a href="https://fr.wikipedia.org/wiki/R%C3%A9gion_fran%C3%A7aise" target="_blank" rel="noopener noreferrer">code INSEE de région</a>
departements_html: Un <a href="https://fr.wikipedia.org/wiki/Num%C3%A9rotation_des_d%C3%A9partements_fran%C3%A7ais" target="_blank">numéro de département</a>
communes_html: Un tableau contenant le code de département et <a href="https://geo.api.gouv.fr/communes" target="_blank" rel="noopener noreferrer">le code INSEE de la commune</a>
communes_html: Un tableau contenant le code postal et <a href="https://geo.api.gouv.fr/communes" target="_blank" rel="noopener noreferrer">le code INSEE de la commune</a>
address_html: Une adresse EXACTEMENT formatée telle que le label retourné par <a href="https://adresse.data.gouv.fr" target="_blank" rel="noopener noreferrer">la Base Adresse Nationale</a>
drop_down_list_html: Un choix parmi ceux sélectionnés à la création de la procédure
datetime_html: Datetime au format ISO8601
@ -494,7 +494,6 @@ fr:
sessions:
new:
sign_in: Connexion à %{application_name}
password: Mot de passe (%{min_length} caractères minimum)
remember_me: Se souvenir de moi
reset_password: Mot de passe oublié ?
connection: Se connecter
@ -552,6 +551,7 @@ fr:
<< : *default_attributes
super_admin:
<< : *default_attributes
otp_attempt: 'Code OTP (uniquement si vous avez déjà activé 2FA)'
procedure:
zone: La démarche est mise en œuvre par
champs:

View file

@ -15,4 +15,4 @@ fr:
format: "Le libellé %{message}"
closed:
format: "%{message}"
accepted: Il doit y avoir au moins un groupe dinstructeurs actif sur chaque démarche
accepted: Il est impossible de désactiver le groupe dinstructeurs par défaut.

View file

@ -18,4 +18,4 @@ fr:
connect: Connectez-vous
signin_with: "Sidentifier avec"
whats_agentconnect: 'Quʼest ce quʼAgentConnect ?'
pro_email: Email professionnel
pro_email: Adresse électronique professionnelle

View file

@ -78,7 +78,7 @@
"postcss": "^8.4.23",
"prettier": "^2.8.8",
"typescript": "^5.0.4",
"vite": "^4.3.0",
"vite": "^4.3.9",
"vite-plugin-full-reload": "^1.0.5",
"vite-plugin-ruby": "^3.2.2",
"vitest": "^0.31.0"

View file

@ -639,9 +639,9 @@ describe API::V2::GraphqlController do
let(:variables) { { input: { groupeInstructeurId: dossier.groupe_instructeur.to_typed_id, closed: true } } }
context 'with multiple groupes' do
before do
create(:groupe_instructeur, procedure: procedure)
end
let!(:defaut_groupe_instructeur) { create(:groupe_instructeur, procedure: procedure) }
before { procedure.update(defaut_groupe_instructeur_id: defaut_groupe_instructeur.id) }
it {
expect(gql_errors).to be_nil
@ -656,10 +656,11 @@ describe API::V2::GraphqlController do
let(:types_de_champ_public) { [{ type: :drop_down_list }] }
let(:groupe_instructeur) { procedure.groupe_instructeurs.first }
let(:routing_champ) { procedure.active_revision.types_de_champ.first }
let!(:defaut_groupe_instructeur) { create(:groupe_instructeur, procedure: procedure) }
before do
groupe_instructeur.update(routing_rule: ds_eq(champ_value(routing_champ.stable_id), constant(groupe_instructeur.label)))
create(:groupe_instructeur, procedure: procedure)
procedure.update(defaut_groupe_instructeur_id: defaut_groupe_instructeur.id)
Flipper.enable(:groupe_instructeur_api_hack, procedure)
end
@ -675,7 +676,7 @@ describe API::V2::GraphqlController do
context 'validation error' do
it {
expect(gql_errors).to be_nil
expect(gql_data[:groupeInstructeurModifier][:errors].first[:message]).to eq('Il doit y avoir au moins un groupe dinstructeurs actif sur chaque démarche')
expect(gql_data[:groupeInstructeurModifier][:errors].first[:message]).to eq('Il est impossible de désactiver le groupe dinstructeurs par défaut.')
}
end
end

View file

@ -559,7 +559,7 @@ describe Experts::AvisController, type: :controller do
procedure_id:,
email: avis.expert.email,
user: {
password: 'my-s3cure-p4ssword'
password: SECURE_PASSWORD
}
}
end
@ -575,7 +575,7 @@ describe Experts::AvisController, type: :controller do
it 'saves the expert new password' do
subject
expect(expert.user.reload.valid_password?('my-s3cure-p4ssword')).to be true
expect(expert.user.reload.valid_password?(SECURE_PASSWORD)).to be true
end
it { is_expected.to redirect_to expert_all_avis_path }
@ -586,7 +586,7 @@ describe Experts::AvisController, type: :controller do
it 'doesnt change the expert password' do
subject
expect(expert.user.reload.valid_password?('my-s3cure-p4ssword')).to be false
expect(expert.user.reload.valid_password?(SECURE_PASSWORD)).to be false
end
it { is_expected.to redirect_to new_user_session_url }

View file

@ -197,7 +197,7 @@ describe FranceConnect::ParticulierController, type: :controller do
let(:fci) { FranceConnectInformation.create!(user_info) }
let(:merge_token) { fci.create_merge_token! }
let(:email) { 'EXISTING_account@a.com ' }
let(:password) { 'my-s3cure-p4ssword' }
let(:password) { SECURE_PASSWORD }
let(:format) { :turbo_stream }
subject { post :merge_with_existing_account, params: { merge_token: merge_token, email: email, password: password }, format: format }

View file

@ -36,7 +36,7 @@ describe Manager::AdministrateursController, type: :controller do
describe 'POST #create' do
let(:email) { 'plop@plop.com' }
let(:password) { 'my-s3cure-p4ssword' }
let(:password) { SECURE_PASSWORD }
subject { post :create, params: { administrateur: { email: email } } }

View file

@ -78,6 +78,20 @@ describe RechercheController, type: :controller do
end
end
context 'when dossier is brouillon without groupe instructeur' do
let(:dossier2) { create(:dossier, :brouillon, procedure: procedure) }
let(:query) { dossier2.id }
before { dossier2.update(groupe_instructeur_id: nil) }
it { is_expected.to have_http_status(200) }
it 'does not return the dossier' do
subject
expect(assigns(:projected_dossiers).count).to eq(0)
expect(assigns(:dossier_not_in_instructor_group)).to eq(nil)
end
end
context 'when instructeur is attached to the procedure but is not in the instructor group of the dossier' do
let!(:gi_p1_1) { GroupeInstructeur.create(label: 'groupe 1', procedure: procedure) }
let!(:gi_p1_2) { GroupeInstructeur.create(label: 'groupe 2', procedure: procedure) }

View file

@ -1,6 +1,6 @@
describe Users::RegistrationsController, type: :controller do
let(:email) { 'test@octo.com' }
let(:password) { 'my-s3cure-p4ssword' }
let(:password) { SECURE_PASSWORD }
let(:user) { { email: email, password: password } }

View file

@ -1,6 +1,6 @@
describe Users::SessionsController, type: :controller do
let(:email) { 'unique@plop.com' }
let(:password) { 'my-s3cure-p4ssword' }
let(:password) { SECURE_PASSWORD }
let(:loged_in_with_france_connect) { User.loged_in_with_france_connects.fetch(:particulier) }
let!(:user) { create(:user, email: email, password: password, loged_in_with_france_connect: loged_in_with_france_connect) }

View file

@ -257,6 +257,28 @@ RSpec.describe Types::DossierType, type: :graphql do
}
end
describe 'dossier on sva procedure' do
let(:procedure) { create(:procedure, :sva) }
let(:query) { DOSSIER_WITH_SVA_QUERY }
let(:variables) { { number: dossier.id } }
context 'dossier en_instruction' do
let(:dossier) { create(:dossier, :en_instruction, procedure:, sva_svr_decision_on: 3.days.from_now.to_date) }
it {
expect(data[:dossier][:datePrevisionnelleDecisionSVASVR]).not_to be_nil
}
end
context 'dossier accepte' do
let(:dossier) { create(:dossier, :accepte, procedure:, sva_svr_decision_triggered_at: 24.hours.ago) }
it {
expect(data[:dossier][:dateTraitementSVASVR]).not_to be_nil
}
end
end
DOSSIER_QUERY = <<-GRAPHQL
query($number: Int!) {
dossier(number: $number) {
@ -440,6 +462,15 @@ RSpec.describe Types::DossierType, type: :graphql do
}
GRAPHQL
DOSSIER_WITH_SVA_QUERY = <<-GRAPHQL
query($number: Int!) {
dossier(number: $number) {
datePrevisionnelleDecisionSVASVR
dateTraitementSVASVR
}
}
GRAPHQL
DOSSIER_WITH_SELECTED_CHAMP_QUERY = <<-GRAPHQL
query($number: Int!, $id: ID!) {
dossier(number: $number) {

View file

@ -38,6 +38,19 @@ RSpec.describe Expert, type: :model do
end
end
context 'when an old expert access a hidden procedure' do
let(:procedure) { create(:procedure, hidden_at: 1.month.ago) }
before do
procedure.experts << old_expert
subject
end
it 'transfers the access to the new expert' do
expect(procedure.reload.experts).to match_array(new_expert)
end
end
context 'when both expert access a procedure' do
let(:procedure) { create(:procedure) }

View file

@ -99,14 +99,15 @@ describe GroupeInstructeur, type: :model do
end
describe "active group validations" do
context "there is at least one active groupe instructeur" do
let(:gi_active) { procedure.defaut_groupe_instructeur }
let(:gi_closed) { create(:groupe_instructeur, procedure:) }
before do
gi_active
gi_closed.update(closed: true)
end
context "there is one active groupe instructeur" do
it "closed is valid when there is one other active groupe" do
expect(gi_active).to be_valid
expect(gi_closed).to be_valid
@ -117,6 +118,15 @@ describe GroupeInstructeur, type: :model do
expect(gi_active).not_to be_valid
end
end
context "there are many active groupes instructeurs" do
let!(:second_gi_active) { create(:groupe_instructeur, procedure:) }
it "closed is invalid for defaut groupe instructeur even if many active groupes" do
gi_active.update(closed: true)
expect(gi_active).not_to be_valid
end
end
end
private

View file

@ -6,7 +6,7 @@ describe User, type: :model do
let(:user) do
create(:user,
email: email,
password: 'my-s3cure-p4ssword',
password: SECURE_PASSWORD,
confirmation_token: '123',
confirmed_at: nil)
end
@ -125,11 +125,11 @@ describe User, type: :model do
end
context 'with an existing user' do
before { create(:user, email: email, password: 'my-s3cure-p4ssword') }
before { create(:user, email: email, password: SECURE_PASSWORD) }
it 'keeps the previous password' do
user = subject
expect(user.valid_password?('my-s3cure-p4ssword')).to be true
expect(user.valid_password?(SECURE_PASSWORD)).to be true
expect(user.instructeur).to be_present
end
@ -189,11 +189,11 @@ describe User, type: :model do
end
context 'with an existing user' do
before { create(:user, email: email, password: 'my-s3cure-p4ssword') }
before { create(:user, email: email, password: SECURE_PASSWORD) }
it 'keeps the previous password' do
user = subject
expect(user.valid_password?('my-s3cure-p4ssword')).to be true
expect(user.valid_password?(SECURE_PASSWORD)).to be true
expect(user.expert).to be_present
end

View file

@ -18,6 +18,8 @@
# See http://rubydoc.info/gems/rspec-core/RSpec/Core/Configuration
require 'rspec/retry'
SECURE_PASSWORD = 'my-s3cure-p4ssword'
RSpec.configure do |config|
config.filter_run_excluding disable: true
config.color = true

View file

@ -34,7 +34,7 @@ module SystemHelpers
end
end
def sign_up_with(email, password = 'my-s3cure-p4ssword')
def sign_up_with(email, password = SECURE_PASSWORD)
fill_in :user_email, with: email
fill_in :user_password, with: password

View file

@ -1,4 +1,4 @@
describe 'wcag rules for usager', js: true do
describe 'wcag rules for usager', js: true, retry: 3 do
let(:procedure) { create(:procedure, :published, :with_all_champs, :with_service, :for_individual) }
let(:password) { 'a very complicated password' }
let(:litteraire_user) { create(:user, password: password) }

View file

@ -1,4 +1,4 @@
describe 'As an administrateur', js: true do
describe 'As an administrateur', js: true, retry: 3 do
let(:super_admin) { create(:super_admin) }
let(:admin_email) { 'new_admin@gouv.fr' }
let(:new_admin) { Administrateur.by_email(admin_email) }
@ -15,7 +15,7 @@ describe 'As an administrateur', js: true do
end
end
scenario 'I can register', js: true do
scenario 'I can register', js: true, retry: 3 do
expect(new_admin.reload.user.active?).to be(false)
confirmation_email = open_email(admin_email)

View file

@ -1,4 +1,4 @@
describe 'As an administrateur I can edit annotation', js: true do
describe 'As an administrateur I can edit annotation', js: true, retry: 3 do
let(:administrateur) { procedure.administrateurs.first }
let(:procedure) { create(:procedure) }

View file

@ -1,4 +1,4 @@
describe 'As an administrateur I can edit types de champ condition', js: true do
describe 'As an administrateur I can edit types de champ condition', js: true, retry: 3 do
include Logic
let(:administrateur) { procedure.administrateurs.first }

View file

@ -1,6 +1,6 @@
require 'system/administrateurs/procedure_spec_helper'
describe 'Administrateurs can manage administrateurs', js: true do
describe 'Administrateurs can manage administrateurs', js: true, retry: 3 do
include ProcedureSpecHelper
let(:administrateur) { create(:administrateur) }

View file

@ -1,6 +1,6 @@
require 'system/administrateurs/procedure_spec_helper'
describe 'Creating a new procedure', js: true do
describe 'Creating a new procedure', js: true, retry: 3 do
include ProcedureSpecHelper
let(:administrateur) { create(:administrateur) }

View file

@ -1,6 +1,6 @@
require 'system/administrateurs/procedure_spec_helper'
describe 'As an administrateur, I want to manage the procedures attestation', js: true do
describe 'As an administrateur, I want to manage the procedures attestation', js: true, retry: 3 do
include ProcedureSpecHelper
let(:administrateur) { create(:administrateur) }

View file

@ -1,6 +1,6 @@
require 'system/administrateurs/procedure_spec_helper'
describe 'As an administrateur I wanna clone a procedure', js: true do
describe 'As an administrateur I wanna clone a procedure', js: true, retry: 3 do
include ProcedureSpecHelper
let(:administrateur) { create(:administrateur) }

View file

@ -1,6 +1,6 @@
require 'system/administrateurs/procedure_spec_helper'
describe 'Creating a new procedure', js: true do
describe 'Creating a new procedure', js: true, retry: 3 do
include ProcedureSpecHelper
let(:administrateur) { create(:administrateur) }

View file

@ -1,6 +1,6 @@
require 'system/administrateurs/procedure_spec_helper'
describe 'Manage procedure instructeurs', js: true do
describe 'Manage procedure instructeurs', js: true, retry: 3 do
include ProcedureSpecHelper
let(:administrateur) { create(:administrateur) }

View file

@ -1,6 +1,6 @@
require 'system/administrateurs/procedure_spec_helper'
describe 'Publishing a procedure', js: true do
describe 'Publishing a procedure', js: true, retry: 3 do
include ProcedureSpecHelper
let(:administrateur) { create(:administrateur) }

View file

@ -1,6 +1,6 @@
require 'system/administrateurs/procedure_spec_helper'
describe 'Administrateurs can edit procedures', js: true do
describe 'Administrateurs can edit procedures', js: true, retry: 3 do
include ProcedureSpecHelper
let(:administrateur) { create(:administrateur) }

View file

@ -1,4 +1,4 @@
describe 'As an administrateur I can edit types de champ', js: true do
describe 'As an administrateur I can edit types de champ', js: true, retry: 3 do
include ActionView::RecordIdentifier
let(:administrateur) { procedure.administrateurs.first }

View file

@ -1,4 +1,4 @@
describe 'fetch API Particulier Data', js: true do
describe 'fetch API Particulier Data', js: true, retry: 3 do
let(:administrateur) { create(:administrateur) }
let(:expected_token) { 'd7e9c9f4c3ca00caadde31f50fd4521a' }

View file

@ -130,7 +130,7 @@ describe 'Inviting an expert:' do
# scenario 'I can invite other experts' do
# end
context 'with dossiers having attached files', js: true do
context 'with dossiers having attached files', js: true, retry: 3 do
let(:path) { 'spec/fixtures/files/piece_justificative_0.pdf' }
let(:commentaire) { create(:commentaire, instructeur: instructeur, dossier: dossier) }

View file

@ -47,7 +47,7 @@ describe 'France Connect Particulier Connexion' do
end
context 'and an user exists with the same email' do
let!(:user) { create(:user, email: email, password: 'my-s3cure-p4ssword') }
let!(:user) { create(:user, email: email, password: SECURE_PASSWORD) }
before do
page.find('.fr-connect').click
@ -59,7 +59,7 @@ describe 'France Connect Particulier Connexion' do
scenario 'it merges its account' do
page.find('#it-is-mine').click
fill_in 'password', with: 'my-s3cure-p4ssword'
fill_in 'password', with: SECURE_PASSWORD
click_on 'Fusionner les comptes'
expect(page).to have_content('Dossiers')
@ -73,8 +73,8 @@ describe 'France Connect Particulier Connexion' do
expect(page).to have_content('Dossiers')
end
context 'and the user wants an email that belongs to another account', js: true do
let!(:another_user) { create(:user, email: 'an_existing_email@a.com', password: 'my-s3cure-p4ssword') }
context 'and the user wants an email that belongs to another account', js: true, retry: 3 do
let!(:another_user) { create(:user, email: 'an_existing_email@a.com', password: SECURE_PASSWORD) }
scenario 'it uses another email that belongs to another account' do
page.find('#it-is-not-mine').click
@ -84,7 +84,7 @@ describe 'France Connect Particulier Connexion' do
expect(page).to have_css('#password-for-another-account', visible: true)
within '#new-account-password-confirmation' do
fill_in 'password', with: 'my-s3cure-p4ssword'
fill_in 'password', with: SECURE_PASSWORD
click_on 'Fusionner les comptes'
end

View file

@ -1,4 +1,4 @@
describe 'BatchOperation a dossier:', js: true do
describe 'BatchOperation a dossier:', js: true, retry: 3 do
include ActionView::RecordIdentifier
include ActiveJob::TestHelper

View file

@ -1,8 +1,8 @@
describe 'Inviting an expert:', js: true do
describe 'Inviting an expert:', js: true, retry: 3 do
include ActiveJob::TestHelper
include ActionView::Helpers
let(:instructeur) { create(:instructeur, password: 'my-s3cure-p4ssword') }
let(:instructeur) { create(:instructeur, password: SECURE_PASSWORD) }
let(:expert) { create(:expert, password: expert_password) }
let(:expert2) { create(:expert, password: expert_password) }
let(:expert_password) { 'mot de passe dexpert' }

View file

@ -1,4 +1,4 @@
describe 'As an instructeur', js: true do
describe 'As an instructeur', js: true, retry: 3 do
let(:administrateur) { create(:administrateur, :with_procedure) }
let(:procedure) { administrateur.procedures.first }
let(:instructeur_email) { 'new_instructeur@gouv.fr' }
@ -20,7 +20,7 @@ describe 'As an instructeur', js: true do
token_params = confirmation_email.body.match(/token=[^"]+/)
visit "users/activate?#{token_params}"
fill_in :user_password, with: 'my-s3cure-p4ssword'
fill_in :user_password, with: SECURE_PASSWORD
click_button 'Définir le mot de passe'

View file

@ -1,7 +1,7 @@
describe 'Instructing a dossier:', js: true do
describe 'Instructing a dossier:', js: true, retry: 3 do
include ActiveJob::TestHelper
let(:password) { 'my-s3cure-p4ssword' }
let(:password) { SECURE_PASSWORD }
let!(:instructeur) { create(:instructeur, password: password) }
let!(:procedure) { create(:procedure, :with_type_de_champ, :published, instructeurs: [instructeur]) }
@ -157,7 +157,7 @@ describe 'Instructing a dossier:', js: true do
expect(page).to have_text(instructeur2.email)
end
scenario 'A instructeur can send a dossier to several instructeurs', js: true do
scenario 'A instructeur can send a dossier to several instructeurs', js: true, retry: 3 do
instructeur_2 = create(:instructeur)
instructeur_3 = create(:instructeur)
procedure.defaut_groupe_instructeur.instructeurs << [instructeur_2, instructeur_3]
@ -195,7 +195,7 @@ describe 'Instructing a dossier:', js: true do
expect(Archive.first.month).not_to be_nil
end
end
context 'with dossiers having attached files', js: true do
context 'with dossiers having attached files', js: true, retry: 3 do
let(:procedure) { create(:procedure, :published, :with_piece_justificative, instructeurs: [instructeur]) }
let(:dossier) { create(:dossier, :en_construction, procedure: procedure) }
let(:champ) { dossier.champs_public.first }

View file

@ -40,7 +40,7 @@ describe "procedure filters" do
end
end
scenario "should add be able to add created_at column", js: true do
scenario "should add be able to add created_at column", js: true, retry: 3 do
add_column("Créé le")
within ".dossiers-table" do
expect(page).to have_link("Créé le")
@ -48,7 +48,7 @@ describe "procedure filters" do
end
end
scenario "should add be able to add and remove custom type_de_champ column", js: true do
scenario "should add be able to add and remove custom type_de_champ column", js: true, retry: 3 do
add_column(type_de_champ.libelle)
within ".dossiers-table" do
expect(page).to have_link(type_de_champ.libelle)
@ -62,7 +62,7 @@ describe "procedure filters" do
end
end
scenario "should be able to add and remove filter", js: true do
scenario "should be able to add and remove filter", js: true, retry: 3 do
add_filter(type_de_champ.libelle, champ.value)
expect(page).to have_content("#{type_de_champ.libelle} : #{champ.value}")
@ -86,7 +86,7 @@ describe "procedure filters" do
end
end
scenario "should be able to user custom fiters", js: true do
scenario "should be able to user custom fiters", js: true, retry: 3 do
# use date filter
click_on 'Sélectionner un filtre'
select "En construction le", from: "Colonne"
@ -104,7 +104,7 @@ describe "procedure filters" do
end
describe 'with a vcr cached cassette' do
scenario "should be able to find by departements with custom enum lookup", js: true do
scenario "should be able to find by departements with custom enum lookup", js: true, retry: 3 do
departement_champ = new_unfollow_dossier.champs.find(&:departement?)
departement_champ.update!(value: 'Oise', external_id: '60')
departement_champ.reload
@ -119,7 +119,7 @@ describe "procedure filters" do
expect(page).to have_link(new_unfollow_dossier.id.to_s)
end
scenario "should be able to find by region with custom enum lookup", js: true do
scenario "should be able to find by region with custom enum lookup", js: true, retry: 3 do
region_champ = new_unfollow_dossier.champs.find(&:region?)
region_champ.update!(value: 'Bretagne', external_id: '53')
region_champ.reload
@ -134,7 +134,7 @@ describe "procedure filters" do
end
end
scenario "should be able to add and remove two filters for the same field", js: true do
scenario "should be able to add and remove two filters for the same field", js: true, retry: 3 do
add_filter(type_de_champ.libelle, champ.value)
add_filter(type_de_champ.libelle, champ_2.value)
add_enum_filter('Groupe instructeur', procedure.groupe_instructeurs.first.label)

View file

@ -1,4 +1,4 @@
describe "procedure sort", js: true do
describe "procedure sort", js: true, retry: 3 do
let(:instructeur) { create(:instructeur) }
let(:procedure) { create(:procedure, :published, :with_type_de_champ, instructeurs: [instructeur]) }
let!(:new_unfollow_dossier) { create(:dossier, procedure: procedure, state: Dossier.states.fetch(:en_instruction)) }

View file

@ -1,4 +1,4 @@
describe 'As an integrator:', js: true do
describe 'As an integrator:', js: true, retry: 3 do
let(:procedure) { create(:procedure, :published, opendata: true) }
let!(:type_de_champ) { create(:type_de_champ_text, procedure: procedure) }

View file

@ -1,4 +1,4 @@
describe 'The routing with rules', js: true do
describe 'The routing with rules', js: true, retry: 3 do
let(:password) { 'a very complicated password' }
let(:procedure) do

View file

@ -1,6 +1,6 @@
describe 'Signin in:' do
let!(:user) { create(:user, password: password) }
let(:password) { 'my-s3cure-p4ssword' }
let(:password) { SECURE_PASSWORD }
scenario 'an existing user can sign-in' do
visit root_path

View file

@ -1,5 +1,5 @@
describe 'The user' do
let(:password) { 'my-s3cure-p4ssword' }
let(:password) { SECURE_PASSWORD }
let!(:user) { create(:user, password: password) }
let!(:procedure) { create(:procedure, :published, :for_individual, :with_all_champs_mandatory) }
@ -104,7 +104,7 @@ describe 'The user' do
expect(page).to have_text('Analyse antivirus en cours')
end
scenario 'fill nothing and every error anchor links points to an existing element', js: true do
scenario 'fill nothing and every error anchor links points to an existing element', js: true, retry: 3 do
log_in(user, procedure)
fill_individual
click_on 'Déposer le dossier'
@ -120,7 +120,7 @@ describe 'The user' do
create(:procedure, :published, :for_individual, types_de_champ_public: [{ type: :repetition, mandatory: true, children: [{ libelle: 'sub type de champ' }] }])
end
scenario 'fill a dossier with repetition', js: true do
scenario 'fill a dossier with repetition', js: true, retry: 3 do
log_in(user, procedure_with_repetition)
fill_individual
@ -146,7 +146,7 @@ describe 'The user' do
let(:simple_procedure) { create(:procedure, :published, :for_individual, types_de_champ_public: [{ mandatory: true, libelle: 'texte obligatoire' }, { mandatory: false, libelle: 'texte optionnel' }]) }
scenario 'save an incomplete dossier as draft but cannot not submit it', js: true do
scenario 'save an incomplete dossier as draft but cannot not submit it', js: true, retry: 3 do
log_in(user, simple_procedure)
fill_individual
@ -163,7 +163,6 @@ describe 'The user' do
# Check a dossier can be submitted when all mandatory fields are filled
fill_in('texte obligatoire', with: 'super texte')
wait_for_autosave
click_on 'Déposer le dossier'
wait_until { user_dossier.reload.en_construction? }
@ -171,7 +170,7 @@ describe 'The user' do
expect(page).to have_current_path(merci_dossier_path(user_dossier))
end
scenario 'extends dossier experation date more than one time, ', js: true do
scenario 'extends dossier experation date more than one time, ', js: true, retry: 3 do
simple_procedure.update(procedure_expires_when_termine_enabled: true)
user_old_dossier = create(:dossier,
procedure: simple_procedure,
@ -196,7 +195,7 @@ describe 'The user' do
let(:procedure_with_pjs) { create(:procedure, :published, :for_individual, types_de_champ_public: [{ type: :piece_justificative, mandatory: true, libelle: 'Pièce justificative 1' }, { type: :piece_justificative, mandatory: true, libelle: 'Pièce justificative 2' }]) }
let(:old_procedure_with_disabled_pj_validation) { create(:procedure, :published, :for_individual, types_de_champ_public: [{ type: :piece_justificative, mandatory: true, libelle: 'Pièce justificative 1', skip_pj_validation: true }]) }
scenario 'add an attachment', js: true do
scenario 'add an attachment', js: true, retry: 3 do
log_in(user, procedure_with_pjs)
fill_individual
@ -220,7 +219,7 @@ describe 'The user' do
expect(page).to have_text('RIB.pdf')
end
scenario 'add an invalid attachment on an old procedure where pj validation is disabled', js: true do
scenario 'add an invalid attachment on an old procedure where pj validation is disabled', js: true, retry: 3 do
log_in(user, old_procedure_with_disabled_pj_validation)
fill_individual
@ -230,7 +229,7 @@ describe 'The user' do
expect(page).to have_text('Analyse antivirus en cours', count: 1, wait: 5)
end
scenario 'retry on transcient upload error', js: true do
scenario 'retry on transcient upload error', js: true, retry: 3 do
log_in(user, procedure_with_pjs)
fill_individual
@ -259,7 +258,7 @@ describe 'The user' do
expect(page).to have_text('file.pdf')
end
scenario "upload multiple pieces justificatives on same champ", js: true do
scenario "upload multiple pieces justificatives on same champ", js: true, retry: 3 do
log_in(user, procedure_with_pjs)
fill_individual
@ -324,7 +323,7 @@ describe 'The user' do
])
end
scenario 'submit a dossier with an hidden mandatory champ within a repetition', js: true do
scenario 'submit a dossier with an hidden mandatory champ within a repetition', js: true, retry: 3 do
log_in(user, procedure)
fill_individual
@ -354,7 +353,7 @@ describe 'The user' do
])
end
scenario 'fill a dossier', js: true do
scenario 'fill a dossier', js: true, retry: 3 do
log_in(user, procedure)
fill_individual
@ -386,7 +385,7 @@ describe 'The user' do
])
end
scenario 'submit a dossier with an hidden mandatory champ ', js: true do
scenario 'submit a dossier with an hidden mandatory champ ', js: true, retry: 3 do
log_in(user, procedure)
fill_individual
@ -395,7 +394,7 @@ describe 'The user' do
expect(page).to have_current_path(merci_dossier_path(user_dossier))
end
scenario 'cannot submit a reveal dossier with a revealed mandatory champ ', js: true do
scenario 'cannot submit a reveal dossier with a revealed mandatory champ ', js: true, retry: 3 do
log_in(user, procedure)
fill_individual
@ -427,7 +426,7 @@ describe 'The user' do
])
end
scenario 'fill a dossier', js: true do
scenario 'fill a dossier', js: true, retry: 3 do
log_in(user, procedure)
fill_individual
@ -476,7 +475,7 @@ describe 'The user' do
end
context 'draft autosave' do
scenario 'autosave a draft', js: true do
scenario 'autosave a draft', js: true, retry: 3 do
log_in(user, simple_procedure)
fill_individual
@ -491,7 +490,7 @@ describe 'The user' do
expect(page).to have_field('texte obligatoire', with: 'a valid user input')
end
scenario 'retry on autosave error', :capybara_ignore_server_errors, js: true do
scenario 'retry on autosave error', :capybara_ignore_server_errors, js: true, retry: 3 do
log_in(user, simple_procedure)
fill_individual
@ -511,7 +510,7 @@ describe 'The user' do
expect(page).to have_field('texte obligatoire', with: 'a valid user input')
end
scenario 'autosave redirects to sign-in after being disconnected', js: true do
scenario 'autosave redirects to sign-in after being disconnected', js: true, retry: 3 do
log_in(user, simple_procedure)
fill_individual

View file

@ -48,7 +48,7 @@ describe 'Dossier details:' do
expect(page).to have_current_path(dossier_path(dossier))
end
context 'with js', js: true do
context 'with js', js: true, retry: 3 do
it_behaves_like 'the user can edit the submitted demande'
it_behaves_like 'the user can send messages to the instructeur'
end

View file

@ -1,5 +1,5 @@
describe 'Prefilling a dossier (with a GET request):', js: true do
let(:password) { 'my-s3cure-p4ssword' }
describe 'Prefilling a dossier (with a GET request):', js: true, retry: 3 do
let(:password) { SECURE_PASSWORD }
let(:procedure) { create(:procedure, :published, opendata: true) }
let(:dossier) { procedure.dossiers.last }

View file

@ -1,5 +1,5 @@
describe 'Prefilling a dossier (with a POST request):', js: true do
let(:password) { 'my-s3cure-p4ssword' }
describe 'Prefilling a dossier (with a POST request):', js: true, retry: 3 do
let(:password) { SECURE_PASSWORD }
let(:procedure) { create(:procedure, :published) }
let(:dossier) { procedure.dossiers.last }

View file

@ -1,5 +1,5 @@
describe 'dropdown list with other option activated', js: true do
let(:password) { 'my-s3cure-p4ssword' }
describe 'dropdown list with other option activated', js: true, retry: 3 do
let(:password) { SECURE_PASSWORD }
let!(:user) { create(:user, password: password) }
let(:procedure) { create(:procedure, :published, :for_individual, types_de_champ_public: [{ type: :drop_down_list, libelle: 'simple dropdown other', options: options + [:other] }]) }
@ -20,14 +20,14 @@ describe 'dropdown list with other option activated', js: true do
]
end
scenario 'Select other option and the other input hidden must appear', js: true do
scenario 'Select other option and the other input hidden must appear', js: true, retry: 3 do
fill_individual
find('.radios').find('label:last-child').find('input').select_option
expect(page).to have_selector('.drop_down_other', visible: true)
end
scenario "Getting back from other save the new option", js: true do
scenario "Getting back from other save the new option", js: true, retry: 3 do
fill_individual
choose "Autre"

View file

@ -11,7 +11,7 @@ describe "Dossier en_construction" do
dossier.find_editing_fork(dossier.user).champs_public.find { _1.type_de_champ_id == tdc.id }
}
scenario 'delete a non mandatory piece justificative', js: true do
scenario 'delete a non mandatory piece justificative', js: true, retry: 3 do
visit_dossier(dossier)
expect(page).not_to have_button("Remplacer")
@ -26,7 +26,7 @@ describe "Dossier en_construction" do
tdc.update_attribute(:mandatory, true)
end
scenario 'remplace a mandatory piece justificative', js: true do
scenario 'remplace a mandatory piece justificative', js: true, retry: 3 do
visit_dossier(dossier)
click_on "Supprimer le fichier toto.txt"
@ -50,7 +50,7 @@ describe "Dossier en_construction" do
tdc.update_attribute(:mandatory, true)
end
scenario 'remplace a mandatory titre identite', js: true do
scenario 'remplace a mandatory titre identite', js: true, retry: 3 do
visit_dossier(dossier)
click_on "Supprimer le fichier toto.png"

View file

@ -9,7 +9,7 @@ describe 'Invitations' do
context 'when the dossier is a brouillon' do
let!(:dossier) { create(:dossier, :with_individual, state: Dossier.states.fetch(:brouillon), user: owner, procedure: procedure) }
scenario 'on the form, the owner of a dossier can invite another user to collaborate on the dossier', js: true do
scenario 'on the form, the owner of a dossier can invite another user to collaborate on the dossier', js: true, retry: 3 do
log_in(owner)
navigate_to_brouillon(dossier)
fill_in 'Texte obligatoire', with: 'Some edited value'
@ -94,7 +94,7 @@ describe 'Invitations' do
end
end
scenario 'an invited user can see and edit the draft', js: true do
scenario 'an invited user can see and edit the draft', js: true, retry: 3 do
navigate_to_invited_dossier(invite)
expect(page).to have_current_path(brouillon_dossier_path(dossier))
@ -117,7 +117,7 @@ describe 'Invitations' do
context 'when the dossier is en_construction' do
let!(:dossier) { create(:dossier, :with_individual, :en_construction, user: owner, procedure: procedure) }
scenario 'on dossier details, the owner of a dossier can invite another user to collaborate on the dossier', js: true do
scenario 'on dossier details, the owner of a dossier can invite another user to collaborate on the dossier', js: true, retry: 3 do
log_in(owner)
navigate_to_dossier(dossier)
@ -128,7 +128,7 @@ describe 'Invitations' do
expect(page).to have_text("user_invite@exemple.fr")
end
context 'as an invited user', js: true do
context 'as an invited user', js: true, retry: 3 do
before do
navigate_to_invited_dossier(invite)
expect(page).to have_current_path(dossier_path(invite.dossier))

View file

@ -1,5 +1,5 @@
describe 'linked dropdown lists' do
let(:password) { 'my-s3cure-p4ssword' }
let(:password) { SECURE_PASSWORD }
let!(:user) { create(:user, password: password) }
let(:options) do
@ -19,7 +19,7 @@ describe 'linked dropdown lists' do
let(:user_dossier) { user.dossiers.first }
context 'not mandatory' do
let(:mandatory) { false }
scenario 'change primary value, secondary options are updated', js: true do
scenario 'change primary value, secondary options are updated', js: true, retry: 3 do
log_in(user.email, password, procedure)
fill_individual
@ -42,7 +42,7 @@ describe 'linked dropdown lists' do
context 'mandatory' do
let(:mandatory) { true }
scenario 'change primary value, secondary options are updated', js: true do
scenario 'change primary value, secondary options are updated', js: true, retry: 3 do
log_in(user.email, password, procedure)
fill_individual

View file

@ -1,4 +1,4 @@
describe 'user access to the list of their dossiers', js: true do
describe 'user access to the list of their dossiers', js: true, retry: 3 do
let(:user) { create(:user) }
let!(:dossier_brouillon) { create(:dossier, user: user) }
let!(:dossier_en_construction) { create(:dossier, :with_populated_champs, :en_construction, user: user) }
@ -155,7 +155,7 @@ describe 'user access to the list of their dossiers', js: true do
expect(page).not_to have_link('Supprimer le dossier', href: dossier_path(dossier_en_instruction))
end
context 'when user clicks on delete button', js: true do
context 'when user clicks on delete button', js: true, retry: 3 do
scenario 'the dossier is deleted' do
expect(page).to have_content(dossier_en_construction.procedure.libelle)
within(:css, ".card", match: :first) do
@ -177,7 +177,7 @@ describe 'user access to the list of their dossiers', js: true do
expect(page).to have_link(nil, href: clone_dossier_path(dossier_en_instruction))
end
context 'when user clicks on clone button', js: true do
context 'when user clicks on clone button', js: true, retry: 3 do
scenario 'the dossier is cloned' do
within(:css, ".card", match: :first) do
click_on 'Autres actions'

View file

@ -1,4 +1,4 @@
describe 'Managing password:', js: true do
describe 'Managing password:', js: true, retry: 3 do
context 'for simple users' do
let(:user) { create(:user) }
let(:new_password) { 'a simple password' }
@ -11,7 +11,7 @@ describe 'Managing password:', js: true do
click_on 'Mot de passe oublié ?'
expect(page).to have_current_path(new_user_password_path)
fill_in 'Email', with: user.email
fill_in 'Adresse électronique', with: user.email
perform_enqueued_jobs do
click_on 'Demander un nouveau mot de passe'
end
@ -34,7 +34,7 @@ describe 'Managing password:', js: true do
let(:weak_password) { '12345678' }
let(:strong_password) { 'a new, long, and complicated password!' }
scenario 'an admin can reset their password', js: true do
scenario 'an admin can reset their password', js: true, retry: 3 do
visit root_path
within('.fr-header .fr-container .fr-header__tools .fr-btns-group') do
click_on 'Se connecter'
@ -42,7 +42,7 @@ describe 'Managing password:', js: true do
click_on 'Mot de passe oublié ?'
expect(page).to have_current_path(new_user_password_path)
fill_in 'Email', with: user.email
fill_in 'Adresse électronique', with: user.email
perform_enqueued_jobs do
click_on 'Demander un nouveau mot de passe'
end
@ -73,12 +73,12 @@ describe 'Managing password:', js: true do
let(:weak_password) { '12345678' }
let(:strong_password) { 'a new, long, and complicated password!' }
scenario 'a super-admin can reset their password', js: true do
scenario 'a super-admin can reset their password', js: true, retry: 3 do
visit manager_root_path
click_on 'Mot de passe oublié'
expect(page).to have_current_path(new_super_admin_password_path)
fill_in 'Email', with: super_admin.email
fill_in 'Adresse électronique', with: super_admin.email
perform_enqueued_jobs do
click_on 'Demander un nouveau mot de passe'
end

View file

@ -1,6 +1,6 @@
describe 'Signing up:' do
let(:user_email) { generate :user_email }
let(:user_password) { 'my-s3cure-p4ssword' }
let(:user_password) { SECURE_PASSWORD }
let(:procedure) { create :simple_procedure, :with_service }
scenario 'a new user can sign-up from scratch' do
@ -25,21 +25,21 @@ describe 'Signing up:' do
fill_in 'Mot de passe', with: '12345'
end
scenario 'they can accept the suggestion', js: true do
scenario 'they can accept the suggestion', js: true, retry: 3 do
expect(page).to have_selector('.suspect-email', visible: true)
click_on 'Oui'
expect(page).to have_field("Adresse électronique", :with => 'bidou@yahoo.fr')
expect(page).to have_selector('.suspect-email', visible: false)
end
scenario 'they can discard the suggestion', js: true do
scenario 'they can discard the suggestion', js: true, retry: 3 do
expect(page).to have_selector('.suspect-email', visible: true)
click_on 'Non'
expect(page).to have_field("Adresse électronique", :with => 'bidou@yahoo.rf')
expect(page).to have_selector('.suspect-email', visible: false)
end
scenario 'they can fix the typo themselves', js: true do
scenario 'they can fix the typo themselves', js: true, retry: 3 do
expect(page).to have_selector('.suspect-email', visible: true)
fill_in 'Adresse électronique', with: 'bidou@yahoo.fr'
blur

181
yarn.lock
View file

@ -1190,221 +1190,111 @@
resolved "https://registry.yarnpkg.com/@emotion/memoize/-/memoize-0.7.4.tgz#19bf0f5af19149111c40d98bb0cf82119f5d9eeb"
integrity sha512-Ja/Vfqe3HpuzRsG1oBtWTHk2PGZ7GR+2Vz5iYGelAw8dx32K0y7PjVuxK6z1nMpZOqAFsRUPCkK1YjJ56qJlgw==
"@esbuild/android-arm64@0.16.14":
version "0.16.14"
resolved "https://registry.yarnpkg.com/@esbuild/android-arm64/-/android-arm64-0.16.14.tgz#f02c9f0d43086ddf6ed2795b881ddf7990f74456"
integrity sha512-hTqB6Iq13pW4xaydeqQrs8vPntUnMjbkq+PgGiBMi69eYk74naG2ftHWqKnxn874kNrt5Or3rQ0PJutx2doJuQ==
"@esbuild/android-arm64@0.17.14":
version "0.17.14"
resolved "https://registry.yarnpkg.com/@esbuild/android-arm64/-/android-arm64-0.17.14.tgz#4624cea3c8941c91f9e9c1228f550d23f1cef037"
integrity sha512-eLOpPO1RvtsP71afiFTvS7tVFShJBCT0txiv/xjFBo5a7R7Gjw7X0IgIaFoLKhqXYAXhahoXm7qAmRXhY4guJg==
"@esbuild/android-arm@0.16.14":
version "0.16.14"
resolved "https://registry.yarnpkg.com/@esbuild/android-arm/-/android-arm-0.16.14.tgz#24e4faf569d0d6bbf9ed46f6ed395d68eb7f04fc"
integrity sha512-u0rITLxFIeYAvtJXBQNhNuV4YZe+MD1YvIWT7Nicj8hZAtRVZk2PgNH6KclcKDVHz1ChLKXRfX7d7tkbQBUfrg==
"@esbuild/android-arm@0.17.14":
version "0.17.14"
resolved "https://registry.yarnpkg.com/@esbuild/android-arm/-/android-arm-0.17.14.tgz#74fae60fcab34c3f0e15cb56473a6091ba2b53a6"
integrity sha512-0CnlwnjDU8cks0yJLXfkaU/uoLyRf9VZJs4p1PskBr2AlAHeEsFEwJEo0of/Z3g+ilw5mpyDwThlxzNEIxOE4g==
"@esbuild/android-x64@0.16.14":
version "0.16.14"
resolved "https://registry.yarnpkg.com/@esbuild/android-x64/-/android-x64-0.16.14.tgz#1173e706cf57c0d4dbf069d18e5d50ae6a5b0871"
integrity sha512-jir51K4J0K5Rt0KOcippjSNdOl7akKDVz5I6yrqdk4/m9y+rldGptQUF7qU4YpX8U61LtR+w2Tu2Ph+K/UaJOw==
"@esbuild/android-x64@0.17.14":
version "0.17.14"
resolved "https://registry.yarnpkg.com/@esbuild/android-x64/-/android-x64-0.17.14.tgz#f002fbc08d5e939d8314bd23bcfb1e95d029491f"
integrity sha512-nrfQYWBfLGfSGLvRVlt6xi63B5IbfHm3tZCdu/82zuFPQ7zez4XjmRtF/wIRYbJQ/DsZrxJdEvYFE67avYXyng==
"@esbuild/darwin-arm64@0.16.14":
version "0.16.14"
resolved "https://registry.yarnpkg.com/@esbuild/darwin-arm64/-/darwin-arm64-0.16.14.tgz#67f05693c5b097bcb4ff656ba5839459f30f79c2"
integrity sha512-vrlaP81IuwPaw1fyX8fHCmivP3Gr73ojVEZy+oWJLAiZVcG8o8Phwun/XDnYIFUHxIoUnMFEpg9o38MIvlw8zw==
"@esbuild/darwin-arm64@0.17.14":
version "0.17.14"
resolved "https://registry.yarnpkg.com/@esbuild/darwin-arm64/-/darwin-arm64-0.17.14.tgz#b8dcd79a1dd19564950b4ca51d62999011e2e168"
integrity sha512-eoSjEuDsU1ROwgBH/c+fZzuSyJUVXQTOIN9xuLs9dE/9HbV/A5IqdXHU1p2OfIMwBwOYJ9SFVGGldxeRCUJFyw==
"@esbuild/darwin-x64@0.16.14":
version "0.16.14"
resolved "https://registry.yarnpkg.com/@esbuild/darwin-x64/-/darwin-x64-0.16.14.tgz#519c9d127c5363d4a1e73b9d954460f798b41d2a"
integrity sha512-KV1E01eC2hGYA2qzFDRCK4wdZCRUvMwCNcobgpiiOzp5QXpJBqFPdxI69j8vvzuU7oxFXDgANwEkXvpeQqyOyg==
"@esbuild/darwin-x64@0.17.14":
version "0.17.14"
resolved "https://registry.yarnpkg.com/@esbuild/darwin-x64/-/darwin-x64-0.17.14.tgz#4b49f195d9473625efc3c773fc757018f2c0d979"
integrity sha512-zN0U8RWfrDttdFNkHqFYZtOH8hdi22z0pFm0aIJPsNC4QQZv7je8DWCX5iA4Zx6tRhS0CCc0XC2m7wKsbWEo5g==
"@esbuild/freebsd-arm64@0.16.14":
version "0.16.14"
resolved "https://registry.yarnpkg.com/@esbuild/freebsd-arm64/-/freebsd-arm64-0.16.14.tgz#2e3f5de2951a8ec732a3e4ec4f5d47a7c9626001"
integrity sha512-xRM1RQsazSvL42BNa5XC7ytD4ZDp0ZyJcH7aB0SlYUcHexJUKiDNKR7dlRVlpt6W0DvoRPU2nWK/9/QWS4u2fw==
"@esbuild/freebsd-arm64@0.17.14":
version "0.17.14"
resolved "https://registry.yarnpkg.com/@esbuild/freebsd-arm64/-/freebsd-arm64-0.17.14.tgz#480923fd38f644c6342c55e916cc7c231a85eeb7"
integrity sha512-z0VcD4ibeZWVQCW1O7szaLxGsx54gcCnajEJMdYoYjLiq4g1jrP2lMq6pk71dbS5+7op/L2Aod+erw+EUr28/A==
"@esbuild/freebsd-x64@0.16.14":
version "0.16.14"
resolved "https://registry.yarnpkg.com/@esbuild/freebsd-x64/-/freebsd-x64-0.16.14.tgz#d3cf84ff28357ac8d0123309bac37fcfcdd98f53"
integrity sha512-7ALTAn6YRRf1O6fw9jmn0rWmOx3XfwDo7njGtjy1LXhDGUjTY/vohEPM3ii5MQ411vJv1r498EEx2aBQTJcrEw==
"@esbuild/freebsd-x64@0.17.14":
version "0.17.14"
resolved "https://registry.yarnpkg.com/@esbuild/freebsd-x64/-/freebsd-x64-0.17.14.tgz#a6b6b01954ad8562461cb8a5e40e8a860af69cbe"
integrity sha512-hd9mPcxfTgJlolrPlcXkQk9BMwNBvNBsVaUe5eNUqXut6weDQH8whcNaKNF2RO8NbpT6GY8rHOK2A9y++s+ehw==
"@esbuild/linux-arm64@0.16.14":
version "0.16.14"
resolved "https://registry.yarnpkg.com/@esbuild/linux-arm64/-/linux-arm64-0.16.14.tgz#f44b0e3d5d470cd763a9bc4855a12b8cb73d6c12"
integrity sha512-TLh2OcbBUQcMYRH4GbiDkDZfZ4t1A3GgmeXY27dHSI6xrU7IkO00MGBiJySmEV6sH3Wa6pAN6UtaVL0DwkGW4Q==
"@esbuild/linux-arm64@0.17.14":
version "0.17.14"
resolved "https://registry.yarnpkg.com/@esbuild/linux-arm64/-/linux-arm64-0.17.14.tgz#1fe2f39f78183b59f75a4ad9c48d079916d92418"
integrity sha512-FhAMNYOq3Iblcj9i+K0l1Fp/MHt+zBeRu/Qkf0LtrcFu3T45jcwB6A1iMsemQ42vR3GBhjNZJZTaCe3VFPbn9g==
"@esbuild/linux-arm@0.16.14":
version "0.16.14"
resolved "https://registry.yarnpkg.com/@esbuild/linux-arm/-/linux-arm-0.16.14.tgz#b239eb7e6cb7df9c34c6b08f4adf113da47e0e09"
integrity sha512-X6xULug66ulrr4IzrW7qq+eq9n4MtEyagdWvj4o4cmWr+JXOT47atjpDF9j5M2zHY0UQBmqnHhwl+tXpkpIb2w==
"@esbuild/linux-arm@0.17.14":
version "0.17.14"
resolved "https://registry.yarnpkg.com/@esbuild/linux-arm/-/linux-arm-0.17.14.tgz#18d594a49b64e4a3a05022c005cb384a58056a2a"
integrity sha512-BNTl+wSJ1omsH8s3TkQmIIIQHwvwJrU9u1ggb9XU2KTVM4TmthRIVyxSp2qxROJHhZuW/r8fht46/QE8hU8Qvg==
"@esbuild/linux-ia32@0.16.14":
version "0.16.14"
resolved "https://registry.yarnpkg.com/@esbuild/linux-ia32/-/linux-ia32-0.16.14.tgz#f5f7886027cd61bed59178e981a0ef47ca5b72ef"
integrity sha512-oBZkcZ56UZDFCAfE3Fd/Jgy10EoS7Td77NzNGenM+HSY8BkdQAcI9VF9qgwdOLZ+tuftWD7UqZ26SAhtvA3XhA==
"@esbuild/linux-ia32@0.17.14":
version "0.17.14"
resolved "https://registry.yarnpkg.com/@esbuild/linux-ia32/-/linux-ia32-0.17.14.tgz#f7f0182a9cfc0159e0922ed66c805c9c6ef1b654"
integrity sha512-91OK/lQ5y2v7AsmnFT+0EyxdPTNhov3y2CWMdizyMfxSxRqHazXdzgBKtlmkU2KYIc+9ZK3Vwp2KyXogEATYxQ==
"@esbuild/linux-loong64@0.16.14":
version "0.16.14"
resolved "https://registry.yarnpkg.com/@esbuild/linux-loong64/-/linux-loong64-0.16.14.tgz#d2329371726f9778156c89ea0bed26fc1bc3cd7e"
integrity sha512-udz/aEHTcuHP+xdWOJmZ5C9RQXHfZd/EhCnTi1Hfay37zH3lBxn/fNs85LA9HlsniFw2zccgcbrrTMKk7Cn1Qg==
"@esbuild/linux-loong64@0.17.14":
version "0.17.14"
resolved "https://registry.yarnpkg.com/@esbuild/linux-loong64/-/linux-loong64-0.17.14.tgz#5f5305fdffe2d71dd9a97aa77d0c99c99409066f"
integrity sha512-vp15H+5NR6hubNgMluqqKza85HcGJgq7t6rMH7O3Y6ApiOWPkvW2AJfNojUQimfTp6OUrACUXfR4hmpcENXoMQ==
"@esbuild/linux-mips64el@0.16.14":
version "0.16.14"
resolved "https://registry.yarnpkg.com/@esbuild/linux-mips64el/-/linux-mips64el-0.16.14.tgz#8af86bdc6ee937c8a2803b3c197b28824f48df8e"
integrity sha512-kJ2iEnikUOdC1SiTGbH0fJUgpZwa0ITDTvj9EHf9lm3I0hZ4Yugsb3M6XSl696jVxrEocLe519/8CbSpQWFSrg==
"@esbuild/linux-mips64el@0.17.14":
version "0.17.14"
resolved "https://registry.yarnpkg.com/@esbuild/linux-mips64el/-/linux-mips64el-0.17.14.tgz#a602e85c51b2f71d2aedfe7f4143b2f92f97f3f5"
integrity sha512-90TOdFV7N+fgi6c2+GO9ochEkmm9kBAKnuD5e08GQMgMINOdOFHuYLPQ91RYVrnWwQ5683sJKuLi9l4SsbJ7Hg==
"@esbuild/linux-ppc64@0.16.14":
version "0.16.14"
resolved "https://registry.yarnpkg.com/@esbuild/linux-ppc64/-/linux-ppc64-0.16.14.tgz#3fa3f8c6c9db3127f2ec5b2eba1cec67ff9a9b8e"
integrity sha512-kclKxvZvX5YhykwlJ/K9ljiY4THe5vXubXpWmr7q3Zu3WxKnUe1VOZmhkEZlqtnJx31GHPEV4SIG95IqTdfgfg==
"@esbuild/linux-ppc64@0.17.14":
version "0.17.14"
resolved "https://registry.yarnpkg.com/@esbuild/linux-ppc64/-/linux-ppc64-0.17.14.tgz#32d918d782105cbd9345dbfba14ee018b9c7afdf"
integrity sha512-NnBGeoqKkTugpBOBZZoktQQ1Yqb7aHKmHxsw43NddPB2YWLAlpb7THZIzsRsTr0Xw3nqiPxbA1H31ZMOG+VVPQ==
"@esbuild/linux-riscv64@0.16.14":
version "0.16.14"
resolved "https://registry.yarnpkg.com/@esbuild/linux-riscv64/-/linux-riscv64-0.16.14.tgz#1bd1b631de2533106a08876295bad3a19b20f629"
integrity sha512-fdwP9Dc+Kx/cZwp9T9kNqjAE/PQjfrxbio4rZ3XnC3cVvZBjuxpkiyu/tuCwt6SbAK5th6AYNjFdEV9kGC020A==
"@esbuild/linux-riscv64@0.17.14":
version "0.17.14"
resolved "https://registry.yarnpkg.com/@esbuild/linux-riscv64/-/linux-riscv64-0.17.14.tgz#38612e7b6c037dff7022c33f49ca17f85c5dec58"
integrity sha512-0qdlKScLXA8MGVy21JUKvMzCYWovctuP8KKqhtE5A6IVPq4onxXhSuhwDd2g5sRCzNDlDjitc5sX31BzDoL5Fw==
"@esbuild/linux-s390x@0.16.14":
version "0.16.14"
resolved "https://registry.yarnpkg.com/@esbuild/linux-s390x/-/linux-s390x-0.16.14.tgz#c87440b6522b9a36a9cafd05b0f1ca3c5bad4cca"
integrity sha512-++fw3P4fQk9nqvdzbANRqimKspL8pDCnSpXomyhV7V/ISha/BZIYvZwLBWVKp9CVWKwWPJ4ktsezuLIvlJRHqA==
"@esbuild/linux-s390x@0.17.14":
version "0.17.14"
resolved "https://registry.yarnpkg.com/@esbuild/linux-s390x/-/linux-s390x-0.17.14.tgz#4397dff354f899e72fd035d72af59a700c465ccb"
integrity sha512-Hdm2Jo1yaaOro4v3+6/zJk6ygCqIZuSDJHdHaf8nVH/tfOuoEX5Riv03Ka15LmQBYJObUTNS1UdyoMk0WUn9Ww==
"@esbuild/linux-x64@0.16.14":
version "0.16.14"
resolved "https://registry.yarnpkg.com/@esbuild/linux-x64/-/linux-x64-0.16.14.tgz#49cd974dad6042ac0141ba332df6307c44e77fed"
integrity sha512-TomtswAuzBf2NnddlrS4W01Tv85RM9YtATB3OugY6On0PLM4Ksz5qvQKVAjtzPKoLgL1FiZtfc8mkZc4IgoMEA==
"@esbuild/linux-x64@0.17.14":
version "0.17.14"
resolved "https://registry.yarnpkg.com/@esbuild/linux-x64/-/linux-x64-0.17.14.tgz#6c5cb99891b6c3e0c08369da3ef465e8038ad9c2"
integrity sha512-8KHF17OstlK4DuzeF/KmSgzrTWQrkWj5boluiiq7kvJCiQVzUrmSkaBvcLB2UgHpKENO2i6BthPkmUhNDaJsVw==
"@esbuild/netbsd-x64@0.16.14":
version "0.16.14"
resolved "https://registry.yarnpkg.com/@esbuild/netbsd-x64/-/netbsd-x64-0.16.14.tgz#53dcfb5131376feff0911adff7f01b4821706cf6"
integrity sha512-U06pfx8P5CqyoPNfqIJmnf+5/r4mJ1S62G4zE6eOjS59naQcxi6GnscUCPH3b+hRG0qdKoGX49RAyiqW+M9aSw==
"@esbuild/netbsd-x64@0.17.14":
version "0.17.14"
resolved "https://registry.yarnpkg.com/@esbuild/netbsd-x64/-/netbsd-x64-0.17.14.tgz#5fa5255a64e9bf3947c1b3bef5e458b50b211994"
integrity sha512-nVwpqvb3yyXztxIT2+VsxJhB5GCgzPdk1n0HHSnchRAcxqKO6ghXwHhJnr0j/B+5FSyEqSxF4q03rbA2fKXtUQ==
"@esbuild/openbsd-x64@0.16.14":
version "0.16.14"
resolved "https://registry.yarnpkg.com/@esbuild/openbsd-x64/-/openbsd-x64-0.16.14.tgz#f36888f73087bcd12c5bf9a4b18e348da9c80ad0"
integrity sha512-/Jl8XVaWEZNu9rZw+n792GIBupQwHo6GDoapHSb/2xp/Ku28eK6QpR2O9cPBkzHH4OOoMH0LB6zg/qczJ5TTGg==
"@esbuild/openbsd-x64@0.17.14":
version "0.17.14"
resolved "https://registry.yarnpkg.com/@esbuild/openbsd-x64/-/openbsd-x64-0.17.14.tgz#74d14c79dcb6faf446878cc64284aa4e02f5ca6f"
integrity sha512-1RZ7uQQ9zcy/GSAJL1xPdN7NDdOOtNEGiJalg/MOzeakZeTrgH/DoCkbq7TaPDiPhWqnDF+4bnydxRqQD7il6g==
"@esbuild/sunos-x64@0.16.14":
version "0.16.14"
resolved "https://registry.yarnpkg.com/@esbuild/sunos-x64/-/sunos-x64-0.16.14.tgz#41e046bb0849ae59702a5cfa8be300431a61ee3a"
integrity sha512-2iI7D34uTbDn/TaSiUbEHz+fUa8KbN90vX5yYqo12QGpu6T8Jl+kxODsWuMCwoTVlqUpwfPV22nBbFPME9OPtw==
"@esbuild/sunos-x64@0.17.14":
version "0.17.14"
resolved "https://registry.yarnpkg.com/@esbuild/sunos-x64/-/sunos-x64-0.17.14.tgz#5c7d1c7203781d86c2a9b2ff77bd2f8036d24cfa"
integrity sha512-nqMjDsFwv7vp7msrwWRysnM38Sd44PKmW8EzV01YzDBTcTWUpczQg6mGao9VLicXSgW/iookNK6AxeogNVNDZA==
"@esbuild/win32-arm64@0.16.14":
version "0.16.14"
resolved "https://registry.yarnpkg.com/@esbuild/win32-arm64/-/win32-arm64-0.16.14.tgz#d6ed78742a6edd413e75796882ddaef8c1e23b93"
integrity sha512-SjlM7AHmQVTiGBJE/nqauY1aDh80UBsXZ94g4g60CDkrDMseatiqALVcIuElg4ZSYzJs8hsg5W6zS2zLpZTVgg==
"@esbuild/win32-arm64@0.17.14":
version "0.17.14"
resolved "https://registry.yarnpkg.com/@esbuild/win32-arm64/-/win32-arm64-0.17.14.tgz#dc36ed84f1390e73b6019ccf0566c80045e5ca3d"
integrity sha512-xrD0mccTKRBBIotrITV7WVQAwNJ5+1va6L0H9zN92v2yEdjfAN7864cUaZwJS7JPEs53bDTzKFbfqVlG2HhyKQ==
"@esbuild/win32-ia32@0.16.14":
version "0.16.14"
resolved "https://registry.yarnpkg.com/@esbuild/win32-ia32/-/win32-ia32-0.16.14.tgz#558bd53859a83fe887d7d2dcdc6cb3fc9aa9a9bc"
integrity sha512-z06t5zqk8ak0Xom5HG81z2iOQ1hNWYsFQp3sczVLVx+dctWdgl80tNRyTbwjaFfui2vFO12dfE3trCTvA+HO4g==
"@esbuild/win32-ia32@0.17.14":
version "0.17.14"
resolved "https://registry.yarnpkg.com/@esbuild/win32-ia32/-/win32-ia32-0.17.14.tgz#0802a107afa9193c13e35de15a94fe347c588767"
integrity sha512-nXpkz9bbJrLLyUTYtRotSS3t5b+FOuljg8LgLdINWFs3FfqZMtbnBCZFUmBzQPyxqU87F8Av+3Nco/M3hEcu1w==
"@esbuild/win32-x64@0.16.14":
version "0.16.14"
resolved "https://registry.yarnpkg.com/@esbuild/win32-x64/-/win32-x64-0.16.14.tgz#90558dcb279989d92a42e5be4dfb884b2399361f"
integrity sha512-ED1UpWcM6lAbalbbQ9TrGqJh4Y9TaASUvu8bI/0mgJcxhSByJ6rbpgqRhxYMaQ682WfA71nxUreaTO7L275zrw==
"@esbuild/win32-x64@0.17.14":
version "0.17.14"
resolved "https://registry.yarnpkg.com/@esbuild/win32-x64/-/win32-x64-0.17.14.tgz#e81fb49de05fed91bf74251c9ca0343f4fc77d31"
@ -3467,34 +3357,6 @@ es-to-primitive@^1.2.1:
is-date-object "^1.0.1"
is-symbol "^1.0.2"
esbuild@^0.16.3:
version "0.16.14"
resolved "https://registry.yarnpkg.com/esbuild/-/esbuild-0.16.14.tgz#366249a0a0fd431d3ab706195721ef1014198919"
integrity sha512-6xAn3O6ZZyoxZAEkwfI9hw4cEqSr/o1ViJtnkvImVkblmUN65Md04o0S/7H1WNu1XGf1Cjij/on7VO4psIYjkw==
optionalDependencies:
"@esbuild/android-arm" "0.16.14"
"@esbuild/android-arm64" "0.16.14"
"@esbuild/android-x64" "0.16.14"
"@esbuild/darwin-arm64" "0.16.14"
"@esbuild/darwin-x64" "0.16.14"
"@esbuild/freebsd-arm64" "0.16.14"
"@esbuild/freebsd-x64" "0.16.14"
"@esbuild/linux-arm" "0.16.14"
"@esbuild/linux-arm64" "0.16.14"
"@esbuild/linux-ia32" "0.16.14"
"@esbuild/linux-loong64" "0.16.14"
"@esbuild/linux-mips64el" "0.16.14"
"@esbuild/linux-ppc64" "0.16.14"
"@esbuild/linux-riscv64" "0.16.14"
"@esbuild/linux-s390x" "0.16.14"
"@esbuild/linux-x64" "0.16.14"
"@esbuild/netbsd-x64" "0.16.14"
"@esbuild/openbsd-x64" "0.16.14"
"@esbuild/sunos-x64" "0.16.14"
"@esbuild/win32-arm64" "0.16.14"
"@esbuild/win32-ia32" "0.16.14"
"@esbuild/win32-x64" "0.16.14"
esbuild@^0.17.5:
version "0.17.14"
resolved "https://registry.yarnpkg.com/esbuild/-/esbuild-0.17.14.tgz#d61a22de751a3133f3c6c7f9c1c3e231e91a3245"
@ -5004,11 +4866,6 @@ nano-time@1.0.0:
dependencies:
big-integer "^1.6.16"
nanoid@^3.3.4:
version "3.3.4"
resolved "https://registry.yarnpkg.com/nanoid/-/nanoid-3.3.4.tgz#730b67e3cd09e2deacf03c027c81c9d9dbc5e8ab"
integrity sha512-MqBkQh/OHTS2egovRtLk45wEyNXwF+cokD+1YPf9u5VfJiRdAiRwB2froX5Co9Rh20xs4siNPm8naNotSD6RBw==
nanoid@^3.3.6:
version "3.3.6"
resolved "https://registry.yarnpkg.com/nanoid/-/nanoid-3.3.6.tgz#443380c856d6e9f9824267d960b4236ad583ea4c"
@ -5335,15 +5192,6 @@ postcss-value-parser@^4.2.0:
resolved "https://registry.yarnpkg.com/postcss-value-parser/-/postcss-value-parser-4.2.0.tgz#723c09920836ba6d3e5af019f92bc0971c02e514"
integrity sha512-1NNCs6uurfkVbeXG4S8JFT9t19m45ICnif8zWLd5oPSZ50QnwMfK+H3jv408d4jw/7Bttv5axS5IiHoLaVNHeQ==
postcss@^8.4.20:
version "8.4.20"
resolved "https://registry.yarnpkg.com/postcss/-/postcss-8.4.20.tgz#64c52f509644cecad8567e949f4081d98349dc56"
integrity sha512-6Q04AXR1212bXr5fh03u8aAwbLxAQNGQ/Q1LNa0VfOI06ZAlhPHtQvE4OIdpj4kLThXilalPnmDSOD65DcHt+g==
dependencies:
nanoid "^3.3.4"
picocolors "^1.0.0"
source-map-js "^1.0.2"
postcss@^8.4.23:
version "8.4.23"
resolved "https://registry.yarnpkg.com/postcss/-/postcss-8.4.23.tgz#df0aee9ac7c5e53e1075c24a3613496f9e6552ab"
@ -5673,7 +5521,7 @@ resolve-protobuf-schema@^2.1.0:
dependencies:
protocol-buffers-schema "^3.3.1"
resolve@^1.14.2, resolve@^1.22.1:
resolve@^1.14.2:
version "1.22.1"
resolved "https://registry.yarnpkg.com/resolve/-/resolve-1.22.1.tgz#27cb2ebb53f91abb49470a928bba7558066ac177"
integrity sha512-nBpuuYuY5jFsli/JIs1oldw6fOQCBioohqWZg/2hiaOybXOft4lonv85uDOKXdf8rhyK159cxU5cDcK/NKk8zw==
@ -5717,13 +5565,6 @@ rollup@^3.21.0:
optionalDependencies:
fsevents "~2.3.2"
rollup@^3.7.0:
version "3.9.1"
resolved "https://registry.yarnpkg.com/rollup/-/rollup-3.9.1.tgz#27501d3d026418765fe379d5620d25954ff2a011"
integrity sha512-GswCYHXftN8ZKGVgQhTFUJB/NBXxrRGgO2NCy6E8s1rwEJ4Q9/VttNqcYfEvx4dTo4j58YqdC3OVztPzlKSX8w==
optionalDependencies:
fsevents "~2.3.2"
rrweb-cssom@^0.6.0:
version "0.6.0"
resolved "https://registry.yarnpkg.com/rrweb-cssom/-/rrweb-cssom-0.6.0.tgz#ed298055b97cbddcdeb278f904857629dec5e0e1"
@ -6440,22 +6281,10 @@ vite-plugin-ruby@^3.2.2:
debug "^4.3.4"
fast-glob "^3.2.12"
"vite@^3.0.0 || ^4.0.0":
version "4.0.4"
resolved "https://registry.yarnpkg.com/vite/-/vite-4.0.4.tgz#4612ce0b47bbb233a887a54a4ae0c6e240a0da31"
integrity sha512-xevPU7M8FU0i/80DMR+YhgrzR5KS2ORy1B4xcX/cXLsvnUWvfHuqMmVU6N0YiJ4JWGRJJsLCgjEzKjG9/GKoSw==
dependencies:
esbuild "^0.16.3"
postcss "^8.4.20"
resolve "^1.22.1"
rollup "^3.7.0"
optionalDependencies:
fsevents "~2.3.2"
vite@^4.3.0:
version "4.3.4"
resolved "https://registry.yarnpkg.com/vite/-/vite-4.3.4.tgz#1c518d763d5a700d890c3a19ab59220f06e7a7d5"
integrity sha512-f90aqGBoxSFxWph2b39ae2uHAxm5jFBBdnfueNxZAT1FTpM13ccFQExCaKbR2xFW5atowjleRniQ7onjJ22QEg==
"vite@^3.0.0 || ^4.0.0", vite@^4.3.9:
version "4.3.9"
resolved "https://registry.yarnpkg.com/vite/-/vite-4.3.9.tgz#db896200c0b1aa13b37cdc35c9e99ee2fdd5f96d"
integrity sha512-qsTNZjO9NoJNW7KnOrgYwczm0WctJ8m/yqYAMAK9Lxt4SoySUfS5S8ia9K7JHpa3KEeMfyF8LoJ3c5NeBJy6pg==
dependencies:
esbuild "^0.17.5"
postcss "^8.4.23"