diff --git a/cvat-ui/src/components/annotation-page/standard-workspace/controls-side-bar/opencv-control.tsx b/cvat-ui/src/components/annotation-page/standard-workspace/controls-side-bar/opencv-control.tsx index 2543a3ef..d993af71 100644 --- a/cvat-ui/src/components/annotation-page/standard-workspace/controls-side-bar/opencv-control.tsx +++ b/cvat-ui/src/components/annotation-page/standard-workspace/controls-side-bar/opencv-control.tsx @@ -229,6 +229,7 @@ class OpenCVControlComponent extends React.PureComponent HistogramEqualization + hist: () => HistogramEqualization; } export class OpenCVWrapper { @@ -41,10 +41,6 @@ export class OpenCVWrapper { const contentLength = response.headers.get('Content-Length'); const { body } = response; - if (contentLength === null) { - throw new Error('Content length is null, but necessary'); - } - if (body === null) { throw new Error('Response body is null, but necessary'); } @@ -64,7 +60,9 @@ export class OpenCVWrapper { if (value instanceof Uint8Array) { decodedScript += decoder.decode(value); receivedLength += value.length; - const percentage = (receivedLength * 100) / +(contentLength as string); + // Cypress workaround: content-length is always zero in cypress, it is done optional here + // Just progress bar will be disabled + const percentage = contentLength ? (receivedLength * 100) / +(contentLength as string) : 0; onProgress(+percentage.toFixed(0)); } } diff --git a/tests/cypress/integration/actions_tasks/case_100_settings_default_number_of_points_in_polygon_approximation.js b/tests/cypress/integration/actions_tasks/case_100_settings_default_number_of_points_in_polygon_approximation.js index 819cb4a9..3191502b 100644 --- a/tests/cypress/integration/actions_tasks/case_100_settings_default_number_of_points_in_polygon_approximation.js +++ b/tests/cypress/integration/actions_tasks/case_100_settings_default_number_of_points_in_polygon_approximation.js @@ -5,6 +5,7 @@ /// import { taskName } from '../../support/const'; +import { generateString } from '../../support/utils'; context('Settings. Default number of points in polygon approximation.', () => { const caseId = '100'; @@ -26,14 +27,6 @@ context('Settings. Default number of points in polygon approximation.', () => { }); } - function generateString(countPointsToMove) { - let action = ''; - for (let i = 0; i < countPointsToMove; i++) { - action += '{rightarrow}'; - } - return action; - } - before(() => { cy.openTaskJob(taskName); }); @@ -43,7 +36,7 @@ context('Settings. Default number of points in polygon approximation.', () => { testOpenSettingsWorkspace(); cy.get('.cvat-workspace-settings-approx-poly-threshold') .find('[role="slider"]') - .type(generateString(4)) + .type(generateString(4, 'rightarrow')) .then((slider) => { const sliderAttrValueNow = slider.attr('aria-valuenow'); const sliderAttrValuemin = slider.attr('aria-valuemin'); diff --git a/tests/cypress/integration/actions_tasks2/case_101_opencv_basic_actions.js b/tests/cypress/integration/actions_tasks2/case_101_opencv_basic_actions.js new file mode 100644 index 00000000..95268fb5 --- /dev/null +++ b/tests/cypress/integration/actions_tasks2/case_101_opencv_basic_actions.js @@ -0,0 +1,117 @@ +// Copyright (C) 2021 Intel Corporation +// +// SPDX-License-Identifier: MIT + +/// + +import { taskName, labelName } from '../../support/const'; +import { generateString } from '../../support/utils'; + +context('OpenCV. Intelligent cissors. Histogram Equalization.', () => { + const caseId = '101'; + const newLabel = `Case ${caseId}` + const createOpencvShape = { + labelName: labelName, + pointsMap: [ + { x: 200, y: 200 }, + { x: 250, y: 200 }, + { x: 300, y: 250 }, + { x: 350, y: 300 }, + { x: 300, y: 350 }, + ], + }; + const createOpencvShapeSecondLabel = { + labelName: newLabel, + pointsMap: [ + { x: 300, y: 200 }, + { x: 350, y: 200 }, + { x: 400, y: 250 }, + { x: 450, y: 300 }, + { x: 400, y: 350 }, + ], + finishWithButton: true, + }; + const keyCodeN = 78; + const pointsMap = [ + { x: 300, y: 400 }, + { x: 350, y: 500 }, + { x: 400, y: 450 }, + { x: 450, y: 500 }, + { x: 400, y: 550 }, + ]; + + function openOpencvControlPopover() { + cy.get('body').focus(); + cy.get('.cvat-tools-control').trigger('mouseleave').trigger('mouseout').trigger('mouseover'); + } + + before(() => { + cy.openTask(taskName); + cy.addNewLabel(newLabel); + cy.openJob(); + }); + + describe(`Testing case "${caseId}"`, () => { + it('Load OpenCV.', () => { + openOpencvControlPopover(); + cy.get('.cvat-opencv-control-popover-visible').find('.cvat-opencv-initialization-button').click(); + // Intelligent cissors button be visible + cy.get('.cvat-opencv-drawing-tool').should('exist').and('be.visible'); + }); + + it('Create a shape with "Intelligent cissors". Create the second shape with the label change and "Done" button.', () => { + cy.opencvCreateShape(createOpencvShape); + cy.opencvCreateShape(createOpencvShapeSecondLabel); + }); + + it('Change the number of points when the shape is drawn. Cancel drawing.', () => { + openOpencvControlPopover(); + cy.get('.cvat-opencv-drawing-tool').click(); + pointsMap.forEach((element) => { + cy.get('.cvat-canvas-container').click(element.x, element.y); + }); + cy.get('.cvat_canvas_interact_intermediate_shape').then((intermediateShape) => { + // Get count of points + const intermediateShapeNumberPointsBeforeChange = intermediateShape.attr('points').split(' ').length; + // Change number of points + cy.get('.cvat-approx-poly-threshold-wrapper') + .find('[role="slider"]') + .type(generateString(4, 'rightarrow')); + cy.get('.cvat_canvas_interact_intermediate_shape').then((intermediateShape) => { + // Get count of points againe + const intermediateShapeNumberPointsAfterChange = intermediateShape.attr('points').split(' ').length; + // expected 7 to be below 10 + expect(intermediateShapeNumberPointsBeforeChange).to.be.lt(intermediateShapeNumberPointsAfterChange); + }); + }); + cy.get('body').type('{Esc}'); // Cancel drawing + cy.get('.cvat_canvas_interact_intermediate_shape').should('not.exist'); + cy.get('.cvat_canvas_shape').should('have.length', 2); + }); + + it('Check "Histogram Equalization" feature.', () => { + openOpencvControlPopover(); + cy.get('.cvat-opencv-control-popover-visible').contains('[role="tab"]', 'Image').click(); + cy.get('.cvat-opencv-image-tool').click().should('have.class', 'cvat-opencv-image-tool-active').trigger('mouseout'); + cy.get('.cvat-notification-notice-opencv-processing-error').should('not.exist'); + cy.get('.cvat-opencv-image-tool').click().should('not.have.class', 'cvat-opencv-image-tool-active').trigger('mouseout'); + }); + + // Waiting for fix https://github.com/openvinotoolkit/cvat/issues/3474 + it.skip('Redraw the shape created with "Intelligent cissors".', () => { + cy.get('.cvat-canvas-container').click(); + cy.get('.cvat-opencv-control-popover').should('be.hidden'); + cy.get('#cvat_canvas_shape_1') + .trigger('mousemove') + .trigger('mouseover') + .should('have.class', 'cvat_canvas_shape_activated'); + cy.get('body').trigger('keydown', { keyCode: keyCodeN, shiftKey: true }).trigger('keyup'); + cy.get('.cvat-tools-control').should('have.attr', 'tabindex'); + createOpencvShape.pointsMap.forEach((el) => { + cy.get('.cvat-canvas-container') + .click(el.x + 150, el.y + 50) + }); + cy.get('body').trigger('keydown', { keyCode: keyCodeN }).trigger('keyup'); + }); + }); +}); diff --git a/tests/cypress/integration/actions_tasks2/case_23_canvas_grid_feature.js b/tests/cypress/integration/actions_tasks2/case_23_canvas_grid_feature.js index 81cd9cdc..0eb350ae 100644 --- a/tests/cypress/integration/actions_tasks2/case_23_canvas_grid_feature.js +++ b/tests/cypress/integration/actions_tasks2/case_23_canvas_grid_feature.js @@ -5,6 +5,7 @@ /// import { taskName } from '../../support/const'; +import { generateString } from '../../support/utils'; context('Canvas grid feature', () => { const caseId = '23'; @@ -12,14 +13,6 @@ context('Canvas grid feature', () => { const gridColor = 'Black'; const gridOpacity = 80; - function generateString(countPointsToMove) { - let action = ''; - for (let i = 0; i < countPointsToMove; i++) { - action += '{leftarrow}'; - } - return action; - } - before(() => { cy.openTaskJob(taskName); cy.get('.cvat-canvas-image-setups-trigger').click(); @@ -44,7 +37,7 @@ context('Canvas grid feature', () => { }); it('Set "Grid opacity" to 80%.', () => { cy.get('.cvat-image-setups-grid-opacity-input').within(() => { - cy.get('[role="slider"]').type(generateString(20)); // Moving the slider to the left up to 80. + cy.get('[role="slider"]').type(generateString(20, 'leftarrow')); // Moving the slider to the left up to 80. cy.get('[role="slider"]').should('have.attr', 'aria-valuenow', gridOpacity); }); }); diff --git a/tests/cypress/integration/actions_tasks2/case_26_canvas_brightness_contrast_saturation_feature.js b/tests/cypress/integration/actions_tasks2/case_26_canvas_brightness_contrast_saturation_feature.js index ed343710..3beb25a4 100644 --- a/tests/cypress/integration/actions_tasks2/case_26_canvas_brightness_contrast_saturation_feature.js +++ b/tests/cypress/integration/actions_tasks2/case_26_canvas_brightness_contrast_saturation_feature.js @@ -5,6 +5,7 @@ /// import { taskName } from '../../support/const'; +import { generateString } from '../../support/utils'; context('Canvas brightness/contrast/saturation feature', () => { const caseId = '26'; @@ -17,14 +18,6 @@ context('Canvas brightness/contrast/saturation feature', () => { '.cvat-image-setups-saturation', ]; - function generateStringCountAction(countAction) { - let stringAction = ''; - for (let i = 0; i < countAction; i++) { - stringAction += '{rightarrow}'; - } - return stringAction; - } - function checkStateValuesInBackground(expectedValue) { cy.get('#cvat_canvas_background') .should('have.attr', 'style') @@ -41,7 +34,7 @@ context('Canvas brightness/contrast/saturation feature', () => { describe(`Testing case "${caseId}"`, () => { it('Check apply of settings', () => { - let stringAction = generateStringCountAction(countActionMoveSlider); + let stringAction = generateString(countActionMoveSlider, 'rightarrow'); cy.get('.cvat-canvas-image-setups-content').within(() => { cy.wrap(classNameSliders).each(($el) => { cy.wrap($el) diff --git a/tests/cypress/support/commands_opencv.js b/tests/cypress/support/commands_opencv.js new file mode 100644 index 00000000..8378c574 --- /dev/null +++ b/tests/cypress/support/commands_opencv.js @@ -0,0 +1,51 @@ +// Copyright (C) 2021 Intel Corporation +// +// SPDX-License-Identifier: MIT + +/// + +let selectedValueGlobal = ''; + +Cypress.Commands.add('opencvCreateShape', (opencvShapeParams) => { + if (!opencvShapeParams.reDraw) { + cy.get('body').focus(); + cy.get('.cvat-tools-control').trigger('mouseleave').trigger('mouseout').trigger('mouseover'); + cy.switchLabel(opencvShapeParams.labelName, 'opencv-control'); + cy.get('.cvat-opencv-control-popover-visible').within(() => { + cy.get('.ant-select-selection-item').then(($labelValue) => { + selectedValueGlobal = $labelValue.text(); + }); + }); + cy.get('.cvat-opencv-drawing-tool').click(); + } + opencvShapeParams.pointsMap.forEach((element) => { + cy.get('.cvat-canvas-container').click(element.x, element.y); + }); + if (opencvShapeParams.finishWithButton) { + cy.contains('span', 'Done').click(); + } else { + const keyCodeN = 78; + cy.get('.cvat-canvas-container') + .trigger('keydown', { keyCode: keyCodeN }) + .trigger('keyup', { keyCode: keyCodeN }); + } + cy.opncvCheckObjectParameters('POLYGON'); +}); + +Cypress.Commands.add('opncvCheckObjectParameters', (objectType) => { + let 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) + .within(() => { + cy.get('.ant-select-selection-item').should('have.text', selectedValueGlobal); + }); + }); +}); diff --git a/tests/cypress/support/index.js b/tests/cypress/support/index.js index 5c8880df..c146c98e 100644 --- a/tests/cypress/support/index.js +++ b/tests/cypress/support/index.js @@ -8,6 +8,7 @@ require('./commands_review_pipeline'); require('./commands_canvas3d'); require('./commands_filters_feature'); require('./commands_models'); +require('./commands_opencv'); require('@cypress/code-coverage/support'); require('cypress-plugin-tab'); diff --git a/tests/cypress/support/utils.js b/tests/cypress/support/utils.js new file mode 100644 index 00000000..975d61e2 --- /dev/null +++ b/tests/cypress/support/utils.js @@ -0,0 +1,11 @@ +// Copyright (C) 2021 Intel Corporation +// +// SPDX-License-Identifier: MIT + +export function generateString(countPointsToMove, arrow) { + let action = ''; + for (let i = 0; i < countPointsToMove; i++) { + action += `{${arrow}}`; + } + return action; +}