Fix editeur de champs specs (#4577)
Administrateur : amélioration de la stabilité de l'éditeur de champs
This commit is contained in:
commit
752bd50e05
10 changed files with 117 additions and 75 deletions
|
@ -12,12 +12,7 @@ function TypeDeChamps({ state: rootState, typeDeChamps }) {
|
|||
typeDeChamps
|
||||
});
|
||||
|
||||
if (state.typeDeChamps.length === 0) {
|
||||
dispatch({
|
||||
type: 'addFirstTypeDeChamp',
|
||||
done: () => dispatch({ type: 'refresh' })
|
||||
});
|
||||
}
|
||||
const hasUnsavedChamps = state.typeDeChamps.some(tdc => tdc.id == undefined);
|
||||
|
||||
return (
|
||||
<div className="champs-editor">
|
||||
|
@ -39,10 +34,18 @@ function TypeDeChamps({ state: rootState, typeDeChamps }) {
|
|||
/>
|
||||
))}
|
||||
</SortableContainer>
|
||||
{state.typeDeChamps.length === 0 && (
|
||||
<h2>
|
||||
<FontAwesomeIcon icon="arrow-circle-down" />
|
||||
Cliquez sur le bouton « Ajouter un champ » pour
|
||||
créer votre premier champ.
|
||||
</h2>
|
||||
)}
|
||||
<div className="footer"> </div>
|
||||
<div className="buttons">
|
||||
<button
|
||||
className="button"
|
||||
disabled={hasUnsavedChamps}
|
||||
onClick={() =>
|
||||
dispatch({
|
||||
type: 'addNewTypeDeChamp',
|
||||
|
|
|
@ -5,6 +5,7 @@ import {
|
|||
faArrowDown,
|
||||
faArrowsAltV,
|
||||
faArrowUp,
|
||||
faArrowCircleDown,
|
||||
faPlus,
|
||||
faTrash
|
||||
} from '@fortawesome/free-solid-svg-icons';
|
||||
|
@ -13,7 +14,14 @@ import Flash from './Flash';
|
|||
import OperationsQueue from './OperationsQueue';
|
||||
import TypeDeChamps from './components/TypeDeChamps';
|
||||
|
||||
library.add(faArrowDown, faArrowsAltV, faArrowUp, faPlus, faTrash);
|
||||
library.add(
|
||||
faArrowDown,
|
||||
faArrowsAltV,
|
||||
faArrowUp,
|
||||
faArrowCircleDown,
|
||||
faPlus,
|
||||
faTrash
|
||||
);
|
||||
|
||||
class TypesDeChampEditor extends Component {
|
||||
constructor(props) {
|
||||
|
|
|
@ -11,8 +11,6 @@ export default function typeDeChampsReducer(state, { type, params, done }) {
|
|||
switch (type) {
|
||||
case 'addNewTypeDeChamp':
|
||||
return addNewTypeDeChamp(state, state.typeDeChamps, done);
|
||||
case 'addFirstTypeDeChamp':
|
||||
return addFirstTypeDeChamp(state, state.typeDeChamps, done);
|
||||
case 'addNewRepetitionTypeDeChamp':
|
||||
return addNewRepetitionTypeDeChamp(
|
||||
state,
|
||||
|
@ -98,19 +96,6 @@ function addNewRepetitionTypeDeChamp(state, typeDeChamps, typeDeChamp, done) {
|
|||
);
|
||||
}
|
||||
|
||||
function addFirstTypeDeChamp(state, typeDeChamps, done) {
|
||||
const typeDeChamp = { ...state.defaultTypeDeChampAttributes, order_place: 0 };
|
||||
|
||||
createTypeDeChampOperation(typeDeChamp, state.queue)
|
||||
.then(() => done())
|
||||
.catch(message => state.flash.error(message));
|
||||
|
||||
return {
|
||||
...state,
|
||||
typeDeChamps: [...typeDeChamps, typeDeChamp]
|
||||
};
|
||||
}
|
||||
|
||||
function updateTypeDeChamp(
|
||||
state,
|
||||
typeDeChamps,
|
||||
|
@ -223,10 +208,14 @@ function getUpdateHandler(typeDeChamp, { queue, flash }) {
|
|||
function findItemToInsertAfter() {
|
||||
const target = getLastVisibleTypeDeChamp();
|
||||
|
||||
return {
|
||||
target,
|
||||
index: parseInt(target.dataset.index) + 1
|
||||
};
|
||||
if (target) {
|
||||
return {
|
||||
target,
|
||||
index: parseInt(target.dataset.index) + 1
|
||||
};
|
||||
} else {
|
||||
return null;
|
||||
}
|
||||
}
|
||||
|
||||
function getLastVisibleTypeDeChamp() {
|
||||
|
|
|
@ -69,14 +69,12 @@ feature 'As an administrateur I wanna create a new procedure', js: true do
|
|||
page.refresh
|
||||
expect(page).to have_current_path(champs_procedure_path(Procedure.last))
|
||||
|
||||
expect(page).to have_selector('#champ-0-libelle')
|
||||
add_champ(remove_flash_message: true)
|
||||
fill_in 'champ-0-libelle', with: 'libelle de champ'
|
||||
blur
|
||||
expect(page).to have_content('Formulaire enregistré')
|
||||
|
||||
within '.buttons' do
|
||||
click_on 'Ajouter un champ'
|
||||
end
|
||||
add_champ
|
||||
expect(page).to have_selector('#champ-1-libelle')
|
||||
|
||||
click_on Procedure.last.libelle
|
||||
|
@ -91,6 +89,7 @@ feature 'As an administrateur I wanna create a new procedure', js: true do
|
|||
scenario 'After adding champ and file, make publication' do
|
||||
page.refresh
|
||||
|
||||
add_champ(remove_flash_message: true)
|
||||
fill_in 'champ-0-libelle', with: 'libelle de champ'
|
||||
blur
|
||||
expect(page).to have_content('Formulaire enregistré')
|
||||
|
|
|
@ -10,14 +10,8 @@ feature 'As an administrateur I can edit types de champ', js: true do
|
|||
end
|
||||
|
||||
it "Add a new champ" do
|
||||
page.accept_alert do
|
||||
click_on 'Supprimer'
|
||||
end
|
||||
add_champ
|
||||
|
||||
within '.buttons' do
|
||||
click_on 'Ajouter un champ'
|
||||
end
|
||||
expect(page).to have_selector('#champ-0-libelle')
|
||||
fill_in 'champ-0-libelle', with: 'libellé de champ'
|
||||
blur
|
||||
expect(page).to have_content('Formulaire enregistré')
|
||||
|
@ -26,65 +20,64 @@ feature 'As an administrateur I can edit types de champ', js: true do
|
|||
within '.buttons' do
|
||||
click_on 'Enregistrer'
|
||||
end
|
||||
|
||||
expect(page).to have_content('Formulaire enregistré')
|
||||
end
|
||||
|
||||
it "Add multiple champs" do
|
||||
within '.buttons' do
|
||||
click_on 'Ajouter un champ'
|
||||
click_on 'Ajouter un champ'
|
||||
click_on 'Ajouter un champ'
|
||||
end
|
||||
page.refresh
|
||||
# Champs are created when clicking the 'Add field' button
|
||||
add_champs(count: 3)
|
||||
|
||||
# Champs are automatically saved
|
||||
expect(page).to have_button('Ajouter un champ', disabled: false)
|
||||
page.refresh
|
||||
expect(page).to have_selector('.type-de-champ', count: 3)
|
||||
|
||||
# Multiple champs can be edited
|
||||
fill_in 'champ-0-libelle', with: 'libellé de champ 0'
|
||||
fill_in 'champ-1-libelle', with: 'libellé de champ 1'
|
||||
blur
|
||||
expect(page).to have_content('Formulaire enregistré')
|
||||
|
||||
expect(page).to have_selector('#champ-0-libelle')
|
||||
expect(page).to have_selector('#champ-1-libelle')
|
||||
expect(page).to have_selector('#champ-2-libelle')
|
||||
expect(page).to have_selector('#champ-3-libelle')
|
||||
|
||||
# Champs can be deleted
|
||||
within '.type-de-champ[data-index="2"]' do
|
||||
page.accept_alert do
|
||||
click_on 'Supprimer'
|
||||
end
|
||||
end
|
||||
expect(page).not_to have_selector('#champ-2-libelle')
|
||||
|
||||
expect(page).not_to have_selector('#champ-3-libelle')
|
||||
fill_in 'champ-2-libelle', with: 'libellé de champ 2'
|
||||
fill_in 'champ-1-libelle', with: 'edited libellé de champ 1'
|
||||
blur
|
||||
expect(page).to have_content('Formulaire enregistré')
|
||||
|
||||
expect(page).to have_content('Supprimer', count: 3)
|
||||
expect(page).to have_content('Supprimer', count: 2)
|
||||
|
||||
page.refresh
|
||||
|
||||
expect(page).to have_content('Supprimer', count: 3)
|
||||
expect(page).to have_content('Supprimer', count: 2)
|
||||
end
|
||||
|
||||
it "Remove champs" do
|
||||
add_champ(remove_flash_message: true)
|
||||
|
||||
fill_in 'champ-0-libelle', with: 'libellé de champ'
|
||||
blur
|
||||
expect(page).to have_content('Formulaire enregistré')
|
||||
page.refresh
|
||||
|
||||
page.accept_alert do
|
||||
click_on 'Supprimer'
|
||||
end
|
||||
expect(page).to have_content('Formulaire enregistré')
|
||||
expect(page).to have_content('Supprimer', count: 1)
|
||||
expect(page).to have_content('Supprimer', count: 0)
|
||||
page.refresh
|
||||
|
||||
expect(page).to have_content('Supprimer', count: 1)
|
||||
expect(page).to have_content('Supprimer', count: 0)
|
||||
end
|
||||
|
||||
it "Only add valid champs" do
|
||||
expect(page).to have_selector('#champ-0-description')
|
||||
add_champ(remove_flash_message: true)
|
||||
|
||||
fill_in 'champ-0-libelle', with: ''
|
||||
fill_in 'champ-0-description', with: 'déscription du champ'
|
||||
fill_in 'champ-0-description', with: 'description du champ'
|
||||
blur
|
||||
expect(page).not_to have_content('Formulaire enregistré')
|
||||
|
||||
|
@ -94,7 +87,8 @@ feature 'As an administrateur I can edit types de champ', js: true do
|
|||
end
|
||||
|
||||
it "Add repetition champ" do
|
||||
expect(page).to have_selector('#champ-0-libelle')
|
||||
add_champ(remove_flash_message: true)
|
||||
|
||||
select('Bloc répétable', from: 'champ-0-type_champ')
|
||||
fill_in 'champ-0-libelle', with: 'libellé de champ'
|
||||
blur
|
||||
|
@ -124,6 +118,8 @@ feature 'As an administrateur I can edit types de champ', js: true do
|
|||
end
|
||||
|
||||
it "Add carte champ" do
|
||||
add_champ
|
||||
|
||||
select('Carte', from: 'champ-0-type_champ')
|
||||
fill_in 'champ-0-libelle', with: 'Libellé de champ carte', fill_options: { clear: :backspace }
|
||||
check 'Quartiers prioritaires'
|
||||
|
@ -140,6 +136,8 @@ feature 'As an administrateur I can edit types de champ', js: true do
|
|||
end
|
||||
|
||||
it "Add dropdown champ" do
|
||||
add_champ
|
||||
|
||||
select('Menu déroulant', from: 'champ-0-type_champ')
|
||||
fill_in 'champ-0-libelle', with: 'Libellé de champ menu déroulant', fill_options: { clear: :backspace }
|
||||
fill_in 'champ-0-drop_down_list_value', with: 'Un menu', fill_options: { clear: :backspace }
|
||||
|
|
|
@ -34,7 +34,7 @@ feature 'Signin in:' do
|
|||
scenario 'an existing user can sign-in and fill the procedure' do
|
||||
click_on 'J’ai déjà un compte'
|
||||
expect(page).to have_current_path new_user_session_path
|
||||
expect_page_to_have_procedure_description(procedure)
|
||||
expect(page).to have_procedure_description(procedure)
|
||||
|
||||
sign_in_with user.email, password
|
||||
|
||||
|
@ -42,7 +42,7 @@ feature 'Signin in:' do
|
|||
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)
|
||||
expect(page).to have_procedure_description(procedure)
|
||||
expect(page).to have_content "Données d'identité"
|
||||
end
|
||||
end
|
||||
|
|
|
@ -20,7 +20,7 @@ feature 'Creating a new dossier:' do
|
|||
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)
|
||||
expect(page).to have_procedure_description(procedure)
|
||||
|
||||
fill_in 'individual_nom', with: 'Nom'
|
||||
fill_in 'individual_prenom', with: 'Prenom'
|
||||
|
@ -82,7 +82,7 @@ feature 'Creating a new dossier:' do
|
|||
click_on 'Commencer la démarche'
|
||||
|
||||
expect(page).to have_current_path siret_dossier_path(dossier)
|
||||
expect_page_to_have_procedure_description(procedure)
|
||||
expect(page).to have_procedure_description(procedure)
|
||||
|
||||
fill_in 'Numéro SIRET', with: siret
|
||||
click_on 'Valider'
|
||||
|
@ -99,7 +99,7 @@ feature 'Creating a new dossier:' do
|
|||
click_on 'Commencer la démarche'
|
||||
|
||||
expect(page).to have_current_path(siret_dossier_path(dossier))
|
||||
expect_page_to_have_procedure_description(procedure)
|
||||
expect(page).to have_procedure_description(procedure)
|
||||
|
||||
fill_in 'Numéro SIRET', with: '0000'
|
||||
click_on 'Valider'
|
||||
|
|
|
@ -42,7 +42,7 @@ feature 'Signing up:' do
|
|||
scenario 'a new user can sign-up and fill the procedure' do
|
||||
click_on 'Créer un compte'
|
||||
expect(page).to have_current_path new_user_registration_path
|
||||
expect_page_to_have_procedure_description(procedure)
|
||||
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}"
|
||||
|
@ -54,7 +54,7 @@ feature 'Signing up:' do
|
|||
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)
|
||||
expect(page).to have_procedure_description(procedure)
|
||||
end
|
||||
end
|
||||
|
||||
|
|
|
@ -55,14 +55,6 @@ module FeatureHelpers
|
|||
visit "/users/confirmation?#{token_params}"
|
||||
end
|
||||
|
||||
def expect_page_to_have_procedure_description(procedure)
|
||||
# Procedure context on the page
|
||||
expect(page).to have_content(procedure.libelle)
|
||||
expect(page).to have_content(procedure.description)
|
||||
# Procedure contact infos in the footer
|
||||
expect(page).to have_content(procedure.service.email)
|
||||
end
|
||||
|
||||
def click_reset_password_link_for(email)
|
||||
reset_password_email = open_email(email)
|
||||
token_params = reset_password_email.body.match(/reset_password_token=[^"]+/)
|
||||
|
@ -70,6 +62,24 @@ module FeatureHelpers
|
|||
visit "/users/password/edit?#{token_params}"
|
||||
end
|
||||
|
||||
# Add a new type de champ in the procedure editor
|
||||
def add_champ(options = {})
|
||||
add_champs(options)
|
||||
end
|
||||
|
||||
# Add several new type de champ in the procedure editor
|
||||
def add_champs(count: 1, remove_flash_message: false)
|
||||
within '.buttons' do
|
||||
count.times { click_on 'Ajouter un champ' }
|
||||
end
|
||||
|
||||
if remove_flash_message
|
||||
expect(page).to have_button('Ajouter un champ', disabled: false)
|
||||
expect(page).to have_content('Formulaire enregistré')
|
||||
execute_script("document.querySelector('#flash_message').remove();")
|
||||
end
|
||||
end
|
||||
|
||||
def blur
|
||||
page.find('body').click
|
||||
end
|
||||
|
@ -85,6 +95,32 @@ module FeatureHelpers
|
|||
value
|
||||
end
|
||||
end
|
||||
|
||||
# Keep the brower window open after a test success of failure, to
|
||||
# allow inspecting the page or the console.
|
||||
#
|
||||
# Usage:
|
||||
# 1. Disable the 'headless' mode in `spec_helper.rb`
|
||||
# 2. Call `leave_browser_open` at the beginning of your scenario
|
||||
def leave_browser_open
|
||||
Selenium::WebDriver::Chrome::Service.class_eval do
|
||||
def stop
|
||||
STDOUT.puts "#{self.class}#stop is a no-op, because leave_browser_open is enabled"
|
||||
end
|
||||
end
|
||||
|
||||
Selenium::WebDriver::Driver.class_eval do
|
||||
def quit
|
||||
STDOUT.puts "#{self.class}#quit is a no-op, because leave_browser_open is enabled"
|
||||
end
|
||||
end
|
||||
|
||||
Capybara::Selenium::Driver.class_eval do
|
||||
def reset!
|
||||
STDOUT.puts "#{self.class}#reset! is a no-op, because leave_browser_open is enabled"
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
RSpec.configure do |config|
|
||||
|
|
9
spec/support/feature_matchers.rb
Normal file
9
spec/support/feature_matchers.rb
Normal file
|
@ -0,0 +1,9 @@
|
|||
module Capybara
|
||||
class Session
|
||||
# Find the description of a procedure on the page
|
||||
# Usage: expect(page).to have_procedure_description(procedure)
|
||||
def has_procedure_description?(procedure)
|
||||
has_content?(procedure.libelle) && has_content?(procedure.description) && has_content?(procedure.service.email)
|
||||
end
|
||||
end
|
||||
end
|
Loading…
Reference in a new issue