Implemented test run editor's test case selection
This commit is contained in:
@@ -90,8 +90,10 @@ app.use("/runs", runsEditRoute);
|
|||||||
app.use("/runs", runDeleteRoute);
|
app.use("/runs", runDeleteRoute);
|
||||||
|
|
||||||
// "/runcases"
|
// "/runcases"
|
||||||
|
const runCaseIndexRoute = require("./routes/runcases/index")(sequelize);
|
||||||
const runCaseNewRoute = require("./routes/runcases/new")(sequelize);
|
const runCaseNewRoute = require("./routes/runcases/new")(sequelize);
|
||||||
const runCaseDeleteRoute = require("./routes/runcases/delete")(sequelize);
|
const runCaseDeleteRoute = require("./routes/runcases/delete")(sequelize);
|
||||||
|
app.use("/runcases", runCaseIndexRoute);
|
||||||
app.use("/runcases", runCaseNewRoute);
|
app.use("/runcases", runCaseNewRoute);
|
||||||
app.use("/runcases", runCaseDeleteRoute);
|
app.use("/runcases", runCaseDeleteRoute);
|
||||||
|
|
||||||
|
|||||||
30
backend/routes/runcases/index.js
Normal file
30
backend/routes/runcases/index.js
Normal 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;
|
||||||
|
};
|
||||||
@@ -1,14 +1,14 @@
|
|||||||
const express = require("express");
|
const express = require("express");
|
||||||
const router = express.Router();
|
const router = express.Router();
|
||||||
const defineRun = require("../../models/runs");
|
const defineRun = require("../../models/runs");
|
||||||
const defineCase = require("../../models/cases");
|
// const defineCase = require("../../models/cases");
|
||||||
const { DataTypes } = require("sequelize");
|
const { DataTypes } = require("sequelize");
|
||||||
|
|
||||||
module.exports = function (sequelize) {
|
module.exports = function (sequelize) {
|
||||||
const Run = defineRun(sequelize, DataTypes);
|
const Run = defineRun(sequelize, DataTypes);
|
||||||
const Case = defineCase(sequelize, DataTypes);
|
// const Case = defineCase(sequelize, DataTypes);
|
||||||
Run.belongsToMany(Case, { through: "runCases" });
|
// Run.belongsToMany(Case, { through: "runCases" });
|
||||||
Case.belongsToMany(Run, { through: "runCases" });
|
// Case.belongsToMany(Run, { through: "runCases" });
|
||||||
|
|
||||||
router.get("/:runId", async (req, res) => {
|
router.get("/:runId", async (req, res) => {
|
||||||
const runId = req.params.runId;
|
const runId = req.params.runId;
|
||||||
@@ -18,14 +18,15 @@ module.exports = function (sequelize) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
try {
|
try {
|
||||||
const project = await Run.findByPk(runId, {
|
// const project = await Run.findByPk(runId, {
|
||||||
include: [
|
// include: [
|
||||||
{
|
// {
|
||||||
model: Case,
|
// model: Case,
|
||||||
through: { attributes: ["status"] },
|
// through: { attributes: ["status"] },
|
||||||
},
|
// },
|
||||||
],
|
// ],
|
||||||
});
|
// });
|
||||||
|
const project = await Run.findByPk(runId);
|
||||||
if (!project) {
|
if (!project) {
|
||||||
return res.status(404).send("Run not found");
|
return res.status(404).send("Run not found");
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -28,12 +28,13 @@ import {
|
|||||||
} from "lucide-react";
|
} from "lucide-react";
|
||||||
import TestCaseSelector from "./TestCaseSelector";
|
import TestCaseSelector from "./TestCaseSelector";
|
||||||
import { testRunStatus } from "@/config/selection";
|
import { testRunStatus } from "@/config/selection";
|
||||||
import { RunType } from "@/types/run";
|
import { RunType, RunCaseType } from "@/types/run";
|
||||||
import { CaseType } from "@/types/case";
|
import { CaseType } from "@/types/case";
|
||||||
import { FolderType } from "@/types/folder";
|
import { FolderType } from "@/types/folder";
|
||||||
import {
|
import {
|
||||||
fetchRun,
|
fetchRun,
|
||||||
updateRun,
|
updateRun,
|
||||||
|
fetchRunCases,
|
||||||
createRunCase,
|
createRunCase,
|
||||||
deleteRunCase,
|
deleteRunCase,
|
||||||
} from "../runsControl";
|
} from "../runsControl";
|
||||||
@@ -57,6 +58,7 @@ type Props = {
|
|||||||
export default function RunEditor({ projectId, runId }: Props) {
|
export default function RunEditor({ projectId, runId }: Props) {
|
||||||
const [testRun, setTestRun] = useState<RunType>(defaultTestRun);
|
const [testRun, setTestRun] = useState<RunType>(defaultTestRun);
|
||||||
const [folders, setFolders] = useState([]);
|
const [folders, setFolders] = useState([]);
|
||||||
|
const [runCases, setRunCases] = useState<RunCaseType[]>([]);
|
||||||
const [selectedKeys, setSelectedKeys] = useState<Selection>(new Set([]));
|
const [selectedKeys, setSelectedKeys] = useState<Selection>(new Set([]));
|
||||||
const [selectedFolder, setSelectedFolder] = useState<FolderType>({});
|
const [selectedFolder, setSelectedFolder] = useState<FolderType>({});
|
||||||
const [testcases, setTestCases] = useState<CaseType[]>([]);
|
const [testcases, setTestCases] = useState<CaseType[]>([]);
|
||||||
@@ -71,6 +73,8 @@ export default function RunEditor({ projectId, runId }: Props) {
|
|||||||
setTestRun(runData);
|
setTestRun(runData);
|
||||||
const foldersData = await fetchFolders(projectId);
|
const foldersData = await fetchFolders(projectId);
|
||||||
setFolders(foldersData);
|
setFolders(foldersData);
|
||||||
|
const runCasesData = await fetchRunCases(runId);
|
||||||
|
setRunCases(runCasesData);
|
||||||
} catch (error: any) {
|
} catch (error: any) {
|
||||||
console.error("Error in effect:", error.message);
|
console.error("Error in effect:", error.message);
|
||||||
}
|
}
|
||||||
@@ -82,25 +86,23 @@ export default function RunEditor({ projectId, runId }: Props) {
|
|||||||
const fetchAndUpdateCases = async () => {
|
const fetchAndUpdateCases = async () => {
|
||||||
try {
|
try {
|
||||||
const testCasesData = await fetchCases(selectedFolder.id);
|
const testCasesData = await fetchCases(selectedFolder.id);
|
||||||
|
|
||||||
// Check if each testCase has an association with testRun
|
// Check if each testCase has an association with testRun
|
||||||
// and add "isIncluded" property
|
// and add "isIncluded" property
|
||||||
testCasesData.forEach((caseItr: CaseType) => {
|
const updatedTestCasesData = testCasesData.map((testCase) => {
|
||||||
let isIncluded: boolean = false;
|
const runCase = runCases.find(
|
||||||
let runStatus: number = 0;
|
(runCase) => runCase.caseId === testCase.id
|
||||||
|
);
|
||||||
|
|
||||||
testRun.Cases.forEach((runCaseItr: CaseType) => {
|
const isIncluded = runCase ? true : false;
|
||||||
if (runCaseItr.id === caseItr.id) {
|
const runStatus = runCase ? runCase.status : 0;
|
||||||
isIncluded = true;
|
return {
|
||||||
runStatus = runCaseItr.runCases.status;
|
...testCase,
|
||||||
}
|
isIncluded,
|
||||||
});
|
runStatus,
|
||||||
|
};
|
||||||
caseItr.isIncluded = isIncluded;
|
|
||||||
caseItr.runStatus = runStatus;
|
|
||||||
});
|
});
|
||||||
|
|
||||||
setTestCases(testCasesData);
|
setTestCases(updatedTestCasesData);
|
||||||
} catch (error: any) {
|
} catch (error: any) {
|
||||||
console.error("Error fetching cases data:", error.message);
|
console.error("Error fetching cases data:", error.message);
|
||||||
}
|
}
|
||||||
@@ -109,6 +111,7 @@ export default function RunEditor({ projectId, runId }: Props) {
|
|||||||
useEffect(() => {
|
useEffect(() => {
|
||||||
async function fetchCasesData() {
|
async function fetchCasesData() {
|
||||||
if (selectedFolder && selectedFolder.id) {
|
if (selectedFolder && selectedFolder.id) {
|
||||||
|
console.log("fetchCasesData")
|
||||||
await fetchAndUpdateCases();
|
await fetchAndUpdateCases();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -120,8 +123,9 @@ export default function RunEditor({ projectId, runId }: Props) {
|
|||||||
isInclude: boolean,
|
isInclude: boolean,
|
||||||
clickedTestCaseId: number
|
clickedTestCaseId: number
|
||||||
) => {
|
) => {
|
||||||
|
let createdRunCase: RunCaseType;
|
||||||
if (isInclude) {
|
if (isInclude) {
|
||||||
await createRunCase(runId, clickedTestCaseId);
|
createdRunCase = await createRunCase(runId, clickedTestCaseId);
|
||||||
} else {
|
} else {
|
||||||
await deleteRunCase(runId, clickedTestCaseId);
|
await deleteRunCase(runId, clickedTestCaseId);
|
||||||
}
|
}
|
||||||
@@ -134,6 +138,18 @@ export default function RunEditor({ projectId, runId }: Props) {
|
|||||||
return testCase;
|
return testCase;
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
|
|
||||||
|
if (isInclude) {
|
||||||
|
setRunCases((prevRunCases) => {
|
||||||
|
return [...prevRunCases, createdRunCase];
|
||||||
|
});
|
||||||
|
} else {
|
||||||
|
setRunCases((prevRunCases) => {
|
||||||
|
return prevRunCases.filter(
|
||||||
|
(runCase) => runCase.caseId !== clickedTestCaseId
|
||||||
|
);
|
||||||
|
});
|
||||||
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
const onIncludeExcludeClick = async (mode: string) => {
|
const onIncludeExcludeClick = async (mode: string) => {
|
||||||
|
|||||||
@@ -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) {
|
async function createRunCase(runId: string, caseId: number) {
|
||||||
const fetchOptions = {
|
const fetchOptions = {
|
||||||
method: "POST",
|
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 };
|
||||||
|
|||||||
@@ -1,4 +1,4 @@
|
|||||||
export type RunType = {
|
type RunType = {
|
||||||
id: number;
|
id: number;
|
||||||
name: string;
|
name: string;
|
||||||
configurations: number;
|
configurations: number;
|
||||||
@@ -7,4 +7,13 @@ export type RunType = {
|
|||||||
projectId: number;
|
projectId: number;
|
||||||
createdAt: string;
|
createdAt: string;
|
||||||
updatedAt: string;
|
updatedAt: string;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
type RunCaseType = {
|
||||||
|
id: number;
|
||||||
|
runId: number;
|
||||||
|
caseId: number;
|
||||||
|
status: number;
|
||||||
|
};
|
||||||
|
|
||||||
|
export { RunType, RunCaseType };
|
||||||
|
|||||||
Reference in New Issue
Block a user