From dbffa03ffae4900975568adb0a7a4c2b70ba07f4 Mon Sep 17 00:00:00 2001 From: Avi Shah Date: Tue, 15 Oct 2024 14:00:12 +0530 Subject: [PATCH] e2e test for organization teams page --- .../organization-invitation-list/index.hbs | 6 +- .../add-team-member/index.hbs | 2 +- .../add-team-project/index.hbs | 6 +- .../organization-team/create-team/index.hbs | 1 + .../organization-team/details/index.hbs | 1 + .../organization-team/overview/index.hbs | 2 + cypress/support/api.routes.ts | 36 ++ cypress/support/application.routes.ts | 1 + cypress/tests/organization-teams.spec.ts | 476 ++++++++++++++++++ 9 files changed, 528 insertions(+), 3 deletions(-) create mode 100644 cypress/tests/organization-teams.spec.ts diff --git a/app/components/organization-invitation-list/index.hbs b/app/components/organization-invitation-list/index.hbs index 7b43b87f11..2455e7cd65 100644 --- a/app/components/organization-invitation-list/index.hbs +++ b/app/components/organization-invitation-list/index.hbs @@ -27,7 +27,11 @@ - + {{#if r.columnValue.component}} {{#let (component r.columnValue.component) as |Component|}} diff --git a/app/components/organization-team/add-team-member/index.hbs b/app/components/organization-team/add-team-member/index.hbs index 7ab30958c5..4245b0b52d 100644 --- a/app/components/organization-team/add-team-member/index.hbs +++ b/app/components/organization-team/add-team-member/index.hbs @@ -57,7 +57,7 @@ - + {{#if r.columnValue.component}} {{#let (component r.columnValue.component) as |CheckBox|}} diff --git a/app/components/organization-team/add-team-project/index.hbs b/app/components/organization-team/add-team-project/index.hbs index 1dde0ace05..d5e3373f63 100644 --- a/app/components/organization-team/add-team-project/index.hbs +++ b/app/components/organization-team/add-team-project/index.hbs @@ -57,7 +57,11 @@ - + {{#if r.columnValue.component}} {{#let (component r.columnValue.component) as |Component|}} diff --git a/app/components/organization-team/create-team/index.hbs b/app/components/organization-team/create-team/index.hbs index f55ed93e4c..25b7af623b 100644 --- a/app/components/organization-team/create-team/index.hbs +++ b/app/components/organization-team/create-team/index.hbs @@ -26,6 +26,7 @@ diff --git a/app/components/organization-team/overview/index.hbs b/app/components/organization-team/overview/index.hbs index 81f7edaabd..37e4b87f2a 100644 --- a/app/components/organization-team/overview/index.hbs +++ b/app/components/organization-team/overview/index.hbs @@ -1,5 +1,6 @@ void; +} + +// fixes cross origin errors +Cypress.on('uncaught:exception', () => { + // returning false here prevents Cypress from failing the test + return false; +}); + +describe('Organization Teams', () => { + beforeEach(() => { + networkActions.hideNetworkLogsFor({ ...API_ROUTES.websockets }); + + cy.intercept(API_ROUTES.userInfo.route).as('userInfoRoute'); + cy.intercept(API_ROUTES.submissionList.route).as('submissionList'); + cy.intercept(API_ROUTES.teamsList.route).as('teamList'); + cy.intercept(API_ROUTES.projectList.route).as('projectList'); + cy.intercept(API_ROUTES.organization.route).as('organization'); + cy.intercept(API_ROUTES.editTeam.route).as('editTeam'); + cy.intercept(API_ROUTES.usersList.route).as('usersList'); + cy.intercept(API_ROUTES.teamProject.route).as('teamProject'); + cy.intercept(API_ROUTES.teamMembersList.route).as('teamMembersList'); + cy.intercept('GET', API_ROUTES.inviteTeam.route).as('getInviteTeam'); + cy.intercept('POST', API_ROUTES.inviteTeam.route).as('postInviteTeam'); + cy.intercept('PUT', API_ROUTES.teamMember.route).as('teamMember'); + + loginActions.loginWithCredAndSaveSession({ ...AUTH_USER }); + + // Visit Organization Teams page + cy.visit(APPLICATION_ROUTES.organizationTeams); + + cy.wrap(false).as('shouldRunAfterEach'); + + // Wait for relevant network responses + cy.wait('@submissionList', NETWORK_WAIT_OPTS); + cy.wait('@userInfoRoute', NETWORK_WAIT_OPTS); + cy.wait('@teamList', NETWORK_WAIT_OPTS); + + // wait for page to load + cy.findAllByTestId('org-team-overview').should( + 'be.visible', + ELEMENT_WAIT_OPTS + ); + }); + + it.skip('should search team in teams list', function () { + // used for clean up in afterEach + cy.wrap(false).as('testCompleted'); + + // Ensure the search input exists + cy.findByPlaceholderText(cyTranslate('searchTeam')) + .as('searchInput') + .should('exist'); + + // Search for the team + cy.get('@searchInput').type(TEST_DATA.teamName); + + // Verify that the team was found + cy.get('@searchInput').should('have.value', TEST_DATA.teamName); + + cy.findByTestId('org-team-overview-name', ELEMENT_WAIT_OPTS).should( + 'contain.text', + TEST_DATA.teamName + ); + + // Clear the search input + cy.get('@searchInput').clear(); + + // Verify the input is cleared + cy.get('@searchInput').should('have.value', ''); + + cy.wrap(true).as('testCompleted'); + }); + + it.skip('should create/delete new team', function () { + // used for clean up in afterEach + cy.wrap(true).as('shouldRunAfterEach'); + + cy.wrap(false).as('testCompleted'); + + cy.wrap({ + perform: () => { + cy.getAliases(['@teamId', '@orgId']).then(([teamId, orgId]) => { + // Make the API request to delete the team + cy.makeAuthenticatedAPIRequest({ + method: 'DELETE', + url: `${API_HOST}/api/organizations/${orgId}/teams/${teamId}`, + }); + }); + }, + }).as('testCleanup'); + + // Click the create new team button + cy.findByText(cyTranslate('createTeam')).as('newTeamBtn').should('exist'); + + cy.get('@newTeamBtn').click(); + + // Ensure the team name input exists + cy.findByPlaceholderText(cyTranslate('teamName')) + .as('teamNameInput') + .should('exist'); + + // Enter the team name + cy.get('@teamNameInput').type(TEST_DATA.newTeamName); + + // Submit the form + cy.findByTestId('create-team-submit-btn').should('exist').click(); + + cy.wait('@teamList', NETWORK_WAIT_OPTS).then((interception) => { + // Assert that the response contains the updated role "Owner" + expect(interception.response?.statusCode).to.eq(201); + + // save the team id and org id + cy.wrap(interception.response?.body?.id).as('teamId'); + cy.wrap(interception.response?.body?.organization).as('orgId'); + }); + + cy.wait('@organization', NETWORK_WAIT_OPTS); + + // Wait for success message + cy.findByText(cyTranslate('teamCreated'), ELEMENT_WAIT_OPTS).should( + 'exist' + ); + + // Verify that the team was created + cy.findAllByTestId('org-team-overview-name', ELEMENT_WAIT_OPTS) + .contains(TEST_DATA.newTeamName) + .should('exist') + .as('newTeam'); + + // Open drawer + cy.get('@newTeam').click(); + + // Delete the team + cy.findByText(cyTranslate('deleteTeam')).click(); + + cy.findByLabelText( + cyTranslate('promptBox.deleteTeamPrompt.description') + ).type(TEST_DATA.newTeamName); + + cy.get('.ember-modal-dialog').within(() => { + cy.findByText(cyTranslate('deleteTeam')).click(); + }); + + // Wait for success message + cy.findByText( + `${TEST_DATA.newTeamName} ${cyTranslate('teamDeleted')}`, + ELEMENT_WAIT_OPTS + ).should('exist'); + + // Verify that the team was deleted + cy.get('@newTeam').should('not.exist'); + + cy.wrap(true).as('testCompleted'); + }); + + it.skip('should add/remove project to team', function () { + // used for clean up in afterEach + cy.wrap(true).as('shouldRunAfterEach'); + + cy.wrap(false).as('testCompleted'); + + cy.wrap({ + perform: () => { + cy.getAliases(['@teamId', '@orgId', '@projectId']).then( + ([teamId, orgId, projectId]) => { + // Make the API request to delete the team + cy.makeAuthenticatedAPIRequest({ + method: 'DELETE', + url: `${API_HOST}/api/organizations/${orgId}/teams/${teamId}/projects/${projectId}`, + }); + } + ); + }, + }).as('testCleanup'); + + // Verify that the team was created + cy.findAllByTestId('org-team-overview-name', ELEMENT_WAIT_OPTS) + .contains(TEST_DATA.teamName) + .should('exist') + .as('cypressTeam'); + + // Open drawer + cy.get('@cypressTeam').click(); + + // Add project to team + cy.findByText(cyTranslate('addProject')).click(); + + cy.wait('@projectList', NETWORK_WAIT_OPTS); + + cy.findAllByTestId('addProjectList-row') + .filter(':contains(' + TEST_DATA.projectName + ')') + .should('exist') + .as('projectRow'); + + // Find the checkbox within this row and check it + cy.get('@projectRow').within(() => { + cy.get('[data-test-checkbox]').check().should('be.checked'); + }); + + cy.get('[data-test-teamDetailAction-actionBtn]') + .contains(cyTranslate('addProject')) + .should('exist') + .click(); + + cy.wait('@teamProject', NETWORK_WAIT_OPTS).then((interception) => { + // Store `projectId` for cleanup + cy.wrap(interception.response?.body?.id).as('projectId'); + }); + + cy.wait('@editTeam', NETWORK_WAIT_OPTS).then((interception) => { + // Store `teamId` and `orgId` for cleanup + cy.wrap(interception.response?.body?.id).as('teamId'); + + cy.wrap(interception.response?.body?.organization).as('orgId'); + }); + + cy.findByText(cyTranslate('teamProjectAdded'), ELEMENT_WAIT_OPTS).should( + 'exist' + ); + + cy.get('[data-test-teamdetailaction-titlebtn]').click(); + + // Remove project from team + cy.get('tr', ELEMENT_WAIT_OPTS) + .filter(':contains(' + TEST_DATA.projectName + ')') + .should('exist') + .as('addedProjectRow'); + + cy.get('@addedProjectRow').within(() => { + cy.get('[data-test-teamProjectList-actionBtn]').click(); + }); + + cy.get('.ember-modal-dialog').within(() => { + cy.get('button[data-test-confirmbox-confirmbtn]').click(); + }); + + cy.wait('@editTeam', NETWORK_WAIT_OPTS); + + cy.findByText(cyTranslate('projectRemoved'), ELEMENT_WAIT_OPTS).should( + 'exist' + ); + + cy.findByTestId('teamDetail-closeBtn').click(); + + cy.wrap(true).as('testCompleted'); + }); + + it.skip('should add/remove user to team', function () { + // used for clean up in afterEach + cy.wrap(true).as('shouldRunAfterEach'); + + cy.wrap(false).as('testCompleted'); + + cy.wrap({ + perform: () => { + cy.getAliases(['@teamId', '@orgId', '@userId']).then( + ([teamId, orgId, userId]) => { + // Make the API request to delete the team + cy.makeAuthenticatedAPIRequest({ + method: 'DELETE', + url: `${API_HOST}/api/organizations/${orgId}/teams/${teamId}/members/${userId}`, + }); + } + ); + }, + }).as('testCleanup'); + + // Add user to team using add user action + cy.findAllByTestId('org-team-overview-name', ELEMENT_WAIT_OPTS) + .contains(TEST_DATA.teamName) + .should('exist') + .as('cypressTeam'); + + // Open drawer + cy.get('@cypressTeam').click(); + + // Add user to team + cy.findByText(cyTranslate('addUser')).click(); + + cy.wait('@usersList', NETWORK_WAIT_OPTS); + + cy.findAllByTestId('userList-row') + .filter(':contains(' + TEST_DATA.testUser.username + ')') + .should('exist') + .as('userRow'); + + // Find the checkbox within this row and check it + cy.get('@userRow').within(() => { + cy.get('[data-test-checkbox]').check().should('be.checked'); + }); + + cy.get('[data-test-teamdetailaction-actionbtn]') + .contains(cyTranslate('addUsers')) + .should('exist') + .click(); + + cy.wait('@teamMember', NETWORK_WAIT_OPTS).then((interception) => { + // Store `userId` for cleanup + cy.wrap(interception.response?.body?.id).as('userId'); + }); + + cy.wait('@editTeam', NETWORK_WAIT_OPTS).then((interception) => { + // Store `teamId` and `orgId` for cleanup + cy.wrap(interception.response?.body?.id).as('teamId'); + + cy.wrap(interception.response?.body?.organization).as('orgId'); + }); + + cy.wait('@usersList', NETWORK_WAIT_OPTS); + + cy.findByText(cyTranslate('teamMemberAdded'), ELEMENT_WAIT_OPTS).should( + 'exist' + ); + + cy.get('[data-test-teamdetailaction-titlebtn]').click(); + + // Remove user from team + cy.get('tr', ELEMENT_WAIT_OPTS) + .filter(':contains(' + TEST_DATA.testUser.username + ')') + .should('exist') + .as('addedUserRow'); + + cy.get('@addedUserRow').within(() => { + cy.get('[data-test-teamUserList-actionBtn]').click(); + }); + + cy.get('.ember-modal-dialog').within(() => { + cy.findByLabelText( + cyTranslate('promptBox.removeMemberPrompt.description') + ).type(TEST_DATA.testUser.username); + + cy.get('button[data-test-confirmbox-confirmbtn]').click(); + }); + + cy.wait('@editTeam', NETWORK_WAIT_OPTS); + + cy.findByText(cyTranslate('teamMemberRemoved'), ELEMENT_WAIT_OPTS).should( + 'exist' + ); + + cy.findByTestId('teamDetail-closeBtn').click(); + + cy.wrap(false).as('testCompleted'); + }); + + it('should invite user to team', function () { + // used for clean up in afterEach + cy.wrap(true).as('shouldRunAfterEach'); + + cy.wrap(false).as('testCompleted'); + + cy.wrap({ + perform: () => { + cy.getAliases(['@teamId', '@orgId', '@inviteId']).then( + ([teamId, orgId, inviteId]) => { + // Make the API request to delete the team + cy.makeAuthenticatedAPIRequest({ + method: 'DELETE', + url: `${API_HOST}/api/organizations/${orgId}/teams/${teamId}/invitations/${inviteId}`, + }); + } + ); + }, + }).as('testCleanup'); + + cy.findAllByTestId('org-team-overview-name', ELEMENT_WAIT_OPTS) + .contains(TEST_DATA.teamName) + .should('exist') + .as('cypressTeam'); + + // Open drawer + cy.get('@cypressTeam').click(); + + // Invite user to team + cy.findByText(cyTranslate('inviteUsers')).click(); + + cy.findByPlaceholderText(cyTranslate('email')).type( + TEST_DATA.testUser.inviteEmail + ); + + cy.findByText(cyTranslate('invite')).click(); + + cy.wait('@postInviteTeam', NETWORK_WAIT_OPTS).then((interception) => { + // Store for cleanup + cy.wrap(interception.response?.body?.id).as('inviteId'); + cy.wrap(interception.response?.body?.team).as('teamId'); + cy.wrap(interception.response?.body?.organization).as('orgId'); + }); + + cy.wait('@getInviteTeam', NETWORK_WAIT_OPTS); + + cy.findByText(cyTranslate('orgMemberInvited'), ELEMENT_WAIT_OPTS).should( + 'exist' + ); + + cy.wait('@teamMembersList', NETWORK_WAIT_OPTS); + + // Delete invitation + cy.findAllByTestId('invitationList-row', ELEMENT_WAIT_OPTS) + .filter(':contains(' + TEST_DATA.testUser.inviteEmail + ')') + .should('exist') + .as('invitedUserRow'); + + cy.get('@invitedUserRow').within(() => { + cy.get('[data-test-invitation-delete-btn]').click(); + }); + + cy.get('.ember-modal-dialog').within(() => { + cy.get('button[data-test-confirmbox-confirmbtn]').click(); + }); + + cy.findByText(cyTranslate('invitationDeleted'), ELEMENT_WAIT_OPTS).should( + 'exist' + ); + + cy.wait('@getInviteTeam', NETWORK_WAIT_OPTS); + + cy.findByTestId('teamDetail-closeBtn').click(); + + cy.wrap(false).as('testCompleted'); + }); + + afterEach(function () { + cy.get('@shouldRunAfterEach').then((shouldRunAfterEach) => { + if (shouldRunAfterEach) { + cy.getAliases(['@testCompleted', '@testCleanup']).then( + ([testCompleted, testCleanup]) => { + if (!testCompleted) { + // Call the cleanup function + (testCleanup as Cleanup).perform(); + } + } + ); + } + }); + }); +});