diff --git a/packages/manager/src/features/CloudPulse/Alerts/AlertsDetail/AlertDetailCriteria.test.tsx b/packages/manager/src/features/CloudPulse/Alerts/AlertsDetail/AlertDetailCriteria.test.tsx index 975b863186a..0f6a6f5752a 100644 --- a/packages/manager/src/features/CloudPulse/Alerts/AlertsDetail/AlertDetailCriteria.test.tsx +++ b/packages/manager/src/features/CloudPulse/Alerts/AlertsDetail/AlertDetailCriteria.test.tsx @@ -1,15 +1,32 @@ import React from 'react'; -import { alertFactory } from 'src/factories'; +import { + alertDimensionsFactory, + alertFactory, + alertRulesFactory, +} from 'src/factories'; import { renderWithTheme } from 'src/utilities/testHelpers'; -import { operators } from '../constants'; +import { metricOperatorTypeMap } from '../constants'; import { convertSecondsToMinutes } from '../Utils/utils'; import { AlertDetailCriteria } from './AlertDetailCriteria'; describe('AlertDetailCriteria component tests', () => { it('should render the alert detail criteria successfully on correct inputs', () => { - const alertDetails = alertFactory.build(); + const alertDetails = alertFactory.build({ + rule_criteria: { + rules: [ + ...alertRulesFactory.buildList(2, { + aggregation_type: 'avg', + dimension_filters: alertDimensionsFactory.buildList(2), + label: 'CPU Usage', + metric: 'cpu_usage', + operator: 'gt', + unit: 'bytes', + }), + ], + }, + }); const { getAllByText, getByText } = renderWithTheme( ); @@ -19,7 +36,8 @@ describe('AlertDetailCriteria component tests', () => { expect(getByText('Criteria')).toBeInTheDocument(); expect(getAllByText('Average').length).toBe(2); expect(getAllByText('CPU Usage').length).toBe(2); - expect(getAllByText(operators['gt']).length).toBe(2); + expect(getAllByText('bytes').length).toBe(2); + expect(getAllByText(metricOperatorTypeMap['gt']).length).toBe(2); const { evaluation_period_seconds, diff --git a/packages/manager/src/features/CloudPulse/Alerts/AlertsDetail/DisplayAlertDetailChips.tsx b/packages/manager/src/features/CloudPulse/Alerts/AlertsDetail/DisplayAlertDetailChips.tsx index 0acebc710f9..b85f463e429 100644 --- a/packages/manager/src/features/CloudPulse/Alerts/AlertsDetail/DisplayAlertDetailChips.tsx +++ b/packages/manager/src/features/CloudPulse/Alerts/AlertsDetail/DisplayAlertDetailChips.tsx @@ -2,6 +2,7 @@ import { Typography } from '@linode/ui'; import { Grid, useTheme } from '@mui/material'; import React from 'react'; +import { getAlertChipBorderRadius } from '../Utils/utils'; import { StyledAlertChip } from './AlertDetail'; export interface AlertDimensionsProp { @@ -42,7 +43,7 @@ export const DisplayAlertDetailChips = React.memo( values: values, } = props; - const iterables: string[][] = Array.isArray(values) + const chipValues: string[][] = Array.isArray(values) ? values.every(Array.isArray) ? values : [values] @@ -50,33 +51,12 @@ export const DisplayAlertDetailChips = React.memo( const theme = useTheme(); - /** - * @param index The index of the list of chips that we are rendering - * @param length The length of the iteration so far - * @returns The border radius to be applied on chips based on the parameters - */ - const getAlertChipBorderRadius = ( - index: number, - length: number - ): string => { - if (!mergeChips || length === 1) { - return theme.spacing(0.3); - } - if (index === 0) { - return `${theme.spacing(0.3)} 0 0 ${theme.spacing(0.3)}`; - } - if (index === length - 1) { - return `0 ${theme.spacing(0.3)} ${theme.spacing(0.3)} 0`; - } - return '0'; - }; - return ( - {iterables.map((value, idx) => ( - + {chipValues.map((value, index) => ( + - {idx === 0 && ( + {index === 0 && ( 0 && ( [ - label, - operatorLabel[operator], - value, - ])} + values={dimensionFilters.map( + ({ + label: dimensionLabel, + operator: dimensionOperator, + value, + }) => [ + dimensionLabel, + dimensionOperatorTypeMap[dimensionOperator], + value, + ] + )} label="Dimension Filter" mergeChips /> diff --git a/packages/manager/src/features/CloudPulse/Alerts/Utils/utils.test.ts b/packages/manager/src/features/CloudPulse/Alerts/Utils/utils.test.ts index d864249ba60..e2c4070cc43 100644 --- a/packages/manager/src/features/CloudPulse/Alerts/Utils/utils.test.ts +++ b/packages/manager/src/features/CloudPulse/Alerts/Utils/utils.test.ts @@ -15,7 +15,7 @@ it('test getServiceTypeLabel method', () => { }); it('test convertSecondsToMinutes method', () => { - expect(convertSecondsToMinutes(0)).toBe('0 minutes'); + expect(convertSecondsToMinutes(0)).toBe('0 minute'); expect(convertSecondsToMinutes(60)).toBe('1 minute'); expect(convertSecondsToMinutes(120)).toBe('2 minutes'); expect(convertSecondsToMinutes(65)).toBe('1 minute and 5 seconds'); diff --git a/packages/manager/src/features/CloudPulse/Alerts/Utils/utils.ts b/packages/manager/src/features/CloudPulse/Alerts/Utils/utils.ts index 201154aedbc..b9cbe3f7609 100644 --- a/packages/manager/src/features/CloudPulse/Alerts/Utils/utils.ts +++ b/packages/manager/src/features/CloudPulse/Alerts/Utils/utils.ts @@ -36,24 +36,41 @@ export const getAlertBoxStyles = (theme: Theme) => ({ * @returns A string representing the time in minutes and seconds. */ export const convertSecondsToMinutes = (seconds: number): string => { - if (seconds === 0) { - return '0 minutes'; + if (seconds <= 0) { + return '0 minute'; } - const minutes = Math.floor(seconds / 60); const remainingSeconds = seconds % 60; + const minuteString = + minutes > 0 + ? `${minutes} ${minutes === 1 ? 'minute' : 'minutes'}` + : undefined; + const secondString = + remainingSeconds > 0 + ? `${remainingSeconds} ${remainingSeconds <= 1 ? 'second' : 'seconds'}` + : undefined; + return [minuteString, secondString].filter(Boolean).join(' and '); +}; - const minuteString = `${minutes} ${minutes === 1 ? 'minute' : 'minutes'}`; - const secondString = `${remainingSeconds} ${ - remainingSeconds === 1 ? 'second' : 'seconds' - }`; - - if (!minutes) { - return secondString; +/** + * @param index The index of the list of chips that we are rendering + * @param length The length of the iteration so far + * @returns The border radius to be applied on chips based on the parameters + */ +export const getAlertChipBorderRadius = ( + index: number, + length: number, + mergeChips: boolean | undefined, + theme: Theme +): string => { + if (!mergeChips || length === 1) { + return theme.spacing(0.3); } - if (!remainingSeconds) { - return minuteString; + if (index === 0) { + return `${theme.spacing(0.3)} 0 0 ${theme.spacing(0.3)}`; } - - return `${minuteString} and ${secondString}`; + if (index === length - 1) { + return `0 ${theme.spacing(0.3)} ${theme.spacing(0.3)} 0`; + } + return '0'; }; diff --git a/packages/manager/src/features/CloudPulse/Alerts/constants.ts b/packages/manager/src/features/CloudPulse/Alerts/constants.ts index 87d1d521f3e..35c0fde6c6c 100644 --- a/packages/manager/src/features/CloudPulse/Alerts/constants.ts +++ b/packages/manager/src/features/CloudPulse/Alerts/constants.ts @@ -87,7 +87,7 @@ export const alertStatusToIconStatusMap: Record = { enabled: 'active', }; -export const operators: Record = { +export const metricOperatorTypeMap: Record = { eq: '=', gt: '>', gte: '>=', @@ -95,7 +95,7 @@ export const operators: Record = { lte: '<=', }; -export const aggregationTypes: Record = { +export const aggregationTypeMap: Record = { avg: 'Average', count: 'Count', max: 'Maximum', @@ -103,7 +103,10 @@ export const aggregationTypes: Record = { sum: 'Sum', }; -export const operatorLabel: Record = { +export const dimensionOperatorTypeMap: Record< + DimensionFilterOperatorType, + string +> = { endswith: 'ends with', eq: 'equals', neq: 'not equals',