Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
67 changes: 64 additions & 3 deletions src/useOnSubmit.test.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -2,11 +2,15 @@ import * as React from 'react';
import { jest } from '@jest/globals';
import { QueryClient, QueryClientProvider } from '@tanstack/react-query';
import { render, waitFor } from '@testing-library/react';
import type { CreateResult, RaRecord, UpdateResult } from 'react-admin';
import { DataProviderContext, testDataProvider } from 'react-admin';
import {
type CreateResult,
DataProviderContext,
type RaRecord,
type UpdateResult,
testDataProvider,
} from 'react-admin';
import { MemoryRouter, Route, Routes } from 'react-router-dom';

import useOnSubmit from './useOnSubmit.js';
import schemaAnalyzer from './hydra/schemaAnalyzer.js';
import { API_FIELDS_DATA } from './__fixtures__/parsedData.js';

Expand All @@ -23,6 +27,16 @@ const onSubmitProps = {
};

jest.mock('./getIdentifierValue.js');
const notify = jest.fn();
const reactAdminActual = jest.requireActual('react-admin') as Record<
string,
unknown
>;
jest.mock('react-admin', () => ({
__esModule: true,
...reactAdminActual,
useNotify: () => notify,
}));

test.each([
{
Expand All @@ -41,6 +55,7 @@ test.each([
])(
'Call create with file input ($name)',
async (values: Omit<RaRecord, 'id'>) => {
const { default: useOnSubmit } = await import('./useOnSubmit.js');
let save;
const Dummy = () => {
const onSubmit = useOnSubmit(onSubmitProps);
Expand Down Expand Up @@ -93,6 +108,7 @@ test.each([
cover: null,
},
])('Call update without file inputs ($name)', async (values: RaRecord) => {
const { default: useOnSubmit } = await import('./useOnSubmit.js');
let save;
const Dummy = () => {
const onSubmit = useOnSubmit(onSubmitProps);
Expand Down Expand Up @@ -125,3 +141,48 @@ test.each([
});
});
});

test.each([{ name: 'Required' }, null])(
'notification handling on validation errors (%s)',
async (submissionErrors) => {
const { default: useOnSubmit } = await import('./useOnSubmit.js');
notify.mockClear();
dataProvider.create = jest.fn(() =>
Promise.reject(new Error('Service Unavailable')),
);

let save;
const Dummy = () => {
const onSubmit = useOnSubmit({
...onSubmitProps,
schemaAnalyzer: {
...onSubmitProps.schemaAnalyzer,
getSubmissionErrors: () => submissionErrors,
},
});
save = onSubmit;
return <span />;
};

render(
<DataProviderContext.Provider value={dataProvider}>
<QueryClientProvider client={new QueryClient()}>
<MemoryRouter initialEntries={['/books/create']}>
<Routes>
<Route path="/books/create" element={<Dummy />} />
</Routes>
</MemoryRouter>
</QueryClientProvider>
</DataProviderContext.Provider>,
);
// eslint-disable-next-line @typescript-eslint/ban-ts-comment
// @ts-ignore
const errors = await save({ author: 'Author 1' });

await waitFor(() => {
expect(dataProvider.create).toHaveBeenCalled();
});
(submissionErrors ? expect(notify).not : expect(notify)).toHaveBeenCalled();
expect(errors).toEqual(submissionErrors ?? {});
},
);
16 changes: 8 additions & 8 deletions src/useOnSubmit.ts
Original file line number Diff line number Diff line change
Expand Up @@ -92,11 +92,14 @@ const useOnSubmit = ({
const failure =
mutationOptions?.onError ??
((error: string | Error) => {
let message = 'ra.notification.http_error';
if (!submissionErrors) {
message =
typeof error === 'string' ? error : error.message || message;
// Notification will be handled by the useNotifyIsFormInvalid hook.
if (submissionErrors) {
return;
}
const message =
typeof error === 'string'
? error
: error.message || 'ra.notification.http_error';
let errorMessage;
if (typeof error === 'string') {
errorMessage = error;
Expand All @@ -116,10 +119,7 @@ const useOnSubmit = ({
},
{},
);
if (submissionErrors) {
return submissionErrors;
}
return {};
return submissionErrors ?? {};
}
},
[
Expand Down
Loading