import * as React from 'react';
import {
AccessControl,
Basic,
DefaultTitle,
Empty,
FetchError,
Loading,
NoAuthProvider,
WithAuthProviderNoAccessControl,
WithRenderProps,
} from './InfiniteListBase.stories';
import { fireEvent, render, screen, waitFor } from '@testing-library/react';
import { testDataProvider } from '../../dataProvider';
describe('InfiniteListBase', () => {
it('should fetch a list of records on mount, put it in a ListContext, and render its children', async () => {
render();
expect(screen.queryByText('Loading...')).not.toBeNull();
await waitFor(() => {
expect(screen.queryByText('Loading...')).toBeNull();
});
await screen.findByText('War and Peace');
});
it('should create an InfinitePaginationContext allowing to fetch following pages', async () => {
render();
await waitFor(() => {
expect(screen.queryByText('Loading...')).toBeNull();
});
// first page is visible
await screen.findByText('The Lord of the Rings'); // #5
// next page is not visible
expect(screen.queryByText('And Then There Were None')).toBeNull(); // #6
screen.getByText('Next').click();
// next page is now visible
await screen.findByText('And Then There Were None'); // #6
// first page is still visible
await screen.findByText('The Lord of the Rings'); // #5
});
it('should load data immediately if authProvider is not provided', async () => {
const dataProvider = testDataProvider({
// @ts-ignore
getList: jest.fn(() =>
Promise.resolve({ data: [{ id: 1, title: 'Hello' }], total: 1 })
),
});
render();
expect(dataProvider.getList).toHaveBeenCalled();
await screen.findByText('Hello');
});
it('should wait for the authentication resolution before loading data', async () => {
let resolveAuth: () => void;
const authProvider = {
login: () => Promise.resolve(),
logout: () => Promise.resolve(),
checkError: () => Promise.resolve(),
checkAuth: () =>
new Promise(resolve => {
resolveAuth = resolve;
}),
};
const dataProvider = testDataProvider({
// @ts-ignore
getList: jest.fn(() =>
Promise.resolve({ data: [{ id: 1, title: 'Hello' }], total: 1 })
),
});
render(
);
expect(dataProvider.getList).not.toHaveBeenCalled();
await screen.findByText('Authentication loading...');
resolveAuth!();
await screen.findByText('Hello');
});
it('should not wait for the authentication resolution before loading data when disableAuthentication is true', async () => {
const authProvider = {
login: () => Promise.resolve(),
logout: () => Promise.resolve(),
checkError: () => Promise.resolve(),
checkAuth: jest.fn(),
};
const dataProvider = testDataProvider({
// @ts-ignore
getList: jest.fn(() =>
Promise.resolve({ data: [{ id: 1, title: 'Hello' }], total: 1 })
),
});
render(
);
await screen.findByText('Hello');
expect(authProvider.checkAuth).not.toHaveBeenCalled();
});
it('should wait for both the authentication and authorization resolution before loading data', async () => {
let resolveAuth: () => void;
let resolveCanAccess: (value: boolean) => void;
const authProvider = {
login: () => Promise.resolve(),
logout: () => Promise.resolve(),
checkError: () => Promise.resolve(),
checkAuth: () =>
new Promise(resolve => {
resolveAuth = resolve;
}),
canAccess: jest.fn(
() =>
new Promise(resolve => {
resolveCanAccess = resolve;
})
),
};
const dataProvider = testDataProvider({
// @ts-ignore
getList: jest.fn(() =>
Promise.resolve({ data: [{ id: 1, title: 'Hello' }], total: 1 })
),
});
render(
);
expect(dataProvider.getList).not.toHaveBeenCalled();
await screen.findByText('Authentication loading...');
resolveAuth!();
expect(dataProvider.getList).not.toHaveBeenCalled();
await screen.findByText('Authentication loading...');
await waitFor(() => {
expect(authProvider.canAccess).toHaveBeenCalled();
});
resolveCanAccess!(true);
await screen.findByText('Hello');
});
it('should provide a default title', async () => {
render();
await screen.findByText('Books (en)');
fireEvent.click(screen.getByText('FR'));
await screen.findByText('Livres (fr)');
});
it('should allow resource specific default title', async () => {
render();
await screen.findByText('Book list (en)');
fireEvent.click(screen.getByText('FR'));
await screen.findByText('Liste des livres (fr)');
});
it('should allow render props', async () => {
render();
await screen.findByText('War and Peace');
expect(screen.queryByText('Loading...')).toBeNull();
});
it('should render a custom empty component when data is empty', async () => {
render();
expect(screen.queryByText('Loading...')).not.toBeNull();
expect(screen.queryByText('War and Peace')).toBeNull();
fireEvent.click(screen.getByText('Resolve books loading'));
await screen.findByText('No books');
});
it('should render loading component while loading', async () => {
render();
expect(screen.queryByText('Loading books...')).not.toBeNull();
expect(screen.queryByText('War and Peace')).toBeNull();
fireEvent.click(screen.getByText('Resolve books loading'));
await waitFor(() => {
expect(screen.queryByText('Loading books...')).toBeNull();
});
await screen.findByText('War and Peace');
});
it('should render error component on error', async () => {
jest.spyOn(console, 'error').mockImplementation(() => {});
render();
expect(screen.queryByText('Cannot load books.')).toBeNull();
expect(screen.queryByText('War and Peace')).toBeNull();
fireEvent.click(screen.getByText('Reject books loading'));
await waitFor(() => {
expect(screen.queryByText('Cannot load books.')).not.toBeNull();
});
expect(screen.queryByText('War and Peace')).toBeNull();
jest.spyOn(console, 'error').mockRestore();
});
});