diff --git a/backend/routes/runcases/edit.js b/backend/routes/runcases/edit.js index fabd071..6819418 100644 --- a/backend/routes/runcases/edit.js +++ b/backend/routes/runcases/edit.js @@ -18,7 +18,7 @@ module.exports = function (sequelize) { { runId: runId, caseId: runCase.caseId, - status: 0, + status: runCase.status, }, { transaction: t } ); diff --git a/frontend/src/app/[locale]/projects/[projectId]/runs/[runId]/RunEditor.tsx b/frontend/src/app/[locale]/projects/[projectId]/runs/[runId]/RunEditor.tsx index 552c393..6aa6947 100644 --- a/frontend/src/app/[locale]/projects/[projectId]/runs/[runId]/RunEditor.tsx +++ b/frontend/src/app/[locale]/projects/[projectId]/runs/[runId]/RunEditor.tsx @@ -21,11 +21,18 @@ import { import { Save, ArrowLeft, Folder, ChevronDown, CopyPlus, CopyMinus, RotateCw } from 'lucide-react'; import RunProgressChart from './RunPregressDonutChart'; import TestCaseSelector from './TestCaseSelector'; -import { testRunCaseStatus, testRunStatus } from '@/config/selection'; +import { testRunStatus } from '@/config/selection'; import { RunType, RunStatusCountType, RunMessages } from '@/types/run'; import { CaseType } from '@/types/case'; import { FolderType } from '@/types/folder'; -import { fetchRun, updateRun, updateRunCases, fetchProjectCases, processTestCases } from '../runsControl'; +import { + fetchRun, + updateRun, + updateRunCases, + fetchProjectCases, + includeExcludeTestCases, + changeStatus, +} from '../runsControl'; import { fetchFolders } from '../../folders/foldersControl'; import { TokenContext } from '@/utils/TokenProvider'; import { useTheme } from 'next-themes'; @@ -113,21 +120,16 @@ export default function RunEditor({ projectId, runId, messages, locale }: Props) onFilter(); }, [selectedFolder, testCases]); - const handleChangeStatus = async (changeCaseId: number, status: number) => { + const handleChangeStatus = async (changeCaseId: number, newStatus: number) => { setIsDirty(true); - const newTestCases = [...testCases]; - const found = newTestCases.find((testCase) => testCase.id === changeCaseId); - if (found && found.RunCases && testRunCaseStatus.length > 0) { - found.RunCases[0].status = status; - found.RunCases[0].editState = 'changed'; - } + const newTestCases = changeStatus(changeCaseId, newStatus, testCases); setTestCases(newTestCases); }; const handleIncludeExcludeCase = async (isInclude: boolean, clickedTestCaseId: number) => { setIsDirty(true); const keys = [clickedTestCaseId]; - const newTestCases = processTestCases(isInclude, keys, Number(runId), testCases); + const newTestCases = includeExcludeTestCases(isInclude, keys, Number(runId), testCases); setTestCases(newTestCases); }; @@ -140,7 +142,7 @@ export default function RunEditor({ projectId, runId, messages, locale }: Props) keys = Array.from(selectedKeys).map(Number); } - const newTestCases = processTestCases(isInclude, keys, Number(runId), testCases); + const newTestCases = includeExcludeTestCases(isInclude, keys, Number(runId), testCases); setTestCases(newTestCases); setSelectedKeys(new Set([])); }; diff --git a/frontend/src/app/[locale]/projects/[projectId]/runs/runsControl.test.ts b/frontend/src/app/[locale]/projects/[projectId]/runs/runsControl.test.ts index 6728d7b..e7e5e78 100644 --- a/frontend/src/app/[locale]/projects/[projectId]/runs/runsControl.test.ts +++ b/frontend/src/app/[locale]/projects/[projectId]/runs/runsControl.test.ts @@ -1,5 +1,5 @@ -import { describe, expect, test } from 'vitest'; -import { processTestCases } from './runsControl'; +import { describe, expect, test, assert } from 'vitest'; +import { changeStatus, includeExcludeTestCases } from './runsControl'; import { CaseType } from '@/types/case'; const sampleTestCase: CaseType = { @@ -51,25 +51,51 @@ const initialTestCases: CaseType[] = [ ]; describe('runsControl', () => { + test('Exclude test cases already included in the test run', () => { + const changeCaseId = 1; + const newStatus = 1; + const currentRunCases = [...initialTestCases]; + const newTestCases = changeStatus(changeCaseId, newStatus, currentRunCases); + + if (newTestCases[0] && newTestCases[0].RunCases && newTestCases[0].RunCases[0]) { + expect(newTestCases[0].RunCases[0].status).toBe(1); + expect(newTestCases[0].RunCases[0].editState).toBe('changed'); + } else { + assert.fail("RunCases isn't exist"); + } + }); + test('include test case', () => { const isInclude = true; const keys: number[] = [3]; const runId = 1; const currentRunCases = [...initialTestCases]; - const newTestCases = processTestCases(isInclude, keys, runId, currentRunCases); + const newTestCases = includeExcludeTestCases(isInclude, keys, runId, currentRunCases); - expect(newTestCases[2].RunCases?.length).toBe(1); - expect(newTestCases[2].RunCases[0].editState).toBe('new'); + if (newTestCases[2] && newTestCases[2].RunCases && newTestCases[2].RunCases[0]) { + expect(newTestCases[2].RunCases[0].editState).toBe('new'); + } else { + assert.fail("RunCases isn't exist"); + } }); - test('Exclude test cases already included in the test run', () => { + test('Exclude test cases which already included', () => { const isInclude = false; const keys: number[] = [1, 3]; const runId = 1; const currentRunCases = [...initialTestCases]; - const newTestCases = processTestCases(isInclude, keys, runId, currentRunCases); + const newTestCases = includeExcludeTestCases(isInclude, keys, runId, currentRunCases); - expect(newTestCases[0].RunCases[0].editState).toBe('deleted'); - expect(newTestCases[2].RunCases[0].editState).toBe('deleted'); + if (newTestCases[0] && newTestCases[0].RunCases && newTestCases[0].RunCases[0]) { + expect(newTestCases[0].RunCases[0].editState).toBe('deleted'); + } else { + assert.fail("RunCases isn't exist"); + } + + if (newTestCases[2] && newTestCases[2].RunCases && newTestCases[2].RunCases[0]) { + expect(newTestCases[2].RunCases[0].editState).toBe('deleted'); + } else { + assert.fail("RunCases isn't exist"); + } }); }); diff --git a/frontend/src/app/[locale]/projects/[projectId]/runs/runsControl.ts b/frontend/src/app/[locale]/projects/[projectId]/runs/runsControl.ts index 6f0a52c..65c5de4 100644 --- a/frontend/src/app/[locale]/projects/[projectId]/runs/runsControl.ts +++ b/frontend/src/app/[locale]/projects/[projectId]/runs/runsControl.ts @@ -1,6 +1,7 @@ import { CaseType } from '@/types/case'; import { RunType, RunCaseType } from '@/types/run'; import Config from '@/config/config'; +import { testRunCaseStatus } from '@/config/selection'; const apiServer = Config.apiServer; async function fetchRun(jwt: string, runId: number) { @@ -151,7 +152,33 @@ async function fetchRunCases(jwt: string, runId: number) { } } -function processTestCases(isInclude: boolean, keys: number[], runId: number, currentTestCases: CaseType[]): CaseType[] { +function changeStatus(changeCaseId: number, newStatus: number, currentTestCases: CaseType[]): CaseType[] { + const updatedTestCases = [...currentTestCases]; + + const found = updatedTestCases.find((testCase) => testCase.id === changeCaseId); + if (found && found.RunCases && testRunCaseStatus.length > 0) { + const runCase = found.RunCases[0]; + if (runCase.editState === 'notChanged') { + runCase.status = newStatus; + runCase.editState = 'changed'; + } else if (runCase.editState === 'changed') { + runCase.status = newStatus; + } else if (runCase.editState === 'new') { + runCase.status = newStatus; + } else if (runCase.editState === 'deleted') { + // do nothing + } + } + + return updatedTestCases; +} + +function includeExcludeTestCases( + isInclude: boolean, + keys: number[], + runId: number, + currentTestCases: CaseType[] +): CaseType[] { const updatedTestCases = [...currentTestCases]; if (isInclude) { @@ -275,7 +302,8 @@ export { updateRun, deleteRun, fetchRunCases, - processTestCases, + changeStatus, + includeExcludeTestCases, updateRunCases, fetchProjectCases, };