mirror of
https://github.com/open-metadata/OpenMetadata.git
synced 2025-08-28 19:05:53 +00:00
migrated cyprss Bots spec to playwright (#17673)
This commit is contained in:
parent
00fe8399ad
commit
d952c1bd1e
@ -1,232 +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 {
|
|
||||||
customFormatDateTime,
|
|
||||||
getEpochMillisForFutureDays,
|
|
||||||
} from '../../../src/utils/date-time/DateTimeUtils';
|
|
||||||
import {
|
|
||||||
descriptionBox,
|
|
||||||
interceptURL,
|
|
||||||
uuid,
|
|
||||||
verifyResponseStatusCode,
|
|
||||||
} from '../../common/common';
|
|
||||||
import { DELETE_TERM } from '../../constants/constants';
|
|
||||||
import { GlobalSettingOptions } from '../../constants/settings.constant';
|
|
||||||
|
|
||||||
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 unlimitedExpiryTime = 'This token has no expiration date.';
|
|
||||||
const JWTToken = 'OpenMetadata JWT';
|
|
||||||
|
|
||||||
const expirationTime = {
|
|
||||||
oneday: '1',
|
|
||||||
sevendays: '7',
|
|
||||||
onemonth: '30',
|
|
||||||
twomonths: '60',
|
|
||||||
threemonths: '90',
|
|
||||||
};
|
|
||||||
const getCreatedBot = () => {
|
|
||||||
interceptURL('GET', `/api/v1/bots/name/${botName}*`, 'getCreatedBot');
|
|
||||||
// Click on created Bot name
|
|
||||||
cy.get(`[data-testid="bot-link-${botName}"]`).should('exist').click();
|
|
||||||
verifyResponseStatusCode('@getCreatedBot', 200);
|
|
||||||
};
|
|
||||||
|
|
||||||
const revokeToken = () => {
|
|
||||||
// Click on revoke button
|
|
||||||
cy.get('[data-testid="revoke-button"]').click();
|
|
||||||
// Verify the revoke text
|
|
||||||
cy.get('[data-testid="body-text"]').should(
|
|
||||||
'contain',
|
|
||||||
'Are you sure you want to revoke access for JWT Token?'
|
|
||||||
);
|
|
||||||
interceptURL('PUT', `/api/v1/users/revokeToken`, 'revokeToken');
|
|
||||||
// Click on confirm button
|
|
||||||
cy.get('[data-testid="save-button"]').click();
|
|
||||||
verifyResponseStatusCode('@revokeToken', 200);
|
|
||||||
|
|
||||||
// Verify the revoke is successful
|
|
||||||
cy.get('[data-testid="revoke-button"]').should('not.exist');
|
|
||||||
cy.get('[data-testid="auth-mechanism"]')
|
|
||||||
.should('be.visible')
|
|
||||||
.invoke('text')
|
|
||||||
.should('eq', 'OpenMetadata JWT');
|
|
||||||
cy.get('[data-testid="token-expiry"]').should('exist').should('be.visible');
|
|
||||||
cy.get('[data-testid="save-edit"]').should('exist').should('be.visible');
|
|
||||||
};
|
|
||||||
|
|
||||||
describe('Bots Page should work properly', { tags: 'Settings' }, () => {
|
|
||||||
beforeEach(() => {
|
|
||||||
cy.login();
|
|
||||||
interceptURL(
|
|
||||||
'GET',
|
|
||||||
'api/v1/bots?limit=*&include=non-deleted',
|
|
||||||
'getBotsList'
|
|
||||||
);
|
|
||||||
cy.settingClick(GlobalSettingOptions.BOTS);
|
|
||||||
verifyResponseStatusCode('@getBotsList', 200);
|
|
||||||
});
|
|
||||||
|
|
||||||
it('Verify ingestion bot delete button is always disabled', () => {
|
|
||||||
cy.get('[data-testid="bot-delete-ingestion-bot"]')
|
|
||||||
.should('exist')
|
|
||||||
.should('be.disabled');
|
|
||||||
});
|
|
||||||
|
|
||||||
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);
|
|
||||||
// Select expiry time
|
|
||||||
cy.get('[data-testid="token-expiry"]').should('be.visible').click();
|
|
||||||
cy.contains('1 hr').should('exist').should('be.visible').click();
|
|
||||||
// Enter description
|
|
||||||
cy.get(descriptionBox).type(description);
|
|
||||||
// Click on save button
|
|
||||||
cy.wait(1000);
|
|
||||||
interceptURL('post', '/api/v1/bots', 'createBot');
|
|
||||||
cy.get('[data-testid="save-user"]')
|
|
||||||
.scrollIntoView()
|
|
||||||
.should('be.visible')
|
|
||||||
.click();
|
|
||||||
verifyResponseStatusCode('@createBot', 201);
|
|
||||||
verifyResponseStatusCode('@getBotsList', 200);
|
|
||||||
// Verify bot is getting added in the bots listing page
|
|
||||||
cy.get('table').should('contain', botName).and('contain', description);
|
|
||||||
|
|
||||||
getCreatedBot();
|
|
||||||
cy.get('[data-testid="revoke-button"]')
|
|
||||||
.should('be.visible')
|
|
||||||
.should('contain', 'Revoke token');
|
|
||||||
|
|
||||||
cy.get('[data-testid="center-panel"]')
|
|
||||||
.should('be.visible')
|
|
||||||
.should('contain', `${JWTToken} Token`);
|
|
||||||
// Verify expiration time
|
|
||||||
cy.get('[data-testid="token-expiry"]').should('be.visible');
|
|
||||||
});
|
|
||||||
|
|
||||||
Object.values(expirationTime).forEach((expiry) => {
|
|
||||||
it(`Update token expiration for ${expiry} days`, () => {
|
|
||||||
getCreatedBot();
|
|
||||||
revokeToken();
|
|
||||||
// Click on dropdown
|
|
||||||
cy.get('[data-testid="token-expiry"]').click();
|
|
||||||
// Select the expiration period
|
|
||||||
cy.contains(`${expiry} days`).should('exist').click();
|
|
||||||
// Save the updated date
|
|
||||||
const expiryDate = customFormatDateTime(
|
|
||||||
getEpochMillisForFutureDays(expiry),
|
|
||||||
`ccc d'th' MMMM, yyyy`
|
|
||||||
);
|
|
||||||
cy.get('[data-testid="save-edit"]').should('be.visible').click();
|
|
||||||
cy.get('[data-testid="center-panel"]')
|
|
||||||
.find('[data-testid="revoke-button"]')
|
|
||||||
.should('be.visible');
|
|
||||||
// Verify the expiry time
|
|
||||||
cy.get('[data-testid="token-expiry"]')
|
|
||||||
.should('be.visible')
|
|
||||||
.invoke('text')
|
|
||||||
.should('contain', `Expires on ${expiryDate}`);
|
|
||||||
});
|
|
||||||
});
|
|
||||||
|
|
||||||
it('Update token expiration for unlimited days', () => {
|
|
||||||
getCreatedBot();
|
|
||||||
revokeToken();
|
|
||||||
// Click on expiry token dropdown
|
|
||||||
cy.get('[data-testid="token-expiry"]').click();
|
|
||||||
// Select unlimited days
|
|
||||||
cy.contains('Unlimited days').click();
|
|
||||||
// Save the selected changes
|
|
||||||
cy.get('[data-testid="save-edit"]').click();
|
|
||||||
// Verify the updated expiry time
|
|
||||||
cy.get('[data-testid="center-panel"]')
|
|
||||||
.find('[data-testid="revoke-button"]')
|
|
||||||
.should('be.visible');
|
|
||||||
// Verify the expiry time
|
|
||||||
cy.get('[data-testid="token-expiry"]')
|
|
||||||
.should('be.visible')
|
|
||||||
.invoke('text')
|
|
||||||
.should('contain', `${unlimitedExpiryTime}`);
|
|
||||||
});
|
|
||||||
|
|
||||||
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
|
|
||||||
|
|
||||||
cy.get('[data-testid="save-displayName"]').should('be.visible').click();
|
|
||||||
|
|
||||||
// Verify the display name is updated on bot details page
|
|
||||||
cy.get('[data-testid="left-panel"]').should('contain', updatedBotName);
|
|
||||||
cy.wait(1000);
|
|
||||||
// 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-${botName}"]`)
|
|
||||||
.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="page-layout-v1"]').should('not.contain', botName);
|
|
||||||
});
|
|
||||||
});
|
|
@ -0,0 +1,92 @@
|
|||||||
|
/*
|
||||||
|
* 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, test as base } from '@playwright/test';
|
||||||
|
import { GlobalSettingOptions } from '../../constant/settings';
|
||||||
|
import { BotClass } from '../../support/bot/BotClass';
|
||||||
|
import { UserClass } from '../../support/user/UserClass';
|
||||||
|
import { performAdminLogin } from '../../utils/admin';
|
||||||
|
import {
|
||||||
|
createBot,
|
||||||
|
deleteBot,
|
||||||
|
getCreatedBot,
|
||||||
|
tokenExpirationForDays,
|
||||||
|
tokenExpirationUnlimitedDays,
|
||||||
|
updateBotDetails,
|
||||||
|
} from '../../utils/bot';
|
||||||
|
import { redirectToHomePage } from '../../utils/common';
|
||||||
|
import { settingClick } from '../../utils/sidebar';
|
||||||
|
|
||||||
|
const adminUser = new UserClass();
|
||||||
|
const bot = new BotClass();
|
||||||
|
|
||||||
|
const test = base.extend<{ adminPage: Page }>({
|
||||||
|
adminPage: async ({ browser }, use) => {
|
||||||
|
const adminPage = await browser.newPage();
|
||||||
|
await adminUser.login(adminPage);
|
||||||
|
await use(adminPage);
|
||||||
|
await adminPage.close();
|
||||||
|
},
|
||||||
|
});
|
||||||
|
|
||||||
|
test.describe('Bots Page should work properly', () => {
|
||||||
|
test.beforeAll('Setup pre-requests', async ({ browser }) => {
|
||||||
|
const { apiContext, afterAction } = await performAdminLogin(browser);
|
||||||
|
await adminUser.create(apiContext);
|
||||||
|
await adminUser.setAdminRole(apiContext);
|
||||||
|
await bot.create(apiContext);
|
||||||
|
|
||||||
|
await afterAction();
|
||||||
|
});
|
||||||
|
|
||||||
|
test.afterAll('Cleanup', async ({ browser }) => {
|
||||||
|
const { apiContext, afterAction } = await performAdminLogin(browser);
|
||||||
|
await adminUser.delete(apiContext);
|
||||||
|
await bot.delete(apiContext);
|
||||||
|
|
||||||
|
await afterAction();
|
||||||
|
});
|
||||||
|
|
||||||
|
test('Verify ingestion bot delete button is always disabled', async ({
|
||||||
|
adminPage,
|
||||||
|
}) => {
|
||||||
|
await redirectToHomePage(adminPage);
|
||||||
|
await settingClick(adminPage, GlobalSettingOptions.BOTS);
|
||||||
|
|
||||||
|
await expect(
|
||||||
|
adminPage.getByTestId('bot-delete-ingestion-bot')
|
||||||
|
).toBeDisabled();
|
||||||
|
});
|
||||||
|
|
||||||
|
test('Create and Delete Bot', async ({ adminPage }) => {
|
||||||
|
await redirectToHomePage(adminPage);
|
||||||
|
await settingClick(adminPage, GlobalSettingOptions.BOTS);
|
||||||
|
await createBot(adminPage);
|
||||||
|
await deleteBot(adminPage);
|
||||||
|
});
|
||||||
|
|
||||||
|
test('Update display name and description', async ({ adminPage }) => {
|
||||||
|
await redirectToHomePage(adminPage);
|
||||||
|
await settingClick(adminPage, GlobalSettingOptions.BOTS);
|
||||||
|
await updateBotDetails(adminPage, bot.responseData);
|
||||||
|
});
|
||||||
|
|
||||||
|
test('Update token expiration', async ({ adminPage }) => {
|
||||||
|
test.slow(true);
|
||||||
|
|
||||||
|
await redirectToHomePage(adminPage);
|
||||||
|
await settingClick(adminPage, GlobalSettingOptions.BOTS);
|
||||||
|
await getCreatedBot(adminPage, bot.responseData.name);
|
||||||
|
await tokenExpirationForDays(adminPage);
|
||||||
|
await tokenExpirationUnlimitedDays(adminPage);
|
||||||
|
});
|
||||||
|
});
|
@ -0,0 +1,112 @@
|
|||||||
|
/*
|
||||||
|
* 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 { APIRequestContext } from '@playwright/test';
|
||||||
|
import { uuid } from '../../utils/common';
|
||||||
|
|
||||||
|
export type BotResponseDataType = {
|
||||||
|
name: string;
|
||||||
|
botUser: string;
|
||||||
|
description: string;
|
||||||
|
id?: string;
|
||||||
|
fullyQualifiedName?: string;
|
||||||
|
};
|
||||||
|
|
||||||
|
export type UserResponseDataType = {
|
||||||
|
botUser: undefined;
|
||||||
|
name: string;
|
||||||
|
description: string;
|
||||||
|
id?: string;
|
||||||
|
fullyQualifiedName?: string;
|
||||||
|
email: string;
|
||||||
|
isAdmin: boolean;
|
||||||
|
isBot: boolean;
|
||||||
|
authenticationMechanism: {
|
||||||
|
authType: string;
|
||||||
|
config: {
|
||||||
|
JWTTokenExpiry: string;
|
||||||
|
};
|
||||||
|
};
|
||||||
|
};
|
||||||
|
|
||||||
|
export class BotClass {
|
||||||
|
id = uuid();
|
||||||
|
data: BotResponseDataType;
|
||||||
|
userData: UserResponseDataType;
|
||||||
|
responseData: BotResponseDataType;
|
||||||
|
|
||||||
|
constructor(data?: BotResponseDataType) {
|
||||||
|
this.data = data ?? {
|
||||||
|
botUser: `PW%Bot-${this.id}`,
|
||||||
|
name: `PW%Bot-${this.id}`,
|
||||||
|
description: 'playwright for bot description',
|
||||||
|
};
|
||||||
|
this.userData = {
|
||||||
|
...this.data,
|
||||||
|
botUser: undefined,
|
||||||
|
email: `pw_bot${this.id}@gmail.com`,
|
||||||
|
isAdmin: false,
|
||||||
|
isBot: true,
|
||||||
|
authenticationMechanism: {
|
||||||
|
authType: 'JWT',
|
||||||
|
config: {
|
||||||
|
JWTTokenExpiry: 'OneHour',
|
||||||
|
},
|
||||||
|
},
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
get() {
|
||||||
|
return this.responseData;
|
||||||
|
}
|
||||||
|
|
||||||
|
async create(apiContext: APIRequestContext) {
|
||||||
|
const userResponse = await apiContext.put('/api/v1/users', {
|
||||||
|
data: this.userData,
|
||||||
|
});
|
||||||
|
|
||||||
|
const response = await apiContext.post('/api/v1/bots', {
|
||||||
|
data: this.data,
|
||||||
|
});
|
||||||
|
const data = await response.json();
|
||||||
|
this.responseData = data;
|
||||||
|
|
||||||
|
const userResponseData = await userResponse.json();
|
||||||
|
this.userData = userResponseData;
|
||||||
|
|
||||||
|
return data;
|
||||||
|
}
|
||||||
|
|
||||||
|
async delete(apiContext: APIRequestContext) {
|
||||||
|
const response = await apiContext.delete(
|
||||||
|
`/api/v1/bots/${this.responseData.id}?hardDelete=true&recursive=false`
|
||||||
|
);
|
||||||
|
|
||||||
|
return await response.json();
|
||||||
|
}
|
||||||
|
|
||||||
|
async patch(apiContext: APIRequestContext, data: Record<string, unknown>[]) {
|
||||||
|
const response = await apiContext.patch(
|
||||||
|
`/api/v1/bots/${this.responseData.id}`,
|
||||||
|
{
|
||||||
|
data,
|
||||||
|
headers: {
|
||||||
|
'Content-Type': 'application/json-patch+json',
|
||||||
|
},
|
||||||
|
}
|
||||||
|
);
|
||||||
|
|
||||||
|
this.responseData = await response.json();
|
||||||
|
|
||||||
|
return await response.json();
|
||||||
|
}
|
||||||
|
}
|
210
openmetadata-ui/src/main/resources/ui/playwright/utils/bot.ts
Normal file
210
openmetadata-ui/src/main/resources/ui/playwright/utils/bot.ts
Normal file
@ -0,0 +1,210 @@
|
|||||||
|
/*
|
||||||
|
* 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';
|
||||||
|
import {
|
||||||
|
customFormatDateTime,
|
||||||
|
getEpochMillisForFutureDays,
|
||||||
|
} from '../../src/utils/date-time/DateTimeUtils';
|
||||||
|
import { GlobalSettingOptions } from '../constant/settings';
|
||||||
|
import { BotResponseDataType } from '../support/bot/BotClass';
|
||||||
|
import { descriptionBox, toastNotification, uuid } from './common';
|
||||||
|
import { settingClick } from './sidebar';
|
||||||
|
import { revokeToken } from './user';
|
||||||
|
|
||||||
|
const botName = `bot-ct-test-${uuid()}`;
|
||||||
|
|
||||||
|
const BOT_DETAILS = {
|
||||||
|
botName: botName,
|
||||||
|
botEmail: `${botName}@mail.com`,
|
||||||
|
description: 'This is bot description',
|
||||||
|
updatedDescription: 'This is updated bot description',
|
||||||
|
updatedBotName: `updated-${botName}`,
|
||||||
|
unlimitedExpiryTime: 'This token has no expiration date.',
|
||||||
|
JWTToken: 'OpenMetadata JWT',
|
||||||
|
};
|
||||||
|
|
||||||
|
const EXPIRATION_TIME = [1, 7, 30, 60, 90];
|
||||||
|
|
||||||
|
export const getCreatedBot = async (page: Page, botName: string) => {
|
||||||
|
// Click on created Bot name
|
||||||
|
const fetchResponse = page.waitForResponse(
|
||||||
|
`/api/v1/bots/name/${encodeURIComponent(botName)}?*`
|
||||||
|
);
|
||||||
|
await page.getByTestId(`bot-link-${botName}`).click();
|
||||||
|
await fetchResponse;
|
||||||
|
};
|
||||||
|
|
||||||
|
export const createBot = async (page: Page) => {
|
||||||
|
// Click on add bot button
|
||||||
|
await page.getByTestId('add-bot').click();
|
||||||
|
|
||||||
|
// Fill the form details
|
||||||
|
await page.getByTestId('email').fill(BOT_DETAILS.botEmail);
|
||||||
|
|
||||||
|
await page.getByTestId('displayName').fill(BOT_DETAILS.botName);
|
||||||
|
|
||||||
|
// Select expiry time
|
||||||
|
await page.click('[data-testid="token-expiry"]');
|
||||||
|
await page.locator('[title="1 hr"] div').click();
|
||||||
|
|
||||||
|
await page.locator(descriptionBox).fill(BOT_DETAILS.description);
|
||||||
|
|
||||||
|
const saveResponse = page.waitForResponse('/api/v1/bots');
|
||||||
|
await page.click('[data-testid="save-user"]');
|
||||||
|
await saveResponse;
|
||||||
|
|
||||||
|
// Verify bot is getting added in the bots listing page
|
||||||
|
const table = page.locator('table');
|
||||||
|
|
||||||
|
await expect(table).toContainText(BOT_DETAILS.botName);
|
||||||
|
await expect(table).toContainText(BOT_DETAILS.description);
|
||||||
|
|
||||||
|
// Get created bot
|
||||||
|
await getCreatedBot(page, botName); // Replace with actual function to get created bot
|
||||||
|
|
||||||
|
await expect(page.getByTestId('revoke-button')).toContainText('Revoke token');
|
||||||
|
|
||||||
|
await expect(page.getByTestId('center-panel')).toContainText(
|
||||||
|
`${BOT_DETAILS.JWTToken} Token`
|
||||||
|
);
|
||||||
|
|
||||||
|
await expect(page.getByTestId('token-expiry')).toBeVisible();
|
||||||
|
|
||||||
|
await toastNotification(page, 'Bot created successfully.');
|
||||||
|
};
|
||||||
|
|
||||||
|
export const deleteBot = async (page: Page) => {
|
||||||
|
await settingClick(page, GlobalSettingOptions.BOTS);
|
||||||
|
|
||||||
|
// Click on delete button
|
||||||
|
await page.getByTestId(`bot-delete-${botName}`).click();
|
||||||
|
|
||||||
|
await page.getByTestId('hard-delete-option').click();
|
||||||
|
|
||||||
|
await page.getByTestId('confirmation-text-input').fill('DELETE');
|
||||||
|
|
||||||
|
const deleteResponse = page.waitForResponse(`/api/v1/bots/*`);
|
||||||
|
|
||||||
|
await page.getByTestId('confirm-button').click();
|
||||||
|
|
||||||
|
await deleteResponse;
|
||||||
|
|
||||||
|
await toastNotification(page, /deleted successfully!/);
|
||||||
|
|
||||||
|
await expect(page.getByTestId('page-layout-v1')).not.toContainText(botName);
|
||||||
|
};
|
||||||
|
|
||||||
|
export const updateBotDetails = async (
|
||||||
|
page: Page,
|
||||||
|
botData: BotResponseDataType
|
||||||
|
) => {
|
||||||
|
await getCreatedBot(page, botData.name);
|
||||||
|
|
||||||
|
await page.click('[data-testid="edit-displayName"]');
|
||||||
|
await page.getByTestId('displayName').fill(BOT_DETAILS.updatedBotName);
|
||||||
|
|
||||||
|
const updateDisplayNameResponse = page.waitForResponse(
|
||||||
|
`api/v1/bots/${botData.id ?? ''}`
|
||||||
|
);
|
||||||
|
await page.getByTestId('save-displayName').click();
|
||||||
|
await updateDisplayNameResponse;
|
||||||
|
|
||||||
|
// Verify the display name is updated on bot details page
|
||||||
|
await expect(
|
||||||
|
page.locator('[data-testid="left-panel"] .display-name')
|
||||||
|
).toContainText(BOT_DETAILS.updatedBotName);
|
||||||
|
|
||||||
|
// Click on edit description button
|
||||||
|
await page.getByTestId('edit-description').click();
|
||||||
|
await page.locator(descriptionBox).fill(BOT_DETAILS.updatedDescription);
|
||||||
|
|
||||||
|
const updateDescriptionResponse = page.waitForResponse(
|
||||||
|
`api/v1/bots/${botData.id ?? ''}`
|
||||||
|
);
|
||||||
|
await page.getByTestId('save').click();
|
||||||
|
await updateDescriptionResponse;
|
||||||
|
|
||||||
|
// Click on the breadcrumb link to go back to the bots listing page
|
||||||
|
const getBotsPageResponse = page.waitForResponse('/api/v1/bots*');
|
||||||
|
await page.locator('[data-testid="breadcrumb-link"]').first().click();
|
||||||
|
await getBotsPageResponse;
|
||||||
|
|
||||||
|
// Verify the updated name is displayed in the Bots listing page
|
||||||
|
await expect(
|
||||||
|
page.getByTestId(`bot-link-${BOT_DETAILS.updatedBotName}`)
|
||||||
|
).toContainText(BOT_DETAILS.updatedBotName);
|
||||||
|
|
||||||
|
await expect(
|
||||||
|
page.locator(
|
||||||
|
`[data-row-key="${botData.name}"] [data-testid="markdown-parser"]`
|
||||||
|
)
|
||||||
|
).toContainText(BOT_DETAILS.updatedDescription);
|
||||||
|
};
|
||||||
|
|
||||||
|
export const tokenExpirationForDays = async (page: Page) => {
|
||||||
|
for (const expiryTime of EXPIRATION_TIME) {
|
||||||
|
await revokeToken(page, true);
|
||||||
|
|
||||||
|
// Click on dropdown
|
||||||
|
await page.click('[data-testid="token-expiry"]');
|
||||||
|
|
||||||
|
// Select the expiration period
|
||||||
|
await page.locator(`text=${expiryTime} days`).click();
|
||||||
|
|
||||||
|
// Save the updated date
|
||||||
|
const expiryDate = customFormatDateTime(
|
||||||
|
getEpochMillisForFutureDays(expiryTime),
|
||||||
|
`ccc d'th' MMMM, yyyy`
|
||||||
|
);
|
||||||
|
|
||||||
|
await page.click('[data-testid="save-edit"]');
|
||||||
|
|
||||||
|
await expect(
|
||||||
|
page.locator('[data-testid="center-panel"] [data-testid="revoke-button"]')
|
||||||
|
).toBeVisible();
|
||||||
|
|
||||||
|
// Verify the expiry time
|
||||||
|
const tokenExpiryText = await page
|
||||||
|
.locator('[data-testid="token-expiry"]')
|
||||||
|
.innerText();
|
||||||
|
|
||||||
|
expect(tokenExpiryText).toContain(`Expires on ${expiryDate}`);
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
export const tokenExpirationUnlimitedDays = async (page: Page) => {
|
||||||
|
await revokeToken(page, true);
|
||||||
|
|
||||||
|
// Click on expiry token dropdown
|
||||||
|
await page.click('[data-testid="token-expiry"]');
|
||||||
|
// Select unlimited days
|
||||||
|
await page.getByText('Unlimited days').click();
|
||||||
|
// Save the selected changes
|
||||||
|
await page.click('[data-testid="save-edit"]');
|
||||||
|
|
||||||
|
// Verify the updated expiry time
|
||||||
|
const revokeButton = page.locator(
|
||||||
|
'[data-testid="center-panel"] [data-testid="revoke-button"]'
|
||||||
|
);
|
||||||
|
|
||||||
|
await expect(revokeButton).toBeVisible();
|
||||||
|
|
||||||
|
// Verify the expiry time
|
||||||
|
const tokenExpiry = page.locator('[data-testid="token-expiry"]');
|
||||||
|
|
||||||
|
await expect(tokenExpiry).toBeVisible();
|
||||||
|
|
||||||
|
const tokenExpiryText = await tokenExpiry.innerText();
|
||||||
|
|
||||||
|
expect(tokenExpiryText).toContain(BOT_DETAILS.unlimitedExpiryTime);
|
||||||
|
};
|
@ -469,11 +469,13 @@ export const generateToken = async (page: Page) => {
|
|||||||
await generateToken;
|
await generateToken;
|
||||||
};
|
};
|
||||||
|
|
||||||
export const revokeToken = async (page: Page) => {
|
export const revokeToken = async (page: Page, isBot?: boolean) => {
|
||||||
await page.click('[data-testid="revoke-button"]');
|
await page.click('[data-testid="revoke-button"]');
|
||||||
|
|
||||||
await expect(page.locator('[data-testid="body-text"]')).toContainText(
|
await expect(page.locator('[data-testid="body-text"]')).toContainText(
|
||||||
'Are you sure you want to revoke access for Personal Access Token?'
|
`Are you sure you want to revoke access for ${
|
||||||
|
isBot ? 'JWT Token' : 'Personal Access Token'
|
||||||
|
}?`
|
||||||
);
|
);
|
||||||
|
|
||||||
await page.click('[data-testid="save-button"]');
|
await page.click('[data-testid="save-button"]');
|
||||||
|
Loading…
x
Reference in New Issue
Block a user