import * as React from 'react';
import expect from 'expect';
import { render, waitFor } from '@testing-library/react';
import { QueryClient } from 'react-query';
import { CoreAdminContext } from '../core';
import { useGetList } from './useGetList';
const UseGetList = ({
resource = 'posts',
pagination = { page: 1, perPage: 10 },
sort = { field: 'id', order: 'DESC' },
filter = {},
options = {},
meta = undefined,
callback = null,
...rest
}) => {
const hookValue = useGetList(
resource,
{ pagination, sort, filter, meta },
options
);
if (callback) callback(hookValue);
return
hello
;
};
describe('useGetList', () => {
it('should call dataProvider.getList() on mount', async () => {
const dataProvider = {
getList: jest.fn(() =>
Promise.resolve({ data: [{ id: 1, title: 'foo' }], total: 1 })
),
};
render(
);
await waitFor(() => {
expect(dataProvider.getList).toBeCalledTimes(1);
expect(dataProvider.getList).toBeCalledWith('posts', {
filter: {},
pagination: { page: 1, perPage: 20 },
sort: { field: 'id', order: 'DESC' },
});
});
});
it('should not call the dataProvider on update', async () => {
const dataProvider = {
getList: jest.fn(() =>
Promise.resolve({ data: [{ id: 1, title: 'foo' }], total: 1 })
),
};
const { rerender } = render(
);
await waitFor(() => {
expect(dataProvider.getList).toBeCalledTimes(1);
});
rerender(
);
await waitFor(() => {
expect(dataProvider.getList).toBeCalledTimes(1);
});
});
it('should call the dataProvider on update when the resource changes', async () => {
const dataProvider = {
getList: jest.fn(() =>
Promise.resolve({ data: [{ id: 1, title: 'foo' }], total: 1 })
),
};
const { rerender } = render(
);
await waitFor(() => {
expect(dataProvider.getList).toBeCalledTimes(1);
});
rerender(
);
await waitFor(() => {
expect(dataProvider.getList).toBeCalledTimes(2);
});
});
it('should accept a meta parameter', async () => {
const dataProvider = {
getList: jest.fn(() =>
Promise.resolve({ data: [{ id: 1, title: 'foo' }], total: 1 })
),
};
render(
);
await waitFor(() => {
expect(dataProvider.getList).toBeCalledWith('posts', {
filter: {},
pagination: { page: 1, perPage: 20 },
sort: { field: 'id', order: 'DESC' },
meta: { hello: 'world' },
});
});
});
it('should return initial data based on Query Cache', async () => {
const callback = jest.fn();
const queryClient = new QueryClient();
queryClient.setQueryData(
[
'posts',
'getList',
{
pagination: { page: 1, perPage: 10 },
sort: { field: 'id', order: 'DESC' },
filter: {},
},
],
{
data: [{ id: 1, title: 'cached' }],
total: 1,
}
);
const dataProvider = {
getList: jest.fn(() =>
Promise.resolve({ data: [{ id: 1, title: 'live' }], total: 1 })
),
};
render(
);
await waitFor(() => {
expect(callback).toHaveBeenCalledWith(
expect.objectContaining({ data: [{ id: 1, title: 'cached' }] })
);
});
await waitFor(() => {
expect(callback).toHaveBeenCalledWith(
expect.objectContaining({ data: [{ id: 1, title: 'live' }] })
);
});
});
it('should return isFetching false once the dataProvider returns', async () => {
const callback = jest.fn();
const dataProvider = {
getList: jest.fn(() =>
Promise.resolve({
data: [
{ id: 1, title: 'foo' },
{ id: 2, title: 'bar' },
],
total: 2,
})
),
};
render(
);
await waitFor(() => {
expect(callback).toHaveBeenCalledWith(
expect.objectContaining({ isFetching: true })
);
});
await waitFor(() => {
expect(callback).toHaveBeenCalledWith(
expect.objectContaining({ isFetching: false })
);
});
});
it('should set the error state when the dataProvider fails', async () => {
jest.spyOn(console, 'error').mockImplementation(() => {});
const callback = jest.fn();
const dataProvider = {
getList: jest.fn(() => Promise.reject(new Error('failed'))),
};
render(
);
await waitFor(() => {
expect(callback).toHaveBeenCalledWith(
expect.objectContaining({ error: null })
);
});
await waitFor(() => {
expect(callback).toHaveBeenCalledWith(
expect.objectContaining({ error: new Error('failed') })
);
});
});
it('should execute success side effects on success', async () => {
const onSuccess1 = jest.fn();
const onSuccess2 = jest.fn();
const dataProvider = {
getList: jest
.fn()
.mockReturnValueOnce(
Promise.resolve({
data: [
{ id: 1, title: 'foo' },
{ id: 2, title: 'bar' },
],
total: 2,
})
)
.mockReturnValueOnce(
Promise.resolve({
data: [
{ id: 3, foo: 1 },
{ id: 4, foo: 2 },
],
total: 2,
})
),
};
render(
);
await waitFor(() => {
expect(onSuccess1).toBeCalledTimes(1);
expect(onSuccess1.mock.calls.pop()[0]).toEqual({
data: [
{ id: 1, title: 'foo' },
{ id: 2, title: 'bar' },
],
total: 2,
});
expect(onSuccess2).toBeCalledTimes(1);
expect(onSuccess2.mock.calls.pop()[0]).toEqual({
data: [
{ id: 3, foo: 1 },
{ id: 4, foo: 2 },
],
total: 2,
});
});
});
it('should execute error side effects on failure', async () => {
jest.spyOn(console, 'error').mockImplementation(() => {});
const onError = jest.fn();
const dataProvider = {
getList: jest.fn(() => Promise.reject(new Error('failed'))),
};
render(
);
await waitFor(() => {
expect(onError).toBeCalledTimes(1);
expect(onError.mock.calls.pop()[0]).toEqual(new Error('failed'));
});
});
it('should pre-populate getOne Query Cache', async () => {
const callback = jest.fn();
const queryClient = new QueryClient();
const dataProvider = {
getList: jest.fn(() =>
Promise.resolve({ data: [{ id: 1, title: 'live' }], total: 1 })
),
};
render(
);
await waitFor(() => {
expect(callback).toHaveBeenCalledWith(
expect.objectContaining({ data: [{ id: 1, title: 'live' }] })
);
});
expect(
queryClient.getQueryData(['posts', 'getOne', { id: '1' }])
).toEqual({ id: 1, title: 'live' });
});
it('should still pre-populate getOne Query Cache with custom onSuccess', async () => {
const callback = jest.fn();
const onSuccess = jest.fn();
const queryClient = new QueryClient();
const dataProvider = {
getList: jest.fn(() =>
Promise.resolve({ data: [{ id: 1, title: 'live' }], total: 1 })
),
};
render(
);
await waitFor(() => {
expect(callback).toHaveBeenCalledWith(
expect.objectContaining({ data: [{ id: 1, title: 'live' }] })
);
});
await waitFor(() => {
expect(onSuccess).toHaveBeenCalledWith(
expect.objectContaining({ data: [{ id: 1, title: 'live' }] })
);
});
expect(
queryClient.getQueryData(['posts', 'getOne', { id: '1' }])
).toEqual({ id: 1, title: 'live' });
});
});