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 (
{Object.keys(definitions).map(key => (
-
{JSON.stringify(definitions[key])}
))}
);
};
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,
});
});
});