From e00e365964d1859c858a253633519f8055d9d09f Mon Sep 17 00:00:00 2001 From: Shaheer Kochai Date: Mon, 20 Jan 2025 09:48:41 +0430 Subject: [PATCH] chore: new alert rule documentation redirection tests (#6822) * chore: new alert rule documentation redirection tests * fix: fix the failing test * fix: add test cases for anomaly based alert and fix the failing tests --- .../AnomalyAlertEvaluationView.tsx | 5 +- ...AlertRuleDocumentationRedirection.test.tsx | 146 ++++++++++++++++++ ...malyAlertDocumentationRedirection.test.tsx | 71 +++++++++ .../container/CreateAlertRule/constants.ts | 47 ++++++ 4 files changed, 267 insertions(+), 2 deletions(-) create mode 100644 frontend/src/container/CreateAlertRule/AlertRuleDocumentationRedirection.test.tsx create mode 100644 frontend/src/container/CreateAlertRule/AnomalyAlertDocumentationRedirection.test.tsx create mode 100644 frontend/src/container/CreateAlertRule/constants.ts diff --git a/frontend/src/container/AnomalyAlertEvaluationView/AnomalyAlertEvaluationView.tsx b/frontend/src/container/AnomalyAlertEvaluationView/AnomalyAlertEvaluationView.tsx index 90ecdbed0f..28d5397302 100644 --- a/frontend/src/container/AnomalyAlertEvaluationView/AnomalyAlertEvaluationView.tsx +++ b/frontend/src/container/AnomalyAlertEvaluationView/AnomalyAlertEvaluationView.tsx @@ -1,8 +1,7 @@ import 'uplot/dist/uPlot.min.css'; import './AnomalyAlertEvaluationView.styles.scss'; -import { Checkbox, Typography } from 'antd'; -import Search from 'antd/es/input/Search'; +import { Checkbox, Input, Typography } from 'antd'; import { useIsDarkMode } from 'hooks/useDarkMode'; import useDebouncedFn from 'hooks/useDebouncedFunction'; import { useResizeObserver } from 'hooks/useDimensions'; @@ -16,6 +15,8 @@ import uPlot from 'uplot'; import tooltipPlugin from './tooltipPlugin'; +const { Search } = Input; + function UplotChart({ data, options, diff --git a/frontend/src/container/CreateAlertRule/AlertRuleDocumentationRedirection.test.tsx b/frontend/src/container/CreateAlertRule/AlertRuleDocumentationRedirection.test.tsx new file mode 100644 index 0000000000..ea878ee748 --- /dev/null +++ b/frontend/src/container/CreateAlertRule/AlertRuleDocumentationRedirection.test.tsx @@ -0,0 +1,146 @@ +import ROUTES from 'constants/routes'; +import CreateAlertPage from 'pages/CreateAlert'; +import { MemoryRouter, Route } from 'react-router-dom'; +import { act, fireEvent, render } from 'tests/test-utils'; +import { AlertTypes } from 'types/api/alerts/alertTypes'; + +import { ALERT_TYPE_TO_TITLE, ALERT_TYPE_URL_MAP } from './constants'; + +jest.mock('react-router-dom', () => ({ + ...jest.requireActual('react-router-dom'), + useLocation: (): { pathname: string } => ({ + pathname: `${process.env.FRONTEND_API_ENDPOINT}${ROUTES.ALERTS_NEW}`, + }), +})); + +jest.mock('uplot', () => { + const paths = { + spline: jest.fn(), + bars: jest.fn(), + }; + const uplotMock = jest.fn(() => ({ + paths, + })); + return { + paths, + default: uplotMock, + }; +}); + +let mockWindowOpen: jest.Mock; + +window.ResizeObserver = + window.ResizeObserver || + jest.fn().mockImplementation(() => ({ + disconnect: jest.fn(), + observe: jest.fn(), + unobserve: jest.fn(), + })); + +function findLinkForAlertType( + links: HTMLElement[], + alertType: AlertTypes, +): HTMLElement { + const link = links.find( + (el) => + el.closest('[data-testid]')?.getAttribute('data-testid') === + `alert-type-card-${alertType}`, + ); + expect(link).toBeTruthy(); + return link as HTMLElement; +} + +function clickLinkAndVerifyRedirect( + link: HTMLElement, + expectedUrl: string, +): void { + fireEvent.click(link); + expect(mockWindowOpen).toHaveBeenCalledWith(expectedUrl, '_blank'); +} +describe('Alert rule documentation redirection', () => { + let renderResult: ReturnType; + + beforeAll(() => { + mockWindowOpen = jest.fn(); + window.open = mockWindowOpen; + }); + + beforeEach(() => { + act(() => { + renderResult = render( + + + + + , + ); + }); + }); + + it('should render alert type cards', () => { + const { getByText, getAllByText } = renderResult; + + // Check for the heading + expect(getByText('choose_alert_type')).toBeInTheDocument(); + + // Check for alert type titles and descriptions + Object.values(AlertTypes).forEach((alertType) => { + const title = ALERT_TYPE_TO_TITLE[alertType]; + expect(getByText(title)).toBeInTheDocument(); + expect(getByText(`${title}_desc`)).toBeInTheDocument(); + }); + + const clickHereLinks = getAllByText( + 'Click here to see how to create a sample alert.', + ); + + expect(clickHereLinks).toHaveLength(5); + }); + + it('should redirect to correct documentation for each alert type', () => { + const { getAllByText } = renderResult; + + const clickHereLinks = getAllByText( + 'Click here to see how to create a sample alert.', + ); + const alertTypeCount = Object.keys(AlertTypes).length; + + expect(clickHereLinks).toHaveLength(alertTypeCount); + + Object.values(AlertTypes).forEach((alertType) => { + const linkForAlertType = findLinkForAlertType(clickHereLinks, alertType); + const expectedUrl = ALERT_TYPE_URL_MAP[alertType]; + + clickLinkAndVerifyRedirect(linkForAlertType, expectedUrl.selection); + }); + + expect(mockWindowOpen).toHaveBeenCalledTimes(alertTypeCount); + }); + + Object.values(AlertTypes) + .filter((type) => type !== AlertTypes.ANOMALY_BASED_ALERT) + .forEach((alertType) => { + it(`should redirect to create alert page for ${alertType} and "Check an example alert" should redirect to the correct documentation`, () => { + const { getByTestId, getByRole } = renderResult; + + const alertTypeLink = getByTestId(`alert-type-card-${alertType}`); + + act(() => { + fireEvent.click(alertTypeLink); + }); + + act(() => { + fireEvent.click( + getByRole('button', { + name: /alert setup guide/i, + }), + ); + }); + + expect(mockWindowOpen).toHaveBeenCalledWith( + ALERT_TYPE_URL_MAP[alertType].creation, + '_blank', + ); + }); + }); +}); diff --git a/frontend/src/container/CreateAlertRule/AnomalyAlertDocumentationRedirection.test.tsx b/frontend/src/container/CreateAlertRule/AnomalyAlertDocumentationRedirection.test.tsx new file mode 100644 index 0000000000..ea892014d3 --- /dev/null +++ b/frontend/src/container/CreateAlertRule/AnomalyAlertDocumentationRedirection.test.tsx @@ -0,0 +1,71 @@ +import ROUTES from 'constants/routes'; +import CreateAlertPage from 'pages/CreateAlert'; +import { MemoryRouter, Route } from 'react-router-dom'; +import { act, fireEvent, render } from 'tests/test-utils'; +import { AlertTypes } from 'types/api/alerts/alertTypes'; + +import { ALERT_TYPE_URL_MAP } from './constants'; + +jest.mock('react-router-dom', () => ({ + ...jest.requireActual('react-router-dom'), + useLocation: (): { pathname: string; search: string } => ({ + pathname: `${process.env.FRONTEND_API_ENDPOINT}${ROUTES.ALERTS_NEW}`, + search: 'ruleType=anomaly_rule', + }), +})); + +jest.mock('uplot', () => { + const paths = { + spline: jest.fn(), + bars: jest.fn(), + }; + const uplotMock = jest.fn(() => ({ + paths, + })); + return { + paths, + default: uplotMock, + }; +}); + +window.ResizeObserver = + window.ResizeObserver || + jest.fn().mockImplementation(() => ({ + disconnect: jest.fn(), + observe: jest.fn(), + unobserve: jest.fn(), + })); + +describe('Anomaly Alert Documentation Redirection', () => { + let mockWindowOpen: jest.Mock; + + beforeAll(() => { + mockWindowOpen = jest.fn(); + window.open = mockWindowOpen; + }); + + it('should handle anomaly alert documentation redirection correctly', () => { + const { getByRole } = render( + + + + + , + ); + + const alertType = AlertTypes.ANOMALY_BASED_ALERT; + + act(() => { + fireEvent.click( + getByRole('button', { + name: /alert setup guide/i, + }), + ); + }); + + expect(mockWindowOpen).toHaveBeenCalledWith( + ALERT_TYPE_URL_MAP[alertType].creation, + '_blank', + ); + }); +}); diff --git a/frontend/src/container/CreateAlertRule/constants.ts b/frontend/src/container/CreateAlertRule/constants.ts new file mode 100644 index 0000000000..d8363f83f3 --- /dev/null +++ b/frontend/src/container/CreateAlertRule/constants.ts @@ -0,0 +1,47 @@ +import { AlertTypes } from 'types/api/alerts/alertTypes'; + +// since we don't have a card in alert creation for anomaly based alert + +export const ALERT_TYPE_URL_MAP: Record< + AlertTypes, + { selection: string; creation: string } +> = { + [AlertTypes.METRICS_BASED_ALERT]: { + selection: + 'https://signoz.io/docs/alerts-management/metrics-based-alerts/?utm_source=product&utm_medium=alert-source-selection-page#examples', + creation: + 'https://signoz.io/docs/alerts-management/metrics-based-alerts/?utm_source=product&utm_medium=alert-creation-page', + }, + [AlertTypes.LOGS_BASED_ALERT]: { + selection: + 'https://signoz.io/docs/alerts-management/log-based-alerts/?utm_source=product&utm_medium=alert-source-selection-page#examples', + creation: + 'https://signoz.io/docs/alerts-management/log-based-alerts/?utm_source=product&utm_medium=alert-creation-page', + }, + [AlertTypes.TRACES_BASED_ALERT]: { + selection: + 'https://signoz.io/docs/alerts-management/trace-based-alerts/?utm_source=product&utm_medium=alert-source-selection-page#examples', + creation: + 'https://signoz.io/docs/alerts-management/trace-based-alerts/?utm_source=product&utm_medium=alert-creation-page', + }, + [AlertTypes.EXCEPTIONS_BASED_ALERT]: { + selection: + 'https://signoz.io/docs/alerts-management/exceptions-based-alerts/?utm_source=product&utm_medium=alert-source-selection-page#examples', + creation: + 'https://signoz.io/docs/alerts-management/exceptions-based-alerts/?utm_source=product&utm_medium=alert-creation-page', + }, + [AlertTypes.ANOMALY_BASED_ALERT]: { + selection: + 'https://signoz.io/docs/alerts-management/anomaly-based-alerts/?utm_source=product&utm_medium=alert-source-selection-page#examples', + creation: + 'https://signoz.io/docs/alerts-management/anomaly-based-alerts/?utm_source=product&utm_medium=alert-creation-page', + }, +}; + +export const ALERT_TYPE_TO_TITLE: Record = { + [AlertTypes.METRICS_BASED_ALERT]: 'metric_based_alert', + [AlertTypes.LOGS_BASED_ALERT]: 'log_based_alert', + [AlertTypes.TRACES_BASED_ALERT]: 'traces_based_alert', + [AlertTypes.EXCEPTIONS_BASED_ALERT]: 'exceptions_based_alert', + [AlertTypes.ANOMALY_BASED_ALERT]: 'anomaly_based_alert', +};