From e885c43f23fccf4e1669e89d28fcea48c879b3ed Mon Sep 17 00:00:00 2001 From: Maya Date: Mon, 12 Sep 2022 18:39:31 +0200 Subject: [PATCH] Common part && export job annotations --- .../select-cloud-storage.tsx | 1 + .../src/components/storage/storage-field.tsx | 18 ++- .../case_113_cloud_storage_import_export.js | 143 +++++++++++++++++- tests/cypress/support/commands.js | 38 ++++- tests/cypress/support/commands_projects.js | 17 ++- 5 files changed, 206 insertions(+), 11 deletions(-) diff --git a/cvat-ui/src/components/select-cloud-storage/select-cloud-storage.tsx b/cvat-ui/src/components/select-cloud-storage/select-cloud-storage.tsx index e4a220a05c68..0812fecfae48 100644 --- a/cvat-ui/src/components/select-cloud-storage/select-cloud-storage.tsx +++ b/cvat-ui/src/components/select-cloud-storage/select-cloud-storage.tsx @@ -127,6 +127,7 @@ function SelectCloudStorage(props: Props): JSX.Element { setSearchPhrase(selectedCloudStorage?.displayName || ''); }} allowClear + className={`cvat-search${!name ? '-' : `-${name[0]}-`}cloud-storage-field`} > diff --git a/cvat-ui/src/components/storage/storage-field.tsx b/cvat-ui/src/components/storage/storage-field.tsx index c9ebf2a0a1d9..44617c526f37 100644 --- a/cvat-ui/src/components/storage/storage-field.tsx +++ b/cvat-ui/src/components/storage/storage-field.tsx @@ -65,6 +65,7 @@ export default function StorageField(props: Props): JSX.Element { <> {locationValue === StorageLocation.CLOUD_STORAGE && renderCloudStorage()} diff --git a/tests/cypress/integration/actions_tasks3/case_113_cloud_storage_import_export.js b/tests/cypress/integration/actions_tasks3/case_113_cloud_storage_import_export.js index e70a7819aa96..642dc7ece42c 100644 --- a/tests/cypress/integration/actions_tasks3/case_113_cloud_storage_import_export.js +++ b/tests/cypress/integration/actions_tasks3/case_113_cloud_storage_import_export.js @@ -5,16 +5,94 @@ /// context('Cloud storage.', () => { + let taskId; + let taskBackupArchiveFullName; + let ctmBeforeExport; + let archiveWithAnnotations; + let createdCloudStorageId; + const caseId = '113'; + const taskName = `Case ${caseId}`; + const labelName = 'car'; + const attrName = 'color'; + const textDefaultValue = 'red'; + const imagesCount = 1; + const imageFileName = `image_${taskName.replace(/\s+/g, '_').toLowerCase()}`; + const width = 800; + const height = 800; + const posX = 10; + const posY = 10; + const color = 'gray'; + const archiveName = `${imageFileName}.zip`; + const archivePath = `cypress/fixtures/${archiveName}`; + const imagesFolder = `cypress/fixtures/${imageFileName}`; + const directoryToArchive = imagesFolder; + const format = 'CVAT for images'; + + const createRectangleShape2Points = { + points: 'By 2 Points', + type: 'Shape', + labelName, + firstX: 250, + firstY: 350, + secondX: 350, + secondY: 450, + }; + + const serverHost = Cypress.config('baseUrl').includes('localhost') ? 'localhost' : 'minio'; + const cloudStorageData = { displayName: 'Demo bucket', resource: 'public', manifest: 'manifest.jsonl', - endpointUrl: 'http://localhost:9000', // for running in docker: http://minio:9000 + endpointUrl: `http://${serverHost}:9000`, }; - let createdCloudStorageId; + const storageConnectedToCloud = { + location: 'Cloud storage', + cloudStorageId: undefined, + }; + + const defaultProject = { + name: `Case ${caseId}`, + label: labelName, + attrName: 'color', + attrVaue: 'red', + multiAttrParams: false, + }; + + const firstProject = { + ...defaultProject, + name: `${defaultProject.name}_1`, + advancedConfiguration: { + sourceStorage: { + ...storageConnectedToCloud, + displayName: cloudStorageData.displayName, + }, + targetStorage: { + ...storageConnectedToCloud, + displayName: cloudStorageData.displayName, + }, + }, + }; + + const secondProject = { + ...defaultProject, + name: `${defaultProject}_2`, + }; + + const firstTask = { + name: taskName, + label: labelName, + attrName, + textDefaultValue, + archiveName, + multiAttrParams: false, + forProject: true, + attachToProject: true, + projectName: firstProject.name, + }; function attachS3Bucket(data) { cy.contains('.cvat-header-button', 'Cloud Storages').should('be.visible').click(); @@ -51,27 +129,78 @@ context('Cloud storage.', () => { cy.wait('@createCloudStorage').then((interseption) => { console.log(interseption); expect(interseption.response.statusCode).to.be.equal(201); - // expect(interseption.response.body.id).to.exist(); createdCloudStorageId = interseption.response.body.id; }); + cy.verifyNotification(); } - afterEach(() => { + before(() => { cy.visit('auth/login'); cy.login(); attachS3Bucket(cloudStorageData); + cy.imageGenerator(imagesFolder, imageFileName, width, height, color, posX, posY, labelName, imagesCount); + cy.createZipArchive(directoryToArchive, archivePath); }); - afterEach(() => { + after(() => { cy.goToCloudStoragesPage(); - cy.deleteCloudStorage(createdCloudStorageId, cloudStorageData.displayName); + cy.deleteCloudStorage(cloudStorageData.displayName); cy.logout(); }); describe(`Testing case "${caseId}"`, () => { - it('', () => { + it('Use project source & target storage for exporting/importing job annotations', () => { + cy.goToProjectsList(); + + firstProject.advancedConfiguration.sourceStorage.cloudStorageId = createdCloudStorageId; + firstProject.advancedConfiguration.targetStorage.cloudStorageId = createdCloudStorageId; + cy.createProjects( + firstProject.name, + firstProject.label, + firstProject.attrName, + firstProject.attrVaue, + firstProject.multiAttrParams, + firstProject.advancedConfiguration, + ); + cy.goToTaskList(); + cy.createAnnotationTask( + firstTask.name, + firstTask.label, + firstTask.attrName, + firstTask.textDefaultValue, + archiveName, + firstTask.multiAttrParams, + null, + firstTask.forProject, + firstTask.attachToProject, + firstTask.projectName, + + ); + cy.goToTaskList(); + cy.openTask(firstTask.name); + cy.url().then((link) => { + taskId = Number(link.split('/').slice(-1)[0]); + }); + cy.openJob(); + cy.createRectangle(createRectangleShape2Points).then(() => { + Cypress.config('scrollBehavior', false); + }); + cy.document().then((doc) => { + ctmBeforeExport = doc.getElementById('cvat_canvas_shape_1').getCTM(); + }); + cy.saveJob('PATCH', 200, 'saveJobDump'); + const exportParams = { + type: 'annotations', + format, + archiveName: 'job_annotations', + }; + cy.exportJob(exportParams); + cy.waitForFileUploadToCloudStorage(); + cy.goToTaskList(); + cy.deleteTask(firstTask.name); }); + // test cases: // 1. create a project with source & target storages, // create a task in a project with default source & target storages diff --git a/tests/cypress/support/commands.js b/tests/cypress/support/commands.js index f815a5ab499c..936bbd1823e5 100644 --- a/tests/cypress/support/commands.js +++ b/tests/cypress/support/commands.js @@ -645,6 +645,29 @@ Cypress.Commands.add('advancedConfiguration', (advancedConfigurationParams) => { if (advancedConfigurationParams.overlapSize) { cy.get('#overlapSize').type(advancedConfigurationParams.overlapSize); } + if (advancedConfigurationParams.sourceStorage) { + const { sourceStorage, targetStorage } = advancedConfigurationParams; + + cy.get('.cvat-select-sourceStorage-storage').within(() => { + cy.get('.ant-select-selection-item').click(); + }); + cy.contains('.cvat-select-sourceStorage-location', sourceStorage.location).should('be.visible').click(); + + if (sourceStorage.cloudStorageId) { + cy.get('.cvat-search-sourceStorage-cloud-storage-field').click(); + cy.get('.cvat-cloud-storage-select-provider').click(); + } + + cy.get('.cvat-select-targetStorage-storage').within(() => { + cy.get('.ant-select-selection-item').click(); + }); + cy.contains('.cvat-select-targetStorage-location', targetStorage.location).should('be.visible').click(); + + if (targetStorage.cloudStorageId) { + cy.get('.cvat-search-targetStorage-cloud-storage-field').click(); + cy.get('.cvat-cloud-storage-select-provider').last().click(); + } + } }); Cypress.Commands.add('removeAnnotations', () => { @@ -876,6 +899,7 @@ Cypress.Commands.add('exportTask', ({ Cypress.Commands.add('exportJob', ({ type, format, archiveCustomeName, + useDefaultLocation = true, location = 'Local', cloudStorageId = null, }) => { cy.interactMenu('Export job dataset'); cy.get('.cvat-modal-export-job').should('be.visible').find('.cvat-modal-export-select').click(); @@ -887,6 +911,18 @@ Cypress.Commands.add('exportJob', ({ if (archiveCustomeName) { cy.get('.cvat-modal-export-job').find('.cvat-modal-export-filename-input').type(archiveCustomeName); } + if (!useDefaultLocation) { + cy.get('.cvat-modal-export-job').find('.cvat-settings-switch').should('be.checked').click(); + cy.get('.cvat-select-targetStorage-storage').within(() => { + cy.get('.ant-select-selection-item').click(); + }); + cy.contains('.cvat-select-targetStorage-location', location).should('be.visible').click(); + + if (cloudStorageId) { + cy.get('.cvat-search-targetStorage-cloud-storage-field').click(); + cy.get('.cvat-cloud-storage-select-provider').click(); + } + } cy.contains('button', 'OK').click(); cy.get('.cvat-notification-notice-export-job-start').should('be.visible'); cy.closeNotification('.cvat-notification-notice-export-job-start'); @@ -956,7 +992,7 @@ Cypress.Commands.add('goToCloudStoragesPage', () => { cy.url().should('include', '/cloudstorages'); }); -Cypress.Commands.add('deleteCloudStorage', (id, displayName) => { +Cypress.Commands.add('deleteCloudStorage', (displayName) => { cy.get('.cvat-cloud-storage-item-menu-button').trigger('mousemove').trigger('mouseover'); cy.get('.ant-dropdown') .not('.ant-dropdown-hidden') diff --git a/tests/cypress/support/commands_projects.js b/tests/cypress/support/commands_projects.js index 21efb8b4f146..705ab273eb01 100644 --- a/tests/cypress/support/commands_projects.js +++ b/tests/cypress/support/commands_projects.js @@ -12,7 +12,11 @@ Cypress.Commands.add('goToProjectsList', () => { Cypress.Commands.add( 'createProjects', - (projectName, labelName, attrName, textDefaultValue, multiAttrParams, expectedResult = 'success') => { + ( + projectName, labelName, attrName, textDefaultValue, + multiAttrParams, advancedConfigurationParams, + expectedResult = 'success', + ) => { cy.get('.cvat-create-project-dropdown').click(); cy.get('.cvat-create-project-button').click(); cy.get('#name').type(projectName); @@ -26,6 +30,9 @@ Cypress.Commands.add( if (multiAttrParams) { cy.updateAttributes(multiAttrParams); } + if (advancedConfigurationParams) { + cy.advancedConfiguration(advancedConfigurationParams); + } cy.contains('button', 'Continue').click(); cy.get('.cvat-create-project-content').within(() => { cy.contains('button', 'Submit & Continue').click(); @@ -179,6 +186,14 @@ Cypress.Commands.add('getDownloadFileName', () => { }); }); +Cypress.Commands.add('waitForFileUploadToCloudStorage', () => { + cy.intercept('GET', '**=download').as('download'); + cy.wait('@download', { requestTimeout: 7000 }).then((interseption) => { + expect(interseption.response.statusCode).to.be.equal(200); + }); + cy.verifyNotification(); +}); + Cypress.Commands.add('waitForDownload', () => { cy.getDownloadFileName().then((filename) => { cy.verifyDownload(filename);