mirror of
https://github.com/jupyterhub/jupyterhub.git
synced 2025-10-12 04:23:01 +00:00
Add front end tests for user search
This commit is contained in:
@@ -60,6 +60,7 @@
|
||||
},
|
||||
"devDependencies": {
|
||||
"@wojtekmaj/enzyme-adapter-react-17": "^0.6.5",
|
||||
"sinon": "^13.0.1",
|
||||
"babel-jest": "^26.6.3",
|
||||
"enzyme": "^3.11.0",
|
||||
"eslint": "^7.18.0",
|
||||
|
@@ -1,6 +1,7 @@
|
||||
export const initialState = {
|
||||
user_data: undefined,
|
||||
user_page: 0,
|
||||
name_filter: "",
|
||||
groups_data: undefined,
|
||||
groups_page: 0,
|
||||
limit: window.api_page_limit,
|
||||
@@ -13,6 +14,7 @@ export const reducers = (state = initialState, action) => {
|
||||
return Object.assign({}, state, {
|
||||
user_page: action.value.page,
|
||||
user_data: action.value.data,
|
||||
name_filter: action.value.name_filter,
|
||||
});
|
||||
|
||||
// Updates the client group model data and stores the page
|
||||
|
@@ -38,12 +38,12 @@ const ServerDashboard = (props) => {
|
||||
|
||||
var [errorAlert, setErrorAlert] = useState(null);
|
||||
var [sortMethod, setSortMethod] = useState(null);
|
||||
var [name_filter, setNameFilter] = useState("");
|
||||
var [disabledButtons, setDisabledButtons] = useState({});
|
||||
|
||||
var user_data = useSelector((state) => state.user_data),
|
||||
user_page = useSelector((state) => state.user_page),
|
||||
limit = useSelector((state) => state.limit),
|
||||
name_filter = useSelector((state) => state.name_filter),
|
||||
page = parseInt(new URLSearchParams(props.location.search).get("page"));
|
||||
|
||||
page = isNaN(page) ? 0 : page;
|
||||
@@ -61,12 +61,13 @@ const ServerDashboard = (props) => {
|
||||
history,
|
||||
} = props;
|
||||
|
||||
var dispatchPageUpdate = (data, page) => {
|
||||
var dispatchPageUpdate = (data, page, name_filter) => {
|
||||
dispatch({
|
||||
type: "USER_PAGE",
|
||||
value: {
|
||||
data: data,
|
||||
page: page,
|
||||
name_filter: name_filter,
|
||||
},
|
||||
});
|
||||
};
|
||||
@@ -76,14 +77,16 @@ const ServerDashboard = (props) => {
|
||||
}
|
||||
|
||||
if (page != user_page) {
|
||||
updateUsers(...slice).then((data) => dispatchPageUpdate(data, page));
|
||||
updateUsers(...slice).then((data) =>
|
||||
dispatchPageUpdate(data, page, name_filter)
|
||||
);
|
||||
}
|
||||
|
||||
var debounce = require("lodash.debounce");
|
||||
const handleSearch = debounce(async (event) => {
|
||||
setNameFilter(event.target.value);
|
||||
// setNameFilter(event.target.value);
|
||||
updateUsers(page * limit, limit, event.target.value).then((data) =>
|
||||
dispatchPageUpdate(data, page)
|
||||
dispatchPageUpdate(data, page, name_filter)
|
||||
);
|
||||
}, 300);
|
||||
|
||||
@@ -104,7 +107,7 @@ const ServerDashboard = (props) => {
|
||||
if (res.status < 300) {
|
||||
updateUsers(...slice)
|
||||
.then((data) => {
|
||||
dispatchPageUpdate(data, page);
|
||||
dispatchPageUpdate(data, page, name_filter);
|
||||
})
|
||||
.catch(() => {
|
||||
setIsDisabled(false);
|
||||
@@ -140,7 +143,7 @@ const ServerDashboard = (props) => {
|
||||
if (res.status < 300) {
|
||||
updateUsers(...slice)
|
||||
.then((data) => {
|
||||
dispatchPageUpdate(data, page);
|
||||
dispatchPageUpdate(data, page, name_filter);
|
||||
})
|
||||
.catch(() => {
|
||||
setErrorAlert(`Failed to update users list.`);
|
||||
@@ -220,7 +223,8 @@ const ServerDashboard = (props) => {
|
||||
type="text"
|
||||
name="user_search"
|
||||
placeholder="Search users"
|
||||
defaultValue={name_filter}
|
||||
aria-label="user-search"
|
||||
value={name_filter}
|
||||
onChange={handleSearch}
|
||||
/>
|
||||
</Col>
|
||||
@@ -308,7 +312,7 @@ const ServerDashboard = (props) => {
|
||||
.then((res) => {
|
||||
updateUsers(...slice)
|
||||
.then((data) => {
|
||||
dispatchPageUpdate(data, page);
|
||||
dispatchPageUpdate(data, page, name_filter);
|
||||
})
|
||||
.catch(() =>
|
||||
setErrorAlert(`Failed to update users list.`)
|
||||
@@ -344,7 +348,7 @@ const ServerDashboard = (props) => {
|
||||
.then((res) => {
|
||||
updateUsers(...slice)
|
||||
.then((data) => {
|
||||
dispatchPageUpdate(data, page);
|
||||
dispatchPageUpdate(data, page, name_filter);
|
||||
})
|
||||
.catch(() =>
|
||||
setErrorAlert(`Failed to update users list.`)
|
||||
|
@@ -9,6 +9,9 @@ import { createStore } from "redux";
|
||||
import regeneratorRuntime from "regenerator-runtime";
|
||||
|
||||
import ServerDashboard from "./ServerDashboard";
|
||||
import * as sinon from "sinon";
|
||||
|
||||
let clock;
|
||||
|
||||
jest.mock("react-redux", () => ({
|
||||
...jest.requireActual("react-redux"),
|
||||
@@ -45,6 +48,7 @@ var mockAppState = () => ({
|
||||
});
|
||||
|
||||
beforeEach(() => {
|
||||
clock = sinon.useFakeTimers();
|
||||
useSelector.mockImplementation((callback) => {
|
||||
return callback(mockAppState());
|
||||
});
|
||||
@@ -52,6 +56,7 @@ beforeEach(() => {
|
||||
|
||||
afterEach(() => {
|
||||
useSelector.mockClear();
|
||||
clock.restore();
|
||||
});
|
||||
|
||||
test("Renders", async () => {
|
||||
@@ -435,3 +440,42 @@ test("Shows a UI error dialogue when stop user server returns an improper status
|
||||
|
||||
expect(errorDialog).toBeVisible();
|
||||
});
|
||||
|
||||
test("Search for user calls updateUsers with name filter", async () => {
|
||||
let spy = mockAsync();
|
||||
let mockUpdateUsers = jest.fn((offset, limit, name_filter) => {
|
||||
return Promise.resolve([]);
|
||||
});
|
||||
await act(async () => {
|
||||
render(
|
||||
<Provider store={createStore(() => {}, {})}>
|
||||
<HashRouter>
|
||||
<Switch>
|
||||
<ServerDashboard
|
||||
updateUsers={mockUpdateUsers}
|
||||
shutdownHub={spy}
|
||||
startServer={spy}
|
||||
stopServer={spy}
|
||||
startAll={spy}
|
||||
stopAll={spy}
|
||||
/>
|
||||
</Switch>
|
||||
</HashRouter>
|
||||
</Provider>
|
||||
);
|
||||
});
|
||||
|
||||
let search = screen.getByLabelText("user-search");
|
||||
|
||||
fireEvent.change(search, { target: { value: "a" } });
|
||||
clock.tick(400);
|
||||
expect(mockUpdateUsers.mock.calls).toHaveLength(2);
|
||||
expect(mockUpdateUsers.mock.calls[1][3]).toEqual("a");
|
||||
expect(search.value).toEqual("a");
|
||||
|
||||
fireEvent.change(search, { target: { value: "ab" } });
|
||||
clock.tick(400);
|
||||
expect(mockUpdateUsers.mock.calls).toHaveLength(3);
|
||||
expect(mockUpdateUsers.mock.calls[1][3]).toEqual("ab");
|
||||
expect(search.value).toEqual("ab");
|
||||
});
|
||||
|
@@ -1268,6 +1268,13 @@
|
||||
lodash "^4.17.15"
|
||||
lodash-es "^4.17.15"
|
||||
|
||||
"@sinonjs/commons@^1.6.0", "@sinonjs/commons@^1.8.3":
|
||||
version "1.8.3"
|
||||
resolved "https://registry.yarnpkg.com/@sinonjs/commons/-/commons-1.8.3.tgz#3802ddd21a50a949b6721ddd72da36e67e7f1b2d"
|
||||
integrity sha512-xkNcLAn/wZaX14RPlwizcKicDk9G3F8m2nU3L7Ukm5zBgTwiT0wsoFAHx9Jq56fJA1z/7uKGtCRu16sOUCLIHQ==
|
||||
dependencies:
|
||||
type-detect "4.0.8"
|
||||
|
||||
"@sinonjs/commons@^1.7.0":
|
||||
version "1.8.1"
|
||||
resolved "https://registry.npmjs.org/@sinonjs/commons/-/commons-1.8.1.tgz"
|
||||
@@ -1275,6 +1282,13 @@
|
||||
dependencies:
|
||||
type-detect "4.0.8"
|
||||
|
||||
"@sinonjs/fake-timers@>=5", "@sinonjs/fake-timers@^9.0.0":
|
||||
version "9.1.1"
|
||||
resolved "https://registry.yarnpkg.com/@sinonjs/fake-timers/-/fake-timers-9.1.1.tgz#7b698e0b9d12d93611f06ee143c30ced848e2840"
|
||||
integrity sha512-Wp5vwlZ0lOqpSYGKqr53INws9HLkt6JDc/pDZcPf7bchQnrXJMXPns8CXx0hFikMSGSWfvtvvpb2gtMVfkWagA==
|
||||
dependencies:
|
||||
"@sinonjs/commons" "^1.7.0"
|
||||
|
||||
"@sinonjs/fake-timers@^6.0.1":
|
||||
version "6.0.1"
|
||||
resolved "https://registry.npmjs.org/@sinonjs/fake-timers/-/fake-timers-6.0.1.tgz"
|
||||
@@ -1282,6 +1296,20 @@
|
||||
dependencies:
|
||||
"@sinonjs/commons" "^1.7.0"
|
||||
|
||||
"@sinonjs/samsam@^6.1.1":
|
||||
version "6.1.1"
|
||||
resolved "https://registry.yarnpkg.com/@sinonjs/samsam/-/samsam-6.1.1.tgz#627f7f4cbdb56e6419fa2c1a3e4751ce4f6a00b1"
|
||||
integrity sha512-cZ7rKJTLiE7u7Wi/v9Hc2fs3Ucc3jrWeMgPHbbTCeVAB2S0wOBbYlkJVeNSL04i7fdhT8wIbDq1zhC/PXTD2SA==
|
||||
dependencies:
|
||||
"@sinonjs/commons" "^1.6.0"
|
||||
lodash.get "^4.4.2"
|
||||
type-detect "^4.0.8"
|
||||
|
||||
"@sinonjs/text-encoding@^0.7.1":
|
||||
version "0.7.1"
|
||||
resolved "https://registry.yarnpkg.com/@sinonjs/text-encoding/-/text-encoding-0.7.1.tgz#8da5c6530915653f3a1f38fd5f101d8c3f8079c5"
|
||||
integrity sha512-+iTbntw2IZPb/anVDbypzfQa+ay64MW0Zo8aJ8gZPWMMK6/OubMVb6lUPMagqjOPnmtauXnFCACVl3O7ogjeqQ==
|
||||
|
||||
"@testing-library/dom@^8.0.0":
|
||||
version "8.11.1"
|
||||
resolved "https://registry.npmjs.org/@testing-library/dom/-/dom-8.11.1.tgz"
|
||||
@@ -2865,6 +2893,11 @@ diff-sequences@^27.4.0:
|
||||
resolved "https://registry.npmjs.org/diff-sequences/-/diff-sequences-27.4.0.tgz"
|
||||
integrity sha512-YqiQzkrsmHMH5uuh8OdQFU9/ZpADnwzml8z0O5HvRNda+5UZsaX/xN+AAxfR2hWq1Y7HZnAzO9J5lJXOuDz2Ww==
|
||||
|
||||
diff@^5.0.0:
|
||||
version "5.0.0"
|
||||
resolved "https://registry.yarnpkg.com/diff/-/diff-5.0.0.tgz#7ed6ad76d859d030787ec35855f5b1daf31d852b"
|
||||
integrity sha512-/VTCrvm5Z0JGty/BWHljh+BAiw3IK+2j87NGMu8Nwc/f48WoDAC395uomO9ZD117ZOBaHmkX1oyLvkVM/aIT3w==
|
||||
|
||||
discontinuous-range@1.0.0:
|
||||
version "1.0.0"
|
||||
resolved "https://registry.npmjs.org/discontinuous-range/-/discontinuous-range-1.0.0.tgz"
|
||||
@@ -5263,6 +5296,11 @@ jsprim@^1.2.2:
|
||||
array-includes "^3.1.2"
|
||||
object.assign "^4.1.2"
|
||||
|
||||
just-extend@^4.0.2:
|
||||
version "4.2.1"
|
||||
resolved "https://registry.yarnpkg.com/just-extend/-/just-extend-4.2.1.tgz#ef5e589afb61e5d66b24eca749409a8939a8c744"
|
||||
integrity sha512-g3UB796vUFIY90VIv/WX3L2c8CS2MdWUww3CNrYmqza1Fg0DURc2K/O4YrnklBdQarSJ/y8JnJYDGc+1iumQjg==
|
||||
|
||||
killable@^1.0.1:
|
||||
version "1.0.1"
|
||||
resolved "https://registry.npmjs.org/killable/-/killable-1.0.1.tgz"
|
||||
@@ -5381,6 +5419,11 @@ lodash.flattendeep@^4.4.0:
|
||||
resolved "https://registry.npmjs.org/lodash.flattendeep/-/lodash.flattendeep-4.4.0.tgz"
|
||||
integrity sha1-+wMJF/hqMTTlvJvsDWngAT3f7bI=
|
||||
|
||||
lodash.get@^4.4.2:
|
||||
version "4.4.2"
|
||||
resolved "https://registry.yarnpkg.com/lodash.get/-/lodash.get-4.4.2.tgz#2d177f652fa31e939b4438d5341499dfa3825e99"
|
||||
integrity sha1-LRd/ZS+jHpObRDjVNBSZ36OCXpk=
|
||||
|
||||
lodash.isequal@^4.5.0:
|
||||
version "4.5.0"
|
||||
resolved "https://registry.npmjs.org/lodash.isequal/-/lodash.isequal-4.5.0.tgz"
|
||||
@@ -5683,6 +5726,17 @@ nice-try@^1.0.4:
|
||||
resolved "https://registry.npmjs.org/nice-try/-/nice-try-1.0.5.tgz"
|
||||
integrity sha512-1nh45deeb5olNY7eX82BkPO7SSxR5SSYJiPTrTdFUVYwAl8CKMA5N9PjTYkHiRjisVcxcQ1HXdLhx2qxxJzLNQ==
|
||||
|
||||
nise@^5.1.1:
|
||||
version "5.1.1"
|
||||
resolved "https://registry.yarnpkg.com/nise/-/nise-5.1.1.tgz#ac4237e0d785ecfcb83e20f389185975da5c31f3"
|
||||
integrity sha512-yr5kW2THW1AkxVmCnKEh4nbYkJdB3I7LUkiUgOvEkOp414mc2UMaHMA7pjq1nYowhdoJZGwEKGaQVbxfpWj10A==
|
||||
dependencies:
|
||||
"@sinonjs/commons" "^1.8.3"
|
||||
"@sinonjs/fake-timers" ">=5"
|
||||
"@sinonjs/text-encoding" "^0.7.1"
|
||||
just-extend "^4.0.2"
|
||||
path-to-regexp "^1.7.0"
|
||||
|
||||
node-fetch@^1.0.1:
|
||||
version "1.7.3"
|
||||
resolved "https://registry.npmjs.org/node-fetch/-/node-fetch-1.7.3.tgz"
|
||||
@@ -7143,6 +7197,18 @@ signal-exit@^3.0.0, signal-exit@^3.0.2:
|
||||
resolved "https://registry.npmjs.org/signal-exit/-/signal-exit-3.0.3.tgz"
|
||||
integrity sha512-VUJ49FC8U1OxwZLxIbTTrDvLnf/6TDgxZcK8wxR8zs13xpx7xbG60ndBlhNrFi2EMuFRoeDoJO7wthSLq42EjA==
|
||||
|
||||
sinon@^13.0.1:
|
||||
version "13.0.1"
|
||||
resolved "https://registry.yarnpkg.com/sinon/-/sinon-13.0.1.tgz#2a568beca2084c48985dd98e276e065c81738e3c"
|
||||
integrity sha512-8yx2wIvkBjIq/MGY1D9h1LMraYW+z1X0mb648KZnKSdvLasvDu7maa0dFaNYdTDczFgbjNw2tOmWdTk9saVfwQ==
|
||||
dependencies:
|
||||
"@sinonjs/commons" "^1.8.3"
|
||||
"@sinonjs/fake-timers" "^9.0.0"
|
||||
"@sinonjs/samsam" "^6.1.1"
|
||||
diff "^5.0.0"
|
||||
nise "^5.1.1"
|
||||
supports-color "^7.2.0"
|
||||
|
||||
sisteransi@^1.0.5:
|
||||
version "1.0.5"
|
||||
resolved "https://registry.npmjs.org/sisteransi/-/sisteransi-1.0.5.tgz"
|
||||
@@ -7535,7 +7601,7 @@ supports-color@^6.1.0:
|
||||
dependencies:
|
||||
has-flag "^3.0.0"
|
||||
|
||||
supports-color@^7.0.0, supports-color@^7.1.0:
|
||||
supports-color@^7.0.0, supports-color@^7.1.0, supports-color@^7.2.0:
|
||||
version "7.2.0"
|
||||
resolved "https://registry.npmjs.org/supports-color/-/supports-color-7.2.0.tgz"
|
||||
integrity sha512-qpCAvRl9stuOHveKsn7HncJRvv501qIacKzQlO/+Lwxc9+0q2wLyv4Dfvt80/DPn2pqOBsJdDiogXGR9+OvwRw==
|
||||
@@ -7745,7 +7811,7 @@ type-check@~0.3.2:
|
||||
dependencies:
|
||||
prelude-ls "~1.1.2"
|
||||
|
||||
type-detect@4.0.8:
|
||||
type-detect@4.0.8, type-detect@^4.0.8:
|
||||
version "4.0.8"
|
||||
resolved "https://registry.npmjs.org/type-detect/-/type-detect-4.0.8.tgz"
|
||||
integrity sha512-0fr/mIH1dlO+x7TlcMy+bIDqKPsw/70tVyeHW787goQjhmqaZe10uwLujubK9q9Lg6Fiho1KUKDYz0Z7k7g5/g==
|
||||
|
File diff suppressed because one or more lines are too long
Reference in New Issue
Block a user