diff --git a/frontend/src/container/CreateAlertRule/AlertRuleDocumentationRedirection.test.tsx b/frontend/src/container/CreateAlertRule/AlertRuleDocumentationRedirection.test.tsx new file mode 100644 index 0000000000..b1a39e1c45 --- /dev/null +++ b/frontend/src/container/CreateAlertRule/AlertRuleDocumentationRedirection.test.tsx @@ -0,0 +1,140 @@ +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(4); + }); + + 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).forEach((alertType) => { + it(`should redirect to create alert page for ${alertType} and "Check an example alert" should redirect to the correct documentation`, () => { + const { getByTestId, getByText } = renderResult; + + const alertTypeLink = getByTestId(`alert-type-card-${alertType}`); + + act(() => { + fireEvent.click(alertTypeLink); + }); + + act(() => { + fireEvent.click(getByText('Check an example alert')); + }); + + expect(mockWindowOpen).toHaveBeenCalledWith( + ALERT_TYPE_URL_MAP[alertType].creation, + '_blank', + ); + }); + }); +}); diff --git a/frontend/src/container/CreateAlertRule/SelectAlertType/index.tsx b/frontend/src/container/CreateAlertRule/SelectAlertType/index.tsx index 52f4d52215..48075649b7 100644 --- a/frontend/src/container/CreateAlertRule/SelectAlertType/index.tsx +++ b/frontend/src/container/CreateAlertRule/SelectAlertType/index.tsx @@ -55,6 +55,7 @@ function SelectAlertType({ onSelect }: SelectAlertTypeProps): JSX.Element { onClick={(): void => { onSelect(option.selection); }} + data-testid={`alert-type-card-${option.selection}`} > {option.description}{' '} = { + [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#examples', + }, + [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#examples', + }, + [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#examples', + }, + [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#examples', + }, +}; + +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', +};