import * as React from 'react'; import { render, screen, waitFor } from '@testing-library/react'; import expect from 'expect'; import { Route } from 'react-router-dom'; import { createMemoryHistory } from 'history'; import { CoreAdminContext } from './CoreAdminContext'; import { CoreAdminRoutes } from './CoreAdminRoutes'; import { Resource } from './Resource'; import { CustomRoutes } from './CustomRoutes'; import { CoreLayoutProps } from '../types'; import { testDataProvider } from '../dataProvider'; const Layout = ({ children }: CoreLayoutProps) =>
Layout {children}
; const CatchAll = () =>
; const Loading = () => <>Loading; describe('', () => { const defaultProps = { customRoutes: [], }; describe('With resources as regular children', () => { it('should render resources and custom routes with and without layout', () => { const history = createMemoryHistory(); render( Foo
} /> Bar} /> PostList} /> CommentList} /> ); expect(screen.getByText('Layout')).not.toBeNull(); history.push('/posts'); expect(screen.getByText('PostList')).not.toBeNull(); history.push('/comments'); expect(screen.getByText('CommentList')).not.toBeNull(); history.push('/foo'); expect(screen.queryByText('Layout')).toBeNull(); expect(screen.getByText('Foo')).not.toBeNull(); history.push('/bar'); expect(screen.getByText('Layout')).not.toBeNull(); expect(screen.getByText('Bar')).not.toBeNull(); }); }); describe('With children returned from a function as children', () => { it('should render resources and custom routes with and without layout', async () => { const history = createMemoryHistory(); render( Foo} /> {() => ( <> Bar} /> PostList} /> CommentList} /> )} ); history.push('/foo'); expect(screen.queryByText('Layout')).toBeNull(); expect(screen.getByText('Foo')).not.toBeNull(); history.push('/bar'); await waitFor(() => { expect(screen.queryByText('Layout')).not.toBeNull(); }); expect(screen.getByText('Bar')).not.toBeNull(); history.push('/posts'); expect(screen.queryByText('PostList')).not.toBeNull(); history.push('/comments'); expect(screen.queryByText('CommentList')).not.toBeNull(); }); it('should render resources and custom routes with and without layout even without an authProvider', async () => { const history = createMemoryHistory(); render( Foo} /> {() => ( <> Bar} /> PostList} /> CommentList} /> )} ); history.push('/foo'); expect(screen.queryByText('Layout')).toBeNull(); expect(screen.getByText('Foo')).not.toBeNull(); history.push('/bar'); await waitFor(() => { expect(screen.queryByText('Layout')).not.toBeNull(); }); expect(screen.getByText('Bar')).not.toBeNull(); history.push('/posts'); expect(screen.queryByText('PostList')).not.toBeNull(); history.push('/comments'); expect(screen.queryByText('CommentList')).not.toBeNull(); }); it('should return loading while the function child is not resolved', async () => { jest.useFakeTimers(); const authProvider = { login: jest.fn().mockResolvedValue(''), logout: jest.fn().mockResolvedValue(''), checkAuth: jest.fn().mockResolvedValue(''), checkError: jest.fn().mockResolvedValue(''), getPermissions: jest.fn().mockResolvedValue(''), }; const Custom = () => <>Custom; const history = createMemoryHistory(); render( } /> {() => new Promise(() => null)} ); // Timeout needed because we wait for a second before displaying the loading screen jest.advanceTimersByTime(1010); history.push('/posts'); expect(screen.queryByText('Loading')).not.toBeNull(); history.push('/foo'); expect(screen.queryByText('Loading')).toBeNull(); expect(screen.queryByText('Custom')).not.toBeNull(); jest.useRealTimers(); }); }); describe('requireAuth', () => { it('should not wait for the authProvider.checkAuth to return before rendering by default', () => { const authProvider = { login: jest.fn().mockResolvedValue(''), logout: jest.fn().mockResolvedValue(''), checkAuth: (): Promise => new Promise(() => {}), // never resolves checkError: jest.fn().mockResolvedValue(''), getPermissions: jest.fn().mockResolvedValue(''), }; const history = createMemoryHistory(); render( PostList} /> ); expect(screen.queryByText('PostList')).not.toBeNull(); expect(screen.queryByText('Loading')).toBeNull(); }); it('should wait for the authProvider.checkAuth to return before rendering when requireAuth is true', async () => { let resolve; const authProvider = { login: jest.fn().mockResolvedValue(''), logout: jest.fn().mockResolvedValue(''), checkAuth: (): Promise => new Promise(res => (resolve = res)), checkError: jest.fn().mockResolvedValue(''), getPermissions: jest.fn().mockResolvedValue(''), }; const history = createMemoryHistory(); render( PostList} /> ); expect(screen.queryByText('PostList')).toBeNull(); expect(screen.queryByText('Loading')).toBeNull(); resolve(); await waitFor(() => expect(screen.queryByText('PostList')).not.toBeNull() ); }); it('should show a loader when requireAuth is true and dataProvider.checkAuth() takes more than 1s to reply', async () => { let resolve; const authProvider = { login: jest.fn().mockResolvedValue(''), logout: jest.fn().mockResolvedValue(''), checkAuth: (): Promise => new Promise(res => (resolve = res)), checkError: jest.fn().mockResolvedValue(''), getPermissions: jest.fn().mockResolvedValue(''), }; const history = createMemoryHistory(); render( PostList} /> ); expect(screen.queryByText('PostList')).toBeNull(); expect(screen.queryByText('Loading')).toBeNull(); await new Promise(resolve => setTimeout(resolve, 1100)); expect(screen.queryByText('Loading')).not.toBeNull(); resolve(); await waitFor(() => expect(screen.queryByText('PostList')).not.toBeNull() ); }); it('should redirect to login when requireAuth is true and authProvider.checkAuth() rejects', async () => { let reject; const authProvider = { login: jest.fn().mockResolvedValue(''), logout: jest.fn().mockResolvedValue(''), checkAuth: (): Promise => new Promise((res, rej) => (reject = rej)), checkError: jest.fn().mockResolvedValue(''), getPermissions: jest.fn().mockResolvedValue(''), }; const history = createMemoryHistory(); render( Login} /> PostList} /> ); expect(screen.queryByText('PostList')).toBeNull(); expect(screen.queryByText('Loading')).toBeNull(); reject(); await waitFor(() => expect(screen.queryByText('Login')).not.toBeNull() ); }); it('should render custom routes when the user is not authenticated and requireAuth is false', async () => { const authProvider = { login: jest.fn().mockResolvedValue(''), logout: jest.fn().mockResolvedValue(''), checkAuth: () => Promise.reject('Not authenticated'), checkError: jest.fn().mockResolvedValue(''), getPermissions: jest.fn().mockResolvedValue(''), }; const history = createMemoryHistory(); render( Custom} /> Login} /> PostList} /> ); expect(screen.queryByText('PostList')).not.toBeNull(); expect(screen.queryByText('Loading')).toBeNull(); history.push('/custom'); await new Promise(resolve => setTimeout(resolve, 1100)); await waitFor(() => expect(screen.queryByText('Custom')).not.toBeNull() ); }); }); });