UI: Fix Bots Listing Page is not showing updated name and description (#7484)

* UI: Fix Bots Listing Page is not showing updated name and description

* Add cypress test for bots page

* Add cypress tests for webhook

* Fix bots displayName test

* Fix Add bot flow

* Fix update bot test flow
This commit is contained in:
Sachin Chaurasiya 2022-09-19 20:38:30 +05:30 committed by GitHub
parent 2a6c6134f4
commit 7e9fbee743
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
7 changed files with 453 additions and 7 deletions

View File

@ -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);
});
});

View File

@ -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);
});
});

View File

@ -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);
});
});

View File

@ -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);
});
});

View File

@ -237,7 +237,9 @@ const BotDetails: FC<BotsDetailProp> = ({
) : (
<Fragment>
{displayName ? (
<span className="tw-text-base tw-font-medium tw-mr-2">
<span
className="tw-text-base tw-font-medium tw-mr-2"
data-testid="bot-displayName">
{displayName}
</span>
) : (

View File

@ -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) => (
<Link
className="hover:tw-underline tw-cursor-pointer"
to={getBotsPath(record.fullyQualifiedName || record.name)}>
{name}
data-testid={`bot-link-${getEntityName(record?.botUser)}`}
to={getBotsPath(
record?.botUser?.fullyQualifiedName || record?.botUser?.name || ''
)}>
{getEntityName(record?.botUser)}
</Link>
),
},
@ -115,10 +119,12 @@ const BotListV1 = ({
dataIndex: 'description',
key: 'description',
render: (_, record) =>
record?.description ? (
<RichTextEditorPreviewer markdown={record?.description || ''} />
record?.botUser?.description ? (
<RichTextEditorPreviewer
markdown={record?.botUser?.description || ''}
/>
) : (
'No Description'
<span data-testid="no-description">No Description</span>
),
},
{
@ -132,6 +138,7 @@ const BotListV1 = ({
placement="bottom"
title={deletePermission ? 'Delete' : NO_PERMISSION_FOR_ACTION}>
<Button
data-testid={`bot-delete-${getEntityName(record?.botUser)}`}
disabled={!deletePermission}
icon={
<SVGIcons
@ -194,6 +201,7 @@ const BotListV1 = ({
title={createPermission ? 'Add Bot' : NO_PERMISSION_FOR_ACTION}>
<Button
ghost
data-testid="add-bot"
disabled={!createPermission}
type="primary"
onClick={handleAddBotClick}>
@ -225,6 +233,7 @@ const BotListV1 = ({
<Tooltip
title={createPermission ? 'Add Bot' : NO_PERMISSION_FOR_ACTION}>
<Button
data-testid="add-bot"
disabled={!createPermission}
type="primary"
onClick={handleAddBotClick}>

View File

@ -55,6 +55,7 @@ import {
} from '../constants/regex.constants';
import { EntityType, FqnPart, TabSpecificField } from '../enums/entity.enum';
import { Ownership } from '../enums/mydata.enum';
import { Bot } from '../generated/entity/bot';
import { Dashboard } from '../generated/entity/data/dashboard';
import { Database } from '../generated/entity/data/database';
import { GlossaryTerm } from '../generated/entity/data/glossaryTerm';
@ -655,6 +656,7 @@ export const getEntityName = (
| Role
| GlossaryTerm
| Webhook
| Bot
) => {
return entity?.displayName || entity?.name || '';
};