Cypress tests for source & target storage (#4914)

* Draft version

* Implemented import & fixed export && some code cleanup && some fixes &&  updated notifications

* Refactoring && fixed several bugs

* Update licence headers && small fixes

* Update remaining licence headers && small changes

* Fix part of tests

* Fix tests

* Remove unused code

* Fix part of comments

* Some fixes

* Move file download process to job

* Rename methods

* Small fix

* Fix storages configuration for tasks

* Styles

* Remove unused

* Change storage configuration && fix forms reset && some fixes

* Update imports

* Remove extra argument type

* Add catch

* Fix import backup from local

* Import architecture refactoring && some fixes

* Rename props

* Small reorganization of export architecture &&  minor fixes

* Remove unused import

* Small fix && skip error notification when no permissions

* Fix project creating

* Fix part of eslint issues

* Fix eslint

* Fix eslint

* Fix eslint

* eslint

* Fix some eslint issues

* Combine uploadAnnotations and importDataset

* Fix annotation uploading from local

* Update tests

* Fix annotation uploading

* Fix notification

* Update dependencies

* fix

* Update jest tests

* Skip error notification when no permissions

* Update case 91 92 canvas3d tests

* Styles

* Update icons

* eslint

* eslint

* eslint

* eslint

* Create & delete cloud storage

* Common part && export job annotations

* Update tests && add tests for project backup

* Fix typo

* Rename variables

* debug

* Revert timeout

* Fix server host

* Fix test with project backup restore

* small refactoring

* Update issue_2473_import_annotations_frames_dots_in_name
main
Maria Khrustaleva 3 years ago committed by GitHub
parent 79dcc0e0cf
commit 56e8c1eb82
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23

@ -305,6 +305,7 @@ jobs:
-f docker-compose.yml \
-f docker-compose.dev.yml \
-f components/serverless/docker-compose.serverless.yml \
-f tests/docker-compose.minio.yml \
-f tests/docker-compose.file_share.yml up -d
- name: Waiting for server

@ -266,6 +266,7 @@ jobs:
-f docker-compose.yml \
-f docker-compose.dev.yml \
-f components/serverless/docker-compose.serverless.yml \
-f tests/docker-compose.minio.yml \
-f tests/docker-compose.file_share.yml up -d
- name: Waiting for server

@ -321,6 +321,7 @@ jobs:
-f docker-compose.yml \
-f docker-compose.dev.yml \
-f tests/docker-compose.file_share.yml \
-f tests/docker-compose.minio.yml \
-f components/serverless/docker-compose.serverless.yml up -d
- name: Waiting for server

@ -4,6 +4,7 @@
// SPDX-License-Identifier: MIT
import { Storage } from './storage';
const serverProxy = require('./server-proxy').default;
const Collection = require('./annotations-collection');
const AnnotationsSaver = require('./annotations-saver');

@ -127,6 +127,7 @@ function SelectCloudStorage(props: Props): JSX.Element {
setSearchPhrase(selectedCloudStorage?.displayName || '');
}}
allowClear
className={`cvat-search${!name ? '-' : `-${name[0].replace('Storage', '-storage')}-`}cloud-storage-field`}
>
<Input />
</AutoComplete>

@ -31,6 +31,11 @@ export default function StorageField(props: Props): JSX.Element {
} = props;
const [cloudStorage, setCloudStorage] = useState<CloudStorage | null>(null);
const [potentialCloudStorage, setPotentialCloudStorage] = useState('');
const [storageType, setStorageType] = useState('');
useEffect(() => {
setStorageType(locationName[0].replace('Storage', '-storage'));
}, [locationName]);
function renderCloudStorage(): JSX.Element {
return (
@ -65,6 +70,7 @@ export default function StorageField(props: Props): JSX.Element {
<>
<Form.Item name={locationName}>
<Select
virtual={false}
onChange={(location: StorageLocation) => {
if (onChangeLocationValue) onChangeLocationValue(location);
}}
@ -72,9 +78,22 @@ export default function StorageField(props: Props): JSX.Element {
if (onChangeLocationValue) onChangeLocationValue(StorageLocation.LOCAL);
}}
allowClear
className={`cvat-select-${storageType}`}
>
<Option value={StorageLocation.LOCAL}>Local</Option>
<Option value={StorageLocation.CLOUD_STORAGE}>Cloud storage</Option>
<Option
value={StorageLocation.LOCAL}
key={`${storageType}-${StorageLocation.LOCAL.toLowerCase()}`}
className={`cvat-select-${storageType}-location`}
>
Local
</Option>
<Option
value={StorageLocation.CLOUD_STORAGE}
key={`${storageType}-${StorageLocation.CLOUD_STORAGE.toLowerCase()}`}
className={`cvat-select-${storageType}-location`}
>
Cloud storage
</Option>
</Select>
</Form.Item>
{locationValue === StorageLocation.CLOUD_STORAGE && renderCloudStorage()}

@ -14,6 +14,7 @@ description: 'Instructions on how to run all existence tests.'
-f docker-compose.yml \
-f docker-compose.dev.yml \
-f components/serverless/docker-compose.serverless.yml \
-f tests/docker-compose.minio.yml \
-f tests/docker-compose.file_share.yml up -d
```
1. Add test user in CVAT:

@ -0,0 +1,165 @@
// Copyright (C) 2022 CVAT.ai Corporation
//
// SPDX-License-Identifier: MIT
/// <reference types="cypress" />
context('Tests source & target storage for backups.', () => {
const backupArchiveName = 'project_backup';
let projectID = '';
let createdCloudStorageId;
const caseId = '117';
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 dataArchiveName = `${imageFileName}.zip`;
const archivePath = `cypress/fixtures/${dataArchiveName}`;
const imagesFolder = `cypress/fixtures/${imageFileName}`;
const directoryToArchive = imagesFolder;
const serverHost = Cypress.config('baseUrl').includes('3000') ? 'localhost' : 'minio';
const cloudStorageData = {
displayName: 'Demo bucket',
resource: 'public',
manifest: 'manifest.jsonl',
endpointUrl: `http://${serverHost}:9000`,
};
const storageConnectedToCloud = {
location: 'Cloud storage',
cloudStorageId: undefined,
};
const project = {
name: `Case ${caseId}`,
label: labelName,
attrName: 'color',
attrVaue: 'red',
multiAttrParams: false,
advancedConfiguration: {
sourceStorage: {
...storageConnectedToCloud,
displayName: cloudStorageData.displayName,
},
targetStorage: {
...storageConnectedToCloud,
displayName: cloudStorageData.displayName,
},
},
};
const task = {
name: taskName,
label: labelName,
attrName,
textDefaultValue,
dataArchiveName,
multiAttrParams: false,
forProject: true,
attachToProject: true,
projectName: project.name,
advancedConfiguration: {
sourceStorage: {
disableSwitch: true,
location: 'Local',
cloudStorageId: null,
},
targetStorage: {
disableSwitch: true,
location: 'Local',
cloudStorageId: null,
},
},
};
function getProjectID() {
cy.url().then((url) => {
projectID = Number(url.split('/').slice(-1)[0].split('?')[0]);
});
}
before(() => {
cy.visit('auth/login');
cy.login();
createdCloudStorageId = cy.attachS3Bucket(cloudStorageData);
cy.imageGenerator(imagesFolder, imageFileName, width, height, color, posX, posY, labelName, imagesCount);
cy.createZipArchive(directoryToArchive, archivePath);
cy.goToProjectsList();
project.advancedConfiguration.sourceStorage.cloudStorageId = createdCloudStorageId;
project.advancedConfiguration.targetStorage.cloudStorageId = createdCloudStorageId;
cy.createProjects(
project.name,
project.label,
project.attrName,
project.attrVaue,
project.multiAttrParams,
project.advancedConfiguration,
);
cy.goToTaskList();
cy.createAnnotationTask(
task.name,
task.label,
task.attrName,
task.textDefaultValue,
dataArchiveName,
task.multiAttrParams,
null,
task.forProject,
task.attachToProject,
task.projectName,
);
cy.openProject(project.name);
getProjectID();
});
after(() => {
cy.goToCloudStoragesPage();
cy.deleteCloudStorage(cloudStorageData.displayName);
cy.logout();
cy.getAuthKey().then((authKey) => {
cy.deleteProjects(authKey, [project.name]);
});
});
describe(`Testing case "${caseId}"`, () => {
it('Export project to custom local storage', () => {
cy.goToProjectsList();
cy.backupProject(
project.name,
backupArchiveName,
{ location: 'Local' },
false,
);
cy.waitForDownload();
});
it('Export project to default minio bucket', () => {
cy.goToProjectsList();
cy.backupProject(
project.name,
backupArchiveName,
project.advancedConfiguration.targetStorage,
);
cy.waitForFileUploadToCloudStorage();
cy.deleteProject(project.name, projectID);
});
it('Import project from minio bucket', () => {
cy.restoreProject(
`${backupArchiveName}.zip`,
project.advancedConfiguration.sourceStorage,
);
});
});
});

@ -112,12 +112,12 @@ context('Import annotations for frames with dots in name.', { browser: '!firefox
it('Upload annotation with YOLO format to job.', () => {
cy.interactMenu('Upload annotations');
cy.intercept('GET', '/api/jobs/**/annotations?**').as('uploadAnnotationsGet');
uploadAnnotation(
dumpType.split(' ')[0],
annotationArchiveName,
'.cvat-modal-content-load-job-annotation',
);
cy.intercept('GET', '/api/jobs/**/annotations?**').as('uploadAnnotationsGet');
cy.wait('@uploadAnnotationsGet').its('response.statusCode').should('equal', 200);
cy.contains('Annotations have been loaded').should('be.visible');
cy.closeNotification('.ant-notification-notice-info');

@ -0,0 +1,185 @@
// Copyright (C) 2022 CVAT.ai Corporation
//
// SPDX-License-Identifier: MIT
/// <reference types="cypress" />
context('Tests for source and target storage.', () => {
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 dataArchiveName = `${imageFileName}.zip`;
const archivePath = `cypress/fixtures/${dataArchiveName}`;
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('3000') ? 'localhost' : 'minio';
const cloudStorageData = {
displayName: 'Demo bucket',
resource: 'public',
manifest: 'manifest.jsonl',
endpointUrl: `http://${serverHost}:9000`,
};
const storageConnectedToCloud = {
location: 'Cloud storage',
cloudStorageId: undefined,
};
const project = {
name: `Case ${caseId}`,
label: labelName,
attrName: 'color',
attrVaue: 'red',
multiAttrParams: false,
advancedConfiguration: {
sourceStorage: {
...storageConnectedToCloud,
displayName: cloudStorageData.displayName,
},
targetStorage: {
...storageConnectedToCloud,
displayName: cloudStorageData.displayName,
},
},
};
const task = {
name: taskName,
label: labelName,
attrName,
textDefaultValue,
dataArchiveName,
multiAttrParams: false,
forProject: true,
attachToProject: true,
projectName: project.name,
advancedConfiguration: {
sourceStorage: {
disableSwitch: true,
location: 'Local',
cloudStorageId: null,
},
targetStorage: {
disableSwitch: true,
location: 'Local',
cloudStorageId: null,
},
},
};
before(() => {
cy.visit('auth/login');
cy.login();
createdCloudStorageId = cy.attachS3Bucket(cloudStorageData);
cy.imageGenerator(imagesFolder, imageFileName, width, height, color, posX, posY, labelName, imagesCount);
cy.createZipArchive(directoryToArchive, archivePath);
cy.goToProjectsList();
project.advancedConfiguration.sourceStorage.cloudStorageId = createdCloudStorageId;
project.advancedConfiguration.targetStorage.cloudStorageId = createdCloudStorageId;
cy.createProjects(
project.name,
project.label,
project.attrName,
project.attrVaue,
project.multiAttrParams,
project.advancedConfiguration,
);
});
after(() => {
cy.goToCloudStoragesPage();
cy.deleteCloudStorage(cloudStorageData.displayName);
cy.logout();
cy.getAuthKey().then((authKey) => {
cy.deleteProjects(authKey, [project.name]);
});
});
describe(`Testing case "${caseId}"`, () => {
it('Export job annotations to default minio bucket that was attached to the project.', () => {
// create an annotation task with default project source and target storages
cy.goToTaskList();
cy.createAnnotationTask(
task.name,
task.label,
task.attrName,
task.textDefaultValue,
dataArchiveName,
task.multiAttrParams,
null,
task.forProject,
task.attachToProject,
task.projectName,
);
cy.goToTaskList();
cy.openTask(task.name);
// create dummy annotations and export them to "public" minio bucket
cy.openJob();
cy.createRectangle(createRectangleShape2Points).then(() => {
Cypress.config('scrollBehavior', false);
});
cy.saveJob('PATCH', 200, 'saveJobDump');
const exportParams = {
type: 'annotations',
format,
archiveCustomeName: 'job_annotations',
targetStorage: project.advancedConfiguration.targetStorage,
};
cy.exportJob(exportParams);
cy.waitForFileUploadToCloudStorage();
// remove annotations
cy.removeAnnotations();
cy.saveJob('PUT');
cy.get('#cvat_canvas_shape_1').should('not.exist');
cy.get('#cvat-objects-sidebar-state-item-1').should('not.exist');
});
it('Import job annotations from default minio bucket that was attached to the project.', () => {
// upload annotations from "public" minio bucket
cy.interactMenu('Upload annotations');
cy.intercept('GET', '/api/jobs/**/annotations?**').as('uploadAnnotationsGet');
cy.uploadAnnotations(
format.split(' ')[0],
'job_annotations.zip',
'.cvat-modal-content-load-job-annotation',
project.advancedConfiguration.sourceStorage,
);
cy.get('.cvat-notification-notice-upload-annotations-fail').should('not.exist');
cy.get('#cvat_canvas_shape_1').should('exist');
cy.get('#cvat-objects-sidebar-state-item-1').should('exist');
cy.goToTaskList();
cy.deleteTask(task.name);
});
});
});

@ -0,0 +1,194 @@
// Copyright (C) 2022 CVAT.ai Corporation
//
// SPDX-License-Identifier: MIT
/// <reference types="cypress" />
context('Tests for source and target storage.', () => {
let annotationsArchiveName = '';
let createdCloudStorageId;
const caseId = '114';
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 dataArchiveName = `${imageFileName}.zip`;
const archivePath = `cypress/fixtures/${dataArchiveName}`;
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('3000') ? 'localhost' : 'minio';
const cloudStorageData = {
displayName: 'Demo bucket',
resource: 'public',
manifest: 'manifest.jsonl',
endpointUrl: `http://${serverHost}:9000`,
};
const storageConnectedToCloud = {
location: 'Cloud storage',
cloudStorageId: undefined,
};
const project = {
name: `Case ${caseId}`,
label: labelName,
attrName: 'color',
attrVaue: 'red',
multiAttrParams: false,
advancedConfiguration: {
sourceStorage: {
...storageConnectedToCloud,
displayName: cloudStorageData.displayName,
},
targetStorage: {
...storageConnectedToCloud,
displayName: cloudStorageData.displayName,
},
},
};
const task = {
name: taskName,
label: labelName,
attrName,
textDefaultValue,
dataArchiveName,
multiAttrParams: false,
forProject: true,
attachToProject: true,
projectName: project.name,
advancedConfiguration: {
sourceStorage: {
disableSwitch: true,
location: 'Local',
cloudStorageId: null,
},
targetStorage: {
disableSwitch: true,
location: 'Local',
cloudStorageId: null,
},
},
};
before(() => {
cy.visit('auth/login');
cy.login();
createdCloudStorageId = cy.attachS3Bucket(cloudStorageData);
cy.imageGenerator(imagesFolder, imageFileName, width, height, color, posX, posY, labelName, imagesCount);
cy.createZipArchive(directoryToArchive, archivePath);
cy.goToProjectsList();
project.advancedConfiguration.sourceStorage.cloudStorageId = createdCloudStorageId;
project.advancedConfiguration.targetStorage.cloudStorageId = createdCloudStorageId;
cy.createProjects(
project.name,
project.label,
project.attrName,
project.attrVaue,
project.multiAttrParams,
project.advancedConfiguration,
);
});
after(() => {
cy.goToCloudStoragesPage();
cy.deleteCloudStorage(cloudStorageData.displayName);
cy.logout();
cy.getAuthKey().then((authKey) => {
cy.deleteProjects(authKey, [project.name]);
});
});
describe(`Testing case "${caseId}"`, () => {
it('Export job annotations to default minio bucket that was attached to the task in the project.', () => {
// create an annotation task with custom local source & target storages
cy.goToTaskList();
cy.createAnnotationTask(
task.name,
task.label,
task.attrName,
task.textDefaultValue,
dataArchiveName,
task.multiAttrParams,
task.advancedConfiguration,
task.forProject,
task.attachToProject,
task.projectName,
);
cy.goToTaskList();
cy.openTask(task.name);
// create dummy annotations and export them to default local storage
cy.openJob();
cy.createRectangle(createRectangleShape2Points).then(() => {
Cypress.config('scrollBehavior', false);
});
cy.saveJob('PATCH', 200, 'saveJobDump');
const exportParams = {
type: 'annotations',
format,
archiveCustomeName: 'job_annotations',
targetStorage: project.advancedConfiguration.targetStorage,
};
cy.exportJob(exportParams);
cy.getDownloadFileName().then((file) => {
annotationsArchiveName = file;
cy.verifyDownload(annotationsArchiveName);
});
cy.verifyNotification();
// remove annotations
cy.removeAnnotations();
cy.saveJob('PUT');
cy.get('#cvat_canvas_shape_1').should('not.exist');
cy.get('#cvat-objects-sidebar-state-item-1').should('not.exist');
});
it('Import job annotations from default minio bucket that was attached to the task in the project.', () => {
cy.goToTaskList();
cy.openTask(task.name);
cy.openJob();
// upload annotations from default local storage
cy.interactMenu('Upload annotations');
cy.intercept('GET', '/api/jobs/**/annotations?**').as('uploadAnnotationsGet');
cy.uploadAnnotations(
format.split(' ')[0],
annotationsArchiveName,
'.cvat-modal-content-load-job-annotation',
task.advancedConfiguration.sourceStorage,
);
cy.get('.cvat-notification-notice-upload-annotations-fail').should('not.exist');
cy.get('#cvat_canvas_shape_1').should('exist');
cy.get('#cvat-objects-sidebar-state-item-1').should('exist');
cy.goToTaskList();
cy.deleteTask(task.name);
});
});
});

@ -0,0 +1,155 @@
// Copyright (C) 2022 CVAT.ai Corporation
//
// SPDX-License-Identifier: MIT
/// <reference types="cypress" />
context('Import and export annotations: specify source and target storage in modals.', () => {
let createdCloudStorageId;
const caseId = '115';
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 dataArchiveName = `${imageFileName}.zip`;
const archivePath = `cypress/fixtures/${dataArchiveName}`;
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('3000') ? 'localhost' : 'minio';
const cloudStorageData = {
displayName: 'Demo bucket',
resource: 'public',
manifest: 'manifest.jsonl',
endpointUrl: `http://${serverHost}:9000`,
};
const project = {
name: `Case ${caseId}`,
label: labelName,
attrName: 'color',
attrVaue: 'red',
multiAttrParams: false,
};
const task = {
name: taskName,
label: labelName,
attrName,
textDefaultValue,
dataArchiveName,
multiAttrParams: false,
forProject: true,
attachToProject: true,
projectName: project.name,
};
before(() => {
cy.visit('auth/login');
cy.login();
createdCloudStorageId = cy.attachS3Bucket(cloudStorageData);
cy.imageGenerator(imagesFolder, imageFileName, width, height, color, posX, posY, labelName, imagesCount);
cy.createZipArchive(directoryToArchive, archivePath);
cy.goToProjectsList();
cy.createProjects(
project.name,
project.label,
project.attrName,
project.attrVaue,
project.multiAttrParams,
);
});
after(() => {
cy.goToCloudStoragesPage();
cy.deleteCloudStorage(cloudStorageData.displayName);
cy.logout();
cy.getAuthKey().then((authKey) => {
cy.deleteProjects(authKey, [project.name]);
});
});
describe(`Testing case "${caseId}"`, () => {
it('Export job annotations to custom minio bucket', () => {
// create an annotation task with local source & target storages
cy.goToTaskList();
cy.createAnnotationTask(
task.name,
task.label,
task.attrName,
task.textDefaultValue,
dataArchiveName,
task.multiAttrParams,
null,
task.forProject,
task.attachToProject,
task.projectName,
);
cy.goToTaskList();
cy.openTask(task.name);
cy.openJob();
// create dummy annotations and export them to "public" minio bucket
cy.createRectangle(createRectangleShape2Points).then(() => {
Cypress.config('scrollBehavior', false);
});
cy.saveJob('PATCH', 200, 'saveJobDump');
const exportParams = {
type: 'annotations',
format,
archiveCustomeName: 'job_annotations',
targetStorage: {
location: 'Cloud storage',
cloudStorageId: createdCloudStorageId,
},
useDefaultLocation: false,
};
cy.exportJob(exportParams);
cy.waitForFileUploadToCloudStorage();
// remove annotations
cy.removeAnnotations();
cy.saveJob('PUT');
cy.get('#cvat_canvas_shape_1').should('not.exist');
cy.get('#cvat-objects-sidebar-state-item-1').should('not.exist');
});
it('Import job annotations from custom minio "public" bucket', () => {
cy.interactMenu('Upload annotations');
cy.intercept('GET', '/api/jobs/**/annotations?**').as('uploadAnnotationsGet');
cy.uploadAnnotations(
format.split(' ')[0],
'job_annotations.zip',
'.cvat-modal-content-load-job-annotation',
{
location: 'Cloud storage',
cloudStorageId: createdCloudStorageId,
},
false,
);
cy.get('.cvat-notification-notice-upload-annotations-fail').should('not.exist');
cy.get('#cvat_canvas_shape_1').should('exist');
cy.get('#cvat-objects-sidebar-state-item-1').should('exist');
});
});
});

@ -645,6 +645,41 @@ Cypress.Commands.add('advancedConfiguration', (advancedConfigurationParams) => {
if (advancedConfigurationParams.overlapSize) {
cy.get('#overlapSize').type(advancedConfigurationParams.overlapSize);
}
if (advancedConfigurationParams.sourceStorage) {
const { sourceStorage } = advancedConfigurationParams;
if (sourceStorage.disableSwitch) {
cy.get('.ant-collapse-content-box').find('#useProjectSourceStorage').click();
}
cy.get('.cvat-select-source-storage').within(() => {
cy.get('.ant-select-selection-item').click();
});
cy.contains('.cvat-select-source-storage-location', sourceStorage.location).should('be.visible').click();
if (sourceStorage.cloudStorageId) {
cy.get('.cvat-search-source-storage-cloud-storage-field').click();
cy.get('.cvat-cloud-storage-select-provider').click();
}
}
if (advancedConfigurationParams.targetStorage) {
const { targetStorage } = advancedConfigurationParams;
if (targetStorage.disableSwitch) {
cy.get('.ant-collapse-content-box').find('#useProjectTargetStorage').click();
}
cy.get('.cvat-select-target-storage').within(() => {
cy.get('.ant-select-selection-item').click();
});
cy.contains('.cvat-select-target-storage-location', targetStorage.location).should('be.visible').click();
if (targetStorage.cloudStorageId) {
cy.get('.cvat-search-target-storage-cloud-storage-field').click();
cy.get('.cvat-cloud-storage-select-provider').last().click();
}
}
});
Cypress.Commands.add('removeAnnotations', () => {
@ -657,6 +692,57 @@ Cypress.Commands.add('removeAnnotations', () => {
});
});
Cypress.Commands.add('confirmUpdate', (modalWindowClassName) => {
cy.get(modalWindowClassName).should('be.visible').within(() => {
cy.contains('button', 'Update').click();
});
});
Cypress.Commands.add(
'uploadAnnotations', (
format,
file,
confirmModalClassName,
sourceStorage = null,
useDefaultLocation = true,
) => {
cy.get('.cvat-modal-import-dataset').find('.cvat-modal-import-select').click();
cy.contains('.cvat-modal-import-dataset-option-item', format).click();
cy.get('.cvat-modal-import-select').should('contain.text', format);
if (!useDefaultLocation) {
cy.get('.cvat-modal-import-dataset')
.find('.cvat-modal-import-switch-use-default-storage')
.click();
cy.get('.cvat-select-source-storage').within(() => {
cy.get('.ant-select-selection-item').click();
});
cy.contains('.cvat-select-source-storage-location', sourceStorage.location)
.should('be.visible')
.click();
if (sourceStorage.cloudStorageId) {
cy.get('.cvat-search-source-storage-cloud-storage-field').click();
cy.get('.cvat-cloud-storage-select-provider').click();
}
}
if (sourceStorage && sourceStorage.cloudStorageId) {
cy.get('.cvat-modal-import-dataset')
.find('.cvat-modal-import-filename-input')
.type(file);
} else {
cy.get('input[type="file"]').attachFile(file, { subjectType: 'drag-n-drop' });
cy.get(`[title="${file}"]`).should('be.visible');
}
cy.contains('button', 'OK').click();
cy.confirmUpdate(confirmModalClassName);
cy.get('.cvat-notification-notice-import-annotation-start').should('be.visible');
cy.closeNotification('.cvat-notification-notice-import-annotation-start');
cy.wait('@uploadAnnotationsGet').its('response.statusCode').should('equal', 200);
cy.contains('Annotations have been loaded').should('be.visible');
cy.closeNotification('.ant-notification-notice-info');
},
);
Cypress.Commands.add('goToTaskList', () => {
cy.get('a[value="tasks"]').click();
cy.url().should('include', '/tasks');
@ -877,6 +963,7 @@ Cypress.Commands.add('exportTask', ({
Cypress.Commands.add('exportJob', ({
type, format, archiveCustomeName,
targetStorage = null, useDefaultLocation = true,
}) => {
cy.interactMenu('Export job dataset');
cy.get('.cvat-modal-export-job').should('be.visible').find('.cvat-modal-export-select').click();
@ -888,6 +975,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').click();
cy.get('.cvat-select-target-storage').within(() => {
cy.get('.ant-select-selection-item').click();
});
cy.contains('.cvat-select-target-storage-location', targetStorage.location).should('be.visible').click();
if (targetStorage.cloudStorageId) {
cy.get('.cvat-search-target-storage-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');
@ -952,6 +1051,25 @@ Cypress.Commands.add('verifyNotification', () => {
cy.closeNotification('.ant-notification-notice-info');
});
Cypress.Commands.add('goToCloudStoragesPage', () => {
cy.get('a[value="cloudstorages"]').click();
cy.url().should('include', '/cloudstorages');
});
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')
.within(() => {
cy.contains('[role="menuitem"]', 'Delete').click();
});
cy.get('.cvat-delete-cloud-storage-modal')
.should('contain', `You are going to remove the cloudstorage "${displayName}"`)
.within(() => {
cy.contains('button', 'Delete').click();
});
});
Cypress.Commands.overwrite('visit', (orig, url, options) => {
orig(url, options);
cy.closeModalUnsupportedPlatform();

@ -0,0 +1,46 @@
// Copyright (C) 2022 CVAT.ai Corp
//
// SPDX-License-Identifier: MIT
/// <reference types="cypress" />
Cypress.Commands.add('attachS3Bucket', (data) => {
let createdCloudStorageId;
cy.contains('.cvat-header-button', 'Cloud Storages').should('be.visible').click();
cy.get('.cvat-attach-cloud-storage-button').should('be.visible').click();
cy.get('#display_name')
.type(data.displayName)
.should('have.attr', 'value', data.displayName);
cy.get('#provider_type').click();
cy.contains('.cvat-cloud-storage-select-provider', 'AWS').click();
cy.get('#resource')
.should('exist')
.type(data.resource)
.should('have.attr', 'value', data.resource);
cy.get('#credentials_type').should('exist').click();
cy.get('.ant-select-dropdown')
.not('.ant-select-dropdown-hidden')
.get('[title="Anonymous access"]')
.should('be.visible')
.click();
cy.get('#endpoint_url')
.type(data.endpointUrl)
.should('have.attr', 'value', data.endpointUrl);
cy.get('.cvat-add-manifest-button').should('be.visible').click();
cy.get('[placeholder="manifest.jsonl"]')
.should('exist')
.should('have.attr', 'value', '')
.type(data.manifest)
.should('have.attr', 'value', data.manifest);
cy.intercept('POST', /\/api\/cloudstorages.*/).as('createCloudStorage');
cy.get('.cvat-cloud-storage-form').within(() => {
cy.contains('button', 'Submit').click();
});
cy.wait('@createCloudStorage').then((interseption) => {
expect(interseption.response.statusCode).to.be.equal(201);
createdCloudStorageId = interseption.response.body.id;
});
cy.verifyNotification();
return createdCloudStorageId;
});

@ -1,4 +1,5 @@
// Copyright (C) 2020-2022 Intel Corporation
// Copyright (C) 2022 CVAT.ai Corporation
//
// SPDX-License-Identifier: MIT
@ -12,7 +13,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 +31,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();
@ -136,34 +144,83 @@ Cypress.Commands.add('importProject', ({
cy.get('.cvat-modal-import-dataset-status').should('not.exist');
});
Cypress.Commands.add('backupProject', (projectName, backupFileName) => {
cy.projectActions(projectName);
cy.get('.cvat-project-actions-menu').contains('Backup Project').click();
cy.get('.cvat-modal-export-project').should('be.visible');
if (backupFileName) {
cy.get('.cvat-modal-export-project').find('.cvat-modal-export-filename-input').type(backupFileName);
}
cy.get('.cvat-modal-export-project').contains('button', 'OK').click();
cy.get('.cvat-notification-notice-export-backup-start').should('be.visible');
cy.closeNotification('.cvat-notification-notice-export-backup-start');
});
Cypress.Commands.add(
'backupProject',
(
projectName,
backupFileName,
targetStorage = null,
useDefaultLocation = true,
) => {
cy.projectActions(projectName);
cy.get('.cvat-project-actions-menu').contains('Backup Project').click();
cy.get('.cvat-modal-export-project').should('be.visible');
if (backupFileName) {
cy.get('.cvat-modal-export-project').find('.cvat-modal-export-filename-input').type(backupFileName);
}
if (!useDefaultLocation) {
cy.get('.cvat-modal-export-project')
.find('.cvat-settings-switch')
.click();
cy.get('.cvat-select-target-storage').within(() => {
cy.get('.ant-select-selection-item').click();
});
cy.contains('.cvat-select-target-storage-location', targetStorage.location)
.should('be.visible')
.click();
Cypress.Commands.add('restoreProject', (archiveWithBackup) => {
if (targetStorage && targetStorage.cloudStorageId) {
cy.get('.cvat-search-target-storage-cloud-storage-field').click();
cy.get('.cvat-cloud-storage-select-provider').click();
}
}
cy.get('.cvat-modal-export-project').contains('button', 'OK').click();
cy.get('.cvat-notification-notice-export-backup-start').should('be.visible');
cy.closeNotification('.cvat-notification-notice-export-backup-start');
},
);
Cypress.Commands.add('restoreProject', (archiveWithBackup, sourceStorage = null) => {
cy.intercept({ method: /PATCH|POST/, url: /\/api\/projects\/backup.*/ }).as('restoreProject');
cy.get('.cvat-create-project-dropdown').click();
cy.get('.cvat-import-project-button').click();
cy.get('input[type=file]').attachFile(archiveWithBackup, { subjectType: 'drag-n-drop' });
cy.get(`[title="${archiveWithBackup}"]`).should('be.visible');
if (sourceStorage) {
cy.get('.cvat-select-source-storage').within(() => {
cy.get('.ant-select-selection-item').click();
});
cy.contains('.cvat-select-source-storage-location', sourceStorage.location)
.should('be.visible')
.click();
if (sourceStorage.cloudStorageId) {
cy.get('.cvat-search-source-storage-cloud-storage-field').click();
cy.get('.cvat-cloud-storage-select-provider').click();
cy.get('.cvat-modal-import-backup')
.find('.cvat-modal-import-filename-input')
.type(archiveWithBackup);
}
} else {
cy.get('input[type=file]').attachFile(archiveWithBackup, { subjectType: 'drag-n-drop' });
cy.get(`[title="${archiveWithBackup}"]`).should('be.visible');
}
cy.contains('button', 'OK').click();
cy.get('.cvat-notification-notice-import-backup-start').should('be.visible');
cy.closeNotification('.cvat-notification-notice-import-backup-start');
cy.wait('@restoreProject').its('response.statusCode').should('equal', 202);
cy.wait('@restoreProject').its('response.statusCode').should('equal', 201);
cy.wait('@restoreProject').its('response.statusCode').should('equal', 204);
cy.wait('@restoreProject').its('response.statusCode').should('equal', 202);
cy.wait('@restoreProject', { timeout: 5000 }).its('response.statusCode').should('equal', 202);
cy.wait('@restoreProject').its('response.statusCode').should('equal', 201);
if (!sourceStorage || !sourceStorage.cloudStorageId) {
cy.wait('@restoreProject').its('response.statusCode').should('equal', 202);
cy.wait('@restoreProject').its('response.statusCode').should('equal', 201);
cy.wait('@restoreProject').its('response.statusCode').should('equal', 204);
cy.wait('@restoreProject').its('response.statusCode').should('equal', 202);
cy.wait('@restoreProject', { timeout: 5000 }).its('response.statusCode').should('equal', 202);
cy.wait('@restoreProject').its('response.statusCode').should('equal', 201);
} else {
cy.wait('@restoreProject').its('response.statusCode').should('equal', 202);
cy.wait('@restoreProject', { timeout: 3000 }).its('response.statusCode').should('equal', 202);
cy.wait('@restoreProject').its('response.statusCode').should('equal', 201);
}
cy.contains('The project has been restored succesfully. Click here to open')
.should('exist')
.and('be.visible');
@ -179,6 +236,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);

@ -1,4 +1,5 @@
// Copyright (C) 2020-2022 Intel Corporation
// Copyright (C) 2022 CVAT.ai Corporation
//
// SPDX-License-Identifier: MIT
@ -10,6 +11,7 @@ require('./commands_filters_feature');
require('./commands_models');
require('./commands_opencv');
require('./commands_organizations');
require('./commands_cloud_storages');
require('@cypress/code-coverage/support');
require('cypress-real-events/support');

@ -27,7 +27,7 @@ CONTAINER_NAME_FILES = [
DC_FILES = [
osp.join(CVAT_ROOT_DIR, dc_file)
for dc_file in ("docker-compose.dev.yml", "tests/python/shared/docker-compose.minio.yml")
for dc_file in ("docker-compose.dev.yml", "tests/docker-compose.minio.yml")
] + CONTAINER_NAME_FILES

Loading…
Cancel
Save