Skip to content

Commit 55d3ff4

Browse files
upcoming: [DI-28227] - Firewall Alerts enhancements (#13110)
* upcoming: [DI-28227] - Firewall Alerts enhancements * add changeset * upcoming: [DI-28227] - Use constant for the tooltip string --------- Co-authored-by: Ankita <[email protected]>
1 parent dcf82ab commit 55d3ff4

File tree

7 files changed

+172
-9
lines changed

7 files changed

+172
-9
lines changed
Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,5 @@
1+
---
2+
"@linode/manager": Upcoming Features
3+
---
4+
5+
ACLP-Alerting: Filtering entities for firewall system alerts, add tooltip text to Entity Type component ([#13110](https://github.com/linode/manager/pull/13110))

packages/manager/src/features/CloudPulse/Alerts/CreateAlert/GeneralInformation/EntityTypeSelect.test.tsx

Lines changed: 22 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -4,6 +4,7 @@ import * as React from 'react';
44

55
import { renderWithThemeAndHookFormContext } from 'src/utilities/testHelpers';
66

7+
import { entityTypeTooltipText } from '../../constants';
78
import { EntityTypeSelect } from './EntityTypeSelect';
89

910
describe('EntityTypeSelect component tests', () => {
@@ -129,4 +130,25 @@ describe('EntityTypeSelect component tests', () => {
129130
within(entityTypeDropdown).queryByRole('button', { name: 'Clear' })
130131
).not.toBeInTheDocument();
131132
});
133+
134+
it('should display tooltip text on hover of the help icon', async () => {
135+
renderWithThemeAndHookFormContext({
136+
component: (
137+
<EntityTypeSelect
138+
name="entity_type"
139+
onEntityTypeChange={onEntityChange}
140+
/>
141+
),
142+
});
143+
144+
const entityTypeContainer = screen.getByTestId(ENTITY_TYPE_SELECT_TEST_ID);
145+
const helpButton =
146+
within(entityTypeContainer).getByTestId('tooltip-info-icon');
147+
148+
await userEvent.hover(helpButton);
149+
150+
expect(await screen.findByText(entityTypeTooltipText)).toBeVisible();
151+
152+
await userEvent.unhover(helpButton);
153+
});
132154
});

packages/manager/src/features/CloudPulse/Alerts/CreateAlert/GeneralInformation/EntityTypeSelect.tsx

Lines changed: 6 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -3,7 +3,8 @@ import * as React from 'react';
33
import { Controller, useFormContext } from 'react-hook-form';
44
import type { ControllerRenderProps, FieldPathByValue } from 'react-hook-form';
55

6-
import type { Item } from '../../constants';
6+
import { entityTypeTooltipText, type Item } from '../../constants';
7+
78
import type { CreateAlertDefinitionForm } from '../types';
89

910
interface EntityTypeSelectProps {
@@ -55,6 +56,10 @@ export const EntityTypeSelect = (props: EntityTypeSelectProps) => {
5556
options={entityTypeOptions}
5657
placeholder="Select an Entity Type"
5758
sx={{ marginTop: '5px' }}
59+
textFieldProps={{
60+
labelTooltipText: entityTypeTooltipText,
61+
tooltipPosition: 'right',
62+
}}
5863
value={
5964
entityTypeOptions.find((option) => option.value === field.value) ??
6065
undefined

packages/manager/src/features/CloudPulse/Alerts/EditAlert/EditAlertDefinition.test.tsx

Lines changed: 72 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -1,8 +1,13 @@
1-
import { waitFor } from '@testing-library/react';
1+
import { waitFor, within } from '@testing-library/react';
22
import userEvent from '@testing-library/user-event';
33
import React from 'react';
44

5-
import { alertFactory, notificationChannelFactory } from 'src/factories';
5+
import {
6+
alertFactory,
7+
firewallMetricRulesFactory,
8+
firewallNodebalancerMetricCriteria,
9+
notificationChannelFactory,
10+
} from 'src/factories';
611
import { renderWithTheme } from 'src/utilities/testHelpers';
712

813
import { UPDATE_ALERT_SUCCESS_MESSAGE } from '../constants';
@@ -47,6 +52,9 @@ const alertDetails = alertFactory.build({
4752
service_type: 'linode',
4853
scope: 'entity',
4954
});
55+
56+
const ENTITY_TYPE_SELECT_TEST_ID = 'entity-type-select';
57+
5058
describe('EditAlertDefinition component', () => {
5159
it('renders the components of the form', { timeout: 20000 }, async () => {
5260
const { findByPlaceholderText, getByLabelText, getByText } =
@@ -96,13 +104,69 @@ describe('EditAlertDefinition component', () => {
96104

97105
await waitFor(() => expect(mutateAsyncSpy).toHaveBeenCalledTimes(1));
98106

99-
expect(navigate).toHaveBeenLastCalledWith({
100-
to: '/alerts/definitions',
107+
expect(navigate).toHaveBeenLastCalledWith({
108+
to: '/alerts/definitions',
109+
});
110+
await waitFor(() => {
111+
expect(
112+
getByText(UPDATE_ALERT_SUCCESS_MESSAGE) // validate whether snackbar is displayed properly
113+
).toBeInTheDocument();
114+
});
101115
});
102-
await waitFor(() => {
103-
expect(
104-
getByText(UPDATE_ALERT_SUCCESS_MESSAGE) // validate whether snackbar is displayed properly
105-
).toBeInTheDocument();
116+
117+
it('should render EntityTypeSelect for firewall with Linode entity type', () => {
118+
const linodeFirewallAlertDetails = alertFactory.build({
119+
id: 1,
120+
rule_criteria: {
121+
rules: [firewallMetricRulesFactory.build()],
122+
},
123+
scope: 'entity',
124+
service_type: 'firewall',
125+
});
126+
127+
const { getByTestId } = renderWithTheme(
128+
<EditAlertDefinition
129+
alertDetails={linodeFirewallAlertDetails}
130+
serviceType="firewall"
131+
/>
132+
);
133+
134+
const entityTypeSelect = getByTestId(ENTITY_TYPE_SELECT_TEST_ID);
135+
expect(entityTypeSelect).toBeVisible();
136+
137+
const combobox = within(entityTypeSelect).getByRole('combobox');
138+
expect(combobox).toHaveAttribute('value', 'Linodes');
139+
});
140+
141+
it('should render EntityTypeSelect for firewall with NodeBalancer entity type', () => {
142+
const nodebalancerFirewallAlertDetails = alertFactory.build({
143+
id: 2,
144+
rule_criteria: {
145+
rules: [firewallNodebalancerMetricCriteria.build()],
146+
},
147+
scope: 'entity',
148+
service_type: 'firewall',
106149
});
150+
151+
const { getByTestId } = renderWithTheme(
152+
<EditAlertDefinition
153+
alertDetails={nodebalancerFirewallAlertDetails}
154+
serviceType="firewall"
155+
/>
156+
);
157+
158+
const entityTypeSelect = getByTestId(ENTITY_TYPE_SELECT_TEST_ID);
159+
expect(entityTypeSelect).toBeVisible();
160+
161+
const combobox = within(entityTypeSelect).getByRole('combobox');
162+
expect(combobox).toHaveAttribute('value', 'NodeBalancers');
163+
});
164+
165+
it('should not render EntityTypeSelect for non-firewall service types', () => {
166+
const { queryByTestId } = renderWithTheme(
167+
<EditAlertDefinition alertDetails={alertDetails} serviceType="linode" />
168+
);
169+
170+
expect(queryByTestId(ENTITY_TYPE_SELECT_TEST_ID)).not.toBeInTheDocument();
107171
});
108172
});

packages/manager/src/features/CloudPulse/Alerts/EditAlert/EditAlertResources.tsx

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -8,6 +8,7 @@ import { Breadcrumb } from 'src/components/Breadcrumb/Breadcrumb';
88
import { useEditAlertDefinition } from 'src/queries/cloudpulse/alerts';
99

1010
import { AlertResources } from '../AlertsResources/AlertsResources';
11+
import { entityLabelMap } from '../constants';
1112
import { isResourcesEqual } from '../Utils/AlertResourceUtils';
1213
import { getAlertBoxStyles } from '../Utils/utils';
1314
import { EditAlertResourcesConfirmDialog } from './EditAlertResourcesConfirmationDialog';
@@ -85,6 +86,14 @@ export const EditAlertResources = (props: EditAlertProps) => {
8586
type,
8687
} = alertDetails;
8788

89+
const entityType =
90+
serviceType === 'firewall'
91+
? alertDetails.rule_criteria.rules[0]?.label.includes(
92+
entityLabelMap['nodebalancer']
93+
)
94+
? 'nodebalancer'
95+
: 'linode'
96+
: undefined;
8897
return (
8998
<>
9099
<Breadcrumb crumbOverrides={overrides} pathname={newPathname} />
@@ -100,6 +109,7 @@ export const EditAlertResources = (props: EditAlertProps) => {
100109
alertLabel={label}
101110
alertResourceIds={entity_ids}
102111
alertType={type}
112+
entityType={entityType}
103113
handleResourcesSelection={handleResourcesSelection}
104114
isSelectionsNeeded
105115
serviceType={service_type}

packages/manager/src/features/CloudPulse/Alerts/constants.ts

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -291,3 +291,6 @@ export const entityLabelMap = {
291291
linode: 'Linode',
292292
nodebalancer: 'Node Balancer',
293293
};
294+
295+
export const entityTypeTooltipText =
296+
'Select a firewall entity type to filter the list in the Entities section. The metrics and dimensions in the Criteria section will update automatically based on your selection.';

packages/manager/src/mocks/serverHandlers.ts

Lines changed: 54 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -3273,6 +3273,28 @@ export const handlers = [
32733273
rules: [firewallNodebalancerMetricCriteria.build()],
32743274
},
32753275
}),
3276+
alertFactory.build({
3277+
id: 340,
3278+
label: 'Firewall-nodebalancer-system',
3279+
type: 'system',
3280+
service_type: 'firewall',
3281+
entity_ids: ['25'],
3282+
rule_criteria: {
3283+
rules: [
3284+
firewallNodebalancerMetricCriteria.build({ dimension_filters: [] }),
3285+
],
3286+
},
3287+
}),
3288+
alertFactory.build({
3289+
id: 123,
3290+
label: 'Firewall-linode-system',
3291+
type: 'system',
3292+
service_type: 'firewall',
3293+
entity_ids: ['1', '4'],
3294+
rule_criteria: {
3295+
rules: [firewallMetricRulesFactory.build()],
3296+
},
3297+
}),
32763298
...alertFactory.buildList(3, { status: 'enabling', type: 'user' }),
32773299
...alertFactory.buildList(3, { status: 'disabling', type: 'user' }),
32783300
...alertFactory.buildList(3, { status: 'provisioning', type: 'user' }),
@@ -3344,6 +3366,38 @@ export const handlers = [
33443366
})
33453367
);
33463368
}
3369+
if (params.id === '340' && params.serviceType === 'firewall') {
3370+
return HttpResponse.json(
3371+
alertFactory.build({
3372+
id: 340,
3373+
label: 'Firewall - nodebalancer - system',
3374+
type: 'system',
3375+
service_type: 'firewall',
3376+
entity_ids: ['25'],
3377+
rule_criteria: {
3378+
rules: [
3379+
firewallNodebalancerMetricCriteria.build({
3380+
dimension_filters: [],
3381+
}),
3382+
],
3383+
},
3384+
})
3385+
);
3386+
}
3387+
if (params.id === '123' && params.serviceType === 'firewall') {
3388+
return HttpResponse.json(
3389+
alertFactory.build({
3390+
id: 123,
3391+
label: 'Firewall-linode-system',
3392+
type: 'system',
3393+
service_type: 'firewall',
3394+
entity_ids: ['1', '4'],
3395+
rule_criteria: {
3396+
rules: [firewallMetricRulesFactory.build()],
3397+
},
3398+
})
3399+
);
3400+
}
33473401
if (params.id !== undefined) {
33483402
return HttpResponse.json(
33493403
alertFactory.build({

0 commit comments

Comments
 (0)