avoid offset race cycle in groups as well

This commit is contained in:
Min RK
2024-05-15 10:42:58 +02:00
parent 2af252c4c3
commit cedf237852
3 changed files with 28 additions and 18 deletions

View File

@@ -14,8 +14,7 @@ const Groups = (props) => {
const dispatch = useDispatch();
const navigate = useNavigate();
const { setOffset, offset, handleLimit, limit, setPagination } =
usePaginationParams();
const { offset, handleLimit, limit, setPagination } = usePaginationParams();
const total = groups_page ? groups_page.total : undefined;
@@ -32,11 +31,22 @@ const Groups = (props) => {
});
};
// single callback to reload the page
// uses current state, or params can be specified if state
// should be updated _after_ load, e.g. offset
const loadPageData = (params) => {
params = params || {};
return updateGroups(
params.offset === undefined ? offset : params.offset,
params.limit === undefined ? limit : params.limit,
)
.then((data) => dispatchPageUpdate(data.items, data._pagination))
.catch((err) => setErrorAlert("Failed to update group list."));
};
useEffect(() => {
updateGroups(offset, limit).then((data) =>
dispatchPageUpdate(data.items, data._pagination),
);
}, [offset, limit]);
loadPageData();
}, [limit]);
if (!groups_data || !groups_page) {
return <div data-testid="no-show"></div>;
@@ -72,8 +82,10 @@ const Groups = (props) => {
limit={limit}
visible={groups_data.length}
total={total}
next={() => setOffset(offset + limit)}
prev={() => setOffset(offset - limit)}
next={() => loadPageData({ offset: offset + limit })}
prev={() =>
loadPageData({ offset: limit > offset ? 0 : offset - limit })
}
handleLimit={handleLimit}
/>
</Card.Body>

View File

@@ -112,8 +112,8 @@ test("Renders nothing if required data is not available", async () => {
expect(noShow).toBeVisible();
});
test("Interacting with PaginationFooter causes state update and refresh via useEffect call", async () => {
let upgradeGroupsSpy = mockAsync();
test("Interacting with PaginationFooter causes page refresh", async () => {
let updateGroupsSpy = mockAsync();
let setSearchParamsSpy = mockAsync();
let searchParams = new URLSearchParams({ limit: "2" });
useSearchParams.mockImplementation(() => [
@@ -125,11 +125,11 @@ test("Interacting with PaginationFooter causes state update and refresh via useE
]);
let _, setSearchParams;
await act(async () => {
render(groupsJsx(upgradeGroupsSpy));
render(groupsJsx(updateGroupsSpy));
[_, setSearchParams] = useSearchParams();
});
expect(upgradeGroupsSpy).toBeCalledWith(0, 2);
expect(updateGroupsSpy).toBeCalledWith(0, 2);
var lastState =
mockReducers.mock.results[mockReducers.mock.results.length - 1].value;
@@ -140,9 +140,7 @@ test("Interacting with PaginationFooter causes state update and refresh via useE
await act(async () => {
fireEvent.click(next);
});
expect(setSearchParamsSpy).toBeCalledWith("limit=2&offset=2");
// FIXME: mocked useSelector, state seem to prevent updateGroups from being called
// making the test environment not representative
// expect(callbackSpy).toHaveBeenCalledWith(2, 2);
expect(updateGroupsSpy).toBeCalledWith(2, 2);
// mocked updateGroups means callback after load doesn't fire
// expect(setSearchParamsSpy).toBeCalledWith("limit=2&offset=2");
});

View File

@@ -155,7 +155,7 @@ const ServerDashboard = (props) => {
useEffect(() => {
loadPageData();
}, [offset, limit, name_filter, sort, state_filter]);
}, [limit, name_filter, sort, state_filter]);
if (!user_data || !user_page) {
return <div data-testid="no-show"></div>;