diff --git a/tests/cypress.json b/tests/cypress.json index fa98e950..eb67a4ae 100644 --- a/tests/cypress.json +++ b/tests/cypress.json @@ -15,6 +15,7 @@ "actions_tasks_objects/**/*", "actions_users/**/*", "actions_projects/**/*", + "canvas3d_functionality/*", "remove_users_tasks_projects.js" ] } diff --git a/tests/cypress/integration/canvas3d_functionality/assets/test_canvas3d.zip b/tests/cypress/integration/canvas3d_functionality/assets/test_canvas3d.zip new file mode 100644 index 00000000..c6defd28 Binary files /dev/null and b/tests/cypress/integration/canvas3d_functionality/assets/test_canvas3d.zip differ diff --git a/tests/cypress/integration/canvas3d_functionality/case_56_canvas3d_functionality_basic_actions.js b/tests/cypress/integration/canvas3d_functionality/case_56_canvas3d_functionality_basic_actions.js new file mode 100644 index 00000000..aa6aa212 --- /dev/null +++ b/tests/cypress/integration/canvas3d_functionality/case_56_canvas3d_functionality_basic_actions.js @@ -0,0 +1,179 @@ +// Copyright (C) 2021 Intel Corporation +// +// SPDX-License-Identifier: MIT + +/// + +import { taskName } from '../../support/const_canvas3d'; +// Firefox does not yet support WebGL in headless mode: https://bugzilla.mozilla.org/show_bug.cgi?id=1375585 (disabled in the cypress_cron_type.json) +context('Canvas 3D functionality. Basic actions.', () => { + const caseId = '56'; + const screenshotsPath = + 'cypress/screenshots/canvas3d_functionality/case_56_canvas3d_functionality_basic_actions.js'; + + function compareImages(imgBefore, imgAfter) { + cy.compareImages(`${screenshotsPath}/${imgBefore}`, `${screenshotsPath}/${imgAfter}`).then((diffPercent) => { + expect(diffPercent).to.be.gt(0); + }); + } + + function testPerspectiveChangeOnKeyPress(key, screenshotNameBefore, screenshotNameAfter) { + cy.get('.cvat-canvas3d-perspective').trigger('mouseover').screenshot(screenshotNameBefore); + cy.get('body').type(`{alt}${key}`); + cy.get('.cvat-canvas3d-perspective').screenshot(screenshotNameAfter); + compareImages(`${screenshotNameBefore}.png`, `${screenshotNameAfter}.png`); + } + + function testPerspectiveChangeOnArrowKeyPress(key, screenshotNameBefore, screenshotNameAfter) { + cy.get('.cvat-canvas3d-perspective').trigger('mouseover').screenshot(screenshotNameBefore); + cy.get('body').type(key); + cy.get('.cvat-canvas3d-perspective').screenshot(screenshotNameAfter); + compareImages(`${screenshotNameBefore}.png`, `${screenshotNameAfter}.png`); + } + + function testPerspectiveChangeOnWheel(screenshotNameBefore, screenshotNameAfter) { + cy.get('.cvat-canvas3d-perspective').screenshot(screenshotNameBefore); + for (let i = 0; i < 5; i++) { + cy.get('.cvat-canvas3d-perspective').trigger('wheel', { deltaY: -200 }); + } + cy.get('.cvat-canvas3d-perspective').screenshot(screenshotNameAfter); + compareImages(`${screenshotNameBefore}.png`, `${screenshotNameAfter}.png`); + } + + function testTopSideFrontChangeOnWheel(element, deltaY, screenshotNameBefore, screenshotNameAfter) { + cy.get(element).screenshot(screenshotNameBefore); + for (let i = 0; i < 10; i++) { + cy.get(element).trigger('wheel', { deltaY: deltaY }); + } + cy.get(element).screenshot(screenshotNameAfter); + compareImages(`${screenshotNameBefore}.png`, `${screenshotNameAfter}.png`); + } + + before(() => { + cy.openTaskJob(taskName); + }); + + after(() => { + cy.goToTaskList(); + cy.deleteTask(taskName); + }); + + describe(`Testing case "${caseId}"`, () => { + it('Check existing of elements.', () => { + cy.get('.cvat-canvas3d-perspective') + .should('exist') + .and('be.visible') + .within(() => { + cy.get('.cvat-canvas3d-perspective-arrow-directions') + .should('exist') + .and('be.visible') + .within(() => { + cy.get('[aria-label="arrow-up"]').should('exist').and('be.visible'); + cy.get('[aria-label="arrow-left"]').should('exist').and('be.visible'); + cy.get('[aria-label="arrow-down"]').should('exist').and('be.visible'); + cy.get('[aria-label="arrow-right"]').should('exist').and('be.visible'); + }); + cy.get('.cvat-canvas3d-perspective-directions') + .should('exist') + .and('be.visible') + .within(() => { + cy.contains('button', 'U').should('exist').and('be.visible'); + cy.contains('button', 'I').should('exist').and('be.visible'); + cy.contains('button', 'O').should('exist').and('be.visible'); + cy.contains('button', 'J').should('exist').and('be.visible'); + cy.contains('button', 'K').should('exist').and('be.visible'); + cy.contains('button', 'L').should('exist').and('be.visible'); + }); + }); + cy.get('.cvat-canvas3d-topview').should('exist').and('be.visible'); + cy.get('.cvat-canvas3d-sideview').should('exist').and('be.visible'); + cy.get('.cvat-canvas3d-frontview').should('exist').and('be.visible'); + cy.get('.cvat-canvas-controls-sidebar') + .should('exist') + .and('be.visible') + .within(() => { + cy.get('.cvat-move-control').should('exist').and('be.visible'); + cy.get('.cvat-cursor-control').should('exist').and('be.visible'); + cy.get('.cvat-draw-cuboid-control').should('exist').and('be.visible'); + cy.get('[aria-label="camera"]').should('exist').and('be.visible'); + }); + }); + + it('Check workspace selector.', () => { + // Try to click on the disabled workspace selectors. The value of the selector should not changed. + cy.get('.cvat-workspace-selector').should('contain.text', 'Standard 3D').click(); + for (const dropdownItems of [ + '[title="Attribute annotation"]', + '[title="Tag annotation"]', + '[title="Review"]', + ]) { + cy.get('.cvat-workspace-selector-dropdown') + .not('.ant-select-dropdown-hidden') + .within(() => { + cy.get(dropdownItems).click(); + }); + cy.get('.cvat-workspace-selector').should('contain.text', 'Standard 3D'); + } + }); + + it('Interaction with the frame change buttons.', () => { + cy.get('.cvat-player-last-button').click(); + cy.checkFrameNum(2); + cy.get('.cvat-player-filename-wrapper').should('contain.text', 'generated_pcd_50000_points.pcd'); + cy.get('.cvat-player-first-button').click(); + cy.checkFrameNum(0); + cy.get('.cvat-player-filename-wrapper').should('contain.text', 'generated_pcd_100000_points.pcd'); + cy.get('.cvat-player-forward-button').click(); + cy.checkFrameNum(2); + cy.get('.cvat-player-filename-wrapper').should('contain.text', 'generated_pcd_50000_points.pcd'); + cy.get('.cvat-player-backward-button').click(); + cy.checkFrameNum(0); + cy.get('.cvat-player-filename-wrapper').should('contain.text', 'generated_pcd_100000_points.pcd'); + cy.get('.cvat-player-next-button').click(); + cy.checkFrameNum(1); + cy.get('.cvat-player-filename-wrapper').should('contain.text', 'generated_pcd_10000_points.pcd'); + cy.get('.cvat-player-previous-button').click(); + cy.checkFrameNum(0); + cy.get('.cvat-player-filename-wrapper').should('contain.text', 'generated_pcd_100000_points.pcd'); + cy.get('.cvat-player-play-button').click(); + cy.checkFrameNum(2); + cy.get('.cvat-player-filename-wrapper').should('contain.text', 'generated_pcd_50000_points.pcd'); + cy.get('.cvat-player-first-button').click(); // Return to first frame + }); + + it('Testing perspective visual regressions.', () => { + testPerspectiveChangeOnWheel('perspective_before_wheel', 'perspective_after_wheel'); + testPerspectiveChangeOnKeyPress('u', 'before_press_altU', 'after_press_altU'); + testPerspectiveChangeOnKeyPress('o', 'before_press_altO', 'after_press_altO'); + testPerspectiveChangeOnKeyPress('i', 'before_press_altI', 'after_press_altI'); + testPerspectiveChangeOnKeyPress('k', 'before_press_altK', 'after_press_altK'); + testPerspectiveChangeOnKeyPress('j', 'before_press_altJ', 'after_press_altJ'); + testPerspectiveChangeOnKeyPress('l', 'before_press_altL', 'after_press_altL'); + testPerspectiveChangeOnArrowKeyPress('{uparrow}', 'before_press_uparrow', 'after_press_uparrow'); + testPerspectiveChangeOnArrowKeyPress('{downarrow}', 'before_press_downarrow', 'after_press_downarrow'); + testPerspectiveChangeOnArrowKeyPress('{leftarrow}', 'before_press_leftarrow', 'after_press_leftarrow'); + testPerspectiveChangeOnArrowKeyPress('{rightarrow}', 'before_press_rightarrow', 'after_press_rightarrow'); + }); + + it('Testing top/side/front views visual regressions.', () => { + testTopSideFrontChangeOnWheel( + '.cvat-canvas3d-topview', + -1000, + 'topview_before_wheel', + 'topview_after_wheel', + ); + testTopSideFrontChangeOnWheel( + '.cvat-canvas3d-sideview', + -1000, + 'sideview_before_wheel', + 'sideview_after_wheel', + ); + testTopSideFrontChangeOnWheel( + '.cvat-canvas3d-frontview', + -1000, + 'frontview_before_wheel', + 'frontview_after_wheel', + ); + }); + }); +}); diff --git a/tests/cypress/plugins/compareImages/addPlugin.js b/tests/cypress/plugins/compareImages/addPlugin.js new file mode 100644 index 00000000..3cb8529d --- /dev/null +++ b/tests/cypress/plugins/compareImages/addPlugin.js @@ -0,0 +1,16 @@ +// Copyright (C) 2021 Intel Corporation +// +// SPDX-License-Identifier: MIT + +// eslint-disable-next-line no-undef +exports.compareImages = compareImages; + +const Jimp = require('jimp'); + +async function compareImages(args) { + const imgBase = await Jimp.read(args.imgBase); + const imgAfterChanges = await Jimp.read(args.imgAfterChanges); + const diff = Jimp.diff(imgBase, imgAfterChanges); + + return diff.percent; +} diff --git a/tests/cypress/plugins/compareImages/compareImagesCommand.js b/tests/cypress/plugins/compareImages/compareImagesCommand.js new file mode 100644 index 00000000..92c49f14 --- /dev/null +++ b/tests/cypress/plugins/compareImages/compareImagesCommand.js @@ -0,0 +1,10 @@ +// Copyright (C) 2021 Intel Corporation +// +// SPDX-License-Identifier: MIT + +Cypress.Commands.add('compareImages', function (imgBase, imgAfterChanges) { + return cy.task('compareImages', { + imgBase: imgBase, + imgAfterChanges: imgAfterChanges, + }); +}); diff --git a/tests/cypress/plugins/index.js b/tests/cypress/plugins/index.js index b9748b5b..b529d9b6 100644 --- a/tests/cypress/plugins/index.js +++ b/tests/cypress/plugins/index.js @@ -6,12 +6,14 @@ const { imageGenerator } = require('../plugins/imageGenerator/addPlugin'); const { createZipArchive } = require('../plugins/createZipArchive/addPlugin'); +const { compareImages } = require('../plugins/compareImages/addPlugin'); const fs = require('fs'); module.exports = (on, config) => { require('@cypress/code-coverage/task')(on, config); on('task', { imageGenerator }); on('task', { createZipArchive }); + on('task', { compareImages }); on('task', { log(message) { console.log(message); diff --git a/tests/cypress/support/commands.js b/tests/cypress/support/commands.js index ae179d1a..d707c8eb 100644 --- a/tests/cypress/support/commands.js +++ b/tests/cypress/support/commands.js @@ -8,6 +8,7 @@ require('cypress-file-upload'); require('../plugins/imageGenerator/imageGeneratorCommand'); require('../plugins/createZipArchive/createZipArchiveCommand'); require('cypress-localstorage-commands'); +require('../plugins/compareImages/compareImagesCommand'); let selectedValueGlobal = ''; diff --git a/tests/cypress/support/const_canvas3d.js b/tests/cypress/support/const_canvas3d.js new file mode 100644 index 00000000..2228893b --- /dev/null +++ b/tests/cypress/support/const_canvas3d.js @@ -0,0 +1,40 @@ +// Copyright (C) 2021 Intel Corporation +// +// SPDX-License-Identifier: MIT + +/// + +export const labelName = `points cloud`; +export const taskName = `Canvas 3D functionality`; +export const pcdPngZipArr = '../../cypress/integration/canvas3d_functionality/assets/test_canvas3d.zip'; +export const attrName = `Attr for ${labelName}`; +export const textDefaultValue = 'Some default value for type Text'; +export const advancedConfigurationParams = false; +export const multiAttrParams = false; + +it('Prepare to testing', () => { + cy.visit('/'); + cy.login(); + cy.get('.cvat-tasks-page').should('exist'); + let listItems = []; + cy.document().then((doc) => { + const collection = Array.from(doc.querySelectorAll('.cvat-item-task-name')); + for (let i = 0; i < collection.length; i++) { + listItems.push(collection[i].innerText); + } + if (listItems.indexOf(taskName) === -1) { + cy.task('log', "A task doesn't exist. Creating."); + cy.createAnnotationTask( + taskName, + labelName, + attrName, + textDefaultValue, + pcdPngZipArr, + multiAttrParams, + advancedConfigurationParams, + ); + } else { + cy.task('log', 'The task exist. Skipping creation.'); + } + }); +});