mirror of
https://github.com/jupyterhub/jupyterhub.git
synced 2025-10-12 20:43:02 +00:00
Add test for details view
This commit is contained in:
@@ -10,6 +10,7 @@ import {
|
|||||||
FormControl,
|
FormControl,
|
||||||
Card,
|
Card,
|
||||||
CardGroup,
|
CardGroup,
|
||||||
|
Collapse,
|
||||||
} from "react-bootstrap";
|
} from "react-bootstrap";
|
||||||
import ReactObjectTableViewer from "react-object-table-viewer";
|
import ReactObjectTableViewer from "react-object-table-viewer";
|
||||||
|
|
||||||
@@ -28,14 +29,6 @@ const AccessServerButton = ({ url }) => (
|
|||||||
</a>
|
</a>
|
||||||
);
|
);
|
||||||
|
|
||||||
const ToggleButton = ({ dataTarget }) => {
|
|
||||||
return (
|
|
||||||
<button data-toggle="collapse" data-target={dataTarget}>
|
|
||||||
<span className="caret"></span>
|
|
||||||
</button>
|
|
||||||
);
|
|
||||||
};
|
|
||||||
|
|
||||||
const ServerDashboard = (props) => {
|
const ServerDashboard = (props) => {
|
||||||
let base_url = window.base_url;
|
let base_url = window.base_url;
|
||||||
// sort methods
|
// sort methods
|
||||||
@@ -57,6 +50,7 @@ const ServerDashboard = (props) => {
|
|||||||
var [errorAlert, setErrorAlert] = useState(null);
|
var [errorAlert, setErrorAlert] = useState(null);
|
||||||
var [sortMethod, setSortMethod] = useState(null);
|
var [sortMethod, setSortMethod] = useState(null);
|
||||||
var [disabledButtons, setDisabledButtons] = useState({});
|
var [disabledButtons, setDisabledButtons] = useState({});
|
||||||
|
const [collapseStates, setCollapseStates] = useState({});
|
||||||
|
|
||||||
var user_data = useSelector((state) => state.user_data),
|
var user_data = useSelector((state) => state.user_data),
|
||||||
user_page = useSelector((state) => state.user_page),
|
user_page = useSelector((state) => state.user_page),
|
||||||
@@ -208,21 +202,38 @@ const ServerDashboard = (props) => {
|
|||||||
|
|
||||||
const serverRow = (user, server) => {
|
const serverRow = (user, server) => {
|
||||||
const { servers, ...userNoServers } = user;
|
const { servers, ...userNoServers } = user;
|
||||||
|
const serverNameDash = server.name ? `-${server.name}` : "";
|
||||||
|
const userServerName = user.name + serverNameDash;
|
||||||
|
const open = collapseStates[userServerName] || false;
|
||||||
return [
|
return [
|
||||||
<tr key={`${user.name}-${server.name}-row`} className="user-row">
|
<tr key={`${userServerName}-row`} className="user-row">
|
||||||
<td data-testid="user-row-name">
|
<td data-testid="user-row-name">
|
||||||
<span>
|
<span>
|
||||||
<ToggleButton
|
<Button
|
||||||
dataTarget={`#${user.name}-${server.name}-collapse`}
|
onClick={() =>
|
||||||
/>{" "}
|
setCollapseStates({
|
||||||
|
...collapseStates,
|
||||||
|
[userServerName]: !open,
|
||||||
|
})
|
||||||
|
}
|
||||||
|
aria-controls={`${userServerName}-collapse`}
|
||||||
|
aria-expanded={open}
|
||||||
|
data-testid={`${userServerName}-collapse-button`}
|
||||||
|
variant={open ? "secondary" : "primary"}
|
||||||
|
size="sm"
|
||||||
|
>
|
||||||
|
<span className="caret"></span>
|
||||||
|
</Button>{" "}
|
||||||
|
</span>
|
||||||
|
<span data-testid={`user-name-div-${userServerName}`}>
|
||||||
|
{user.name}
|
||||||
</span>
|
</span>
|
||||||
<div data-testid={`user-name-div-${user.name}`}>{user.name}</div>
|
|
||||||
</td>
|
</td>
|
||||||
<td data-testid="user-row-admin">{user.admin ? "admin" : ""}</td>
|
<td data-testid="user-row-admin">{user.admin ? "admin" : ""}</td>
|
||||||
|
|
||||||
<td data-testid="user-row-server">
|
<td data-testid="user-row-server">
|
||||||
{server.name ? (
|
{server.name ? (
|
||||||
<p class="text-secondary">{server.name}</p>
|
<p className="text-secondary">{server.name}</p>
|
||||||
) : (
|
) : (
|
||||||
<p style={{ color: "lightgrey" }}>[MAIN]</p>
|
<p style={{ color: "lightgrey" }}>[MAIN]</p>
|
||||||
)}
|
)}
|
||||||
@@ -263,11 +274,14 @@ const ServerDashboard = (props) => {
|
|||||||
<EditUserCell user={user} />
|
<EditUserCell user={user} />
|
||||||
</tr>,
|
</tr>,
|
||||||
<tr>
|
<tr>
|
||||||
<td colSpan={6} style={{ padding: 0 }}>
|
<td
|
||||||
{/*<div style={{ margin: "0 auto", float: "none" }}>*/}
|
colSpan={6}
|
||||||
|
style={{ padding: 0 }}
|
||||||
|
data-testid={`${userServerName}-td`}
|
||||||
|
>
|
||||||
|
<Collapse in={open} data-testid={`${userServerName}-collapse`}>
|
||||||
<CardGroup
|
<CardGroup
|
||||||
id={`${user.name}-${server.name}-collapse`}
|
id={`${userServerName}-card-group`}
|
||||||
className="collapse"
|
|
||||||
style={{ width: "90%", margin: "0 auto", float: "none" }}
|
style={{ width: "90%", margin: "0 auto", float: "none" }}
|
||||||
>
|
>
|
||||||
<Card style={{ width: "50%", padding: 6, float: "left" }}>
|
<Card style={{ width: "50%", padding: 6, float: "left" }}>
|
||||||
@@ -287,7 +301,9 @@ const ServerDashboard = (props) => {
|
|||||||
data={userNoServers}
|
data={userNoServers}
|
||||||
/>
|
/>
|
||||||
</Card>
|
</Card>
|
||||||
<Card style={{ width: "50%", padding: 6, display: "inline-block" }}>
|
<Card
|
||||||
|
style={{ width: "50%", padding: 6, display: "inline-block" }}
|
||||||
|
>
|
||||||
<Card.Title>Server</Card.Title>
|
<Card.Title>Server</Card.Title>
|
||||||
<ReactObjectTableViewer
|
<ReactObjectTableViewer
|
||||||
className="table-striped table-bordered admin-table-head"
|
className="table-striped table-bordered admin-table-head"
|
||||||
@@ -305,7 +321,7 @@ const ServerDashboard = (props) => {
|
|||||||
/>
|
/>
|
||||||
</Card>
|
</Card>
|
||||||
</CardGroup>
|
</CardGroup>
|
||||||
{/*</div>*/}
|
</Collapse>
|
||||||
</td>
|
</td>
|
||||||
</tr>,
|
</tr>,
|
||||||
];
|
];
|
||||||
|
@@ -221,6 +221,46 @@ test("Sorts according to server status (running/not running)", async () => {
|
|||||||
expect(first.textContent).toContain("bar");
|
expect(first.textContent).toContain("bar");
|
||||||
});
|
});
|
||||||
|
|
||||||
|
test("Shows server details with button click", async () => {
|
||||||
|
let callbackSpy = mockAsync();
|
||||||
|
|
||||||
|
await act(async () => {
|
||||||
|
render(serverDashboardJsx(callbackSpy));
|
||||||
|
});
|
||||||
|
let button = screen.getByTestId("foo-collapse-button");
|
||||||
|
let collapse = screen.getByTestId("foo-collapse");
|
||||||
|
let collapseBar = screen.getByTestId("bar-collapse");
|
||||||
|
|
||||||
|
expect(collapse.className).toContain("collapse");
|
||||||
|
expect(collapse.className).not.toContain("show");
|
||||||
|
expect(collapseBar.className).not.toContain("show");
|
||||||
|
|
||||||
|
await act(async () => {
|
||||||
|
fireEvent.click(button);
|
||||||
|
});
|
||||||
|
clock.tick(400);
|
||||||
|
|
||||||
|
expect(collapse.className).toContain("collapse show");
|
||||||
|
expect(collapseBar.className).not.toContain("show");
|
||||||
|
|
||||||
|
await act(async () => {
|
||||||
|
fireEvent.click(button);
|
||||||
|
});
|
||||||
|
clock.tick(400);
|
||||||
|
|
||||||
|
expect(collapse.className).toContain("collapse");
|
||||||
|
expect(collapse.className).not.toContain("show");
|
||||||
|
expect(collapseBar.className).not.toContain("show");
|
||||||
|
|
||||||
|
await act(async () => {
|
||||||
|
fireEvent.click(button);
|
||||||
|
});
|
||||||
|
clock.tick(400);
|
||||||
|
|
||||||
|
expect(collapse.className).toContain("collapse show");
|
||||||
|
expect(collapseBar.className).not.toContain("show");
|
||||||
|
});
|
||||||
|
|
||||||
test("Renders nothing if required data is not available", async () => {
|
test("Renders nothing if required data is not available", async () => {
|
||||||
useSelector.mockImplementation((callback) => {
|
useSelector.mockImplementation((callback) => {
|
||||||
return callback({});
|
return callback({});
|
||||||
|
File diff suppressed because one or more lines are too long
Reference in New Issue
Block a user