1910 lines
72 KiB
JavaScript
1910 lines
72 KiB
JavaScript
// Copyright (C) 2020-2022 Intel Corporation
|
|
// Copyright (C) CVAT.ai Corporation
|
|
//
|
|
// SPDX-License-Identifier: MIT
|
|
|
|
/// <reference types="cypress" />
|
|
|
|
/* eslint-disable security/detect-non-literal-regexp */
|
|
|
|
import { decomposeMatrix } from './utils';
|
|
|
|
require('cypress-file-upload');
|
|
require('../plugins/imageGenerator/imageGeneratorCommand');
|
|
require('../plugins/createZipArchive/createZipArchiveCommand');
|
|
require('cypress-localstorage-commands');
|
|
require('../plugins/compareImages/compareImagesCommand');
|
|
require('../plugins/unpackZipArchive/unpackZipArchiveCommand');
|
|
require('cy-verify-downloads').addCustomCommand();
|
|
|
|
let selectedValueGlobal = '';
|
|
|
|
Cypress.Commands.add('login', (username = Cypress.env('user'), password = Cypress.env('password'), page = 'tasks') => {
|
|
cy.get('#credential').type(username);
|
|
cy.get('#password').type(password);
|
|
cy.get('.cvat-credentials-action-button').click();
|
|
cy.url().should('contain', `/${page}`);
|
|
cy.document().then((doc) => {
|
|
const loadSettingFailNotice = Array.from(doc.querySelectorAll('.cvat-notification-notice-load-settings-fail'));
|
|
if (loadSettingFailNotice.length > 0) {
|
|
cy.closeNotification('.cvat-notification-notice-load-settings-fail');
|
|
}
|
|
});
|
|
});
|
|
|
|
Cypress.Commands.add('logout', () => {
|
|
cy.get('.cvat-header-menu-user-dropdown-user').click();
|
|
cy.get('span[aria-label="logout"]').click();
|
|
cy.url().should('include', '/auth/login');
|
|
cy.clearCookies();
|
|
cy.visit('/auth/login');
|
|
cy.url().should('not.include', '?next=');
|
|
cy.contains('Sign in').should('exist');
|
|
});
|
|
|
|
Cypress.Commands.add('userRegistration', (firstName, lastName, userName, emailAddr, password) => {
|
|
cy.get('#firstName').type(firstName);
|
|
cy.get('#lastName').type(lastName);
|
|
cy.get('#username').type(userName);
|
|
cy.get('#email').type(emailAddr);
|
|
cy.get('#password1').type(password);
|
|
cy.get('.cvat-credentials-action-button').click();
|
|
if (Cypress.browser.family === 'chromium') {
|
|
cy.url().should('include', '/tasks');
|
|
}
|
|
});
|
|
|
|
Cypress.Commands.add('getAuthKey', () => {
|
|
cy.request({
|
|
method: 'POST',
|
|
url: '/api/auth/login',
|
|
body: {
|
|
username: Cypress.env('user'),
|
|
email: Cypress.env('email'),
|
|
password: Cypress.env('password'),
|
|
},
|
|
});
|
|
});
|
|
|
|
Cypress.Commands.add('deleteUsers', (authResponse, accountsToDelete) => {
|
|
const authKey = authResponse.body.key;
|
|
cy.request({
|
|
url: '/api/users?page_size=all',
|
|
headers: {
|
|
Authorization: `Token ${authKey}`,
|
|
},
|
|
}).then((_response) => {
|
|
const responseResult = _response.body.results;
|
|
for (const user of responseResult) {
|
|
const { id, username } = user;
|
|
for (const account of accountsToDelete) {
|
|
if (username === account) {
|
|
cy.request({
|
|
method: 'DELETE',
|
|
url: `/api/users/${id}`,
|
|
headers: {
|
|
Authorization: `Token ${authKey}`,
|
|
},
|
|
});
|
|
}
|
|
}
|
|
}
|
|
});
|
|
});
|
|
|
|
Cypress.Commands.add('headlessDeleteUser', (userId) => {
|
|
cy.intercept('DELETE', '/api/users/**').as('deleteUser');
|
|
cy.window().its('cvat', { timeout: 25000 }).should('not.be.undefined');
|
|
cy.window().then(async ($win) => {
|
|
await $win.cvat.server.request(`/api/users/${userId}`,
|
|
{ method: 'DELETE' },
|
|
);
|
|
});
|
|
cy.wait('@deleteUser');
|
|
});
|
|
|
|
Cypress.Commands.add('changeUserActiveStatus', (authKey, accountsToChangeActiveStatus, isActive) => {
|
|
cy.request({
|
|
url: '/api/users?page_size=all',
|
|
headers: {
|
|
Authorization: `Token ${authKey}`,
|
|
},
|
|
}).then((response) => {
|
|
const responseResult = response.body.results;
|
|
responseResult.forEach((user) => {
|
|
const userId = user.id;
|
|
const userName = user.username;
|
|
if (userName.includes(accountsToChangeActiveStatus)) {
|
|
cy.request({
|
|
method: 'PATCH',
|
|
url: `/api/users/${userId}`,
|
|
headers: {
|
|
Authorization: `Token ${authKey}`,
|
|
},
|
|
body: {
|
|
is_active: isActive,
|
|
},
|
|
});
|
|
}
|
|
});
|
|
});
|
|
});
|
|
|
|
Cypress.Commands.add('checkUserStatuses', (authKey, userName, staffStatus, superuserStatus, activeStatus) => {
|
|
cy.request({
|
|
url: '/api/users?page_size=all',
|
|
headers: {
|
|
Authorization: `Token ${authKey}`,
|
|
},
|
|
}).then((response) => {
|
|
const responseResult = response.body.results;
|
|
responseResult.forEach((user) => {
|
|
if (user.username.includes(userName)) {
|
|
expect(staffStatus).to.be.equal(user.is_staff);
|
|
expect(superuserStatus).to.be.equal(user.is_superuser);
|
|
expect(activeStatus).to.be.equal(user.is_active);
|
|
}
|
|
});
|
|
});
|
|
});
|
|
|
|
Cypress.Commands.add('deleteTasks', (authResponse, tasksToDelete) => {
|
|
const authKey = authResponse.body.key;
|
|
cy.request({
|
|
url: '/api/tasks?page_size=all',
|
|
headers: {
|
|
Authorization: `Token ${authKey}`,
|
|
},
|
|
}).then((_response) => {
|
|
const responseResult = _response.body.results;
|
|
for (const task of responseResult) {
|
|
const { id, name } = task;
|
|
for (const taskToDelete of tasksToDelete) {
|
|
if (name === taskToDelete) {
|
|
cy.request({
|
|
method: 'DELETE',
|
|
url: `/api/tasks/${id}`,
|
|
headers: {
|
|
Authorization: `Token ${authKey}`,
|
|
},
|
|
});
|
|
}
|
|
}
|
|
}
|
|
});
|
|
});
|
|
|
|
Cypress.Commands.add(
|
|
'createAnnotationTask',
|
|
(
|
|
taskName = 'New annotation task',
|
|
labelName = 'Some label',
|
|
attrName = 'Some attr name',
|
|
textDefaultValue = 'Some default value for type Text',
|
|
image = 'image.png',
|
|
multiAttrParams = null,
|
|
advancedConfigurationParams = null,
|
|
forProject = false,
|
|
attachToProject = false,
|
|
projectName = '',
|
|
expectedResult = 'success',
|
|
projectSubsetFieldValue = 'Test',
|
|
qualityConfigurationParams = null,
|
|
) => {
|
|
cy.url().then(() => {
|
|
cy.get('.cvat-create-task-dropdown').click();
|
|
cy.get('.cvat-create-task-button').click({ force: true });
|
|
cy.url().should('include', '/tasks/create');
|
|
cy.get('[id="name"]').type(taskName);
|
|
if (!forProject) {
|
|
cy.get('.cvat-constructor-viewer-new-item').click();
|
|
cy.get('[placeholder="Label name"]').type(labelName);
|
|
cy.get('.cvat-new-attribute-button').click();
|
|
cy.get('[placeholder="Name"]').type(attrName);
|
|
cy.get('.cvat-attribute-type-input').click();
|
|
cy.get('.cvat-attribute-type-input-text').click();
|
|
cy.get('[placeholder="Default value"]').type(textDefaultValue);
|
|
if (multiAttrParams) {
|
|
cy.updateAttributes(multiAttrParams);
|
|
}
|
|
cy.contains('button', 'Continue').click();
|
|
} else {
|
|
if (attachToProject) {
|
|
cy.get('.cvat-project-search-field').click();
|
|
cy.get('.ant-select-dropdown')
|
|
.not('.ant-select-dropdown-hidden')
|
|
.within(() => {
|
|
cy.get(`.ant-select-item-option[title="${projectName}"]`).click();
|
|
});
|
|
}
|
|
cy.get('.cvat-project-search-field').first().within(() => {
|
|
cy.get('[type="search"]').should('have.value', projectName);
|
|
});
|
|
cy.get('.cvat-project-subset-field').type(`${projectSubsetFieldValue}{Enter}`);
|
|
cy.get('.cvat-constructor-viewer-new-item').should('not.exist');
|
|
}
|
|
cy.get('input[type="file"]').attachFile(image, { subjectType: 'drag-n-drop' });
|
|
if (advancedConfigurationParams) {
|
|
cy.advancedConfiguration(advancedConfigurationParams);
|
|
}
|
|
if (qualityConfigurationParams) {
|
|
cy.configureTaskQualityMode(qualityConfigurationParams);
|
|
}
|
|
cy.get('.cvat-submit-continue-task-button').scrollIntoView();
|
|
cy.get('.cvat-submit-continue-task-button').click();
|
|
if (expectedResult === 'success') {
|
|
cy.get('.cvat-notification-create-task-success').should('exist').find('[data-icon="close"]').click();
|
|
} else if (expectedResult === 'fail') {
|
|
cy.get('.cvat-notification-notice-create-task-failed').should('exist').find('[data-icon="close"]').click();
|
|
}
|
|
if (!forProject) {
|
|
cy.goToTaskList();
|
|
} else {
|
|
cy.goToProjectsList();
|
|
}
|
|
});
|
|
},
|
|
);
|
|
|
|
Cypress.Commands.add('selectFilesFromShare', (serverFiles) => {
|
|
cy.intercept('GET', '/api/server/share?**').as('shareRequest');
|
|
cy.contains('[role="tab"]', 'Connected file share').click();
|
|
cy.wait('@shareRequest');
|
|
|
|
const selectServerFiles = (files) => {
|
|
if (Array.isArray(files)) {
|
|
cy.get('.cvat-remote-browser-table-wrapper').within(() => {
|
|
files.forEach((file) => {
|
|
cy.get('.ant-table-cell').contains(file).parent().within(() => {
|
|
cy.get('.ant-checkbox-input').click();
|
|
});
|
|
});
|
|
});
|
|
cy.get('.cvat-remote-browser-nav-breadcrumb').contains('root').click();
|
|
} else {
|
|
for (const directory of Object.keys(files)) {
|
|
cy.get('.cvat-remote-browser-table-wrapper').within(() => {
|
|
cy.get('button').contains(directory).click();
|
|
cy.wait('@shareRequest');
|
|
});
|
|
selectServerFiles(files[directory]);
|
|
}
|
|
}
|
|
};
|
|
|
|
selectServerFiles(serverFiles);
|
|
});
|
|
|
|
Cypress.Commands.add('headlessLogin', ({
|
|
username,
|
|
password,
|
|
nextURL,
|
|
} = {}) => {
|
|
cy.window().its('cvat', { timeout: 25000 }).should('not.be.undefined');
|
|
return cy.window().then((win) => (
|
|
cy.headlessLogout().then(() => (
|
|
win.cvat.server.login(
|
|
username || Cypress.env('user'),
|
|
password || Cypress.env('password'),
|
|
).then(() => win.cvat.users.get({ self: true }).then((users) => {
|
|
if (nextURL) {
|
|
cy.intercept('GET', nextURL).as('nextPage');
|
|
cy.visit(nextURL);
|
|
return cy.wait('@nextPage').then(() => {
|
|
cy.url().should('include', nextURL);
|
|
cy.get('.cvat-spinner').should('not.exist');
|
|
}).then(() => users[0]);
|
|
}
|
|
|
|
return users[0];
|
|
}))
|
|
))
|
|
));
|
|
});
|
|
|
|
Cypress.Commands.add('headlessCreateObjects', (objects, jobID) => {
|
|
const convertShape = ($win, job) => (shape) => ({
|
|
frame: shape.frame,
|
|
type: shape.type,
|
|
points: $win.Array.from(shape.points),
|
|
label_id: job.labels.find((label) => label.name === shape.labelName).id,
|
|
occluded: shape.occluded || false,
|
|
outside: shape.outside || false,
|
|
source: shape.source || 'manual',
|
|
attributes: $win.Array.from(shape.attributes || []),
|
|
elements: $win.Array.from(shape.elements ? shape.elements.map(convertShape) : []),
|
|
rotation: shape.rotation || 0,
|
|
group: shape.group || 0,
|
|
z_order: shape.zOrder || 0,
|
|
});
|
|
|
|
const convertTag = ($win, job) => (tag) => ({
|
|
frame: tag.frame,
|
|
label_id: job.labels.find((label) => label.name === tag.labelName).id,
|
|
source: tag.source || 'manual',
|
|
attributes: $win.Array.from(tag.attributes || []),
|
|
group: tag.group || 0,
|
|
});
|
|
|
|
const convertTrack = ($win, job) => (track) => ({
|
|
frame: track.frame,
|
|
label_id: job.labels.find((label) => label.name === track.labelName).id,
|
|
group: track.group || 0,
|
|
source: track.source || 'manual',
|
|
attributes: $win.Array.from(track.attributes || []),
|
|
elements: $win.Array.from(track.elements ? track.elements.map(convertTrack) : []),
|
|
shapes: track.shapes.map((shape) => ({
|
|
attributes: $win.Array.from(shape.attributes || []),
|
|
points: $win.Array.from(shape.points),
|
|
frame: shape.frame,
|
|
occluded: shape.occluded || false,
|
|
outside: shape.outside || false,
|
|
rotation: shape.rotation || 0,
|
|
type: shape.type,
|
|
z_order: shape.zOrder || 0,
|
|
})),
|
|
});
|
|
|
|
cy.window().then(async ($win) => {
|
|
const job = (await $win.cvat.jobs.get({ jobID }))[0];
|
|
await job.annotations.clear({ reload: true });
|
|
|
|
const shapes = objects.filter((object) => object.objectType === 'shape').map(convertShape($win, job));
|
|
const tracks = objects.filter((object) => object.objectType === 'track').map(convertTrack($win, job));
|
|
const tags = objects.filter((object) => object.objectType === 'tag').map(convertTag($win, job));
|
|
|
|
await job.annotations.import({
|
|
shapes: $win.Array.from(shapes),
|
|
tracks: $win.Array.from(tracks),
|
|
tags: $win.Array.from(tags),
|
|
});
|
|
|
|
await job.annotations.save();
|
|
return cy.wrap();
|
|
});
|
|
});
|
|
|
|
Cypress.Commands.add('headlessRestoreAllFrames', (jobID) => {
|
|
cy.intercept('PATCH', `/api/jobs/${jobID}/data/meta**`).as('patchMeta');
|
|
cy.window().then(async ($win) => {
|
|
await $win.cvat.server.request(`/api/jobs/${jobID}/data/meta`, {
|
|
method: 'PATCH',
|
|
data: { deleted_frames: [] },
|
|
});
|
|
});
|
|
cy.wait('@patchMeta');
|
|
});
|
|
|
|
Cypress.Commands.add('headlessCreateTask', (taskSpec, dataSpec, extras) => {
|
|
cy.window().then(async ($win) => {
|
|
const task = new $win.cvat.classes.Task({
|
|
...taskSpec,
|
|
...dataSpec,
|
|
});
|
|
|
|
if (dataSpec.server_files) {
|
|
task.serverFiles = dataSpec.server_files;
|
|
}
|
|
|
|
if (dataSpec.client_files) {
|
|
task.clientFiles = dataSpec.client_files;
|
|
}
|
|
|
|
if (dataSpec.remote_files) {
|
|
task.remoteFiles = dataSpec.remote_files;
|
|
}
|
|
|
|
const result = await task.save(extras || {});
|
|
return cy.wrap({ taskID: result.id, jobIDs: result.jobs.map((job) => job.id) });
|
|
});
|
|
});
|
|
|
|
Cypress.Commands.add('headlessCreateProject', (projectSpec) => {
|
|
cy.window().then(async ($win) => {
|
|
const project = new $win.cvat.classes.Project({
|
|
...projectSpec,
|
|
});
|
|
|
|
const result = await project.save();
|
|
return cy.wrap({ projectID: result.id });
|
|
});
|
|
});
|
|
|
|
Cypress.Commands.add('headlessDeleteProject', (projectID) => {
|
|
cy.window()
|
|
.then(($win) => cy.wrap($win.cvat.projects.get({ id: projectID })))
|
|
.then(([project]) => cy.wrap(project.delete()));
|
|
});
|
|
|
|
Cypress.Commands.add('headlessDeleteTask', (taskID) => {
|
|
cy.window().then(async ($win) => {
|
|
const [task] = await $win.cvat.tasks.get({ id: taskID });
|
|
await task.delete();
|
|
});
|
|
});
|
|
|
|
Cypress.Commands.add('headlessCreateUser', (userSpec) => {
|
|
cy.window().its('cvat', { timeout: 25000 }).should('not.be.undefined');
|
|
cy.intercept('POST', '/api/auth/register**', (req) => {
|
|
req.continue((response) => {
|
|
delete response.headers['set-cookie'];
|
|
expect(response.statusCode).to.eq(201);
|
|
expect(response.body.username).to.eq(userSpec.username);
|
|
expect(response.body.email).to.eq(userSpec.email);
|
|
});
|
|
}).as('registerRequest');
|
|
|
|
return cy.window().then((win) => (
|
|
win.cvat.server.register(
|
|
userSpec.username,
|
|
userSpec.firstName,
|
|
userSpec.lastName,
|
|
userSpec.email,
|
|
userSpec.password,
|
|
[],
|
|
)
|
|
));
|
|
});
|
|
|
|
Cypress.Commands.add('headlessLogout', () => {
|
|
// currently it is supposed that headlessLogout does not need core initialized to perform its logic
|
|
// this may be improved in the future, but now this behaviour is enough
|
|
cy.clearCookies();
|
|
});
|
|
|
|
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('headlessUpdateTask', (taskId, callback) => {
|
|
cy.window().then(async ($win) => (
|
|
cy.wrap($win.cvat.tasks.get({ id: taskId }))
|
|
.then(([task]) => {
|
|
callback(task);
|
|
return cy.wrap(task.save());
|
|
})
|
|
));
|
|
});
|
|
|
|
Cypress.Commands.add('headlessUpdateJob', (jobID, updateJobParameters) => {
|
|
cy.window().then(async ($win) => (
|
|
cy.wrap($win.cvat.jobs.get({ jobID }))
|
|
.then(([job]) => cy.wrap(job.save(updateJobParameters)))
|
|
));
|
|
});
|
|
|
|
Cypress.Commands.add('openTask', (taskName, projectSubsetFieldValue) => {
|
|
cy.contains('strong', new RegExp(`^${taskName}$`))
|
|
.parents('.cvat-tasks-list-item')
|
|
.contains('a', 'Open').click({ force: true });
|
|
cy.get('.cvat-spinner').should('not.exist');
|
|
cy.get('.cvat-task-details').should('exist');
|
|
if (projectSubsetFieldValue) {
|
|
cy.get('.cvat-project-subset-field').find('input').should('have.attr', 'value', projectSubsetFieldValue);
|
|
}
|
|
});
|
|
|
|
Cypress.Commands.add('openTaskById', (taskId) => {
|
|
cy.visit(`/tasks/${taskId}`);
|
|
cy.get('.cvat-spinner').should('not.exist');
|
|
cy.get('.cvat-task-details').should('exist').and('be.visible');
|
|
});
|
|
|
|
Cypress.Commands.add('saveJob', (method = 'PATCH', status = 200, as = 'saveJob') => {
|
|
cy.intercept(method, '/api/jobs/**').as(as);
|
|
cy.clickSaveAnnotationView();
|
|
cy.wait(`@${as}`).its('response.statusCode').should('equal', status);
|
|
});
|
|
|
|
Cypress.Commands.add('getJobIDFromIdx', (jobIdx) => {
|
|
const jobsKey = [];
|
|
cy.document().then((doc) => {
|
|
const jobs = Array.from(doc.querySelectorAll('.cvat-job-item'));
|
|
for (let i = 0; i < jobs.length; i++) {
|
|
jobsKey.push(+jobs[i].getAttribute('data-row-id'));
|
|
}
|
|
const minKey = Math.min(...jobsKey);
|
|
return minKey + jobIdx;
|
|
});
|
|
});
|
|
|
|
Cypress.Commands.add('openJobFromJobsPage', (jobID) => {
|
|
cy.get('.cvat-header-jobs-button').click();
|
|
cy.get('.cvat-jobs-page').should('exist').and('be.visible');
|
|
cy.get('.cvat-job-page-list-item-id').contains(`ID: ${jobID}`)
|
|
.prev()
|
|
.should('not.have.class', 'cvat-job-item-loading-preview')
|
|
.click();
|
|
cy.get('.cvat-canvas-container').should('exist').and('be.visible');
|
|
});
|
|
|
|
Cypress.Commands.add('openJob', (jobIdx = 0, removeAnnotations = true, expectedFail = false) => {
|
|
cy.get('.cvat-task-job-list').should('exist');
|
|
cy.getJobIDFromIdx(jobIdx).then((jobID) => {
|
|
cy.get('.cvat-job-item').contains('a', `Job #${jobID}`).click();
|
|
});
|
|
cy.url().should('include', '/jobs');
|
|
if (expectedFail) {
|
|
cy.get('.cvat-canvas-container').should('not.exist');
|
|
} else {
|
|
cy.get('.cvat-canvas-container').should('exist').and('be.visible');
|
|
}
|
|
if (removeAnnotations) {
|
|
cy.document().then((doc) => {
|
|
const objects = Array.from(doc.querySelectorAll('.cvat_canvas_shape'));
|
|
if (typeof objects !== 'undefined' && objects.length > 0) {
|
|
cy.removeAnnotations();
|
|
cy.saveJob('PUT');
|
|
}
|
|
});
|
|
}
|
|
});
|
|
|
|
Cypress.Commands.add('pressSplitControl', () => {
|
|
cy.document().then((doc) => {
|
|
const [el] = doc.getElementsByClassName('cvat-extra-controls-control');
|
|
if (el) {
|
|
cy.get('.cvat-extra-controls-control').click();
|
|
}
|
|
|
|
cy.get('.cvat-split-track-control').click();
|
|
|
|
if (el) {
|
|
cy.get('body').click();
|
|
}
|
|
});
|
|
});
|
|
|
|
Cypress.Commands.add('openTaskJob', (taskName, jobID = 0, removeAnnotations = true, expectedFail = false) => {
|
|
cy.openTask(taskName);
|
|
cy.openJob(jobID, removeAnnotations, expectedFail);
|
|
});
|
|
|
|
Cypress.Commands.add('interactControlButton', (objectType) => {
|
|
cy.get('body').trigger('mousedown');
|
|
cy.get(`.cvat-${objectType}-control`).click();
|
|
cy.get(`.cvat-${objectType}-popover`)
|
|
.should('be.visible')
|
|
.should('have.attr', 'style')
|
|
.should('not.include', 'pointer-events: none');
|
|
});
|
|
|
|
Cypress.Commands.add('createRectangle', (createRectangleParams) => {
|
|
cy.interactControlButton('draw-rectangle');
|
|
cy.switchLabel(createRectangleParams.labelName, 'draw-rectangle');
|
|
cy.get('.cvat-draw-rectangle-popover').within(() => {
|
|
cy.get('.ant-select-selection-item').then(($labelValue) => {
|
|
selectedValueGlobal = $labelValue.text();
|
|
});
|
|
cy.contains('.ant-radio-wrapper', createRectangleParams.points).click();
|
|
cy.contains('button', createRectangleParams.type).click();
|
|
});
|
|
cy.get('.cvat-canvas-container').click(createRectangleParams.firstX, createRectangleParams.firstY);
|
|
cy.get('.cvat-canvas-container').click(createRectangleParams.secondX, createRectangleParams.secondY);
|
|
if (createRectangleParams.points === 'By 4 Points') {
|
|
cy.get('.cvat-canvas-container')
|
|
.click(createRectangleParams.thirdX, createRectangleParams.thirdY);
|
|
cy.get('.cvat-canvas-container')
|
|
.click(createRectangleParams.fourthX, createRectangleParams.fourthY);
|
|
}
|
|
cy.checkPopoverHidden('draw-rectangle');
|
|
cy.checkObjectParameters(createRectangleParams, 'RECTANGLE');
|
|
});
|
|
|
|
Cypress.Commands.add('switchLabel', (labelName, objectType) => {
|
|
cy.get(`.cvat-${objectType}-popover`).find('.ant-select-selection-item').click();
|
|
cy.get('.ant-select-dropdown')
|
|
.not('.ant-select-dropdown-hidden')
|
|
.find(`.ant-select-item-option[title="${labelName}"]`)
|
|
.click();
|
|
});
|
|
|
|
Cypress.Commands.add('checkPopoverHidden', (objectType) => {
|
|
cy.get(`.cvat-${objectType}-popover`).should('be.hidden');
|
|
});
|
|
|
|
Cypress.Commands.add('checkObjectParameters', (objectParameters, objectType) => {
|
|
const listCanvasShapeId = [];
|
|
cy.document().then((doc) => {
|
|
const listCanvasShape = Array.from(doc.querySelectorAll('.cvat_canvas_shape'));
|
|
for (let i = 0; i < listCanvasShape.length; i++) {
|
|
listCanvasShapeId.push(listCanvasShape[i].id.match(/\d+$/));
|
|
}
|
|
const maxId = Math.max(...listCanvasShapeId);
|
|
cy.get(`#cvat_canvas_shape_${maxId}`).should('be.visible');
|
|
cy.get(`#cvat-objects-sidebar-state-item-${maxId}`)
|
|
.should('contain', maxId)
|
|
.and('contain', `${objectType} ${objectParameters.type.toUpperCase()}`)
|
|
.within(() => {
|
|
cy.get('.ant-select-selection-item').should('have.text', selectedValueGlobal);
|
|
});
|
|
});
|
|
});
|
|
|
|
Cypress.Commands.add('createPoint', (createPointParams) => {
|
|
cy.interactControlButton('draw-points');
|
|
cy.switchLabel(createPointParams.labelName, 'draw-points');
|
|
cy.get('.cvat-draw-points-popover').within(() => {
|
|
cy.get('.ant-select-selection-item').then(($labelValue) => {
|
|
selectedValueGlobal = $labelValue.text();
|
|
});
|
|
if (createPointParams.numberOfPoints) {
|
|
cy.get('.ant-input-number-input').clear();
|
|
cy.get('.ant-input-number-input').type(createPointParams.numberOfPoints);
|
|
}
|
|
cy.contains('button', createPointParams.type).click();
|
|
});
|
|
createPointParams.pointsMap.forEach((element) => {
|
|
cy.get('.cvat-canvas-container').click(element.x, element.y);
|
|
});
|
|
if (createPointParams.finishWithButton) {
|
|
cy.contains('span', 'Done').click();
|
|
} else if (!createPointParams.numberOfPoints) {
|
|
const keyCodeN = 78;
|
|
cy.get('.cvat-canvas-container')
|
|
.trigger('keydown', { keyCode: keyCodeN, code: 'KeyN' });
|
|
cy.get('.cvat-canvas-container')
|
|
.trigger('keyup', { keyCode: keyCodeN, code: 'KeyN' });
|
|
}
|
|
cy.checkPopoverHidden('draw-points');
|
|
cy.checkObjectParameters(createPointParams, 'POINTS');
|
|
});
|
|
|
|
Cypress.Commands.add('createEllipse', (createEllipseParams) => {
|
|
cy.interactControlButton('draw-ellipse');
|
|
cy.switchLabel(createEllipseParams.labelName, 'draw-ellipse');
|
|
cy.get('.cvat-draw-ellipse-popover').within(() => {
|
|
cy.get('.ant-select-selection-item').then(($labelValue) => {
|
|
selectedValueGlobal = $labelValue.text();
|
|
});
|
|
cy.contains('button', createEllipseParams.type).click();
|
|
});
|
|
cy.get('.cvat-canvas-container')
|
|
.click(createEllipseParams.firstX, createEllipseParams.firstY);
|
|
cy.get('.cvat-canvas-container')
|
|
.click(createEllipseParams.secondX, createEllipseParams.secondY);
|
|
cy.checkPopoverHidden('draw-ellipse');
|
|
cy.checkObjectParameters(createEllipseParams, 'ELLIPSE');
|
|
});
|
|
|
|
Cypress.Commands.add('createSkeleton', (skeletonParameters) => {
|
|
cy.interactControlButton('draw-skeleton');
|
|
cy.switchLabel(skeletonParameters.labelName, 'draw-skeleton');
|
|
cy.get('.cvat-draw-skeleton-popover').within(() => {
|
|
cy.get('.ant-select-selection-item').then(($labelValue) => {
|
|
selectedValueGlobal = $labelValue.text();
|
|
});
|
|
cy.contains('button', skeletonParameters.type).click();
|
|
});
|
|
cy.get('.cvat-canvas-container')
|
|
.click(skeletonParameters.xtl, skeletonParameters.ytl);
|
|
cy.get('.cvat-canvas-container')
|
|
.click(skeletonParameters.xbr, skeletonParameters.ybr);
|
|
cy.checkPopoverHidden('draw-skeleton');
|
|
cy.checkObjectParameters(skeletonParameters, 'SKELETON');
|
|
});
|
|
|
|
Cypress.Commands.add('changeAppearance', (colorBy) => {
|
|
cy.get('.cvat-appearance-color-by-radio-group').within(() => {
|
|
cy.get('[type="radio"]').check(colorBy, { force: true });
|
|
});
|
|
});
|
|
|
|
Cypress.Commands.add('shapeGrouping', (firstX, firstY, lastX, lastY) => {
|
|
const keyCodeG = 71;
|
|
cy.get('.cvat-canvas-container')
|
|
.trigger('keydown', { keyCode: keyCodeG, code: 'KeyG' });
|
|
cy.get('.cvat-canvas-container')
|
|
.trigger('keyup', { keyCode: keyCodeG, code: 'KeyG' });
|
|
cy.get('.cvat-canvas-container')
|
|
.trigger('mousedown', firstX, firstY, { which: 1 });
|
|
cy.get('.cvat-canvas-container')
|
|
.trigger('mousemove', lastX, lastY);
|
|
cy.get('.cvat-canvas-container')
|
|
.trigger('mouseup', lastX, lastY);
|
|
cy.get('.cvat-canvas-container')
|
|
.trigger('keydown', { keyCode: keyCodeG, code: 'KeyG' });
|
|
cy.get('.cvat-canvas-container')
|
|
.trigger('keyup', { keyCode: keyCodeG, code: 'KeyG' });
|
|
});
|
|
|
|
Cypress.Commands.add('createPolygon', (createPolygonParams) => {
|
|
if (!createPolygonParams.reDraw) {
|
|
cy.interactControlButton('draw-polygon');
|
|
cy.switchLabel(createPolygonParams.labelName, 'draw-polygon');
|
|
cy.get('.cvat-draw-polygon-popover').within(() => {
|
|
cy.get('.ant-select-selection-item').then(($labelValue) => {
|
|
selectedValueGlobal = $labelValue.text();
|
|
});
|
|
if (createPolygonParams.numberOfPoints) {
|
|
cy.get('.ant-input-number-input').clear();
|
|
cy.get('.ant-input-number-input').type(createPolygonParams.numberOfPoints);
|
|
}
|
|
cy.contains('button', createPolygonParams.type).click();
|
|
});
|
|
}
|
|
createPolygonParams.pointsMap.forEach((element) => {
|
|
cy.get('.cvat-canvas-container').click(element.x, element.y);
|
|
});
|
|
if (createPolygonParams.finishWithButton) {
|
|
cy.contains('span', 'Done').click();
|
|
} else if (!createPolygonParams.numberOfPoints) {
|
|
const keyCodeN = 78;
|
|
cy.get('.cvat-canvas-container')
|
|
.trigger('keydown', { keyCode: keyCodeN, code: 'KeyN' });
|
|
cy.get('.cvat-canvas-container')
|
|
.trigger('keyup', { keyCode: keyCodeN, code: 'KeyN' });
|
|
}
|
|
cy.checkPopoverHidden('draw-polygon');
|
|
cy.checkObjectParameters(createPolygonParams, 'POLYGON');
|
|
});
|
|
|
|
Cypress.Commands.add('openSettings', () => {
|
|
cy.get('.cvat-header-menu-user-dropdown').click();
|
|
cy.get('.cvat-header-menu')
|
|
.should('exist')
|
|
.and('be.visible')
|
|
.find('[role="menuitem"]')
|
|
.filter(':contains("Settings")')
|
|
.click();
|
|
cy.get('.cvat-settings-modal').should('be.visible');
|
|
});
|
|
|
|
Cypress.Commands.add('closeSettings', () => {
|
|
cy.get('.cvat-settings-modal').within(() => {
|
|
cy.contains('button', 'Close').click();
|
|
});
|
|
cy.get('.cvat-settings-modal').should('not.be.visible');
|
|
});
|
|
|
|
Cypress.Commands.add('changeWorkspace', (mode) => {
|
|
cy.get('.cvat-workspace-selector').click();
|
|
cy.get('.cvat-workspace-selector-dropdown').within(() => {
|
|
cy.get(`.ant-select-item-option[title="${mode}"]`).click();
|
|
});
|
|
|
|
cy.get('.cvat-workspace-selector').should('contain.text', mode);
|
|
});
|
|
|
|
Cypress.Commands.add('changeLabelAAM', (labelName) => {
|
|
cy.get('.cvat-workspace-selector').then((value) => {
|
|
const cvatWorkspaceSelectorValue = value.text();
|
|
if (cvatWorkspaceSelectorValue.includes('Attribute annotation')) {
|
|
cy.get('.cvat-attribute-annotation-sidebar-basics-editor').within(() => {
|
|
cy.get('.ant-select-selector').click();
|
|
});
|
|
cy.get('.ant-select-dropdown')
|
|
.not('.ant-select-dropdown-hidden')
|
|
.first()
|
|
.within(() => {
|
|
cy.get(`.ant-select-item-option[title="${labelName}"]`).click();
|
|
});
|
|
}
|
|
});
|
|
});
|
|
|
|
Cypress.Commands.add('createCuboid', (createCuboidParams) => {
|
|
cy.interactControlButton('draw-cuboid');
|
|
cy.switchLabel(createCuboidParams.labelName, 'draw-cuboid');
|
|
cy.get('.cvat-draw-cuboid-popover').within(() => {
|
|
cy.get('.ant-select-selection-item').then(($labelValue) => {
|
|
selectedValueGlobal = $labelValue.text();
|
|
});
|
|
cy.contains(createCuboidParams.points).click();
|
|
cy.contains('button', createCuboidParams.type).click();
|
|
});
|
|
cy.get('.cvat-canvas-container').click(createCuboidParams.firstX, createCuboidParams.firstY);
|
|
cy.get('.cvat-canvas-container').click(createCuboidParams.secondX, createCuboidParams.secondY);
|
|
if (createCuboidParams.points === 'By 4 Points') {
|
|
cy.get('.cvat-canvas-container').click(createCuboidParams.thirdX, createCuboidParams.thirdY);
|
|
cy.get('.cvat-canvas-container').click(createCuboidParams.fourthX, createCuboidParams.fourthY);
|
|
}
|
|
cy.checkPopoverHidden('draw-cuboid');
|
|
cy.checkObjectParameters(createCuboidParams, 'CUBOID');
|
|
});
|
|
|
|
Cypress.Commands.add('updateAttributes', (attributes) => {
|
|
const cvatAttributeInputsWrapperId = [];
|
|
cy.get('.cvat-new-attribute-button').click();
|
|
cy.document().then((doc) => {
|
|
const cvatAttributeInputsWrapperList = Array.from(doc.querySelectorAll('.cvat-attribute-inputs-wrapper'));
|
|
for (let i = 0; i < cvatAttributeInputsWrapperList.length; i++) {
|
|
cvatAttributeInputsWrapperId.push(cvatAttributeInputsWrapperList[i].getAttribute('cvat-attribute-id'));
|
|
}
|
|
|
|
const minId = Math.min(...cvatAttributeInputsWrapperId);
|
|
|
|
cy.get(`[cvat-attribute-id="${minId}"]`).within(() => {
|
|
cy.get('.cvat-attribute-name-input').type(attributes.name);
|
|
cy.get('.cvat-attribute-type-input').click();
|
|
});
|
|
cy.get('.ant-select-dropdown:has(.cvat-attribute-type-input-select)')
|
|
.not('.ant-select-dropdown-hidden')
|
|
.should('exist').and('be.visible')
|
|
.first()
|
|
.within(() => {
|
|
cy.get(`.cvat-attribute-type-input-${attributes.type.toLowerCase()}`).click();
|
|
});
|
|
|
|
if (['Number', 'Text'].includes(attributes.type)) {
|
|
cy.get(`[cvat-attribute-id="${minId}"]`).within(() => {
|
|
if (attributes.values !== '') {
|
|
cy.get('.cvat-attribute-values-input').type(attributes.values);
|
|
} else {
|
|
cy.get('.cvat-attribute-values-input').clear();
|
|
}
|
|
});
|
|
} else if (['Radio', 'Select'].includes(attributes.type)) {
|
|
cy.get(`[cvat-attribute-id="${minId}"]`).within(() => {
|
|
cy.get('.cvat-attribute-values-input').type(`${attributes.values}{Enter}`);
|
|
|
|
if (attributes.defaultValue) {
|
|
cy.get('.cvat-attribute-values-input').within(() => {
|
|
cy.get('.ant-tag').contains(attributes.defaultValue).click({ force: true });
|
|
cy.get('.ant-tag').should('have.class', 'ant-tag-blue');
|
|
});
|
|
}
|
|
});
|
|
} else if (attributes.type === 'Checkbox') {
|
|
cy.get(`[cvat-attribute-id="${minId}"]`).within(() => {
|
|
cy.get('.cvat-attribute-values-input').click();
|
|
});
|
|
cy.get('.ant-select-dropdown')
|
|
.not('.ant-select-dropdown-hidden')
|
|
.first()
|
|
.within(() => {
|
|
cy.get(`.ant-select-item-option[title="${attributes.values}"]`).click();
|
|
});
|
|
}
|
|
if (attributes.mutable) {
|
|
cy.get('.cvat-attribute-mutable-checkbox')
|
|
.find('[type="checkbox"]')
|
|
.should('not.be.checked')
|
|
.check();
|
|
cy.get('.cvat-attribute-mutable-checkbox')
|
|
.find('[type="checkbox"]')
|
|
.should('be.checked');
|
|
}
|
|
});
|
|
});
|
|
|
|
Cypress.Commands.add('createPolyline', (createPolylineParams) => {
|
|
cy.interactControlButton('draw-polyline');
|
|
cy.switchLabel(createPolylineParams.labelName, 'draw-polyline');
|
|
cy.get('.cvat-draw-polyline-popover').within(() => {
|
|
cy.get('.ant-select-selection-item').then(($labelValue) => {
|
|
selectedValueGlobal = $labelValue.text();
|
|
});
|
|
if (createPolylineParams.numberOfPoints) {
|
|
cy.get('.ant-input-number-input').clear();
|
|
cy.get('.ant-input-number-input').type(createPolylineParams.numberOfPoints);
|
|
}
|
|
cy.contains('button', createPolylineParams.type).click();
|
|
});
|
|
createPolylineParams.pointsMap.forEach((element) => {
|
|
cy.get('.cvat-canvas-container').click(element.x, element.y);
|
|
});
|
|
if (createPolylineParams.finishWithButton) {
|
|
cy.contains('span', 'Done').click();
|
|
} else if (!createPolylineParams.numberOfPoints) {
|
|
const keyCodeN = 78;
|
|
cy.get('.cvat-canvas-container')
|
|
.trigger('keydown', { keyCode: keyCodeN, code: 'KeyN' });
|
|
cy.get('.cvat-canvas-container')
|
|
.trigger('keyup', { keyCode: keyCodeN, code: 'KeyN' });
|
|
}
|
|
cy.checkPopoverHidden('draw-polyline');
|
|
cy.checkObjectParameters(createPolylineParams, 'POLYLINE');
|
|
});
|
|
|
|
Cypress.Commands.add('openTaskMenu', (taskName, fromTaskPage) => {
|
|
if (fromTaskPage) {
|
|
cy.contains('.cvat-text-color', 'Actions').click();
|
|
} else {
|
|
cy.contains('strong', taskName).parents('.cvat-tasks-list-item').find('.cvat-menu-icon').click();
|
|
}
|
|
});
|
|
|
|
Cypress.Commands.add('clickInTaskMenu', (item, fromTaskPage, taskName = '') => {
|
|
cy.openTaskMenu(taskName, fromTaskPage);
|
|
cy.get('.ant-dropdown').not('.ant-dropdown-hidden').within(() => {
|
|
cy.get('.cvat-actions-menu')
|
|
.should('be.visible')
|
|
.find('[role="menuitem"]')
|
|
.filter(`:contains("${item}")`)
|
|
.last()
|
|
.click();
|
|
});
|
|
});
|
|
|
|
Cypress.Commands.add('deleteTask', (taskName) => {
|
|
let taskId = '';
|
|
cy.contains('.cvat-item-task-name', new RegExp(`^${taskName}$`))
|
|
.parents('.cvat-task-item-description')
|
|
.find('.cvat-item-task-id')
|
|
.then(($taskId) => {
|
|
taskId = $taskId.text().replace(/[^\d]/g, '');
|
|
cy.clickInTaskMenu('Delete', false, taskName);
|
|
cy.get('.cvat-modal-confirm-delete-task')
|
|
.should('contain', `The task ${taskId} will be deleted`)
|
|
.within(() => {
|
|
cy.contains('button', 'Delete').click();
|
|
});
|
|
});
|
|
cy.contains('.cvat-item-task-name', new RegExp(`^${taskName}$`))
|
|
.parents('.cvat-tasks-list-item')
|
|
.should('have.attr', 'style')
|
|
.and('contain', 'pointer-events: none; opacity: 0.5;');
|
|
});
|
|
|
|
Cypress.Commands.add('advancedConfiguration', (advancedConfigurationParams) => {
|
|
cy.contains('Advanced configuration').click();
|
|
if (advancedConfigurationParams.multiJobs) {
|
|
cy.get('#segmentSize').type(advancedConfigurationParams.segmentSize);
|
|
}
|
|
if (advancedConfigurationParams.sssFrame) {
|
|
cy.get('#startFrame').type(advancedConfigurationParams.startFrame);
|
|
cy.get('#stopFrame').type(advancedConfigurationParams.stopFrame);
|
|
cy.get('#frameStep').type(advancedConfigurationParams.frameStep);
|
|
}
|
|
if (advancedConfigurationParams.chunkSize) {
|
|
cy.get('#dataChunkSize').type(advancedConfigurationParams.chunkSize);
|
|
}
|
|
if (advancedConfigurationParams.consensusReplicas) {
|
|
cy.get('#consensusReplicas').type(advancedConfigurationParams.consensusReplicas);
|
|
}
|
|
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('configureTaskQualityMode', (qualityConfigurationParams) => {
|
|
cy.contains('Quality').click();
|
|
if (qualityConfigurationParams.validationMode) {
|
|
cy.get('#validationMode').within(() => {
|
|
cy.contains(qualityConfigurationParams.validationMode).click();
|
|
});
|
|
}
|
|
if (qualityConfigurationParams.validationFramesPercent) {
|
|
cy.get('#validationFramesPercent').clear();
|
|
cy.get('#validationFramesPercent').type(qualityConfigurationParams.validationFramesPercent);
|
|
}
|
|
if (qualityConfigurationParams.validationFramesPerJobPercent) {
|
|
cy.get('#validationFramesPerJobPercent').clear();
|
|
cy.get('#validationFramesPerJobPercent').type(qualityConfigurationParams.validationFramesPerJobPercent);
|
|
}
|
|
});
|
|
|
|
Cypress.Commands.add('removeAnnotations', () => {
|
|
cy.contains('.cvat-annotation-header-button', 'Menu').click();
|
|
cy.get('.cvat-annotation-menu').within(() => {
|
|
cy.contains('Remove annotations').click();
|
|
});
|
|
cy.get('.cvat-modal-confirm-remove-annotation').within(() => {
|
|
cy.contains('button', 'Delete').click();
|
|
});
|
|
});
|
|
|
|
Cypress.Commands.add('confirmUpdate', (modalWindowClassName) => {
|
|
cy.get(modalWindowClassName).should('be.visible').within(() => {
|
|
cy.contains('button', 'Update').click();
|
|
});
|
|
});
|
|
|
|
Cypress.Commands.add(
|
|
'uploadAnnotations', ({
|
|
format, filePath, confirmModalClassName,
|
|
sourceStorage = null, useDefaultLocation = true, waitAnnotationsGet = true,
|
|
expectedResult = 'success',
|
|
},
|
|
) => {
|
|
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(filePath);
|
|
} else {
|
|
cy.get('input[type="file"]').attachFile(filePath, { subjectType: 'drag-n-drop' });
|
|
cy.get(`[title="${filePath.split('/').pop()}"]`).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');
|
|
if (waitAnnotationsGet) {
|
|
cy.wait('@uploadAnnotationsGet').its('response.statusCode').should('equal', 200);
|
|
}
|
|
if (expectedResult === 'success') {
|
|
cy.contains('Annotations have been loaded').should('be.visible');
|
|
cy.closeNotification('.ant-notification-notice-info');
|
|
} else if (expectedResult === 'fail') {
|
|
cy.contains('Could not upload annotation').should('be.visible');
|
|
cy.closeNotification('.ant-notification-notice-error');
|
|
}
|
|
},
|
|
);
|
|
|
|
Cypress.Commands.add('goToTaskList', () => {
|
|
cy.get('a[value="tasks"]').click();
|
|
cy.url().should('include', '/tasks');
|
|
});
|
|
|
|
Cypress.Commands.add('changeColorViaBadge', (labelColor) => {
|
|
cy.get('.cvat-label-color-picker')
|
|
.not('.ant-popover-hidden')
|
|
.should('be.visible')
|
|
.first()
|
|
.within(() => {
|
|
cy.contains('hex').prev().clear();
|
|
cy.contains('hex').prev().type(labelColor);
|
|
cy.contains('button', 'Ok').click();
|
|
});
|
|
});
|
|
|
|
Cypress.Commands.add('collectLabelsName', () => {
|
|
const listCvatConstructorViewerItemText = [];
|
|
cy.get('.cvat-constructor-viewer').should('exist');
|
|
cy.document().then((doc) => {
|
|
const labels = Array.from(doc.querySelectorAll('.cvat-constructor-viewer-item'));
|
|
for (let i = 0; i < labels.length; i++) {
|
|
listCvatConstructorViewerItemText.push(labels[i].textContent);
|
|
}
|
|
return listCvatConstructorViewerItemText;
|
|
});
|
|
});
|
|
|
|
Cypress.Commands.add('deleteLabel', (labelName) => {
|
|
cy.contains('.cvat-constructor-viewer-item', new RegExp(`^${labelName}$`))
|
|
.should('exist')
|
|
.and('be.visible')
|
|
.find('[aria-label="delete"]')
|
|
.click();
|
|
cy.intercept('DELETE', '/api/labels/*').as('deleteLabel');
|
|
cy.get('.cvat-modal-delete-label')
|
|
.should('be.visible')
|
|
.first()
|
|
.within(() => {
|
|
cy.contains('[type="button"]', 'OK').click();
|
|
});
|
|
cy.wait('@deleteLabel').its('response.statusCode').should('equal', 204);
|
|
cy.contains('.cvat-constructor-viewer-item', new RegExp(`^${labelName}$`)).should('not.exist');
|
|
});
|
|
|
|
Cypress.Commands.add('addNewLabel', ({ name, color }, additionalAttrs) => {
|
|
cy.collectLabelsName().then((labelsNames) => {
|
|
if (labelsNames.includes(name)) {
|
|
cy.deleteLabel(name);
|
|
}
|
|
});
|
|
cy.contains('button', 'Add label').click();
|
|
cy.get('[placeholder="Label name"]').type(name);
|
|
if (color) {
|
|
cy.get('.cvat-change-task-label-color-badge').click();
|
|
cy.changeColorViaBadge(color);
|
|
cy.get('.cvat-label-color-picker').should('be.hidden');
|
|
}
|
|
if (additionalAttrs) {
|
|
for (let i = 0; i < additionalAttrs.length; i++) {
|
|
cy.updateAttributes(additionalAttrs[i]);
|
|
}
|
|
}
|
|
cy.contains('button', 'Continue').click();
|
|
cy.contains('button', 'Cancel').click();
|
|
cy.get('.cvat-spinner').should('not.exist');
|
|
cy.get('.cvat-constructor-viewer').should('be.visible');
|
|
cy.contains('.cvat-constructor-viewer-item', new RegExp(`^${name}$`)).should('exist');
|
|
});
|
|
|
|
Cypress.Commands.add('addNewSkeletonLabel', ({ name, points }) => {
|
|
cy.get('.cvat-constructor-viewer-new-skeleton-item').click();
|
|
cy.get('.cvat-skeleton-configurator').should('exist').and('be.visible');
|
|
|
|
cy.get('.cvat-label-constructor-creator').within(() => {
|
|
cy.get('#name').type(name);
|
|
cy.get('.ant-radio-button-checked').within(() => {
|
|
cy.get('.ant-radio-button-input').should('have.attr', 'value', 'point');
|
|
});
|
|
});
|
|
|
|
cy.get('.cvat-skeleton-configurator-svg').then(($canvas) => {
|
|
const canvas = $canvas[0];
|
|
canvas.scrollIntoView();
|
|
const rect = canvas.getBoundingClientRect();
|
|
const { width, height } = rect;
|
|
points.forEach(({ x: xOffset, y: yOffset }) => {
|
|
canvas.dispatchEvent(new MouseEvent('mousedown', {
|
|
clientX: rect.x + width * xOffset,
|
|
clientY: rect.y + height * yOffset,
|
|
button: 0,
|
|
bubbles: true,
|
|
}));
|
|
});
|
|
|
|
cy.get('.ant-radio-button-wrapper:nth-child(3)').click();
|
|
cy.get('.ant-radio-button-wrapper:nth-child(3)').within(() => {
|
|
cy.get('.ant-radio-button-input').should('have.attr', 'value', 'join');
|
|
});
|
|
|
|
cy.get('.cvat-skeleton-configurator-svg').within(() => {
|
|
cy.get('circle').then(($circles) => {
|
|
expect($circles.length).to.be.equal(5);
|
|
$circles.each(function (i) {
|
|
const circle1 = this;
|
|
$circles.each(function (j) {
|
|
const circle2 = this;
|
|
if (i === j) return;
|
|
circle1.dispatchEvent(new MouseEvent('mouseover', { bubbles: true }));
|
|
circle1.dispatchEvent(new MouseEvent('click', { button: 0, bubbles: true }));
|
|
circle1.dispatchEvent(new MouseEvent('mouseout', { bubbles: true }));
|
|
|
|
circle2.dispatchEvent(new MouseEvent('mouseover', { bubbles: true }));
|
|
circle2.dispatchEvent(new MouseEvent('click', { button: 0, bubbles: true }));
|
|
circle2.dispatchEvent(new MouseEvent('mouseout', { bubbles: true }));
|
|
});
|
|
});
|
|
});
|
|
});
|
|
|
|
cy.contains('Continue').scrollIntoView();
|
|
cy.contains('Continue').click();
|
|
cy.contains('Cancel').click();
|
|
});
|
|
});
|
|
|
|
Cypress.Commands.add('checkCanvasSidebarColorEqualness', (id) => {
|
|
cy.get(`#cvat-objects-sidebar-state-item-${id}`).then(($el) => {
|
|
const labelColor = $el.css('backgroundColor');
|
|
const [r, g, b] = labelColor.match(/(\d+)/g);
|
|
const hexColor = `#${[r, g, b].map((v) => (+v).toString(16).padStart(2, '0')).join('')}`;
|
|
cy.get(`#cvat_canvas_shape_${id}`).should('have.attr', 'fill', hexColor);
|
|
});
|
|
});
|
|
|
|
Cypress.Commands.add('addNewLabelViaContinueButton', (additionalLabels) => {
|
|
cy.collectLabelsName().then((labelsNames) => {
|
|
if (additionalLabels.some((el) => labelsNames.indexOf(el) === -1)) {
|
|
cy.get('.cvat-constructor-viewer-new-item').click();
|
|
for (let j = 0; j < additionalLabels.length; j++) {
|
|
cy.get('[placeholder="Label name"]').type(additionalLabels[j]);
|
|
cy.contains('button', 'Continue').click();
|
|
cy.contains('button', 'Continue').trigger('mouseout');
|
|
}
|
|
cy.contains('button', 'Cancel').click();
|
|
}
|
|
});
|
|
});
|
|
|
|
Cypress.Commands.add('createTag', (labelName) => {
|
|
cy.interactControlButton('setup-tag');
|
|
cy.switchLabel(labelName, 'setup-tag');
|
|
cy.get('.cvat-setup-tag-popover').within(() => {
|
|
cy.get('button').click();
|
|
});
|
|
});
|
|
|
|
Cypress.Commands.add('sidebarItemSortBy', (sortBy) => {
|
|
cy.get('.cvat-objects-sidebar-ordering-selector').click();
|
|
cy.get('.cvat-objects-sidebar-ordering-dropdown').within(() => {
|
|
cy.get(`.ant-select-item-option[title="${sortBy}"]`).click();
|
|
});
|
|
});
|
|
|
|
Cypress.Commands.add('goToRegisterPage', () => {
|
|
cy.get('a[href="/auth/register"]').click();
|
|
cy.url().should('include', '/auth/register');
|
|
});
|
|
|
|
Cypress.Commands.add('getScaleValue', () => {
|
|
cy.get('#cvat_canvas_background')
|
|
.should('have.attr', 'style')
|
|
.then(($styles) => (Number($styles.match(/scale\((\d\.\d+)\)/m)[1])));
|
|
});
|
|
|
|
Cypress.Commands.add('goCheckFrameNumber', (frameNum) => {
|
|
cy.get('.cvat-player-frame-selector').within(() => {
|
|
cy.get('input[role="spinbutton"]').clear({ force: true });
|
|
cy.get('input[role="spinbutton"]').type(`${frameNum}{Enter}`, { force: true });
|
|
cy.get('input[role="spinbutton"]').should('have.value', frameNum);
|
|
});
|
|
});
|
|
|
|
Cypress.Commands.add('checkFrameNum', (frameNum) => {
|
|
cy.get('.cvat-player-frame-selector').within(() => {
|
|
cy.get('input[role="spinbutton"]').should('have.value', frameNum);
|
|
});
|
|
});
|
|
|
|
Cypress.Commands.add('goToNextFrame', (expectedFrameNum) => {
|
|
cy.get('.cvat-player-next-button').click();
|
|
cy.get('.cvat-player-next-button').trigger('mouseout');
|
|
cy.checkFrameNum(expectedFrameNum);
|
|
});
|
|
|
|
Cypress.Commands.add('goToPreviousFrame', (expectedFrameNum) => {
|
|
cy.get('.cvat-player-previous-button').click();
|
|
cy.get('.cvat-player-previous-button').trigger('mouseout');
|
|
cy.checkFrameNum(expectedFrameNum);
|
|
});
|
|
|
|
Cypress.Commands.add('interactMenu', (choice) => {
|
|
cy.contains('.cvat-annotation-header-button', 'Menu').click();
|
|
cy.get('.cvat-annotation-menu').within(() => {
|
|
cy.contains(new RegExp(`^${choice}$`)).click();
|
|
});
|
|
cy.get('.cvat-spinner').should('not.exist');
|
|
});
|
|
|
|
Cypress.Commands.add('updateJobStateOnAnnotationView', (choice) => {
|
|
cy.interactMenu('Change job state');
|
|
cy.get('.cvat-annotation-menu-job-state-submenu')
|
|
.should('not.have.class', 'ant-zoom-big').within(() => {
|
|
cy.contains(choice).click();
|
|
});
|
|
cy.get('.cvat-modal-content-change-job-state')
|
|
.should('be.visible')
|
|
.within(() => {
|
|
cy.contains('[type="button"]', 'Continue').click();
|
|
});
|
|
cy.get('.cvat-modal-content-change-job-state').should('not.exist');
|
|
cy.get('.cvat-spinner').should('not.exist');
|
|
});
|
|
|
|
Cypress.Commands.add('setJobState', (jobID, state) => {
|
|
cy.get('.cvat-task-job-list')
|
|
.contains('a', `Job #${jobID}`)
|
|
.parents('.cvat-job-item')
|
|
.find('.cvat-job-item-state').click();
|
|
cy.get('.cvat-job-item-state-dropdown')
|
|
.should('be.visible')
|
|
.not('.ant-select-dropdown-hidden')
|
|
.within(() => {
|
|
cy.get(`[title="${state}"]`).click();
|
|
});
|
|
cy.get('.cvat-spinner').should('not.exist');
|
|
});
|
|
|
|
Cypress.Commands.add('setJobStage', (jobID, stage) => {
|
|
cy.get('.cvat-task-job-list')
|
|
.contains('a', `Job #${jobID}`)
|
|
.parents('.cvat-job-item')
|
|
.find('.cvat-job-item-stage').click();
|
|
cy.get('.cvat-job-item-stage-dropdown')
|
|
.should('be.visible')
|
|
.not('.ant-select-dropdown-hidden')
|
|
.within(() => {
|
|
cy.get(`[title="${stage}"]`).click();
|
|
});
|
|
cy.get('.cvat-spinner').should('not.exist');
|
|
});
|
|
|
|
Cypress.Commands.add('closeNotification', (className, numOfNotifications = 1) => {
|
|
cy.get(className)
|
|
.should('have.length', numOfNotifications)
|
|
.find('span[aria-label="close"]')
|
|
.then(($elements) => {
|
|
// Click in reverse order to avoid re-render instability
|
|
for (let i = $elements.length - 1; i >= 0; i--) {
|
|
cy.wrap($elements[i]).click();
|
|
}
|
|
});
|
|
cy.get(className).should('not.exist');
|
|
});
|
|
|
|
Cypress.Commands.add('getObjectIdNumberByLabelName', (labelName) => {
|
|
cy.document().then((doc) => {
|
|
const stateItemLabelSelectorList = Array.from(
|
|
doc.querySelectorAll('.cvat-objects-sidebar-state-item-label-selector'),
|
|
);
|
|
for (let i = 0; i < stateItemLabelSelectorList.length; i++) {
|
|
if (stateItemLabelSelectorList[i].textContent === labelName) {
|
|
cy.get(stateItemLabelSelectorList[i])
|
|
.parents('.cvat-objects-sidebar-state-item')
|
|
.should('have.attr', 'id')
|
|
.then((id) => (Number(id.match(/\d+$/))));
|
|
}
|
|
}
|
|
});
|
|
});
|
|
|
|
Cypress.Commands.add('closeModalUnsupportedPlatform', () => {
|
|
if (Cypress.browser.family !== 'chromium' && !window.localStorage.getItem('platformNotiticationShown')) {
|
|
cy.get('.cvat-modal-unsupported-platform-warning').within(() => {
|
|
cy.contains('button', 'OK').click();
|
|
});
|
|
}
|
|
});
|
|
|
|
Cypress.Commands.add('exportTask', ({
|
|
type, format, archiveCustomName,
|
|
targetStorage = null, useDefaultLocation = true,
|
|
}) => {
|
|
cy.clickInTaskMenu('Export task dataset', true);
|
|
cy.get('.cvat-modal-export-task').should('be.visible').find('.cvat-modal-export-select').click();
|
|
cy.contains('.cvat-modal-export-option-item', format).should('be.visible').click();
|
|
cy.get('.cvat-modal-export-task').find('.cvat-modal-export-select').should('contain.text', format);
|
|
if (type === 'dataset') {
|
|
cy.get('.cvat-modal-export-task').find('.cvat-modal-export-save-images').should('not.be.checked').click();
|
|
}
|
|
if (archiveCustomName) {
|
|
cy.get('.cvat-modal-export-task').find('.cvat-modal-export-filename-input').type(archiveCustomName);
|
|
}
|
|
if (!useDefaultLocation) {
|
|
cy.get('.cvat-modal-export-task').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('.cvat-modal-export-task button', 'OK').click();
|
|
cy.get('.cvat-notification-notice-export-task-start').should('be.visible');
|
|
cy.closeNotification('.cvat-notification-notice-export-task-start');
|
|
});
|
|
|
|
Cypress.Commands.add('exportJob', ({
|
|
type, format, archiveCustomName,
|
|
targetStorage = null, useDefaultLocation = true, jobOnTaskPage = null,
|
|
}) => {
|
|
if (!jobOnTaskPage) {
|
|
cy.interactMenu('Export job dataset');
|
|
} else {
|
|
cy.get('.cvat-job-item').contains('a', `Job #${jobOnTaskPage}`)
|
|
.parents('.cvat-job-item')
|
|
.find('.cvat-job-item-more-button')
|
|
.click();
|
|
cy.contains('Export annotations').click();
|
|
}
|
|
cy.get('.cvat-modal-export-job').should('be.visible').find('.cvat-modal-export-select').click();
|
|
cy.get('.ant-select-dropdown')
|
|
.not('.ant-select-dropdown-hidden')
|
|
.not('.ant-slide-up')
|
|
.within(() => {
|
|
cy.contains('.cvat-modal-export-option-item', format).scrollIntoView();
|
|
});
|
|
cy.contains('.cvat-modal-export-option-item', format).should('be.visible').click();
|
|
cy.get('.cvat-modal-export-job').find('.cvat-modal-export-select').should('contain.text', format);
|
|
if (type === 'dataset') {
|
|
cy.get('.cvat-modal-export-job').find('.cvat-modal-export-save-images').should('not.be.checked').click();
|
|
}
|
|
if (archiveCustomName) {
|
|
cy.get('.cvat-modal-export-job').find('.cvat-modal-export-filename-input').type(archiveCustomName);
|
|
}
|
|
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.get('.cvat-modal-export-job').contains('button', 'OK').click();
|
|
cy.get('.cvat-notification-notice-export-job-start').should('be.visible');
|
|
cy.closeNotification('.cvat-notification-notice-export-job-start');
|
|
});
|
|
|
|
Cypress.Commands.add('downloadExport', ({ expectNotification = true } = {}) => {
|
|
if (expectNotification) {
|
|
cy.verifyNotification();
|
|
}
|
|
cy.get('.cvat-header-requests-button').click();
|
|
cy.get('.cvat-spinner').should('not.exist');
|
|
cy.get('.cvat-requests-list').should('be.visible');
|
|
cy.get('.cvat-requests-card').first().within(() => {
|
|
cy.get('.cvat-requests-page-actions-button').click();
|
|
});
|
|
cy.intercept('GET', '**/download?rq_id=*').as('download');
|
|
cy.get('.ant-dropdown')
|
|
.not('.ant-dropdown-hidden')
|
|
.within(() => {
|
|
cy.contains('[role="menuitem"]', 'Download').click();
|
|
});
|
|
cy.wait('@download', { requestTimeout: 10000 })
|
|
.then((download) => {
|
|
const filename = download.response.headers['content-disposition'].split(';')[1].split('filename=')[1];
|
|
// need to remove quotes
|
|
return filename.substring(1, filename.length - 1);
|
|
});
|
|
});
|
|
|
|
Cypress.Commands.add('goBack', () => {
|
|
cy.go('back');
|
|
cy.get('.cvat-spinner').should('not.exist');
|
|
});
|
|
|
|
Cypress.Commands.add('renameTask', (oldName, newName) => {
|
|
cy.get('.cvat-task-details-task-name').within(() => {
|
|
cy.get('[aria-label="edit"]').click();
|
|
});
|
|
cy.contains('.cvat-text-color', oldName).type(`{selectall}{backspace}${newName}{Enter}`);
|
|
cy.get('.cvat-spinner').should('not.exist');
|
|
cy.contains('.cvat-task-details-task-name', newName).should('exist');
|
|
});
|
|
|
|
Cypress.Commands.add('shapeRotate', (shape, expectedRotateDeg, pressShift = false) => {
|
|
cy.get(shape).trigger('mousemove');
|
|
cy.get(shape).trigger('mouseover');
|
|
cy.get(shape).should('have.class', 'cvat_canvas_shape_activated');
|
|
cy.get('.svg_select_points_rot').then(($el) => {
|
|
const rect = $el[0].getBoundingClientRect();
|
|
let { x, y } = rect;
|
|
const { width, height } = rect;
|
|
x += width / 2;
|
|
y += height / 2;
|
|
|
|
cy.get('#root').trigger('mousemove', x, y);
|
|
cy.get('#root').trigger('mouseenter', x, y);
|
|
cy.get('.svg_select_points_rot').should('have.class', 'cvat_canvas_selected_point');
|
|
cy.get('#root').trigger('mousedown', x, y, { button: 0 });
|
|
if (pressShift) {
|
|
cy.get('body').type('{shift}', { release: false });
|
|
}
|
|
cy.get('#root').trigger('mousemove', x + 20, y);
|
|
cy.get(shape).should('have.attr', 'transform');
|
|
cy.document().then((doc) => {
|
|
const modShapeIDString = shape.substring(1); // Remove "#" from the shape id string
|
|
const shapeTransformMatrix = decomposeMatrix(doc.getElementById(modShapeIDString).getCTM());
|
|
cy.get('#cvat_canvas_text_content').should('contain.text', `${shapeTransformMatrix}°`);
|
|
expect(`${shapeTransformMatrix}°`).to.be.equal(`${expectedRotateDeg}°`);
|
|
});
|
|
cy.get('#root').trigger('mouseup');
|
|
});
|
|
});
|
|
|
|
Cypress.Commands.add('deleteFrame', (action = 'delete') => {
|
|
cy.intercept('PATCH', '/api/jobs/**/data/meta**').as('patchMeta');
|
|
if (action === 'restore') {
|
|
cy.get('.cvat-player-restore-frame').click();
|
|
} else if (action === 'delete') {
|
|
cy.clickDeleteFrameAnnotationView();
|
|
}
|
|
cy.saveJob('PATCH', 200);
|
|
cy.wait('@patchMeta').its('response.statusCode').should('equal', 200);
|
|
});
|
|
|
|
Cypress.Commands.add('verifyNotification', () => {
|
|
cy.get('.ant-notification-notice-info').should('be.visible');
|
|
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').click();
|
|
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.add('createJob', (options = {
|
|
jobType: 'Ground truth',
|
|
frameSelectionMethod: 'Random',
|
|
quantity: null,
|
|
frameCount: null,
|
|
randomSeed: null,
|
|
fromTaskPage: true,
|
|
}) => {
|
|
const {
|
|
jobType,
|
|
frameSelectionMethod,
|
|
quantity,
|
|
frameCount,
|
|
randomSeed,
|
|
fromTaskPage,
|
|
} = options;
|
|
|
|
if (fromTaskPage) {
|
|
cy.get('.cvat-create-job').click({ force: true });
|
|
}
|
|
cy.url().should('include', '/jobs/create');
|
|
|
|
cy.get('.cvat-select-job-type').click();
|
|
cy.get('.ant-select-dropdown')
|
|
.not('.ant-select-dropdown-hidden')
|
|
.first()
|
|
.within(() => {
|
|
cy.get(`.ant-select-item-option[title="${jobType}"]`).click();
|
|
});
|
|
|
|
cy.get('.cvat-select-frame-selection-method').click();
|
|
cy.get('.ant-select-dropdown')
|
|
.not('.ant-select-dropdown-hidden')
|
|
.first()
|
|
.within(() => {
|
|
cy.get(`.ant-select-item-option[title="${frameSelectionMethod}"]`).click();
|
|
});
|
|
|
|
if (quantity) {
|
|
cy.get('.cvat-input-frame-quantity').clear();
|
|
cy.get('.cvat-input-frame-quantity').type(quantity);
|
|
} else if (frameCount) {
|
|
cy.get('.cvat-input-frame-count').clear();
|
|
cy.get('.cvat-input-frame-count').type(frameCount);
|
|
}
|
|
|
|
if (randomSeed) {
|
|
cy.get('.cvat-input-seed').clear();
|
|
cy.get('.cvat-input-seed').type(randomSeed);
|
|
}
|
|
|
|
cy.contains('button', 'Submit').click();
|
|
|
|
cy.get('.cvat-spinner').should('not.exist');
|
|
cy.url().should('match', /\/tasks\/\d+\/jobs\/\d+/);
|
|
});
|
|
|
|
Cypress.Commands.add('deleteJob', (jobID) => {
|
|
cy.get('.cvat-job-item').contains('a', `Job #${jobID}`)
|
|
.parents('.cvat-job-item')
|
|
.find('.cvat-job-item-more-button')
|
|
.click();
|
|
cy.get('.ant-dropdown')
|
|
.not('.ant-dropdown-hidden')
|
|
.within(() => {
|
|
cy.contains('[role="menuitem"]', 'Delete').click();
|
|
});
|
|
cy.get('.cvat-modal-confirm-delete-job')
|
|
.should('contain', `The job ${jobID} will be deleted`)
|
|
.within(() => {
|
|
cy.contains('button', 'Delete').click();
|
|
});
|
|
cy.get('.cvat-job-item').contains('a', `Job #${jobID}`)
|
|
.parents('.cvat-job-item')
|
|
.should('have.css', 'opacity', '0.5');
|
|
});
|
|
|
|
Cypress.Commands.add('drawMask', (instructions) => {
|
|
for (const instruction of instructions) {
|
|
const { method } = instruction;
|
|
if (method === 'brush-size') {
|
|
const { value } = instruction;
|
|
cy.get('.cvat-brush-tools-brush').click();
|
|
cy.get('.cvat-brush-tools-brush-size').within(() => {
|
|
cy.get('input').clear();
|
|
cy.get('input').type(`${value}`);
|
|
});
|
|
} else {
|
|
const { coordinates } = instruction;
|
|
if (['brush', 'eraser'].includes(method)) {
|
|
if (method === 'eraser') {
|
|
cy.get('.cvat-brush-tools-eraser').click();
|
|
} else {
|
|
cy.get('.cvat-brush-tools-brush').click();
|
|
}
|
|
|
|
cy.get('.cvat-canvas-container').then(([$canvas]) => {
|
|
const [initX, initY] = coordinates[0];
|
|
cy.wrap($canvas).trigger('mousemove', { clientX: initX, clientY: initY, bubbles: true });
|
|
cy.wrap($canvas).trigger('mousedown', {
|
|
clientX: initX, clientY: initY, button: 0, bubbles: true,
|
|
});
|
|
for (const coord of coordinates) {
|
|
const [clientX, clientY] = coord;
|
|
cy.wrap($canvas).trigger('mousemove', { clientX, clientY, bubbles: true });
|
|
}
|
|
cy.wrap($canvas).trigger('mousemove', { clientX: initX, clientY: initY, bubbles: true });
|
|
cy.wrap($canvas).trigger('mouseup', { bubbles: true });
|
|
});
|
|
} else if (['polygon-plus', 'polygon-minus'].includes(method)) {
|
|
if (method === 'polygon-plus') {
|
|
cy.get('.cvat-brush-tools-polygon-plus').click();
|
|
} else {
|
|
cy.get('.cvat-brush-tools-polygon-minus').click();
|
|
}
|
|
|
|
cy.get('.cvat-canvas-container').then(($canvas) => {
|
|
for (const [x, y] of coordinates) {
|
|
cy.wrap($canvas).click(x, y);
|
|
}
|
|
});
|
|
}
|
|
}
|
|
}
|
|
});
|
|
|
|
Cypress.Commands.add('startMaskDrawing', () => {
|
|
cy.get('.cvat-draw-mask-control ').click();
|
|
cy.get('.cvat-draw-mask-popover').should('exist').and('be.visible').within(() => {
|
|
cy.get('button').click();
|
|
});
|
|
cy.get('.cvat-brush-tools-toolbox').should('exist').and('be.visible');
|
|
});
|
|
|
|
Cypress.Commands.add('finishMaskDrawing', () => {
|
|
cy.get('.cvat-brush-tools-brush').click();
|
|
cy.get('.cvat-brush-tools-finish').click();
|
|
cy.hideTooltips();
|
|
});
|
|
|
|
Cypress.Commands.add('sliceShape', (
|
|
object,
|
|
coordinates,
|
|
options = {
|
|
shortcut: null,
|
|
slipMode: false,
|
|
},
|
|
) => {
|
|
const { shortcut, slipMode } = options;
|
|
if (shortcut) {
|
|
cy.get('body').type(shortcut);
|
|
} else {
|
|
cy.get('.cvat-slice-control').click();
|
|
cy.get('.cvat-slice-control').trigger('mouseleave');
|
|
}
|
|
|
|
cy.get('.cvat-canvas-hints-container').within(() => {
|
|
cy.contains('Click a mask or polygon shape you would like to slice').should('exist');
|
|
});
|
|
|
|
const [initialX, initialY] = coordinates.shift();
|
|
cy.get(object).click(initialX, initialY);
|
|
cy.get('.cvat-canvas-hints-container').within(() => {
|
|
cy.contains('Set initial point on the shape contour').should('exist');
|
|
});
|
|
|
|
cy.get('.cvat-canvas-container').then(($canvas) => {
|
|
if (slipMode) {
|
|
const [initX, initY] = coordinates.shift();
|
|
cy.wrap($canvas).click(initX, initY);
|
|
const [endX, endY] = coordinates.pop();
|
|
|
|
for (const [x, y] of coordinates) {
|
|
cy.wrap($canvas).trigger('mousemove', x, y, { button: 0, shiftKey: true, bubbles: true });
|
|
}
|
|
cy.wrap($canvas).click(endX, endY);
|
|
} else {
|
|
for (const [x, y] of coordinates) {
|
|
cy.wrap($canvas).click(x, y);
|
|
}
|
|
}
|
|
});
|
|
});
|
|
|
|
Cypress.Commands.add('joinShapes', (
|
|
objects,
|
|
coordinates,
|
|
options = {
|
|
shortcut: null,
|
|
},
|
|
) => {
|
|
const { shortcut } = options;
|
|
|
|
const interactWithTool = () => {
|
|
if (shortcut) {
|
|
cy.get('body').type(shortcut);
|
|
} else {
|
|
cy.get('.cvat-join-control').click();
|
|
cy.get('.cvat-join-control').trigger('mouseleave');
|
|
}
|
|
};
|
|
interactWithTool();
|
|
|
|
cy.get('.cvat-canvas-hints-container').within(() => {
|
|
cy.contains('Click masks you would like to join').should('exist');
|
|
});
|
|
|
|
for (const [index, object] of objects.entries()) {
|
|
cy.get(object).click(coordinates[index][0], coordinates[index][1]);
|
|
}
|
|
interactWithTool();
|
|
});
|
|
|
|
Cypress.Commands.add('interactAnnotationObjectMenu', (parentSelector, button) => {
|
|
cy.get(parentSelector).within(() => {
|
|
cy.get('[aria-label="more"]').click();
|
|
});
|
|
|
|
cy.document().find('.cvat-object-item-menu').within(() => {
|
|
cy.contains('button', button).click();
|
|
});
|
|
});
|
|
|
|
Cypress.Commands.add('hideTooltips', () => {
|
|
cy.wait(500); // wait while tooltips are opened
|
|
|
|
cy.document().then((doc) => {
|
|
const tooltips = Array.from(doc.querySelectorAll('.ant-tooltip'));
|
|
if (tooltips.length > 0) {
|
|
cy.get('.ant-tooltip').invoke('hide');
|
|
}
|
|
});
|
|
});
|
|
|
|
Cypress.Commands.add('checkDeletedFrameVisibility', () => {
|
|
cy.openSettings();
|
|
cy.get('.cvat-workspace-settings-show-deleted').within(() => {
|
|
cy.get('[type="checkbox"]').should('not.be.checked').check();
|
|
});
|
|
cy.closeSettings();
|
|
});
|
|
|
|
Cypress.Commands.add('checkCsvFileContent', (expectedFileName, header, rowsCount, checkRow = null) => {
|
|
const downloadsFolder = Cypress.config('downloadsFolder');
|
|
const filePath = `${downloadsFolder}/${expectedFileName}`;
|
|
cy.readFile(filePath).then((csv) => {
|
|
const rows = csv.split('\n');
|
|
expect(rows.length).to.equal(rowsCount);
|
|
expect(rows[0]).to.include(header);
|
|
if (checkRow) {
|
|
rows.slice(1).forEach(checkRow);
|
|
}
|
|
});
|
|
});
|
|
|
|
Cypress.Commands.overwrite('visit', (orig, url, options) => {
|
|
orig(url, options);
|
|
cy.closeModalUnsupportedPlatform();
|
|
});
|
|
|
|
Cypress.Commands.overwrite('reload', (orig, options) => {
|
|
orig(options);
|
|
cy.closeModalUnsupportedPlatform();
|
|
});
|
|
|
|
Cypress.Commands.add('clickDeleteFrameAnnotationView', () => {
|
|
cy.get('.cvat-player-delete-frame').click();
|
|
cy.get('.cvat-modal-delete-frame').within(() => {
|
|
cy.contains('button', 'Delete').click();
|
|
});
|
|
});
|
|
|
|
Cypress.Commands.add('clickSaveAnnotationView', () => {
|
|
cy.get('button').contains('Save').click();
|
|
cy.get('button').contains('Save').trigger('mouseout');
|
|
});
|
|
|
|
Cypress.Commands.add('makeCustomImage', (directory, fileName,
|
|
width, height, fontSize, backColor, textColor, posX, posY,
|
|
message, extension = 'png', maxWidth = undefined) => {
|
|
cy.window().then(async ($win) => {
|
|
const ofc = new $win.OffscreenCanvas(width, height);
|
|
const ctx = ofc.getContext('2d');
|
|
|
|
ctx.fillStyle = backColor;
|
|
ctx.fillRect(0, 0, width, height);
|
|
|
|
ctx.font = `${fontSize}px Impact`;
|
|
|
|
ctx.fillStyle = textColor;
|
|
ctx.textBaseline = 'top'; // so that text aligns with tracking coords
|
|
ctx.fillText(message, posX, posY, maxWidth);
|
|
|
|
cy.bufferToImage(directory, fileName, extension,
|
|
await (await ofc.convertToBlob()).arrayBuffer(),
|
|
);
|
|
});
|
|
});
|
|
|
|
Cypress.Commands.add('checkSlidersValues', (wrapper, slidersClassNames, expectedResults) => {
|
|
cy.get(wrapper).within(() => {
|
|
cy.wrap(slidersClassNames).each(($el, index) => {
|
|
cy.wrap($el)
|
|
.get($el)
|
|
.within(() => {
|
|
cy.get('[role=slider]')
|
|
.should('have.attr', 'aria-valuenow', expectedResults[index]);
|
|
});
|
|
});
|
|
});
|
|
});
|
|
|
|
Cypress.Commands.add('applyActionToSliders', (wrapper, slidersClassNames, action) => {
|
|
cy.get(wrapper).within(() => {
|
|
cy.wrap(slidersClassNames).each(($el) => {
|
|
cy.wrap($el)
|
|
.get($el)
|
|
.within(() => {
|
|
cy.get('[role=slider]').type(action);
|
|
});
|
|
});
|
|
});
|
|
cy.get('.ant-tooltip').invoke('hide');
|
|
});
|
|
|
|
Cypress.Commands.add('mergeConsensusTask', (status = 202) => {
|
|
cy.intercept('POST', '/api/consensus/merges**').as('mergeTask');
|
|
|
|
cy.get('.cvat-task-details-wrapper').should('be.visible');
|
|
cy.contains('button', 'Actions').click();
|
|
cy.contains('Merge consensus jobs').should('be.visible').click();
|
|
cy.get('.cvat-modal-confirm-consensus-merge-task')
|
|
.contains('button', 'Merge')
|
|
.click();
|
|
|
|
cy.wait('@mergeTask').its('response.statusCode').should('eq', status);
|
|
});
|
|
|
|
Cypress.Commands.add('mergeConsensusJob', (jobID, status = 202) => {
|
|
cy.intercept('POST', '/api/consensus/merges**').as('mergeJob');
|
|
cy.get('.cvat-job-item')
|
|
.filter(':has(.cvat-tag-consensus)')
|
|
.filter(`:contains("Job #${jobID}")`)
|
|
.find('.anticon-more').first().click();
|
|
|
|
cy.get('.ant-dropdown-menu').contains('li', 'Merge consensus job').click();
|
|
cy.get('.cvat-modal-confirm-consensus-merge-job')
|
|
.contains('button', 'Merge')
|
|
.click();
|
|
|
|
cy.wait('@mergeJob').its('response.statusCode').should('eq', status);
|
|
});
|