diff --git a/openmetadata-ui/src/main/resources/ui/cypress/e2e/Pages/Roles.spec.ts b/openmetadata-ui/src/main/resources/ui/cypress/e2e/Pages/Roles.spec.ts deleted file mode 100644 index 9fff71ac4fc..00000000000 --- a/openmetadata-ui/src/main/resources/ui/cypress/e2e/Pages/Roles.spec.ts +++ /dev/null @@ -1,308 +0,0 @@ -/* - * Copyright 2022 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 { - descriptionBox, - interceptURL, - uuid, - verifyResponseStatusCode, -} from '../../common/common'; -import { BASE_URL } from '../../constants/constants'; -import { GlobalSettingOptions } from '../../constants/settings.constant'; - -const roles = { - dataConsumer: 'Data Consumer', - dataSteward: 'Data Steward', -}; - -const policies = { - dataConsumerPolicy: 'Data Consumer Policy', - dataStewardPolicy: 'Data Steward Policy', - organizationPolicy: 'Organization Policy', -}; - -const errorMessageValidation = { - ifPolicyNotSelected: 'Enter at least one policy', - ifNameNotEntered: 'Name size must be between 1 and 128', - lastPolicyCannotBeRemoved: 'At least one policy is required in a role', -}; - -const roleName = `Role-test-${uuid()}`; -const description = `This is ${roleName} description`; - -const removePolicyFromRole = (policyName) => { - // Clicking on remove action for added policy - cy.get(`[data-testid="remove-action-${policyName}"]`) - .should('be.visible') - .click(); - - cy.get('.ant-modal-body') - .should('be.visible') - .should( - 'have.text', - `Are you sure you want to remove the ${policyName} from ${roleName}?` - ); - - cy.get('[type="button"]').contains('Confirm').should('be.visible').click(); -}; - -describe('Roles page should work properly', { tags: 'Settings' }, () => { - beforeEach(() => { - cy.login(); - - interceptURL('GET', '*api/v1/roles*', 'getRoles'); - - cy.settingClick(GlobalSettingOptions.ROLES); - - verifyResponseStatusCode('@getRoles', 200); - - cy.url().should('eq', `${BASE_URL}/settings/access/roles`); - }); - - it('Add new role and check all tabs data', () => { - cy.get('[data-testid="add-role"]') - .contains('Add Role') - .should('be.visible') - .click(); - - // Asserting navigation - cy.get('[data-testid="inactive-link"]') - .should('contain', 'Add New Role') - .should('be.visible'); - // Entering name - cy.get('#name').should('be.visible').type(roleName); - // Entering descrription - cy.get(descriptionBox).type(description); - // Select the policies - cy.get('[data-testid="policies"]').should('be.visible').click(); - - cy.get('[title="Data Consumer Policy"]') - .scrollIntoView() - .should('be.visible') - .click(); - - cy.get('[title="Data Steward Policy"]') - .scrollIntoView() - .should('be.visible') - .click(); - // Save the role - cy.get('[data-testid="submit-btn"]') - .scrollIntoView() - .should('be.visible') - .click(); - - // Verify the role is added successfully - cy.url().should('eq', `${BASE_URL}/settings/access/roles/${roleName}`); - cy.get('[data-testid="inactive-link"]').should('contain', roleName); - - // Verify added description - cy.get( - '[data-testid="asset-description-container"] [data-testid="viewer-container"]' - ) - .should('be.visible') - .should('contain', description); - - // click on the policies tab - cy.get('[role="tab"]').contains('Policies').should('be.visible').click(); - - // Verifying the added policies - cy.get('.ant-table-cell') - .should('contain', policies.dataConsumerPolicy) - .should('be.visible') - .and('contain', policies.dataStewardPolicy) - .should('be.visible'); - - // click on the teams tab - cy.get('[role="tab"]').contains('Teams').should('be.visible').click(); - - // check for empty table - cy.get('table').should('be.visible'); - cy.get('.ant-empty').should('be.visible'); - - // click on the users tab - cy.get('[role="tab"]').contains('Users').should('be.visible').click(); - - // check for empty table - cy.get('table').should('be.visible'); - cy.get('.ant-empty').should('be.visible'); - - // Navigating to roles tab to verify the added role - cy.get('[data-testid="breadcrumb-link"]').first().click(); - cy.get('table').should('be.visible').should('contain', roleName); - cy.get(`[data-row-key="${roleName}"]`) - .find('[data-testid="plus-more-count"]') - .scrollIntoView() - .should('be.visible') - .click(); - - // second policy should be visible on tooltip - cy.get('[role="tooltip"]') - .should('be.visible') - .contains(policies.dataStewardPolicy); - }); - - it('Add new role without selecting data', () => { - cy.get('[data-testid="add-role"]') - .contains('Add Role') - .should('be.visible') - .click(); - - // Asserting navigation - cy.get('[data-testid="inactive-link"]') - .should('contain', 'Add New Role') - .should('be.visible'); - // Entering name - cy.get('#name').should('be.visible').type(roleName); - // Entering descrription - cy.get(descriptionBox).type(description); - // Do not Select the policies - // Save the role - cy.get('[data-testid="submit-btn"]').scrollIntoView().click(); - - // Verify the error message that is displayed - cy.get('[role="alert"]').should( - 'contain', - errorMessageValidation.ifPolicyNotSelected - ); - }); - - it('Edit created role', () => { - // Edit description - cy.get('[data-testid="role-name"]') - .contains(roleName) - .scrollIntoView() - .should('be.visible') - .click(); - cy.get('[data-testid="edit-description"]').should('be.visible').click(); - - cy.get(descriptionBox).clear().type(`${description}-updated`); - cy.get('[data-testid="save"]').should('be.visible').click(); - - cy.get('[data-testid="inactive-link"]').should('be.visible'); - // Asserting updated description - cy.get( - '[data-testid="asset-description-container"] [data-testid="viewer-container"]' - ) - .should('be.visible') - .should('contain', `${description}-updated`); - }); - - it('Add new policy to created role', () => { - cy.get('[data-testid="role-name"]') - .contains(roleName) - .scrollIntoView() - .should('be.visible') - .click(); - // Asserting navigation - cy.get('[data-testid="inactive-link"]') - .should('contain', roleName) - .should('be.visible'); - - cy.get('[data-testid="add-policy"]').should('be.visible').click(); - // Checking the added policy is selected in the add policy modal - cy.get('[data-testid="policy-row"]') - .should('contain', policies.dataConsumerPolicy) - .should('have.class', 'selected'); - cy.get('[data-testid="policy-row"]') - .should('contain', policies.dataStewardPolicy) - .should('have.class', 'selected'); - - // Add policy - cy.get('[data-testid="policy-row"]') - .contains(policies.organizationPolicy) - .click(); - - cy.get('[data-testid="policy-row"]') - .should('contain', policies.organizationPolicy) - .should('have.class', 'selected'); - - cy.get('[type="button"]').contains('Submit').scrollIntoView().click(); - - cy.get('[data-testid="entity-name"]') - .should('contain', policies.organizationPolicy) - .should('be.visible'); - }); - - it('Remove added policy from created role', () => { - cy.get('[data-testid="role-name"]') - .contains(roleName) - .scrollIntoView() - .should('be.visible') - .click(); - // Asserting navigation - cy.get('[data-testid="inactive-link"]') - .should('contain', roleName) - .should('be.visible'); - - removePolicyFromRole(policies.organizationPolicy); - - // Validating if the policy is removed successfully - cy.get('[data-testid="entity-name"]').should( - 'not.contain', - policies.organizationPolicy - ); - }); - - it('Check if last policy is not removed', () => { - interceptURL('GET', `/api/v1/roles/name/${roleName}*`, 'getSelectedRole'); - - cy.get('[data-testid="role-name"]') - .contains(roleName) - .scrollIntoView() - .should('be.visible') - .click(); - - // Asserting navigation - cy.get('[data-testid="inactive-link"]') - .should('contain', roleName) - .should('be.visible'); - - verifyResponseStatusCode('@getSelectedRole', 200); - - interceptURL('PATCH', '/api/v1/roles/*', 'checkDeletedRole'); - // Removing second policy from the role - removePolicyFromRole(policies.dataStewardPolicy); - - // Validating if the policy is removed successfully - cy.get('[data-testid="entity-name"]').should( - 'not.contain', - policies.dataStewardPolicy - ); - verifyResponseStatusCode('@checkDeletedRole', 200); - - // Removing the last policy and validating the error message - removePolicyFromRole(policies.dataConsumerPolicy); - - cy.get('.Toastify__toast-body') - .should('be.visible') - .should('contain', errorMessageValidation.lastPolicyCannotBeRemoved); - - cy.get('[data-testid="entity-name"]').should( - 'contain', - policies.dataConsumerPolicy - ); - }); - - it('Delete created Role', () => { - cy.get(`[data-testid="delete-action-${roleName}"]`) - .scrollIntoView() - .click({ force: true }); - - cy.get('[data-testid="confirmation-text-input"]').type('DELETE'); - - cy.get('[data-testid="confirm-button"]').scrollIntoView().click(); - - // Validate deleted role - cy.get('[data-testid="role-name"]').should('not.contain', roleName); - }); -}); diff --git a/openmetadata-ui/src/main/resources/ui/playwright/e2e/Pages/Roles.spec.ts b/openmetadata-ui/src/main/resources/ui/playwright/e2e/Pages/Roles.spec.ts new file mode 100644 index 00000000000..ce8df842364 --- /dev/null +++ b/openmetadata-ui/src/main/resources/ui/playwright/e2e/Pages/Roles.spec.ts @@ -0,0 +1,227 @@ +/* + * Copyright 2024 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 { expect, test } from '@playwright/test'; +import { GlobalSettingOptions } from '../../constant/settings'; +import { descriptionBox, redirectToHomePage, uuid } from '../../utils/common'; +import { removePolicyFromRole } from '../../utils/roles'; +import { settingClick } from '../../utils/sidebar'; + +const policies = { + dataConsumerPolicy: 'Data Consumer Policy', + dataStewardPolicy: 'Data Steward Policy', + organizationPolicy: 'Organization Policy', +}; + +const errorMessageValidation = { + ifPolicyNotSelected: 'Enter at least one policy', + ifNameNotEntered: 'Name size must be between 1 and 128', + lastPolicyCannotBeRemoved: 'At least one policy is required in a role', +}; + +const roleName = `Role-test-${uuid()}`; +const description = `This is ${roleName} description`; + +// use the admin user to login +test.use({ storageState: 'playwright/.auth/admin.json' }); + +test.beforeEach(async ({ page }) => { + await redirectToHomePage(page); +}); + +test('Roles page should work properly', async ({ page }) => { + test.slow(true); + + await test.step('Add new role and check all tabs data', async () => { + await settingClick(page, GlobalSettingOptions.ROLES); + await page.locator('[data-testid="add-role"]').click(); + + // Asserting navigation + await expect(page.locator('[data-testid="inactive-link"]')).toContainText( + 'Add New Role' + ); + + // Entering name + await page.locator('#name').fill(roleName); + // Entering description + await page.locator(descriptionBox).fill(description); + // Select the policies + await page.locator('[data-testid="policies"]').click(); + await page.locator('[title="Data Consumer Policy"]').click(); + await page.locator('[title="Data Steward Policy"]').click(); + // Save the role + await page.locator('[data-testid="submit-btn"]').click(); + + // Verify the role is added successfully + await expect(page).toHaveURL(`/settings/access/roles/${roleName}`); + await expect(page.locator('[data-testid="inactive-link"]')).toContainText( + roleName + ); + // Verify added description + await expect( + page.locator( + '[data-testid="asset-description-container"] [data-testid="viewer-container"]' + ) + ).toContainText(description); + + // click on the policies tab + await page.locator('[role="tab"]:has-text("Policies")').click(); + + // Verifying the added policies + + await page + .getByRole('link', { name: policies.dataConsumerPolicy, exact: true }) + .isVisible(); + + await page + .getByRole('link', { name: policies.dataStewardPolicy, exact: true }) + .isVisible(); + + // click on the teams tab + await page.locator('[role="tab"]:has-text("Teams")').click(); + + await expect(page.getByRole('cell', { name: 'No data' })).toBeVisible(); + + // click on the users tab + await page.locator('[role="tab"]:has-text("Users")').click(); + + await expect(page.getByRole('cell', { name: 'No data' })).toBeVisible(); + + // Navigating to roles tab to verify the added role + await page.locator('[data-testid="breadcrumb-link"]').first().click(); + + await expect(page.locator('table')).toContainText(roleName); + + // second policy should be visible on tooltip + await page + .locator(`[data-row-key="${roleName}"] [data-testid="plus-more-count"]`) + .click(); + + await expect(page.locator('[role="tooltip"]')).toContainText( + policies.dataStewardPolicy + ); + }); + + await test.step('Add new role without selecting data', async () => { + await settingClick(page, GlobalSettingOptions.ROLES); + await page.locator('[data-testid="add-role"]').click(); + + // Asserting navigation + await expect(page.locator('[data-testid="inactive-link"]')).toContainText( + 'Add New Role' + ); + + // Entering name + await page.locator('#name').fill(roleName); + // Entering description + await page.locator(descriptionBox).fill(description); + // Do not Select the policies + // Save the role + await page.locator('[data-testid="submit-btn"]').click(); + + // Verify the error message that is displayed + await expect(page.locator('[role="alert"]')).toContainText( + errorMessageValidation.ifPolicyNotSelected + ); + }); + + await test.step('Edit created role', async () => { + await settingClick(page, GlobalSettingOptions.ROLES); + // Edit description + await page.getByRole('link', { name: roleName }).click(); + await page.locator('[data-testid="edit-description"]').click(); + + await page.locator(descriptionBox).fill(`${description}-updated`); + await page.locator('[data-testid="save"]').click(); + + await expect(page.locator('[data-testid="inactive-link"]')).toBeVisible(); + // Asserting updated description + await expect( + page.locator( + '[data-testid="asset-description-container"] [data-testid="viewer-container"]' + ) + ).toContainText(`${description}-updated`); + }); + + await test.step('Add new policy to created role', async () => { + await settingClick(page, GlobalSettingOptions.ROLES); + await page.getByRole('link', { name: roleName }).click(); + // Asserting navigation + await page.locator('[data-testid="add-policy"]').click(); + // Checking the added policy is selected in the add policy modal + page.getByTestId('modal-container').getByText(policies.dataConsumerPolicy); + page.getByTestId('modal-container').getByText(policies.dataStewardPolicy); + + // Add policy + await page + .locator('[data-testid="policy-row"]') + .getByText(policies.organizationPolicy) + .click(); + page.getByTestId('modal-container').getByText(policies.organizationPolicy); + + await page.locator('[type="button"]:has-text("Submit")').click(); + + await page + .getByRole('link', { name: policies.dataStewardPolicy, exact: true }) + .isVisible(); + }); + + await test.step('Remove added policy from created role', async () => { + await settingClick(page, GlobalSettingOptions.ROLES); + await page.getByRole('link', { name: roleName }).click(); + // Asserting navigation + await removePolicyFromRole(page, policies.organizationPolicy, roleName); + + // Validating if the policy is removed successfully + await expect(page.locator('.ant-table-row').last()).not.toContainText( + policies.organizationPolicy + ); + }); + + await test.step('Check if last policy is not removed', async () => { + await settingClick(page, GlobalSettingOptions.ROLES); + await page.getByRole('link', { name: roleName }).click(); + // Removing second policy from the role + await removePolicyFromRole(page, policies.dataStewardPolicy, roleName); + + // Validating if the policy is removed successfully + await expect(page.locator('.ant-table-row').last()).not.toContainText( + policies.dataStewardPolicy + ); + + // Removing the last policy and validating the error message + await removePolicyFromRole(page, policies.dataConsumerPolicy, roleName); + + await expect(page.locator('.Toastify__toast-body')).toContainText( + errorMessageValidation.lastPolicyCannotBeRemoved + ); + await expect(page.locator('.ant-table-row')).toContainText( + policies.dataConsumerPolicy + ); + }); + + await test.step('Delete created Role', async () => { + await settingClick(page, GlobalSettingOptions.ROLES); + await page.locator(`[data-testid="delete-action-${roleName}"]`).click(); + await page + .locator('[data-testid="confirmation-text-input"]') + .fill('DELETE'); + await page.locator('[data-testid="confirm-button"]').click(); + + // Validate deleted role + await expect( + page.locator( + `[data-testid="role-name"][href="/settings/access/roles/${roleName}"]` + ) + ).not.toBeVisible(); + }); +}); diff --git a/openmetadata-ui/src/main/resources/ui/playwright/utils/roles.ts b/openmetadata-ui/src/main/resources/ui/playwright/utils/roles.ts new file mode 100644 index 00000000000..a82a571bd77 --- /dev/null +++ b/openmetadata-ui/src/main/resources/ui/playwright/utils/roles.ts @@ -0,0 +1,30 @@ +/* + * Copyright 2024 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 { expect, Page } from '@playwright/test'; + +export const removePolicyFromRole = async ( + page: Page, + policyName: string, + roleName: string +) => { + // Clicking on remove action for added policy + await page.locator(`[data-testid="remove-action-${policyName}"]`).click(); + + const modalText = await page.locator('.ant-modal-body').textContent(); + + expect(modalText).toBe( + `Are you sure you want to remove the ${policyName} from ${roleName}?` + ); + + await page.locator('[type="button"]:has-text("Confirm")').click(); +};