import * as React from 'react'; import { render, screen, waitFor } from '@testing-library/react'; import expect from 'expect'; import { Route } from 'react-router-dom'; import { useResourceDefinitions } from './useResourceDefinitions'; import { CoreAdminContext } from './CoreAdminContext'; import { CoreAdminRoutes } from './CoreAdminRoutes'; import { Resource } from './Resource'; import { CustomRoutes } from './CustomRoutes'; import { AuthProvider, CoreLayoutProps, ResourceProps } from '../types'; import { TestMemoryRouter } from '../routing'; const ResourceDefinitionsTestComponent = () => { const definitions = useResourceDefinitions(); if (!definitions) return null; return ( ); }; const MyLayout = ({ children }: CoreLayoutProps) => ( <> {children} ); const CatchAll = () =>
; const Loading = () => <>Loading; const Ready = () => <>Ready; const TestedComponent = ({ role }) => { return ( {() => role === 'admin' ? [ , , ] : role === 'user' ? [] : [] } ); }; const TestedComponentReturningNull = ({ role }) => { return ( {() => role === 'admin' ? [ , , ] : role === 'user' ? [] : null } ); }; const TestedComponentWithAuthProvider = ({ callback }) => { const authProvider = { login: () => Promise.resolve(), logout: () => Promise.resolve(), checkAuth: () => Promise.resolve(), checkError: () => Promise.resolve(), getPermissions: () => Promise.resolve('admin'), }; return ( {callback} ); }; const ResourceWithPermissions = (props: ResourceProps) => ( ); ResourceWithPermissions.raName = 'Resource'; ResourceWithPermissions.registerResource = ( { create, edit, icon, list, name, options, show }: ResourceProps, permissions: any ) => ({ name, options, hasList: !!list && permissions && permissions[name]?.list, hasCreate: !!create && permissions && permissions[name]?.create, hasEdit: !!edit && permissions && permissions[name]?.edit, hasShow: !!show && permissions && permissions[name]?.show, icon, }); const TestedComponentWithPermissions = () => { const authProvider: AuthProvider = { login: () => Promise.resolve(), logout: () => Promise.resolve(), checkAuth: () => Promise.resolve(), checkError: () => Promise.resolve(), getPermissions: () => Promise.resolve({ posts: { list: true, create: true, edit: true, show: true, }, comments: { list: true, create: false, edit: false, show: true, }, users: { list: true, create: false, edit: false, show: false, }, }), }; return ( } create={
} edit={
} show={
} /> } create={
} edit={
} show={
} /> } create={
} edit={
} show={
} /> ); }; const TestedComponentWithOnlyLazyCustomRoutes = ({ navigateCallback }) => { const [lazyRoutes, setLazyRoutes] = React.useState(null); React.useEffect(() => { const timer = setTimeout( () => setLazyRoutes( Foo
} /> ), 500 ); return () => clearTimeout(timer); }, [setLazyRoutes]); return ( {lazyRoutes} ); }; const TestedComponentWithForcedRoutes = () => { return ( } hasCreate hasEdit hasShow /> } /> {() => [} hasEdit />]} ); }; describe('useConfigureAdminRouterFromChildren', () => { it('should always load static resources', async () => { render(); await waitFor(() => expect(screen.queryByText('Loading')).toBeNull()); await screen.findByText(`"name":"posts"`, { exact: false }); await screen.findByText(`"name":"comments"`, { exact: false }); expect( screen.queryByText(`"name":"user"`, { exact: false }) ).toBeNull(); expect( screen.queryByText(`"name":"admin"`, { exact: false }) ).toBeNull(); }); it('should not call the children function until the permissions have been retrieved', async () => { const callback = jest.fn(() => Promise.resolve(resolve => setTimeout(resolve, 50)) ); render(); await waitFor(() => expect(callback).toHaveBeenCalled()); expect(callback).not.toHaveBeenCalledWith(undefined); }); it('should load dynamic resource definitions', async () => { render(); await waitFor(() => expect(screen.queryByText('Loading')).toBeNull()); await screen.findByText(`"name":"user"`, { exact: false }); await screen.findByText(`"name":"admin"`, { exact: false }); }); it('should accept function returning null', async () => { render(); await waitFor(() => expect(screen.queryByText('Loading')).toBeNull()); await screen.findByText(`"name":"user"`, { exact: false }); await screen.findByText(`"name":"admin"`, { exact: false }); }); it('should call registerResource with the permissions', async () => { render(); await waitFor(() => expect(screen.queryByText('Loading')).toBeNull()); await screen.findByText(`"name":"posts"`, { exact: false, }); await screen.findByText(`"hasList":true`, { selector: `[data-resource=posts]`, exact: false, }); await screen.findByText(`"hasCreate":true`, { selector: `[data-resource=posts]`, exact: false, }); await screen.findByText(`"hasShow":true`, { selector: `[data-resource=posts]`, exact: false, }); await screen.findByText(`"hasList":true`, { selector: `[data-resource=comments]`, exact: false, }); await screen.findByText(`"hasShow":true`, { selector: `[data-resource=comments]`, exact: false, }); await screen.findByText(`"hasCreate":false`, { selector: `[data-resource=comments]`, exact: false, }); await screen.findByText(`"hasEdit":false`, { selector: `[data-resource=comments]`, exact: false, }); await screen.findByText(`"hasList":true`, { selector: `[data-resource=users]`, exact: false, }); await screen.findByText(`"hasShow":false`, { selector: `[data-resource=users]`, exact: false, }); await screen.findByText(`"hasCreate":false`, { selector: `[data-resource=users]`, exact: false, }); await screen.findByText(`"hasEdit":false`, { selector: `[data-resource=users]`, exact: false, }); }); it('should allow adding new resource after the first render', async () => { const { rerender } = render(); await waitFor(() => expect(screen.queryByText('Loading')).toBeNull()); await screen.findByText(`"name":"posts"`, { exact: false }); await screen.findByText(`"name":"comments"`, { exact: false }); await screen.findByText(`"name":"user"`, { exact: false }); expect( screen.queryByText(`"name":"admin"`, { exact: false }) ).toBeNull(); rerender(); await waitFor(() => expect(screen.queryByText('Loading')).toBeNull()); await screen.findByText(`"name":"posts"`, { exact: false }); await screen.findByText(`"name":"comments"`, { exact: false }); await screen.findByText(`"name":"user"`, { exact: false }); await screen.findByText(`"name":"admin"`, { exact: false }); }); it('should allow removing a resource after the first render', async () => { const { rerender } = render(); await waitFor(() => expect(screen.queryByText('Loading')).toBeNull()); await screen.findByText(`"name":"posts"`, { exact: false }); await screen.findByText(`"name":"comments"`, { exact: false }); await screen.findByText(`"name":"user"`, { exact: false }); await screen.findByText(`"name":"admin"`, { exact: false }); rerender(); await waitFor(() => expect(screen.queryByText('Loading')).toBeNull()); await screen.findByText(`"name":"posts"`, { exact: false }); await screen.findByText(`"name":"comments"`, { exact: false }); await screen.findByText(`"name":"user"`, { exact: false }); expect( screen.queryByText(`"name":"admin"`, { exact: false }) ).toBeNull(); }); it('should allow dynamically loaded custom routes without any resources', async () => { let navigate; render( { navigate = n; }} /> ); expect(screen.queryByText('Ready')).not.toBeNull(); await new Promise(resolve => setTimeout(resolve, 1010)); expect(screen.queryByText('Ready')).toBeNull(); navigate('/foo'); await screen.findByText('Foo'); }); it('should support forcing hasEdit hasCreate or hasShow', async () => { render(); await waitFor(() => expect(screen.queryByText('Loading')).toBeNull()); await screen.findByText(`"hasList":true`, { selector: `[data-resource=posts]`, exact: false, }); await screen.findByText(`"hasShow":true`, { selector: `[data-resource=posts]`, exact: false, }); await screen.findByText(`"hasEdit":true`, { selector: `[data-resource=posts]`, exact: false, }); await screen.findByText(`"hasCreate":true`, { selector: `[data-resource=posts]`, exact: false, }); await screen.findByText(`"hasList":true`, { selector: `[data-resource=comments]`, exact: false, }); await screen.findByText(`"hasShow":false`, { selector: `[data-resource=comments]`, exact: false, }); await screen.findByText(`"hasEdit":false`, { selector: `[data-resource=comments]`, exact: false, }); await screen.findByText(`"hasCreate":false`, { selector: `[data-resource=comments]`, exact: false, }); await screen.findByText(`"hasList":true`, { selector: `[data-resource=user]`, exact: false, }); await screen.findByText(`"hasShow":false`, { selector: `[data-resource=user]`, exact: false, }); await screen.findByText(`"hasEdit":true`, { selector: `[data-resource=user]`, exact: false, }); await screen.findByText(`"hasCreate":false`, { selector: `[data-resource=user]`, exact: false, }); }); });