From 3be050acf5b98b7864378b81c5ce22b69424906f Mon Sep 17 00:00:00 2001
From: santoshp210-akamai
<159890961+santoshp210-akamai@users.noreply.github.com>
Date: Fri, 14 Nov 2025 11:22:46 +0530
Subject: [PATCH 1/3] upcoming: [DI-28227] - Firewall Alerts enhancements
---
.../EntityTypeSelect.test.tsx | 25 +++++++
.../GeneralInformation/EntityTypeSelect.tsx | 4 ++
.../EditAlert/EditAlertDefinition.test.tsx | 68 ++++++++++++++++++-
.../Alerts/EditAlert/EditAlertResources.tsx | 10 +++
packages/manager/src/mocks/serverHandlers.ts | 54 +++++++++++++++
5 files changed, 159 insertions(+), 2 deletions(-)
diff --git a/packages/manager/src/features/CloudPulse/Alerts/CreateAlert/GeneralInformation/EntityTypeSelect.test.tsx b/packages/manager/src/features/CloudPulse/Alerts/CreateAlert/GeneralInformation/EntityTypeSelect.test.tsx
index 952574122dd..d6258cc7024 100644
--- a/packages/manager/src/features/CloudPulse/Alerts/CreateAlert/GeneralInformation/EntityTypeSelect.test.tsx
+++ b/packages/manager/src/features/CloudPulse/Alerts/CreateAlert/GeneralInformation/EntityTypeSelect.test.tsx
@@ -129,4 +129,29 @@ describe('EntityTypeSelect component tests', () => {
within(entityTypeDropdown).queryByRole('button', { name: 'Clear' })
).not.toBeInTheDocument();
});
+
+ it('should display tooltip text on hover of the help icon', async () => {
+ renderWithThemeAndHookFormContext({
+ component: (
+
+ ),
+ });
+
+ const entityTypeContainer = screen.getByTestId(ENTITY_TYPE_SELECT_TEST_ID);
+ const helpButton =
+ within(entityTypeContainer).getByTestId('tooltip-info-icon');
+
+ await userEvent.hover(helpButton);
+
+ expect(
+ await screen.findByText(
+ '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.'
+ )
+ ).toBeVisible();
+
+ await userEvent.unhover(helpButton);
+ });
});
diff --git a/packages/manager/src/features/CloudPulse/Alerts/CreateAlert/GeneralInformation/EntityTypeSelect.tsx b/packages/manager/src/features/CloudPulse/Alerts/CreateAlert/GeneralInformation/EntityTypeSelect.tsx
index b5f00f52aed..405e42e44d0 100644
--- a/packages/manager/src/features/CloudPulse/Alerts/CreateAlert/GeneralInformation/EntityTypeSelect.tsx
+++ b/packages/manager/src/features/CloudPulse/Alerts/CreateAlert/GeneralInformation/EntityTypeSelect.tsx
@@ -55,6 +55,10 @@ export const EntityTypeSelect = (props: EntityTypeSelectProps) => {
options={entityTypeOptions}
placeholder="Select an Entity Type"
sx={{ marginTop: '5px' }}
+ textFieldProps={{
+ labelTooltipText:
+ '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.',
+ }}
value={
entityTypeOptions.find((option) => option.value === field.value) ??
undefined
diff --git a/packages/manager/src/features/CloudPulse/Alerts/EditAlert/EditAlertDefinition.test.tsx b/packages/manager/src/features/CloudPulse/Alerts/EditAlert/EditAlertDefinition.test.tsx
index 9c921f21bf2..3289a183404 100644
--- a/packages/manager/src/features/CloudPulse/Alerts/EditAlert/EditAlertDefinition.test.tsx
+++ b/packages/manager/src/features/CloudPulse/Alerts/EditAlert/EditAlertDefinition.test.tsx
@@ -1,8 +1,13 @@
-import { waitFor } from '@testing-library/react';
+import { waitFor, within } from '@testing-library/react';
import userEvent from '@testing-library/user-event';
import React from 'react';
-import { alertFactory, notificationChannelFactory } from 'src/factories';
+import {
+ alertFactory,
+ firewallMetricRulesFactory,
+ firewallNodebalancerMetricCriteria,
+ notificationChannelFactory,
+} from 'src/factories';
import { renderWithTheme } from 'src/utilities/testHelpers';
import { UPDATE_ALERT_SUCCESS_MESSAGE } from '../constants';
@@ -47,6 +52,9 @@ const alertDetails = alertFactory.build({
service_type: 'linode',
scope: 'entity',
});
+
+const ENTITY_TYPE_SELECT_TEST_ID = 'entity-type-select';
+
describe('EditAlertDefinition component', () => {
it(
'renders the components of the form',
@@ -116,4 +124,60 @@ describe('EditAlertDefinition component', () => {
},
{ timeout: 10000 }
);
+
+ it('should render EntityTypeSelect for firewall with Linode entity type', () => {
+ const linodeFirewallAlertDetails = alertFactory.build({
+ id: 1,
+ rule_criteria: {
+ rules: [firewallMetricRulesFactory.build()],
+ },
+ scope: 'entity',
+ service_type: 'firewall',
+ });
+
+ const { getByTestId } = renderWithTheme(
+
+ );
+
+ const entityTypeSelect = getByTestId(ENTITY_TYPE_SELECT_TEST_ID);
+ expect(entityTypeSelect).toBeVisible();
+
+ const combobox = within(entityTypeSelect).getByRole('combobox');
+ expect(combobox).toHaveAttribute('value', 'Linodes');
+ });
+
+ it('should render EntityTypeSelect for firewall with NodeBalancer entity type', () => {
+ const nodebalancerFirewallAlertDetails = alertFactory.build({
+ id: 2,
+ rule_criteria: {
+ rules: [firewallNodebalancerMetricCriteria.build()],
+ },
+ scope: 'entity',
+ service_type: 'firewall',
+ });
+
+ const { getByTestId } = renderWithTheme(
+
+ );
+
+ const entityTypeSelect = getByTestId(ENTITY_TYPE_SELECT_TEST_ID);
+ expect(entityTypeSelect).toBeVisible();
+
+ const combobox = within(entityTypeSelect).getByRole('combobox');
+ expect(combobox).toHaveAttribute('value', 'NodeBalancers');
+ });
+
+ it('should not render EntityTypeSelect for non-firewall service types', () => {
+ const { queryByTestId } = renderWithTheme(
+
+ );
+
+ expect(queryByTestId(ENTITY_TYPE_SELECT_TEST_ID)).not.toBeInTheDocument();
+ });
});
diff --git a/packages/manager/src/features/CloudPulse/Alerts/EditAlert/EditAlertResources.tsx b/packages/manager/src/features/CloudPulse/Alerts/EditAlert/EditAlertResources.tsx
index fb24c4b98c3..8672f9a92f9 100644
--- a/packages/manager/src/features/CloudPulse/Alerts/EditAlert/EditAlertResources.tsx
+++ b/packages/manager/src/features/CloudPulse/Alerts/EditAlert/EditAlertResources.tsx
@@ -8,6 +8,7 @@ import { Breadcrumb } from 'src/components/Breadcrumb/Breadcrumb';
import { useEditAlertDefinition } from 'src/queries/cloudpulse/alerts';
import { AlertResources } from '../AlertsResources/AlertsResources';
+import { entityLabelMap } from '../constants';
import { isResourcesEqual } from '../Utils/AlertResourceUtils';
import { getAlertBoxStyles } from '../Utils/utils';
import { EditAlertResourcesConfirmDialog } from './EditAlertResourcesConfirmationDialog';
@@ -85,6 +86,14 @@ export const EditAlertResources = (props: EditAlertProps) => {
type,
} = alertDetails;
+ const entityType =
+ serviceType === 'firewall'
+ ? alertDetails.rule_criteria.rules[0]?.label.includes(
+ entityLabelMap['nodebalancer']
+ )
+ ? 'nodebalancer'
+ : 'linode'
+ : undefined;
return (
<>
@@ -100,6 +109,7 @@ export const EditAlertResources = (props: EditAlertProps) => {
alertLabel={label}
alertResourceIds={entity_ids}
alertType={type}
+ entityType={entityType}
handleResourcesSelection={handleResourcesSelection}
isSelectionsNeeded
serviceType={service_type}
diff --git a/packages/manager/src/mocks/serverHandlers.ts b/packages/manager/src/mocks/serverHandlers.ts
index ee7e446336b..c888dac3e55 100644
--- a/packages/manager/src/mocks/serverHandlers.ts
+++ b/packages/manager/src/mocks/serverHandlers.ts
@@ -3219,6 +3219,28 @@ export const handlers = [
rules: [firewallNodebalancerMetricCriteria.build()],
},
}),
+ alertFactory.build({
+ id: 340,
+ label: 'Firewall-nodebalancer-system',
+ type: 'system',
+ service_type: 'firewall',
+ entity_ids: ['25'],
+ rule_criteria: {
+ rules: [
+ firewallNodebalancerMetricCriteria.build({ dimension_filters: [] }),
+ ],
+ },
+ }),
+ alertFactory.build({
+ id: 123,
+ label: 'Firewall-linode-system',
+ type: 'system',
+ service_type: 'firewall',
+ entity_ids: ['1', '4'],
+ rule_criteria: {
+ rules: [firewallMetricRulesFactory.build()],
+ },
+ }),
];
return HttpResponse.json(makeResourcePage(alerts));
}),
@@ -3286,6 +3308,38 @@ export const handlers = [
})
);
}
+ if (params.id === '340' && params.serviceType === 'firewall') {
+ return HttpResponse.json(
+ alertFactory.build({
+ id: 340,
+ label: 'Firewall - nodebalancer - system',
+ type: 'system',
+ service_type: 'firewall',
+ entity_ids: ['25'],
+ rule_criteria: {
+ rules: [
+ firewallNodebalancerMetricCriteria.build({
+ dimension_filters: [],
+ }),
+ ],
+ },
+ })
+ );
+ }
+ if (params.id === '123' && params.serviceType === 'firewall') {
+ return HttpResponse.json(
+ alertFactory.build({
+ id: 123,
+ label: 'Firewall-linode-system',
+ type: 'system',
+ service_type: 'firewall',
+ entity_ids: ['1', '4'],
+ rule_criteria: {
+ rules: [firewallMetricRulesFactory.build()],
+ },
+ })
+ );
+ }
if (params.id !== undefined) {
return HttpResponse.json(
alertFactory.build({
From ef871db91442ef0800582d5b8d5700d28e3f6743 Mon Sep 17 00:00:00 2001
From: santoshp210-akamai
<159890961+santoshp210-akamai@users.noreply.github.com>
Date: Thu, 20 Nov 2025 11:16:38 +0530
Subject: [PATCH 2/3] add changeset
---
.../.changeset/pr-13110-upcoming-features-1763617588411.md | 5 +++++
1 file changed, 5 insertions(+)
create mode 100644 packages/manager/.changeset/pr-13110-upcoming-features-1763617588411.md
diff --git a/packages/manager/.changeset/pr-13110-upcoming-features-1763617588411.md b/packages/manager/.changeset/pr-13110-upcoming-features-1763617588411.md
new file mode 100644
index 00000000000..17bae8d23d4
--- /dev/null
+++ b/packages/manager/.changeset/pr-13110-upcoming-features-1763617588411.md
@@ -0,0 +1,5 @@
+---
+"@linode/manager": Upcoming Features
+---
+
+ACLP-Alerting: Filtering entities for firewall system alerts, add tooltip text to Entity Type component ([#13110](https://github.com/linode/manager/pull/13110))
From d15e06e583ab5de4f00abd460ccafb52ad24cbeb Mon Sep 17 00:00:00 2001
From: santoshp210-akamai
<159890961+santoshp210-akamai@users.noreply.github.com>
Date: Tue, 25 Nov 2025 09:30:44 +0530
Subject: [PATCH 3/3] upcoming: [DI-28227] - Use constant for the tooltip
string
---
.../GeneralInformation/EntityTypeSelect.test.tsx | 7 ++-----
.../CreateAlert/GeneralInformation/EntityTypeSelect.tsx | 7 ++++---
.../manager/src/features/CloudPulse/Alerts/constants.ts | 3 +++
3 files changed, 9 insertions(+), 8 deletions(-)
diff --git a/packages/manager/src/features/CloudPulse/Alerts/CreateAlert/GeneralInformation/EntityTypeSelect.test.tsx b/packages/manager/src/features/CloudPulse/Alerts/CreateAlert/GeneralInformation/EntityTypeSelect.test.tsx
index d6258cc7024..4a4065dceff 100644
--- a/packages/manager/src/features/CloudPulse/Alerts/CreateAlert/GeneralInformation/EntityTypeSelect.test.tsx
+++ b/packages/manager/src/features/CloudPulse/Alerts/CreateAlert/GeneralInformation/EntityTypeSelect.test.tsx
@@ -4,6 +4,7 @@ import * as React from 'react';
import { renderWithThemeAndHookFormContext } from 'src/utilities/testHelpers';
+import { entityTypeTooltipText } from '../../constants';
import { EntityTypeSelect } from './EntityTypeSelect';
describe('EntityTypeSelect component tests', () => {
@@ -146,11 +147,7 @@ describe('EntityTypeSelect component tests', () => {
await userEvent.hover(helpButton);
- expect(
- await screen.findByText(
- '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.'
- )
- ).toBeVisible();
+ expect(await screen.findByText(entityTypeTooltipText)).toBeVisible();
await userEvent.unhover(helpButton);
});
diff --git a/packages/manager/src/features/CloudPulse/Alerts/CreateAlert/GeneralInformation/EntityTypeSelect.tsx b/packages/manager/src/features/CloudPulse/Alerts/CreateAlert/GeneralInformation/EntityTypeSelect.tsx
index 405e42e44d0..1ecef33f6b9 100644
--- a/packages/manager/src/features/CloudPulse/Alerts/CreateAlert/GeneralInformation/EntityTypeSelect.tsx
+++ b/packages/manager/src/features/CloudPulse/Alerts/CreateAlert/GeneralInformation/EntityTypeSelect.tsx
@@ -3,7 +3,8 @@ import * as React from 'react';
import { Controller, useFormContext } from 'react-hook-form';
import type { ControllerRenderProps, FieldPathByValue } from 'react-hook-form';
-import type { Item } from '../../constants';
+import { entityTypeTooltipText, type Item } from '../../constants';
+
import type { CreateAlertDefinitionForm } from '../types';
interface EntityTypeSelectProps {
@@ -56,8 +57,8 @@ export const EntityTypeSelect = (props: EntityTypeSelectProps) => {
placeholder="Select an Entity Type"
sx={{ marginTop: '5px' }}
textFieldProps={{
- labelTooltipText:
- '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.',
+ labelTooltipText: entityTypeTooltipText,
+ tooltipPosition: 'right',
}}
value={
entityTypeOptions.find((option) => option.value === field.value) ??
diff --git a/packages/manager/src/features/CloudPulse/Alerts/constants.ts b/packages/manager/src/features/CloudPulse/Alerts/constants.ts
index d796dad6c75..45ba4ff3c1a 100644
--- a/packages/manager/src/features/CloudPulse/Alerts/constants.ts
+++ b/packages/manager/src/features/CloudPulse/Alerts/constants.ts
@@ -274,3 +274,6 @@ export const entityLabelMap = {
linode: 'Linode',
nodebalancer: 'Node Balancer',
};
+
+export const entityTypeTooltipText =
+ '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.';