Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
105 changes: 54 additions & 51 deletions tests/cypress/e2e/actions_objects/snap_tool_feature.js
Original file line number Diff line number Diff line change
Expand Up @@ -5,12 +5,18 @@

/// <reference types="cypress" />

/**
* A point on a two dimensional plane.
* @typedef {Object} Point
* @property {number} x - The X Coordinate
* @property {number} y - The Y Coordinate
*/

import * as allure from 'allure-js-commons';
import { taskName, labelName } from '../../support/const';
import { checkAutoborderPointsCount } from '../../support/utils.cy';

context('Snap tool feature.', () => {
const keyCodeN = 78;
const createRectangleShape2Points = {
points: 'By 2 Points',
type: 'Shape',
Expand All @@ -20,6 +26,15 @@ context('Snap tool feature.', () => {
secondX: 500,
secondY: 450,
};
const createPolygonShape = {
type: 'Shape',
labelName,
pointsMap: [
{ x: 400, y: 350 },
{ x: 500, y: 350 },
{ x: 400, y: 450 },
],
};
const defaultStartingPoint = { x: 450, y: 150 };

function getShapeCoord(type, objectId) {
Expand Down Expand Up @@ -64,7 +79,6 @@ context('Snap tool feature.', () => {
cy.get('.cvat-snap-tools-control-popover').should('not.be.visible');
}

const toArr = (p) => ([p.x, p.y]);
const coordsToRect = (coords) => ({
firstX: coords[0],
firstY: coords[1],
Expand Down Expand Up @@ -106,7 +120,7 @@ context('Snap tool feature.', () => {
* @param {number} point.y
* @param {object} rect
* @param {number} angleDegrees
* @returns {object} new point
* @returns {Point}
*/
function rotate(point, rect, angleDegrees) {
const { center: origin } = getRectCenter(rect);
Expand Down Expand Up @@ -146,15 +160,6 @@ context('Snap tool feature.', () => {
let rectanglePoints;

context('Basic drawing cases', () => {
const createPolygonShape = {
type: 'Shape',
labelName,
pointsMap: [
{ x: 400, y: 350 },
{ x: 500, y: 350 },
{ x: 400, y: 450 },
],
};
const createPolylineShape = {
type: 'Shape',
labelName,
Expand Down Expand Up @@ -186,9 +191,6 @@ context('Snap tool feature.', () => {
});

it('Drawing a polygon with autoborder.', () => {
cy.interactControlButton('draw-polygon');
cy.get('.cvat-draw-polygon-popover').find('[type="button"]').contains('Shape').click();

cy.createPolygon(createPolygonShape, { numberOfAutoborderPoints: 8 });
cy.get('.cvat_canvas_autoborder_point').should('not.exist');

Expand Down Expand Up @@ -220,24 +222,16 @@ context('Snap tool feature.', () => {
const rotatedCornersGlobal = getRectCorners(rectangleGlobal, true)
.map((p) => rotate(p, rectangleGlobal, degrees));

// Draw polygon with autoborder at the rotated corner positions
cy.interactControlButton('draw-polygon');
cy.get('.cvat-draw-polygon-popover').find('[type="button"]').contains('Shape').click();

checkAutoborderPointsCount(8); // 8 points at the rectangles (4 per rectangle)

// Create polygon at rotated positions (use first 3 corners)
const { tl, br } = getRectCorners(createRectangleShape2Points);
const [p1, p2] = [tl, br].map((p) => toArr(rotate(p, createRectangleShape2Points, degrees)));
const createAutoborderedPolygonShape = {
type: 'Shape',
labelName,
pointsMap: [tl, br].map((p) => rotate(p, createRectangleShape2Points, degrees)),
};

cy.get('.cvat-canvas-container').trigger('mousemove', ...p1);
cy.get('.cvat-canvas-container').trigger('mousedown', ...p1, { button: 0 });

cy.get('.cvat-canvas-container').trigger('mousemove', ...p2);
cy.get('.cvat-canvas-container').trigger('mousedown', ...p2, { button: 0 });

cy.get('.cvat-canvas-container').trigger('keydown', { keyCode: keyCodeN, code: 'KeyN' });
cy.get('.cvat-canvas-container').trigger('keyup', { keyCode: keyCodeN, code: 'KeyN' });
// Draw polygon with autoborder at the rotated corner positions
cy.createPolygon(createAutoborderedPolygonShape, { numberOfAutoborderPoints: 8 }, 'trigger');
cy.get('.cvat_canvas_autoborder_point').should('not.exist');

// Collect the polygon points coordinates and verify they match rotated rectangle corners
Expand Down Expand Up @@ -360,9 +354,6 @@ context('Snap tool feature.', () => {
labelName,
};

cy.interactControlButton('draw-polyline');
cy.get('.cvat-draw-polyline-popover').find('[type="button"]').contains('Shape').click();

cy.createPolyline(createRegionOfRectanglePolylineShape);

cy.get('#cvat_canvas_shape_2').should('exist').and('be.visible');
Expand All @@ -389,23 +380,17 @@ context('Snap tool feature.', () => {
cy.shapeRotate('#cvat_canvas_shape_1', degrees.toFixed(1), true);

// Draw a polygon
cy.interactControlButton('draw-polygon');
cy.get('.cvat-draw-polygon-popover').find('[type="button"]').contains('Shape').click();

cy.get('.cvat-canvas-container').trigger('mousemove', ...toArr(defaultStartingPoint));
cy.get('.cvat-canvas-container').trigger('mousedown', ...toArr(defaultStartingPoint), { button: 0 });

// Should snap inside delta region
cy.get('.cvat-canvas-container').trigger('mousemove', ...toArr(regionOf(rotatedPoints[0])));
cy.get('.cvat-canvas-container').trigger('mousedown', ...toArr(regionOf(rotatedPoints[0])), { button: 0 });

cy.get('.cvat-canvas-container').trigger('mousemove', ...toArr(regionOf(rotatedPoints[1])));
cy.get('.cvat-canvas-container').trigger('mousedown', ...toArr(regionOf(rotatedPoints[1])), { button: 0 });

cy.get('.cvat-canvas-container').trigger('keydown', { keyCode: keyCodeN, code: 'KeyN' });
cy.get('.cvat-canvas-container').trigger('keyup', { keyCode: keyCodeN, code: 'KeyN' });

// TODO: cy.createPolygon approach used in previous as doesn't work here
const createRotatedPolygonShape = {
type: 'Shape',
labelName,
pointsMap: [
defaultStartingPoint,
regionOf(rotatedPoints[0]),
regionOf(rotatedPoints[1]),
],
};
cy.createPolygon(createRotatedPolygonShape, null, 'trigger');
// TODO: cy.createPolygon 'click' approach, as used previously, doesn't work here
// some snapped points are drawn twice and persist after test
// cy.wait in loop doesn't work
// not reproducible manually though, so not a user issue
Expand All @@ -419,6 +404,24 @@ context('Snap tool feature.', () => {
.equal(`${rotatedPointsGlobal[1].x},${rotatedPointsGlobal[1].y}`);
});
});

it('Snapping works when the first snapped point is on another shape', () => {
allure.issue('https://github.com/cvat-ai/cvat/pull/10509', 'Snap to initial point');
const rectCorners = getRectCorners(createRectangleShape2Points);
const createPolygonShapeSnappedSide = {
pointsMap: [
regionOf(rectCorners.tl),
regionOf(rectCorners.tr),
{ x: rectCorners.tl.x + 50, y: rectCorners.tr.y - 100 },
],
type: 'Shape',
labelName,
};
cy.createPolygon(createPolygonShapeSnappedSide);
getShapeCoord('polygon', '#cvat_canvas_shape_2').should(([firstPolygonPoint]) => {
expect(firstPolygonPoint).to.equal(`${rectanglePointsGlobal[0]},${rectanglePointsGlobal[1]}`);
});
});
});

context('Regression tests', () => {
Expand All @@ -440,7 +443,7 @@ context('Snap tool feature.', () => {
cy.removeAnnotations();
toggleSnapTool('contour', false);
});
it('Issue 3931: Autoborder points are not visible for invisible shapes', () => {
it('Autoborder points are not visible for invisible shapes', () => {
allure.issue('https://github.com/cvat-ai/cvat/pull/3931');

cy.get('.cvat-objects-sidebar-state-item').find('[data-icon="eye"]').click();
Expand Down
23 changes: 9 additions & 14 deletions tests/cypress/support/commands.js
Original file line number Diff line number Diff line change
Expand Up @@ -7,8 +7,9 @@

/* eslint-disable security/detect-non-literal-regexp */

import { keyCodeN } from './const';
import { decomposeMatrix, convertClasses, toSnakeCase } from './utils';
import { checkAutoborderPointsCount } from './utils.cy';
import { checkAutoborderPointsCount, drawWithTriggers, drawWithClicks } from './utils.cy';

require('cypress-file-upload');
require('../plugins/imageGenerator/imageGeneratorCommand');
Expand Down Expand Up @@ -602,13 +603,10 @@ Cypress.Commands.add('createPoint', (createPointParams) => {
}
cy.contains('button', createPointParams.type).click();
});
createPointParams.pointsMap.forEach((element) => {
cy.get('.cvat-canvas-container').click(element.x, element.y);
});
drawWithClicks(createPointParams.pointsMap);
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')
Expand Down Expand Up @@ -676,7 +674,7 @@ Cypress.Commands.add('shapeGrouping', (firstX, firstY, lastX, lastY) => {
.trigger('keyup', { keyCode: keyCodeG, code: 'KeyG' });
});

Cypress.Commands.add('createPolygon', (createPolygonParams, autoborderParams = null) => {
Cypress.Commands.add('createPolygon', (createPolygonParams, autoborderParams = null, drawMethod = 'click') => {
if (!createPolygonParams.reDraw) {
cy.interactControlButton('draw-polygon');
cy.switchLabel(createPolygonParams.labelName, 'draw-polygon');
Expand All @@ -694,13 +692,13 @@ Cypress.Commands.add('createPolygon', (createPolygonParams, autoborderParams = n
if (autoborderParams && Number.isInteger(autoborderParams.numberOfAutoborderPoints)) {
checkAutoborderPointsCount(autoborderParams.numberOfAutoborderPoints);
}
createPolygonParams.pointsMap.forEach((element) => {
cy.get('.cvat-canvas-container').click(element.x, element.y);
});
if (drawMethod === 'trigger') {
drawWithTriggers(createPolygonParams.pointsMap);
} else if (drawMethod === 'click') { drawWithClicks(createPolygonParams.pointsMap); }

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')
Expand Down Expand Up @@ -867,13 +865,10 @@ Cypress.Commands.add('createPolyline', (createPolylineParams, autoborderParams =
if (autoborderParams && autoborderParams.numberOfAutoborderPoints) {
checkAutoborderPointsCount(autoborderParams.numberOfAutoborderPoints);
}
createPolylineParams.pointsMap.forEach((element) => {
cy.get('.cvat-canvas-container').click(element.x, element.y);
});
drawWithClicks(createPolylineParams.pointsMap);
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')
Expand Down
1 change: 1 addition & 0 deletions tests/cypress/support/const.js
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,7 @@

/// <reference types="cypress" />

export const keyCodeN = 78;
export const labelName = 'Main task';
export const taskName = `New annotation task for ${labelName}`;
export const CLIPBOARD_ALIAS = 'copyTextToClipboard';
Expand Down
23 changes: 23 additions & 0 deletions tests/cypress/support/utils.cy.js
Original file line number Diff line number Diff line change
Expand Up @@ -40,3 +40,26 @@ export function checkAutoborderPointsCount(expectedCount) {
});
}
}

/**
* Draw a shape by clicking through an array of points
* using cy.trigger events
* @param {Array<{x: number, y: number}>} points - Array of points to trigger
*/
export function drawWithTriggers(pointsMap) {
pointsMap.forEach((p) => {
cy.get('.cvat-canvas-container').trigger('mousemove', ...[p.x, p.y]);
cy.get('.cvat-canvas-container').trigger('mousedown', ...[p.x, p.y], { button: 0 });
});
}

/**
* Draw a shape by clicking through an array of points
* using cy.click
* @param {Array<{x: number, y: number}>} points - Array of points to click
*/
export function drawWithClicks(pointsMap) {
pointsMap.forEach((element) => {
cy.get('.cvat-canvas-container').click(element.x, element.y);
});
}
Loading