cvat/tests/cypress/e2e/features/single_object_annotation.js

269 lines
9.4 KiB
JavaScript

// Copyright (C) CVAT.ai Corporation
//
// SPDX-License-Identifier: MIT
/// <reference types="cypress" />
/*
TODO: Add new test cases
- After drawing with disabled "autoNext", user should be able to activate and drag/resize object
- User also should be able to remove activated object with shortcut
- After removing an object, drawing should start automatically
*/
context('Single object annotation mode', { scrollBehavior: false }, () => {
const taskName = 'Single object annotation mode';
const serverFiles = ['images/image_1.jpg', 'images/image_2.jpg', 'images/image_3.jpg'];
const frameCount = serverFiles.length;
let taskID = null;
let jobID = null;
const rectangleShape = [
{ x: 300, y: 100 },
{ x: 400, y: 400 },
];
const polygonShape = [
{ x: 300, y: 100 },
{ x: 400, y: 400 },
{ x: 400, y: 250 },
{ x: 450, y: 350 },
];
const polylineShape = [
{ x: 300, y: 100 },
{ x: 400, y: 400 },
{ x: 400, y: 250 },
{ x: 450, y: 350 },
{ x: 500, y: 450 },
];
const pointsShape = [
{ x: 300, y: 100 },
{ x: 400, y: 400 },
{ x: 400, y: 250 },
{ x: 450, y: 350 },
];
const ellipseShape = [
{ x: 300, y: 100 },
{ x: 400, y: 400 },
];
const cuboidShape = [
{ x: 300, y: 100 },
{ x: 400, y: 400 },
];
const maskActions = [{
method: 'brush',
coordinates: [[300, 300], [700, 300], [700, 700], [300, 700]],
}];
function clickPoints(shape) {
shape.forEach((element) => {
cy.get('.cvat-canvas-container').click(element.x, element.y);
});
}
function checkFrameNum(frameNum) {
cy.get('.cvat-player-frame-selector').within(() => {
cy.get('input[role="spinbutton"]').should('have.value', frameNum);
});
}
function checkSingleShapeModeOpened() {
cy.get('.cvat-workspace-selector').should('have.text', 'Single shape');
cy.get('.cvat-canvas-controls-sidebar').should('not.exist');
cy.get('.cvat-player-frame-selector input').should('be.disabled');
cy.get('.cvat-single-shape-annotation-sidebar-hint').should('exist');
cy.get('.cvat-single-shape-annotation-sidebar-ux-hints').should('exist');
cy.get('#cvat_canvas_wrapper').should('have.css', 'cursor', 'crosshair');
}
function openJob(params) {
cy.visit(`/tasks/${taskID}/jobs/${jobID}`, {
qs: {
defaultWorkspace: 'single_shape',
...params,
},
});
cy.get('.cvat-canvas-container').should('not.exist');
cy.get('.cvat-canvas-container').should('exist').and('be.visible');
}
function drawObject(creatorFunction) {
checkSingleShapeModeOpened();
cy.intercept('PATCH', `/api/jobs/${jobID}/**`).as('submitJob');
for (let frame = 0; frame < frameCount; frame++) {
checkFrameNum(frame);
creatorFunction();
}
cy.wait('@submitJob').its('response.statusCode').should('equal', 200);
cy.get('.cvat-annotation-job-finished-success').should('exist');
cy.get('.cvat-annotation-job-finished-success').should('not.exist');
}
function changeLabel(labelName) {
cy.get('.cvat-single-shape-annotation-sidebar-label-select').click();
cy.get('.ant-select-dropdown').not('.ant-select-dropdown-hidden').within(() => {
cy.get('.ant-select-item-option-content').contains(labelName).click();
});
}
function resetAfterTestCase() {
cy.removeAnnotations();
cy.saveJob('PUT');
}
before(() => {
cy.visit('/auth/login');
cy.login();
cy.headlessCreateTask({
labels: [
{ name: 'rectangle_label', attributes: [], type: 'rectangle' },
{ name: 'polygon_label', attributes: [], type: 'polygon' },
{ name: 'polyline_label', attributes: [], type: 'polyline' },
{ name: 'points_label', attributes: [], type: 'points' },
{ name: 'ellipse_label', attributes: [], type: 'ellipse' },
{ name: 'cuboid_label', attributes: [], type: 'cuboid' },
{ name: 'mask_label', attributes: [], type: 'mask' },
],
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((response) => {
taskID = response.taskID;
[jobID] = response.jobIDs;
}).then(() => {
cy.visit(`/tasks/${taskID}/jobs/${jobID}`);
cy.get('.cvat-canvas-container').should('exist').and('be.visible');
});
});
after(() => {
cy.logout();
cy.getAuthKey().then((response) => {
const authKey = response.body.key;
cy.request({
method: 'DELETE',
url: `/api/tasks/${taskID}`,
headers: {
Authorization: `Token ${authKey}`,
},
});
});
});
describe('Tests basic features of single shape annotation mode', () => {
afterEach(resetAfterTestCase);
it('Check basic single shape annotation pipeline for polygon', () => {
openJob({ defaultLabel: 'polygon_label', defaultPointsCount: 4 });
drawObject(() => clickPoints(polygonShape));
});
it('Check basic single shape annotation pipeline for rectangle', () => {
openJob({ defaultLabel: 'rectangle_label' });
drawObject(() => clickPoints(rectangleShape));
});
it('Check basic single shape annotation pipeline for polyline', () => {
openJob({ defaultLabel: 'polyline_label', defaultPointsCount: 5 });
drawObject(() => clickPoints(polylineShape));
});
it('Check basic single shape annotation pipeline for ellipse', () => {
openJob({ defaultLabel: 'ellipse_label' });
drawObject(() => clickPoints(ellipseShape));
});
it('Check basic single shape annotation pipeline for points', () => {
openJob({ defaultLabel: 'points_label', defaultPointsCount: 4 });
drawObject(() => clickPoints(pointsShape));
});
it('Check basic single shape annotation pipeline for cuboid', () => {
openJob({ defaultLabel: 'cuboid_label' });
drawObject(() => clickPoints(cuboidShape));
});
it('Check basic single shape annotation pipeline for mask', () => {
openJob({ defaultLabel: 'mask_label' });
cy.drawMask(maskActions);
cy.finishMaskDrawing();
});
});
describe('Tests advanced features of single shape annotation mode', () => {
afterEach(resetAfterTestCase);
it('Check single shape annotation mode controls', () => {
openJob({ defaultLabel: 'polygon_label', defaultPointsCount: 4 });
checkSingleShapeModeOpened();
// Skip
cy.get('.cvat-single-shape-annotation-sidebar-finish-frame-wrapper').within(() => {
cy.contains('Skip').click();
});
checkFrameNum(1);
// Auto next frame - disabled
cy.get('.cvat-single-shape-annotation-sidebar-auto-next-frame-checkbox').within(() => {
cy.get('[type="checkbox"]').uncheck();
});
clickPoints(polygonShape);
checkFrameNum(1);
// Auto save when finish - disabled
cy.get('.cvat-player-next-button-empty').click();
cy.get('.cvat-single-shape-annotation-sidebar-auto-save-checkbox').within(() => {
cy.get('[type="checkbox"]').uncheck();
});
clickPoints(polygonShape);
cy.get('.cvat-annotation-job-finished-success').should('not.exist');
// Navigate only on empty frames
cy.get('.cvat-player-previous-button-empty').click();
checkFrameNum(0);
cy.get('.cvat-player-next-button-empty').click();
checkFrameNum(0);
cy.get('.cvat-single-shape-annotation-sidebar-navigate-empty-checkbox').within(() => {
cy.get('[type="checkbox"]').uncheck();
});
cy.get('.cvat-player-next-button').click();
checkFrameNum(1);
cy.get('.cvat-player-next-button').click();
checkFrameNum(2);
cy.saveJob();
});
});
describe('Regression tests', () => {
afterEach(resetAfterTestCase);
it('Changing labels in single shape annotation mode', () => {
openJob({ defaultLabel: 'polygon_label', defaultPointsCount: 4 });
checkSingleShapeModeOpened();
const anotherLabelName = 'points_label';
changeLabel(anotherLabelName);
clickPoints(pointsShape);
cy.changeWorkspace('Standard');
cy.goCheckFrameNumber(0);
cy.get('#cvat-objects-sidebar-state-item-1').within(() => {
cy.get('.cvat-objects-sidebar-state-item-label-selector').should('have.text', anotherLabelName);
});
cy.saveJob();
});
});
});