Implemented test run editor's test case selection

This commit is contained in:
Takeshi Kimata
2024-04-20 23:26:47 +09:00
parent c5091833d0
commit e8376c07ef
6 changed files with 111 additions and 31 deletions

View File

@@ -90,8 +90,10 @@ app.use("/runs", runsEditRoute);
app.use("/runs", runDeleteRoute);
// "/runcases"
const runCaseIndexRoute = require("./routes/runcases/index")(sequelize);
const runCaseNewRoute = require("./routes/runcases/new")(sequelize);
const runCaseDeleteRoute = require("./routes/runcases/delete")(sequelize);
app.use("/runcases", runCaseIndexRoute);
app.use("/runcases", runCaseNewRoute);
app.use("/runcases", runCaseDeleteRoute);

View File

@@ -0,0 +1,30 @@
const express = require("express");
const router = express.Router();
const defineRunCase = require("../../models/runCases");
const { DataTypes } = require('sequelize');
module.exports = function(sequelize) {
const RunCase = defineRunCase(sequelize, DataTypes)
router.get("/", async (req, res) => {
const { runId } = req.query;
if (!runId) {
return res.status(400).json({ error: 'run is required' });
}
try {
const runCases = await RunCase.findAll({
where: {
runId: runId
}
});
res.json(runCases);
} catch (error) {
console.error(error);
res.status(500).send("Internal Server Error");
}
});
return router;
};

View File

@@ -1,14 +1,14 @@
const express = require("express");
const router = express.Router();
const defineRun = require("../../models/runs");
const defineCase = require("../../models/cases");
// const defineCase = require("../../models/cases");
const { DataTypes } = require("sequelize");
module.exports = function (sequelize) {
const Run = defineRun(sequelize, DataTypes);
const Case = defineCase(sequelize, DataTypes);
Run.belongsToMany(Case, { through: "runCases" });
Case.belongsToMany(Run, { through: "runCases" });
// const Case = defineCase(sequelize, DataTypes);
// Run.belongsToMany(Case, { through: "runCases" });
// Case.belongsToMany(Run, { through: "runCases" });
router.get("/:runId", async (req, res) => {
const runId = req.params.runId;
@@ -18,14 +18,15 @@ module.exports = function (sequelize) {
}
try {
const project = await Run.findByPk(runId, {
include: [
{
model: Case,
through: { attributes: ["status"] },
},
],
});
// const project = await Run.findByPk(runId, {
// include: [
// {
// model: Case,
// through: { attributes: ["status"] },
// },
// ],
// });
const project = await Run.findByPk(runId);
if (!project) {
return res.status(404).send("Run not found");
}

View File

@@ -28,12 +28,13 @@ import {
} from "lucide-react";
import TestCaseSelector from "./TestCaseSelector";
import { testRunStatus } from "@/config/selection";
import { RunType } from "@/types/run";
import { RunType, RunCaseType } from "@/types/run";
import { CaseType } from "@/types/case";
import { FolderType } from "@/types/folder";
import {
fetchRun,
updateRun,
fetchRunCases,
createRunCase,
deleteRunCase,
} from "../runsControl";
@@ -57,6 +58,7 @@ type Props = {
export default function RunEditor({ projectId, runId }: Props) {
const [testRun, setTestRun] = useState<RunType>(defaultTestRun);
const [folders, setFolders] = useState([]);
const [runCases, setRunCases] = useState<RunCaseType[]>([]);
const [selectedKeys, setSelectedKeys] = useState<Selection>(new Set([]));
const [selectedFolder, setSelectedFolder] = useState<FolderType>({});
const [testcases, setTestCases] = useState<CaseType[]>([]);
@@ -71,6 +73,8 @@ export default function RunEditor({ projectId, runId }: Props) {
setTestRun(runData);
const foldersData = await fetchFolders(projectId);
setFolders(foldersData);
const runCasesData = await fetchRunCases(runId);
setRunCases(runCasesData);
} catch (error: any) {
console.error("Error in effect:", error.message);
}
@@ -82,25 +86,23 @@ export default function RunEditor({ projectId, runId }: Props) {
const fetchAndUpdateCases = async () => {
try {
const testCasesData = await fetchCases(selectedFolder.id);
// Check if each testCase has an association with testRun
// and add "isIncluded" property
testCasesData.forEach((caseItr: CaseType) => {
let isIncluded: boolean = false;
let runStatus: number = 0;
const updatedTestCasesData = testCasesData.map((testCase) => {
const runCase = runCases.find(
(runCase) => runCase.caseId === testCase.id
);
testRun.Cases.forEach((runCaseItr: CaseType) => {
if (runCaseItr.id === caseItr.id) {
isIncluded = true;
runStatus = runCaseItr.runCases.status;
}
const isIncluded = runCase ? true : false;
const runStatus = runCase ? runCase.status : 0;
return {
...testCase,
isIncluded,
runStatus,
};
});
caseItr.isIncluded = isIncluded;
caseItr.runStatus = runStatus;
});
setTestCases(testCasesData);
setTestCases(updatedTestCasesData);
} catch (error: any) {
console.error("Error fetching cases data:", error.message);
}
@@ -109,6 +111,7 @@ export default function RunEditor({ projectId, runId }: Props) {
useEffect(() => {
async function fetchCasesData() {
if (selectedFolder && selectedFolder.id) {
console.log("fetchCasesData")
await fetchAndUpdateCases();
}
}
@@ -120,8 +123,9 @@ export default function RunEditor({ projectId, runId }: Props) {
isInclude: boolean,
clickedTestCaseId: number
) => {
let createdRunCase: RunCaseType;
if (isInclude) {
await createRunCase(runId, clickedTestCaseId);
createdRunCase = await createRunCase(runId, clickedTestCaseId);
} else {
await deleteRunCase(runId, clickedTestCaseId);
}
@@ -134,6 +138,18 @@ export default function RunEditor({ projectId, runId }: Props) {
return testCase;
});
});
if (isInclude) {
setRunCases((prevRunCases) => {
return [...prevRunCases, createdRunCase];
});
} else {
setRunCases((prevRunCases) => {
return prevRunCases.filter(
(runCase) => runCase.caseId !== clickedTestCaseId
);
});
}
};
const onIncludeExcludeClick = async (mode: string) => {

View File

@@ -123,6 +123,28 @@ async function deleteRun(runId: number) {
}
}
async function fetchRunCases(runId: string) {
const url = `${apiServer}/runcases?runId=${runId}`;
try {
const response = await fetch(url, {
method: "GET",
headers: {
"Content-Type": "application/json",
},
});
if (!response.ok) {
throw new Error(`HTTP error! Status: ${response.status}`);
}
const data = await response.json();
return data;
} catch (error: any) {
console.error("Error fetching data:", error.message);
}
}
async function createRunCase(runId: string, caseId: number) {
const fetchOptions = {
method: "POST",
@@ -167,4 +189,4 @@ async function deleteRunCase(runId: string, caseId: number) {
}
}
export { fetchRun, fetchRuns, createRun, updateRun, deleteRun, createRunCase, deleteRunCase };
export { fetchRun, fetchRuns, createRun, updateRun, deleteRun, fetchRunCases, createRunCase, deleteRunCase };

View File

@@ -1,4 +1,4 @@
export type RunType = {
type RunType = {
id: number;
name: string;
configurations: number;
@@ -8,3 +8,12 @@ export type RunType = {
createdAt: string;
updatedAt: string;
};
type RunCaseType = {
id: number;
runId: number;
caseId: number;
status: number;
};
export { RunType, RunCaseType };