From b8f3e42e582de18f1768046ce392c8a3c347ef8b Mon Sep 17 00:00:00 2001
From: Shailesh Parmar
Date: Tue, 24 May 2022 18:55:17 +0530
Subject: [PATCH] Cypress: E2E testing for teams and users page (#5103)
* initial setup
* added teams e2e flow
* fix some fliky test
* removed only key word
* added users page flow
* removed 'only' key word
* wait time fix
---
.../resources/ui/cypress/common/common.js | 2 +-
.../ui/cypress/constants/constants.js | 34 ++
.../integration/Pages/EntityDetails.spec.js | 12 +-
.../integration/Pages/TeamsAndUsers.spec.js | 479 ++++++++++++++++++
.../components/TeamDetails/TeamDetails.tsx | 9 +-
.../TeamsAndUsers/TeamsAndUsers.component.tsx | 12 +-
.../components/UserDetails/UserDetails.tsx | 2 +-
.../common/DeleteWidget/DeleteWidget.tsx | 30 +-
.../resources/ui/src/utils/EntityUtils.tsx | 1 +
9 files changed, 558 insertions(+), 23 deletions(-)
create mode 100644 openmetadata-ui/src/main/resources/ui/cypress/integration/Pages/TeamsAndUsers.spec.js
diff --git a/openmetadata-ui/src/main/resources/ui/cypress/common/common.js b/openmetadata-ui/src/main/resources/ui/cypress/common/common.js
index db3e1c42d65..c1761d7a1df 100644
--- a/openmetadata-ui/src/main/resources/ui/cypress/common/common.js
+++ b/openmetadata-ui/src/main/resources/ui/cypress/common/common.js
@@ -11,7 +11,7 @@
* limitations under the License.
*/
-const uuid = () => Cypress._.random(0, 1e6);
+export const uuid = () => Cypress._.random(0, 1e6);
const isDatabaseService = (type) => type === 'database';
diff --git a/openmetadata-ui/src/main/resources/ui/cypress/constants/constants.js b/openmetadata-ui/src/main/resources/ui/cypress/constants/constants.js
index df33200ce4a..96038e2a23a 100644
--- a/openmetadata-ui/src/main/resources/ui/cypress/constants/constants.js
+++ b/openmetadata-ui/src/main/resources/ui/cypress/constants/constants.js
@@ -11,6 +11,8 @@
* limitations under the License.
*/
+import { uuid } from '../common/common';
+
export const MYDATA_SUMMARY_OPTIONS = {
tables: 'tables',
topics: 'topics',
@@ -87,3 +89,35 @@ export const FOLLOWING_TITLE = 'Following';
export const NO_SEARCHED_TERMS = 'No searched terms';
export const DELETE_TERM = 'DELETE';
+
+export const TOTAL_SAMPLE_DATA_TEAMS_COUNT = 7;
+export const TEAMS = {
+ Cloud_Infra: { name: 'Cloud_Infra', users: 15 },
+ Customer_Support: { name: 'Customer_Support', users: 20 },
+ Data_Platform: { name: 'Data_Platform', users: 16 },
+};
+
+export const NEW_TEAM = {
+ team_1: {
+ name: 'account',
+ display_name: 'Account',
+ description: 'Account department',
+ },
+ team_2: {
+ name: 'service',
+ display_name: 'Service',
+ description: 'Service department',
+ },
+};
+const id = uuid();
+export const NEW_USER = {
+ email: `test_${id}@gmail.com`,
+ display_name: `Test user ${id}`,
+ description: 'Hello, I am test user',
+};
+
+export const NEW_ADMIN = {
+ email: `test_${id}@gmail.com`,
+ display_name: `Test admin ${id}`,
+ description: 'Hello, I am test admin',
+};
diff --git a/openmetadata-ui/src/main/resources/ui/cypress/integration/Pages/EntityDetails.spec.js b/openmetadata-ui/src/main/resources/ui/cypress/integration/Pages/EntityDetails.spec.js
index ace669a1fab..244ad4129af 100644
--- a/openmetadata-ui/src/main/resources/ui/cypress/integration/Pages/EntityDetails.spec.js
+++ b/openmetadata-ui/src/main/resources/ui/cypress/integration/Pages/EntityDetails.spec.js
@@ -61,8 +61,11 @@ describe('Entity Details Page', () => {
cy.get('@confirmBtn').click();
// success modal should be visible
- cy.contains('Entity deleted successfully!').should('be.visible');
- cy.get('.Toastify__close-button > svg').first().should('be.visible').click();
+ cy.contains('deleted successfully!').should('be.visible');
+ cy.get('.Toastify__close-button > svg')
+ .first()
+ .should('be.visible')
+ .click();
cy.get('[data-testid="message-container"]')
.first()
@@ -78,7 +81,10 @@ describe('Entity Details Page', () => {
.should('be.visible')
.should('contain', `${singuler} instance for ${fqn} not found`);
- cy.get('.Toastify__close-button > svg').first().should('be.visible').click();
+ cy.get('.Toastify__close-button > svg')
+ .first()
+ .should('be.visible')
+ .click();
cy.get('[data-testid="no-data-image"]').should('be.visible');
cy.contains(
`${Cypress._.startCase(singuler)} instance for ${fqn} not found`
diff --git a/openmetadata-ui/src/main/resources/ui/cypress/integration/Pages/TeamsAndUsers.spec.js b/openmetadata-ui/src/main/resources/ui/cypress/integration/Pages/TeamsAndUsers.spec.js
new file mode 100644
index 00000000000..a4f8c992cc5
--- /dev/null
+++ b/openmetadata-ui/src/main/resources/ui/cypress/integration/Pages/TeamsAndUsers.spec.js
@@ -0,0 +1,479 @@
+/*
+ * Copyright 2021 Collate
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ * http://www.apache.org/licenses/LICENSE-2.0
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+import { searchEntity } from '../../common/common';
+import { DELETE_TERM, NEW_TEAM, NEW_USER, SEARCH_ENTITY_TABLE, TEAMS, TOTAL_SAMPLE_DATA_TEAMS_COUNT } from '../../constants/constants';
+
+describe('TeamsAndUsers page', () => {
+ beforeEach(() => {
+ cy.goToHomePage();
+ cy.get('[data-testid="terms"]').should('be.visible').click();
+ });
+
+ const seletctTeam = (name) => {
+ cy.get(`[data-testid="team-${name}"]`).should('be.visible').click();
+ cy.get(`[data-testid="team-${name}"] > .tw-group`).should(
+ 'have.class',
+ 'activeCategory'
+ );
+ };
+
+ const toastNotification = (msg) => {
+ cy.get('.Toastify__toast-body').should('be.visible').contains(msg);
+
+ cy.get('.Toastify__close-button > svg > path').should('be.visible').click();
+ };
+
+ const createNewTeam = (data) => {
+ cy.get('[data-testid="add-team-button"]').should('be.visible').click();
+ cy.get('.tw-modal-container').should('be.visible');
+ cy.get('[data-testid="name"]').should('be.visible').type(data.name);
+ cy.get('[data-testid="displayName"]')
+ .should('be.visible')
+ .type(data.display_name);
+ cy.get('.toastui-editor-md-container > .toastui-editor > .ProseMirror')
+ .should('be.visible')
+ .type(data.description);
+
+ cy.get('[data-testid="saveButton"]')
+ .should('be.visible')
+ .scrollIntoView()
+ .click();
+
+ cy.get(`[data-testid="team-${TEAMS.Cloud_Infra.name}"]`).should(
+ 'be.visible'
+ );
+ };
+
+ const deleteNewTeam = (data) => {
+ seletctTeam(data.name);
+ cy.get('[data-testid="Manage"]').should('be.visible').click();
+ cy.get('[data-testid="hard-delete"]')
+ .should('be.visible')
+ .as('hardDeleteContainer');
+
+ cy.get('@hardDeleteContainer')
+ .find('[data-testid="delete-button"]')
+ .should('be.visible')
+ .click();
+
+ cy.get('[data-testid="confirmation-text-input"]')
+ .should('be.visible')
+ .type(DELETE_TERM);
+
+ cy.get('[data-testid="confirm-button"]')
+ .should('be.visible')
+ .should('not.be.disabled')
+ .click();
+
+ toastNotification('Team deleted successfully!');
+ };
+
+ it('All the required details should render properly', () => {
+ cy.get('[data-testid="team-name"]').should(
+ 'have.length',
+ TOTAL_SAMPLE_DATA_TEAMS_COUNT
+ );
+ cy.get(`[data-testid="team-${TEAMS.Cloud_Infra.name}"] > .tw-group`).should(
+ 'have.class',
+ 'activeCategory'
+ );
+ cy.get('[data-testid="team-heading"]')
+ .should('be.visible')
+ .invoke('text')
+ .then((text) => {
+ expect(text).equal(TEAMS.Cloud_Infra.name);
+ });
+ });
+
+ it('Add new team flow should work properly', () => {
+ const newTeams = Object.values(NEW_TEAM);
+ newTeams.forEach((team) => {
+ createNewTeam(team);
+ });
+
+ cy.get('[data-testid="team-name"]').should(
+ 'have.length',
+ TOTAL_SAMPLE_DATA_TEAMS_COUNT + newTeams.length
+ );
+ });
+
+ it('Description and display name updation should work properly', () => {
+ const updatedName = 'Account_department';
+ const updatedDescription = 'New description';
+ cy.get('[data-testid="edit-synonyms"]').should('be.visible').click();
+ cy.get('[data-testid="synonyms"]')
+ .should('be.visible')
+ .clear()
+ .type(updatedName);
+
+ cy.get('[data-testid="saveAssociatedTag"]').should('be.visible').click();
+
+ cy.get('[data-testid="team-heading"]')
+ .should('be.visible')
+ .invoke('text')
+ .then((text) => {
+ expect(text).equal(updatedName);
+ });
+
+ cy.get('[data-testid="edit-description"] > [data-testid="image"]')
+ .should('be.visible')
+ .click();
+ cy.get('.tw-modal-container').should('be.visible');
+ cy.get('.toastui-editor-md-container > .toastui-editor > .ProseMirror')
+ .should('be.visible')
+ .clear()
+ .type(updatedDescription);
+
+ cy.get('[data-testid="save"]').should('be.visible').click();
+ cy.get('[data-testid="viewer-container"]')
+ .contains(updatedDescription)
+ .should('exist');
+ });
+
+ it('Add and remove user to team should work properly', () => {
+ const searchString = 'aaron';
+
+ cy.wait(1000)
+ cy.get('[data-testid="add-new-user"]').should('be.visible');
+ cy.get('[data-testid="add-new-user"]').click();
+ cy.get('.tw-modal-container').should('be.visible');
+ cy.get(
+ '.tw-modal-body > [data-testid="search-bar-container"] > .tw-flex > [data-testid="searchbar"]'
+ )
+ .should('be.visible')
+ .type(searchString);
+
+ cy.get('.tw-grid').children().its('length').should('be.gt', 0);
+ cy.get('[data-testid="checkboxAddUser"]').eq(1).check();
+
+ cy.get('[data-testid="AddUserSave"]').should('be.visible').click();
+ cy.get('[data-testid="user-card-container"]').should('be.visible');
+
+ // remove user from team
+ cy.get('[data-testid="remove"]').first().should('be.visible').click();
+ cy.get('.tw-modal-container').should('be.visible');
+ cy.get('[data-testid="body-text"]')
+ .contains('Are you sure you want to remove')
+ .should('be.visible');
+
+ cy.get('[data-testid="save-button"]').should('be.visible').click();
+
+ cy.get('.tw-modal-container').should('not.exist');
+ cy.get('[data-testid="add-new-user"]').should('be.visible');
+ });
+
+ it('Delete team flow should work properly', () => {
+ const newTeams = Object.values(NEW_TEAM);
+ newTeams.forEach((team) => {
+ deleteNewTeam(team);
+ });
+ });
+
+ it('Join team flow should work properly', () => {
+ seletctTeam(TEAMS.Customer_Support.name);
+ cy.get('[data-testid="team-heading"]')
+ .should('be.visible')
+ .invoke('text')
+ .then((text) => {
+ expect(text).equal(TEAMS.Customer_Support.name);
+ });
+
+ cy.get('[data-testid="join-teams"]').should('be.visible').click();
+
+ toastNotification('Team joined successfully!');
+
+ // get current user name and search user list
+ cy.get(
+ '[data-testid="dropdown-profile"] > [data-testid="dropdown-item"] > :nth-child(1) > [data-testid="menu-button"]'
+ )
+ .should('be.visible')
+ .click();
+ cy.get('[data-testid="greeting-text"] > a > :nth-child(1)')
+ .should('be.visible')
+ .invoke('text')
+ .then((name) => {
+ cy.get('[data-testid="dropdown-item"] > .tw-z-10').click();
+ cy.get('[data-testid="searchbar"]').should('be.visible').type(name);
+ cy.get('.tw-grid > [data-testid="user-card-container"]')
+ .should('be.visible')
+ .contains(name)
+ .should('exist');
+ });
+ });
+
+ it('Leave team flow should work properly', () => {
+ seletctTeam(TEAMS.Customer_Support.name);
+ cy.get('[data-testid="team-heading"]')
+ .should('be.visible')
+ .invoke('text')
+ .then((text) => {
+ expect(text).equal(TEAMS.Customer_Support.name);
+ });
+
+ cy.get('[data-testid="join-teams"]').should('not.exist');
+ cy.get('[data-testid="leave-team-button"]').should('be.visible').click();
+ cy.get('.tw-modal-container')
+ .should('be.visible')
+ .contains(
+ `Are you sure you want to leave the team ${TEAMS.Customer_Support.name}?`
+ )
+ .should('exist');
+
+ cy.get('[data-testid="save-button"]').should('be.visible').click();
+ toastNotification('Left the team successfully!');
+
+ // This need to be un-commented once ES issue is resoved
+ // cy.get(
+ // '[data-testid="dropdown-profile"] > [data-testid="dropdown-item"] > :nth-child(1) > [data-testid="menu-button"]'
+ // )
+ // .should('be.visible')
+ // .click();
+ // cy.get('[data-testid="greeting-text"] > a > :nth-child(1)')
+ // .should('be.visible')
+ // .invoke('text')
+ // .then((name) => {
+ // cy.get('[data-testid="dropdown-item"] > .tw-z-10').click();
+ // cy.get('[data-testid="searchbar"]').should('be.visible').type(name);
+ // cy.contains(`There are no users as ${name}.`).should('exist');
+ // });
+
+ cy.get('[data-testid="Users"] > .tw-py-px > [data-testid="filter-count"]')
+ .should('be.visible')
+ .invoke('text')
+ .then((text) => {
+ expect(+text).equal(TEAMS.Customer_Support.users);
+ });
+ });
+
+ it('Assets tab should work properly', () => {
+ cy.intercept(
+ '/api/v1/search/query?q=*&from=0&size=*&sort_field=last_updated_timestamp&sort_order=desc&index=*'
+ ).as('searchApi');
+ cy.get('[data-testid="Assets"]').should('be.visible').click();
+ cy.get('[data-testid="Assets"]').should('have.class', 'active');
+ cy.get('[data-testid="Assets"] > .tw-py-px > [data-testid="filter-count"]')
+ .invoke('text')
+ .then((text) => {
+ expect(+text).equal(0);
+ });
+
+ cy.contains('Your team does not have any dataset').should('be.visible');
+ cy.get('a > .button-comp').should('be.visible').contains('Explore');
+ searchEntity(SEARCH_ENTITY_TABLE.table_1.term);
+ cy.intercept(
+ '/api/v1/search/query?q=*&from=0&size=10&sort_order=desc&index=*'
+ ).as('searchApi');
+
+ cy.wait('@searchApi');
+
+ cy.get('[data-testid="table-link"]')
+ .first()
+ .contains(SEARCH_ENTITY_TABLE.table_1.term)
+ .click();
+
+ cy.get('[data-testid="Manage"]').should('be.visible').click();
+ cy.get('[data-testid="owner-dropdown"]').should('be.visible').click();
+
+ cy.get('[data-testid="searchInputText"]')
+ .should('be.visible')
+ .type(TEAMS.Cloud_Infra.name);
+
+ cy.get('[data-testid="list-item"] > .tw-truncate')
+ .should('be.visible')
+ .click();
+
+ cy.clickOnLogo();
+ cy.get('[data-testid="terms"]').should('be.visible').click();
+
+ cy.get('[data-testid="Assets"]').should('be.visible').click();
+ cy.get('[data-testid="Assets"]').should('have.class', 'active');
+ cy.get('[data-testid="Assets"] > .tw-py-px > [data-testid="filter-count"]')
+ .invoke('text')
+ .then((text) => {
+ expect(+text).equal(1);
+ });
+ });
+
+ it('Roles tab should work properly', () => {
+ cy.intercept('/api/v1/teams?fields=*').as('teamApi');
+ cy.get('[data-testid="Roles"]').should('be.visible').click();
+ cy.get('[data-testid="Roles"]').should('have.class', 'active');
+ cy.get('[data-testid="Roles"] > .tw-py-px > [data-testid="filter-count"]')
+ .invoke('text')
+ .then((text) => {
+ expect(+text).equal(0);
+ });
+
+ cy.contains('There are no roles assigned yet.').should('be.visible');
+ cy.get(
+ '.tw-ml-5 > [data-testid="dropdown-item"] > div > [data-testid="menu-button"]'
+ )
+ .should('be.visible')
+ .click();
+ cy.get('[data-testid="menu-item-Roles"] > .tw-flex')
+ .should('be.visible')
+ .click();
+
+ cy.get('[data-testid="teams"]').should('be.visible').click();
+ cy.get('[data-testid="teams"]').should('have.class', 'active');
+
+ cy.get('[data-testid="add-teams-button"]').should('be.visible').click();
+
+ cy.get('.tw-modal-container').should('be.visible');
+
+ cy.get('[data-testid="checkboxAddUser"]')
+ .first()
+ .should('be.visible')
+ .click();
+
+ cy.get('[data-testid="AddUserSave"]').should('be.visible').click();
+
+ cy.clickOnLogo();
+ cy.get('[data-testid="terms"]').should('be.visible').click();
+
+ cy.get('[data-testid="Roles"]').should('be.visible').click();
+ cy.get('[data-testid="Roles"]').should('have.class', 'active');
+ cy.wait('@teamApi');
+ cy.get('[data-testid="Roles"] > .tw-py-px > [data-testid="filter-count"]')
+ .invoke('text')
+ .then((text) => {
+ expect(+text).equal(1);
+ });
+ });
+
+ it('Add owner flow should work properly', () => {
+ cy.get('[data-testid="Manage"]').should('be.visible').click();
+ cy.get('[data-testid="Manage"]').should('have.class', 'active');
+
+ cy.get(
+ '[data-testid="dropdown-profile"] > [data-testid="dropdown-item"] > :nth-child(1) > [data-testid="menu-button"]'
+ )
+ .should('be.visible')
+ .click();
+ cy.get('[data-testid="greeting-text"] > a > :nth-child(1)')
+ .should('be.visible')
+ .invoke('text')
+ .then((name) => {
+ cy.get('.tw-z-10').click();
+
+ cy.get('[data-testid="owner-dropdown"]').should('be.visible').click();
+ cy.get('[data-testid="searchInputText"]').type(name);
+ cy.get('[data-testid="list-item"]').should('be.visible').click();
+ cy.get('[data-testid="owner-dropdown"] > .tw-truncate')
+ .invoke('text')
+ .then((text) => {
+ expect(text).equal(name);
+ });
+
+ cy.get('[data-testid="owner-name"]')
+ .should('be.visible')
+ .contains(name);
+ });
+ });
+
+ it('Create new user should work properly', () => {
+ cy.get('[data-testid="users"] > .tw-group > [data-testid="user-type"]')
+ .should('be.visible')
+ .click();
+
+ cy.get('[data-testid="users"] > .tw-group').should(
+ 'have.class',
+ 'activeCategory'
+ );
+
+ cy.get('[data-testid="add-user-button"]').should('be.visible').click();
+ cy.contains('Create User').should('be.visible');
+
+ cy.get('[data-testid="email"]').should('be.visible').type(NEW_USER.email);
+ cy.get('[data-testid="displayName"]')
+ .should('be.visible')
+ .type(NEW_USER.display_name);
+ cy.get('.toastui-editor-md-container > .toastui-editor > .ProseMirror')
+ .should('be.visible')
+ .type(NEW_USER.description);
+
+ cy.get(
+ ':nth-child(5) > [data-testid="dropdown-item"] > div > [data-testid="menu-button"]'
+ )
+ .should('be.visible')
+ .click();
+
+ cy.get('[data-testid="Cloud_Infra"]').should('be.visible').click();
+ cy.get('[data-testid="close-dropdown"]').click();
+
+ cy.get(
+ ':nth-child(6) > [data-testid="dropdown-item"] > div > [data-testid="menu-button"]'
+ )
+ .should('be.visible')
+ .click();
+ cy.get('[data-testid="Data Consumer"]').should('be.visible').click();
+ cy.get('[data-testid="close-dropdown"]').click();
+
+ cy.get('[data-testid="save-user"]').should('be.visible').click();
+
+ cy.get('[data-testid="searchbar"]')
+ .should('be.visible')
+ .type(NEW_USER.display_name);
+
+ cy.wait(500);
+
+ cy.get('[data-testid="user-card-container"]')
+ .first()
+ .contains(NEW_USER.display_name)
+ .should('exist')
+ .click();
+
+ cy.contains(NEW_USER.display_name).should('exist');
+ cy.contains(NEW_USER.description).should('exist');
+ cy.contains(NEW_USER.email).should('exist');
+ });
+
+ it('Delete user should work properly', () => {
+ cy.get('[data-testid="users"] > .tw-group > [data-testid="user-type"]')
+ .should('be.visible')
+ .click();
+
+ cy.get('[data-testid="users"] > .tw-group').should(
+ 'have.class',
+ 'activeCategory'
+ );
+ cy.get('[data-testid="searchbar"]')
+ .should('be.visible')
+ .type(NEW_USER.display_name);
+
+ cy.wait(500);
+
+ cy.get('[data-testid="user-card-container"]')
+ .first()
+ .contains(NEW_USER.display_name)
+ .should('exist');
+
+ cy.get('[data-testid="remove"] > [data-testid="image"]')
+ .should('not.be.visible')
+ .click();
+
+ cy.get('.tw-modal-container').should('be.visible');
+ cy.contains('Are you sure you want to delete').should('be.visible');
+ cy.get('[data-testid="save-button"]').should('be.visible').click();
+
+ cy.get('[data-testid="searchbar"]')
+ .should('be.visible')
+ .type(NEW_USER.display_name);
+
+ cy.wait(500);
+
+ cy.get('[data-testid="no-data-image"]').should('be.visible');
+ cy.contains('No user available').should('be.visible');
+ });
+});
diff --git a/openmetadata-ui/src/main/resources/ui/src/components/TeamDetails/TeamDetails.tsx b/openmetadata-ui/src/main/resources/ui/src/components/TeamDetails/TeamDetails.tsx
index 66c9c168c3b..42b3bb6330d 100644
--- a/openmetadata-ui/src/main/resources/ui/src/components/TeamDetails/TeamDetails.tsx
+++ b/openmetadata-ui/src/main/resources/ui/src/components/TeamDetails/TeamDetails.tsx
@@ -319,7 +319,7 @@ const TeamDetails = ({
title={TITLE_FOR_NON_ADMIN_ACTION}>