mirror of
https://github.com/open-metadata/OpenMetadata.git
synced 2025-08-25 09:28:23 +00:00
1013 lines
25 KiB
TypeScript
1013 lines
25 KiB
TypeScript
![]() |
/*
|
||
|
* 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 { isEmpty, startCase } from 'lodash';
|
||
|
import { ALERT_DESCRIPTION } from '../constant/alert';
|
||
|
import {
|
||
|
AlertDetails,
|
||
|
ObservabilityCreationDetails,
|
||
|
} from '../constant/alert.interface';
|
||
|
import { DELETE_TERM } from '../constant/common';
|
||
|
import { SidebarItem } from '../constant/sidebar';
|
||
|
import {
|
||
|
clickOutside,
|
||
|
descriptionBox,
|
||
|
redirectToHomePage,
|
||
|
toastNotification,
|
||
|
uuid,
|
||
|
} from './common';
|
||
|
import { validateFormNameFieldInput } from './form';
|
||
|
import { sidebarClick } from './sidebar';
|
||
|
|
||
|
export const generateAlertName = () => `0%alert-playwright-${uuid()}`;
|
||
|
|
||
|
export const visitNotificationAlertPage = async (page: Page) => {
|
||
|
await redirectToHomePage(page);
|
||
|
await sidebarClick(page, SidebarItem.SETTINGS);
|
||
|
const getAlerts = page.waitForResponse('/api/v1/events/subscriptions?*');
|
||
|
const getActivityFeedAlertDetails = page.waitForResponse(
|
||
|
'/api/v1/events/subscriptions/name/ActivityFeedAlert?include=all'
|
||
|
);
|
||
|
await page.click('[data-testid="notifications"]');
|
||
|
await getAlerts;
|
||
|
await getActivityFeedAlertDetails;
|
||
|
};
|
||
|
|
||
|
export const visitObservabilityAlertPage = async (page: Page) => {
|
||
|
await redirectToHomePage(page);
|
||
|
const getAlerts = page.waitForResponse(
|
||
|
'/api/v1/events/subscriptions?*alertType=Observability*'
|
||
|
);
|
||
|
await sidebarClick(page, SidebarItem.OBSERVABILITY_ALERT);
|
||
|
await getAlerts;
|
||
|
};
|
||
|
|
||
|
export const findPageWithAlert = async (
|
||
|
page: Page,
|
||
|
alertDetails: AlertDetails
|
||
|
) => {
|
||
|
const { id } = alertDetails;
|
||
|
const alertRow = page.locator(`[data-row-key="${id}"]`);
|
||
|
const nextButton = page.locator('[data-testid="next"]');
|
||
|
if ((await alertRow.isHidden()) && (await nextButton.isEnabled())) {
|
||
|
const getAlerts = page.waitForResponse('/api/v1/events/subscriptions?*');
|
||
|
await nextButton.click();
|
||
|
await getAlerts;
|
||
|
await page.waitForSelector('.ant-table-wrapper [data-testid="loader"]', {
|
||
|
state: 'detached',
|
||
|
});
|
||
|
await findPageWithAlert(page, alertDetails);
|
||
|
}
|
||
|
};
|
||
|
|
||
|
export const visitEditAlertPage = async (
|
||
|
page: Page,
|
||
|
alertDetails: AlertDetails,
|
||
|
isNotificationAlert = true
|
||
|
) => {
|
||
|
if (isNotificationAlert) {
|
||
|
await visitNotificationAlertPage(page);
|
||
|
} else {
|
||
|
await visitObservabilityAlertPage(page);
|
||
|
}
|
||
|
const { id: alertId } = alertDetails;
|
||
|
|
||
|
await findPageWithAlert(page, alertDetails);
|
||
|
await page.click(
|
||
|
`[data-row-key="${alertId}"] [data-testid="alert-edit-${alertDetails.name}"]`
|
||
|
);
|
||
|
|
||
|
// Check alert name
|
||
|
await expect(page.locator('#name')).toHaveValue(alertDetails.name);
|
||
|
};
|
||
|
|
||
|
export const visitAlertDetailsPage = async (
|
||
|
page: Page,
|
||
|
alertDetails: AlertDetails
|
||
|
) => {
|
||
|
await findPageWithAlert(page, alertDetails);
|
||
|
|
||
|
const getAlertDetails = page.waitForResponse(
|
||
|
'/api/v1/events/subscriptions/name/*'
|
||
|
);
|
||
|
await page
|
||
|
.locator(`[data-row-key="${alertDetails.id}"]`)
|
||
|
.getByText(alertDetails.name)
|
||
|
.click();
|
||
|
await getAlertDetails;
|
||
|
};
|
||
|
|
||
|
export const deleteAlertSteps = async (page: Page, name: string) => {
|
||
|
await page.getByTestId(`alert-delete-${name}`).click();
|
||
|
|
||
|
await expect(page.locator('.ant-modal-header')).toHaveText(
|
||
|
`Delete subscription "${name}"`
|
||
|
);
|
||
|
|
||
|
await page.fill('[data-testid="confirmation-text-input"]', DELETE_TERM);
|
||
|
|
||
|
const deleteAlert = page.waitForResponse(
|
||
|
(response) =>
|
||
|
response.request().method() === 'DELETE' && response.status() === 200
|
||
|
);
|
||
|
await page.click('[data-testid="confirm-button"]');
|
||
|
await deleteAlert;
|
||
|
|
||
|
await toastNotification(page, `"${name}" deleted successfully!`);
|
||
|
};
|
||
|
|
||
|
export const addOwnerFilter = async ({
|
||
|
page,
|
||
|
filterNumber,
|
||
|
ownerName,
|
||
|
exclude = false,
|
||
|
selectId = 'Owner',
|
||
|
}: {
|
||
|
page: Page;
|
||
|
filterNumber: number;
|
||
|
ownerName: string;
|
||
|
exclude?: boolean;
|
||
|
selectId?: string;
|
||
|
}) => {
|
||
|
// Select owner filter
|
||
|
await page.click(`[data-testid="filter-select-${filterNumber}"]`);
|
||
|
await page.click(`[data-testid="${selectId}-filter-option"]:visible`);
|
||
|
|
||
|
// Search and select owner
|
||
|
const getSearchResult = page.waitForResponse('/api/v1/search/query?q=*');
|
||
|
await page.waitForSelector('.ant-select-dropdown:visible');
|
||
|
await page.fill(
|
||
|
'[data-testid="owner-name-select"] [role="combobox"]',
|
||
|
ownerName,
|
||
|
{
|
||
|
force: true,
|
||
|
}
|
||
|
);
|
||
|
await getSearchResult;
|
||
|
await page
|
||
|
.locator(`.ant-select-dropdown:visible [title="${ownerName}"]`)
|
||
|
.click();
|
||
|
|
||
|
await expect(
|
||
|
page.getByTestId('owner-name-select').getByTitle(ownerName)
|
||
|
).toBeAttached();
|
||
|
|
||
|
if (exclude) {
|
||
|
// Change filter effect
|
||
|
await page.click(`[data-testid="filter-switch-${filterNumber}"]`);
|
||
|
}
|
||
|
};
|
||
|
|
||
|
export const addEntityFQNFilter = async ({
|
||
|
page,
|
||
|
filterNumber,
|
||
|
entityFQN,
|
||
|
exclude = false,
|
||
|
selectId = 'Entity FQN',
|
||
|
}: {
|
||
|
page: Page;
|
||
|
filterNumber: number;
|
||
|
entityFQN: string;
|
||
|
exclude?: boolean;
|
||
|
selectId?: string;
|
||
|
}) => {
|
||
|
// Select entity FQN filter
|
||
|
await page.click(`[data-testid="filter-select-${filterNumber}"]`);
|
||
|
await page.click(`[data-testid="${selectId}-filter-option"]:visible`);
|
||
|
|
||
|
// Search and select entity
|
||
|
const getSearchResult = page.waitForResponse('/api/v1/search/query?q=*');
|
||
|
await page.fill(
|
||
|
'[data-testid="fqn-list-select"] [role="combobox"]',
|
||
|
entityFQN,
|
||
|
{
|
||
|
force: true,
|
||
|
}
|
||
|
);
|
||
|
await getSearchResult;
|
||
|
await page.click(`.ant-select-dropdown:visible [title="${entityFQN}"]`);
|
||
|
|
||
|
await expect(
|
||
|
page.getByTestId('fqn-list-select').getByTitle(entityFQN)
|
||
|
).toBeAttached();
|
||
|
|
||
|
if (exclude) {
|
||
|
// Change filter effect
|
||
|
await page.click(`[data-testid="filter-switch-${filterNumber}"]`);
|
||
|
}
|
||
|
};
|
||
|
|
||
|
export const addEventTypeFilter = async ({
|
||
|
page,
|
||
|
filterNumber,
|
||
|
eventType,
|
||
|
exclude = false,
|
||
|
}: {
|
||
|
page: Page;
|
||
|
filterNumber: number;
|
||
|
eventType: string;
|
||
|
exclude?: boolean;
|
||
|
}) => {
|
||
|
// Select event type filter
|
||
|
await page.click(`[data-testid="filter-select-${filterNumber}"]`);
|
||
|
await page.click(`[data-testid="Event Type-filter-option"]:visible`);
|
||
|
|
||
|
// Search and select event type
|
||
|
await page.fill(
|
||
|
'[data-testid="event-type-select"] [role="combobox"]',
|
||
|
eventType,
|
||
|
{
|
||
|
force: true,
|
||
|
}
|
||
|
);
|
||
|
await page.click(
|
||
|
`.ant-select-dropdown:visible [title="${startCase(eventType)}"]`
|
||
|
);
|
||
|
|
||
|
await expect(page.getByTestId('event-type-select')).toHaveText(
|
||
|
startCase(eventType)
|
||
|
);
|
||
|
|
||
|
if (exclude) {
|
||
|
// Change filter effect
|
||
|
await page.click(`[data-testid="filter-switch-${filterNumber}"]`);
|
||
|
}
|
||
|
};
|
||
|
|
||
|
export const addFilterWithUsersListInput = async ({
|
||
|
page,
|
||
|
filterTestId,
|
||
|
filterNumber,
|
||
|
updaterName,
|
||
|
exclude = false,
|
||
|
}: {
|
||
|
page: Page;
|
||
|
filterTestId: string;
|
||
|
filterNumber: number;
|
||
|
updaterName: string;
|
||
|
exclude?: boolean;
|
||
|
}) => {
|
||
|
// Select updater name filter
|
||
|
await page.click(`[data-testid="filter-select-${filterNumber}"]`);
|
||
|
await page.click(`[data-testid="${filterTestId}"]:visible`);
|
||
|
|
||
|
// Search and select user
|
||
|
const getSearchResult = page.waitForResponse('/api/v1/search/query?q=*');
|
||
|
await page.fill(
|
||
|
'[data-testid="user-name-select"] [role="combobox"]',
|
||
|
updaterName,
|
||
|
{
|
||
|
force: true,
|
||
|
}
|
||
|
);
|
||
|
await getSearchResult;
|
||
|
await page.click(`.ant-select-dropdown:visible [title="${updaterName}"]`);
|
||
|
|
||
|
await expect(page.getByTestId('user-name-select')).toHaveText(updaterName);
|
||
|
|
||
|
if (exclude) {
|
||
|
// Change filter effect
|
||
|
await page.click(`[data-testid="filter-switch-${filterNumber}"]`);
|
||
|
}
|
||
|
};
|
||
|
|
||
|
export const addDomainFilter = async ({
|
||
|
page,
|
||
|
filterNumber,
|
||
|
domainName,
|
||
|
domainDisplayName,
|
||
|
exclude = false,
|
||
|
}: {
|
||
|
page: Page;
|
||
|
filterNumber: number;
|
||
|
domainName: string;
|
||
|
domainDisplayName: string;
|
||
|
exclude?: boolean;
|
||
|
}) => {
|
||
|
// Select domain filter
|
||
|
await page.click(`[data-testid="filter-select-${filterNumber}"]`);
|
||
|
await page.click(`[data-testid="Domain-filter-option"]:visible`);
|
||
|
|
||
|
// Search and select domain
|
||
|
const getSearchResult = page.waitForResponse(
|
||
|
'/api/v1/search/query?q=**index=domain_search_index'
|
||
|
);
|
||
|
await page.fill(
|
||
|
'[data-testid="domain-select"] [role="combobox"]',
|
||
|
domainName,
|
||
|
{
|
||
|
force: true,
|
||
|
}
|
||
|
);
|
||
|
await getSearchResult;
|
||
|
await page.click(
|
||
|
`.ant-select-dropdown:visible [title="${domainDisplayName}"]`
|
||
|
);
|
||
|
|
||
|
await expect(
|
||
|
page.getByTestId('domain-select').getByTitle(domainDisplayName)
|
||
|
).toBeAttached();
|
||
|
|
||
|
if (exclude) {
|
||
|
// Change filter effect
|
||
|
await page.click(`[data-testid="filter-switch-${filterNumber}"]`);
|
||
|
}
|
||
|
};
|
||
|
|
||
|
export const addGMEFilter = async ({
|
||
|
page,
|
||
|
filterNumber,
|
||
|
exclude = false,
|
||
|
}: {
|
||
|
page: Page;
|
||
|
filterNumber: number;
|
||
|
exclude?: boolean;
|
||
|
}) => {
|
||
|
// Select general metadata events filter
|
||
|
await page.click(`[data-testid="filter-select-${filterNumber}"]`);
|
||
|
await page.click(
|
||
|
`[data-testid="General Metadata Events-filter-option"]:visible`
|
||
|
);
|
||
|
|
||
|
if (exclude) {
|
||
|
// Change filter effect
|
||
|
await page.click(`[data-testid="filter-switch-${filterNumber}"]`);
|
||
|
}
|
||
|
};
|
||
|
|
||
|
export const addInternalDestination = async ({
|
||
|
page,
|
||
|
destinationNumber,
|
||
|
category,
|
||
|
typeId,
|
||
|
type = '',
|
||
|
searchText = '',
|
||
|
}: {
|
||
|
page: Page;
|
||
|
destinationNumber: number;
|
||
|
category: string;
|
||
|
typeId?: string;
|
||
|
type?: string;
|
||
|
searchText?: string;
|
||
|
}) => {
|
||
|
// Select destination category
|
||
|
await page.click(
|
||
|
`[data-testid="destination-category-select-${destinationNumber}"]`
|
||
|
);
|
||
|
await page.click(`[data-testid="${category}-internal-option"]:visible`);
|
||
|
|
||
|
// Select the receivers
|
||
|
if (typeId) {
|
||
|
if (category === 'Teams' || category === 'Users') {
|
||
|
await page.click(
|
||
|
`[data-testid="destination-${destinationNumber}"] [data-testid="dropdown-trigger-button"]`
|
||
|
);
|
||
|
const getSearchResult = page.waitForResponse('/api/v1/search/query?q=*');
|
||
|
await page.fill(
|
||
|
`[data-testid="team-user-select-dropdown-${destinationNumber}"]:visible [data-testid="search-input"]`,
|
||
|
searchText
|
||
|
);
|
||
|
|
||
|
await getSearchResult;
|
||
|
await page.click(
|
||
|
`.ant-dropdown:visible [data-testid="${searchText}-option-label"]`
|
||
|
);
|
||
|
} else {
|
||
|
const getSearchResult = page.waitForResponse('/api/v1/search/query?q=*');
|
||
|
await page.fill(`[data-testid="${typeId}"]`, searchText);
|
||
|
await getSearchResult;
|
||
|
await page.click(`.ant-select-dropdown:visible [title="${searchText}"]`);
|
||
|
}
|
||
|
await clickOutside(page);
|
||
|
}
|
||
|
|
||
|
// Select destination type
|
||
|
await page.click(
|
||
|
`[data-testid="destination-type-select-${destinationNumber}"]`
|
||
|
);
|
||
|
await page.click(
|
||
|
`.select-options-container [data-testid="${type}-external-option"]:visible`
|
||
|
);
|
||
|
|
||
|
// Check the added destination type
|
||
|
await expect(
|
||
|
page
|
||
|
.getByTestId(`destination-type-select-${destinationNumber}`)
|
||
|
.getByTestId(`${type}-external-option`)
|
||
|
).toBeAttached();
|
||
|
};
|
||
|
|
||
|
export const addExternalDestination = async ({
|
||
|
page,
|
||
|
destinationNumber,
|
||
|
category,
|
||
|
secretKey,
|
||
|
input = '',
|
||
|
}: {
|
||
|
page: Page;
|
||
|
destinationNumber: number;
|
||
|
category: string;
|
||
|
input?: string;
|
||
|
secretKey?: string;
|
||
|
}) => {
|
||
|
// Select destination category
|
||
|
await page.click(
|
||
|
`[data-testid="destination-category-select-${destinationNumber}"]`
|
||
|
);
|
||
|
|
||
|
// Select external tab
|
||
|
await page.click(`[data-testid="tab-label-external"]:visible`);
|
||
|
|
||
|
// Select destination category option
|
||
|
await page.click(
|
||
|
`[data-testid="destination-category-dropdown-${destinationNumber}"]:visible [data-testid="${category}-external-option"]:visible`
|
||
|
);
|
||
|
|
||
|
// Input the destination receivers value
|
||
|
if (category === 'Email') {
|
||
|
await page.fill(
|
||
|
`[data-testid="email-input-${destinationNumber}"] [role="combobox"]`,
|
||
|
input
|
||
|
);
|
||
|
await page.keyboard.press('Enter');
|
||
|
} else {
|
||
|
await page.fill(
|
||
|
`[data-testid="endpoint-input-${destinationNumber}"]`,
|
||
|
input
|
||
|
);
|
||
|
}
|
||
|
|
||
|
// Input the secret key value
|
||
|
if (category === 'Webhook' && secretKey) {
|
||
|
await page.fill(
|
||
|
`[data-testid="secret-key-input-${destinationNumber}"]`,
|
||
|
secretKey
|
||
|
);
|
||
|
}
|
||
|
};
|
||
|
|
||
|
const checkActionOrFilterDetails = async ({
|
||
|
page,
|
||
|
filters,
|
||
|
}: {
|
||
|
page: Page;
|
||
|
filters: AlertDetails['input']['filters'];
|
||
|
}) => {
|
||
|
if (!isEmpty(filters)) {
|
||
|
for (const filter of filters) {
|
||
|
const index = filters.indexOf(filter);
|
||
|
|
||
|
// Check filter effect
|
||
|
await expect(
|
||
|
page.locator('[data-testid="effect-value"]').nth(index)
|
||
|
).toContainText(startCase(filter.effect));
|
||
|
|
||
|
// Check filter name
|
||
|
await expect(
|
||
|
page.locator('[data-testid="filter-name"]').nth(index)
|
||
|
).toContainText(startCase(filter.name));
|
||
|
|
||
|
if (!isEmpty(filter.arguments)) {
|
||
|
for (const argument of filter.arguments) {
|
||
|
// Check filter arguments
|
||
|
await expect(
|
||
|
page.locator(`[data-testid="argument-container-${argument.name}"]`)
|
||
|
).toBeAttached();
|
||
|
|
||
|
for (const val of argument.input) {
|
||
|
await expect(
|
||
|
page.locator(`[data-testid="argument-value"]`).getByText(val)
|
||
|
).toBeAttached();
|
||
|
}
|
||
|
}
|
||
|
}
|
||
|
}
|
||
|
}
|
||
|
};
|
||
|
|
||
|
export const verifyAlertDetails = async ({
|
||
|
page,
|
||
|
alertDetails,
|
||
|
isObservabilityAlert = false,
|
||
|
}: {
|
||
|
page: Page;
|
||
|
alertDetails: AlertDetails;
|
||
|
isObservabilityAlert?: boolean;
|
||
|
}) => {
|
||
|
const { name, description, filteringRules, input, destinations } =
|
||
|
alertDetails;
|
||
|
|
||
|
const triggerName = filteringRules.resources[0];
|
||
|
const filters = input.filters;
|
||
|
|
||
|
// Check created alert details
|
||
|
await expect(page.getByTestId('alert-details-container')).toBeAttached();
|
||
|
|
||
|
// Check alert name
|
||
|
await expect(page.getByTestId('alert-name')).toContainText(name);
|
||
|
|
||
|
if (description) {
|
||
|
// Check alert name
|
||
|
await expect(page.getByTestId('alert-description')).toContainText(
|
||
|
description
|
||
|
);
|
||
|
}
|
||
|
|
||
|
// Check trigger name
|
||
|
await expect(page.getByTestId('resource-name')).toContainText(
|
||
|
startCase(triggerName)
|
||
|
);
|
||
|
|
||
|
// Check filter details
|
||
|
await checkActionOrFilterDetails({ page, filters });
|
||
|
|
||
|
if (isObservabilityAlert) {
|
||
|
const actions = input.actions;
|
||
|
|
||
|
// Check action details
|
||
|
await checkActionOrFilterDetails({ page, filters: actions });
|
||
|
}
|
||
|
|
||
|
if (!isEmpty(destinations)) {
|
||
|
// Check connection timeout details
|
||
|
await expect(page.getByTestId('connection-timeout')).toContainText(
|
||
|
destinations[0].timeout.toString()
|
||
|
);
|
||
|
|
||
|
for (const destination of destinations) {
|
||
|
// Check Destination category
|
||
|
await expect(
|
||
|
page
|
||
|
.getByTestId(`destination-${destination.category}`)
|
||
|
.getByTestId('category-value')
|
||
|
).toContainText(destination.category);
|
||
|
|
||
|
// Check Destination type
|
||
|
await expect(
|
||
|
page
|
||
|
.getByTestId(`destination-${destination.category}`)
|
||
|
.getByTestId('destination-type')
|
||
|
).toContainText(startCase(destination.type));
|
||
|
|
||
|
if (!isEmpty(destination.config?.secretKey)) {
|
||
|
// Check secret key is present
|
||
|
await expect(
|
||
|
page.getByTestId(`destination-${destination.category}`)
|
||
|
).toContainText('Secret Key');
|
||
|
}
|
||
|
|
||
|
if (!isEmpty(destination.config?.receivers)) {
|
||
|
// Check Destination receivers
|
||
|
for (const receiver of destination.config.receivers) {
|
||
|
await expect(page.getByTestId(`receiver-${receiver}`)).toBeAttached();
|
||
|
}
|
||
|
}
|
||
|
}
|
||
|
}
|
||
|
};
|
||
|
|
||
|
export const addGetSchemaChangesAction = async ({
|
||
|
page,
|
||
|
filterNumber,
|
||
|
exclude = false,
|
||
|
}: {
|
||
|
page: Page;
|
||
|
filterNumber: number;
|
||
|
exclude?: boolean;
|
||
|
}) => {
|
||
|
// Select owner filter
|
||
|
await page.click(`[data-testid="trigger-select-${filterNumber}"]`);
|
||
|
await page.click(`[data-testid="Get Schema Changes-filter-option"]:visible`);
|
||
|
|
||
|
if (exclude) {
|
||
|
// Change filter effect
|
||
|
await page.click(`[data-testid="filter-switch-${filterNumber}"]`);
|
||
|
}
|
||
|
};
|
||
|
|
||
|
export const addPipelineStatusUpdatesAction = async ({
|
||
|
page,
|
||
|
filterNumber,
|
||
|
statusName,
|
||
|
exclude = false,
|
||
|
}: {
|
||
|
page: Page;
|
||
|
filterNumber: number;
|
||
|
statusName: string;
|
||
|
exclude?: boolean;
|
||
|
}) => {
|
||
|
// Select pipeline status action
|
||
|
await page.click(`[data-testid="trigger-select-${filterNumber}"]`);
|
||
|
await page.click(
|
||
|
`[data-testid="Get Pipeline Status Updates-filter-option"]:visible`
|
||
|
);
|
||
|
|
||
|
// Search and select pipeline status input
|
||
|
await page.fill(
|
||
|
'[data-testid="pipeline-status-select"] [role="combobox"]',
|
||
|
statusName,
|
||
|
{
|
||
|
force: true,
|
||
|
}
|
||
|
);
|
||
|
await page.click(`[title="${statusName}"]:visible`);
|
||
|
|
||
|
await expect(page.getByTestId('pipeline-status-select')).toHaveText(
|
||
|
statusName
|
||
|
);
|
||
|
|
||
|
await clickOutside(page);
|
||
|
|
||
|
if (exclude) {
|
||
|
// Change action effect
|
||
|
await page.click(`[data-testid="trigger-switch-${filterNumber}"]`);
|
||
|
}
|
||
|
};
|
||
|
|
||
|
export const addMultipleFilters = async ({
|
||
|
page,
|
||
|
user1,
|
||
|
user2,
|
||
|
domain,
|
||
|
dashboard,
|
||
|
}: {
|
||
|
page: Page;
|
||
|
user1;
|
||
|
user2;
|
||
|
domain;
|
||
|
dashboard;
|
||
|
}) => {
|
||
|
// Add owner filter
|
||
|
await page.click('[data-testid="add-filters"]');
|
||
|
await addOwnerFilter({
|
||
|
page,
|
||
|
filterNumber: 0,
|
||
|
ownerName: user1.getUserName(),
|
||
|
});
|
||
|
|
||
|
// Add entityFQN filter
|
||
|
await page.click('[data-testid="add-filters"]');
|
||
|
await addEntityFQNFilter({
|
||
|
page,
|
||
|
filterNumber: 1,
|
||
|
entityFQN: (dashboard.entityResponseData as { fullyQualifiedName: string })
|
||
|
.fullyQualifiedName,
|
||
|
exclude: true,
|
||
|
});
|
||
|
|
||
|
// Add event type filter
|
||
|
await page.click('[data-testid="add-filters"]');
|
||
|
await addEventTypeFilter({
|
||
|
page,
|
||
|
filterNumber: 2,
|
||
|
eventType: 'entityCreated',
|
||
|
});
|
||
|
|
||
|
// Add users list filter
|
||
|
await page.click('[data-testid="add-filters"]');
|
||
|
await addFilterWithUsersListInput({
|
||
|
page,
|
||
|
filterTestId: 'Updater Name-filter-option',
|
||
|
filterNumber: 3,
|
||
|
updaterName: user2.getUserName(),
|
||
|
exclude: true,
|
||
|
});
|
||
|
|
||
|
// Add domain filter
|
||
|
await page.click('[data-testid="add-filters"]');
|
||
|
await addDomainFilter({
|
||
|
page,
|
||
|
filterNumber: 4,
|
||
|
domainName: domain.responseData.name,
|
||
|
domainDisplayName: domain.responseData.displayName,
|
||
|
});
|
||
|
|
||
|
// Add general metadata events filter
|
||
|
await page.click('[data-testid="add-filters"]');
|
||
|
await addGMEFilter({ page, filterNumber: 5 });
|
||
|
};
|
||
|
|
||
|
export const inputBasicAlertInformation = async ({
|
||
|
page,
|
||
|
name,
|
||
|
createButtonId = 'create-notification',
|
||
|
sourceName,
|
||
|
sourceDisplayName,
|
||
|
}: {
|
||
|
page: Page;
|
||
|
createButtonId?: string;
|
||
|
name: string;
|
||
|
sourceName: string;
|
||
|
sourceDisplayName: string;
|
||
|
}) => {
|
||
|
await page.click(`[data-testid="${createButtonId}"]`);
|
||
|
|
||
|
// Enter alert name
|
||
|
await validateFormNameFieldInput({
|
||
|
page,
|
||
|
value: name,
|
||
|
fieldName: 'Name',
|
||
|
errorDivSelector: '#name_help',
|
||
|
});
|
||
|
|
||
|
// Enter description
|
||
|
await page.locator(descriptionBox).clear();
|
||
|
await page.locator(descriptionBox).fill(ALERT_DESCRIPTION);
|
||
|
|
||
|
// Select all source
|
||
|
await page.click('[data-testid="add-source-button"]');
|
||
|
|
||
|
await page
|
||
|
.getByTestId('drop-down-menu')
|
||
|
.getByTestId(`${sourceName}-option`)
|
||
|
.click();
|
||
|
|
||
|
await expect(page.getByTestId('source-select')).toHaveText(sourceDisplayName);
|
||
|
};
|
||
|
|
||
|
export const saveAlertAndVerifyResponse = async (page: Page) => {
|
||
|
const data = {
|
||
|
alertDetails: {
|
||
|
id: '',
|
||
|
name: '',
|
||
|
description: '',
|
||
|
filteringRules: { resources: [] },
|
||
|
input: { filters: [], actions: [] },
|
||
|
destinations: [],
|
||
|
},
|
||
|
};
|
||
|
|
||
|
const getAlertDetails = page.waitForResponse(
|
||
|
'/api/v1/events/subscriptions/name/*'
|
||
|
);
|
||
|
const createAlert = page.waitForResponse(
|
||
|
(response) => response.request().method() === 'POST'
|
||
|
);
|
||
|
|
||
|
// Click save
|
||
|
await page.click('[data-testid="save-button"]');
|
||
|
await createAlert.then(async (response) => {
|
||
|
data.alertDetails = await response.json();
|
||
|
|
||
|
expect(response.status()).toEqual(201);
|
||
|
});
|
||
|
await toastNotification(page, 'Alerts created successfully.');
|
||
|
|
||
|
// Check if the alert details page is visible
|
||
|
await getAlertDetails;
|
||
|
|
||
|
await expect(page.getByTestId('alert-details-container')).toBeAttached();
|
||
|
|
||
|
return data.alertDetails;
|
||
|
};
|
||
|
|
||
|
export const deleteAlert = async (
|
||
|
page: Page,
|
||
|
alertDetails: AlertDetails,
|
||
|
isNotificationAlert = true
|
||
|
) => {
|
||
|
if (isNotificationAlert) {
|
||
|
await visitNotificationAlertPage(page);
|
||
|
} else {
|
||
|
await visitObservabilityAlertPage(page);
|
||
|
}
|
||
|
await findPageWithAlert(page, alertDetails);
|
||
|
await deleteAlertSteps(page, alertDetails.name);
|
||
|
};
|
||
|
|
||
|
export const getObservabilityCreationDetails = ({
|
||
|
tableName1,
|
||
|
tableName2,
|
||
|
testCaseName,
|
||
|
ingestionPipelineName,
|
||
|
domainName,
|
||
|
domainDisplayName,
|
||
|
userName,
|
||
|
testSuiteFQN,
|
||
|
}: {
|
||
|
tableName1: string;
|
||
|
tableName2: string;
|
||
|
testCaseName: string;
|
||
|
ingestionPipelineName: string;
|
||
|
domainName: string;
|
||
|
domainDisplayName: string;
|
||
|
userName: string;
|
||
|
testSuiteFQN: string;
|
||
|
}): Array<ObservabilityCreationDetails> => {
|
||
|
return [
|
||
|
{
|
||
|
source: 'table',
|
||
|
sourceDisplayName: 'Table',
|
||
|
filters: [
|
||
|
{
|
||
|
name: 'Table Name',
|
||
|
inputSelector: 'fqn-list-select',
|
||
|
inputValue: tableName1,
|
||
|
exclude: true,
|
||
|
},
|
||
|
{
|
||
|
name: 'Domain',
|
||
|
inputSelector: 'domain-select',
|
||
|
inputValue: domainName,
|
||
|
inputValueId: domainDisplayName,
|
||
|
exclude: false,
|
||
|
},
|
||
|
{
|
||
|
name: 'Owner Name',
|
||
|
inputSelector: 'owner-name-select',
|
||
|
inputValue: userName,
|
||
|
exclude: true,
|
||
|
},
|
||
|
],
|
||
|
actions: [
|
||
|
{
|
||
|
name: 'Get Schema Changes',
|
||
|
exclude: true,
|
||
|
},
|
||
|
{
|
||
|
name: 'Get Table Metrics Updates',
|
||
|
exclude: false,
|
||
|
},
|
||
|
],
|
||
|
destinations: [
|
||
|
{
|
||
|
mode: 'internal',
|
||
|
category: 'Owners',
|
||
|
type: 'Email',
|
||
|
},
|
||
|
{
|
||
|
mode: 'external',
|
||
|
category: 'Webhook',
|
||
|
inputValue: 'https://webhook.com',
|
||
|
secretKey: 'secret_key',
|
||
|
},
|
||
|
],
|
||
|
},
|
||
|
{
|
||
|
source: 'ingestionPipeline',
|
||
|
sourceDisplayName: 'Ingestion Pipeline',
|
||
|
filters: [
|
||
|
{
|
||
|
name: 'Ingestion Pipeline Name',
|
||
|
inputSelector: 'fqn-list-select',
|
||
|
inputValue: ingestionPipelineName,
|
||
|
exclude: false,
|
||
|
},
|
||
|
{
|
||
|
name: 'Domain',
|
||
|
inputSelector: 'domain-select',
|
||
|
inputValue: domainName,
|
||
|
inputValueId: domainDisplayName,
|
||
|
exclude: false,
|
||
|
},
|
||
|
{
|
||
|
name: 'Owner Name',
|
||
|
inputSelector: 'owner-name-select',
|
||
|
inputValue: userName,
|
||
|
exclude: true,
|
||
|
},
|
||
|
],
|
||
|
actions: [
|
||
|
{
|
||
|
name: 'Get Ingestion Pipeline Status Updates',
|
||
|
inputs: [
|
||
|
{
|
||
|
inputSelector: 'pipeline-status-select',
|
||
|
inputValue: 'Queued',
|
||
|
},
|
||
|
],
|
||
|
exclude: false,
|
||
|
},
|
||
|
],
|
||
|
destinations: [
|
||
|
{
|
||
|
mode: 'internal',
|
||
|
category: 'Owners',
|
||
|
type: 'Email',
|
||
|
},
|
||
|
{
|
||
|
mode: 'external',
|
||
|
category: 'Email',
|
||
|
inputValue: 'test@example.com',
|
||
|
},
|
||
|
],
|
||
|
},
|
||
|
{
|
||
|
source: 'testCase',
|
||
|
sourceDisplayName: 'Test case',
|
||
|
filters: [
|
||
|
{
|
||
|
name: 'Test Case Name',
|
||
|
inputSelector: 'fqn-list-select',
|
||
|
inputValue: testCaseName,
|
||
|
exclude: true,
|
||
|
},
|
||
|
{
|
||
|
name: 'Domain',
|
||
|
inputSelector: 'domain-select',
|
||
|
inputValue: domainName,
|
||
|
inputValueId: domainDisplayName,
|
||
|
exclude: false,
|
||
|
},
|
||
|
{
|
||
|
name: 'Owner Name',
|
||
|
inputSelector: 'owner-name-select',
|
||
|
inputValue: userName,
|
||
|
exclude: true,
|
||
|
},
|
||
|
{
|
||
|
name: 'Table Name A Test Case Belongs To',
|
||
|
inputSelector: 'table-name-select',
|
||
|
inputValue: tableName2,
|
||
|
exclude: false,
|
||
|
},
|
||
|
],
|
||
|
actions: [
|
||
|
{
|
||
|
name: 'Get Test Case Status Updates',
|
||
|
inputs: [
|
||
|
{
|
||
|
inputSelector: 'test-result-select',
|
||
|
inputValue: 'Success',
|
||
|
},
|
||
|
],
|
||
|
exclude: false,
|
||
|
},
|
||
|
{
|
||
|
name: 'Get Test Case Status Updates belonging to a Test Suite',
|
||
|
inputs: [
|
||
|
{
|
||
|
inputSelector: 'test-suite-select',
|
||
|
inputValue: testSuiteFQN,
|
||
|
waitForAPI: true,
|
||
|
},
|
||
|
{
|
||
|
inputSelector: 'test-status-select',
|
||
|
inputValue: 'Failed',
|
||
|
},
|
||
|
],
|
||
|
exclude: false,
|
||
|
},
|
||
|
],
|
||
|
destinations: [
|
||
|
{
|
||
|
mode: 'internal',
|
||
|
category: 'Users',
|
||
|
inputSelector: 'User-select',
|
||
|
inputValue: userName,
|
||
|
type: 'Email',
|
||
|
},
|
||
|
{
|
||
|
mode: 'external',
|
||
|
category: 'Webhook',
|
||
|
inputValue: 'https://webhook.com',
|
||
|
},
|
||
|
],
|
||
|
},
|
||
|
{
|
||
|
source: 'testSuite',
|
||
|
sourceDisplayName: 'Test Suite',
|
||
|
filters: [
|
||
|
{
|
||
|
name: 'Test Suite Name',
|
||
|
inputSelector: 'fqn-list-select',
|
||
|
inputValue: testSuiteFQN,
|
||
|
exclude: true,
|
||
|
},
|
||
|
{
|
||
|
name: 'Domain',
|
||
|
inputSelector: 'domain-select',
|
||
|
inputValue: domainName,
|
||
|
inputValueId: domainDisplayName,
|
||
|
exclude: false,
|
||
|
},
|
||
|
{
|
||
|
name: 'Owner Name',
|
||
|
inputSelector: 'owner-name-select',
|
||
|
inputValue: userName,
|
||
|
exclude: false,
|
||
|
},
|
||
|
],
|
||
|
actions: [],
|
||
|
destinations: [
|
||
|
{
|
||
|
mode: 'external',
|
||
|
category: 'Slack',
|
||
|
inputValue: 'https://slack.com',
|
||
|
},
|
||
|
],
|
||
|
},
|
||
|
];
|
||
|
};
|