diff --git a/packages/ra-core/src/core/useConfigureAdminRouterFromChildren.spec.tsx b/packages/ra-core/src/core/useConfigureAdminRouterFromChildren.spec.tsx index 1a0a1dfa213..0340275ceea 100644 --- a/packages/ra-core/src/core/useConfigureAdminRouterFromChildren.spec.tsx +++ b/packages/ra-core/src/core/useConfigureAdminRouterFromChildren.spec.tsx @@ -80,6 +80,31 @@ const TestedComponentReturningNull = ({ role }) => { ); }; +const TestedComponentWithAuthProvider = ({ callback }) => { + const history = createMemoryHistory(); + const authProvider = { + login: () => Promise.resolve(), + logout: () => Promise.resolve(), + checkAuth: () => Promise.resolve(), + checkError: () => Promise.resolve(), + getPermissions: () => Promise.resolve('admin'), + }; + + return ( + + + + + {callback} + + + ); +}; + const ResourceWithPermissions = (props: ResourceProps) => ( ); @@ -186,6 +211,16 @@ describe('useConfigureAdminRouterFromChildren', () => { expectResource('user').toBeNull(); expectResource('admin').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()); diff --git a/packages/ra-core/src/core/useConfigureAdminRouterFromChildren.tsx b/packages/ra-core/src/core/useConfigureAdminRouterFromChildren.tsx index 8147c20598a..2ed39f7adf4 100644 --- a/packages/ra-core/src/core/useConfigureAdminRouterFromChildren.tsx +++ b/packages/ra-core/src/core/useConfigureAdminRouterFromChildren.tsx @@ -43,12 +43,13 @@ import { useResourceDefinitionContext } from './useResourceDefinitionContext'; export const useConfigureAdminRouterFromChildren = ( children: AdminChildren ): RoutesAndResources & { status: AdminRouterStatus } => { - const { permissions } = usePermissions(); + const { permissions, isLoading } = usePermissions(); // Whenever children are updated, update our custom routes and resources const [routesAndResources, status] = useRoutesAndResourcesFromChildren( children, - permissions + permissions, + isLoading ); // Whenever the resources change, we must ensure they're all registered @@ -70,7 +71,8 @@ export const useConfigureAdminRouterFromChildren = ( */ const useRoutesAndResourcesFromChildren = ( children: ReactNode, - permissions: any + permissions: any, + isLoading: boolean ): [RoutesAndResources, AdminRouterStatus] => { // Gather custom routes and resources that were declared as direct children of CoreAdminRouter // e.g. Not returned from the child function (if any) @@ -136,11 +138,14 @@ const useRoutesAndResourcesFromChildren = ( resolveChildFunction(functionChild); } }; - updateFromChildren(); + if (!isLoading) { + updateFromChildren(); + } }, [ authenticated, children, doLogout, + isLoading, mergeRoutesAndResources, permissions, setRoutesAndResources, diff --git a/packages/ra-no-code/src/Admin.spec.tsx b/packages/ra-no-code/src/Admin.spec.tsx index 1d459a12398..a5039668205 100644 --- a/packages/ra-no-code/src/Admin.spec.tsx +++ b/packages/ra-no-code/src/Admin.spec.tsx @@ -47,6 +47,10 @@ describe('Admin', () => { ); + await waitFor(() => { + screen.getByLabelText('CSV File'); + }); + userEvents.upload(screen.getByLabelText('CSV File'), file); await screen.findByDisplayValue('customers');