From e212d57136b6be9f961ddeada37bd07770635c54 Mon Sep 17 00:00:00 2001 From: Dmitry Kruchinin Date: Mon, 24 Jan 2022 17:44:15 +0300 Subject: [PATCH] Cypress. New organization pipeline. (#4143) * The folder renamed * Add classes * Rename the folder * Rename/rework the script for remoing users, tasts, projects, organizations * Added commands for organizations * Fix eslint issues * Fix workflow * Move the test to the registration_involved folder * Added class * Update the test. Added some commands. * Added class * Add a command. Updated the test. * Fix eslint issue * Added some classes * Added cypress command. Update corespinding test. * Continue writin the test. Update commands. * Continue writing the test * Update main.yml * Add className * Update the test. Add command * Update the test * Added command for remove a tasks, users, progects, orgs * Some reworks * Add a class * Update the test * Added check issue 4096 * Update year * Update years * Update the stept in the test * Rework command to remove users, etc. * The tests adaptation * Rework command to deleting users, etc. * Apply comments * Revert changes except base_actions_project test * Rename the command to delete a task by api * Apply commenst. Split tests * Update the command, the test. * Added steps to check * Fix support/index.js * The test adaptation. * Removed comments. Co-authored-by: dvkruchinin --- .github/workflows/main.yml | 10 +- cvat-ui/src/components/header/header.tsx | 17 +- .../organization-page/member-item.tsx | 3 +- .../components/organization-page/top-bar.tsx | 6 +- tests/cypress.json | 3 +- .../case_113_new_organization_pipeline.js | 299 ++++++++++++++++++ .../base_actions_project_task_user.js | 6 +- .../case_39_issue_2572_rename_task.js | 14 +- .../case_69_filters_sorting_jobs.js | 7 +- .../case_28_review_pipeline_feature.js | 11 +- .../case_2_register_user_change_pass.js | 6 +- .../case_4_assign_taks_job_users.js | 10 +- .../issue_1599_ch_user_registration.js | 6 +- .../issue_1599_pl_user_registration.js | 6 +- ...ove_users_tasks_projects_organizations.js} | 90 ++++-- tests/cypress/support/commands.js | 89 ++++-- .../cypress/support/commands_organizations.js | 183 +++++++++++ tests/cypress/support/commands_projects.js | 27 ++ tests/cypress/support/index.js | 1 + tests/cypress_canvas3d.json | 2 +- tests/cypress_cron_type.json | 2 +- 21 files changed, 692 insertions(+), 106 deletions(-) create mode 100644 tests/cypress/integration/actions_organizations/case_113_new_organization_pipeline.js rename tests/cypress/integration/{remove_users_tasks_projects.js => remove_users_tasks_projects_organizations.js} (52%) create mode 100644 tests/cypress/support/commands_organizations.js diff --git a/.github/workflows/main.yml b/.github/workflows/main.yml index f2907a9e..59484c6b 100644 --- a/.github/workflows/main.yml +++ b/.github/workflows/main.yml @@ -107,7 +107,7 @@ jobs: strategy: fail-fast: false matrix: - specs: ['actions_tasks', 'actions_tasks2', 'actions_tasks3', 'actions_objects', 'actions_objects2', 'actions_users', 'actions_projects_models', 'canvas3d_functionality', 'canvas3d_functionality_2', 'issues_prs', 'issues_prs2'] + specs: ['actions_tasks', 'actions_tasks2', 'actions_tasks3', 'actions_objects', 'actions_objects2', 'actions_users', 'actions_projects_models', 'actions_organizations', 'canvas3d_functionality', 'canvas3d_functionality_2', 'issues_prs', 'issues_prs2'] steps: - uses: actions/checkout@v2 - name: Getting SHA from the default branch @@ -193,16 +193,16 @@ jobs: npm ci if [[ ${{ github.ref }} == 'refs/heads/develop' ]]; then if [ ${{ matrix.specs }} == 'canvas3d_functionality' ] || [ ${{ matrix.specs }} == 'canvas3d_functionality_2' ]; then - npx cypress run --headed --browser chrome --config-file cypress_canvas3d.json --spec 'cypress/integration/${{ matrix.specs }}/**/*.js,cypress/integration/remove_users_tasks_projects.js' + npx cypress run --headed --browser chrome --config-file cypress_canvas3d.json --spec 'cypress/integration/${{ matrix.specs }}/**/*.js,cypress/integration/remove_users_tasks_projects_organizations.js' else - npx cypress run --browser chrome --spec 'cypress/integration/${{ matrix.specs }}/**/*.js,cypress/integration/remove_users_tasks_projects.js' + npx cypress run --browser chrome --spec 'cypress/integration/${{ matrix.specs }}/**/*.js,cypress/integration/remove_users_tasks_projects_organizations.js' fi mv ./.nyc_output/out.json ./.nyc_output/out_${{ matrix.specs }}.json else if [ ${{ matrix.specs }} == 'canvas3d_functionality' ] || [ ${{ matrix.specs }} == 'canvas3d_functionality_2' ]; then - npx cypress run --headed --browser chrome --env coverage=false --config-file cypress_canvas3d.json --spec 'cypress/integration/${{ matrix.specs }}/**/*.js,cypress/integration/remove_users_tasks_projects.js' + npx cypress run --headed --browser chrome --env coverage=false --config-file cypress_canvas3d.json --spec 'cypress/integration/${{ matrix.specs }}/**/*.js,cypress/integration/remove_users_tasks_projects_organizations.js' else - npx cypress run --browser chrome --env coverage=false --spec 'cypress/integration/${{ matrix.specs }}/**/*.js,cypress/integration/remove_users_tasks_projects.js' + npx cypress run --browser chrome --env coverage=false --spec 'cypress/integration/${{ matrix.specs }}/**/*.js,cypress/integration/remove_users_tasks_projects_organizations.js' fi fi - name: Creating a log file from "cvat" container logs diff --git a/cvat-ui/src/components/header/header.tsx b/cvat-ui/src/components/header/header.tsx index c54732af..6b9722e2 100644 --- a/cvat-ui/src/components/header/header.tsx +++ b/cvat-ui/src/components/header/header.tsx @@ -1,4 +1,4 @@ -// Copyright (C) 2020-2021 Intel Corporation +// Copyright (C) 2020-2022 Intel Corporation // // SPDX-License-Identifier: MIT @@ -266,11 +266,11 @@ function HeaderContainer(props: Props): JSX.Element { icon={organizationsFetching ? : } > {currentOrganization ? ( - } key='open_organization' onClick={() => history.push('/organization')}> + } key='open_organization' onClick={() => history.push('/organization')} className='cvat-header-menu-open-organization'> Settings ) : null} - } key='create_organization' onClick={() => history.push('/organizations/create')}>Create + } key='create_organization' onClick={() => history.push('/organizations/create')} className='cvat-header-menu-create-organization'>Create { organizationsList.length > 5 ? ( @@ -324,7 +325,7 @@ function HeaderContainer(props: Props): JSX.Element { {organizationsList.map((organization: any): JSX.Element => ( setNewOrganization(organization)} > @@ -475,13 +476,15 @@ function HeaderContainer(props: Props): JSX.Element { - + {user.username.length > 14 ? `${user.username.slice(0, 10)} ...` : user.username} { currentOrganization ? ( - {currentOrganization.slug} + + {currentOrganization.slug} + ) : null } diff --git a/cvat-ui/src/components/organization-page/member-item.tsx b/cvat-ui/src/components/organization-page/member-item.tsx index 1fcc3178..ff00d83c 100644 --- a/cvat-ui/src/components/organization-page/member-item.tsx +++ b/cvat-ui/src/components/organization-page/member-item.tsx @@ -1,4 +1,4 @@ -// Copyright (C) 2021 Intel Corporation +// Copyright (C) 2021-2022 Intel Corporation // // SPDX-License-Identifier: MIT @@ -65,6 +65,7 @@ function MemberItem(props: Props): JSX.Element { { Modal.confirm({ + className: 'cvat-modal-organization-member-remove', title: `You are removing "${username}" from this organization`, content: 'The person will not have access to the organization data anymore. Continue?', okText: 'Yes, remove', diff --git a/cvat-ui/src/components/organization-page/top-bar.tsx b/cvat-ui/src/components/organization-page/top-bar.tsx index 8b050426..ab40483f 100644 --- a/cvat-ui/src/components/organization-page/top-bar.tsx +++ b/cvat-ui/src/components/organization-page/top-bar.tsx @@ -1,4 +1,4 @@ -// Copyright (C) 2021 Intel Corporation +// Copyright (C) 2021-2022 Intel Corporation // // SPDX-License-Identifier: MIT @@ -194,6 +194,7 @@ function OrganizationTopBar(props: Props): JSX.Element { onOk: () => { dispatch(leaveOrganizationAsync(organizationInstance)); }, + className: 'cvat-modal-organization-leave-confirm', content: ( <> Please, confirm leaving the organization @@ -260,6 +261,7 @@ function OrganizationTopBar(props: Props): JSX.Element { { setVisibleInviteModal(false); @@ -294,6 +296,7 @@ function OrganizationTopBar(props: Props): JSX.Element { + +context('New organization pipeline.', () => { + const caseId = '113'; + const firstUserName = 'Firstuser'; + const secondUserName = 'Seconduser'; + const thirdUserName = 'Thirduser'; + + const firstUser = { + firstName: `${firstUserName} fitstname`, + lastName: `${firstUserName} lastname`, + emailAddr: `${firstUserName.toLowerCase()}@local.local`, + password: 'UfdU21!dds', + }; + const secondUser = { + firstName: `${secondUserName} fitstname`, + lastName: `${secondUserName} lastname`, + emailAddr: `${secondUserName.toLowerCase()}@local.local`, + password: 'UfdU21!dds', + }; + const thirdUser = { + firstName: `${thirdUserName} fitstname`, + lastName: `${thirdUserName} lastname`, + emailAddr: `${thirdUserName.toLowerCase()}@local.local`, + password: 'Fv5Df3#f55g', + }; + const organizationParams = { + shortName: 'TestOrganization', + fullName: 'Organization full name. Only for test.', + description: 'This organization was created to test the functionality.', + email: 'testorganization@local.local', + phoneNumber: '+70000000000', + location: 'Country, State, Address, 000000', + }; + const project = { + name: `Project case ${caseId}`, + label: 'car', + attrName: 'color', + attrVaue: 'red', + multiAttrParams: false, + }; + + const labelName = `Case ${caseId}`; + const taskName = `New annotation task for ${labelName}`; + const newTaskName = labelName; + const attrName = `Attr for ${labelName}`; + const textDefaultValue = 'Some default value for type Text'; + const imagesCount = 1; + const imageFileName = `image_${labelName.replace(' ', '_').toLowerCase()}`; + const width = 800; + const height = 800; + const posX = 10; + const posY = 10; + const color = 'gray'; + const archiveName = `${imageFileName}.zip`; + const archivePath = `cypress/fixtures/${archiveName}`; + const imagesFolder = `cypress/fixtures/${imageFileName}`; + const directoryToArchive = imagesFolder; + let taskID; + let jobID; + + const createCuboidShape2Points = { + points: 'From rectangle', + type: 'Shape', + labelName, + firstX: 250, + firstY: 350, + secondX: 350, + secondY: 450, + }; + + function capitalizeEmail(email) { + return email.split('@').map((part) => `${part.toUpperCase()[0]}${part.slice(1)}`).join('@'); + } + + before(() => { + cy.imageGenerator( + imagesFolder, + imageFileName, + width, + height, + color, + posX, + posY, + project.label, + imagesCount, + ); + cy.createZipArchive(directoryToArchive, archivePath); + + cy.visit('/'); + cy.goToRegisterPage(); + cy.userRegistration( + secondUser.firstName, + secondUser.lastName, + secondUserName, + secondUser.emailAddr, + secondUser.password, + ); + cy.logout(secondUserName); + + cy.goToRegisterPage(); + cy.userRegistration( + thirdUser.firstName, + thirdUser.lastName, + thirdUserName, + thirdUser.emailAddr, + thirdUser.password, + ); + cy.logout(thirdUserName); + + cy.goToRegisterPage(); + cy.userRegistration( + firstUser.firstName, + firstUser.lastName, + firstUserName, + firstUser.emailAddr, + firstUser.password, + ); + }); + + beforeEach(() => { + Cypress.Cookies.preserveOnce('sessionid', 'csrftoken'); + }); + + after(() => { + cy.logout(thirdUserName); + cy.getAuthKey().then((authKey) => { + cy.deleteUsers(authKey, [thirdUserName]); + cy.deleteTasks(authKey, [newTaskName]); + cy.deleteProjects(authKey, [project.name]); + cy.deleteOrganizations(authKey, [organizationParams.shortName]); + }); + }); + + describe(`Testing case "${caseId}"`, () => { + it('The first user creates an organization and activates it.', () => { + cy.createOrganization(organizationParams); + cy.activateOrganization(organizationParams.shortName); + }); + + it('Open the organization settings. Invite members.', () => { + cy.openOrganization(organizationParams.shortName); + cy.checkOrganizationParams(organizationParams); + cy.checkOrganizationMembers(1, [firstUserName]); + const membersToInvite = [ + { + email: capitalizeEmail(secondUser.emailAddr), + role: 'Worker', + }, + { + email: thirdUser.emailAddr, + role: 'Worker', + }, + ]; + cy.inviteMembersToOrganization(membersToInvite); + cy.checkOrganizationMembers(3, [firstUserName, secondUserName, thirdUserName]); + }); + + it('Create a project, create a task. Deactivate organization.', () => { + cy.goToProjectsList(); + cy.createProjects( + project.name, + project.label, + project.attrName, + project.attrVaue, + project.multiAttrParams, + ); + cy.goToTaskList(); + cy.createAnnotationTask(taskName, labelName, attrName, textDefaultValue, archiveName); + cy.openTask(taskName); + cy.assignTaskToUser(secondUserName); + cy.deactivateOrganization(); + }); + + it('The project, the task are invisible now.', () => { + cy.contains('.cvat-item-task-name', taskName).should('not.exist'); + cy.goToProjectsList(); + cy.contains('.cvat-projects-project-item-title', project.name).should('not.exist'); + }); + + it('Admin tries to leave from organization (not successfully because he is not a member of it).', () => { + cy.logout(firstUserName); + cy.login(); + cy.activateOrganization(organizationParams.shortName); + cy.openOrganization(organizationParams.shortName); + cy.contains('button', 'Leave organization').should('be.visible').click(); + cy.get('.cvat-modal-organization-leave-confirm') + .should('be.visible') + .within(() => { + cy.contains('button', 'Leave').click(); + }); + cy.get('.cvat-notification-notice-leave-organization-failed').should('exist'); + cy.closeNotification('.cvat-notification-notice-leave-organization-failed'); + }); + + it('The second user login. The user is able to see the organization, can\'t see the task.', () => { + cy.logout(); + cy.login(secondUserName, secondUser.password); + cy.checkOrganizationExists(organizationParams.shortName); + cy.contains('.cvat-item-task-name', taskName).should('not.exist'); + }); + + it('The second user activates the organization, can\'t see the project because it is not assigned to him.', () => { + cy.activateOrganization(organizationParams.shortName); + cy.goToProjectsList(); + cy.contains('.cvat-projects-project-item-title', project.name).should('not.exist'); + }); + + it('The first user login. Assigne the project to the second user.', () => { + cy.logout(secondUserName); + cy.login(firstUserName, firstUser.password); + cy.activateOrganization(organizationParams.shortName); + cy.goToProjectsList(); + cy.openProject(project.name); + cy.assignProjectToUser(secondUserName); + }); + + it('The second user login. Now he sees the project and can open it.', () => { + cy.logout(firstUserName); + cy.login(secondUserName, secondUser.password); + cy.activateOrganization(organizationParams.shortName); + cy.goToProjectsList(); + cy.openProject(project.name); + }); + + it('Open the task, assign one of jobs to the third user. Rename the task.', () => { + cy.goToTaskList(); + cy.openTask(taskName); + cy.assignJobToUser(0, thirdUserName); + cy.renameTask(taskName, newTaskName); + cy.url().then((url) => { + taskID = Number(url.split('/').slice(-1)[0]); + }); + cy.getJobNum(0).then(($jobID) => { + jobID = $jobID; + }); + }); + + it('Logout, the third user login. The user does not see the project, the task. The user can\'t open the job using direct link.', () => { + cy.logout(secondUserName); + cy.login(thirdUserName, thirdUser.password); + cy.contains('.cvat-item-task-name', taskName).should('not.exist'); + cy.goToProjectsList(); + cy.contains('.cvat-projects-project-item-title', project.name).should('not.exist'); + cy.visit(`/tasks/${taskID}/jobs/${jobID}`); + cy.get('.cvat-canvas-container').should('not.exist'); + cy.get('.cvat-notification-notice-fetch-job-failed').should('be.visible'); + cy.closeNotification('.cvat-notification-notice-fetch-job-failed'); + }); + + it('The third user activates the organization. Now can open the job using direct link. Create an object, save annotations.', () => { + cy.activateOrganization(organizationParams.shortName); + cy.visit(`/tasks/${taskID}/jobs/${jobID}`); + cy.get('.cvat-canvas-container').should('exist'); + cy.createCuboid(createCuboidShape2Points); + cy.saveJob(); + }); + + it('The owner of the organization removes the second user from it.', () => { + cy.logout(thirdUserName); + cy.login(firstUserName, firstUser.password); + cy.activateOrganization(organizationParams.shortName); + cy.openOrganization(organizationParams.shortName); + cy.removeMemberFromOrganization(secondUserName); + cy.checkOrganizationMembers(2, [firstUserName, thirdUserName]); + }); + + it('The organization, project, task is no longer available to the second user.', () => { + cy.logout(firstUserName); + cy.login(secondUserName, secondUser.password); + cy.checkOrganizationExists(organizationParams.shortName, false); + cy.contains('.cvat-item-task-name', taskName).should('not.exist'); + cy.goToProjectsList(); + cy.contains('.cvat-projects-project-item-title', project.name).should('not.exist'); + }); + + it('Logout. Remove the first, the second user (deletion occurs from user admin).', () => { + cy.logout(secondUserName); + cy.getAuthKey().then((authKey) => { + cy.deleteUsers(authKey, [firstUserName, secondUserName]); + }); + }); + + it('Login as the third user. The organization page can be opened. The job can be opened.', () => { + cy.login(thirdUserName, thirdUser.password); + cy.activateOrganization(organizationParams.shortName); + cy.visit('/organization'); + cy.checkOrganizationParams(organizationParams); + cy.checkOrganizationMembers(1, [thirdUserName]); + cy.visit(`/tasks/${taskID}/jobs/${jobID}`); + cy.get('.cvat-canvas-container').should('exist'); + cy.get('.cvat_canvas_shape_cuboid').should('be.visible'); + }); + }); +}); diff --git a/tests/cypress/integration/actions_projects_models/registration_involved/base_actions_project_task_user.js b/tests/cypress/integration/actions_projects_models/registration_involved/base_actions_project_task_user.js index d669b395..9b46a40b 100644 --- a/tests/cypress/integration/actions_projects_models/registration_involved/base_actions_project_task_user.js +++ b/tests/cypress/integration/actions_projects_models/registration_involved/base_actions_project_task_user.js @@ -1,4 +1,4 @@ -// Copyright (C) 2020-2021 Intel Corporation +// Copyright (C) 2020-2022 Intel Corporation // // SPDX-License-Identifier: MIT @@ -58,7 +58,9 @@ context('Base actions on the project', () => { }); after(() => { - cy.deletingRegisteredUsers([userName]); + cy.getAuthKey().then((authKey) => { + cy.deleteUsers(authKey, [userName]); + }); }); describe('Testing "Base actions on the project"', () => { diff --git a/tests/cypress/integration/actions_tasks/registration_involved/case_39_issue_2572_rename_task.js b/tests/cypress/integration/actions_tasks/registration_involved/case_39_issue_2572_rename_task.js index b9fd4dee..6a52c1e2 100644 --- a/tests/cypress/integration/actions_tasks/registration_involved/case_39_issue_2572_rename_task.js +++ b/tests/cypress/integration/actions_tasks/registration_involved/case_39_issue_2572_rename_task.js @@ -1,4 +1,4 @@ -// Copyright (C) 2021 Intel Corporation +// Copyright (C) 2021-2022 Intel Corporation // // SPDX-License-Identifier: MIT @@ -56,9 +56,11 @@ context('Rename a task.', () => { }); after(() => { - cy.deletingRegisteredUsers([secondUserName]); - cy.login(); - cy.deleteTask(newTaskNameSecondUser); + cy.logout(secondUserName); + cy.getAuthKey().then((authKey) => { + cy.deleteUsers(authKey, [secondUserName]); + cy.deleteTasks(authKey, [newTaskNameSecondUser]); + }); }); describe(`Testing "${labelName}". Issue 2572.`, () => { @@ -72,9 +74,7 @@ context('Rename a task.', () => { it('The second user tries to rename the task. Success.', () => { cy.login(secondUserName, secondUser.password); cy.openTask(newTaskName); - renameTask(newTaskName, '{leftarrow}{leftarrow}3{Enter}'); - cy.contains('.cvat-task-details-task-name', newTaskNameSecondUser).should('exist'); - cy.logout(secondUserName); + cy.renameTask(newTaskName, newTaskNameSecondUser); }); }); }); diff --git a/tests/cypress/integration/actions_tasks/registration_involved/case_69_filters_sorting_jobs.js b/tests/cypress/integration/actions_tasks/registration_involved/case_69_filters_sorting_jobs.js index 2424f13c..ee8e2fdb 100644 --- a/tests/cypress/integration/actions_tasks/registration_involved/case_69_filters_sorting_jobs.js +++ b/tests/cypress/integration/actions_tasks/registration_involved/case_69_filters_sorting_jobs.js @@ -121,9 +121,10 @@ context('Filtering, sorting jobs.', () => { after(() => { cy.logout(); - cy.deletingRegisteredUsers([secondUserName]); - cy.login(); - cy.deleteTask(taskName); + cy.getAuthKey().then((authKey) => { + cy.deleteUsers(authKey, [secondUserName]); + cy.deleteTasks(authKey, [taskName]); + }); }); describe(`Testing "${labelName}".`, () => { diff --git a/tests/cypress/integration/actions_users/registration_involved/case_28_review_pipeline_feature.js b/tests/cypress/integration/actions_users/registration_involved/case_28_review_pipeline_feature.js index d53f7917..ca134e26 100644 --- a/tests/cypress/integration/actions_users/registration_involved/case_28_review_pipeline_feature.js +++ b/tests/cypress/integration/actions_users/registration_involved/case_28_review_pipeline_feature.js @@ -1,4 +1,4 @@ -// Copyright (C) 2020-2021 Intel Corporation +// Copyright (C) 2020-2022 Intel Corporation // // SPDX-License-Identifier: MIT @@ -137,11 +137,11 @@ context('Review pipeline feature', () => { }); after(() => { - cy.login(); - cy.goToTaskList(); - cy.deleteTask(taskName); cy.logout(); - cy.deletingRegisteredUsers([secondUserName, thirdUserName]); + cy.getAuthKey().then((authKey) => { + cy.deleteUsers(authKey, [secondUserName, thirdUserName]); + cy.deleteTasks(authKey, [taskName]); + }); }); describe(`Testing "${labelName}"`, () => { @@ -193,7 +193,6 @@ context('Review pipeline feature', () => { cy.login(); cy.openTask(taskName); cy.assignJobToUser(0, secondUserName); - cy.logout(); }); /* FIXME: Second user has access to a job inside the task. Need to redesign openTaskJob. diff --git a/tests/cypress/integration/actions_users/registration_involved/case_2_register_user_change_pass.js b/tests/cypress/integration/actions_users/registration_involved/case_2_register_user_change_pass.js index 75b1f2c5..c78d5baf 100644 --- a/tests/cypress/integration/actions_users/registration_involved/case_2_register_user_change_pass.js +++ b/tests/cypress/integration/actions_users/registration_involved/case_2_register_user_change_pass.js @@ -1,4 +1,4 @@ -// Copyright (C) 2020-2021 Intel Corporation +// Copyright (C) 2020-2022 Intel Corporation // // SPDX-License-Identifier: MIT @@ -37,7 +37,9 @@ context('Register user, change password, login with new password', () => { after(() => { cy.get('.cvat-modal-change-password').find('[aria-label="Close"]').click(); cy.logout(userName); - cy.deletingRegisteredUsers([userName]); + cy.getAuthKey().then((authKey) => { + cy.deleteUsers(authKey, [userName]); + }); }); describe(`Testing "Case ${caseId}"`, () => { diff --git a/tests/cypress/integration/actions_users/registration_involved/case_4_assign_taks_job_users.js b/tests/cypress/integration/actions_users/registration_involved/case_4_assign_taks_job_users.js index 4c1a48a2..82d9e7ae 100644 --- a/tests/cypress/integration/actions_users/registration_involved/case_4_assign_taks_job_users.js +++ b/tests/cypress/integration/actions_users/registration_involved/case_4_assign_taks_job_users.js @@ -1,4 +1,4 @@ -// Copyright (C) 2020-2021 Intel Corporation +// Copyright (C) 2020-2022 Intel Corporation // // SPDX-License-Identifier: MIT @@ -61,11 +61,11 @@ context('Multiple users. Assign task, job. Deactivating users.', () => { }); after(() => { - cy.goToTaskList(); - cy.deleteTask(taskName); - cy.deleteTask(secondTaskName); cy.logout(); - cy.deletingRegisteredUsers([secondUserName, thirdUserName]); + cy.getAuthKey().then(($authKey) => { + cy.deleteUsers($authKey, [secondUserName, thirdUserName]); + cy.deleteTasks($authKey, [taskName, secondTaskName]); + }); }); describe(`Testing case "${caseId}"`, () => { diff --git a/tests/cypress/integration/actions_users/registration_involved/issue_1599_ch_user_registration.js b/tests/cypress/integration/actions_users/registration_involved/issue_1599_ch_user_registration.js index 37842cee..4cf06d98 100644 --- a/tests/cypress/integration/actions_users/registration_involved/issue_1599_ch_user_registration.js +++ b/tests/cypress/integration/actions_users/registration_involved/issue_1599_ch_user_registration.js @@ -1,4 +1,4 @@ -// Copyright (C) 2020-2021 Intel Corporation +// Copyright (C) 2020-2022 Intel Corporation // // SPDX-License-Identifier: MIT @@ -18,7 +18,9 @@ context('Issue 1599 (Chinese alphabet).', () => { after(() => { cy.logout(userName); - cy.deletingRegisteredUsers([userName]); + cy.getAuthKey().then((authKey) => { + cy.deleteUsers(authKey, [userName]); + }); }); describe('User registration using the Chinese alphabet.', () => { diff --git a/tests/cypress/integration/actions_users/registration_involved/issue_1599_pl_user_registration.js b/tests/cypress/integration/actions_users/registration_involved/issue_1599_pl_user_registration.js index e0605bf9..3abbdfb7 100644 --- a/tests/cypress/integration/actions_users/registration_involved/issue_1599_pl_user_registration.js +++ b/tests/cypress/integration/actions_users/registration_involved/issue_1599_pl_user_registration.js @@ -1,4 +1,4 @@ -// Copyright (C) 2020-2021 Intel Corporation +// Copyright (C) 2020-2022 Intel Corporation // // SPDX-License-Identifier: MIT @@ -18,7 +18,9 @@ context('Issue 1599 (Polish alphabet).', () => { after(() => { cy.logout(userName); - cy.deletingRegisteredUsers([userName]); + cy.getAuthKey().then((authKey) => { + cy.deleteUsers(authKey, [userName]); + }); }); describe('User registration using the Polish alphabet.', () => { diff --git a/tests/cypress/integration/remove_users_tasks_projects.js b/tests/cypress/integration/remove_users_tasks_projects_organizations.js similarity index 52% rename from tests/cypress/integration/remove_users_tasks_projects.js rename to tests/cypress/integration/remove_users_tasks_projects_organizations.js index 87c47092..913b0e53 100644 --- a/tests/cypress/integration/remove_users_tasks_projects.js +++ b/tests/cypress/integration/remove_users_tasks_projects_organizations.js @@ -1,4 +1,4 @@ -// Copyright (C) 2020-2021 Intel Corporation +// Copyright (C) 2020-2022 Intel Corporation // // SPDX-License-Identifier: MIT @@ -6,7 +6,7 @@ let authKey = ''; -describe('Delete users and tasks created during the test run.', () => { +describe('Delete users, tasks, projects, organizations created during the tests run.', () => { it('Get token', () => { cy.request({ method: 'POST', @@ -16,45 +16,45 @@ describe('Delete users and tasks created during the test run.', () => { email: Cypress.env('email'), password: Cypress.env('password'), }, - }).then(async (response) => { - authKey = await response['body']['key']; + }).then((response) => { + authKey = response.body.key; }); }); - it('Get a list of users and delete all except id:1', () => { + + it('Get a list of tasks and delete them all', () => { cy.request({ - url: '/api/v1/users', + url: '/api/v1/tasks?page_size=1000', headers: { Authorization: `Token ${authKey}`, }, - }).then(async (response) => { - const responceResult = await response['body']['results']; - for (let user of responceResult) { - let userId = user['id']; - if (userId !== 1) { - cy.request({ - method: 'DELETE', - url: `/api/v1/users/${userId}`, - headers: { - Authorization: `Token ${authKey}`, - }, - }); - } + }).then((response) => { + const responseResult = response.body.results; + for (const task of responseResult) { + const { id } = task; + cy.request({ + method: 'DELETE', + url: `/api/v1/tasks/${id}`, + headers: { + Authorization: `Token ${authKey}`, + }, + }); } }); }); - it('Get a list of tasks and delete them all', () => { + + it('Get a list of projects and delete them all', () => { cy.request({ - url: '/api/v1/tasks?page_size=1000', + url: '/api/v1/projects?page_size=all', headers: { Authorization: `Token ${authKey}`, }, - }).then(async (response) => { - const responceResult = await response['body']['results']; - for (let tasks of responceResult) { - let taskId = tasks['id']; + }).then((response) => { + const responseResult = response.body.results; + for (const project of responseResult) { + const { id } = project; cy.request({ method: 'DELETE', - url: `/api/v1/tasks/${taskId}`, + url: `/api/v1/projects/${id}`, headers: { Authorization: `Token ${authKey}`, }, @@ -62,19 +62,20 @@ describe('Delete users and tasks created during the test run.', () => { } }); }); - it('Get a list of projects and delete them all', () => { + + it('Get a list of organizations and delete them all', () => { cy.request({ - url: '/api/v1/projects?page_size=all', + url: '/api/v1/organizations?page_size=all', headers: { Authorization: `Token ${authKey}`, }, - }).then(async (response) => { - const responceResult = await response['body']['results']; - for (let tasks of responceResult) { - let taskId = tasks['id']; + }).then((response) => { + const responseResult = response.body; + for (const org of responseResult) { + const { id } = org; cy.request({ method: 'DELETE', - url: `/api/v1/projects/${taskId}`, + url: `/api/v1/organizations/${id}`, headers: { Authorization: `Token ${authKey}`, }, @@ -82,4 +83,27 @@ describe('Delete users and tasks created during the test run.', () => { } }); }); + + it('Get a list of users and delete all except id:1', () => { + cy.request({ + url: '/api/v1/users', + headers: { + Authorization: `Token ${authKey}`, + }, + }).then((response) => { + const responseResult = response.body.results; + for (const user of responseResult) { + const { id } = user; + if (id !== 1) { + cy.request({ + method: 'DELETE', + url: `/api/v1/users/${id}`, + headers: { + Authorization: `Token ${authKey}`, + }, + }); + } + } + }); + }); }); diff --git a/tests/cypress/support/commands.js b/tests/cypress/support/commands.js index c701d198..82ce94ce 100644 --- a/tests/cypress/support/commands.js +++ b/tests/cypress/support/commands.js @@ -16,11 +16,11 @@ require('cy-verify-downloads').addCustomCommand(); let selectedValueGlobal = ''; -Cypress.Commands.add('login', (username = Cypress.env('user'), password = Cypress.env('password')) => { +Cypress.Commands.add('login', (username = Cypress.env('user'), password = Cypress.env('password'), page = 'tasks') => { cy.get('[placeholder="Username"]').type(username); cy.get('[placeholder="Password"]').type(password); cy.get('[type="submit"]').click(); - cy.url().should('match', /\/tasks$/); + 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) { @@ -31,7 +31,7 @@ Cypress.Commands.add('login', (username = Cypress.env('user'), password = Cypres Cypress.Commands.add('logout', (username = Cypress.env('user')) => { cy.get('.cvat-right-header').within(() => { - cy.get('.cvat-header-menu-user-dropdown').should('have.text', username).trigger('mouseover', { which: 1 }); + cy.get('.cvat-header-menu-user-dropdown-user').should('have.text', username).trigger('mouseover'); }); cy.get('span[aria-label="logout"]').click(); cy.url().should('include', '/auth/login'); @@ -52,7 +52,7 @@ Cypress.Commands.add('userRegistration', (firstName, lastName, userName, emailAd } }); -Cypress.Commands.add('deletingRegisteredUsers', (accountToDelete) => { +Cypress.Commands.add('getAuthKey', () => { cy.request({ method: 'POST', url: '/api/v1/auth/login', @@ -61,31 +61,32 @@ Cypress.Commands.add('deletingRegisteredUsers', (accountToDelete) => { email: Cypress.env('email'), password: Cypress.env('password'), }, - }).then((response) => { - const authKey = response.body.key; - cy.request({ - url: '/api/v1/users?page_size=all', - headers: { - Authorization: `Token ${authKey}`, - }, - }).then((_response) => { - const responceResult = _response.body.results; - for (const user of responceResult) { - const userId = user.id; - const userName = user.username; - for (const account of accountToDelete) { - if (userName === account) { - cy.request({ - method: 'DELETE', - url: `/api/v1/users/${userId}`, - headers: { - Authorization: `Token ${authKey}`, - }, - }); - } + }); +}); + +Cypress.Commands.add('deleteUsers', (authResponse, accountsToDelete) => { + const authKey = authResponse.body.key; + cy.request({ + url: '/api/v1/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/v1/users/${id}`, + headers: { + Authorization: `Token ${authKey}`, + }, + }); } } - }); + } }); }); @@ -134,6 +135,32 @@ Cypress.Commands.add('checkUserStatuses', (authKey, userName, staffStatus, super }); }); +Cypress.Commands.add('deleteTasks', (authResponse, tasksToDelete) => { + const authKey = authResponse.body.key; + cy.request({ + url: '/api/v1/tasks?page_size=all', + headers: { + Authorization: `Token ${authKey}`, + }, + }).then((_response) => { + const responceResult = _response.body.results; + for (const task of responceResult) { + const { id, name } = task; + for (const taskToDelete of tasksToDelete) { + if (name === taskToDelete) { + cy.request({ + method: 'DELETE', + url: `/api/v1/tasks/${id}`, + headers: { + Authorization: `Token ${authKey}`, + }, + }); + } + } + } + }); +}); + Cypress.Commands.add( 'createAnnotationTask', ( @@ -802,6 +829,14 @@ Cypress.Commands.add('exportTask', ({ cy.closeNotification('.cvat-notification-notice-export-task-start'); }); +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).clear().type(`${newName}{Enter}`); + cy.contains('.cvat-task-details-task-name', newName).should('exist'); +}); + Cypress.Commands.add('shapeRotate', (shape, x, y, expectedRotateDeg, pressShift = false) => { cy.get(shape) .trigger('mousemove') diff --git a/tests/cypress/support/commands_organizations.js b/tests/cypress/support/commands_organizations.js new file mode 100644 index 00000000..e3df85c4 --- /dev/null +++ b/tests/cypress/support/commands_organizations.js @@ -0,0 +1,183 @@ +// Copyright (C) 2022 Intel Corporation +// +// SPDX-License-Identifier: MIT + +/// + +Cypress.Commands.add('createOrganization', (organizationParams) => { + cy.get('.cvat-header-menu-user-dropdown').trigger('mouseover'); + cy.get('.cvat-header-menu') + .should('be.visible') + .find('[role="menuitem"]') + .filter(':contains("Organization")') + .trigger('mouseover'); + cy.get('.cvat-header-menu-create-organization') + .should('be.visible') + .click(); + cy.url().should('contain', '/organizations/create'); + cy.get('.cvat-create-organization-form').should('be.visible').within(() => { + cy.get('#slug').type(organizationParams.shortName); + cy.get('#name').type(organizationParams.fullName); + cy.get('#description').type(organizationParams.description); + cy.get('#email').type(organizationParams.email); + cy.get('#phoneNumber').type(organizationParams.phoneNumber); + cy.get('#location').type(organizationParams.location); + cy.intercept('POST', '/api/v1/organizations**').as('createOrganizations'); + cy.get('[type="submit"]').click(); + cy.wait('@createOrganizations').its('response.statusCode').should('equal', 201); + }); +}); + +Cypress.Commands.add('deleteOrganizations', (authResponse, otrganizationsToDelete) => { + const authKey = authResponse.body.key; + cy.request({ + url: '/api/v1/organizations?page_size=all', + headers: { + Authorization: `Token ${authKey}`, + }, + }).then((_response) => { + const responceResult = _response.body; + for (const organization of responceResult) { + const { id, slug } = organization; + for (const organizationToDelete of otrganizationsToDelete) { + if (slug === organizationToDelete) { + cy.request({ + method: 'DELETE', + url: `/api/v1/organizations/${id}`, + headers: { + Authorization: `Token ${authKey}`, + }, + }); + } + } + } + }); +}); + +Cypress.Commands.add('activateOrganization', (organizationShortName) => { + cy.get('.cvat-header-menu-user-dropdown').trigger('mouseover'); + cy.get('.ant-dropdown') + .should('be.visible') + .not('ant-dropdown-hidden') + .find('[role="menuitem"]') + .filter(':contains("Organization")') + .trigger('mouseover'); + cy.contains('.cvat-header-menu-organization-item', organizationShortName).click(); + cy.get('.cvat-header-menu-user-dropdown').should('be.visible'); + cy.get('.cvat-header-menu-user-dropdown-organization') + .should('exist') + .and('have.text', organizationShortName); +}); + +Cypress.Commands.add('deactivateOrganization', () => { + cy.get('.cvat-header-menu-user-dropdown').trigger('mouseover'); + cy.get('.ant-dropdown') + .should('be.visible') + .not('ant-dropdown-hidden') + .find('[role="menuitem"]') + .filter(':contains("Organization")') + .trigger('mouseover'); + cy.contains('.cvat-header-menu-organization-item', 'Personal workspace').click(); + cy.get('.cvat-header-menu-user-dropdown').should('be.visible'); + cy.get('.cvat-header-menu-user-dropdown-organization').should('not.exist'); +}); + +Cypress.Commands.add('openOrganization', (organizationShortName) => { + cy.get('.cvat-header-menu-user-dropdown').trigger('mouseover'); + cy.get('.ant-dropdown') + .should('be.visible') + .not('ant-dropdown-hidden') + .find('[role="menuitem"]') + .filter(':contains("Organization")') + .trigger('mouseover'); + cy.get('.cvat-header-menu-active-organization-item') + .should('have.text', organizationShortName); + cy.get('.cvat-header-menu-open-organization') + .should('be.visible') + .click(); + cy.get('.cvat-organization-page').should('exist').and('be.visible'); +}); + +Cypress.Commands.add('checkOrganizationExists', (organizationShortName, shouldExist = true) => { + cy.get('.cvat-header-menu-user-dropdown').trigger('mouseover'); + cy.get('.ant-dropdown') + .should('be.visible') + .not('ant-dropdown-hidden') + .find('[role="menuitem"]') + .filter(':contains("Organization")') + .trigger('mouseover'); + if (shouldExist) { + cy.contains('.cvat-header-menu-organization-item', organizationShortName) + .should('exist') + .trigger('mouseout') + .should('be.hidden'); + } else { + cy.contains('.cvat-header-menu-organization-item', organizationShortName).should('not.exist'); + cy.get('.cvat-header-menu-active-organization-item').trigger('mouseout').should('be.hidden'); + } +}); + +Cypress.Commands.add('checkOrganizationParams', (organizationParams) => { + cy.get('.cvat-organization-top-bar-descriptions').then((orgDescriptions) => { + const orgDescText = orgDescriptions.text(); + expect(orgDescText).contain(organizationParams.shortName); + expect(orgDescText).contain(organizationParams.fullName); + expect(orgDescText).contain(organizationParams.description); + }); + cy.get('.cvat-organization-top-bar-contacts').then((orgContacts) => { + const orgContactsText = orgContacts.text(); + expect(orgContactsText).contain(organizationParams.email); + expect(orgContactsText).contain(organizationParams.phoneNumber); + expect(orgContactsText).contain(organizationParams.location); + }); +}); + +Cypress.Commands.add('checkOrganizationMembers', (expectedMembersCount, expectedOrganizationMembers) => { + const orgMembersUserameText = []; + cy.get('.cvat-organization-member-item').should('have.length', expectedMembersCount); + cy.get('.cvat-organization-member-item-username').each((el) => { + orgMembersUserameText.push(el.text()); + }).then(() => { + expect(orgMembersUserameText).to.include.members(expectedOrganizationMembers); + }); +}); + +Cypress.Commands.add('inviteMembersToOrganization', (members) => { + cy.get('.cvat-organization-top-bar-buttons-block').should('exist'); + cy.contains('button', 'Invite members').click(); + cy.get('.cvat-organization-invitation-modal').should('be.visible'); + let addedMembers = 0; + for (const el of members) { + cy.get('.cvat-organization-invitation-field-email') + .last() + .find('input') + .type(el.email) + .should('have.value', el.email); + cy.get('.cvat-organization-invitation-field-email') + .find('[aria-label="check-circle"]') + .should('exist'); + cy.get('.cvat-organization-invitation-field-role').last().click(); + cy.get('.ant-select-dropdown') + .should('be.visible') + .not('.ant-select-dropdown-hidden') + .find(`[title=${el.role}]`) + .click(); + addedMembers++; + if (addedMembers !== Object.keys(members).length) { + cy.contains('button', 'Invite more').click(); + } + } + cy.get('.cvat-organization-invitation-modal') + .contains('button', 'OK') + .click(); +}); + +Cypress.Commands.add('removeMemberFromOrganization', (username) => { + cy.contains('.cvat-organization-member-item-username', username) + .parents('.cvat-organization-member-item') + .find('.cvat-organization-member-item-remove') + .click(); + cy.get('.cvat-modal-organization-member-remove') + .contains('button', 'Yes, remove') + .click(); +}); diff --git a/tests/cypress/support/commands_projects.js b/tests/cypress/support/commands_projects.js index 55bae092..e0544c38 100644 --- a/tests/cypress/support/commands_projects.js +++ b/tests/cypress/support/commands_projects.js @@ -7,6 +7,7 @@ Cypress.Commands.add('goToProjectsList', () => { cy.get('[value="projects"]').click(); cy.url().should('include', '/projects'); + cy.get('.cvat-spinner').should('not.exist'); }); Cypress.Commands.add( @@ -37,6 +38,32 @@ Cypress.Commands.add( }, ); +Cypress.Commands.add('deleteProjects', (authResponse, projectsToDelete) => { + const authKey = authResponse.body.key; + cy.request({ + url: '/api/v1/projects?page_size=all', + headers: { + Authorization: `Token ${authKey}`, + }, + }).then((_response) => { + const responceResult = _response.body.results; + for (const project of responceResult) { + const { id, name } = project; + for (const projectToDelete of projectsToDelete) { + if (name === projectToDelete) { + cy.request({ + method: 'DELETE', + url: `/api/v1/projects/${id}`, + headers: { + Authorization: `Token ${authKey}`, + }, + }); + } + } + } + }); +}); + Cypress.Commands.add('openProject', (projectName) => { cy.contains(projectName).click({ force: true }); cy.get('.cvat-project-details').should('exist'); diff --git a/tests/cypress/support/index.js b/tests/cypress/support/index.js index dd649730..62aaa768 100644 --- a/tests/cypress/support/index.js +++ b/tests/cypress/support/index.js @@ -9,6 +9,7 @@ require('./commands_canvas3d'); require('./commands_filters_feature'); require('./commands_models'); require('./commands_opencv'); +require('./commands_organizations'); require('@cypress/code-coverage/support'); before(() => { diff --git a/tests/cypress_canvas3d.json b/tests/cypress_canvas3d.json index d965f768..b6a0bfc1 100644 --- a/tests/cypress_canvas3d.json +++ b/tests/cypress_canvas3d.json @@ -14,6 +14,6 @@ "auth_page.js", "canvas3d_functionality/*.js", "canvas3d_functionality_2/*.js", - "remove_users_tasks_projects.js" + "remove_users_tasks_projects_organizations.js" ] } diff --git a/tests/cypress_cron_type.json b/tests/cypress_cron_type.json index c8d01f82..6565c36e 100644 --- a/tests/cypress_cron_type.json +++ b/tests/cypress_cron_type.json @@ -21,6 +21,6 @@ "actions_projects_models/*.js", "actions_users/*.js", "email_system/*.js", - "remove_users_tasks_projects.js" + "remove_users_tasks_projects_organizations.js" ] }