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 70b4ce8..b33c59d 100644 --- a/frontend/src/app/[locale]/projects/[projectId]/runs/[runId]/RunEditor.tsx +++ b/frontend/src/app/[locale]/projects/[projectId]/runs/[runId]/RunEditor.tsx @@ -25,7 +25,7 @@ import { testRunStatus } from '@/config/selection'; import { RunType, RunCaseType, RunStatusCountType, RunMessages } from '@/types/run'; import { CaseType } from '@/types/case'; import { FolderType } from '@/types/folder'; -import { fetchRun, updateRun, fetchRunCases, updateRunCases } from '../runsControl'; +import { fetchRun, updateRun, fetchRunCases, updateRunCases, processRunCases } from '../runsControl'; import { fetchFolders } from '../../folders/foldersControl'; import { fetchCases } from '@/utils/caseControl'; import { TokenContext } from '@/utils/TokenProvider'; @@ -171,50 +171,8 @@ export default function RunEditor({ projectId, runId, messages, locale }: Props) keys = Array.from(selectedKeys).map(Number); } - if (isInclude) { - // TODO fix and add unit test - setRunCases((prevRunCases) => { - const updatedRunCases = prevRunCases.map((runCase) => { - if (keys.includes(runCase.caseId) && runCase.editState === 'deleted') { - return { ...runCase, editState: 'changed' }; - } - return runCase; - }); - - keys.forEach((caseId) => { - const existingRunCase = prevRunCases.find((runCase) => runCase.caseId === caseId); - if (!existingRunCase) { - updatedRunCases.push({ - id: -1, - runId: Number(runId), - caseId: caseId, - status: -1, - editState: 'new', - }); - } - }); - - return updatedRunCases; - }); - } else { - setRunCases((prevRunCases) => - prevRunCases - .filter((runCase) => { - // If editState is 'new', remove from the array - if (keys.includes(runCase.caseId) && runCase.editState === 'new') { - return false; - } - return true; - }) - .map((runCase) => { - // If editState isn't 'new', set editState to 'deleted'. - if (keys.includes(runCase.caseId) && runCase.editState !== 'new') { - return { ...runCase, editState: 'deleted' }; - } - return runCase; - }) - ); - } + const newRunCases = processRunCases(isInclude, keys, Number(runId), runCases); + setRunCases(newRunCases); const updatedTestCases = testcases.map((testcase) => { if (keys.includes(testcase.id)) { diff --git a/frontend/src/app/[locale]/projects/[projectId]/runs/runsControl.test.ts b/frontend/src/app/[locale]/projects/[projectId]/runs/runsControl.test.ts new file mode 100644 index 0000000..0074e0d --- /dev/null +++ b/frontend/src/app/[locale]/projects/[projectId]/runs/runsControl.test.ts @@ -0,0 +1,41 @@ +import { describe, expect, test } from 'vitest'; +import { processRunCases } from './runsControl'; +import { RunCaseType } from '@/types/run'; + +const initialRuncases: RunCaseType[] = [ + { id: 1, runId: 1, caseId: 1, editState: 'notChanged', status: 0 }, + { id: 2, runId: 1, caseId: 2, editState: 'notChanged', status: 0 }, + { id: 3, runId: 1, caseId: 3, editState: 'notChanged', status: 0 }, +]; + +describe('runsControl', () => { + test('Add test cases not yet included in the test run', () => { + const isInclude = true; + const keys: number[] = [4, 5]; + const runId = 1; + const currentRunCases = [...initialRuncases]; + const newRunCases = processRunCases(isInclude, keys, runId, currentRunCases); + + expect(newRunCases).toStrictEqual([ + { id: 1, runId: 1, caseId: 1, editState: 'notChanged', status: 0 }, + { id: 2, runId: 1, caseId: 2, editState: 'notChanged', status: 0 }, + { id: 3, runId: 1, caseId: 3, editState: 'notChanged', status: 0 }, + { id: -1, runId: runId, caseId: 4, status: -1, editState: 'new' }, + { id: -1, runId: runId, caseId: 5, status: -1, editState: 'new' }, + ]); + }); + + test('Exclude test cases already included in the test run', () => { + const isInclude = false; + const keys: number[] = [1, 3]; + const runId = 1; + const currentRunCases = [...initialRuncases]; + const newRunCases = processRunCases(isInclude, keys, runId, currentRunCases); + + expect(newRunCases).toStrictEqual([ + { id: 1, runId: 1, caseId: 1, editState: 'deleted', status: 0 }, + { id: 2, runId: 1, caseId: 2, editState: 'notChanged', status: 0 }, + { id: 3, runId: 1, caseId: 3, editState: 'deleted', status: 0 }, + ]); + }); +}); diff --git a/frontend/src/app/[locale]/projects/[projectId]/runs/runsControl.ts b/frontend/src/app/[locale]/projects/[projectId]/runs/runsControl.ts index 857ce94..96723c4 100644 --- a/frontend/src/app/[locale]/projects/[projectId]/runs/runsControl.ts +++ b/frontend/src/app/[locale]/projects/[projectId]/runs/runsControl.ts @@ -150,6 +150,55 @@ async function fetchRunCases(jwt: string, runId: number) { } } +function processRunCases( + isInclude: boolean, + keys: number[], + runId: number, + currentRunCases: RunCaseType[] +): RunCaseType[] { + if (isInclude) { + const updatedRunCases = currentRunCases.map((runCase) => { + if (keys.includes(runCase.caseId) && runCase.editState === 'deleted') { + return { ...runCase, editState: 'changed' } as RunCaseType; + } + return runCase; + }); + + keys.forEach((caseId) => { + const existingRunCase = currentRunCases.find((runCase) => runCase.caseId === caseId); + if (!existingRunCase) { + updatedRunCases.push({ + id: -1, + runId: runId, + caseId: caseId, + status: -1, + editState: 'new', + }); + } + }); + + return updatedRunCases; + } else { + const updatedRunCases = currentRunCases + .filter((runCase) => { + // If editState is 'new', remove from the array + if (keys.includes(runCase.caseId) && runCase.editState === 'new') { + return false; + } + return true; + }) + .map((runCase) => { + // If editState isn't 'new', set editState to 'deleted'. + if (keys.includes(runCase.caseId) && runCase.editState !== 'new') { + return { ...runCase, editState: 'deleted' } as RunCaseType; + } + return runCase; + }); + + return updatedRunCases; + } +} + async function updateRunCases(jwt: string, runId: number, runCases: RunCaseType[]) { const fetchOptions = { method: 'POST', @@ -175,4 +224,4 @@ async function updateRunCases(jwt: string, runId: number, runCases: RunCaseType[ } } -export { fetchRun, fetchRuns, createRun, updateRun, deleteRun, fetchRunCases, updateRunCases }; +export { fetchRun, fetchRuns, createRun, updateRun, deleteRun, fetchRunCases, processRunCases, updateRunCases }; diff --git a/vitest.config.ts b/vitest.config.ts index 6143f1e..aa2e9ed 100644 --- a/vitest.config.ts +++ b/vitest.config.ts @@ -7,6 +7,14 @@ export default defineConfig({ exclude: ['**/node_modules/**', 'docs/**', '**/.next/**'], provider: 'v8', }, + exclude: [ + '**/node_modules/**', + '**/dist/**', + '**/cypress/**', + '**/.{idea,git,cache,output,temp}/**', + '**/{karma,rollup,webpack,vite,vitest,jest,ava,babel,nyc,cypress,tsup,build}.config.*', + '**/e2e/**', + ], }, resolve: { alias: [{ find: '@', replacement: resolve(__dirname, './frontend') }],