Skip to content

Commit

Permalink
Merge pull request #1370 from navikt/address-error-message
Browse files Browse the repository at this point in the history
Rewrite error messages
  • Loading branch information
lotorvik authored Dec 2, 2024
2 parents 359bd19 + 0537460 commit 0f67ddc
Show file tree
Hide file tree
Showing 17 changed files with 178 additions and 133 deletions.
7 changes: 7 additions & 0 deletions .github/workflows/cypress-tests.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -35,6 +35,13 @@ jobs:
config: video=false
env:
FYLLUT_BACKEND_LOGLEVEL: ${{ runner.debug == '1' && 'debug' || 'error' }}
- name: Upload screenshots
uses: actions/upload-artifact@v4
if: failure()
with:
name: cypress-screenshots
path: ${{ github.workspace }}/packages/fyllut/cypress/screenshots/*


cypress-run-bygger:
runs-on: ubuntu-latest-8-cores
Expand Down
5 changes: 4 additions & 1 deletion packages/bygger/cypress/e2e/form-builder.spec.cy.ts
Original file line number Diff line number Diff line change
Expand Up @@ -173,8 +173,11 @@ describe('Form Builder', () => {
cy.get('[data-testid="editorSaveButton"]').click();
});

// This error comes from Component.highlightInvalidComponents in Formio
it('should show error message stating duplicate API key', () => {
cy.findByText('API Key is not unique: personopplysninger').should('exist');
// We get one error message on TextField and one from formio in Panel.
// The Panel component uses old templates, that is the reason the error is not correct format.
cy.findAllByText('API Key is not unique: personopplysninger').should('have.length', 2);
});

it('should not remove panel when changing components key to something else', () => {
Expand Down
2 changes: 2 additions & 0 deletions packages/bygger/src/formio/builder/WebformBuilder.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -56,6 +56,8 @@ class WebformBuilder extends NavFormioJs.Builders.builders.webform {

super.editComponent(component, parent, isNew, isJsonEdit, original, flags);

this.editForm.editFormDialog = true;

if (isJsonEdit) {
this.editForm.form = {
...this.editForm.form,
Expand Down
2 changes: 2 additions & 0 deletions packages/bygger/src/formio/builder/WizardBuilder.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -87,6 +87,8 @@ class WizardBuilder extends NavFormioJs.Builders.builders.wizard {

super.editComponent(component, parent, isNew, isJsonEdit, original, flags);

this.editForm.editFormDialog = true;

if (isJsonEdit) {
this.editForm.form = {
...this.editForm.form,
Expand Down
2 changes: 2 additions & 0 deletions packages/fyllut/cypress/e2e/components/datagrid.cy.ts
Original file line number Diff line number Diff line change
Expand Up @@ -23,13 +23,15 @@ describe('Datagrid', () => {
cy.visit('/fyllut/datagridReact?sub=digital');
cy.defaultWaits();
cy.clickStart();
cy.wait('@createMellomlagring');
cy.findByRole('checkbox', { name: 'Avkryssingsboks inni datagrid (valgfritt)' }).check();
cy.findByRole('textbox', { name: 'Dato inni datagrid' }).type('15.01.2022');
cy.findByRole('combobox', { name: 'Nedtrekksmeny inni datagrid' }).type('F{enter}');
cy.findByRole('radio', { name: 'Nei' }).check();
cy.findByRole('textbox', { name: 'Tekstområde inni datagrid' }).type('Lorem Ipsum');
cy.findByRole('textbox', { name: 'Tekstfelt inni datagrid' }).type('Hund');
cy.clickSaveAndContinue();
cy.wait('@updateMellomlagring');
cy.findByRoleWhenAttached('heading', { level: 2, name: 'Oppsummering' }).should('exist');
cy.findByRoleWhenAttached('link', { name: TEXTS.grensesnitt.summaryPage.editAnswers }).should('exist').click();

Expand Down
117 changes: 64 additions & 53 deletions packages/fyllut/cypress/e2e/components/driving-list.cy.ts
Original file line number Diff line number Diff line change
Expand Up @@ -20,54 +20,9 @@ describe('DrivingList', () => {
cy.configMocksServer();
});

beforeEach(() => {
cy.defaultIntercepts();
cy.defaultInterceptsMellomlagring();
cy.defaultInterceptsExternal();
cy.mocksRestoreRouteVariants();
});

after(() => {
cy.mocksRestoreRouteVariants();
});

describe('paper', () => {
it('should fill out form and show data in summary', () => {
cy.visit(`/fyllut/testdrivinglist?sub=paper`);
cy.defaultWaits();
cy.clickStart();

cy.findByRole('textbox', { name: DATE_PICKER_LABEL }).should('exist').type('15.05.2023{esc}');
cy.findByRole('group', { name: PARKING_LABEL })
.should('exist')
.within(() => {
cy.findAllByRole('radio').should('have.length', 2);
cy.findByRole('radio', { name: 'Ja' }).should('exist').check();
});

cy.findByRole('button', { name: '15. mai 2023 - 21. mai 2023' }).click();

cy.findByRole('group', { name: DAY_PICKER_LABEL_WITH_PARKING })
.should('exist')
.within(() => {
cy.findAllByRole('checkbox').should('have.length', 7);
cy.findByRole('checkbox', { name: 'mandag 15. mai 2023' }).should('exist').check();
cy.findByRole('checkbox', { name: 'søndag 21. mai 2023' }).should('exist').check();
cy.findAllByRole('textbox', { name: PARKING_EXPENSES_LABEL }).eq(0).should('exist').type('100');
});

cy.clickNextStep();

// Summary
cy.get('dl')
.first()
.within(() => {
cy.get('dt').eq(0).should('contain.text', 'Legg til kjøreliste for en eller flere perioder');

cy.findAllByRole('listitem').should('have.length', 2);
cy.findByText('mandag 15. mai 2023, parkeringsutgift: 100 kr').should('exist');
cy.findByText('søndag 21. mai 2023').should('exist');
});
beforeEach(() => {
cy.defaultIntercepts();
});

it('should show errors', () => {
Expand All @@ -76,9 +31,13 @@ describe('DrivingList', () => {
cy.clickStart();

// Should fill out form
cy.findByRole('textbox', { name: DATE_PICKER_LABEL }).should('exist');
cy.findByRole('group', { name: 'Skal du registrere parkering?' }).should('exist');
cy.clickNextStep();
cy.get('[data-cy=error-summary]')

cy.findByRole('heading', { name: 'For å gå videre må du rette opp følgende:' })
.should('exist')
.parent()
.within(() => {
cy.findByRole('link', { name: `Du må fylle ut: ${DATE_PICKER_LABEL}` })
.should('exist')
Expand All @@ -94,23 +53,62 @@ describe('DrivingList', () => {
cy.findByRole('textbox', { name: PARKING_EXPENSES_LABEL }).clear();
cy.findByRole('textbox', { name: PARKING_EXPENSES_LABEL }).type('text');
cy.clickNextStep();
cy.get('[data-cy=error-summary]')
cy.findByRole('heading', { name: 'For å gå videre må du rette opp følgende:' })
.should('exist')
.parent()
.within(() => {
cy.findByRole('link', { name: 'Parkeringsutgiftene for 15.05.2023 må være et gyldig beløp' })
.should('exist')
.click();
});

cy.findByRole('textbox', { name: PARKING_EXPENSES_LABEL }).should('have.focus').type('{selectall}78');
cy.get('[data-cy=error-summary]').should('not.exist');
cy.findByRole('heading', { name: 'For å gå videre må du rette opp følgende:' }).should('not.exist');

// Parking expenses should not show even with value over 100
cy.findByRole('textbox', { name: PARKING_EXPENSES_LABEL }).should('exist').type('101');
cy.clickNextStep();
cy.findByRole('heading', { name: 'Oppsummering' }).should('exist');
});

it('should fill out form and show data in summary', () => {
cy.visit(`/fyllut/testdrivinglist?sub=paper`);
cy.defaultWaits();
cy.clickStart();

cy.findByRole('textbox', { name: DATE_PICKER_LABEL }).should('exist').type('15.05.2023{esc}');
cy.findByRole('group', { name: PARKING_LABEL })
.should('exist')
.within(() => {
cy.findAllByRole('radio').should('have.length', 2);
cy.findByRole('radio', { name: 'Ja' }).should('exist').check();
});

cy.findByRole('button', { name: '15. mai 2023 - 21. mai 2023' }).click();

cy.findByRole('group', { name: DAY_PICKER_LABEL_WITH_PARKING })
.should('exist')
.within(() => {
cy.findAllByRole('checkbox').should('have.length', 7);
cy.findByRole('checkbox', { name: 'mandag 15. mai 2023' }).should('exist').check();
cy.findByRole('checkbox', { name: 'søndag 21. mai 2023' }).should('exist').check();
cy.findAllByRole('textbox', { name: PARKING_EXPENSES_LABEL }).eq(0).should('exist').type('100');
});

cy.clickNextStep();

// Summary
cy.get('dl')
.first()
.within(() => {
cy.get('dt').eq(0).should('contain.text', 'Legg til kjøreliste for en eller flere perioder');

cy.findAllByRole('listitem').should('have.length', 2);
cy.findByText('mandag 15. mai 2023, parkeringsutgift: 100 kr').should('exist');
cy.findByText('søndag 21. mai 2023').should('exist');
});
});

it('should add and remove periods', () => {
cy.visit(`/fyllut/testdrivinglist?sub=paper`);
cy.defaultWaits();
Expand All @@ -137,11 +135,19 @@ describe('DrivingList', () => {
});

describe('digital', () => {
beforeEach(() => {
cy.mocksRestoreRouteVariants();
cy.defaultInterceptsMellomlagring();
cy.defaultInterceptsExternal();
cy.defaultIntercepts();
});

it('should fill out form and show data in summary', () => {
cy.visit(`/fyllut/testdrivinglist?sub=digital`);
cy.defaultWaits();
cy.clickStart();
cy.wait('@getActivities');
cy.wait('@createMellomlagring');

cy.findByRole('group', { name: ACTIVITIES_LABEL })
.should('exist')
Expand Down Expand Up @@ -201,10 +207,11 @@ describe('DrivingList', () => {
});

it('should fill out mellomlagret values', () => {
cy.visit(`/fyllut/testdrivinglist/veiledning?sub=digital&innsendingsId=8495201b-71fd-4a95-82f8-d224d32237e5`);
cy.mocksUseRouteVariant('get-soknad:success-driving-list');
cy.visit(`/fyllut/testdrivinglist/veiledning?sub=digital&innsendingsId=8495201b-71fd-4a95-82f8-d224d32237e5`);
cy.defaultWaits();
cy.wait('@getActivities');
cy.wait('@getMellomlagring');

cy.findByRole('radio', { name: 'Arbeidstrening: 01. januar 2024 - 31. august 2024' }).should('be.checked');

Expand All @@ -220,10 +227,11 @@ describe('DrivingList', () => {
});

it('should load driving list without dates', () => {
cy.visit(`/fyllut/testdrivinglist/veiledning?sub=digital&innsendingsId=a66e8932-ce2a-41c1-932b-716fc487813b`);
cy.mocksUseRouteVariant('get-soknad:success-driving-list-no-dates');
cy.visit(`/fyllut/testdrivinglist/veiledning?sub=digital&innsendingsId=a66e8932-ce2a-41c1-932b-716fc487813b`);
cy.defaultWaits();
cy.wait('@getActivities');
cy.wait('@getMellomlagring');

cy.findByRole('radio', { name: 'Arbeidstrening: 01. januar 2024 - 31. august 2024' }).should('be.checked');

Expand All @@ -241,6 +249,7 @@ describe('DrivingList', () => {
cy.visit(`/fyllut/testdrivinglist/veiledning?sub=digital`);
cy.defaultWaits();
cy.wait('@getActivities');
cy.wait('@createMellomlagring');

cy.findByRole('radio', { name: 'Arbeidstrening: 01. januar 2099 - 31. august 2099' }).check();

Expand All @@ -260,6 +269,7 @@ describe('DrivingList', () => {

cy.clickStart();
cy.wait('@getActivities');
cy.wait('@createMellomlagring');

cy.clickSaveAndContinue();
cy.get('[data-cy=error-summary]')
Expand Down Expand Up @@ -295,11 +305,12 @@ describe('DrivingList', () => {
});

it('should render alert when there are no activities and error when trying to continue', () => {
cy.mocksUseRouteVariant('get-activities:success-empty');
cy.visit(`/fyllut/testdrivinglist?sub=digital`);
cy.defaultWaits();
cy.mocksUseRouteVariant('get-activities:success-empty');
cy.clickStart();
cy.wait('@getActivities');
cy.wait('@createMellomlagring');

cy.get('.navds-alert').within(() => {
cy.findByText(TEXTS.statiske.drivingList.noVedtakHeading).should('exist');
Expand Down
2 changes: 1 addition & 1 deletion packages/fyllut/cypress/e2e/components/general.cy.ts
Original file line number Diff line number Diff line change
Expand Up @@ -33,7 +33,7 @@ describe('React components', () => {

cy.findAllByText('Du må fylle ut: Velg valuta').should('have.length', 2);
cy.findAllByText('Du må fylle ut: Velg valuta').first().click();
cy.findByRole('combobox', { name: 'Velg valuta' }).should('have.focus').type('{upArrow}{enter}');
cy.findByRole('combobox', { name: 'Velg valuta' }).type('{upArrow}{enter}');
cy.clickNextStep();

cy.findByRole('heading', { name: 'Vedlegg' }).should('exist');
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -15,7 +15,7 @@ interface Props {

const AddressTextField = ({ type, label, value, required = false, children, autoComplete }: Props) => {
const { onChange, readOnly, className } = useAddress();
const { translate, addRef, getComponentError } = useComponentUtils();
const { translate, addRef, getComponentError, focusHandler, blurHandler } = useComponentUtils();

const translateLabel = (text: string) => {
return required || readOnly ? translate(text) : `${translate(text)} (${translate('valgfritt')})`;
Expand All @@ -31,6 +31,8 @@ const AddressTextField = ({ type, label, value, required = false, children, auto
onChange={(event) => onChange(type, event.currentTarget.value)}
defaultValue={value}
label={translateLabel(label)}
onFocus={focusHandler(`address:${type}`)}
onBlur={blurHandler(`address:${type}`)}
ref={(ref) => addRef(`address:${type}`, ref)}
error={getComponentError(`address:${type}`)}
readOnly={readOnly}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -150,13 +150,6 @@ class BaseComponent extends FormioReactComponent {
return this.component?.customLabels;
}

/**
* Get error custom for component renderReact()
*/
getError() {
return this.error?.message;
}

/**
* Get whether user is logged in or not for custom component renderReact()
*/
Expand Down Expand Up @@ -200,11 +193,37 @@ class BaseComponent extends FormioReactComponent {
return (this.isSubmissionDigital() && !!this.component?.prefillKey && !!this.component?.prefillValue) ?? false;
}

// elementId is used to focus to the correct element when clicking on error summary
// Message is the error message that is shown in the error summary
/**
* elementId is used to focus to the correct element when clicking on error summary
* Message is the error message that is shown in the error summary
*/
addError(message: string, elementId?: string) {
this.logger.debug('addError', { errorMessage: message });
this.componentErrors.push(this.createError(message, elementId));
if (this.showErrorMessages()) {
this.logger.debug('addError', { errorMessage: message });
this.componentErrors.push(this.createError(message, elementId));
}
}

get errors() {
return this.componentErrors;
}

override setCustomValidity(messages: string | ComponentError[], _dirty?: boolean, _external?: boolean) {
this.removeAllErrors();

if (messages) {
if (Array.isArray(messages)) {
if (messages.length > 1) {
this.logger.info(`Should never get more then one message, got ${messages.length}.`, { messages });
}
messages.forEach((componentError: ComponentError) => {
this.addError(componentError.message, this.getId());
});
} else {
this.addError(messages, this.getId());
}
}
this.rerender();
}

createError(message: string, elementId?: string): ComponentError {
Expand All @@ -220,9 +239,25 @@ class BaseComponent extends FormioReactComponent {
this.componentErrors = [];
}

getError() {
return this.getComponentError(this.getId());
}

getComponentError(elementId: string) {
return this.componentErrors.find((error) => error.elementId === elementId)?.message;
}

/**
* nextPageClicked: When user click next page in Fyllut (except last page)
* submitted: When user click next page in Fyllut (last page)
* builderMode: When user is in the regular form builder
* editFormDialog: When user have open a form dialog in the form builder
*/
showErrorMessages() {
return (
this.root.currentPage?.nextPageClicked || this.root.submitted || this.builderMode || this.root.editFormDialog
);
}
}

export default BaseComponent;
Loading

0 comments on commit 0f67ddc

Please sign in to comment.