From 9dc95a05792146800ca22e3e1b515883bfc31b41 Mon Sep 17 00:00:00 2001 From: Dmytro Melnyshyn Date: Fri, 27 Dec 2024 17:06:05 +0200 Subject: [PATCH] UIQM-743: Prevent 'handleSubmit' from running if there is any validation issue, instead of using the 'complete' form API. --- src/QuickMarcEditor/QuickMarcEditor.js | 7 ++ src/QuickMarcEditor/QuickMarcEditor.test.js | 26 +++++++ .../useSaveRecord/useSaveRecord.test.js | 69 ------------------- .../useSubmitRecord/useSumbitRecord.js | 26 +------ 4 files changed, 36 insertions(+), 92 deletions(-) diff --git a/src/QuickMarcEditor/QuickMarcEditor.js b/src/QuickMarcEditor/QuickMarcEditor.js index 43942f74..4b05e7ac 100644 --- a/src/QuickMarcEditor/QuickMarcEditor.js +++ b/src/QuickMarcEditor/QuickMarcEditor.js @@ -130,6 +130,7 @@ const QuickMarcEditor = ({ const { setValidationErrors, continueAfterSave, + validationErrorsRef, } = useContext(QuickMarcContext); const { hasErrorIssues, isBackEndValidationMarcType } = useValidation(); @@ -310,6 +311,11 @@ const QuickMarcEditor = ({ } } + // if validation has any issues - cancel submit + if (!isEmpty(validationErrorsRef.current)) { + return; + } + handleSubmit(e) ?.then(handleSubmitResponse) ?.finally(closeModals); @@ -329,6 +335,7 @@ const QuickMarcEditor = ({ focusLastFocusedInput, showValidationIssuesToasts, continueAfterSave, + validationErrorsRef, ]); const paneFooter = useMemo(() => { diff --git a/src/QuickMarcEditor/QuickMarcEditor.test.js b/src/QuickMarcEditor/QuickMarcEditor.test.js index a6f9e991..775112a1 100644 --- a/src/QuickMarcEditor/QuickMarcEditor.test.js +++ b/src/QuickMarcEditor/QuickMarcEditor.test.js @@ -912,6 +912,32 @@ describe('Given QuickMarcEditor', () => { }); }); + describe('when saving form with validation issue', () => { + it('should prevent submitting', async () => { + const { + getByText, + getByTestId, + } = renderQuickMarcEditor({}, { + quickMarcContext: { + validationErrorsRef: { + current: { + [MISSING_FIELD_ID]: [ + { id: 'some warning', severity: 'warn', values: {} }, + ], + }, + }, + }, + }); + + const contentField = getByTestId('content-field-3'); + + fireEvent.change(contentField, { target: { value: '' } }); + await fireEvent.click(getByText('stripes-acq-components.FormFooter.save')); + + expect(onSubmitMock).not.toHaveBeenCalled(); + }); + }); + describe('when saving form without validation warnings or errors', () => { beforeEach(async () => { mockValidate.mockClear().mockResolvedValue({}); diff --git a/src/QuickMarcEditor/useSaveRecord/useSaveRecord.test.js b/src/QuickMarcEditor/useSaveRecord/useSaveRecord.test.js index af76c079..75d67964 100644 --- a/src/QuickMarcEditor/useSaveRecord/useSaveRecord.test.js +++ b/src/QuickMarcEditor/useSaveRecord/useSaveRecord.test.js @@ -94,9 +94,7 @@ const mockOnSave = jest.fn(); const mockActualizeLinks = jest.fn((formValuesToProcess) => Promise.resolve(formValuesToProcess)); const mockUpdateMarcRecord = jest.fn().mockResolvedValue(); const mockValidateFetch = jest.fn().mockResolvedValue({}); -const mockComplete = jest.fn(); -const _api = null; const basePath = '/base-path'; const locations = [{ @@ -719,29 +717,6 @@ describe('useSaveRecord', () => { }); describe('when creating', () => { - describe('when there is a validation error', () => { - it('should stop submitting', async () => { - const { result } = renderHook(useSaveRecord, { - initialProps: getInitialProps(MARC_TYPES.BIB), - wrapper: getWrapper({ - quickMarcContext: { - action: QUICK_MARC_ACTIONS.CREATE, - validationErrorsRef: { - current: { - 'id-with-error': [{ id: 'some-error' }], - }, - }, - }, - }), - }); - - await result.current.onSubmit(null, _api, mockComplete); - - expect(mockComplete).toHaveBeenCalled(); - expect(getMutator().quickMarcEditMarcRecord.POST).not.toHaveBeenCalled(); - }); - }); - describe('when marc type is not a bib', () => { it('should not call actualizeLinks', async () => { const marcType = MARC_TYPES.HOLDINGS; @@ -1156,28 +1131,6 @@ describe('useSaveRecord', () => { }); describe('when editing', () => { - describe('when there is a validation error', () => { - it('should stop submitting', async () => { - const { result } = renderHook(useSaveRecord, { - initialProps: getInitialProps(MARC_TYPES.BIB), - wrapper: getWrapper({ - quickMarcContext: { - action: QUICK_MARC_ACTIONS.EDIT, - validationErrorsRef: { - current: { - 'id-with-error': [{ id: 'some-error' }], - }, - }, - }, - }), - }); - - await result.current.onSubmit(null, _api, mockComplete); - - expect(mockComplete).toHaveBeenCalled(); - }); - }); - describe('when marc type is not a bib', () => { it('should not call actualizeLinks', async () => { const marcType = MARC_TYPES.AUTHORITY; @@ -1672,28 +1625,6 @@ describe('useSaveRecord', () => { }); describe('when deriving', () => { - describe('when there is a validation error', () => { - it('should stop submitting', async () => { - const { result } = renderHook(useSaveRecord, { - initialProps: getInitialProps(MARC_TYPES.BIB), - wrapper: getWrapper({ - quickMarcContext: { - action: QUICK_MARC_ACTIONS.DERIVE, - validationErrorsRef: { - current: { - 'id-with-error': [{ id: 'some-error' }], - }, - }, - }, - }), - }); - - await result.current.onSubmit(null, _api, mockComplete); - - expect(mockComplete).toHaveBeenCalled(); - }); - }); - it('should actualize links', async () => { const action = QUICK_MARC_ACTIONS.DERIVE; const marcType = MARC_TYPES.BIB; diff --git a/src/QuickMarcEditor/useSaveRecord/useSubmitRecord/useSumbitRecord.js b/src/QuickMarcEditor/useSaveRecord/useSubmitRecord/useSumbitRecord.js index cba62fe1..55b6239a 100644 --- a/src/QuickMarcEditor/useSaveRecord/useSubmitRecord/useSumbitRecord.js +++ b/src/QuickMarcEditor/useSaveRecord/useSubmitRecord/useSumbitRecord.js @@ -8,7 +8,6 @@ import { useLocation, useParams, } from 'react-router-dom'; -import isEmpty from 'lodash/isEmpty'; import noop from 'lodash/noop'; import isNil from 'lodash/isNil'; @@ -56,7 +55,6 @@ const useSubmitRecord = ({ basePath, initialValues, instance, - validationErrorsRef, continueAfterSave, relatedRecordVersion, } = useContext(QuickMarcContext); @@ -95,12 +93,7 @@ const useSubmitRecord = ({ }); }, [basePath, marcType, location, history, refreshPageData]); - const onCreate = useCallback(async (formValues, _api, complete) => { - // if validation has any issues - cancel submit - if (!isEmpty(validationErrorsRef.current)) { - return complete(); - } - + const onCreate = useCallback(async (formValues, _api) => { const formValuesToProcess = prepareForSubmit(formValues); let formValuesToHydrate; @@ -168,7 +161,6 @@ const useSubmitRecord = ({ showCallout, prepareForSubmit, actualizeLinks, - validationErrorsRef, marcType, continueAfterSave, mutator, @@ -176,14 +168,9 @@ const useSubmitRecord = ({ redirectToRecord, ]); - const onEdit = useCallback(async (formValues, _api, complete) => { + const onEdit = useCallback(async (formValues, _api) => { let is1xxOr010Updated = false; - // if validation has any issues - cancel submit - if (!isEmpty(validationErrorsRef.current)) { - return complete(); - } - if (marcType === MARC_TYPES.AUTHORITY && linksCount > 0) { is1xxOr010Updated = are010Or1xxUpdated(initialValues.records, formValues.records); } @@ -293,7 +280,6 @@ const useSubmitRecord = ({ locale, updateMarcRecord, isRequestToCentralTenantFromMember, - validationErrorsRef, relatedRecordVersion, _externalId, _instanceId, @@ -301,12 +287,7 @@ const useSubmitRecord = ({ redirectToRecord, ]); - const onDerive = useCallback(async (formValues, _api, complete) => { - // if validation has any issues - cancel submit - if (!isEmpty(validationErrorsRef.current)) { - return complete(); - } - + const onDerive = useCallback(async (formValues, _api) => { const formValuesToProcess = prepareForSubmit(formValues); showCallout({ messageId: 'ui-quick-marc.record.saveNew.onSave' }); @@ -379,7 +360,6 @@ const useSubmitRecord = ({ showCallout, prepareForSubmit, actualizeLinks, - validationErrorsRef, continueAfterSave, mutator, processEditingAfterCreation,