import * as React from 'react'; import { fireEvent, render, screen, waitFor } from '@testing-library/react'; import { Create, DataProviderErrorOnValidation, DeepField, Edit, WithAdditionalFilters, WithMessage, } from './useUnique.stories'; import { testDataProvider } from '../../dataProvider'; import { DataProvider } from '../../types'; describe('useUnique', () => { const baseDataProvider = (overrides?: Partial) => testDataProvider({ // @ts-ignore getList: jest.fn(() => Promise.resolve({ data: [{ id: 1, name: 'John Doe' }], total: 1, }) ), // @ts-ignore create: jest.fn(() => Promise.resolve({ data: { id: 1 } })), ...overrides, }); it('should show the default error when the field value already exists', async () => { const dataProvider = baseDataProvider(); render(); await screen.findByDisplayValue('John Doe'); fireEvent.click(screen.getByText('Submit')); await waitFor( () => { expect(dataProvider.getList).toHaveBeenCalledWith('users', { filter: { name: 'John Doe', }, pagination: { page: 1, perPage: 1, }, sort: { field: 'id', order: 'ASC', }, }); }, { timeout: 5000 } ); await screen.findByText('Must be unique'); expect(dataProvider.create).not.toHaveBeenCalled(); }); it('should not show the error when the field value already exists but only for the current record', async () => { const dataProvider = baseDataProvider({ // @ts-ignore getList: jest.fn((resource, params) => params.filter.name === 'John Doe' ? Promise.resolve({ data: [{ id: 1, name: 'John Doe' }], total: 1, }) : Promise.resolve({ data: [{ id: 2, name: 'Jane Doe' }], total: 1, }) ), // @ts-ignore getOne: jest.fn(() => Promise.resolve({ data: { id: 1, name: 'John Doe' }, }) ), // @ts-ignore update: jest.fn(() => Promise.resolve({ data: { id: 1 } })), }); render(); await waitFor(() => expect(dataProvider.getOne).toHaveBeenCalledWith('users', { id: 1, signal: undefined, }) ); await new Promise(resolve => setTimeout(resolve, 500)); fireEvent.change(await screen.findByDisplayValue('John Doe'), { target: { value: 'Jane Doe' }, }); fireEvent.blur(await screen.findByDisplayValue('Jane Doe')); fireEvent.click(screen.getByText('Submit')); await waitFor( () => expect(dataProvider.getList).toHaveBeenCalledWith('users', { filter: { name: 'Jane Doe', }, pagination: { page: 1, perPage: 1, }, sort: { field: 'id', order: 'ASC', }, }), { timeout: 5000 } ); await screen.findByText('Must be unique'); fireEvent.change(screen.getByDisplayValue('Jane Doe'), { target: { value: 'John Doe' }, }); await waitFor( () => expect(screen.queryByText('Must be unique')).toBeNull(), { timeout: 5000 } ); }); it('should not show the default error when the field value does not already exist', async () => { const dataProvider = baseDataProvider({ // @ts-ignore getList: jest.fn(() => Promise.resolve({ data: [], total: 0, }) ), }); render(); await screen.findByDisplayValue('John Doe'); fireEvent.change(screen.getByDisplayValue('John Doe'), { target: { value: 'Jordan Doe' }, }); await waitFor(() => { expect(screen.queryByText('Must be unique')).toBeNull(); }); fireEvent.click(screen.getByText('Submit')); await waitFor( () => { expect(dataProvider.create).toHaveBeenCalled(); }, { timeout: 5000 } ); }); it('should show a custom error when the field value already exists and message is provided', async () => { const dataProvider = baseDataProvider(); render(); await screen.findByDisplayValue('John Doe'); fireEvent.click(screen.getByText('Submit')); await screen.findByText( 'Someone is already registered with this name', {}, { timeout: 5000 } ); expect(dataProvider.create).not.toHaveBeenCalled(); }); it('should not show the custom error when the field value does not already exist and a message is provided', async () => { const dataProvider = baseDataProvider({ // @ts-ignore getList: jest.fn(() => Promise.resolve({ data: [], total: 0, }) ), }); render(); await screen.findByDisplayValue('John Doe'); fireEvent.change(screen.getByDisplayValue('John Doe'), { target: { value: 'Jordan Doe' }, }); fireEvent.click(screen.getByText('Submit')); await waitFor( () => { expect(dataProvider.create).toHaveBeenCalled(); }, { timeout: 5000 } ); expect( screen.queryByText('Someone is already registered with this name') ).toBeNull(); }); it('should call the dataProvider with additional filter when provided', async () => { const dataProvider = baseDataProvider(); render(); await screen.findByDisplayValue('John Doe'); fireEvent.click(screen.getByText('Submit')); await waitFor( () => { expect(dataProvider.getList).toHaveBeenCalledWith('users', { filter: { name: 'John Doe', organization_id: 1, }, pagination: { page: 1, perPage: 1, }, sort: { field: 'id', order: 'ASC', }, }); }, { timeout: 5000 } ); await screen.findByText('Must be unique'); }); it('should work with deep paths', async () => { const dataProvider = baseDataProvider(); render(); await screen.findByDisplayValue('John Doe'); fireEvent.click(screen.getByText('Submit')); await waitFor( () => { expect(dataProvider.getList).toHaveBeenCalledWith('users', { filter: { identity: { name: 'John Doe', }, }, pagination: { page: 1, perPage: 1, }, sort: { field: 'id', order: 'ASC', }, }); }, { timeout: 5000 } ); await screen.findByText('Must be unique'); expect(dataProvider.create).not.toHaveBeenCalled(); }); it('should show an error when the dataProvider fails', async () => { render(); await screen.findByDisplayValue('John Doe'); // The dataProvider for this story fails one over two times // Here's the first time, it should show an error fireEvent.click(screen.getByText('Submit')); expect(screen.queryByText('Server communication error')).toBeNull(); // Here's the second time, it should show the validation message fireEvent.click(screen.getByText('Submit')); expect(screen.queryByText('Must be unique')).toBeNull(); }); it('should not show an error when the field value is empty', async () => { const dataProvider = baseDataProvider(); render(); const input = await screen.findByDisplayValue('John Doe'); fireEvent.change(input, { target: { value: '' } }); fireEvent.click(screen.getByText('Submit')); await waitFor(() => { expect(dataProvider.create).toHaveBeenCalled(); }); expect(dataProvider.getList).not.toHaveBeenCalled(); expect(screen.queryByText('Must be unique')).toBeNull(); }); });