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

228 lines
7.9 KiB
JavaScript
Raw Permalink Normal View History

2025-09-16 01:19:40 +00:00
// Copyright (C) CVAT.ai Corporation
//
// SPDX-License-Identifier: MIT
/// <reference types="cypress" />
import { defaultTaskSpec } from '../../support/default-specs';
context('Bulk actions in UI', () => {
const taskName = 'task_bulk_actions';
const projectName = 'project_bulk_actions';
const serverFiles = ['smallArchive.zip'];
const labelName = 'car';
const project = {
name: projectName,
label: 'car',
attrName: 'color',
attrValue: 'red',
multiAttrParams: false,
};
const projectSpec = {
name: project.name,
labels: [{
name: labelName,
attributes: [{
name: project.attrName,
mutable: false,
input_type: 'text',
default_value: project.attrValue,
values: [project.attrValue],
}],
}],
};
const projects = [];
const taskTwoJobs = {
ID: null,
jobIDs: [],
};
let projectTwoTasks = null;
const nobjs = 2;
const framesPerJob = 1;
const stringID = (i, str) => str.concat(`_${i}`);
const createTaskInProject = (i, projectID, taskParams) => {
const { taskSpec, dataSpec, extras } = defaultTaskSpec({
...taskParams,
projectID,
taskName: stringID(i, taskParams.taskName),
});
delete taskSpec.labels; // can only have labels or project_id
return cy.headlessCreateTask(taskSpec, dataSpec, extras);
};
const createProject = (i) => cy.headlessCreateProject({
...projectSpec,
name: stringID(i, projectName),
});
function selectAll() {
cy.get('.cvat-bulk-wrapper').should('exist').and('be.visible');
cy.contains('Select all').click();
}
function getBulkActionsMenu() {
selectAll();
cy.get('.cvat-item-selected').first().within(() => {
cy.get('.cvat-actions-menu-button').click();
});
return cy.get('.ant-dropdown');
}
function assignToAdmin() {
cy.contains(`Assignee (${nobjs})`).click();
cy.get('.cvat-user-search-field').type('admin', { delay: 0 }); // all at once
return cy.get('.cvat-user-search-field').type('{enter}');
}
before(() => {
cy.visit('/auth/login');
cy.headlessLogin();
createProject(1).then(({ projectID }) => projects.push(projectID)); // empty project
createProject(2).then(({ projectID }) => {
projects.push(projectID);
projectTwoTasks = projectID;
// default task with 1 job
createTaskInProject(1, projectID, { taskName, labelName, serverFiles });
// default task with 2 jobs
createTaskInProject(2, projectID, {
taskName, labelName, serverFiles, segmentSize: framesPerJob,
}).then(({ taskID, jobIDs }) => {
taskTwoJobs.ID = taskID;
taskTwoJobs.jobIDs = jobIDs;
});
});
});
after(() => {
projects.forEach(cy.headlessDeleteProject);
cy.headlessLogout();
});
describe('Bulk-change object attributes, confirm UI state', () => {
before(() => {
cy.openProjectById(projectTwoTasks);
});
context('Project page, change tasks', () => {
it('"Select all", all items are selected, "Deselect" button is visible', () => {
cy.get('.cvat-item-selected').should('not.exist');
cy.get('.cvat-bulk-wrapper')
.should('exist')
.and('be.visible');
cy.get('.cvat-resource-select-all-button')
.should('be.visible')
.and('have.text', 'Select all')
.click();
cy.get('.cvat-item-selected')
.should('exist')
.its('length')
.should('eq', nobjs);
cy.get('.cvat-resource-selection-count')
.should('be.visible')
.and('have.text', `Selected: ${nobjs}`);
cy.get('.cvat-resource-deselect-button')
.should('be.visible')
.and('have.text', 'Deselect').click();
cy.get('.cvat-item-selected').should('not.exist');
});
it('Bulk-change assignees', () => {
getBulkActionsMenu().within(() => {
assignToAdmin();
});
cy.get('.cvat-bulk-progress-wrapper').should('be.visible');
cy.openTaskById(taskTwoJobs.ID);
// Ensure task was assigned to admin
cy.get('.cvat-user-search-field').first()
.should('exist').within(() => {
cy.get('[value="admin"]');
});
});
});
context('Task page, change jobs', () => {
before(() => {
cy.openTaskById(taskTwoJobs.ID);
});
it('Bulk-change assignees', () => {
getBulkActionsMenu().within(() => {
assignToAdmin();
});
cy.get('.cvat-bulk-progress-wrapper').should('be.visible');
cy.get('.cvat-job-assignee-selector').each(($el) => {
cy.wrap($el).find('[value="admin"]').should('exist');
});
});
it('Bulk-change state', () => {
getBulkActionsMenu().within(() => {
cy.contains(`State (${nobjs})`).click();
cy.get('.cvat-job-item-state').click();
// state is 'new' by default, so pick second option (='in progress')
cy.get('.ant-select-selection-search').type('{downarrow}');
cy.get('.ant-select-selection-search').type('{enter}');
});
cy.get('.cvat-bulk-progress-wrapper').should('be.visible');
cy.get('.ant-select-selection-item[title="in progress"]')
.should('have.length', nobjs);
});
});
});
describe('Bulk export', () => {
before(() => {
cy.openTaskById(taskTwoJobs.ID);
});
it('Bulk-export job annotations', () => {
getBulkActionsMenu().within(() => {
cy.contains(`Export annotations (${nobjs})`)
.should('be.visible')
.click();
});
cy.get('.cvat-modal-export-job')
.should('exist').and('be.visible')
.find('.ant-modal-header')
.should('have.text', `Export ${nobjs} jobs as datasets`);
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');
cy.closeNotification('.cvat-notification-notice-export-job-finished', nobjs);
});
});
describe('Delete all tasks in project', () => {
before(() => {
cy.openProjectById(projectTwoTasks);
});
it('Delete all tasks, ensure deletion', () => {
getBulkActionsMenu().within(() => {
cy.contains(`Delete (${nobjs})`).click();
});
cy.get('.cvat-modal-confirm-delete-task')
.should('be.visible').within(() => {
cy.contains(`Delete ${nobjs} selected tasks`);
cy.contains('Delete selected')
.should('be.visible')
.click();
});
cy.get('.cvat-bulk-progress-wrapper').should('be.visible');
cy.get('.cvat-tasks-list-item').each(($el) => {
cy.wrap($el)
.invoke('attr', 'style')
.should('include', 'pointer-events: none');
});
});
});
});