demarches-normaliennes/spec/system/users/brouillon_spec.rb

520 lines
21 KiB
Ruby
Raw Normal View History

describe 'The user' do
let(:password) { 'my-s3cure-p4ssword' }
2018-02-21 18:32:07 +01:00
let!(:user) { create(:user, password: password) }
let!(:procedure) { create(:procedure, :published, :for_individual, :with_all_champs_mandatory) }
let(:user_dossier) { user.dossiers.first }
let!(:dossier_to_link) { create(:dossier) }
2018-02-21 18:32:07 +01:00
2020-10-07 17:44:21 +02:00
scenario 'fill a dossier', js: true do
log_in(user, procedure)
2018-02-21 18:32:07 +01:00
fill_individual
# fill data
fill_in('text *', with: 'super texte')
2018-02-21 18:32:07 +01:00
fill_in('textarea', with: 'super textarea')
2018-09-12 22:25:57 +02:00
fill_in('date', with: '12-12-2012')
2020-08-13 13:30:52 +02:00
select_date_and_time(Time.zone.parse('06/01/2030 7h05'), form_id_for_datetime('datetime'))
2018-02-21 18:32:07 +01:00
fill_in('number', with: '42')
fill_in('decimal_number', with: '17')
fill_in('integer_number', with: '12')
scroll_to(find_field('checkbox'), align: :center)
2018-02-21 18:32:07 +01:00
check('checkbox')
choose('Madame')
fill_in('email', with: 'loulou@yopmail.com')
2020-07-29 15:45:25 +02:00
fill_in('phone', with: '0123456789')
scroll_to(find_field('Non'), align: :center)
2018-02-21 18:32:07 +01:00
choose('Non')
2020-06-24 10:55:53 +02:00
choose('val2')
check('val1')
check('val3')
select('bravo', from: form_id_for('simple_choice_drop_down_list_long'))
select_combobox('multiple_choice_drop_down_list_long', 'alp', 'alpha')
select_combobox('multiple_choice_drop_down_list_long', 'cha', 'charly')
select_combobox('pays', 'aust', 'Australie')
select_combobox('regions', 'Ma', 'Martinique')
select_combobox('departements', 'Ai', '02 - Aisne')
select_combobox('communes', 'Ai', '02 - Aisne', check: false)
select_combobox('communes', 'Ambl', 'Ambléon (01300)')
fill_in('dossier_link', with: '123')
2019-02-19 17:36:02 +01:00
find('.editable-champ-piece_justificative input[type=file]').attach_file(Rails.root + 'spec/fixtures/files/file.pdf')
2018-02-21 18:32:07 +01:00
expect(page).to have_css('span', text: 'Votre brouillon est automatiquement enregistré', visible: true)
wait_for_autosave
2018-02-21 18:32:07 +01:00
# check data on the dossier
expect(user_dossier.brouillon?).to be true
expect(champ_value_for('text')).to eq('super texte')
expect(champ_value_for('textarea')).to eq('super textarea')
expect(champ_value_for('date')).to eq('2012-12-12')
expect(champ_value_for('datetime')).to eq('06/01/2030 07:05')
expect(champ_value_for('number')).to eq('42')
expect(champ_value_for('decimal_number')).to eq('17')
expect(champ_value_for('integer_number')).to eq('12')
expect(champ_value_for('checkbox')).to eq('on')
expect(champ_value_for('civilite')).to eq('Mme')
expect(champ_value_for('email')).to eq('loulou@yopmail.com')
expect(champ_value_for('phone')).to eq('0123456789')
expect(champ_value_for('yes_no')).to eq('false')
expect(champ_value_for('simple_drop_down_list')).to eq('val2')
expect(champ_value_for('simple_choice_drop_down_list_long')).to eq('bravo')
expect(JSON.parse(champ_value_for('multiple_choice_drop_down_list_long'))).to match(['alpha', 'charly'])
expect(JSON.parse(champ_value_for('multiple_drop_down_list'))).to match(['val1', 'val3'])
expect(champ_value_for('pays')).to eq('Australie')
expect(champ_value_for('regions')).to eq('Martinique')
expect(champ_value_for('departements')).to eq('02 - Aisne')
expect(champ_value_for('communes')).to eq('Ambléon (01300)')
expect(champ_value_for('dossier_link')).to eq('123')
expect(champ_value_for('piece_justificative')).to be_nil # antivirus hasn't approved the file yet
2018-02-21 18:32:07 +01:00
## check data on the gui
2019-02-19 17:36:02 +01:00
2018-02-21 18:32:07 +01:00
expect(page).to have_field('text', with: 'super texte')
expect(page).to have_field('textarea', with: 'super textarea')
expect(page).to have_field('date', with: '2012-12-12')
2020-08-13 13:30:52 +02:00
check_date_and_time(Time.zone.parse('06/01/2030 7:05'), form_id_for_datetime('datetime'))
2018-02-21 18:32:07 +01:00
expect(page).to have_field('number', with: '42')
expect(page).to have_checked_field('checkbox')
expect(page).to have_checked_field('Madame')
expect(page).to have_field('email', with: 'loulou@yopmail.com')
2020-07-29 15:45:25 +02:00
expect(page).to have_field('phone', with: '0123456789')
2018-02-21 18:32:07 +01:00
expect(page).to have_checked_field('Non')
2020-06-24 10:55:53 +02:00
expect(page).to have_checked_field('val2')
expect(page).to have_checked_field('val1')
expect(page).to have_checked_field('val3')
expect(page).to have_selected_value('simple_choice_drop_down_list_long', selected: 'bravo')
check_selected_value('multiple_choice_drop_down_list_long', with: ['alpha', 'charly'])
check_selected_value('pays', with: 'Australie')
check_selected_value('regions', with: 'Martinique')
check_selected_value('departements', with: '02 - Aisne')
check_selected_value('communes', with: 'Ambléon (01300)')
expect(page).to have_field('dossier_link', with: '123')
2019-02-19 17:36:02 +01:00
expect(page).to have_text('file.pdf')
expect(page).to have_text('analyse antivirus en cours')
2018-02-21 18:32:07 +01:00
end
2019-01-30 16:14:15 +01:00
let(:procedure_with_repetition) do
2020-08-27 19:56:34 +02:00
create(:procedure, :published, :for_individual, :with_repetition)
2019-01-30 16:14:15 +01:00
end
scenario 'fill a dossier with repetition', js: true do
log_in(user, procedure_with_repetition)
2019-01-30 16:14:15 +01:00
fill_individual
2020-08-27 19:56:34 +02:00
fill_in('sub type de champ', with: 'super texte')
expect(page).to have_field('sub type de champ', with: 'super texte')
2019-01-30 16:14:15 +01:00
click_on 'Ajouter un élément pour'
2019-01-30 16:14:15 +01:00
within '.repetition .row:first-child' do
2020-08-27 19:56:34 +02:00
fill_in('sub type de champ', with: 'un autre texte')
2019-01-30 16:14:15 +01:00
end
expect(page).to have_content('Supprimer', count: 2)
within '.repetition .row:first-child' do
click_on 'Supprimer lélément'
2019-01-30 16:14:15 +01:00
end
expect(page).to have_content('Supprimer', count: 1)
end
let(:simple_procedure) { create(:procedure, :published, :for_individual, types_de_champ_public: [{ mandatory: true, libelle: 'texte obligatoire' }, { mandatory: false, libelle: 'texte optionnel' }]) }
2018-02-21 18:32:07 +01:00
scenario 'save an incomplete dossier as draft but cannot not submit it', js: true do
log_in(user, simple_procedure)
2018-02-21 18:32:07 +01:00
fill_individual
2018-07-02 12:27:01 +02:00
# Check an incomplete dossier can be saved as a draft, even when mandatory fields are missing
2020-09-15 13:38:45 +02:00
fill_in('texte optionnel', with: 'ça ne suffira pas')
wait_for_autosave
expect(page).to have_current_path(brouillon_dossier_path(user_dossier))
2018-02-21 18:32:07 +01:00
2018-07-02 12:27:01 +02:00
# Check an incomplete dossier cannot be submitted when mandatory fields are missing
2019-07-15 16:10:34 +02:00
click_on 'Déposer le dossier'
2018-02-21 18:32:07 +01:00
expect(user_dossier.reload.brouillon?).to be(true)
expect(page).to have_current_path(brouillon_dossier_path(user_dossier))
2018-02-21 18:32:07 +01:00
2018-07-02 12:27:01 +02:00
# Check a dossier can be submitted when all mandatory fields are filled
fill_in('texte obligatoire', with: 'super texte')
wait_for_autosave
2018-02-21 18:32:07 +01:00
2019-07-15 16:10:34 +02:00
click_on 'Déposer le dossier'
2018-02-21 18:32:07 +01:00
expect(user_dossier.reload.en_construction?).to be(true)
2018-07-02 12:27:01 +02:00
expect(champ_value_for('texte obligatoire')).to eq('super texte')
2018-02-27 09:49:58 +01:00
expect(page).to have_current_path(merci_dossier_path(user_dossier))
2018-02-21 18:32:07 +01:00
end
scenario 'extends dossier experation date more than one time, ', js: true do
simple_procedure.update(procedure_expires_when_termine_enabled: true)
user_old_dossier = create(:dossier,
procedure: simple_procedure,
created_at: simple_procedure.duree_conservation_dossiers_dans_ds.month.ago,
user: user)
login_as(user, scope: :user)
visit brouillon_dossier_path(user_old_dossier)
expect(page).to have_css('.card-title', text: 'Votre dossier va expirer', visible: true)
find('#test-user-repousser-expiration').click
expect(page).to have_no_selector('#test-user-repousser-expiration')
Timecop.freeze(simple_procedure.duree_conservation_dossiers_dans_ds.month.from_now) do
visit brouillon_dossier_path(user_old_dossier)
expect(page).to have_css('.card-title', text: 'Votre dossier va expirer', visible: true)
find('#test-user-repousser-expiration').click
expect(page).to have_no_selector('#test-user-repousser-expiration')
end
end
let(:procedure_with_pj) { create(:procedure, :published, :for_individual, types_de_champ_public: [{ type: :piece_justificative, mandatory: true, libelle: 'Pièce justificative' }]) }
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
log_in(user, procedure_with_pjs)
2019-02-19 17:36:02 +01:00
fill_individual
# Add attachments
find_field('Pièce justificative 1').attach_file(Rails.root + 'spec/fixtures/files/file.pdf')
find_field('Pièce justificative 2').attach_file(Rails.root + 'spec/fixtures/files/RIB.pdf')
2019-02-19 17:36:02 +01:00
# Expect the files to be uploaded immediately
expect(page).to have_text('analyse antivirus en cours', count: 2)
expect(page).to have_text('file.pdf')
2019-02-19 17:36:02 +01:00
expect(page).to have_text('RIB.pdf')
# Expect the submit buttons to be enabled
expect(page).to have_button('Déposer le dossier', disabled: false)
2019-02-19 17:36:02 +01:00
# Reload the current page
visit current_path
# Expect the files to have been saved on the dossier
expect(page).to have_text('file.pdf')
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
log_in(user, old_procedure_with_disabled_pj_validation)
fill_individual
# Test invalid file type
attach_file('Pièce justificative 1', Rails.root + 'spec/fixtures/files/invalid_file_format.json')
expect(page).to have_no_text('La pièce justificative nest pas dun type accepté')
expect(page).to have_text('analyse antivirus en cours', count: 1)
end
scenario 'retry on transcient upload error', js: true do
log_in(user, procedure_with_pjs)
fill_individual
# Test auto-upload failure
# Make the subsequent auto-upload request fail
allow_any_instance_of(Champs::PieceJustificativeController).to receive(:update) do |instance|
instance.render json: { errors: ['Error'] }, status: :bad_request
end
attach_file('Pièce justificative 1', Rails.root + 'spec/fixtures/files/file.pdf')
expect(page).to have_text('Une erreur sest produite pendant lenvoi du fichier')
expect(page).to have_button('Ré-essayer', visible: true)
expect(page).to have_button('Déposer le dossier', disabled: false)
allow_any_instance_of(Champs::PieceJustificativeController).to receive(:update).and_call_original
# Test that retrying after a failure works
click_on('Ré-essayer', visible: true)
expect(page).to have_text('analyse antivirus en cours')
expect(page).to have_text('file.pdf')
expect(page).to have_button('Déposer le dossier', disabled: false)
# Reload the current page
visit current_path
# Expect the file to have been saved on the dossier
expect(page).to have_text('file.pdf')
end
2022-10-10 18:03:47 +02:00
context 'with routing activated and one instructor group' do
let!(:simple_procedure) { create(:simple_procedure, :published, :with_type_de_champ, :for_individual) }
let!(:administrateur) { create(:administrateur, procedures: [simple_procedure]) }
before do
simple_procedure.update(routing_enabled: true)
simple_procedure.defaut_groupe_instructeur.instructeurs << administrateur.instructeur
end
it 'sends the dossier without selecting instructor group', js: true do
log_in(user, simple_procedure)
fill_individual
fill_in('Texte obligatoire', with: 'bla bla')
wait_for_autosave
expect(page).not_to have_text('Votre ville')
click_on 'Déposer le dossier'
expect(page).to have_text('Merci')
end
end
context 'with condition' do
include Logic
context 'with a repetition' do
let(:procedure) do
procedure = create(:procedure, :published, :for_individual,
types_de_champ_public: [
{ type: :integer_number, libelle: 'age' },
{
type: :repetition, libelle: 'repetition', children: [
{ type: :text, libelle: 'nom', mandatory: true }
]
}
])
age = procedure.published_revision.types_de_champ.where(libelle: 'age').first
repetition = procedure.published_revision.types_de_champ.repetition.first
repetition.update(condition: greater_than_eq(champ_value(age.stable_id), constant(18)))
procedure
end
scenario 'submit a dossier with an hidden mandatory champ within a repetition', js: true do
log_in(user, procedure)
fill_individual
fill_in('age', with: 10)
click_on 'Déposer le dossier'
expect(page).to have_current_path(merci_dossier_path(user_dossier))
end
end
2022-08-08 17:11:20 +02:00
context 'with a required conditionnal champ' do
let(:procedure) do
procedure = create(:procedure, :published, :for_individual,
types_de_champ_public: [
{ type: :integer_number, libelle: 'age' },
{ type: :text, libelle: 'nom', mandatory: true }
])
age, nom = procedure.draft_revision.types_de_champ.all
nom.update(condition: greater_than_eq(champ_value(age.stable_id), constant(18)))
procedure
end
scenario 'submit a dossier with an hidden mandatory champ ', js: true do
log_in(user, procedure)
fill_individual
click_on 'Déposer le dossier'
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
log_in(user, procedure)
fill_individual
fill_in('age', with: '18')
expect(page).to have_css('label', text: 'nom *', visible: :visible)
click_on 'Déposer le dossier'
expect(page).to have_current_path(brouillon_dossier_path(user_dossier))
end
2022-08-08 17:11:20 +02:00
end
2022-08-08 16:27:02 +02:00
context 'with a visibilite in cascade' do
let(:procedure) do
procedure = create(:procedure, :for_individual).tap do |p|
p.draft_revision.add_type_de_champ(type_champ: :integer_number, libelle: 'age')
p.draft_revision.add_type_de_champ(type_champ: :yes_no, libelle: 'permis de conduire')
p.draft_revision.add_type_de_champ(type_champ: :integer_number, libelle: 'tonnage')
p.draft_revision.add_type_de_champ(type_champ: :text, libelle: 'parking')
end
2022-08-08 16:27:02 +02:00
age, permis, tonnage, parking = procedure.draft_revision.types_de_champ.all
2022-07-20 10:58:03 +02:00
2022-08-08 16:27:02 +02:00
permis.update(condition: greater_than_eq(champ_value(age.stable_id), constant(18)))
tonnage.update(condition: ds_eq(champ_value(permis.stable_id), constant(true)))
parking.update(condition: less_than_eq(champ_value(tonnage.stable_id), constant(20)))
2022-07-20 10:58:03 +02:00
2022-08-08 16:27:02 +02:00
procedure.publish!
2022-07-20 10:58:03 +02:00
2022-08-08 16:27:02 +02:00
procedure
end
2022-08-08 16:27:02 +02:00
scenario 'fill a dossier', js: true do
log_in(user, procedure)
2022-08-08 16:27:02 +02:00
fill_individual
2022-08-08 16:27:02 +02:00
expect(page).to have_css('label', text: 'age', visible: true)
expect(page).to have_no_css('label', text: 'permis de conduire', visible: true)
expect(page).to have_no_css('label', text: 'tonnage', visible: true)
2022-07-20 10:58:03 +02:00
2022-08-08 16:27:02 +02:00
fill_in('age', with: '18')
expect(page).to have_css('label', text: 'permis de conduire', visible: true)
expect(page).to have_no_css('label', text: 'tonnage', visible: true)
2022-07-20 10:58:03 +02:00
2022-08-08 16:27:02 +02:00
choose('Oui')
expect(page).to have_css('label', text: 'permis de conduire', visible: true)
expect(page).to have_css('label', text: 'tonnage', visible: true)
2022-07-20 10:58:03 +02:00
2022-08-08 16:27:02 +02:00
fill_in('tonnage', with: '1')
expect(page).to have_css('label', text: 'parking', visible: true)
2022-08-08 16:27:02 +02:00
# try to fill with invalid data
fill_in('tonnage', with: 'a')
expect(page).to have_no_css('label', text: 'parking', visible: true)
2022-08-08 16:27:02 +02:00
fill_in('age', with: '2')
expect(page).to have_no_css('label', text: 'permis de conduire', visible: true)
expect(page).to have_no_css('label', text: 'tonnage', visible: true)
2022-08-08 16:27:02 +02:00
click_on 'Déposer le dossier'
click_on 'Accéder à votre dossier'
click_on 'Modifier mon dossier'
2022-08-08 16:27:02 +02:00
expect(page).to have_css('label', text: 'age', visible: true)
expect(page).to have_no_css('label', text: 'permis de conduire', visible: true)
expect(page).to have_no_css('label', text: 'tonnage', visible: true)
2022-07-20 10:58:03 +02:00
2022-08-08 16:27:02 +02:00
fill_in('age', with: '18')
wait_for_autosave(false)
2022-08-08 16:27:02 +02:00
# the champ keeps their previous value so they are all displayed
expect(page).to have_css('label', text: 'permis de conduire', visible: true)
expect(page).to have_css('label', text: 'tonnage', visible: true)
end
end
end
2020-09-14 22:40:43 +02:00
context 'draft autosave' do
2019-11-19 14:40:28 +01:00
scenario 'autosave a draft', js: true do
log_in(user, simple_procedure)
fill_individual
expect(page).to have_no_button('Enregistrer le brouillon')
2019-11-19 14:40:28 +01:00
expect(page).to have_content('Votre brouillon est automatiquement enregistré')
fill_in('texte obligatoire', with: 'a valid user input')
wait_for_autosave
2019-11-19 14:40:28 +01:00
visit current_path
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
2019-11-19 14:40:28 +01:00
log_in(user, simple_procedure)
fill_individual
# Test autosave failure
allow_any_instance_of(Users::DossiersController).to receive(:update_brouillon).and_raise("Server is busy")
2019-11-19 14:40:28 +01:00
fill_in('texte obligatoire', with: 'a valid user input')
blur
expect(page).to have_css('span', text: 'Impossible denregistrer le brouillon', visible: true)
# Test that retrying after a failure works
allow_any_instance_of(Users::DossiersController).to receive(:update_brouillon).and_call_original
2019-11-19 14:40:28 +01:00
click_on 'réessayer'
wait_for_autosave
2019-11-19 14:40:28 +01:00
visit current_path
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
log_in(user, simple_procedure)
fill_individual
# When the user is disconnected
# (either because signing-out in another tab, or because the session cookie expired)
logout(:user)
fill_in('texte obligatoire', with: 'a valid user input')
blur
# … they are redirected to the sign-in page.
expect(page).to have_current_path(new_user_session_path)
# After sign-in, they are redirected back to their brouillon
sign_in_with(user.email, password)
expect(page).to have_current_path(brouillon_dossier_path(user_dossier))
fill_in('texte obligatoire', with: 'a valid user input')
wait_for_autosave
end
2019-11-19 14:40:28 +01:00
end
2018-02-21 18:32:07 +01:00
private
def log_in(user, procedure)
login_as user, scope: :user
2018-02-21 18:32:07 +01:00
visit "/commencer/#{procedure.path}"
click_on 'Commencer la démarche'
2021-05-26 15:16:30 +02:00
expect(page).to have_content("Données didentité")
2018-02-21 18:32:07 +01:00
expect(page).to have_current_path(identite_dossier_path(user_dossier))
end
2020-03-16 17:42:49 +01:00
def form_id_for_datetime(libelle)
# The HTML for datetime is a bit specific since it has 5 selects, below here is a sample HTML
# So, we want to find the partial id of a datetime (partial because there are 5 ids:
# dossier_champs_attributes_3_value_1i, 2i, ... 5i) ; we are interested in the 'dossier_champs_attributes_3_value' part
# which is then completed in select_date_and_time and check_date_and_time
#
# We find the H2, find the first select in the next .datetime div, then strip the last 3 characters
#
# <h4 class="form-label">
# libelle
# </h4>
# <div class="datetime">
# <span class="hidden">
# <label for="dossier_champs_attributes_3_value_3i">Jour</label></span>
# <select id="dossier_champs_attributes_3_value_3i" name="dossier[champs_attributes][3][value(3i)]">
# <option value=""></option>
# <option value="1">1</option>
# <option value="2">2</option>
# <!-- … -->
# </select>
# <!-- … 4 other selects for month, year, minute and seconds -->
# </div>
e = find(:xpath, ".//div[contains(text()[normalize-space()], '#{libelle}')]")
2020-03-16 17:42:49 +01:00
e.sibling('.datetime').first('select')[:id][0..-4]
end
2018-02-21 18:32:07 +01:00
def champ_value_for(libelle)
champs = user_dossier.reload.champs
2018-02-21 18:32:07 +01:00
champs.find { |c| c.libelle == libelle }.value
end
def fill_individual
2020-12-08 17:43:50 +01:00
choose 'Monsieur'
2018-02-21 18:32:07 +01:00
fill_in('individual_prenom', with: 'prenom')
fill_in('individual_nom', with: 'nom')
click_on 'Continuer'
expect(page).to have_current_path(brouillon_dossier_path(user_dossier))
2018-02-21 18:32:07 +01:00
end
def select_date_and_time(date, field)
select date.strftime('%Y'), from: "#{field}_1i" # year
select I18n.l(date, format: '%B'), from: "#{field}_2i" # month
select date.strftime('%-d'), from: "#{field}_3i" # day
select date.strftime('%H'), from: "#{field}_4i" # hour
select date.strftime('%M'), from: "#{field}_5i" # minute
end
def check_date_and_time(date, field)
expect(page).to have_selected_value("#{field}_1i", selected: date.strftime('%Y'))
expect(page).to have_selected_value("#{field}_2i", selected: I18n.l(date, format: '%B'))
expect(page).to have_selected_value("#{field}_3i", selected: date.strftime('%-d'))
expect(page).to have_selected_value("#{field}_4i", selected: date.strftime('%H'))
expect(page).to have_selected_value("#{field}_5i", selected: date.strftime('%M'))
2018-02-21 18:32:07 +01:00
end
end