) => {
const [{ page, perPage, sort, order, filter }, { setPage }] =
useListParams({
resource: 'posts',
disableSyncWithLocation,
...options,
});
const handleClick = () => {
setPage(10);
};
return (
<>
page: {page}
perPage: {perPage}
sort: {sort}
order: {order}
filter: {JSON.stringify(filter)}
>
);
};
it('should synchronize parameters with location and store when sync is enabled', async () => {
let location;
let storeValue;
const StoreReader = () => {
const [value] = useStore('posts.listParams');
React.useEffect(() => {
storeValue = value;
}, [value]);
return null;
};
render(
{
location = l;
}}
>
);
fireEvent.click(screen.getByText('update'));
await waitFor(() => {
expect(location).toEqual(
expect.objectContaining({
pathname: '/',
search:
'?' +
stringify({
filter: JSON.stringify({}),
sort: 'id',
order: 'ASC',
page: 10,
perPage: 10,
}),
})
);
});
expect(storeValue).toEqual({
sort: 'id',
order: 'ASC',
page: 10,
perPage: 10,
filter: {},
});
});
it('should synchronize parameters with location and store when sync is enabled while keeping custom query params', async () => {
let locationSearchValue;
let storeValue;
const ComponentThatSetsCustomQueryString = ({
disableSyncWithLocation = false,
}) => {
const [_, { setFilters }] = useListParams({
resource: 'posts',
disableSyncWithLocation,
});
const handleClick = () => {
setFilters({ x: 'y' }, []);
};
return (
<>
>
);
};
const StoreReader = () => {
const [value] = useStore('posts.listParams');
React.useEffect(() => {
storeValue = value;
}, [value]);
return null;
};
render(
{
locationSearchValue = l.search;
}}
>
);
fireEvent.click(screen.getByText('set filters'));
await waitFor(() => {
expect(parse(locationSearchValue)).toEqual({
displayedFilters: '[]',
filter: '{"x":"y"}',
foo: 'bar',
order: 'ASC',
page: '1',
perPage: '10',
sort: 'id',
});
});
expect(storeValue).toEqual({
displayedFilters: [],
filter: { x: 'y' },
foo: 'bar',
order: 'ASC',
page: 1,
perPage: 10,
sort: 'id',
});
});
it('should synchronize location with store when sync is enabled', async () => {
let location;
let storeValue;
const StoreReader = () => {
const [value] = useStore('posts.listParams');
React.useEffect(() => {
storeValue = value;
}, [value]);
return null;
};
render(
{
location = l;
}}
>
);
await waitFor(() => {
expect(storeValue).toEqual({
sort: 'id',
order: 'ASC',
page: 10,
perPage: 10,
filter: {},
});
});
await waitFor(() => {
expect(location).toEqual(
expect.objectContaining({
hash: '',
key: expect.any(String),
state: null,
pathname: '/',
search:
'?' +
stringify({
filter: JSON.stringify({}),
sort: 'id',
order: 'ASC',
page: 10,
perPage: 10,
}),
})
);
});
});
it('should not synchronize parameters with location and store when sync is not enabled', async () => {
let location;
let storeValue;
const StoreReader = () => {
const [value] = useStore('posts.listParams');
React.useEffect(() => {
storeValue = value;
}, [value]);
return null;
};
render(
{
location = l;
}}
>
);
fireEvent.click(screen.getByText('update'));
await screen.findByText('page: 10');
expect(location).not.toEqual(
expect.objectContaining({
pathname: '/',
search:
'?' +
stringify({
filter: JSON.stringify({}),
sort: 'id',
order: 'ASC',
page: 10,
perPage: 10,
}),
})
);
expect(storeValue).toBeUndefined();
});
it('should not synchronize location with store if the location already contains parameters', async () => {
let location;
render(
{
location = l;
}}
>
);
await waitFor(() => {
expect(location).toEqual(
expect.objectContaining({
hash: '',
key: expect.any(String),
state: null,
pathname: '/',
search:
'?' +
stringify({
filter: JSON.stringify({}),
sort: 'id',
order: 'ASC',
page: 5,
perPage: 10,
}),
})
);
});
});
it('should not synchronize location with store if the store parameters are the defaults', async () => {
let location;
render(
{
location = l;
}}
>
);
// Let React do its thing
await new Promise(resolve => setTimeout(resolve, 0));
await waitFor(() => {
expect(location).toEqual(
expect.objectContaining({
hash: '',
key: expect.any(String),
state: null,
pathname: '/',
search: '',
})
);
});
});
it('should not synchronize location with store if the store parameters are the custom defaults provided to the hook', async () => {
let location;
render(
{
location = l;
}}
>
);
// Let React do its thing
await new Promise(resolve => setTimeout(resolve, 0));
// The list is using the default set on the component
await screen.findByText('perPage: 5');
await screen.findByText('sort: title');
await screen.findByText('order: DESC');
// The location is the default for the list (no query parameters)
await waitFor(() => {
expect(location).toEqual(
expect.objectContaining({
hash: '',
key: expect.any(String),
state: null,
pathname: '/',
search: '',
})
);
});
});
it('should not synchronize location with store when sync is not enabled', async () => {
let location;
let storeValue;
const StoreReader = () => {
const [value] = useStore('posts.listParams');
React.useEffect(() => {
storeValue = value;
}, [value]);
return null;
};
render(
{
location = l;
}}
>
);
await waitFor(() => {
expect(storeValue).toEqual({
sort: 'id',
order: 'ASC',
page: 10,
perPage: 10,
filter: {},
});
});
await waitFor(() => {
expect(location).toEqual(
expect.objectContaining({
hash: '',
key: expect.any(String),
state: null,
pathname: '/',
search: '',
})
);
});
});
it('should synchronize parameters with store when sync is not enabled and storeKey is passed', async () => {
let storeValue;
const Component = ({
disableSyncWithLocation = false,
storeKey = undefined,
}) => {
const [{ page }, { setPage }] = useListParams({
resource: 'posts',
disableSyncWithLocation,
storeKey,
});
const handleClick = () => {
setPage(10);
};
return (
<>
page: {page}
>
);
};
const StoreReader = () => {
const [value] = useStore('myListParams');
React.useEffect(() => {
storeValue = value;
}, [value]);
return null;
};
render(
);
fireEvent.click(screen.getByText('update'));
await screen.findByText('page: 10');
expect(storeValue).toEqual({
filter: {},
order: 'ASC',
page: 10,
perPage: 10,
sort: 'id',
});
});
});
});