import * as React from 'react'; import expect from 'expect'; import { render, screen, waitFor, fireEvent } from '@testing-library/react'; import { onlineManager, QueryClient } from '@tanstack/react-query'; import { CoreAdminContext } from '../../core'; import { ChoicesProps, Form, InputProps, useChoices, useChoicesContext, useInput, } from '../../form'; import { testDataProvider } from '../../dataProvider'; import { ReferenceInputBase } from './ReferenceInputBase'; import { SelfReference, QueryOptions, Meta, Offline, } from './ReferenceInputBase.stories'; describe('', () => { const defaultProps = { reference: 'posts', resource: 'comments', source: 'post_id', }; beforeAll(() => { window.scrollTo = jest.fn(); }); beforeEach(() => { onlineManager.setOnline(true); }); it('should display an error if error is defined', async () => { jest.spyOn(console, 'error') .mockImplementationOnce(() => {}) .mockImplementationOnce(() => {}); /** * For some reason, we cannot use the Error story for the test. Although it behaves correctly in storybook, * it does not render the error message in the test. */ render( Promise.reject(new Error('fetch error')), })} >
); await waitFor(() => { expect(screen.queryByText('fetch error')).not.toBeNull(); }); }); it('should pass the correct resource down to child component', async () => { const MyComponent = () => { const { resource } = useChoicesContext(); return
{resource}
; }; const dataProvider = testDataProvider({ getList: () => // @ts-ignore Promise.resolve({ data: [{ id: 1 }, { id: 2 }], total: 2 }), }); render(
); await waitFor(() => { expect(screen.queryByText('posts')).not.toBeNull(); }); }); it('should provide a ChoicesContext with all available choices', async () => { const Children = () => { const { total } = useChoicesContext(); return
{total}
; }; const dataProvider = testDataProvider({ getList: () => // @ts-ignore Promise.resolve({ data: [{ id: 1 }, { id: 2 }], total: 2 }), }); render(
); await waitFor(() => { expect(screen.getByLabelText('total').innerHTML).toEqual('2'); }); }); it('should accept meta in queryOptions', async () => { const getList = jest .fn() .mockImplementation(() => Promise.resolve({ data: [], total: 25 })); const dataProvider = testDataProvider({ getList, // @ts-ignore getOne: () => Promise.resolve({ data: { id: 1 } }), }); render(); await waitFor(() => { expect(getList).toHaveBeenCalledWith('authors', { filter: {}, pagination: { page: 1, perPage: 25 }, sort: { field: 'id', order: 'DESC' }, meta: { test: true }, signal: undefined, }); }); }); it('should use meta when fetching current value', async () => { const getList = jest .fn() .mockImplementationOnce(() => Promise.resolve({ data: [], total: 25 }) ); const getMany = jest .fn() .mockImplementationOnce(() => Promise.resolve({ data: [] })); const dataProvider = testDataProvider({ getList, getMany }); render(
); await waitFor(() => { expect(getMany).toHaveBeenCalledWith('posts', { ids: [23], meta: { foo: 'bar' }, signal: undefined, }); }); }); it('should pass queryOptions to both queries', async () => { render(); await waitFor(() => new Promise(resolve => setTimeout(resolve, 100))); expect(screen.queryByDisplayValue('Tolstoy')).toBeNull(); fireEvent.click(screen.getByText('Toggle queryOptions')); await waitFor(() => { expect(screen.queryByDisplayValue('Tolstoy')).not.toBeNull(); }); }); it('should not throw an error on save when it is a self reference and the reference is undefined', async () => { jest.spyOn(console, 'log').mockImplementationOnce(() => {}); jest.spyOn(console, 'error').mockImplementationOnce(() => {}); render(); fireEvent.click(await screen.findByLabelText('Self reference')); await waitFor(() => { expect(screen.getAllByRole('option')).toHaveLength(5); }); const titleInput = await screen.findByDisplayValue('War and Peace'); fireEvent.change(titleInput, { target: { value: 'War and Peace 2' }, }); screen.getByText('Save').click(); await screen.findByText('Proust', undefined, { timeout: 5000 }); }); it('should render the offline prop node when offline', async () => { render(); fireEvent.click(await screen.findByText('Simulate offline')); fireEvent.click(await screen.findByText('Toggle Child')); await screen.findByText('You are offline, cannot load data'); fireEvent.click(await screen.findByText('Simulate online')); await screen.findByText('lorem'); }); }); const AutocompleteInput = ( props: Omit & Partial> & ChoicesProps & { source?: string } ) => { const { allChoices, error, source, setFilters } = useChoicesContext(props); const { getChoiceValue, getChoiceText } = useChoices(props); const { field } = useInput({ ...props, source }); if (error) { return
{error.message}
; } return (
{ const choice = allChoices?.find( choice => getChoiceText(choice).toString() === e.target.value ); if (choice) { field.onChange(getChoiceValue(choice)); return; } setFilters({ q: e.target.value }, {}, true); }} /> {allChoices?.map(choice => ( ))}
); };