mirror of
https://github.com/open-metadata/OpenMetadata.git
synced 2025-08-31 12:39:01 +00:00
Minor: Unit tests for observability and notification alert flow components (#14908)
This commit is contained in:
parent
ecfcdc89db
commit
3d7085e971
@ -387,17 +387,12 @@ const ObservabilityAlertsPage = withSuspenseFallback(
|
||||
)
|
||||
);
|
||||
|
||||
const ObservabilityAlertDetailsPage = withSuspenseFallback(
|
||||
React.lazy(
|
||||
() =>
|
||||
import(
|
||||
'../../pages/ObservabilityAlertDetailsPage/ObservabilityAlertDetailsPage'
|
||||
)
|
||||
)
|
||||
const AlertDetailsPage = withSuspenseFallback(
|
||||
React.lazy(() => import('../../pages/AlertDetailsPage/AlertDetailsPage'))
|
||||
);
|
||||
|
||||
const NotificationsAlertDetailsPage = () => (
|
||||
<ObservabilityAlertDetailsPage isNotificationAlert />
|
||||
<AlertDetailsPage isNotificationAlert />
|
||||
);
|
||||
|
||||
const AddObservabilityPage = withSuspenseFallback(
|
||||
@ -1070,7 +1065,7 @@ const AuthenticatedAppRouter: FunctionComponent = () => {
|
||||
|
||||
<AdminProtectedRoute
|
||||
exact
|
||||
component={ObservabilityAlertDetailsPage}
|
||||
component={AlertDetailsPage}
|
||||
path={ROUTES.OBSERVABILITY_ALERT_DETAILS}
|
||||
/>
|
||||
|
||||
|
@ -0,0 +1,134 @@
|
||||
/*
|
||||
* 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 { act, fireEvent, render, screen } from '@testing-library/react';
|
||||
import React from 'react';
|
||||
import { MemoryRouter } from 'react-router-dom';
|
||||
import AddNotificationPage from './AddNotificationPage';
|
||||
|
||||
const mockPush = jest.fn();
|
||||
const mockGoBack = jest.fn();
|
||||
|
||||
jest.mock('../../rest/alertsAPI', () => ({
|
||||
getAlertsFromName: jest.fn().mockImplementation(() =>
|
||||
Promise.resolve({
|
||||
name: 'ActivityFeedAlert',
|
||||
})
|
||||
),
|
||||
getResourceFunctions: jest.fn(),
|
||||
updateNotificationAlert: jest.fn().mockImplementation(() =>
|
||||
Promise.resolve({
|
||||
id: 'ActivityFeedAlert',
|
||||
data: [],
|
||||
})
|
||||
),
|
||||
createNotificationAlert: jest.fn().mockImplementation(() =>
|
||||
Promise.resolve({
|
||||
alert: 'Notification',
|
||||
})
|
||||
),
|
||||
}));
|
||||
|
||||
jest.mock('../../utils/RouterUtils', () => ({
|
||||
getNotificationAlertDetailsPath: jest.fn(),
|
||||
getSettingPath: jest.fn(),
|
||||
}));
|
||||
|
||||
jest.mock('../../components/common/ResizablePanels/ResizablePanels', () =>
|
||||
jest.fn().mockImplementation(({ firstPanel, secondPanel }) => (
|
||||
<>
|
||||
<div>{firstPanel.children}</div>
|
||||
<div>{secondPanel.children}</div>
|
||||
</>
|
||||
))
|
||||
);
|
||||
|
||||
jest.mock('react-router-dom', () => ({
|
||||
...jest.requireActual('react-router-dom'),
|
||||
useHistory: jest.fn().mockImplementation(() => ({
|
||||
push: mockPush,
|
||||
goBack: mockGoBack,
|
||||
})),
|
||||
}));
|
||||
|
||||
jest.mock('../../hooks/useFqn', () => ({
|
||||
useFqn: jest.fn().mockReturnValue({ fqn: '' }),
|
||||
}));
|
||||
|
||||
describe('AddNotificationPage', () => {
|
||||
beforeEach(() => {
|
||||
jest.clearAllMocks();
|
||||
});
|
||||
|
||||
it('should render Add Notification Page', async () => {
|
||||
await act(async () => {
|
||||
render(<AddNotificationPage />, {
|
||||
wrapper: MemoryRouter,
|
||||
});
|
||||
});
|
||||
|
||||
expect(
|
||||
await screen.findByText('label.notification-plural')
|
||||
).toBeInTheDocument();
|
||||
});
|
||||
|
||||
it('should display the correct breadcrumb', async () => {
|
||||
await act(async () => {
|
||||
render(<AddNotificationPage />, {
|
||||
wrapper: MemoryRouter,
|
||||
});
|
||||
});
|
||||
const breadcrumbLinks = screen.getAllByTestId('breadcrumb-link');
|
||||
|
||||
expect(breadcrumbLinks[0]).toHaveTextContent('label.setting-plural');
|
||||
expect(breadcrumbLinks[1]).toHaveTextContent('label.notification-plural');
|
||||
expect(breadcrumbLinks[2]).toHaveTextContent('label.create-entity');
|
||||
});
|
||||
|
||||
it('should display SubTitle', async () => {
|
||||
await act(async () => {
|
||||
render(<AddNotificationPage />, {
|
||||
wrapper: MemoryRouter,
|
||||
});
|
||||
});
|
||||
|
||||
expect(
|
||||
await screen.findByText(/message.alerts-description/)
|
||||
).toBeInTheDocument();
|
||||
});
|
||||
|
||||
it('should render Add alert button', async () => {
|
||||
await act(async () => {
|
||||
render(<AddNotificationPage />, {
|
||||
wrapper: MemoryRouter,
|
||||
});
|
||||
});
|
||||
|
||||
expect(await screen.findByText(/label.create-entity/)).toBeInTheDocument();
|
||||
});
|
||||
|
||||
it('should navigate back when the cancel button is clicked', async () => {
|
||||
await act(async () => {
|
||||
render(<AddNotificationPage />, {
|
||||
wrapper: MemoryRouter,
|
||||
});
|
||||
});
|
||||
|
||||
const cancelButton = screen.getByTestId('cancel-button');
|
||||
|
||||
await act(async () => {
|
||||
fireEvent.click(cancelButton);
|
||||
});
|
||||
|
||||
expect(mockGoBack).toHaveBeenCalled();
|
||||
});
|
||||
});
|
@ -0,0 +1,150 @@
|
||||
/*
|
||||
* 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 { act, fireEvent, render, screen } from '@testing-library/react';
|
||||
import React from 'react';
|
||||
import { MemoryRouter } from 'react-router-dom';
|
||||
import AddObservabilityPage from './AddObservabilityPage';
|
||||
|
||||
const MOCK_DATA = [
|
||||
{
|
||||
id: '971a21b3-eeaf-4765-bda7-4e2cdb9788de',
|
||||
name: 'alert-test',
|
||||
fullyQualifiedName: 'alert-test',
|
||||
href: 'http://localhost:8585/api/v1/events/subscriptions/971a21b3-eeaf-4765-bda7-4e2cdb9788de',
|
||||
version: 0.1,
|
||||
updatedAt: 1682366749021,
|
||||
updatedBy: 'admin',
|
||||
filteringRules: {
|
||||
resources: ['all'],
|
||||
rules: [
|
||||
{
|
||||
name: 'matchIngestionPipelineState',
|
||||
effect: 'include',
|
||||
condition: "matchIngestionPipelineState('partialSuccess')",
|
||||
},
|
||||
],
|
||||
},
|
||||
subscriptionType: 'Email',
|
||||
subscriptionConfig: {
|
||||
receivers: ['test@gmail.com'],
|
||||
},
|
||||
enabled: true,
|
||||
batchSize: 10,
|
||||
timeout: 10,
|
||||
readTimeout: 12,
|
||||
deleted: false,
|
||||
provider: 'user',
|
||||
},
|
||||
];
|
||||
const mockPush = jest.fn();
|
||||
const mockGoBack = jest.fn();
|
||||
|
||||
jest.mock('../../rest/observabilityAPI', () => ({
|
||||
getObservabilityAlertByFQN: jest.fn().mockImplementation(() =>
|
||||
Promise.resolve({
|
||||
fqn: 'alert-test',
|
||||
})
|
||||
),
|
||||
createObservabilityAlert: jest.fn().mockImplementation(() =>
|
||||
Promise.resolve({
|
||||
alert: 'Observability',
|
||||
})
|
||||
),
|
||||
getResourceFunctions: jest.fn(),
|
||||
updateObservabilityAlert: jest.fn().mockImplementation(() =>
|
||||
Promise.resolve({
|
||||
id: 'test',
|
||||
jsonPatch: MOCK_DATA,
|
||||
})
|
||||
),
|
||||
}));
|
||||
|
||||
jest.mock('../../components/common/ResizablePanels/ResizablePanels', () =>
|
||||
jest.fn().mockImplementation(({ firstPanel, secondPanel }) => (
|
||||
<>
|
||||
<div>{firstPanel.children}</div>
|
||||
<div>{secondPanel.children}</div>
|
||||
</>
|
||||
))
|
||||
);
|
||||
|
||||
jest.mock('react-router-dom', () => ({
|
||||
...jest.requireActual('react-router-dom'),
|
||||
useHistory: jest.fn().mockImplementation(() => ({
|
||||
push: mockPush,
|
||||
goBack: mockGoBack,
|
||||
})),
|
||||
}));
|
||||
|
||||
describe('Add ObservabilityPage Alerts Page Tests', () => {
|
||||
it('should render Add Observability Page', async () => {
|
||||
await act(async () => {
|
||||
render(<AddObservabilityPage />, {
|
||||
wrapper: MemoryRouter,
|
||||
});
|
||||
});
|
||||
|
||||
expect(await screen.findByText('label.observability')).toBeInTheDocument();
|
||||
});
|
||||
|
||||
it('should display SubTitle', async () => {
|
||||
await act(async () => {
|
||||
render(<AddObservabilityPage />, {
|
||||
wrapper: MemoryRouter,
|
||||
});
|
||||
});
|
||||
|
||||
expect(
|
||||
await screen.findByText(/message.alerts-description/)
|
||||
).toBeInTheDocument();
|
||||
});
|
||||
|
||||
it('should render Add alert button', async () => {
|
||||
await act(async () => {
|
||||
render(<AddObservabilityPage />, {
|
||||
wrapper: MemoryRouter,
|
||||
});
|
||||
});
|
||||
|
||||
expect(await screen.findByText(/label.create-entity/)).toBeInTheDocument();
|
||||
});
|
||||
|
||||
it('should display the correct breadcrumb', async () => {
|
||||
await act(async () => {
|
||||
render(<AddObservabilityPage />, {
|
||||
wrapper: MemoryRouter,
|
||||
});
|
||||
});
|
||||
const breadcrumbLinks = screen.getAllByTestId('breadcrumb-link');
|
||||
|
||||
expect(breadcrumbLinks[0]).toHaveTextContent('label.observability');
|
||||
expect(breadcrumbLinks[1]).toHaveTextContent('label.alert-plural');
|
||||
expect(breadcrumbLinks[2]).toHaveTextContent('label.create-entity');
|
||||
});
|
||||
|
||||
it('should navigate back when the cancel button is clicked', async () => {
|
||||
await act(async () => {
|
||||
render(<AddObservabilityPage />, {
|
||||
wrapper: MemoryRouter,
|
||||
});
|
||||
});
|
||||
|
||||
const cancelButton = screen.getByTestId('cancel-button');
|
||||
|
||||
await act(async () => {
|
||||
fireEvent.click(cancelButton);
|
||||
});
|
||||
|
||||
expect(mockGoBack).toHaveBeenCalled();
|
||||
});
|
||||
});
|
@ -0,0 +1,100 @@
|
||||
/*
|
||||
* 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 { render, screen } from '@testing-library/react';
|
||||
import { Form, FormInstance } from 'antd';
|
||||
import React from 'react';
|
||||
import DestinationFormItem from './DestinationFormItem.component';
|
||||
|
||||
jest.mock('../../../utils/Alerts/AlertsUtil', () => ({
|
||||
getDestinationConfigField: jest
|
||||
.fn()
|
||||
.mockReturnValue(<div data-testid="destination-field" />),
|
||||
getSubscriptionTypeOptions: jest.fn().mockReturnValue([]),
|
||||
listLengthValidator: jest.fn().mockImplementation(() => Promise.resolve()),
|
||||
}));
|
||||
|
||||
jest.mock('../../../utils/ObservabilityUtils', () => ({
|
||||
checkIfDestinationIsInternal: jest.fn().mockImplementation(() => false),
|
||||
getAlertDestinationCategoryIcons: jest
|
||||
.fn()
|
||||
.mockImplementation(() => <span data-testid="icon">Icon</span>),
|
||||
}));
|
||||
|
||||
const mockProps = {
|
||||
heading: 'heading',
|
||||
subHeading: 'subHeading',
|
||||
buttonLabel: 'buttonLabel',
|
||||
};
|
||||
|
||||
describe('DestinationFormItem', () => {
|
||||
it('should renders without crashing', () => {
|
||||
const setFieldValue = jest.fn();
|
||||
const getFieldValue = jest.fn();
|
||||
jest.spyOn(Form, 'useFormInstance').mockImplementation(
|
||||
() =>
|
||||
({
|
||||
setFieldValue,
|
||||
getFieldValue,
|
||||
} as unknown as FormInstance)
|
||||
);
|
||||
|
||||
const useWatchMock = jest.spyOn(Form, 'useWatch');
|
||||
useWatchMock.mockImplementation(() => ['container']);
|
||||
|
||||
render(<DestinationFormItem {...mockProps} />);
|
||||
|
||||
expect(screen.getByText('heading')).toBeInTheDocument();
|
||||
expect(screen.getByText('subHeading')).toBeInTheDocument();
|
||||
expect(screen.getByText('buttonLabel')).toBeInTheDocument();
|
||||
|
||||
expect(screen.getByTestId('add-destination-button')).toBeInTheDocument();
|
||||
});
|
||||
|
||||
it('add destination button should be disabled if there is no selected trigger', () => {
|
||||
const setFieldValue = jest.fn();
|
||||
const getFieldValue = jest.fn();
|
||||
jest.spyOn(Form, 'useFormInstance').mockImplementation(
|
||||
() =>
|
||||
({
|
||||
setFieldValue,
|
||||
getFieldValue,
|
||||
} as unknown as FormInstance)
|
||||
);
|
||||
|
||||
const useWatchMock = jest.spyOn(Form, 'useWatch');
|
||||
useWatchMock.mockImplementation(() => []);
|
||||
|
||||
render(<DestinationFormItem {...mockProps} />);
|
||||
|
||||
expect(screen.getByTestId('add-destination-button')).toBeDisabled();
|
||||
});
|
||||
|
||||
it('add destination button should be enabled if there is selected trigger', () => {
|
||||
const setFieldValue = jest.fn();
|
||||
const getFieldValue = jest.fn();
|
||||
jest.spyOn(Form, 'useFormInstance').mockImplementation(
|
||||
() =>
|
||||
({
|
||||
setFieldValue,
|
||||
getFieldValue,
|
||||
} as unknown as FormInstance)
|
||||
);
|
||||
|
||||
const useWatchMock = jest.spyOn(Form, 'useWatch');
|
||||
useWatchMock.mockImplementation(() => ['container']);
|
||||
|
||||
render(<DestinationFormItem {...mockProps} />);
|
||||
|
||||
expect(screen.getByTestId('add-destination-button')).toBeEnabled();
|
||||
});
|
||||
});
|
@ -0,0 +1,109 @@
|
||||
/*
|
||||
* 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 { render, screen } from '@testing-library/react';
|
||||
import { Form, FormInstance } from 'antd';
|
||||
import React from 'react';
|
||||
import { EventFilterRule } from '../../../generated/events/eventSubscription';
|
||||
import { MOCK_FILTER_RESOURCES } from '../../../test/unit/mocks/observability.mock';
|
||||
import ObservabilityFormActionItem from './ObservabilityFormActionItem';
|
||||
|
||||
jest.mock('../../../utils/Alerts/AlertsUtil', () => ({
|
||||
getConditionalField: jest
|
||||
.fn()
|
||||
.mockReturnValue(<div data-testid="condition-field" />),
|
||||
getSupportedFilterOptions: jest.fn().mockReturnValue([]),
|
||||
}));
|
||||
|
||||
const mockSupportedActions = MOCK_FILTER_RESOURCES.reduce(
|
||||
(resource, current) => {
|
||||
resource.push(...(current.supportedActions ?? []));
|
||||
|
||||
return resource;
|
||||
},
|
||||
[] as EventFilterRule[]
|
||||
);
|
||||
|
||||
describe('ObservabilityFormActionItem', () => {
|
||||
it('should renders without crashing', () => {
|
||||
const setFieldValue = jest.fn();
|
||||
const getFieldValue = jest.fn();
|
||||
jest.spyOn(Form, 'useFormInstance').mockImplementation(
|
||||
() =>
|
||||
({
|
||||
setFieldValue,
|
||||
getFieldValue,
|
||||
} as unknown as FormInstance)
|
||||
);
|
||||
|
||||
const useWatchMock = jest.spyOn(Form, 'useWatch');
|
||||
useWatchMock.mockImplementation(() => ['container']);
|
||||
|
||||
render(
|
||||
<ObservabilityFormActionItem supportedActions={mockSupportedActions} />
|
||||
);
|
||||
|
||||
expect(screen.getByText('label.action-plural')).toBeInTheDocument();
|
||||
expect(
|
||||
screen.getByText('message.alerts-action-description')
|
||||
).toBeInTheDocument();
|
||||
|
||||
expect(screen.getByTestId('actions-list')).toBeInTheDocument();
|
||||
expect(screen.getByTestId('add-actions')).toBeInTheDocument();
|
||||
});
|
||||
|
||||
it('add actions button should be disabled if there is no selected trigger and filters', () => {
|
||||
const setFieldValue = jest.fn();
|
||||
const getFieldValue = jest.fn();
|
||||
jest.spyOn(Form, 'useFormInstance').mockImplementation(
|
||||
() =>
|
||||
({
|
||||
setFieldValue,
|
||||
getFieldValue,
|
||||
} as unknown as FormInstance)
|
||||
);
|
||||
|
||||
const useWatchMock = jest.spyOn(Form, 'useWatch');
|
||||
useWatchMock.mockImplementation(() => []);
|
||||
|
||||
render(
|
||||
<ObservabilityFormActionItem supportedActions={mockSupportedActions} />
|
||||
);
|
||||
|
||||
const addButton = screen.getByTestId('add-actions');
|
||||
|
||||
expect(addButton).toBeDisabled();
|
||||
});
|
||||
|
||||
it('add actions button should not be disabled if there is selected trigger and filters', () => {
|
||||
const setFieldValue = jest.fn();
|
||||
const getFieldValue = jest.fn();
|
||||
jest.spyOn(Form, 'useFormInstance').mockImplementation(
|
||||
() =>
|
||||
({
|
||||
setFieldValue,
|
||||
getFieldValue,
|
||||
} as unknown as FormInstance)
|
||||
);
|
||||
|
||||
const useWatchMock = jest.spyOn(Form, 'useWatch');
|
||||
useWatchMock.mockImplementation(() => ['container']);
|
||||
|
||||
render(
|
||||
<ObservabilityFormActionItem supportedActions={mockSupportedActions} />
|
||||
);
|
||||
|
||||
const addButton = screen.getByTestId('add-actions');
|
||||
|
||||
expect(addButton).not.toBeDisabled();
|
||||
});
|
||||
});
|
@ -67,7 +67,7 @@ function ObservabilityFormActionItem({
|
||||
fields.length < (supportedActions?.length ?? 1);
|
||||
|
||||
return (
|
||||
<Row gutter={[16, 16]} key="actions">
|
||||
<Row data-testid="actions-list" gutter={[16, 16]} key="actions">
|
||||
{fields.map(({ key, name }) => {
|
||||
const effect =
|
||||
form.getFieldValue([
|
||||
|
@ -0,0 +1,109 @@
|
||||
/*
|
||||
* 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 { render, screen } from '@testing-library/react';
|
||||
import { Form, FormInstance } from 'antd';
|
||||
import React from 'react';
|
||||
import { EventFilterRule } from '../../../generated/events/eventSubscription';
|
||||
import { MOCK_FILTER_RESOURCES } from '../../../test/unit/mocks/observability.mock';
|
||||
import ObservabilityFormFiltersItem from './ObservabilityFormFiltersItem';
|
||||
|
||||
jest.mock('../../../utils/Alerts/AlertsUtil', () => ({
|
||||
getConditionalField: jest
|
||||
.fn()
|
||||
.mockReturnValue(<div data-testid="condition-field" />),
|
||||
getSupportedFilterOptions: jest.fn().mockReturnValue([]),
|
||||
}));
|
||||
|
||||
const mockSupportedFilters = MOCK_FILTER_RESOURCES.reduce(
|
||||
(resource, current) => {
|
||||
resource.push(...(current.supportedFilters ?? []));
|
||||
|
||||
return resource;
|
||||
},
|
||||
[] as EventFilterRule[]
|
||||
);
|
||||
|
||||
describe('ObservabilityFormFiltersItem', () => {
|
||||
it('should renders without crashing', () => {
|
||||
const setFieldValue = jest.fn();
|
||||
const getFieldValue = jest.fn();
|
||||
jest.spyOn(Form, 'useFormInstance').mockImplementation(
|
||||
() =>
|
||||
({
|
||||
setFieldValue,
|
||||
getFieldValue,
|
||||
} as unknown as FormInstance)
|
||||
);
|
||||
|
||||
const useWatchMock = jest.spyOn(Form, 'useWatch');
|
||||
useWatchMock.mockImplementation(() => ['container']);
|
||||
|
||||
render(
|
||||
<ObservabilityFormFiltersItem supportedFilters={mockSupportedFilters} />
|
||||
);
|
||||
|
||||
expect(screen.getByText('label.filter-plural')).toBeInTheDocument();
|
||||
expect(
|
||||
screen.getByText('message.alerts-filter-description')
|
||||
).toBeInTheDocument();
|
||||
|
||||
expect(screen.getByTestId('filters-list')).toBeInTheDocument();
|
||||
expect(screen.getByTestId('add-filters')).toBeInTheDocument();
|
||||
});
|
||||
|
||||
it('add filter button should be disabled if there is no selected trigger', () => {
|
||||
const setFieldValue = jest.fn();
|
||||
const getFieldValue = jest.fn();
|
||||
jest.spyOn(Form, 'useFormInstance').mockImplementation(
|
||||
() =>
|
||||
({
|
||||
setFieldValue,
|
||||
getFieldValue,
|
||||
} as unknown as FormInstance)
|
||||
);
|
||||
|
||||
const useWatchMock = jest.spyOn(Form, 'useWatch');
|
||||
useWatchMock.mockImplementation(() => []);
|
||||
|
||||
render(
|
||||
<ObservabilityFormFiltersItem supportedFilters={mockSupportedFilters} />
|
||||
);
|
||||
|
||||
const addButton = screen.getByTestId('add-filters');
|
||||
|
||||
expect(addButton).toBeDisabled();
|
||||
});
|
||||
|
||||
it('add filter button should not be disabled if there is selected trigger', () => {
|
||||
const setFieldValue = jest.fn();
|
||||
const getFieldValue = jest.fn();
|
||||
jest.spyOn(Form, 'useFormInstance').mockImplementation(
|
||||
() =>
|
||||
({
|
||||
setFieldValue,
|
||||
getFieldValue,
|
||||
} as unknown as FormInstance)
|
||||
);
|
||||
|
||||
const useWatchMock = jest.spyOn(Form, 'useWatch');
|
||||
useWatchMock.mockImplementation(() => ['container']);
|
||||
|
||||
render(
|
||||
<ObservabilityFormFiltersItem supportedFilters={mockSupportedFilters} />
|
||||
);
|
||||
|
||||
const addButton = screen.getByTestId('add-filters');
|
||||
|
||||
expect(addButton).not.toBeDisabled();
|
||||
});
|
||||
});
|
@ -0,0 +1,81 @@
|
||||
/*
|
||||
* 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 { render, screen } from '@testing-library/react';
|
||||
import userEvent from '@testing-library/user-event';
|
||||
import React from 'react';
|
||||
import { act } from 'react-dom/test-utils';
|
||||
import { MemoryRouter } from 'react-router-dom';
|
||||
import { useFqn } from '../../../hooks/useFqn';
|
||||
import { MOCK_FILTER_RESOURCES } from '../../../test/unit/mocks/observability.mock';
|
||||
import ObservabilityFormTriggerItem from './ObservabilityFormTriggerItem';
|
||||
|
||||
jest.mock('../../../hooks/useFqn', () => ({
|
||||
useFqn: jest.fn().mockReturnValue({ fqn: '' }),
|
||||
}));
|
||||
|
||||
jest.mock('antd', () => {
|
||||
const antd = jest.requireActual('antd');
|
||||
|
||||
return {
|
||||
...antd,
|
||||
Form: {
|
||||
...antd.Form,
|
||||
useFormInstance: jest.fn().mockImplementation(() => ({
|
||||
setFieldValue: jest.fn(),
|
||||
getFieldValue: jest.fn(),
|
||||
})),
|
||||
},
|
||||
};
|
||||
});
|
||||
|
||||
describe('ObservabilityFormTriggerItem', () => {
|
||||
it('should renders without crashing', () => {
|
||||
render(
|
||||
<ObservabilityFormTriggerItem filterResources={MOCK_FILTER_RESOURCES} />,
|
||||
{ wrapper: MemoryRouter }
|
||||
);
|
||||
|
||||
expect(screen.getByText('label.trigger')).toBeInTheDocument();
|
||||
expect(
|
||||
screen.getByText('message.alerts-trigger-description')
|
||||
).toBeInTheDocument();
|
||||
|
||||
expect(screen.getByTestId('add-trigger-button')).toBeInTheDocument();
|
||||
});
|
||||
|
||||
it('should render the trigger select when fqn is provided', () => {
|
||||
(useFqn as jest.Mock).mockImplementationOnce(() => ({
|
||||
fqn: 'test',
|
||||
}));
|
||||
|
||||
render(
|
||||
<ObservabilityFormTriggerItem filterResources={MOCK_FILTER_RESOURCES} />,
|
||||
{ wrapper: MemoryRouter }
|
||||
);
|
||||
|
||||
expect(screen.getByTestId('trigger-select')).toBeInTheDocument();
|
||||
});
|
||||
|
||||
it('should display select dropdown when clicked on add trigger button', async () => {
|
||||
render(
|
||||
<ObservabilityFormTriggerItem filterResources={MOCK_FILTER_RESOURCES} />,
|
||||
{ wrapper: MemoryRouter }
|
||||
);
|
||||
const addButton = screen.getByTestId('add-trigger-button');
|
||||
await act(async () => {
|
||||
userEvent.click(addButton);
|
||||
});
|
||||
|
||||
expect(screen.getByTestId('drop-down-menu')).toBeInTheDocument();
|
||||
});
|
||||
});
|
@ -11,6 +11,6 @@
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
export interface ObservabilityAlertDetailsPageProps {
|
||||
export interface AlertDetailsPageProps {
|
||||
isNotificationAlert: boolean;
|
||||
}
|
@ -58,11 +58,11 @@ import {
|
||||
} from '../../utils/RouterUtils';
|
||||
import { getEntityIcon } from '../../utils/TableUtils';
|
||||
import '../AddObservabilityPage/add-observability-page.less';
|
||||
import { ObservabilityAlertDetailsPageProps } from './ObservabilityAlertDetailsPage.interface';
|
||||
import { AlertDetailsPageProps } from './AlertDetailsPage.interface';
|
||||
|
||||
function ObservabilityAlertDetailsPage({
|
||||
isNotificationAlert,
|
||||
}: Readonly<ObservabilityAlertDetailsPageProps>) {
|
||||
function AlertDetailsPage({
|
||||
isNotificationAlert = false,
|
||||
}: Readonly<AlertDetailsPageProps>) {
|
||||
const { t } = useTranslation();
|
||||
const { fqn } = useFqn();
|
||||
const history = useHistory();
|
||||
@ -441,4 +441,4 @@ function ObservabilityAlertDetailsPage({
|
||||
);
|
||||
}
|
||||
|
||||
export default ObservabilityAlertDetailsPage;
|
||||
export default AlertDetailsPage;
|
@ -10,10 +10,11 @@
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
import { render } from '@testing-library/react';
|
||||
import { act, render, screen } from '@testing-library/react';
|
||||
import React from 'react';
|
||||
import { MemoryRouter } from 'react-router-dom';
|
||||
import { ROUTES } from '../../constants/constants';
|
||||
import { getAllAlerts } from '../../rest/alertsAPI';
|
||||
import NotificationListPage from './NotificationListPage';
|
||||
|
||||
const MOCK_DATA = [
|
||||
@ -55,6 +56,12 @@ jest.mock('../../rest/alertsAPI', () => ({
|
||||
paging: { total: 1 },
|
||||
})
|
||||
),
|
||||
getAlertsFromName: jest.fn().mockImplementation(() =>
|
||||
Promise.resolve({
|
||||
name: 'ActivityFeedAlert',
|
||||
params: 'all',
|
||||
})
|
||||
),
|
||||
}));
|
||||
|
||||
jest.mock('../../utils/GlobalSettingsUtils', () => ({
|
||||
@ -77,28 +84,68 @@ jest.mock(
|
||||
}
|
||||
);
|
||||
|
||||
describe('Alerts Page Tests', () => {
|
||||
describe('Notification Alerts Page Tests', () => {
|
||||
it('Title should be rendered', async () => {
|
||||
const { findByText } = render(<NotificationListPage />, {
|
||||
wrapper: MemoryRouter,
|
||||
await act(async () => {
|
||||
render(<NotificationListPage />, {
|
||||
wrapper: MemoryRouter,
|
||||
});
|
||||
});
|
||||
|
||||
expect(await findByText('label.notification-plural')).toBeInTheDocument();
|
||||
expect(
|
||||
await screen.findByText('label.notification-plural')
|
||||
).toBeInTheDocument();
|
||||
});
|
||||
|
||||
it('SubTitle should be rendered', async () => {
|
||||
const { findByText } = render(<NotificationListPage />, {
|
||||
wrapper: MemoryRouter,
|
||||
await act(async () => {
|
||||
render(<NotificationListPage />, {
|
||||
wrapper: MemoryRouter,
|
||||
});
|
||||
});
|
||||
|
||||
expect(await findByText(/message.alerts-description/)).toBeInTheDocument();
|
||||
expect(
|
||||
await screen.findByText(/message.alerts-description/)
|
||||
).toBeInTheDocument();
|
||||
});
|
||||
|
||||
it('Add alert button should be rendered', async () => {
|
||||
const { findByText } = render(<NotificationListPage />, {
|
||||
wrapper: MemoryRouter,
|
||||
await act(async () => {
|
||||
render(<NotificationListPage />, {
|
||||
wrapper: MemoryRouter,
|
||||
});
|
||||
});
|
||||
|
||||
expect(await findByText(/label.add-entity/)).toBeInTheDocument();
|
||||
expect(await screen.findByText(/label.add-entity/)).toBeInTheDocument();
|
||||
});
|
||||
|
||||
it('Table should render alerts data', async () => {
|
||||
await act(async () => {
|
||||
render(<NotificationListPage />, {
|
||||
wrapper: MemoryRouter,
|
||||
});
|
||||
});
|
||||
|
||||
const alertNameElement = await screen.findByTestId('alert-name');
|
||||
|
||||
expect(alertNameElement).toBeInTheDocument();
|
||||
});
|
||||
|
||||
it('Table should render no data', async () => {
|
||||
(getAllAlerts as jest.Mock).mockImplementation(() =>
|
||||
Promise.resolve({
|
||||
data: [],
|
||||
paging: { total: 1 },
|
||||
})
|
||||
);
|
||||
await act(async () => {
|
||||
render(<NotificationListPage />, {
|
||||
wrapper: MemoryRouter,
|
||||
});
|
||||
});
|
||||
|
||||
const alertNameElement = await screen.findByText('label.no-entity');
|
||||
|
||||
expect(alertNameElement).toBeInTheDocument();
|
||||
});
|
||||
});
|
||||
|
@ -10,9 +10,10 @@
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
import { render } from '@testing-library/react';
|
||||
import { act, render, screen } from '@testing-library/react';
|
||||
import React from 'react';
|
||||
import { MemoryRouter } from 'react-router-dom';
|
||||
import { getAllAlerts } from '../../rest/alertsAPI';
|
||||
import ObservabilityAlertsPage from './ObservabilityAlertsPage';
|
||||
|
||||
const MOCK_DATA = [
|
||||
@ -55,29 +56,72 @@ jest.mock('../../rest/alertsAPI', () => ({
|
||||
})
|
||||
),
|
||||
}));
|
||||
jest.mock('../../components/PageLayoutV1/PageLayoutV1', () => {
|
||||
return jest.fn().mockImplementation(({ children }) => <div>{children}</div>);
|
||||
});
|
||||
|
||||
describe.skip('Alerts Page Tests', () => {
|
||||
describe('Observability Alerts Page Tests', () => {
|
||||
it('Title should be rendered', async () => {
|
||||
const { findByText } = render(<ObservabilityAlertsPage />, {
|
||||
wrapper: MemoryRouter,
|
||||
await act(async () => {
|
||||
render(<ObservabilityAlertsPage />, {
|
||||
wrapper: MemoryRouter,
|
||||
});
|
||||
});
|
||||
|
||||
expect(await findByText('label.alert-plural')).toBeInTheDocument();
|
||||
expect(await screen.findByText('label.observability')).toBeInTheDocument();
|
||||
});
|
||||
|
||||
it('SubTitle should be rendered', async () => {
|
||||
const { findByText } = render(<ObservabilityAlertsPage />, {
|
||||
wrapper: MemoryRouter,
|
||||
await act(async () => {
|
||||
render(<ObservabilityAlertsPage />, {
|
||||
wrapper: MemoryRouter,
|
||||
});
|
||||
});
|
||||
|
||||
expect(await findByText(/message.alerts-description/)).toBeInTheDocument();
|
||||
expect(
|
||||
await screen.findByText(/message.alerts-description/)
|
||||
).toBeInTheDocument();
|
||||
});
|
||||
|
||||
it('Add alert button should be rendered', async () => {
|
||||
const { findByText } = render(<ObservabilityAlertsPage />, {
|
||||
wrapper: MemoryRouter,
|
||||
await act(async () => {
|
||||
render(<ObservabilityAlertsPage />, {
|
||||
wrapper: MemoryRouter,
|
||||
});
|
||||
});
|
||||
|
||||
expect(await findByText(/label.create-entity/)).toBeInTheDocument();
|
||||
expect(await screen.findByText(/label.add-entity/)).toBeInTheDocument();
|
||||
});
|
||||
|
||||
it('Table should render alerts data', async () => {
|
||||
await act(async () => {
|
||||
render(<ObservabilityAlertsPage />, {
|
||||
wrapper: MemoryRouter,
|
||||
});
|
||||
});
|
||||
|
||||
const alertNameElement = await screen.findByText('alert-test');
|
||||
|
||||
expect(alertNameElement).toBeInTheDocument();
|
||||
});
|
||||
|
||||
it('Table should render no data', async () => {
|
||||
(getAllAlerts as jest.Mock).mockImplementation(() =>
|
||||
Promise.resolve({
|
||||
data: [],
|
||||
paging: { total: 1 },
|
||||
})
|
||||
);
|
||||
await act(async () => {
|
||||
render(<ObservabilityAlertsPage />, {
|
||||
wrapper: MemoryRouter,
|
||||
});
|
||||
});
|
||||
|
||||
const alertNameElement = await screen.findByText(
|
||||
'message.adding-new-entity-is-easy-just-give-it-a-spin'
|
||||
);
|
||||
|
||||
expect(alertNameElement).toBeInTheDocument();
|
||||
});
|
||||
});
|
||||
|
@ -0,0 +1,343 @@
|
||||
/*
|
||||
* 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 { FilterResourceDescriptor } from '../../../generated/events/filterResourceDescriptor';
|
||||
|
||||
export const MOCK_FILTER_RESOURCES = [
|
||||
{
|
||||
name: 'container',
|
||||
supportedFilters: [
|
||||
{
|
||||
name: 'filterByFqn',
|
||||
displayName: 'Container Name',
|
||||
fullyQualifiedName: 'eventSubscription.filterByFqn',
|
||||
description: 'Event Filtering By Container Name',
|
||||
effect: 'include',
|
||||
condition: 'matchAnyEntityFqn(${fqnList})',
|
||||
arguments: ['fqnList'],
|
||||
inputType: 'runtime',
|
||||
},
|
||||
{
|
||||
name: 'filterByDomain',
|
||||
displayName: 'Domain',
|
||||
fullyQualifiedName: 'eventSubscription.filterByDomain',
|
||||
description: 'Event Filtering By Domain a Entity Belongs To',
|
||||
effect: 'include',
|
||||
condition: 'matchAnyDomain(${domainList})',
|
||||
arguments: ['domainList'],
|
||||
inputType: 'runtime',
|
||||
},
|
||||
{
|
||||
name: 'filterByOwner',
|
||||
displayName: 'Owner Name',
|
||||
fullyQualifiedName: 'eventSubscription.filterByOwner',
|
||||
description: 'Event Filtering By Owner Name of Asset',
|
||||
effect: 'include',
|
||||
condition: 'matchAnyOwnerName(${ownerNameList})',
|
||||
arguments: ['ownerNameList'],
|
||||
inputType: 'runtime',
|
||||
},
|
||||
],
|
||||
supportedActions: [
|
||||
{
|
||||
name: 'GetContainerSchemaChanges',
|
||||
displayName: 'Get Schema Changes',
|
||||
fullyQualifiedName: 'eventSubscription.GetContainerSchemaChanges',
|
||||
description: 'Get Updates for Schema Changes',
|
||||
effect: 'include',
|
||||
condition: "matchAnyFieldChange({'parent','children'})",
|
||||
arguments: [],
|
||||
inputType: 'none',
|
||||
},
|
||||
],
|
||||
},
|
||||
{
|
||||
name: 'pipeline',
|
||||
supportedFilters: [
|
||||
{
|
||||
name: 'filterByFqn',
|
||||
displayName: 'Pipeline Name',
|
||||
fullyQualifiedName: 'eventSubscription.filterByFqn',
|
||||
description: 'Event Filtering By Pipeline Name',
|
||||
effect: 'include',
|
||||
condition: 'matchAnyEntityFqn(${fqnList})',
|
||||
arguments: ['fqnList'],
|
||||
inputType: 'runtime',
|
||||
},
|
||||
{
|
||||
name: 'filterByDomain',
|
||||
displayName: 'Domain',
|
||||
fullyQualifiedName: 'eventSubscription.filterByDomain',
|
||||
description: 'Event Filtering By Domain a Entity Belongs To',
|
||||
effect: 'include',
|
||||
condition: 'matchAnyDomain(${domainList})',
|
||||
arguments: ['domainList'],
|
||||
inputType: 'runtime',
|
||||
},
|
||||
{
|
||||
name: 'filterByOwner',
|
||||
displayName: 'Owner Name',
|
||||
fullyQualifiedName: 'eventSubscription.filterByOwner',
|
||||
description: 'Event Filtering By Owner Name of Asset',
|
||||
effect: 'include',
|
||||
condition: 'matchAnyOwnerName(${ownerNameList})',
|
||||
arguments: ['ownerNameList'],
|
||||
inputType: 'runtime',
|
||||
},
|
||||
],
|
||||
supportedActions: [
|
||||
{
|
||||
name: 'GetPipelineStatusUpdates',
|
||||
displayName: 'Get Pipeline Status Updates',
|
||||
fullyQualifiedName: 'eventSubscription.GetPipelineStatusUpdates',
|
||||
description: 'Get Updates for Pipeline Status Changes',
|
||||
effect: 'include',
|
||||
condition: 'matchIngestionPipelineState(${pipelineStateList})',
|
||||
arguments: ['pipelineStateList'],
|
||||
inputType: 'runtime',
|
||||
},
|
||||
],
|
||||
},
|
||||
{
|
||||
name: 'table',
|
||||
supportedFilters: [
|
||||
{
|
||||
name: 'filterByFqn',
|
||||
displayName: 'Table Name',
|
||||
fullyQualifiedName: 'eventSubscription.filterByFqn',
|
||||
description: 'Event Filtering By Table Name',
|
||||
effect: 'include',
|
||||
condition: 'matchAnyEntityFqn(${fqnList})',
|
||||
arguments: ['fqnList'],
|
||||
inputType: 'runtime',
|
||||
},
|
||||
{
|
||||
name: 'filterByDomain',
|
||||
displayName: 'Domain',
|
||||
fullyQualifiedName: 'eventSubscription.filterByDomain',
|
||||
description: 'Event Filtering By Domain a Entity Belongs To',
|
||||
effect: 'include',
|
||||
condition: 'matchAnyDomain(${domainList})',
|
||||
arguments: ['domainList'],
|
||||
inputType: 'runtime',
|
||||
},
|
||||
{
|
||||
name: 'filterByOwner',
|
||||
displayName: 'Owner Name',
|
||||
fullyQualifiedName: 'eventSubscription.filterByOwner',
|
||||
description: 'Event Filtering By Owner Name of Asset',
|
||||
effect: 'include',
|
||||
condition: 'matchAnyOwnerName(${ownerNameList})',
|
||||
arguments: ['ownerNameList'],
|
||||
inputType: 'runtime',
|
||||
},
|
||||
],
|
||||
supportedActions: [
|
||||
{
|
||||
name: 'GetTableSchemaChanges',
|
||||
displayName: 'Get Schema Changes',
|
||||
fullyQualifiedName: 'eventSubscription.GetTableSchemaChanges',
|
||||
description: 'Get Updates for Schema Changes',
|
||||
effect: 'include',
|
||||
condition: "matchAnyFieldChange({'columns','dataModel','joins'})",
|
||||
arguments: [],
|
||||
inputType: 'none',
|
||||
},
|
||||
{
|
||||
name: 'GetTableMetricsUpdates',
|
||||
displayName: 'Get Table Metrics Updates',
|
||||
fullyQualifiedName: 'eventSubscription.GetTableMetricsUpdates',
|
||||
description: 'Get Updates About Table Metrics',
|
||||
effect: 'include',
|
||||
condition: "matchAnyFieldChange({'customMetrics', 'profile'})",
|
||||
arguments: [],
|
||||
inputType: 'none',
|
||||
},
|
||||
],
|
||||
},
|
||||
{
|
||||
name: 'testCase',
|
||||
supportedFilters: [
|
||||
{
|
||||
name: 'filterByFqn',
|
||||
displayName: 'Test Case Name',
|
||||
fullyQualifiedName: 'eventSubscription.filterByFqn',
|
||||
description: 'Event By Test Case Name',
|
||||
effect: 'include',
|
||||
condition: 'matchAnyEntityFqn(${fqnList})',
|
||||
arguments: ['fqnList'],
|
||||
inputType: 'runtime',
|
||||
},
|
||||
{
|
||||
name: 'filterByDomain',
|
||||
displayName: 'Domain',
|
||||
fullyQualifiedName: 'eventSubscription.filterByDomain',
|
||||
description: 'Event Filtering By Domain a Entity Belongs To',
|
||||
effect: 'include',
|
||||
condition: 'matchAnyDomain(${domainList})',
|
||||
arguments: ['domainList'],
|
||||
inputType: 'runtime',
|
||||
},
|
||||
{
|
||||
name: 'filterByOwner',
|
||||
displayName: 'Owner Name',
|
||||
fullyQualifiedName: 'eventSubscription.filterByOwner',
|
||||
description: 'Event Filtering By Owner Name of Asset',
|
||||
effect: 'include',
|
||||
condition: 'matchAnyOwnerName(${ownerNameList})',
|
||||
arguments: ['ownerNameList'],
|
||||
inputType: 'runtime',
|
||||
},
|
||||
{
|
||||
name: 'filterByTableNameTestCaseBelongsTo',
|
||||
displayName: 'Table Name A Test Case Belongs To',
|
||||
fullyQualifiedName:
|
||||
'eventSubscription.filterByTableNameTestCaseBelongsTo',
|
||||
description: 'Event Filtering By Table Name A Test Case Belongs To',
|
||||
effect: 'include',
|
||||
condition: 'filterByTableNameTestCaseBelongsTo(${tableNameList})',
|
||||
arguments: ['tableNameList'],
|
||||
inputType: 'runtime',
|
||||
},
|
||||
],
|
||||
supportedActions: [
|
||||
{
|
||||
name: 'GetTestCaseSchemaChanges',
|
||||
displayName: 'Get Schema Changes',
|
||||
fullyQualifiedName: 'eventSubscription.filterBySchemaChange',
|
||||
description: 'Get Updates for Schema Changes',
|
||||
effect: 'include',
|
||||
condition:
|
||||
"matchAnyFieldChange({'testDefinition','parameterValues','description'})",
|
||||
arguments: [],
|
||||
inputType: 'none',
|
||||
},
|
||||
{
|
||||
name: 'GetTestCaseStatusUpdates',
|
||||
displayName: 'Get Test Case Status Updates',
|
||||
fullyQualifiedName: 'eventSubscription.GetTestCaseStatusUpdates',
|
||||
description: 'Get Status Updates Test Cases',
|
||||
effect: 'include',
|
||||
condition: 'matchTestResult(${testResultList})',
|
||||
arguments: ['testResultList'],
|
||||
inputType: 'runtime',
|
||||
},
|
||||
],
|
||||
},
|
||||
{
|
||||
name: 'testSuite',
|
||||
supportedFilters: [
|
||||
{
|
||||
name: 'filterByFqn',
|
||||
displayName: 'Test Suite Name',
|
||||
fullyQualifiedName: 'eventSubscription.filterByFqn',
|
||||
description: 'Event Filtering By Test Suite Name',
|
||||
effect: 'include',
|
||||
condition: 'matchAnyEntityFqn(${fqnList})',
|
||||
arguments: ['fqnList'],
|
||||
inputType: 'runtime',
|
||||
},
|
||||
{
|
||||
name: 'filterByOwner',
|
||||
displayName: 'Owner Name',
|
||||
fullyQualifiedName: 'eventSubscription.filterByOwner',
|
||||
description: 'Event Filtering By Owner Name of Asset',
|
||||
effect: 'include',
|
||||
condition: 'matchAnyOwnerName(${ownerNameList})',
|
||||
arguments: ['ownerNameList'],
|
||||
inputType: 'runtime',
|
||||
},
|
||||
{
|
||||
name: 'filterByDomain',
|
||||
displayName: 'Domain',
|
||||
fullyQualifiedName: 'eventSubscription.filterByDomain',
|
||||
description: 'Event Filtering By Domain a Entity Belongs To',
|
||||
effect: 'include',
|
||||
condition: 'matchAnyDomain(${domainList})',
|
||||
arguments: ['domainList'],
|
||||
inputType: 'runtime',
|
||||
},
|
||||
],
|
||||
supportedActions: [
|
||||
{
|
||||
name: 'GetTestSuiteSchemaChanges',
|
||||
displayName: 'Get Schema Changes',
|
||||
fullyQualifiedName: 'eventSubscription.filterBySchemaChange',
|
||||
description: 'Get Updates for Schema Changes',
|
||||
effect: 'include',
|
||||
condition:
|
||||
"matchAnyFieldChange({'connection','pipelines','description'})",
|
||||
arguments: [],
|
||||
inputType: 'none',
|
||||
},
|
||||
{
|
||||
name: 'GetTestCaseStatusUpdatesUnderSuite',
|
||||
displayName: 'Get Test Case Status Updates belonging to a Test Suite',
|
||||
fullyQualifiedName:
|
||||
'eventSubscription.GetTestCaseStatusUpdatesUnderSuite',
|
||||
description: 'Get Status Updates Test Cases belonging to a Test Suite',
|
||||
effect: 'include',
|
||||
condition:
|
||||
'getTestCaseStatusIfInTestSuite(${testSuiteList}, ${testStatusList})',
|
||||
arguments: ['testSuiteList', 'testStatusList'],
|
||||
inputType: 'runtime',
|
||||
},
|
||||
],
|
||||
},
|
||||
{
|
||||
name: 'topic',
|
||||
supportedFilters: [
|
||||
{
|
||||
name: 'filterByFqn',
|
||||
displayName: 'Topic Name',
|
||||
fullyQualifiedName: 'eventSubscription.filterByFqn',
|
||||
description: 'Event Filtering By Topic Name',
|
||||
effect: 'include',
|
||||
condition: 'matchAnyEntityFqn(${fqnList})',
|
||||
arguments: ['fqnList'],
|
||||
inputType: 'runtime',
|
||||
},
|
||||
{
|
||||
name: 'filterByDomain',
|
||||
displayName: 'Domain',
|
||||
fullyQualifiedName: 'eventSubscription.filterByDomain',
|
||||
description: 'Event Filtering By Domain a Entity Belongs To',
|
||||
effect: 'include',
|
||||
condition: 'matchAnyDomain(${domainList})',
|
||||
arguments: ['domainList'],
|
||||
inputType: 'runtime',
|
||||
},
|
||||
{
|
||||
name: 'filterByOwner',
|
||||
displayName: 'Owner Name',
|
||||
fullyQualifiedName: 'eventSubscription.filterByOwner',
|
||||
description: 'Event Filtering By Owner Name of Asset',
|
||||
effect: 'include',
|
||||
condition: 'matchAnyOwnerName(${ownerNameList})',
|
||||
arguments: ['ownerNameList'],
|
||||
inputType: 'runtime',
|
||||
},
|
||||
],
|
||||
supportedActions: [
|
||||
{
|
||||
name: 'GetTopicSchemaChanges',
|
||||
displayName: 'Get Schema Changes',
|
||||
fullyQualifiedName: 'eventSubscription.GetTopicSchemaChanges',
|
||||
description: 'Get Updates for Schema Changes',
|
||||
effect: 'include',
|
||||
condition: "matchAnyFieldChange({'messageSchema'})",
|
||||
arguments: [],
|
||||
inputType: 'none',
|
||||
},
|
||||
],
|
||||
},
|
||||
] as FilterResourceDescriptor[];
|
@ -10,8 +10,20 @@
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
import { getFunctionDisplayName } from './AlertsUtil';
|
||||
import React from 'react';
|
||||
import { ReactComponent as AllActivityIcon } from '../../assets/svg/all-activity.svg';
|
||||
import { ReactComponent as MailIcon } from '../../assets/svg/ic-mail.svg';
|
||||
import { ReactComponent as MSTeamsIcon } from '../../assets/svg/ms-teams.svg';
|
||||
import { ReactComponent as SlackIcon } from '../../assets/svg/slack.svg';
|
||||
import { ReactComponent as WebhookIcon } from '../../assets/svg/webhook.svg';
|
||||
import { SubscriptionType } from '../../generated/events/eventSubscription';
|
||||
import {
|
||||
getAlertActionTypeDisplayName,
|
||||
getAlertsActionTypeIcon,
|
||||
getDisplayNameForEntities,
|
||||
getFunctionDisplayName,
|
||||
listLengthValidator,
|
||||
} from './AlertsUtil';
|
||||
|
||||
describe('AlertsUtil tests', () => {
|
||||
it('getFunctionDisplayName should return correct text for matchAnyEntityFqn', () => {
|
||||
@ -47,4 +59,83 @@ describe('AlertsUtil tests', () => {
|
||||
'label.entity-id-match'
|
||||
);
|
||||
});
|
||||
|
||||
it('getAlertsActionTypeIcon should return correct icon for Slack', () => {
|
||||
const icon = getAlertsActionTypeIcon(SubscriptionType.Slack);
|
||||
|
||||
expect(icon).toStrictEqual(<SlackIcon height={16} width={16} />);
|
||||
});
|
||||
|
||||
it('getAlertsActionTypeIcon should return correct icon for Email', () => {
|
||||
const icon = getAlertsActionTypeIcon(SubscriptionType.Email);
|
||||
|
||||
expect(icon).toStrictEqual(<MailIcon height={16} width={16} />);
|
||||
});
|
||||
|
||||
it('getAlertsActionTypeIcon should return correct icon for MSTeam', () => {
|
||||
const icon = getAlertsActionTypeIcon(SubscriptionType.MSTeams);
|
||||
|
||||
expect(icon).toStrictEqual(<MSTeamsIcon height={16} width={16} />);
|
||||
});
|
||||
|
||||
it('getAlertsActionTypeIcon should return correct icon for ActivityFeed', () => {
|
||||
const icon = getAlertsActionTypeIcon(SubscriptionType.ActivityFeed);
|
||||
|
||||
expect(icon).toStrictEqual(<AllActivityIcon height={16} width={16} />);
|
||||
});
|
||||
|
||||
it('getAlertsActionTypeIcon should return correct icon for generic', () => {
|
||||
const icon = getAlertsActionTypeIcon(SubscriptionType.Generic);
|
||||
|
||||
expect(icon).toStrictEqual(<WebhookIcon height={16} width={16} />);
|
||||
});
|
||||
|
||||
it('listLengthValidator should return error function', async () => {
|
||||
const error = listLengthValidator('name', 64);
|
||||
|
||||
expect(typeof error).toBe('function');
|
||||
});
|
||||
|
||||
it('getAlertActionTypeDisplayName should return correct text for Slack', () => {
|
||||
expect(getAlertActionTypeDisplayName(SubscriptionType.Slack)).toBe(
|
||||
'label.slack'
|
||||
);
|
||||
});
|
||||
|
||||
it('getAlertActionTypeDisplayName should return correct text for Email', () => {
|
||||
expect(getAlertActionTypeDisplayName(SubscriptionType.Email)).toBe(
|
||||
'label.email'
|
||||
);
|
||||
});
|
||||
|
||||
it('getAlertActionTypeDisplayName should return correct text for MSTeam', () => {
|
||||
expect(getAlertActionTypeDisplayName(SubscriptionType.MSTeams)).toBe(
|
||||
'label.ms-team-plural'
|
||||
);
|
||||
});
|
||||
|
||||
it('getAlertActionTypeDisplayName should return correct text for ActivityFeed', () => {
|
||||
expect(getAlertActionTypeDisplayName(SubscriptionType.ActivityFeed)).toBe(
|
||||
'label.activity-feed-plural'
|
||||
);
|
||||
});
|
||||
|
||||
it('getAlertActionTypeDisplayName should return correct text for generic', () => {
|
||||
expect(getAlertActionTypeDisplayName(SubscriptionType.Generic)).toBe(
|
||||
'label.webhook'
|
||||
);
|
||||
});
|
||||
|
||||
it('getAlertActionTypeDisplayName should return correct text for GChat', () => {
|
||||
expect(getAlertActionTypeDisplayName(SubscriptionType.GChat)).toBe(
|
||||
'label.g-chat'
|
||||
);
|
||||
});
|
||||
|
||||
it('getDisplayNameForEntities should return correct text', () => {
|
||||
expect(getDisplayNameForEntities('kpi')).toBe('label.kpi-uppercase');
|
||||
expect(getDisplayNameForEntities('mlmodel')).toBe('label.ml-model');
|
||||
|
||||
expect(getDisplayNameForEntities('unknown')).toBe('Unknown');
|
||||
});
|
||||
});
|
||||
|
@ -11,7 +11,7 @@
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
import { Col, Input, Select, Switch, Tooltip, Typography } from 'antd';
|
||||
import { Col, Input, Select, Switch, Tooltip } from 'antd';
|
||||
import Form, { RuleObject } from 'antd/lib/form';
|
||||
import { AxiosError } from 'axios';
|
||||
import i18next, { t } from 'i18next';
|
||||
@ -91,24 +91,6 @@ export const getFunctionDisplayName = (func: string): string => {
|
||||
}
|
||||
};
|
||||
|
||||
export const StyledCard = ({
|
||||
heading,
|
||||
subHeading,
|
||||
}: {
|
||||
heading: string;
|
||||
subHeading: string;
|
||||
}) => {
|
||||
return (
|
||||
<div className="bg-grey p-sm rounded-4 min-h-24">
|
||||
<Typography.Text>{heading}</Typography.Text>
|
||||
<br />
|
||||
<Typography.Text className="text-xs text-grey-muted">
|
||||
{subHeading}
|
||||
</Typography.Text>
|
||||
</div>
|
||||
);
|
||||
};
|
||||
|
||||
/**
|
||||
*
|
||||
* @param name Field name used to identify which field has error
|
||||
|
@ -0,0 +1,90 @@
|
||||
/*
|
||||
* 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 { SubscriptionCategory } from '../generated/events/eventSubscription';
|
||||
import {
|
||||
checkIfDestinationIsInternal,
|
||||
getAlertDestinationCategoryIcons,
|
||||
getConfigFieldFromDestinationType,
|
||||
} from './ObservabilityUtils';
|
||||
|
||||
describe('Observability Utils test', () => {
|
||||
describe('getAlertDestinationCategoryIcons', () => {
|
||||
it('should return the correct icon for each type', () => {
|
||||
const types = [
|
||||
'Teams',
|
||||
'Users',
|
||||
'Admins',
|
||||
'GChat',
|
||||
'Slack',
|
||||
'Email',
|
||||
'MsTeams',
|
||||
'Followers',
|
||||
'Generic',
|
||||
'Owners',
|
||||
];
|
||||
types.forEach((type) => {
|
||||
const icon = getAlertDestinationCategoryIcons(type);
|
||||
|
||||
expect(icon).not.toBeNull();
|
||||
});
|
||||
});
|
||||
|
||||
it('should return null for an unknown type', () => {
|
||||
const icon = getAlertDestinationCategoryIcons('Unknown');
|
||||
|
||||
expect(icon).toBeNull();
|
||||
});
|
||||
});
|
||||
|
||||
describe('checkIfDestinationIsInternal', () => {
|
||||
it('should return true for internal destinations', () => {
|
||||
const destinationName = SubscriptionCategory.Admins;
|
||||
const result = checkIfDestinationIsInternal(destinationName);
|
||||
|
||||
expect(result).toBe(true);
|
||||
});
|
||||
|
||||
it('should return false for external destinations', () => {
|
||||
const destinationName = 'Test';
|
||||
const result = checkIfDestinationIsInternal(destinationName);
|
||||
|
||||
expect(result).toBe(false);
|
||||
});
|
||||
});
|
||||
|
||||
describe('getConfigFieldFromDestinationType', () => {
|
||||
it('should return the correct config field for each type', () => {
|
||||
const types = [
|
||||
SubscriptionCategory.Admins,
|
||||
SubscriptionCategory.Owners,
|
||||
SubscriptionCategory.Followers,
|
||||
];
|
||||
const expectedResults = [
|
||||
'sendToAdmins',
|
||||
'sendToOwners',
|
||||
'sendToFollowers',
|
||||
];
|
||||
types.forEach((type, index) => {
|
||||
const result = getConfigFieldFromDestinationType(type);
|
||||
|
||||
expect(result).toBe(expectedResults[index]);
|
||||
});
|
||||
});
|
||||
|
||||
it('should return an empty string for an unknown type', () => {
|
||||
const result = getConfigFieldFromDestinationType('Unknown');
|
||||
|
||||
expect(result).toBe('');
|
||||
});
|
||||
});
|
||||
});
|
Loading…
x
Reference in New Issue
Block a user