specs: migrate from features to system specs
System specs have been available since Rails 5.1, and are better integrated with the Rails framework. - Rename `spec/features` to `spec/system` - Rename `feature do` to `describe do` - Configure Capybara for system specs Steps mostly taken from https://medium.com/table-xi/a-quick-guide-to-rails-system-tests-in-rspec-b6e9e8a8b5f6
This commit is contained in:
parent
df9fa258ae
commit
9fd38cae5e
42 changed files with 58 additions and 53 deletions
371
spec/system/users/brouillon_spec.rb
Normal file
371
spec/system/users/brouillon_spec.rb
Normal file
|
@ -0,0 +1,371 @@
|
|||
describe 'The user' do
|
||||
let(:password) { 'my-s3cure-p4ssword' }
|
||||
let!(:user) { create(:user, password: password) }
|
||||
|
||||
let!(:procedure) { create(:procedure, :published, :for_individual, :with_all_champs_mandatory) }
|
||||
let(:user_dossier) { user.dossiers.first }
|
||||
|
||||
scenario 'fill a dossier', js: true do
|
||||
log_in(user, procedure)
|
||||
|
||||
fill_individual
|
||||
|
||||
# fill data
|
||||
fill_in('text', with: 'super texte')
|
||||
fill_in('textarea', with: 'super textarea')
|
||||
fill_in('date', with: '12-12-2012')
|
||||
select_date_and_time(Time.zone.parse('06/01/2030 7h05'), form_id_for_datetime('datetime'))
|
||||
fill_in('number', with: '42')
|
||||
find_field('checkbox').scroll_to(:center)
|
||||
check('checkbox')
|
||||
choose('Madame')
|
||||
fill_in('email', with: 'loulou@yopmail.com')
|
||||
fill_in('phone', with: '0123456789')
|
||||
choose('Non')
|
||||
choose('val2')
|
||||
check('val1')
|
||||
check('val3')
|
||||
select('bravo', from: form_id_for('simple_choice_drop_down_list_long'))
|
||||
select_multi_combobox('multiple_choice_drop_down_list_long', 'alp', 'alpha')
|
||||
select_multi_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', 'Ambl', 'Ambléon (01300)')
|
||||
|
||||
check('engagement')
|
||||
fill_in('dossier_link', with: '123')
|
||||
find('.editable-champ-piece_justificative input[type=file]').attach_file(Rails.root + 'spec/fixtures/files/file.pdf')
|
||||
|
||||
blur
|
||||
sleep(0.7)
|
||||
expect(page).to have_css('span', text: 'Brouillon enregistré', visible: true)
|
||||
|
||||
# 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('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('engagement')).to eq('on')
|
||||
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
|
||||
|
||||
## check data on the gui
|
||||
|
||||
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')
|
||||
check_date_and_time(Time.zone.parse('06/01/2030 7:05'), form_id_for_datetime('datetime'))
|
||||
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')
|
||||
expect(page).to have_field('phone', with: '0123456789')
|
||||
expect(page).to have_checked_field('Non')
|
||||
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_values('multiple_choice_drop_down_list_long', ['alpha', 'charly'])
|
||||
expect(page).to have_hidden_field('pays', with: 'Australie')
|
||||
expect(page).to have_hidden_field('regions', with: 'Martinique')
|
||||
expect(page).to have_hidden_field('departements', with: '02 - Aisne')
|
||||
expect(page).to have_hidden_field('communes', with: 'Ambléon (01300)')
|
||||
expect(page).to have_checked_field('engagement')
|
||||
expect(page).to have_field('dossier_link', with: '123')
|
||||
expect(page).to have_text('file.pdf')
|
||||
expect(page).to have_text('analyse antivirus en cours')
|
||||
end
|
||||
|
||||
let(:procedure_with_repetition) do
|
||||
create(:procedure, :published, :for_individual, :with_repetition)
|
||||
end
|
||||
|
||||
scenario 'fill a dossier with repetition', js: true do
|
||||
log_in(user, procedure_with_repetition)
|
||||
|
||||
fill_individual
|
||||
|
||||
fill_in('sub type de champ', with: 'super texte')
|
||||
expect(page).to have_field('sub type de champ', with: 'super texte')
|
||||
|
||||
click_on 'Ajouter un élément pour'
|
||||
|
||||
within '.row-1' do
|
||||
fill_in('sub type de champ', with: 'un autre texte')
|
||||
end
|
||||
|
||||
expect(page).to have_content('Supprimer', count: 2)
|
||||
|
||||
blur
|
||||
expect(page).to have_css('span', text: 'Brouillon enregistré', visible: true)
|
||||
|
||||
expect(page).to have_content('Supprimer', count: 2)
|
||||
|
||||
within '.row-1' do
|
||||
click_on 'Supprimer l’élément'
|
||||
end
|
||||
|
||||
blur
|
||||
expect(page).to have_css('span', text: 'Brouillon enregistré', visible: true)
|
||||
|
||||
expect(page).to have_content('Supprimer', count: 1)
|
||||
end
|
||||
|
||||
let(:simple_procedure) do
|
||||
tdcs = [
|
||||
build(:type_de_champ, mandatory: true, libelle: 'texte obligatoire'),
|
||||
build(:type_de_champ, mandatory: false, libelle: 'texte optionnel')
|
||||
]
|
||||
create(:procedure, :published, :for_individual, types_de_champ: tdcs)
|
||||
end
|
||||
|
||||
scenario 'save an incomplete dossier as draft but cannot not submit it', js: true do
|
||||
log_in(user, simple_procedure)
|
||||
fill_individual
|
||||
|
||||
# Check an incomplete dossier can be saved as a draft, even when mandatory fields are missing
|
||||
fill_in('texte optionnel', with: 'ça ne suffira pas')
|
||||
blur
|
||||
expect(page).to have_css('span', text: 'Brouillon enregistré', visible: true)
|
||||
expect(page).to have_current_path(brouillon_dossier_path(user_dossier))
|
||||
|
||||
# Check an incomplete dossier cannot be submitted when mandatory fields are missing
|
||||
click_on 'Déposer le dossier'
|
||||
expect(user_dossier.reload.brouillon?).to be(true)
|
||||
expect(page).to have_current_path(brouillon_dossier_path(user_dossier))
|
||||
|
||||
# Check a dossier can be submitted when all mandatory fields are filled
|
||||
fill_in('texte obligatoire', with: 'super texte')
|
||||
|
||||
click_on 'Déposer le dossier'
|
||||
expect(user_dossier.reload.en_construction?).to be(true)
|
||||
expect(champ_value_for('texte obligatoire')).to eq('super texte')
|
||||
expect(page).to have_current_path(merci_dossier_path(user_dossier))
|
||||
end
|
||||
|
||||
let(:procedure_with_pj) do
|
||||
tdcs = [build(:type_de_champ_piece_justificative, mandatory: true, libelle: 'Pièce justificative')]
|
||||
create(:procedure, :published, :for_individual, types_de_champ: tdcs)
|
||||
end
|
||||
|
||||
let(:procedure_with_pjs) do
|
||||
tdcs = [
|
||||
build(:type_de_champ_piece_justificative, mandatory: true, libelle: 'Pièce justificative 1', position: 1),
|
||||
build(:type_de_champ_piece_justificative, mandatory: true, libelle: 'Pièce justificative 2', position: 2)
|
||||
]
|
||||
create(:procedure, :published, :for_individual, types_de_champ: tdcs)
|
||||
end
|
||||
|
||||
let(:old_procedure_with_disabled_pj_validation) do
|
||||
tdcs = [
|
||||
create(:type_de_champ_piece_justificative, mandatory: true, libelle: 'Pièce justificative 1', order_place: 1, skip_pj_validation: true)
|
||||
]
|
||||
create(:procedure, :published, :for_individual, types_de_champ: tdcs)
|
||||
end
|
||||
|
||||
scenario 'add an attachment', js: true do
|
||||
log_in(user, procedure_with_pjs)
|
||||
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')
|
||||
|
||||
# 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')
|
||||
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)
|
||||
|
||||
# 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 n’est pas d’un 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
|
||||
logout(:user) # Make the subsequent auto-upload request fail
|
||||
attach_file('Pièce justificative 1', Rails.root + 'spec/fixtures/files/file.pdf')
|
||||
expect(page).to have_text('Une erreur s’est produite pendant l’envoi du fichier')
|
||||
expect(page).to have_button('Ré-essayer', visible: true)
|
||||
expect(page).to have_button('Déposer le dossier', disabled: false)
|
||||
|
||||
# Test that retrying after a failure works
|
||||
login_as(user, scope: :user) # Make the auto-upload request work again
|
||||
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
|
||||
|
||||
context 'draft autosave' do
|
||||
scenario 'autosave a draft', js: true do
|
||||
log_in(user, simple_procedure)
|
||||
fill_individual
|
||||
|
||||
expect(page).not_to have_button('Enregistrer le brouillon')
|
||||
expect(page).to have_content('Votre brouillon est automatiquement enregistré')
|
||||
|
||||
fill_in('texte obligatoire', with: 'a valid user input')
|
||||
blur
|
||||
|
||||
expect(page).to have_css('span', text: 'Brouillon enregistré', visible: true)
|
||||
|
||||
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
|
||||
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")
|
||||
fill_in('texte obligatoire', with: 'a valid user input')
|
||||
blur
|
||||
expect(page).to have_css('span', text: 'Impossible d’enregistrer le brouillon', visible: true)
|
||||
|
||||
# Test that retrying after a failure works
|
||||
allow_any_instance_of(Users::DossiersController).to receive(:update_brouillon).and_call_original
|
||||
click_on 'réessayer'
|
||||
expect(page).to have_css('span', text: 'Brouillon enregistré', visible: true)
|
||||
|
||||
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')
|
||||
blur
|
||||
expect(page).to have_css('span', text: 'Brouillon enregistré', visible: true)
|
||||
end
|
||||
end
|
||||
|
||||
private
|
||||
|
||||
def log_in(user, procedure)
|
||||
login_as user, scope: :user
|
||||
|
||||
visit "/commencer/#{procedure.path}"
|
||||
click_on 'Commencer la démarche'
|
||||
|
||||
expect(page).to have_content("Données d’identité")
|
||||
expect(page).to have_current_path(identite_dossier_path(user_dossier))
|
||||
end
|
||||
|
||||
def form_id_for(libelle)
|
||||
find(:xpath, ".//label[contains(text()[normalize-space()], '#{libelle}')]")[:for]
|
||||
end
|
||||
|
||||
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}')]")
|
||||
e.sibling('.datetime').first('select')[:id][0..-4]
|
||||
end
|
||||
|
||||
def champ_value_for(libelle)
|
||||
champs = user_dossier.champs
|
||||
champs.find { |c| c.libelle == libelle }.value
|
||||
end
|
||||
|
||||
def fill_individual
|
||||
choose 'Monsieur'
|
||||
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))
|
||||
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'))
|
||||
end
|
||||
end
|
31
spec/system/users/change_email_spec.rb
Normal file
31
spec/system/users/change_email_spec.rb
Normal file
|
@ -0,0 +1,31 @@
|
|||
describe 'Changing an email' do
|
||||
let(:old_email) { 'old@email.com' }
|
||||
let(:user) { create(:user, email: old_email) }
|
||||
|
||||
before do
|
||||
login_as user, scope: :user
|
||||
end
|
||||
|
||||
scenario 'is easy' do
|
||||
new_email = 'new@email.com'
|
||||
|
||||
visit '/profil'
|
||||
|
||||
fill_in :user_email, with: new_email
|
||||
|
||||
perform_enqueued_jobs do
|
||||
click_button 'Changer mon adresse'
|
||||
end
|
||||
|
||||
expect(page).to have_content(I18n.t('devise.registrations.update_needs_confirmation'))
|
||||
expect(page).to have_content(old_email)
|
||||
expect(page).to have_content(new_email)
|
||||
|
||||
click_confirmation_link_for(new_email)
|
||||
|
||||
expect(page).to have_content(I18n.t('devise.confirmations.confirmed'))
|
||||
expect(page).not_to have_content(old_email)
|
||||
expect(page).to have_content(new_email)
|
||||
expect(user.reload.email).to eq(new_email)
|
||||
end
|
||||
end
|
132
spec/system/users/dossier_creation_spec.rb
Normal file
132
spec/system/users/dossier_creation_spec.rb
Normal file
|
@ -0,0 +1,132 @@
|
|||
describe 'Creating a new dossier:' do
|
||||
let(:user) { create(:user) }
|
||||
let(:siret) { '41816609600051' }
|
||||
let(:siren) { siret[0...9] }
|
||||
|
||||
context 'when the user is already signed in' do
|
||||
before do
|
||||
login_as user, scope: :user
|
||||
end
|
||||
|
||||
context 'when the procedure has identification by individual' do
|
||||
let(:procedure) { create(:procedure, :published, :for_individual, :with_service, ask_birthday: ask_birthday) }
|
||||
let(:ask_birthday) { false }
|
||||
let(:expected_birthday) { nil }
|
||||
|
||||
before do
|
||||
visit commencer_path(path: procedure.path)
|
||||
click_on 'Commencer la démarche'
|
||||
|
||||
expect(page).to have_current_path identite_dossier_path(user.reload.dossiers.last)
|
||||
expect(page).to have_procedure_description(procedure)
|
||||
|
||||
choose 'Monsieur'
|
||||
fill_in 'individual_nom', with: 'Nom'
|
||||
fill_in 'individual_prenom', with: 'Prenom'
|
||||
end
|
||||
|
||||
shared_examples 'the user can create a new draft' do
|
||||
it do
|
||||
click_button('Continuer')
|
||||
|
||||
expect(page).to have_current_path(brouillon_dossier_path(procedure.dossiers.last))
|
||||
|
||||
expect(user.dossiers.first.individual.birthdate).to eq(expected_birthday)
|
||||
end
|
||||
end
|
||||
|
||||
context 'when the birthday is asked' do
|
||||
let(:ask_birthday) { true }
|
||||
let(:expected_birthday) { Date.new(1987, 10, 14) }
|
||||
|
||||
before do
|
||||
fill_in 'individual_birthdate', with: birthday_format
|
||||
end
|
||||
|
||||
context 'when the browser supports `type=date` input fields' do
|
||||
let(:birthday_format) { '1987-10-14' }
|
||||
it_behaves_like 'the user can create a new draft'
|
||||
end
|
||||
|
||||
context 'when the browser does not support `type=date` input fields' do
|
||||
let(:birthday_format) { '1987-10-14' }
|
||||
it_behaves_like 'the user can create a new draft'
|
||||
end
|
||||
end
|
||||
|
||||
context 'when the birthday is not asked' do
|
||||
let(:ask_birthday) { false }
|
||||
let(:expected_birthday) { nil }
|
||||
it_behaves_like 'the user can create a new draft'
|
||||
end
|
||||
end
|
||||
|
||||
context 'when identifying through SIRET' do
|
||||
let(:procedure) { create(:procedure, :published, :with_service, :with_type_de_champ) }
|
||||
let(:dossier) { procedure.dossiers.last }
|
||||
|
||||
before do
|
||||
stub_request(:get, /https:\/\/entreprise.api.gouv.fr\/v2\/etablissements\/#{siret}/)
|
||||
.to_return(status: 200, body: File.read('spec/fixtures/files/api_entreprise/etablissements.json'))
|
||||
stub_request(:get, /https:\/\/entreprise.api.gouv.fr\/v2\/entreprises\/#{siren}/)
|
||||
.to_return(status: 200, body: File.read('spec/fixtures/files/api_entreprise/entreprises.json'))
|
||||
stub_request(:get, /https:\/\/entreprise.api.gouv.fr\/v2\/exercices\/#{siret}/)
|
||||
.to_return(status: 200, body: File.read('spec/fixtures/files/api_entreprise/exercices.json'))
|
||||
stub_request(:get, /https:\/\/entreprise.api.gouv.fr\/v2\/associations\/#{siret}/)
|
||||
.to_return(status: 404, body: '')
|
||||
stub_request(:get, /https:\/\/entreprise.api.gouv.fr\/v2\/effectifs_mensuels_acoss_covid\/2020\/02\/entreprise\/#{siren}/)
|
||||
.to_return(status: 404, body: '')
|
||||
stub_request(:get, /https:\/\/entreprise.api.gouv.fr\/v2\/effectifs_annuels_acoss_covid\/#{siren}/)
|
||||
.to_return(status: 404, body: '')
|
||||
allow_any_instance_of(APIEntrepriseToken).to receive(:roles).and_return([])
|
||||
allow_any_instance_of(APIEntrepriseToken).to receive(:expired?).and_return(false)
|
||||
end
|
||||
before { Timecop.freeze(Time.zone.local(2020, 3, 14)) }
|
||||
after { Timecop.return }
|
||||
|
||||
scenario 'the user can enter the SIRET of its etablissement and create a new draft' do
|
||||
visit commencer_path(path: procedure.path)
|
||||
click_on 'Commencer la démarche'
|
||||
|
||||
expect(page).to have_current_path siret_dossier_path(dossier)
|
||||
expect(page).to have_procedure_description(procedure)
|
||||
|
||||
fill_in 'Numéro SIRET', with: siret
|
||||
click_on 'Valider'
|
||||
|
||||
expect(page).to have_current_path(etablissement_dossier_path(dossier))
|
||||
expect(page).to have_content('OCTO TECHNOLOGY')
|
||||
click_on 'Continuer avec ces informations'
|
||||
|
||||
expect(page).to have_current_path(brouillon_dossier_path(dossier))
|
||||
end
|
||||
|
||||
scenario 'the user is notified when its SIRET is invalid' do
|
||||
visit commencer_path(path: procedure.path)
|
||||
click_on 'Commencer la démarche'
|
||||
|
||||
expect(page).to have_current_path(siret_dossier_path(dossier))
|
||||
expect(page).to have_procedure_description(procedure)
|
||||
|
||||
fill_in 'Numéro SIRET', with: '0000'
|
||||
click_on 'Valider'
|
||||
|
||||
expect(page).to have_current_path(siret_dossier_path(dossier))
|
||||
expect(page).to have_content('Le numéro SIRET doit comporter 14 chiffres')
|
||||
expect(page).to have_field('Numéro SIRET', with: '0000')
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
context 'when the user is not signed in' do
|
||||
let(:instructeur) { create(:instructeur) }
|
||||
let(:procedure) { create(:procedure, :published) }
|
||||
scenario 'the user is an instructeur with untrusted device' do
|
||||
visit commencer_path(path: procedure.path)
|
||||
click_on "J’ai déjà un compte"
|
||||
sign_in_with(instructeur.email, instructeur.user.password, true)
|
||||
|
||||
expect(page).to have_current_path(commencer_path(path: procedure.path))
|
||||
end
|
||||
end
|
||||
end
|
61
spec/system/users/dossier_details_spec.rb
Normal file
61
spec/system/users/dossier_details_spec.rb
Normal file
|
@ -0,0 +1,61 @@
|
|||
require 'system/users/dossier_shared_examples.rb'
|
||||
|
||||
describe 'Dossier details:' do
|
||||
let(:user) { create(:user) }
|
||||
let(:procedure) { create(:simple_procedure) }
|
||||
let(:dossier) { create(:dossier, :en_construction, :with_individual, :with_commentaires, user: user, procedure: procedure) }
|
||||
|
||||
before do
|
||||
visit_dossier dossier
|
||||
end
|
||||
|
||||
scenario 'the user can see the summary of the dossier status' do
|
||||
expect(page).to have_current_path(dossier_path(dossier))
|
||||
expect(page).to have_content(dossier.id)
|
||||
expect(page).to have_selector('.status-explanation')
|
||||
expect(page).to have_text(dossier.commentaires.last.body)
|
||||
end
|
||||
|
||||
describe "the user can see the mean time they are expected to wait" do
|
||||
let(:other_dossier) { create(:dossier, :accepte, :with_individual, procedure: procedure, en_construction_at: 10.days.ago, en_instruction_at: 9.days.ago, processed_at: Time.zone.now) }
|
||||
|
||||
context "when the dossier is in construction" do
|
||||
it "displays the estimated wait duration" do
|
||||
other_dossier
|
||||
visit dossier_path(dossier)
|
||||
expect(page).to have_text("Habituellement, les dossiers de cette démarche sont traités dans un délai de 10 jours.")
|
||||
end
|
||||
end
|
||||
|
||||
context "when the dossier is in instruction" do
|
||||
let(:dossier) { create(:dossier, :en_instruction, :with_individual, :with_commentaires, user: user, procedure: procedure) }
|
||||
|
||||
it "displays the estimated wait duration" do
|
||||
other_dossier
|
||||
visit dossier_path(dossier)
|
||||
expect(page).to have_text("Habituellement, les dossiers de cette démarche sont traités dans un délai de 10 jours.")
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
scenario 'the user is redirected from old URLs' do
|
||||
visit "/users/dossiers/#{dossier.id}/recapitulatif"
|
||||
expect(page).to have_current_path(dossier_path(dossier))
|
||||
end
|
||||
|
||||
it_behaves_like 'the user can edit the submitted demande'
|
||||
it_behaves_like 'the user can send messages to the instructeur'
|
||||
|
||||
private
|
||||
|
||||
def visit_dossier(dossier)
|
||||
visit dossier_path(dossier)
|
||||
|
||||
expect(page).to have_current_path(new_user_session_path)
|
||||
fill_in 'user_email', with: user.email
|
||||
fill_in 'user_password', with: user.password
|
||||
click_on 'Se connecter'
|
||||
|
||||
expect(page).to have_current_path(dossier_path(dossier))
|
||||
end
|
||||
end
|
41
spec/system/users/dossier_shared_examples.rb
Normal file
41
spec/system/users/dossier_shared_examples.rb
Normal file
|
@ -0,0 +1,41 @@
|
|||
RSpec.shared_examples 'the user can edit the submitted demande' do
|
||||
scenario js: true do
|
||||
visit dossier_path(dossier)
|
||||
|
||||
expect(page).to have_current_path(dossier_path(dossier))
|
||||
click_on 'Demande'
|
||||
|
||||
expect(page).to have_current_path(demande_dossier_path(dossier))
|
||||
click_on 'Modifier le dossier'
|
||||
|
||||
expect(page).to have_current_path(modifier_dossier_path(dossier))
|
||||
fill_in('Texte obligatoire', with: 'Nouveau texte')
|
||||
click_on 'Enregistrer les modifications du dossier'
|
||||
|
||||
expect(page).to have_current_path(demande_dossier_path(dossier))
|
||||
expect(page).to have_content('Nouveau texte')
|
||||
end
|
||||
end
|
||||
|
||||
RSpec.shared_examples 'the user can send messages to the instructeur' do
|
||||
let!(:commentaire) { create(:commentaire, dossier: dossier, email: 'instructeur@exemple.fr', body: 'Message envoyé à l’usager') }
|
||||
let(:message_body) { 'Message envoyé à l’instructeur' }
|
||||
|
||||
scenario js: true do
|
||||
visit dossier_path(dossier)
|
||||
|
||||
expect(page).to have_current_path(dossier_path(dossier))
|
||||
click_on 'Messagerie'
|
||||
|
||||
expect(page).to have_current_path(messagerie_dossier_path(dossier))
|
||||
expect(page).to have_content(commentaire.body)
|
||||
|
||||
fill_in 'commentaire_body', with: message_body
|
||||
click_on 'Envoyer le message'
|
||||
|
||||
expect(page).to have_current_path(messagerie_dossier_path(dossier))
|
||||
expect(page).to have_content('Message envoyé')
|
||||
expect(page).to have_content(commentaire.body)
|
||||
expect(page).to have_content(message_body)
|
||||
end
|
||||
end
|
128
spec/system/users/invite_spec.rb
Normal file
128
spec/system/users/invite_spec.rb
Normal file
|
@ -0,0 +1,128 @@
|
|||
require 'system/users/dossier_shared_examples.rb'
|
||||
|
||||
describe 'Invitations' do
|
||||
let(:owner) { create(:user) }
|
||||
let(:invited_user) { create(:user, email: 'user_invite@exemple.fr') }
|
||||
let(:procedure) { create(:simple_procedure) }
|
||||
let(:invite) { create(:invite, user: invited_user, dossier: dossier) }
|
||||
|
||||
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
|
||||
log_in(owner)
|
||||
navigate_to_brouillon(dossier)
|
||||
|
||||
fill_in 'Texte obligatoire', with: 'Some edited value'
|
||||
send_invite_to "user_invite@exemple.fr"
|
||||
|
||||
expect(page).to have_current_path(brouillon_dossier_path(dossier))
|
||||
expect(page).to have_text("Une invitation a été envoyée à user_invite@exemple.fr.")
|
||||
expect(page).to have_text("user_invite@exemple.fr")
|
||||
|
||||
# Ensure unsaved edits to the form are not lost
|
||||
expect(page).to have_field('Texte obligatoire', with: 'Some edited value')
|
||||
end
|
||||
|
||||
context 'when inviting someone without an existing account' do
|
||||
let(:invite) { create(:invite, dossier: dossier, user: nil) }
|
||||
let(:user_password) { 'my-s3cure-p4ssword' }
|
||||
|
||||
scenario 'an invited user can register using the registration link sent in the invitation email' do
|
||||
# Click the invitation link
|
||||
visit invite_path(invite, params: { email: invite.email })
|
||||
expect(page).to have_current_path(new_user_registration_path, ignore_query: true)
|
||||
expect(page).to have_field('user_email', with: invite.email)
|
||||
|
||||
# Create the account
|
||||
sign_up_with invite.email, user_password
|
||||
expect(page).to have_content('lien d’activation')
|
||||
|
||||
# Confirm the account
|
||||
# (The user should be redirected to the dossier they was invited on)
|
||||
click_confirmation_link_for invite.email
|
||||
expect(page).to have_content('Votre compte a bien été confirmé.')
|
||||
expect(page).to have_current_path(brouillon_dossier_path(dossier))
|
||||
end
|
||||
end
|
||||
|
||||
scenario 'an invited user can see and edit the draft', js: true do
|
||||
navigate_to_invited_dossier(invite)
|
||||
expect(page).to have_current_path(brouillon_dossier_path(dossier))
|
||||
|
||||
expect(page).to have_no_selector('.button.invite-user-action')
|
||||
|
||||
fill_in 'Texte obligatoire', with: 'Some edited value'
|
||||
blur
|
||||
expect(page).to have_field('Texte obligatoire', with: 'Some edited value')
|
||||
end
|
||||
|
||||
scenario 'an invited user cannot submit the draft' do
|
||||
navigate_to_invited_dossier(invite)
|
||||
expect(page).to have_current_path(brouillon_dossier_path(dossier))
|
||||
|
||||
expect(page).to have_button('Déposer le dossier', disabled: true)
|
||||
expect(page).to have_selector('.invite-cannot-submit')
|
||||
end
|
||||
end
|
||||
|
||||
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
|
||||
log_in(owner)
|
||||
navigate_to_dossier(dossier)
|
||||
|
||||
send_invite_to "user_invite@exemple.fr"
|
||||
|
||||
expect(page).to have_current_path(dossier_path(dossier))
|
||||
expect(page).to have_text("Une invitation a été envoyée à user_invite@exemple.fr.")
|
||||
expect(page).to have_text("user_invite@exemple.fr")
|
||||
end
|
||||
|
||||
context 'as an invited user' do
|
||||
before do
|
||||
navigate_to_invited_dossier(invite)
|
||||
expect(page).to have_current_path(dossier_path(invite.dossier))
|
||||
end
|
||||
|
||||
it_behaves_like 'the user can edit the submitted demande'
|
||||
it_behaves_like 'the user can send messages to the instructeur'
|
||||
end
|
||||
end
|
||||
|
||||
private
|
||||
|
||||
def log_in(user)
|
||||
visit '/'
|
||||
click_on 'Connexion'
|
||||
sign_in_with(user.email, user.password)
|
||||
expect(page).to have_current_path(dossiers_path)
|
||||
end
|
||||
|
||||
def navigate_to_brouillon(dossier)
|
||||
expect(page).to have_current_path(dossiers_path)
|
||||
click_on(dossier.id.to_s)
|
||||
expect(page).to have_current_path(brouillon_dossier_path(dossier))
|
||||
end
|
||||
|
||||
def navigate_to_dossier(dossier)
|
||||
expect(page).to have_current_path(dossiers_path)
|
||||
click_on(dossier.id.to_s)
|
||||
expect(page).to have_current_path(dossier_path(dossier))
|
||||
end
|
||||
|
||||
def navigate_to_invited_dossier(invite)
|
||||
visit invite_path(invite)
|
||||
expect(page).to have_current_path(new_user_session_path)
|
||||
sign_in_with(invited_user.email, invited_user.password)
|
||||
end
|
||||
|
||||
def send_invite_to(invited_email)
|
||||
click_on "Inviter une personne à modifier ce dossier"
|
||||
expect(page).to have_button("Envoyer une invitation", visible: true)
|
||||
|
||||
fill_in 'invite_email', with: invited_email
|
||||
click_on "Envoyer une invitation"
|
||||
end
|
||||
end
|
77
spec/system/users/linked_dropdown_spec.rb
Normal file
77
spec/system/users/linked_dropdown_spec.rb
Normal file
|
@ -0,0 +1,77 @@
|
|||
describe 'linked dropdown lists' do
|
||||
let(:password) { 'my-s3cure-p4ssword' }
|
||||
let!(:user) { create(:user, password: password) }
|
||||
|
||||
let(:list_items) do
|
||||
<<~END_OF_LIST
|
||||
--Primary 1--
|
||||
Secondary 1.1
|
||||
Secondary 1.2
|
||||
--Primary 2--
|
||||
Secondary 2.1
|
||||
Secondary 2.2
|
||||
Secondary 2.3
|
||||
END_OF_LIST
|
||||
end
|
||||
let(:type_de_champ) { build(:type_de_champ_linked_drop_down_list, libelle: 'linked dropdown', drop_down_list_value: list_items) }
|
||||
|
||||
let!(:procedure) do
|
||||
create(:procedure, :published, :for_individual, types_de_champ: [type_de_champ])
|
||||
end
|
||||
|
||||
let(:user_dossier) { user.dossiers.first }
|
||||
|
||||
scenario 'change primary value, secondary options are updated', js: true do
|
||||
log_in(user.email, password, procedure)
|
||||
|
||||
fill_individual
|
||||
|
||||
# Select a primary value
|
||||
select('Primary 2', from: primary_id_for('linked dropdown'))
|
||||
|
||||
# Secondary menu reflects chosen primary value
|
||||
expect(page).to have_select(secondary_id_for('linked dropdown'), options: ['', 'Secondary 2.1', 'Secondary 2.2', 'Secondary 2.3'])
|
||||
|
||||
# Select another primary value
|
||||
select('Primary 1', from: primary_id_for('linked dropdown'))
|
||||
|
||||
# Secondary menu gets updated
|
||||
expect(page).to have_select(secondary_id_for('linked dropdown'), options: ['', 'Secondary 1.1', 'Secondary 1.2'])
|
||||
end
|
||||
|
||||
private
|
||||
|
||||
def log_in(email, password, procedure)
|
||||
visit "/commencer/#{procedure.path}"
|
||||
click_on 'J’ai déjà un compte'
|
||||
|
||||
expect(page).to have_current_path(new_user_session_path)
|
||||
|
||||
sign_in_with(email, password)
|
||||
|
||||
expect(page).to have_current_path(commencer_path(path: procedure.path))
|
||||
click_on 'Commencer la démarche'
|
||||
|
||||
expect(page).to have_content("Données d’identité")
|
||||
expect(page).to have_current_path(identite_dossier_path(user_dossier))
|
||||
end
|
||||
|
||||
def fill_individual
|
||||
choose 'Monsieur'
|
||||
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))
|
||||
end
|
||||
|
||||
def primary_id_for(libelle)
|
||||
find(:xpath, ".//label[contains(text()[normalize-space()], '#{libelle}')]")[:for]
|
||||
end
|
||||
|
||||
def secondary_id_for(libelle)
|
||||
primary_id = primary_id_for(libelle)
|
||||
find("\##{primary_id}")
|
||||
.ancestor('.editable-champ')
|
||||
.find("[data-secondary]")['id']
|
||||
end
|
||||
end
|
152
spec/system/users/list_dossiers_spec.rb
Normal file
152
spec/system/users/list_dossiers_spec.rb
Normal file
|
@ -0,0 +1,152 @@
|
|||
describe 'user access to the list of their dossiers' do
|
||||
let(:user) { create(:user) }
|
||||
let!(:dossier_brouillon) { create(:dossier, user: user) }
|
||||
let!(:dossier_en_construction) { create(:dossier, :with_all_champs, :en_construction, user: user) }
|
||||
let!(:dossier_en_instruction) { create(:dossier, :en_instruction, user: user) }
|
||||
let!(:dossier_archived) { create(:dossier, :en_instruction, :archived, user: user) }
|
||||
let(:dossiers_per_page) { 25 }
|
||||
let(:last_updated_dossier) { dossier_en_construction }
|
||||
|
||||
before do
|
||||
@default_per_page = Dossier.default_per_page
|
||||
Dossier.paginates_per dossiers_per_page
|
||||
|
||||
last_updated_dossier.update_column(:updated_at, "19/07/2052 15:35".to_time)
|
||||
|
||||
login_as user, scope: :user
|
||||
visit dossiers_path
|
||||
end
|
||||
|
||||
after do
|
||||
Dossier.paginates_per @default_per_page
|
||||
end
|
||||
|
||||
it 'the list of dossier is displayed' do
|
||||
expect(page).to have_content(dossier_brouillon.procedure.libelle)
|
||||
expect(page).to have_content(dossier_en_construction.procedure.libelle)
|
||||
expect(page).to have_content(dossier_en_instruction.procedure.libelle)
|
||||
expect(page).to have_content(dossier_archived.procedure.libelle)
|
||||
end
|
||||
|
||||
it 'the list must be ordered by last updated' do
|
||||
expect(page.body).to match(/#{last_updated_dossier.procedure.libelle}.*#{dossier_en_instruction.procedure.libelle}/m)
|
||||
end
|
||||
|
||||
context 'when there are dossiers from other users' do
|
||||
let!(:dossier_other_user) { create(:dossier) }
|
||||
|
||||
it 'doesn’t display dossiers belonging to other users' do
|
||||
expect(page).not_to have_content(dossier_other_user.procedure.libelle)
|
||||
end
|
||||
end
|
||||
|
||||
context 'when there is more than one page' do
|
||||
let(:dossiers_per_page) { 2 }
|
||||
|
||||
scenario 'the user can navigate through the other pages' do
|
||||
expect(page).not_to have_content(dossier_en_instruction.procedure.libelle)
|
||||
page.click_link("Suivant")
|
||||
expect(page).to have_content(dossier_en_instruction.procedure.libelle)
|
||||
end
|
||||
end
|
||||
|
||||
context 'when user clicks on a projet in list' do
|
||||
before do
|
||||
page.click_on(dossier_en_construction.procedure.libelle)
|
||||
end
|
||||
|
||||
scenario 'user is redirected to dossier page' do
|
||||
expect(page).to have_current_path(dossier_path(dossier_en_construction))
|
||||
end
|
||||
end
|
||||
|
||||
describe 'deletion' do
|
||||
it 'should have links to delete dossiers' do
|
||||
expect(page).to have_link(nil, href: ask_deletion_dossier_path(dossier_brouillon))
|
||||
expect(page).to have_link(nil, href: ask_deletion_dossier_path(dossier_en_construction))
|
||||
expect(page).not_to have_link(nil, href: ask_deletion_dossier_path(dossier_en_instruction))
|
||||
end
|
||||
|
||||
context 'when user clicks on delete button', js: true do
|
||||
scenario 'the dossier is deleted' do
|
||||
within(:css, "tr[data-dossier-id=\"#{dossier_brouillon.id}\"]") do
|
||||
click_on 'Actions'
|
||||
page.accept_alert('Confirmer la suppression ?') do
|
||||
click_on 'Supprimer le dossier'
|
||||
end
|
||||
end
|
||||
|
||||
expect(page).to have_content('Votre dossier a bien été supprimé.')
|
||||
expect(page).not_to have_content(dossier_brouillon.procedure.libelle)
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
describe "recherche" do
|
||||
context "when the dossier does not exist" do
|
||||
before do
|
||||
page.find_by_id('q').set(10000000)
|
||||
click_button("Rechercher")
|
||||
end
|
||||
|
||||
it "shows an error message on the dossiers page" do
|
||||
expect(current_path).to eq(dossiers_path)
|
||||
expect(page).to have_content("Vous n’avez pas de dossiers contenant « 10000000 ».")
|
||||
end
|
||||
end
|
||||
|
||||
context "when the dossier does not belong to the user" do
|
||||
let!(:dossier_other_user) { create(:dossier) }
|
||||
|
||||
before do
|
||||
page.find_by_id('q').set(dossier_other_user.id)
|
||||
click_button("Rechercher")
|
||||
end
|
||||
|
||||
it "shows an error message on the dossiers page" do
|
||||
expect(current_path).to eq(dossiers_path)
|
||||
expect(page).to have_content("Vous n’avez pas de dossiers contenant « #{dossier_other_user.id} ».")
|
||||
end
|
||||
end
|
||||
|
||||
context "when the dossier belongs to the user" do
|
||||
before do
|
||||
page.find_by_id('q').set(dossier_en_construction.id)
|
||||
click_button("Rechercher")
|
||||
end
|
||||
|
||||
it "redirects to the dossier page" do
|
||||
expect(current_path).to eq(dossier_path(dossier_en_construction))
|
||||
end
|
||||
end
|
||||
|
||||
context "when user search for something inside the dossier" do
|
||||
let(:dossier_en_construction2) { create(:dossier, :with_all_champs, :en_construction, user: user) }
|
||||
before do
|
||||
page.find_by_id('q').set(dossier_en_construction.champs.first.value)
|
||||
end
|
||||
|
||||
context 'when it only matches one dossier' do
|
||||
before do
|
||||
click_button("Rechercher")
|
||||
end
|
||||
it "redirects to the dossier page" do
|
||||
expect(current_path).to eq(dossier_path(dossier_en_construction))
|
||||
end
|
||||
end
|
||||
|
||||
context 'when it matches multiple dossier' do
|
||||
before do
|
||||
dossier_en_construction2.champs.first.update(value: dossier_en_construction.champs.first.value)
|
||||
click_button("Rechercher")
|
||||
end
|
||||
|
||||
it "redirects to the search results" do
|
||||
expect(current_path).to eq(recherche_dossiers_path)
|
||||
expect(page).to have_content(dossier_en_construction.id)
|
||||
expect(page).to have_content(dossier_en_construction2.id)
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
111
spec/system/users/managing_password_spec.rb
Normal file
111
spec/system/users/managing_password_spec.rb
Normal file
|
@ -0,0 +1,111 @@
|
|||
describe 'Managing password:' do
|
||||
context 'for simple users' do
|
||||
let(:user) { create(:user) }
|
||||
let(:new_password) { 'a simple password' }
|
||||
|
||||
scenario 'a simple user can reset their password' do
|
||||
visit root_path
|
||||
click_on 'Connexion'
|
||||
click_on 'Mot de passe oublié ?'
|
||||
expect(page).to have_current_path(new_user_password_path)
|
||||
|
||||
fill_in 'Email', with: user.email
|
||||
perform_enqueued_jobs do
|
||||
click_on 'Demander un nouveau mot de passe'
|
||||
end
|
||||
expect(page).to have_text 'Nous vous avons envoyé un email'
|
||||
expect(page).to have_text user.email
|
||||
|
||||
click_reset_password_link_for user.email
|
||||
expect(page).to have_content 'Changement de mot de passe'
|
||||
|
||||
fill_in 'user_password', with: new_password
|
||||
fill_in 'user_password_confirmation', with: new_password
|
||||
click_on 'Changer le mot de passe'
|
||||
expect(page).to have_content('Votre mot de passe a bien été modifié.')
|
||||
end
|
||||
end
|
||||
|
||||
context 'for admins' do
|
||||
let(:administrateur) { create(:administrateur) }
|
||||
let(:user) { administrateur.user }
|
||||
let(:weak_password) { '12345678' }
|
||||
let(:strong_password) { 'a new, long, and complicated password!' }
|
||||
|
||||
scenario 'an admin can reset their password', js: true do
|
||||
visit root_path
|
||||
click_on 'Connexion'
|
||||
click_on 'Mot de passe oublié ?'
|
||||
expect(page).to have_current_path(new_user_password_path)
|
||||
|
||||
fill_in 'Email', with: user.email
|
||||
perform_enqueued_jobs do
|
||||
click_on 'Demander un nouveau mot de passe'
|
||||
end
|
||||
expect(page).to have_text 'Nous vous avons envoyé un email'
|
||||
expect(page).to have_text user.email
|
||||
|
||||
click_reset_password_link_for user.email
|
||||
|
||||
expect(page).to have_content 'Changement de mot de passe'
|
||||
|
||||
fill_in 'user_password', with: weak_password
|
||||
fill_in 'user_password_confirmation', with: weak_password
|
||||
expect(page).to have_text('Mot de passe très vulnérable')
|
||||
expect(page).to have_button('Changer le mot de passe', disabled: true)
|
||||
|
||||
fill_in 'user_password', with: strong_password
|
||||
fill_in 'user_password_confirmation', with: strong_password
|
||||
expect(page).to have_text('Mot de passe suffisamment fort et sécurisé')
|
||||
expect(page).to have_button('Changer le mot de passe', disabled: false)
|
||||
|
||||
click_on 'Changer le mot de passe'
|
||||
expect(page).to have_content('Votre mot de passe a bien été modifié.')
|
||||
end
|
||||
end
|
||||
|
||||
context 'for super-admins' do
|
||||
let(:super_admin) { create(:super_admin) }
|
||||
let(:weak_password) { '12345678' }
|
||||
let(:strong_password) { 'a new, long, and complicated password!' }
|
||||
|
||||
scenario 'a super-admin can reset their password', js: true 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
|
||||
perform_enqueued_jobs do
|
||||
click_on 'Demander un nouveau mot de passe'
|
||||
end
|
||||
expect(page).to have_text 'vous recevrez un lien vous permettant de récupérer votre mot de passe'
|
||||
|
||||
click_reset_password_link_for super_admin.email
|
||||
|
||||
expect(page).to have_content 'Changement de mot de passe'
|
||||
|
||||
fill_in 'super_admin_password', with: weak_password
|
||||
fill_in 'super_admin_password_confirmation', with: weak_password
|
||||
expect(page).to have_text('Mot de passe très vulnérable')
|
||||
expect(page).to have_button('Changer le mot de passe', disabled: true)
|
||||
|
||||
fill_in 'super_admin_password', with: strong_password
|
||||
fill_in 'super_admin_password_confirmation', with: strong_password
|
||||
expect(page).to have_text('Mot de passe suffisamment fort et sécurisé')
|
||||
expect(page).to have_button('Changer le mot de passe', disabled: false)
|
||||
|
||||
click_on 'Changer le mot de passe'
|
||||
expect(page).to have_content('Votre mot de passe a bien été modifié.')
|
||||
end
|
||||
end
|
||||
|
||||
scenario 'the password reset token has expired' do
|
||||
visit edit_user_password_path(reset_password_token: 'invalid-password-token')
|
||||
expect(page).to have_content 'Changement de mot de passe'
|
||||
|
||||
fill_in 'user_password', with: 'SomePassword'
|
||||
fill_in 'user_password_confirmation', with: 'SomePassword'
|
||||
click_on 'Changer le mot de passe'
|
||||
expect(page).to have_content('Votre lien de nouveau mot de passe a expiré')
|
||||
end
|
||||
end
|
15
spec/system/users/sign_out_spec.rb
Normal file
15
spec/system/users/sign_out_spec.rb
Normal file
|
@ -0,0 +1,15 @@
|
|||
describe 'Sign out' do
|
||||
context 'when a user is logged in' do
|
||||
let(:user) { create(:administrateur).user }
|
||||
|
||||
before { login_as user, scope: :user }
|
||||
|
||||
scenario 'he can sign out' do
|
||||
visit dossiers_path
|
||||
|
||||
click_on 'Se déconnecter'
|
||||
|
||||
expect(page).to have_current_path(root_path)
|
||||
end
|
||||
end
|
||||
end
|
147
spec/system/users/sign_up_spec.rb
Normal file
147
spec/system/users/sign_up_spec.rb
Normal file
|
@ -0,0 +1,147 @@
|
|||
describe 'Signing up:' do
|
||||
let(:user_email) { generate :user_email }
|
||||
let(:user_password) { 'my-s3cure-p4ssword' }
|
||||
let(:procedure) { create :simple_procedure, :with_service }
|
||||
|
||||
scenario 'a new user can sign-up from scratch' do
|
||||
visit new_user_registration_path
|
||||
|
||||
sign_up_with user_email, user_password
|
||||
expect(page).to have_content "nous avons besoin de vérifier votre adresse #{user_email}"
|
||||
|
||||
click_confirmation_link_for user_email
|
||||
expect(page).to have_content('Votre compte a bien été confirmé.')
|
||||
expect(page).to have_current_path dossiers_path
|
||||
end
|
||||
|
||||
context 'when the user makes a typo in their email address' do
|
||||
let(:procedure) { create :simple_procedure, :with_service }
|
||||
|
||||
before do
|
||||
visit commencer_path(path: procedure.path)
|
||||
click_on "Créer un compte #{APPLICATION_NAME}"
|
||||
expect(page).to have_selector('.suspect-email', visible: false)
|
||||
fill_in 'Email', with: 'bidou@yahoo.rf'
|
||||
fill_in 'Mot de passe', with: '12345'
|
||||
end
|
||||
|
||||
scenario 'they can accept the suggestion', js: true do
|
||||
expect(page).to have_selector('.suspect-email', visible: true)
|
||||
click_on 'Oui'
|
||||
expect(page).to have_field("Email", :with => 'bidou@yahoo.fr')
|
||||
expect(page).to have_selector('.suspect-email', visible: false)
|
||||
end
|
||||
|
||||
scenario 'they can discard the suggestion', js: true do
|
||||
expect(page).to have_selector('.suspect-email', visible: true)
|
||||
click_on 'Non'
|
||||
expect(page).to have_field("Email", :with => 'bidou@yahoo.rf')
|
||||
expect(page).to have_selector('.suspect-email', visible: false)
|
||||
end
|
||||
|
||||
scenario 'they can fix the typo themselves', js: true do
|
||||
expect(page).to have_selector('.suspect-email', visible: true)
|
||||
fill_in 'Email', with: 'bidou@yahoo.fr'
|
||||
blur
|
||||
expect(page).to have_selector('.suspect-email', visible: false)
|
||||
end
|
||||
end
|
||||
|
||||
scenario 'a new user can’t sign-up with too short password when visiting a procedure' do
|
||||
visit commencer_path(path: procedure.path)
|
||||
click_on "Créer un compte #{APPLICATION_NAME}"
|
||||
|
||||
expect(page).to have_current_path new_user_registration_path
|
||||
sign_up_with user_email, '1234567'
|
||||
expect(page).to have_current_path user_registration_path
|
||||
expect(page).to have_content 'Le mot de passe est trop court'
|
||||
|
||||
# Then with a good password
|
||||
sign_up_with user_email, user_password
|
||||
expect(page).to have_current_path new_user_confirmation_path user: { email: user_email }
|
||||
expect(page).to have_content "nous avons besoin de vérifier votre adresse #{user_email}"
|
||||
end
|
||||
|
||||
context 'when visiting a procedure' do
|
||||
let(:procedure) { create :simple_procedure, :with_service }
|
||||
|
||||
scenario 'a new user can sign-up and fill the procedure' do
|
||||
visit commencer_path(path: procedure.path)
|
||||
|
||||
click_on 'Créer un compte'
|
||||
expect(page).to have_current_path new_user_registration_path
|
||||
expect(page).to have_procedure_description(procedure)
|
||||
|
||||
sign_up_with user_email, user_password
|
||||
expect(page).to have_content "nous avons besoin de vérifier votre adresse #{user_email}"
|
||||
|
||||
click_confirmation_link_for(user_email, in_another_browser: true)
|
||||
|
||||
# After confirmation, the user is redirected to the procedure they were initially starting
|
||||
# (even when confirming the account in another browser).
|
||||
expect(page).to have_current_path(commencer_path(path: procedure.path))
|
||||
expect(page).to have_content I18n.t('devise.confirmations.confirmed')
|
||||
click_on 'Commencer la démarche'
|
||||
|
||||
expect(page).to have_current_path identite_dossier_path(procedure.reload.dossiers.last)
|
||||
expect(page).to have_procedure_description(procedure)
|
||||
end
|
||||
end
|
||||
|
||||
context 'when the user is not confirmed yet' do
|
||||
before do
|
||||
create(:user, :unconfirmed, email: user_email, password: user_password)
|
||||
end
|
||||
|
||||
scenario 'the email confirmation page is displayed' do
|
||||
visit commencer_path(path: procedure.path)
|
||||
click_on 'Créer un compte'
|
||||
|
||||
sign_up_with user_email, user_password
|
||||
|
||||
# The same page than for initial sign-ups is displayed, to avoid leaking informations
|
||||
# about the account existence.
|
||||
expect(page).to have_content "nous avons besoin de vérifier votre adresse #{user_email}"
|
||||
|
||||
# The confirmation email is sent again
|
||||
confirmation_email = open_email(user_email)
|
||||
expect(confirmation_email.body).to have_text('Pour activer votre compte')
|
||||
|
||||
click_confirmation_link_for(user_email, in_another_browser: true)
|
||||
|
||||
# After confirmation, the user is redirected to the procedure they were initially starting
|
||||
# (even when confirming the account in another browser).
|
||||
expect(page).to have_current_path(commencer_path(path: procedure.path))
|
||||
expect(page).to have_content I18n.t('devise.confirmations.confirmed')
|
||||
expect(page).to have_content 'Commencer la démarche'
|
||||
end
|
||||
end
|
||||
|
||||
context 'when the user already has a confirmed account' do
|
||||
before do
|
||||
create(:user, email: user_email, password: user_password)
|
||||
end
|
||||
|
||||
scenario 'they get a warning email, containing a link to the procedure' do
|
||||
visit commencer_path(path: procedure.path)
|
||||
click_on 'Créer un compte'
|
||||
|
||||
sign_up_with user_email, user_password
|
||||
|
||||
# The same page than for initial sign-ups is displayed, to avoid leaking informations
|
||||
# about the accound existence.
|
||||
expect(page).to have_content "nous avons besoin de vérifier votre adresse #{user_email}"
|
||||
|
||||
# A warning email is sent
|
||||
warning_email = open_email(user_email)
|
||||
expect(warning_email.body).to have_text('Votre compte existe déjà')
|
||||
|
||||
# When clicking the main button, the user is redirected directly to
|
||||
# the sign-in page for the procedure they were initially starting.
|
||||
click_procedure_sign_in_link_for user_email
|
||||
|
||||
expect(page).to have_current_path new_user_session_path
|
||||
expect(page).to have_procedure_description(procedure)
|
||||
end
|
||||
end
|
||||
end
|
32
spec/system/users/transfer_dossier_spec.rb
Normal file
32
spec/system/users/transfer_dossier_spec.rb
Normal file
|
@ -0,0 +1,32 @@
|
|||
describe 'Transfer dossier:' do
|
||||
let(:user) { create(:user) }
|
||||
let(:other_user) { create(:user) }
|
||||
let(:procedure) { create(:simple_procedure) }
|
||||
let(:dossier) { create(:dossier, :en_construction, :with_individual, :with_commentaires, user: user, procedure: procedure) }
|
||||
|
||||
before do
|
||||
dossier
|
||||
login_as user, scope: :user
|
||||
visit dossiers_path
|
||||
end
|
||||
|
||||
scenario 'the user can transfer dossier to another user' do
|
||||
within(:css, "tr[data-dossier-id=\"#{dossier.id}\"]") do
|
||||
click_on 'Actions'
|
||||
click_on 'Transferer le dossier'
|
||||
end
|
||||
|
||||
expect(page).to have_current_path(transferer_dossier_path(dossier))
|
||||
expect(page).to have_content("Transferer le dossier en construction nº #{dossier.id}")
|
||||
fill_in 'Email du compte destinataire', with: other_user.email
|
||||
click_on 'Envoyer la demande de transfert'
|
||||
|
||||
logout
|
||||
login_as other_user, scope: :user
|
||||
visit dossiers_path
|
||||
|
||||
expect(page).to have_content("Demande de transfert Nº #{dossier.reload.transfer.id} envoyé par #{user.email}")
|
||||
click_on 'Accepter'
|
||||
expect(page).to have_current_path(dossiers_path)
|
||||
end
|
||||
end
|
Loading…
Add table
Add a link
Reference in a new issue