get most jsx tests passing

This commit is contained in:
Min RK
2024-03-06 01:26:34 +01:00
parent 87bf84d05f
commit f13e69b172
7 changed files with 206 additions and 156 deletions

View File

@@ -199,8 +199,8 @@ const DynamicTable = (props) => {
DynamicTable.propTypes = {
current_keys: PropTypes.array,
current_values: PropTypes.array,
setPropKeys: PropTypes.array,
setPropValues: PropTypes.array,
setPropKeys: PropTypes.func,
setPropValues: PropTypes.func,
setProp: PropTypes.func,
};
export default DynamicTable;

View File

@@ -6,6 +6,7 @@ import userEvent from "@testing-library/user-event";
import { Provider, useSelector } from "react-redux";
import { createStore } from "redux";
import { HashRouter } from "react-router-dom";
import { CompatRouter } from "react-router-dom-v5-compat";
// eslint-disable-next-line
import regeneratorRuntime from "regenerator-runtime";
@@ -27,6 +28,7 @@ var okPacket = new Promise((resolve) => resolve(true));
var groupEditJsx = (callbackSpy) => (
<Provider store={createStore(() => {}, {})}>
<HashRouter>
<CompatRouter>
<GroupEdit
location={{
state: {
@@ -41,6 +43,7 @@ var groupEditJsx = (callbackSpy) => (
updateGroups={callbackSpy}
validateUser={jest.fn().mockImplementation(() => okPacket)}
/>
</CompatRouter>
</HashRouter>
</Provider>
);

View File

@@ -3,7 +3,7 @@ import { useSelector, useDispatch } from "react-redux";
import PropTypes from "prop-types";
import { Link } from "react-router-dom";
import { useSearchParams } from "react-router-dom-v5-compat";
import { usePaginationParams } from "../../util/paginationParams";
import PaginationFooter from "../PaginationFooter/PaginationFooter";
const Groups = (props) => {

View File

@@ -5,6 +5,7 @@ import { render, screen, fireEvent } from "@testing-library/react";
import { Provider, useDispatch, useSelector } from "react-redux";
import { createStore } from "redux";
import { HashRouter } from "react-router-dom";
import { CompatRouter, useSearchParams } from "react-router-dom-v5-compat";
// eslint-disable-next-line
import regeneratorRuntime from "regenerator-runtime";
@@ -16,13 +17,20 @@ jest.mock("react-redux", () => ({
useSelector: jest.fn(),
}));
jest.mock("react-router-dom-v5-compat", () => ({
...jest.requireActual("react-router-dom-v5-compat"),
useSearchParams: jest.fn(),
}));
var mockAsync = () =>
jest.fn().mockImplementation(() => Promise.resolve({ key: "value" }));
var groupsJsx = (callbackSpy) => (
<Provider store={createStore(mockReducers, mockAppState())}>
<HashRouter>
<CompatRouter>
<Groups location={{ search: "0" }} updateGroups={callbackSpy} />
</CompatRouter>
</HashRouter>
</Provider>
);
@@ -50,11 +58,6 @@ var mockAppState = () =>
offset: 0,
limit: 2,
total: 4,
next: {
offset: 2,
limit: 2,
url: "http://localhost:8000/hub/api/groups?offset=2&limit=2",
},
},
});
@@ -62,11 +65,15 @@ beforeEach(() => {
useSelector.mockImplementation((callback) => {
return callback(mockAppState());
});
useSearchParams.mockImplementation(() => {
return [new URLSearchParams(), jest.fn()];
});
});
afterEach(() => {
useSelector.mockClear();
mockReducers.mockClear();
useSearchParams.mockClear();
});
test("Renders", async () => {
@@ -109,13 +116,23 @@ test("Renders nothing if required data is not available", async () => {
});
test("Interacting with PaginationFooter causes state update and refresh via useEffect call", async () => {
let callbackSpy = mockAsync();
let upgradeGroupsSpy = mockAsync();
let setSearchParamsSpy = mockAsync();
let searchParams = new URLSearchParams({ limit: "2" });
useSearchParams.mockImplementation(() => [
searchParams,
(callback) => {
searchParams = callback(searchParams);
setSearchParamsSpy(searchParams.toString());
},
]);
let _, setSearchParams;
await act(async () => {
render(groupsJsx(callbackSpy));
render(groupsJsx(upgradeGroupsSpy));
[_, setSearchParams] = useSearchParams();
});
expect(callbackSpy).toBeCalledWith(0, 2);
expect(upgradeGroupsSpy).toBeCalledWith(0, 2);
var lastState =
mockReducers.mock.results[mockReducers.mock.results.length - 1].value;
@@ -123,12 +140,10 @@ test("Interacting with PaginationFooter causes state update and refresh via useE
expect(lastState.groups_page.limit).toEqual(2);
let next = screen.getByTestId("paginate-next");
await act(async () => {
fireEvent.click(next);
lastState =
mockReducers.mock.results[mockReducers.mock.results.length - 1].value;
expect(lastState.groups_page.offset).toEqual(2);
expect(lastState.groups_page.limit).toEqual(2);
});
expect(setSearchParamsSpy).toBeCalledWith("limit=2&offset=2");
// FIXME: mocked useSelector, state seem to prevent updateGroups from being called
// making the test environment not representative

View File

@@ -55,13 +55,13 @@ const ServerDashboard = (props) => {
const [sortMethod, setSortMethod] = useState(null);
const [collapseStates, setCollapseStates] = useState({});
const user_data = useSelector((state) => state.user_data);
let user_data = useSelector((state) => state.user_data);
const user_page = useSelector((state) => state.user_page);
const { setOffset, offset, setLimit, handleLimit, limit, setPagination } =
usePaginationParams();
const name_filter = searchParams.get("name_filter");
const name_filter = searchParams.get("name_filter") || "";
const total = user_page ? user_page.total : undefined;

View File

@@ -10,6 +10,7 @@ import {
getAllByRole,
} from "@testing-library/react";
import { HashRouter, Switch } from "react-router-dom";
import { CompatRouter, useSearchParams } from "react-router-dom-v5-compat";
import { Provider, useSelector } from "react-redux";
import { createStore } from "redux";
// eslint-disable-next-line
@@ -25,10 +26,15 @@ jest.mock("react-redux", () => ({
...jest.requireActual("react-redux"),
useSelector: jest.fn(),
}));
jest.mock("react-router-dom-v5-compat", () => ({
...jest.requireActual("react-router-dom-v5-compat"),
useSearchParams: jest.fn(),
}));
var serverDashboardJsx = (spy) => (
<Provider store={createStore(mockReducers, mockAppState())}>
<HashRouter>
<CompatRouter>
<Switch>
<ServerDashboard
updateUsers={spy}
@@ -39,6 +45,7 @@ var serverDashboardJsx = (spy) => (
stopAll={spy}
/>
</Switch>
</CompatRouter>
</HashRouter>
</Provider>
);
@@ -137,14 +144,25 @@ var mockReducers = jest.fn((state, action) => {
return state;
});
let searchParams = new URLSearchParams();
beforeEach(() => {
clock = sinon.useFakeTimers();
useSelector.mockImplementation((callback) => {
return callback(mockAppState());
});
searchParams = new URLSearchParams();
useSearchParams.mockImplementation(() => [
searchParams,
(callback) => {
searchParams = callback(searchParams);
},
]);
});
afterEach(() => {
useSearchParams.mockClear();
useSelector.mockClear();
mockReducers.mockClear();
clock.restore();
@@ -350,16 +368,16 @@ test("Shows server details with button click", async () => {
await act(async () => {
fireEvent.click(button);
await clock.tick(400);
});
clock.tick(400);
expect(collapse).toHaveClass("collapse show");
expect(collapseBar).not.toHaveClass("show");
await act(async () => {
fireEvent.click(button);
await clock.tick(400);
});
clock.tick(400);
expect(collapse).toHaveClass("collapse");
expect(collapse).not.toHaveClass("show");
@@ -367,8 +385,8 @@ test("Shows server details with button click", async () => {
await act(async () => {
fireEvent.click(button);
await clock.tick(400);
});
clock.tick(400);
expect(collapse).toHaveClass("collapse show");
expect(collapseBar).not.toHaveClass("show");
@@ -398,6 +416,7 @@ test("Shows a UI error dialogue when start all servers fails", async () => {
render(
<Provider store={createStore(() => {}, {})}>
<HashRouter>
<CompatRouter>
<Switch>
<ServerDashboard
updateUsers={spy}
@@ -408,6 +427,7 @@ test("Shows a UI error dialogue when start all servers fails", async () => {
stopAll={spy}
/>
</Switch>
</CompatRouter>
</HashRouter>
</Provider>,
);
@@ -432,6 +452,7 @@ test("Shows a UI error dialogue when stop all servers fails", async () => {
render(
<Provider store={createStore(() => {}, {})}>
<HashRouter>
<CompatRouter>
<Switch>
<ServerDashboard
updateUsers={spy}
@@ -442,6 +463,7 @@ test("Shows a UI error dialogue when stop all servers fails", async () => {
stopAll={rejectSpy}
/>
</Switch>
</CompatRouter>
</HashRouter>
</Provider>,
);
@@ -466,6 +488,7 @@ test("Shows a UI error dialogue when start user server fails", async () => {
render(
<Provider store={createStore(() => {}, {})}>
<HashRouter>
<CompatRouter>
<Switch>
<ServerDashboard
updateUsers={spy}
@@ -476,6 +499,7 @@ test("Shows a UI error dialogue when start user server fails", async () => {
stopAll={spy}
/>
</Switch>
</CompatRouter>
</HashRouter>
</Provider>,
);
@@ -501,6 +525,7 @@ test("Shows a UI error dialogue when start user server returns an improper statu
render(
<Provider store={createStore(() => {}, {})}>
<HashRouter>
<CompatRouter>
<Switch>
<ServerDashboard
updateUsers={spy}
@@ -511,6 +536,7 @@ test("Shows a UI error dialogue when start user server returns an improper statu
stopAll={spy}
/>
</Switch>
</CompatRouter>
</HashRouter>
</Provider>,
);
@@ -536,6 +562,7 @@ test("Shows a UI error dialogue when stop user servers fails", async () => {
render(
<Provider store={createStore(() => {}, {})}>
<HashRouter>
<CompatRouter>
<Switch>
<ServerDashboard
updateUsers={spy}
@@ -546,6 +573,7 @@ test("Shows a UI error dialogue when stop user servers fails", async () => {
stopAll={spy}
/>
</Switch>
</CompatRouter>
</HashRouter>
</Provider>,
);
@@ -570,6 +598,7 @@ test("Shows a UI error dialogue when stop user server returns an improper status
render(
<Provider store={createStore(() => {}, {})}>
<HashRouter>
<CompatRouter>
<Switch>
<ServerDashboard
updateUsers={spy}
@@ -580,6 +609,7 @@ test("Shows a UI error dialogue when stop user server returns an improper status
stopAll={spy}
/>
</Switch>
</CompatRouter>
</HashRouter>
</Provider>,
);
@@ -616,6 +646,7 @@ test("Search for user calls updateUsers with name filter", async () => {
render(
<Provider store={createStore(mockReducers, mockAppState())}>
<HashRouter>
<CompatRouter>
<Switch>
<ServerDashboard
updateUsers={mockUpdateUsers}
@@ -626,6 +657,7 @@ test("Search for user calls updateUsers with name filter", async () => {
stopAll={spy}
/>
</Switch>
</CompatRouter>
</HashRouter>
</Provider>,
);
@@ -637,21 +669,20 @@ test("Search for user calls updateUsers with name filter", async () => {
userEvent.type(search, "a");
expect(search.value).toEqual("a");
clock.tick(400);
expect(mockReducers.mock.calls).toHaveLength(3);
var lastState =
mockReducers.mock.results[mockReducers.mock.results.length - 1].value;
expect(lastState.name_filter).toEqual("a");
// TODO: this should
expect(mockUpdateUsers.mock.calls).toHaveLength(1);
await act(async () => {
await clock.tick(400);
});
expect(searchParams.get("name_filter")).toEqual("a");
// FIXME: useSelector mocks prevent updateUsers from being called
// expect(mockUpdateUsers.mock.calls).toHaveLength(2);
// expect(mockUpdateUsers).toBeCalledWith(0, 100, "a");
userEvent.type(search, "b");
expect(search.value).toEqual("ab");
clock.tick(400);
expect(mockReducers.mock.calls).toHaveLength(4);
lastState =
mockReducers.mock.results[mockReducers.mock.results.length - 1].value;
expect(lastState.name_filter).toEqual("ab");
expect(lastState.user_page.offset).toEqual(0);
await act(async () => {
jest.runAllTimers();
});
expect(searchParams.get("name_filter")).toEqual("ab");
// expect(mockUpdateUsers).toBeCalledWith(0, 100, "ab");
});
test("Interacting with PaginationFooter causes state update and refresh via useEffect call", async () => {
@@ -661,24 +692,20 @@ test("Interacting with PaginationFooter causes state update and refresh via useE
render(serverDashboardJsx(callbackSpy));
});
expect(callbackSpy).toBeCalledWith(0, 2, "");
expect(callbackSpy).toBeCalledWith(0, 100, "");
expect(mockReducers.mock.results).toHaveLength(2);
lastState =
mockReducers.mock.results[mockReducers.mock.results.length - 1].value;
console.log(lastState);
expect(lastState.user_page.offset).toEqual(0);
expect(lastState.user_page.limit).toEqual(2);
var n = 3;
expect(searchParams.get("offset")).toEqual(null);
expect(searchParams.get("limit")).toEqual(null);
let next = screen.getByTestId("paginate-next");
await act(async () => {
fireEvent.click(next);
clock.tick(400);
await clock.tick(400);
});
expect(mockReducers.mock.results).toHaveLength(3);
var lastState =
mockReducers.mock.results[mockReducers.mock.results.length - 1].value;
expect(lastState.user_page.offset).toEqual(2);
expect(lastState.user_page.limit).toEqual(2);
expect(searchParams.get("offset")).toEqual("100");
expect(searchParams.get("limit")).toEqual(null);
// FIXME: should call updateUsers, does in reality.
// tests don't reflect reality due to mocked state/useSelector
@@ -721,6 +748,7 @@ test("Start server and confirm pending state", async () => {
render(
<Provider store={createStore(mockReducers, {})}>
<HashRouter>
<CompatRouter>
<Switch>
<ServerDashboard
updateUsers={mockUpdateUsers}
@@ -731,6 +759,7 @@ test("Start server and confirm pending state", async () => {
stopAll={spy}
/>
</Switch>
</CompatRouter>
</HashRouter>
</Provider>,
);

View File

@@ -6,7 +6,7 @@ export const usePaginationParams = () => {
const [searchParams, setSearchParams] = useSearchParams();
const offset = parseInt(searchParams.get("offset", "0")) || 0;
const limit =
parseInt(searchParams.get("limit", "0")) || window.api_page_limit;
parseInt(searchParams.get("limit", "0")) || window.api_page_limit || 100;
const _setOffset = (params, offset) => {
if (offset < 0) offset = 0;
@@ -26,6 +26,9 @@ export const usePaginationParams = () => {
};
const setPagination = (pagination) => {
// update pagination in one
if (!pagination) {
return;
}
setSearchParams((params) => {
_setOffset(params, pagination.offset);
_setLimit(params, pagination.limit);