import * as React from 'react';
import expect from 'expect';
import { render, screen } from '@testing-library/react';
import { stringify } from 'query-string';
import { createMemoryHistory } from 'history';
import { fireEvent, waitFor } from '@testing-library/react';
import { CoreAdminContext } from '../../core';
import { testDataProvider } from '../../dataProvider';
import { useStore } from '../../store/useStore';
import { useListParams, getQuery, getNumberOrDefault } from './useListParams';
import { SORT_DESC, SORT_ASC } from './queryReducer';
describe('useListParams', () => {
describe('getQuery', () => {
it('Returns the values from the location first', () => {
const query = getQuery({
queryFromLocation: {
page: 3,
perPage: 15,
sort: 'name',
order: SORT_ASC,
filter: { name: 'marmelab' },
},
params: {
page: 1,
perPage: 10,
sort: 'city',
order: SORT_DESC,
filter: {
city: 'Dijon',
},
},
filterDefaultValues: {},
perPage: 50,
sort: {
field: 'company',
order: SORT_DESC,
},
});
expect(query).toEqual({
page: 3,
perPage: 15,
sort: 'name',
order: SORT_ASC,
filter: {
name: 'marmelab',
},
});
});
it('Extends the values from the location with those from the props', () => {
const query = getQuery({
queryFromLocation: {
filter: { name: 'marmelab' },
},
params: {
page: 1,
perPage: 10,
sort: 'city',
order: SORT_DESC,
filter: {
city: 'Dijon',
},
},
filterDefaultValues: {},
perPage: 50,
sort: {
field: 'company',
order: SORT_DESC,
},
});
expect(query).toEqual({
page: 1,
perPage: 50,
sort: 'company',
order: SORT_DESC,
filter: {
name: 'marmelab',
},
});
});
it('Sets the values from the store if location does not have them', () => {
const query = getQuery({
queryFromLocation: {},
params: {
page: 2,
perPage: 10,
sort: 'city',
order: SORT_DESC,
filter: {
city: 'Dijon',
},
},
filterDefaultValues: {},
perPage: 50,
sort: {
field: 'company',
order: SORT_DESC,
},
});
expect(query).toEqual({
page: 2,
perPage: 10,
sort: 'city',
order: SORT_DESC,
filter: {
city: 'Dijon',
},
});
});
it('Extends the values from the store with those from the props', () => {
const query = getQuery({
queryFromLocation: {},
params: {
page: 2,
sort: 'city',
order: SORT_DESC,
filter: {
city: 'Dijon',
},
},
filterDefaultValues: {},
perPage: 50,
sort: {
field: 'company',
order: SORT_DESC,
},
});
expect(query).toEqual({
page: 2,
perPage: 50,
sort: 'city',
order: SORT_DESC,
filter: {
city: 'Dijon',
},
});
});
it('Uses the filterDefaultValues if neither the location or the store have them', () => {
const query = getQuery({
queryFromLocation: {},
params: {},
filterDefaultValues: { city: 'Nancy' },
perPage: 50,
sort: {
field: 'company',
order: SORT_DESC,
},
});
expect(query).toEqual({
page: 1,
perPage: 50,
sort: 'company',
order: SORT_DESC,
filter: {
city: 'Nancy',
},
});
});
});
describe('getNumberOrDefault', () => {
it('should return the parsed number', () => {
const result = getNumberOrDefault('29', 2);
expect(result).toEqual(29);
});
it('should return the default number when passing a not valid number', () => {
const result = getNumberOrDefault('covfefe', 2);
expect(result).toEqual(2);
});
it('should return the default number when passing an undefined number', () => {
const result = getNumberOrDefault(undefined, 2);
expect(result).toEqual(2);
});
it('should not return the default number when passing "0"', () => {
const result = getNumberOrDefault('0', 2);
expect(result).toEqual(0);
});
});
describe('showFilter', () => {
it('should initialize displayed filters', async () => {
const history = createMemoryHistory();
const navigate = jest.spyOn(history, 'push');
const TestedComponent = () => {
const [, { showFilter }] = useListParams({
resource: 'foo',
});
showFilter('foo', 'bar');
return ;
};
render(
);
await waitFor(() => {
expect(navigate).toHaveBeenCalledWith(
{
hash: '',
pathname: '/',
search:
'?' +
stringify({
displayedFilters: JSON.stringify({ foo: true }),
filter: JSON.stringify({ foo: 'bar' }),
sort: 'id',
order: 'ASC',
page: 1,
perPage: 10,
}),
},
{ _scrollToTop: false }
);
});
});
it('should initialize filters', async () => {
const history = createMemoryHistory();
const navigate = jest.spyOn(history, 'push');
const TestedComponent = () => {
const [, { showFilter }] = useListParams({
resource: 'foo',
});
showFilter('foo', 'bar');
return ;
};
render(
);
await waitFor(() => {
expect(navigate).toBeCalledWith(
{
hash: '',
pathname: '/',
search:
'?' +
stringify({
displayedFilters: JSON.stringify({ foo: true }),
filter: JSON.stringify({ foo: 'bar' }),
sort: 'id',
order: 'ASC',
page: 1,
perPage: 10,
}),
},
{ _scrollToTop: false }
);
});
});
it('should initialize displayed filters on compound filters', async () => {
const history = createMemoryHistory();
const navigate = jest.spyOn(history, 'push');
const TestedComponent = () => {
const [, { showFilter }] = useListParams({
resource: 'foo',
});
showFilter('foo.bar', 'baz');
return ;
};
render(
);
await waitFor(() => {
expect(navigate).toBeCalledWith(
{
hash: '',
pathname: '/',
search:
'?' +
stringify({
displayedFilters: JSON.stringify({
'foo.bar': true,
}),
filter: JSON.stringify({ foo: { bar: 'baz' } }),
sort: 'id',
order: 'ASC',
page: 1,
perPage: 10,
}),
},
{ _scrollToTop: false }
);
});
});
it('should initialize filters on compound filters', async () => {
const history = createMemoryHistory();
const navigate = jest.spyOn(history, 'push');
const TestedComponent = () => {
const [, { showFilter }] = useListParams({
resource: 'foo',
});
showFilter('foo.bar', 'baz');
return ;
};
render(
);
await waitFor(() => {
expect(navigate).toBeCalledWith(
{
hash: '',
pathname: '/',
search:
'?' +
stringify({
displayedFilters: JSON.stringify({
'foo.bar': true,
}),
filter: JSON.stringify({ foo: { bar: 'baz' } }),
sort: 'id',
order: 'ASC',
page: 1,
perPage: 10,
}),
},
{ _scrollToTop: false }
);
});
});
});
describe('useListParams', () => {
const Component = ({ disableSyncWithLocation = false }) => {
const [, { setPage }] = useListParams({
resource: 'posts',
disableSyncWithLocation,
});
const handleClick = () => {
setPage(10);
};
return ;
};
it('should synchronize parameters with location and store when sync is enabled', async () => {
const history = createMemoryHistory();
const navigate = jest.spyOn(history, 'push');
let storeValue;
const StoreReader = () => {
const [value] = useStore('posts.listParams');
React.useEffect(() => {
storeValue = value;
}, [value]);
return null;
};
render(
);
fireEvent.click(screen.getByText('update'));
await waitFor(() => {
expect(navigate).toHaveBeenCalled();
});
expect(storeValue).toEqual({
sort: 'id',
order: 'ASC',
page: 10,
perPage: 10,
filter: {},
});
});
test('should not synchronize parameters with location and store when sync is not enabled', async () => {
const history = createMemoryHistory();
const navigate = jest.spyOn(history, 'push');
let storeValue;
const StoreReader = () => {
const [value] = useStore('posts.listParams');
React.useEffect(() => {
storeValue = value;
}, [value]);
return null;
};
render(
);
fireEvent.click(screen.getByText('update'));
await waitFor(() => {
expect(navigate).not.toHaveBeenCalled();
expect(storeValue).toBeUndefined();
});
});
});
});