diff --git a/openmetadata-ui/src/main/resources/ui/cypress/e2e/Pages/Bots.spec.js b/openmetadata-ui/src/main/resources/ui/cypress/e2e/Pages/Bots.spec.js new file mode 100644 index 00000000000..555d8fc781e --- /dev/null +++ b/openmetadata-ui/src/main/resources/ui/cypress/e2e/Pages/Bots.spec.js @@ -0,0 +1,135 @@ +/* + * 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 { descriptionBox, interceptURL, uuid, verifyResponseStatusCode } from '../../common/common'; +import { DELETE_TERM } from '../../constants/constants'; + +const botName = `Bot-ct-test-${uuid()}`; +const botEmail = `${botName}@mail.com`; +const description = 'This is bot description'; +const updatedDescription = 'This is updated bot description'; +const updatedBotName = `updated-${botName}`; + +const getCreatedBot = () => { + interceptURL( + 'GET', + `/api/v1/permissions/bot/name/${botName}`, + 'getCreatedBot' + ); + //Click on created Bot name + cy.get('.ant-table-cell').contains(botName).should('be.visible').click(); + verifyResponseStatusCode('@getCreatedBot', 200); +}; + +describe('Bots Page should work properly', () => { + beforeEach(() => { + cy.goToHomePage(); + + cy.get('[data-testid="appbar-item-settings"]') + .should('exist') + .should('be.visible') + .click(); + interceptURL( + 'GET', + 'api/v1/bots?limit=15&include=non-deleted', + 'getBotsPage' + ); + cy.get('.ant-menu-title-content') + .contains('Bots') + .scrollIntoView() + .should('be.visible') + .click(); + verifyResponseStatusCode('@getBotsPage', 200); + }); + + it('Create new Bot', () => { + cy.get('[data-testid="add-bot"]') + .should('exist') + .should('be.visible') + .as('addBotButton'); + cy.wait(500); + //Click on add bot button + cy.get('@addBotButton').click(); + //Enter email + cy.get('[data-testid="email"]').should('exist').type(botEmail); + //Enter display name + cy.get('[data-testid="displayName"]').should('exist').type(botName); + //Enter description + cy.get(descriptionBox).type(description); + interceptURL('POST', '/api/v1/bots', 'createBot'); + //Click on save button + cy.get('[data-testid="save-user"]') + .scrollIntoView() + .should('be.visible') + .click(); + verifyResponseStatusCode('@createBot', 201); + //Verify bot is getting added in the bots listing page + cy.get('table').should('contain', botName).and('contain', description); + }); + + it('Update display name and description', () => { + getCreatedBot(); + + //Click on edit display name + cy.get('[data-testid="edit-displayName"]') + .should('exist') + .should('be.visible') + .click(); + //Enter new display name + cy.get('[data-testid="displayName"]') + .should('be.visible') + .clear() + .type(updatedBotName); + //Save the updated display name + interceptURL('PATCH', '/api/v1/users/*', 'updateBot'); + cy.get('[data-testid="save-displayName"]').should('be.visible').click(); + verifyResponseStatusCode('@updateBot', 200); + //Verify the display name is updated on bot details page + cy.get('[data-testid="container"]').should('contain', updatedBotName); + //Click on edit description button + cy.get('[data-testid="edit-description"]').should('be.visible').click(); + //Enter updated description and save + cy.get(descriptionBox).clear().type(updatedDescription); + cy.get('[data-testid="save"]').click(); + + interceptURL('GET', '/api/v1/bots*', 'getBotsPage'); + cy.get('[data-testid="breadcrumb-link"]').first().click(); + verifyResponseStatusCode('@getBotsPage', 200); + + //Verify the updated name is displayed in the Bots listing page + cy.get(`[data-testid="bot-link-${updatedBotName}"]`).should( + 'contain', + updatedBotName + ); + cy.get('[data-testid="markdown-parser"]').should( + 'contain', + updatedDescription + ); + }); + + it('Delete created bot', () => { + //Click on delete button + cy.get(`[data-testid="bot-delete-${updatedBotName}"]`) + .should('be.visible') + .click(); + //Select permanent delete + cy.get('[data-testid="hard-delete-option"]').should('be.visible').click(); + //Enter confirmation text + cy.get('[data-testid="confirmation-text-input"]') + .should('be.visible') + .type(DELETE_TERM); + interceptURL('DELETE', '/api/v1/bots/*', 'deleteBot'); + cy.get('[data-testid="confirm-button"]').should('be.visible').click(); + verifyResponseStatusCode('@deleteBot', 200); + cy.get('[data-testid="container"]').should('not.contain', botName); + }); +}); diff --git a/openmetadata-ui/src/main/resources/ui/cypress/e2e/Pages/MSTeams.spec.js b/openmetadata-ui/src/main/resources/ui/cypress/e2e/Pages/MSTeams.spec.js new file mode 100644 index 00000000000..a74f4dc16a1 --- /dev/null +++ b/openmetadata-ui/src/main/resources/ui/cypress/e2e/Pages/MSTeams.spec.js @@ -0,0 +1,98 @@ +/* + * 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 { descriptionBox, interceptURL, uuid, verifyResponseStatusCode } from '../../common/common'; + +const MSteamName = `MSTeam-ct-test-${uuid()}`; +const updatedDescription = 'This is updated slack description'; +const endpointURL = 'http://localhost:8585'; + +describe('MSTeams Page', () => { + beforeEach(() => { + cy.goToHomePage(); + + cy.get('[data-testid="appbar-item-settings"]') + .should('exist') + .should('be.visible') + .click(); + + cy.get('.ant-menu-title-content') + .contains('MS Teams') + .scrollIntoView() + .should('be.visible') + .click(); + }); + + it('Add MSTeams', () => { + interceptURL('GET', '/api/v1/settings/bootstrappedFilters', 'addMSTeam'); + cy.get('[data-testid="add-webhook-button"]') + .should('exist') + .should('be.visible') + .click(); + verifyResponseStatusCode('@addMSTeam', 200); + cy.get('[data-testid="name"]').should('exist').type(MSteamName); + cy.get(descriptionBox).should('exist').type('This is MSTeams description'); + cy.get('[data-testid="endpoint-url"]') + .should('exist') + .type('http://localhost:8585/add-webhook/msteams'); + + interceptURL('POST', 'api/v1/webhook', 'createMSTeam'); + cy.get('[data-testid="save-webhook"]') + .scrollIntoView() + .should('exist') + .should('be.visible') + .click(); + verifyResponseStatusCode('@createMSTeam', 201); + cy.get('[data-testid="webhook-link"]') + .should('be.visible') + .should('exist') + .should('contain', MSteamName); + }); + + it('Edit MSTeams description', () => { + interceptURL('GET', `/api/v1/webhook/name/${MSteamName}`, 'editSlack'); + cy.get(`[data-testid="edit-action-${MSteamName}"]`) + .should('exist') + .should('be.visible') + .click(); + verifyResponseStatusCode('@editSlack', 200); + cy.get(descriptionBox).clear().type(updatedDescription); + cy.get('[data-testid="endpoint-url"]').clear().type(endpointURL); + interceptURL('PUT', '/api/v1/webhook', 'updateDescription'); + cy.get('[data-testid="save-webhook"]') + .scrollIntoView() + .should('exist') + .should('be.visible') + .click(); + verifyResponseStatusCode('@updateDescription', 200); + cy.get('[data-testid="viewer-container"]').should( + 'contain', + updatedDescription + ); + }); + + it('Delete MSTeams', () => { + cy.get(`[data-testid="delete-action-${MSteamName}"]`) + .scrollIntoView() + .should('exist') + .should('be.visible') + .click(); + + interceptURL('DELETE', '/api/v1/webhook/*', 'deleteSlack'); + cy.get('[data-testid="save-button"]') + .should('exist') + .should('be.visible') + .click(); + verifyResponseStatusCode('@deleteSlack', 200); + cy.get('table').should('not.contain', MSteamName); + }); +}); diff --git a/openmetadata-ui/src/main/resources/ui/cypress/e2e/Pages/Slack.spec.js b/openmetadata-ui/src/main/resources/ui/cypress/e2e/Pages/Slack.spec.js new file mode 100644 index 00000000000..96bf63c06b5 --- /dev/null +++ b/openmetadata-ui/src/main/resources/ui/cypress/e2e/Pages/Slack.spec.js @@ -0,0 +1,98 @@ +/* + * 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 { descriptionBox, interceptURL, uuid, verifyResponseStatusCode } from '../../common/common'; + +const slackName = `Slack-ct-test-${uuid()}`; +const updatedDescription = 'This is updated slack description'; +const endpointURL = 'http://localhost:8585'; + +describe('Slack Page', () => { + beforeEach(() => { + cy.goToHomePage(); + + cy.get('[data-testid="appbar-item-settings"]') + .should('exist') + .should('be.visible') + .click(); + + cy.get('.ant-menu-title-content') + .contains('Slack') + .scrollIntoView() + .should('be.visible') + .click(); + }); + + it('Add slack', () => { + interceptURL('GET', '/api/v1/settings/bootstrappedFilters', 'addSlack'); + cy.get('[data-testid="add-webhook-button"]') + .should('exist') + .should('be.visible') + .click(); + verifyResponseStatusCode('@addSlack', 200); + cy.get('[data-testid="name"]').should('exist').type(slackName); + cy.get(descriptionBox).should('exist').type('This is slack description'); + cy.get('[data-testid="endpoint-url"]') + .should('exist') + .type('http://localhost:8585/add-webhook/slack'); + + interceptURL('POST', 'api/v1/webhook', 'createWebhook'); + cy.get('[data-testid="save-webhook"]') + .scrollIntoView() + .should('exist') + .should('be.visible') + .click(); + verifyResponseStatusCode('@createWebhook', 201); + cy.get('[data-testid="webhook-link"]') + .should('be.visible') + .should('exist') + .should('contain', slackName); + }); + + it('Edit Slack description', () => { + interceptURL('GET', `/api/v1/webhook/name/${slackName}`, 'editSlack'); + cy.get(`[data-testid="edit-action-${slackName}"]`) + .should('exist') + .should('be.visible') + .click(); + verifyResponseStatusCode('@editSlack', 200); + cy.get(descriptionBox).clear().type(updatedDescription); + cy.get('[data-testid="endpoint-url"]').clear().type(endpointURL); + interceptURL('PUT', '/api/v1/webhook', 'updateDescription'); + cy.get('[data-testid="save-webhook"]') + .scrollIntoView() + .should('exist') + .should('be.visible') + .click(); + verifyResponseStatusCode('@updateDescription', 200); + cy.get('[data-testid="viewer-container"]').should( + 'contain', + updatedDescription + ); + }); + + it('Delete Slack', () => { + cy.get(`[data-testid="delete-action-${slackName}"]`) + .scrollIntoView() + .should('exist') + .should('be.visible') + .click(); + + interceptURL('DELETE', '/api/v1/webhook/*', 'deleteSlack'); + cy.get('[data-testid="save-button"]') + .should('exist') + .should('be.visible') + .click(); + verifyResponseStatusCode('@deleteSlack', 200); + cy.get('table').should('not.contain', slackName); + }); +}); diff --git a/openmetadata-ui/src/main/resources/ui/cypress/e2e/Pages/Webhooks.spec.js b/openmetadata-ui/src/main/resources/ui/cypress/e2e/Pages/Webhooks.spec.js new file mode 100644 index 00000000000..c4ede5dc8c7 --- /dev/null +++ b/openmetadata-ui/src/main/resources/ui/cypress/e2e/Pages/Webhooks.spec.js @@ -0,0 +1,102 @@ +/* + * 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 { descriptionBox, interceptURL, uuid, verifyResponseStatusCode } from '../../common/common'; + +const webhookName = `Webhook-ct-test-${uuid()}`; +const updatedDescription = 'This is updated webhook description'; +const endpointURL = 'http://localhost:8585'; + +describe('Webooks Page', () => { + beforeEach(() => { + cy.goToHomePage(); + + cy.get('[data-testid="appbar-item-settings"]') + .should('exist') + .should('be.visible') + .click(); + + cy.get('.ant-menu-title-content') + .contains('Webhook') + .scrollIntoView() + .should('be.visible') + .click(); + }); + + it('Add webhook', () => { + interceptURL('GET', '/api/v1/settings/bootstrappedFilters', 'addWebhook'); + cy.get('[data-testid="add-webhook-button"]') + .should('exist') + .should('be.visible') + .click(); + verifyResponseStatusCode('@addWebhook', 200); + cy.get('[data-testid="name"]').should('exist').type(webhookName); + cy.get(descriptionBox).should('exist').type('This is webhook description'); + cy.get('[data-testid="endpoint-url"]') + .should('exist') + .type('http://localhost:8585/add-webhook'); + + interceptURL('POST', 'api/v1/webhook', 'createWebhook'); + cy.get('[data-testid="save-webhook"]') + .scrollIntoView() + .should('exist') + .should('be.visible') + .click(); + verifyResponseStatusCode('@createWebhook', 201); + cy.get('[data-testid="webhook-link"]') + .should('be.visible') + .should('exist') + .should('contain', webhookName); + }); + + it('Edit Webhook description', () => { + interceptURL('GET', `/api/v1/webhook/name/${webhookName}`, 'editWebhook'); + cy.get(`[data-testid="edit-action-${webhookName}"]`) + .should('exist') + .should('be.visible') + .click(); + verifyResponseStatusCode('@editWebhook', 200); + cy.get(descriptionBox).should('exist').clear().type(updatedDescription); + cy.get('[data-testid="endpoint-url"]') + .should('exist') + .clear() + .type(endpointURL); + interceptURL('PUT', '/api/v1/webhook', 'updateDescription'); + cy.get('[data-testid="save-webhook"]') + .scrollIntoView() + .should('exist') + .should('be.visible') + .click(); + verifyResponseStatusCode('@updateDescription', 200); + //uncomment this code once webhook description issue is fixed + // cy.get('[data-testid="viewer-container"]').should( + // 'contain', + // updatedDescription + // ); + }); + + it('Delete webhook', () => { + cy.get(`[data-testid="delete-action-${webhookName}"]`) + .scrollIntoView() + .should('exist') + .should('be.visible') + .click(); + + interceptURL('DELETE', '/api/v1/webhook/*', 'deleteWebhook'); + cy.get('[data-testid="save-button"]') + .should('exist') + .should('be.visible') + .click(); + verifyResponseStatusCode('@deleteWebhook', 200); + cy.get('table').should('not.contain', webhookName); + }); +}); diff --git a/openmetadata-ui/src/main/resources/ui/src/components/BotDetails/BotDetails.component.tsx b/openmetadata-ui/src/main/resources/ui/src/components/BotDetails/BotDetails.component.tsx index 31a7e753c49..466a8153e0b 100644 --- a/openmetadata-ui/src/main/resources/ui/src/components/BotDetails/BotDetails.component.tsx +++ b/openmetadata-ui/src/main/resources/ui/src/components/BotDetails/BotDetails.component.tsx @@ -237,7 +237,9 @@ const BotDetails: FC = ({ ) : ( {displayName ? ( - + {displayName} ) : ( diff --git a/openmetadata-ui/src/main/resources/ui/src/components/BotListV1/BotListV1.component.tsx b/openmetadata-ui/src/main/resources/ui/src/components/BotListV1/BotListV1.component.tsx index c702c60e2fe..c2df16e915b 100644 --- a/openmetadata-ui/src/main/resources/ui/src/components/BotListV1/BotListV1.component.tsx +++ b/openmetadata-ui/src/main/resources/ui/src/components/BotListV1/BotListV1.component.tsx @@ -30,6 +30,7 @@ import { Bot } from '../../generated/entity/bot'; import { Operation } from '../../generated/entity/policies/accessControl/rule'; import { Include } from '../../generated/type/include'; import { Paging } from '../../generated/type/paging'; +import { getEntityName } from '../../utils/CommonUtils'; import { checkPermission } from '../../utils/PermissionsUtils'; import SVGIcons, { Icons } from '../../utils/SvgUtils'; import { showErrorToast } from '../../utils/ToastUtils'; @@ -102,11 +103,14 @@ const BotListV1 = ({ title: 'Name', dataIndex: 'displayName', key: 'displayName', - render: (name, record) => ( + render: (_, record) => ( - {name} + data-testid={`bot-link-${getEntityName(record?.botUser)}`} + to={getBotsPath( + record?.botUser?.fullyQualifiedName || record?.botUser?.name || '' + )}> + {getEntityName(record?.botUser)} ), }, @@ -115,10 +119,12 @@ const BotListV1 = ({ dataIndex: 'description', key: 'description', render: (_, record) => - record?.description ? ( - + record?.botUser?.description ? ( + ) : ( - 'No Description' + No Description ), }, { @@ -132,6 +138,7 @@ const BotListV1 = ({ placement="bottom" title={deletePermission ? 'Delete' : NO_PERMISSION_FOR_ACTION}>