From 772d0d7389b2948f9fe57ebe1806cda55a0fbbfa Mon Sep 17 00:00:00 2001 From: Kirill Lakhov Date: Tue, 17 Sep 2024 12:48:33 +0300 Subject: [PATCH 1/2] added tests --- .../task-quality/allocation-table.tsx | 8 +- .../quality-control/task-quality/summary.tsx | 6 +- .../cypress/e2e/features/ground_truth_jobs.js | 133 +++++++++++++++++- tests/cypress/support/commands.js | 19 ++- 4 files changed, 154 insertions(+), 12 deletions(-) diff --git a/cvat-ui/src/components/quality-control/task-quality/allocation-table.tsx b/cvat-ui/src/components/quality-control/task-quality/allocation-table.tsx index e1a4862ad822..b1619bf6fcd3 100644 --- a/cvat-ui/src/components/quality-control/task-quality/allocation-table.tsx +++ b/cvat-ui/src/components/quality-control/task-quality/allocation-table.tsx @@ -109,10 +109,12 @@ function AllocationTable(props: Readonly): JSX.Element { render: (active: boolean, record: RowData): JSX.Element => ( active ? ( { onDeleteFrames([record.frame]); }} /> ) : ( { onRestoreFrames([record.frame]); }} component={RestoreIcon} /> @@ -130,7 +132,7 @@ function AllocationTable(props: Readonly): JSX.Element { { selection.selectedRowKeys.length !== 0 ? ( <> - + { const framesToUpdate = selection.selectedRows @@ -141,7 +143,7 @@ function AllocationTable(props: Readonly): JSX.Element { }} /> - + { const framesToUpdate = selection.selectedRows @@ -163,7 +165,7 @@ function AllocationTable(props: Readonly): JSX.Element { if (!rowData.active) { return 'cvat-allocation-frame-row cvat-allocation-frame-row-excluded'; } - return 'cvat-allocation-frame'; + return 'cvat-allocation-frame-row'; }} columns={columns} dataSource={data} diff --git a/cvat-ui/src/components/quality-control/task-quality/summary.tsx b/cvat-ui/src/components/quality-control/task-quality/summary.tsx index be249341b37d..59767192ed0d 100644 --- a/cvat-ui/src/components/quality-control/task-quality/summary.tsx +++ b/cvat-ui/src/components/quality-control/task-quality/summary.tsx @@ -20,14 +20,14 @@ export default function SummaryComponent(props: Readonly): JSX.Element { - + Excluded count: {' '} {excludedCount} - + Total count: {' '} @@ -36,7 +36,7 @@ export default function SummaryComponent(props: Readonly): JSX.Element { - + Active count: {' '} diff --git a/tests/cypress/e2e/features/ground_truth_jobs.js b/tests/cypress/e2e/features/ground_truth_jobs.js index 9eba445b76a2..dd0a8d53f11e 100644 --- a/tests/cypress/e2e/features/ground_truth_jobs.js +++ b/tests/cypress/e2e/features/ground_truth_jobs.js @@ -88,6 +88,14 @@ context('Ground truth jobs', () => { .should('be.visible'); } + function openManagementTab() { + cy.clickInTaskMenu('Quality control', true); + cy.get('.cvat-task-control-tabs') + .within(() => { + cy.contains('Management').click(); + }); + } + before(() => { cy.visit('auth/login'); cy.login(); @@ -187,9 +195,124 @@ context('Ground truth jobs', () => { }); }); + describe('Testing ground truth management basics', () => { + const serverFiles = ['images/image_1.jpg', 'images/image_2.jpg', 'images/image_3.jpg']; + + before(() => { + cy.headlessCreateTask({ + labels: [{ name: labelName, attributes: [], type: 'any' }], + name: taskName, + project_id: null, + source_storage: { location: 'local' }, + target_storage: { location: 'local' }, + }, { + server_files: serverFiles, + image_quality: 70, + use_zip_chunks: true, + use_cache: true, + sorting_method: 'lexicographical', + }).then((taskResponse) => { + taskID = taskResponse.taskID; + [jobID] = taskResponse.jobIDs; + }).then(() => ( + cy.headlessCreateJob({ + task_id: taskID, + frame_count: 3, + type: 'ground_truth', + frame_selection_method: 'random_uniform', + }) + )).then((jobResponse) => { + groundTruthJobID = jobResponse.jobID; + }).then(() => { + cy.visit(`/tasks/${taskID}`); + cy.get('.cvat-task-details').should('exist').and('be.visible'); + }); + openManagementTab(); + }); + + after(() => { + cy.headlessDeleteTask(taskID); + }); + + it('Check management page contents.', () => { + cy.get('.cvat-annotations-quality-allocation-table-summary').should('exist'); + cy.contains('.cvat-allocation-summary-excluded', '0').should('exist'); + cy.contains('.cvat-allocation-summary-total', '3').should('exist'); + cy.contains('.cvat-allocation-summary-active', '3').should('exist'); + + cy.get('.cvat-frame-allocation-table').should('exist'); + cy.get('.cvat-allocation-frame-row').should('have.length', 3); + cy.get('.cvat-allocation-frame-row').each(($el, index) => { + cy.wrap($el).within(() => { + cy.contains(`#${index}`).should('exist'); + cy.contains(`images/image_${index + 1}.jpg`).should('exist'); + }); + }); + }); + + it('Check link to frame.', () => { + cy.get('.cvat-allocation-frame-row').last().within(() => { + cy.get('.cvat-open-frame-button').first().click(); + }); + cy.get('.cvat-spinner').should('not.exist'); + cy.url().should('contain', `/tasks/${taskID}/jobs/${groundTruthJobID}`); + cy.checkFrameNum(2); + + cy.interactMenu('Open the task'); + openManagementTab(); + }); + + it('Disable single frame, enable it back.', () => { + cy.get('.cvat-allocation-frame-row').last().within(() => { + cy.get('.cvat-allocation-frame-delete').click(); + }); + cy.get('.cvat-spinner').should('not.exist'); + + cy.get('.cvat-allocation-frame-row-excluded').should('exist'); + cy.contains('.cvat-allocation-summary-excluded', '1').should('exist'); + cy.contains('.cvat-allocation-summary-active', '2').should('exist'); + + cy.get('.cvat-allocation-frame-row-excluded').within(() => { + cy.get('.cvat-allocation-frame-restore').click(); + }); + cy.get('.cvat-spinner').should('not.exist'); + cy.get('.cvat-allocation-frame-row-excluded').should('not.exist'); + cy.contains('.cvat-allocation-summary-excluded', '0').should('exist'); + cy.contains('.cvat-allocation-summary-active', '3').should('exist'); + }); + + it('Select several frames, use group operations.', () => { + function selectFrames() { + cy.get('.cvat-allocation-frame-row').each(($el, index) => { + if (index !== 0) { + cy.wrap($el).within(() => { + cy.get('.ant-table-selection-column input[type="checkbox"]').should('not.be.checked').check(); + }); + } + }); + } + + selectFrames(); + cy.get('.cvat-allocation-selection-frame-delete').click(); + cy.get('.cvat-spinner').should('not.exist'); + + cy.get('.cvat-allocation-frame-row-excluded').should('have.length', 2); + cy.contains('.cvat-allocation-summary-excluded', '2').should('exist'); + cy.contains('.cvat-allocation-summary-active', '1').should('exist'); + + selectFrames(); + cy.get('.cvat-allocation-selection-frame-restore').click(); + cy.get('.cvat-spinner').should('not.exist'); + + cy.get('.cvat-allocation-frame-row-excluded').should('not.exist'); + cy.contains('.cvat-allocation-summary-excluded', '0').should('exist'); + cy.contains('.cvat-allocation-summary-active', '3').should('exist'); + }); + }); + describe('Regression tests', () => { const imagesCount = 20; - const imageFileName = 'ground_truth_2'; + const imageFileName = 'ground_truth_3'; const width = 100; const height = 100; const posX = 10; @@ -205,8 +328,12 @@ context('Ground truth jobs', () => { cy.imageGenerator(imagesFolder, imageFileName, width, height, color, posX, posY, labelName, imagesCount); cy.createZipArchive(directoryToArchive, archivePath); cy.createAnnotationTask( - taskName, labelName, attrName, - textDefaultValue, archiveName, false, + taskName, + labelName, + attrName, + textDefaultValue, + archiveName, + false, { multiJobs: true, segmentSize: 1 }, ); cy.openTask(taskName); diff --git a/tests/cypress/support/commands.js b/tests/cypress/support/commands.js index 83628abfb66b..76f7ffe2640c 100644 --- a/tests/cypress/support/commands.js +++ b/tests/cypress/support/commands.js @@ -171,11 +171,11 @@ Cypress.Commands.add( attrName = 'Some attr name', textDefaultValue = 'Some default value for type Text', image = 'image.png', - multiAttrParams, - advancedConfigurationParams, + multiAttrParams = null, + advancedConfigurationParams = null, forProject = false, attachToProject = false, - projectName, + projectName = '', expectedResult = 'success', projectSubsetFieldValue = 'Test', ) => { @@ -365,6 +365,19 @@ Cypress.Commands.add('headlessLogout', () => { cy.clearAllLocalStorage(); }); +Cypress.Commands.add('headlessCreateJob', (jobSpec) => { + cy.window().then(async ($win) => { + const data = { + ...jobSpec, + }; + + const job = new $win.cvat.classes.Job(data); + + const result = await job.save(data); + return cy.wrap({ jobID: result.id }); + }); +}); + Cypress.Commands.add('openTask', (taskName, projectSubsetFieldValue) => { cy.contains('strong', new RegExp(`^${taskName}$`)) .parents('.cvat-tasks-list-item') From 15edbb40b2708716d3be780bc6c599615c6e3c1f Mon Sep 17 00:00:00 2001 From: Kirill Lakhov Date: Tue, 17 Sep 2024 13:26:38 +0300 Subject: [PATCH 2/2] small improvement --- tests/cypress/e2e/features/ground_truth_jobs.js | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/tests/cypress/e2e/features/ground_truth_jobs.js b/tests/cypress/e2e/features/ground_truth_jobs.js index dd0a8d53f11e..dfd8a8fe2b52 100644 --- a/tests/cypress/e2e/features/ground_truth_jobs.js +++ b/tests/cypress/e2e/features/ground_truth_jobs.js @@ -226,8 +226,8 @@ context('Ground truth jobs', () => { }).then(() => { cy.visit(`/tasks/${taskID}`); cy.get('.cvat-task-details').should('exist').and('be.visible'); + openManagementTab(); }); - openManagementTab(); }); after(() => { @@ -312,7 +312,7 @@ context('Ground truth jobs', () => { describe('Regression tests', () => { const imagesCount = 20; - const imageFileName = 'ground_truth_3'; + const imageFileName = 'ground_truth_2'; const width = 100; const height = 100; const posX = 10;