From e8376c07ef70a29d6e808887a923472fe80c0155 Mon Sep 17 00:00:00 2001 From: Takeshi Kimata <117462761+kimatata@users.noreply.github.com> Date: Sat, 20 Apr 2024 23:26:47 +0900 Subject: [PATCH] Implemented test run editor's test case selection --- backend/index.js | 2 + backend/routes/runcases/index.js | 30 ++++++++++++ backend/routes/runs/show.js | 25 +++++----- .../[projectId]/runs/[runId]/RunEditor.tsx | 48 ++++++++++++------- .../projects/[projectId]/runs/runsControl.ts | 24 +++++++++- frontend/types/run.ts | 13 ++++- 6 files changed, 111 insertions(+), 31 deletions(-) create mode 100644 backend/routes/runcases/index.js diff --git a/backend/index.js b/backend/index.js index 06c79e3..98a7737 100644 --- a/backend/index.js +++ b/backend/index.js @@ -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); diff --git a/backend/routes/runcases/index.js b/backend/routes/runcases/index.js new file mode 100644 index 0000000..33d5ffc --- /dev/null +++ b/backend/routes/runcases/index.js @@ -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; +}; \ No newline at end of file diff --git a/backend/routes/runs/show.js b/backend/routes/runs/show.js index 23d8490..8357051 100644 --- a/backend/routes/runs/show.js +++ b/backend/routes/runs/show.js @@ -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"); } diff --git a/frontend/app/projects/[projectId]/runs/[runId]/RunEditor.tsx b/frontend/app/projects/[projectId]/runs/[runId]/RunEditor.tsx index ce69d6d..3308005 100644 --- a/frontend/app/projects/[projectId]/runs/[runId]/RunEditor.tsx +++ b/frontend/app/projects/[projectId]/runs/[runId]/RunEditor.tsx @@ -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(defaultTestRun); const [folders, setFolders] = useState([]); + const [runCases, setRunCases] = useState([]); const [selectedKeys, setSelectedKeys] = useState(new Set([])); const [selectedFolder, setSelectedFolder] = useState({}); const [testcases, setTestCases] = useState([]); @@ -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; - } - }); - - caseItr.isIncluded = isIncluded; - caseItr.runStatus = runStatus; + const isIncluded = runCase ? true : false; + const runStatus = runCase ? runCase.status : 0; + return { + ...testCase, + isIncluded, + 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) => { diff --git a/frontend/app/projects/[projectId]/runs/runsControl.ts b/frontend/app/projects/[projectId]/runs/runsControl.ts index 42afd21..b60484f 100644 --- a/frontend/app/projects/[projectId]/runs/runsControl.ts +++ b/frontend/app/projects/[projectId]/runs/runsControl.ts @@ -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 }; diff --git a/frontend/types/run.ts b/frontend/types/run.ts index c09d99c..f20d2d3 100644 --- a/frontend/types/run.ts +++ b/frontend/types/run.ts @@ -1,4 +1,4 @@ -export type RunType = { +type RunType = { id: number; name: string; configurations: number; @@ -7,4 +7,13 @@ export type RunType = { projectId: number; createdAt: string; updatedAt: string; -}; \ No newline at end of file +}; + +type RunCaseType = { + id: number; + runId: number; + caseId: number; + status: number; +}; + +export { RunType, RunCaseType };