From a2fea7a127bf319983c07c92f6d11c5c86882190 Mon Sep 17 00:00:00 2001 From: Matheus Santana <83383321+matheusfsantana@users.noreply.github.com> Date: Sat, 29 Nov 2025 03:00:43 -0300 Subject: [PATCH] feat: add folder on export and handle steps on import (#352) --- backend/routes/cases/download.js | 9 + backend/routes/cases/download.test.js | 1 + backend/routes/cases/import.js | 175 ++++++++++++------ .../unittcms-import-template-v1.1.xlsx | Bin 0 -> 106490 bytes .../[folderId]/cases/CaseImportDialog.tsx | 2 +- 5 files changed, 126 insertions(+), 61 deletions(-) create mode 100644 frontend/public/template/unittcms-import-template-v1.1.xlsx diff --git a/backend/routes/cases/download.js b/backend/routes/cases/download.js index ab2071d..3714968 100644 --- a/backend/routes/cases/download.js +++ b/backend/routes/cases/download.js @@ -4,6 +4,7 @@ import { DataTypes } from 'sequelize'; import Papa from 'papaparse'; import defineCase from '../../models/cases.js'; import defineStep from '../../models/steps.js'; +import defineFolder from '../../models/folders.js'; import authMiddleware from '../../middleware/auth.js'; import visibilityMiddleware from '../../middleware/verifyVisible.js'; import { testRunStatus, priorities, testTypes, automationStatus, templates } from '../../config/enums.js'; @@ -11,6 +12,8 @@ import { testRunStatus, priorities, testTypes, automationStatus, templates } fro export default function (sequelize) { const Case = defineCase(sequelize, DataTypes); const Step = defineStep(sequelize, DataTypes); + const Folder = defineFolder(sequelize, DataTypes); + Case.belongsTo(Folder); Case.belongsToMany(Step, { through: 'caseSteps' }); Step.belongsToMany(Case, { through: 'caseSteps' }); const { verifySignedIn } = authMiddleware(sequelize); @@ -37,6 +40,10 @@ export default function (sequelize) { order: [['stepNo', 'ASC']], attributes: { exclude: ['createdAt', 'updatedAt'] }, }, + { + model: Folder, + attributes: ['name'], + }, ], where: { folderId }, raw: true, @@ -90,6 +97,7 @@ const _formatRawCasesToJson = (cases) => { casesObject[c.id] = { id: c.id, folderId: c.folderId, + folder: c['Folder.name'], title: c.title, state: c.state, priority: c.priority, @@ -119,6 +127,7 @@ const _formatRawCasesToCsv = (cases) => { return cases.map((c) => ({ id: c.id, folderId: c.folderId, + folder: c['Folder.name'], title: c.title, state: c.state, priority: c.priority, diff --git a/backend/routes/cases/download.test.js b/backend/routes/cases/download.test.js index 06e60c2..e8a1b56 100644 --- a/backend/routes/cases/download.test.js +++ b/backend/routes/cases/download.test.js @@ -38,6 +38,7 @@ vi.mock('../../middleware/verifyVisible.js', () => ({ const mockCase = { findAll: vi.fn(), belongsToMany: vi.fn(), + belongsTo: vi.fn(), }; vi.mock('../../models/cases.js', () => ({ default: () => mockCase, diff --git a/backend/routes/cases/import.js b/backend/routes/cases/import.js index 9b07cfd..894b859 100644 --- a/backend/routes/cases/import.js +++ b/backend/routes/cases/import.js @@ -5,6 +5,8 @@ import multer from 'multer'; import XLSX from 'xlsx'; import { DataTypes } from 'sequelize'; import defineCase from '../../models/cases.js'; +import defineStep from '../../models/steps.js'; +import defineCaseStep from '../../models/caseSteps.js'; import authMiddleware from '../../middleware/auth.js'; import editableMiddleware from '../../middleware/verifyEditable.js'; import { priorities, testTypes, automationStatus, templates } from '../../config/enums.js'; @@ -34,6 +36,10 @@ const upload = multer({ export default function (sequelize) { const Case = defineCase(sequelize, DataTypes); + const Step = defineStep(sequelize, DataTypes); + const CaseStep = defineCaseStep(sequelize, DataTypes); + Case.belongsToMany(Step, { through: CaseStep }); + Step.belongsToMany(Case, { through: CaseStep }); const { verifySignedIn } = authMiddleware(sequelize); const { verifyProjectDeveloperFromFolderId } = editableMiddleware(sequelize); @@ -60,86 +66,135 @@ export default function (sequelize) { return res.status(400).json({ error: 'folderId is required' }); } + const t = await sequelize.transaction(); try { const workbook = XLSX.read(req.file.buffer, { type: 'buffer' }); const sheetName = workbook.SheetNames[0]; const worksheet = workbook.Sheets[sheetName]; const jsonData = XLSX.utils.sheet_to_json(worksheet); - let errorMessage = null; + let currentTitle = null; + let previousTitle = null; + let stepNo = 1; const casesToCreate = []; - const requiredFields = ['title', 'priority', 'type', 'template']; + const stepsToCreate = []; for (const [index, row] of jsonData.entries()) { - const rowNumber = index + 2; - for (const field of requiredFields) { - if (!row[field]) { - errorMessage = `Row ${rowNumber} is missing required field: ${field}`; - console.log(`Error found for field: ${errorMessage}`); - } - } - - // Validate priority if provided - let priorityIndex = priorities.indexOf('medium'); // default to 'medium' - if (row['priority']) { - priorityIndex = priorities.indexOf(row['priority'].toLowerCase()); - if (priorityIndex === -1) { - errorMessage = `Row ${rowNumber} has invalid priority: ${row['priority']}`; - } - } - - // Validate type if provided - let typeIndex = testTypes.indexOf('other'); // default to 'other' - if (row['type']) { - typeIndex = testTypes.indexOf(row['type'].toLowerCase()); - if (typeIndex === -1) { - errorMessage = `Row ${rowNumber} has invalid type: ${row['type']}`; - } - } - - // Validate automationStatus if provided - let automationStatusIndex = automationStatus.indexOf('automation-not-required'); // default to 'automation-not-required' - if (row['automationStatus']) { - automationStatusIndex = automationStatus.indexOf(row['automationStatus'].toLowerCase()); - if (automationStatusIndex === -1) { - errorMessage = `Row ${rowNumber} has invalid automationStatus: ${row['automationStatus']}`; - } - } - - // Validate template if provided - let templateIndex = templates.indexOf('text'); // default to 'text' - if (row['template']) { - templateIndex = templates.indexOf(row['template'].toLowerCase()); - if (templateIndex === -1) { - errorMessage = `Row ${rowNumber} has invalid template: ${row['template']}`; - } - } - + const errorMessage = _getRowValidationError(row, index); if (errorMessage) { return res.status(400).json({ error: errorMessage }); } - casesToCreate.push({ - folderId: folderId, - title: row['title'], - description: row['description'] || '', - state: 0, // default state - priority: priorityIndex, - type: typeIndex, - preConditions: row['preConditions'], - expectedResults: row['expectedResults'], - automationStatus: automationStatusIndex, - template: templateIndex, - }); + // Add step to the same case if the current row title is equal to previous row title + // This handle cases with multiple steps :) + currentTitle = row['title'].trim(); + previousTitle = casesToCreate[casesToCreate.length - 1]?.title.trim(); + if (casesToCreate.length > 0 && previousTitle === currentTitle) { + stepNo += 1; + stepsToCreate.push({ + caseIndex: casesToCreate.length - 1, + stepNo: stepNo, + step: row['step'] || '', + result: row['expectedStepResult'] || '', + }); + } else { + stepNo = 1; + casesToCreate.push({ + folderId: folderId, + title: currentTitle, + description: row['description'] || '', + state: 0, // default state + priority: row['priority'] ? priorities.indexOf(row['priority']) : priorities.indexOf('medium'), + type: row['type'] ? testTypes.indexOf(row['type']) : testTypes.indexOf('other'), + preConditions: row['preConditions'], + expectedResults: row['expectedResults'], + automationStatus: row['automationStatus'] + ? automationStatus.indexOf(row['automationStatus']) + : automationStatus.indexOf('automation-not-required'), + template: row['template'] ? templates.indexOf(row['template']) : templates.indexOf('text'), + }); + stepsToCreate.push({ + caseIndex: casesToCreate.length - 1, + stepNo: stepNo, + step: row['step'] || '', + result: row['expectedStepResult'] || '', + }); + } } - const createdCases = await Case.bulkCreate(casesToCreate); + // 'Manually' create cases, steps and caseStep association. + const createdCases = await Case.bulkCreate(casesToCreate, { transaction: t }); + for (const stepData of stepsToCreate) { + const createdCase = createdCases[stepData.caseIndex]; + const createdStep = await Step.create( + { + step: stepData.step, + result: stepData.result, + }, + { transaction: t } + ); + await CaseStep.create( + { + caseId: createdCase.id, + stepId: createdStep.id, + stepNo: stepData.stepNo, + }, + { transaction: t } + ); + } + + await t.commit(); res.json(createdCases); } catch (error) { + await t.rollback(); console.error(error); - res.status(500).send('Internal Server Error'); } } ); return router; } + +function _getRowValidationError(row, index) { + const requiredFields = ['title', 'priority', 'type', 'template']; + const rowNumber = index + 2; + + for (const field of requiredFields) { + if (!row[field]) { + return `Row ${rowNumber} is missing required field: ${field}`; + } + } + + // Validate priority if provided + if (row['priority']) { + const priorityIndex = priorities.indexOf(row['priority']?.toLowerCase()); + if (priorityIndex === -1) { + return `Row ${rowNumber} has invalid priority: ${row['priority']}`; + } + } + + // Validate type if provided + if (row['type']) { + const typeIndex = testTypes.indexOf(row['type']?.toLowerCase()); + if (typeIndex === -1) { + return `Row ${rowNumber} has invalid type: ${row['type']}`; + } + } + + // Validate automationStatus if provided + if (row['automationStatus']) { + const automationStatusIndex = automationStatus.indexOf(row['automationStatus']?.toLowerCase()); + if (automationStatusIndex === -1) { + return `Row ${rowNumber} has invalid automationStatus: ${row['automationStatus']}`; + } + } + + // Validate template if provided + if (row['template']) { + const templateIndex = templates.indexOf(row['template']?.toLowerCase()); + if (templateIndex === -1) { + return `Row ${rowNumber} has invalid template: ${row['template']}`; + } + } + + return null; +} diff --git a/frontend/public/template/unittcms-import-template-v1.1.xlsx b/frontend/public/template/unittcms-import-template-v1.1.xlsx new file mode 100644 index 0000000000000000000000000000000000000000..ff6c70ee6107c7b2729c9fdc0c4cd3d220cb47af GIT binary patch literal 106490 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 literal 0 HcmV?d00001 diff --git a/frontend/src/app/[locale]/projects/[projectId]/folders/[folderId]/cases/CaseImportDialog.tsx b/frontend/src/app/[locale]/projects/[projectId]/folders/[folderId]/cases/CaseImportDialog.tsx index 3a1167e..d771130 100644 --- a/frontend/src/app/[locale]/projects/[projectId]/folders/[folderId]/cases/CaseImportDialog.tsx +++ b/frontend/src/app/[locale]/projects/[projectId]/folders/[folderId]/cases/CaseImportDialog.tsx @@ -70,7 +70,7 @@ export default function CaseImportDialog({ isOpen, folderId, isDisabled, onImpor
{messages.importAvailable}
- + {messages.downloadTemplate}