2022-05-17 12:32:04 +00:00
|
|
|
import { useState, useContext } from "react";
|
2022-08-06 12:25:56 +00:00
|
|
|
import { useNavigate } from "react-router-dom";
|
2022-08-09 04:29:10 +00:00
|
|
|
import { useCurrentlyFailing, useSilencedAlerts } from "../../Queries.jsx";
|
2022-07-12 21:48:05 +00:00
|
|
|
import StoreContext from "../../ctx/StoreContext.jsx";
|
|
|
|
import JobContext from "../../ctx/JobContext.jsx";
|
|
|
|
import SilenceDialog from "../alerting/SilenceDialog.jsx";
|
|
|
|
import FailingBox from "./FailingBox.jsx";
|
2022-05-17 12:32:04 +00:00
|
|
|
|
2022-05-23 00:24:21 +00:00
|
|
|
import SpeedDial from "@mui/material/SpeedDial";
|
2022-05-17 12:32:04 +00:00
|
|
|
|
2022-05-23 00:24:21 +00:00
|
|
|
import Button from "@mui/material/Button";
|
|
|
|
import Dialog from "@mui/material/Dialog";
|
|
|
|
import DialogActions from "@mui/material/DialogActions";
|
|
|
|
import DialogContent from "@mui/material/DialogContent";
|
|
|
|
import DialogContentText from "@mui/material/DialogContentText";
|
|
|
|
import DialogTitle from "@mui/material/DialogTitle";
|
2022-05-17 12:32:04 +00:00
|
|
|
|
2022-05-23 00:24:21 +00:00
|
|
|
import ReplayIcon from "@mui/icons-material/Replay";
|
2022-08-06 21:21:41 +00:00
|
|
|
import Box from "@mui/material/Box";
|
|
|
|
|
|
|
|
import Typography from "@mui/material/Typography";
|
2022-05-23 00:24:21 +00:00
|
|
|
|
2022-05-17 12:32:04 +00:00
|
|
|
export default function Failing() {
|
2022-08-05 13:03:48 +00:00
|
|
|
const { state: jobState, retryAll } = useContext(JobContext);
|
2022-08-06 12:25:56 +00:00
|
|
|
const navigate = useNavigate();
|
2022-06-22 00:47:19 +00:00
|
|
|
const {
|
|
|
|
state: store,
|
|
|
|
updateStore,
|
|
|
|
silenceRequest,
|
|
|
|
} = useContext(StoreContext);
|
2022-08-09 04:29:10 +00:00
|
|
|
const { isLoading, data: failing } = useCurrentlyFailing();
|
|
|
|
const { isSilencedLoading, data: silencedAlerts } = useSilencedAlerts();
|
2022-06-22 00:47:19 +00:00
|
|
|
const [silenceEntry, setSilenceEntry] = useState({ open: false });
|
|
|
|
|
|
|
|
const closeSilence = () => setSilenceEntry({ ...silenceEntry, open: false });
|
|
|
|
|
|
|
|
const handleSilenceClose = (silenceReq) => {
|
|
|
|
closeSilence();
|
|
|
|
if (!silenceReq) return;
|
|
|
|
silenceRequest(silenceReq);
|
|
|
|
};
|
|
|
|
|
|
|
|
const editSilence = (silence) => () => {
|
|
|
|
setSilenceEntry({ ...silence, open: true });
|
|
|
|
};
|
|
|
|
|
2022-05-17 12:32:04 +00:00
|
|
|
const [retryAllOpen, setRetryAllOpen] = useState(false);
|
|
|
|
const retryAllClick = () => setRetryAllOpen(!retryAllOpen);
|
2022-06-22 00:47:19 +00:00
|
|
|
|
2022-05-23 00:24:21 +00:00
|
|
|
const handleClose = (confirmed) => () => {
|
2022-05-17 12:32:04 +00:00
|
|
|
retryAllClick();
|
2022-05-23 00:24:21 +00:00
|
|
|
if (!confirmed) return;
|
2022-08-06 12:25:56 +00:00
|
|
|
const jobId = retryAll(store.failing);
|
|
|
|
|
|
|
|
if (!store.focusJob) return;
|
|
|
|
navigate(`/qualiteer/jobs#${jobId}`);
|
2022-05-23 00:24:21 +00:00
|
|
|
};
|
|
|
|
|
2022-08-06 22:09:37 +00:00
|
|
|
const failingTestsWithJobs = () => {
|
|
|
|
const silences = silencedAlerts ?? [];
|
2022-08-09 04:29:10 +00:00
|
|
|
for (var test of failing) {
|
|
|
|
const silence = silences.find(
|
|
|
|
(s) => s.name === test.name || s.class === test.class
|
|
|
|
);
|
|
|
|
|
|
|
|
if (silence) test.silencedUntil = silence;
|
2022-08-10 12:39:09 +00:00
|
|
|
if (test.isPipeline) {
|
|
|
|
const pipeline = jobState.pipelines.find((p) =>
|
|
|
|
p.selectedBranches.includes(test.name)
|
|
|
|
);
|
|
|
|
if (!pipeline) continue;
|
|
|
|
const pipelineJob = jobState.jobs.find(
|
|
|
|
(j) =>
|
|
|
|
j.isPipeline &&
|
|
|
|
j.pipelineId === pipeline.id &&
|
|
|
|
j.branchId === test.name
|
|
|
|
);
|
|
|
|
if (!pipelineJob) test.pipeline = pipeline;
|
|
|
|
test.job = pipelineJob;
|
|
|
|
continue;
|
|
|
|
}
|
|
|
|
const job = jobState.jobs.find(
|
|
|
|
(j) => !j.isPipeline && j.builderCache.testNames.includes(test.name)
|
|
|
|
);
|
|
|
|
if (job) test.job = job;
|
2022-08-06 22:09:37 +00:00
|
|
|
}
|
|
|
|
return failing;
|
2022-08-09 04:29:10 +00:00
|
|
|
};
|
2022-08-06 22:09:37 +00:00
|
|
|
|
2022-05-17 12:32:04 +00:00
|
|
|
return (
|
|
|
|
<div className="failing">
|
2022-08-09 04:29:10 +00:00
|
|
|
{isLoading
|
|
|
|
? null
|
|
|
|
: failingTestsWithJobs().map((v, i) => (
|
|
|
|
<FailingBox key={i} failingTest={v} silenceClick={editSilence(v)} />
|
|
|
|
))}
|
2022-05-17 12:32:04 +00:00
|
|
|
|
|
|
|
<Dialog
|
|
|
|
open={retryAllOpen}
|
|
|
|
onClose={handleClose()}
|
2022-05-23 00:24:21 +00:00
|
|
|
sx={{ "& .MuiDialog-paper": { width: "80%", maxHeight: 435 } }}
|
|
|
|
maxWidth="xs"
|
2022-05-17 12:32:04 +00:00
|
|
|
>
|
2022-05-23 00:24:21 +00:00
|
|
|
<DialogTitle>Retry all failing tests?</DialogTitle>
|
2022-05-17 12:32:04 +00:00
|
|
|
<DialogContent>
|
|
|
|
<DialogContentText>
|
|
|
|
This will create x jobs and run y tests
|
|
|
|
</DialogContentText>
|
|
|
|
</DialogContent>
|
|
|
|
<DialogActions>
|
|
|
|
<Button onClick={handleClose()}>Cancel</Button>
|
|
|
|
<Button onClick={handleClose(true)} autoFocus>
|
|
|
|
Yes
|
|
|
|
</Button>
|
|
|
|
</DialogActions>
|
|
|
|
</Dialog>
|
2022-06-22 00:47:19 +00:00
|
|
|
<SilenceDialog
|
|
|
|
keepMounted
|
|
|
|
open={silenceEntry.open}
|
|
|
|
onClose={handleSilenceClose}
|
|
|
|
silence={silenceEntry}
|
|
|
|
/>
|
2022-08-09 04:29:10 +00:00
|
|
|
{(failing ?? []).length === 0 ? (
|
|
|
|
<Box display="flex" alignItems="center" justifyContent="center">
|
|
|
|
<Typography variant="h4">No tests failing!</Typography>
|
|
|
|
</Box>
|
|
|
|
) : null}
|
|
|
|
|
|
|
|
{(failing ?? []).length === 0 ? null : (
|
|
|
|
<SpeedDial
|
|
|
|
ariaLabel="Retry All"
|
|
|
|
sx={{ position: "fixed", bottom: 16, right: 16 }}
|
|
|
|
icon={<ReplayIcon />}
|
|
|
|
onClick={retryAllClick}
|
|
|
|
open={false}
|
|
|
|
/>
|
|
|
|
)}
|
2022-05-17 12:32:04 +00:00
|
|
|
</div>
|
|
|
|
);
|
|
|
|
}
|