Skip to content
5 changes: 5 additions & 0 deletions packages/manager/.changeset/pr-11869-fixed-1742283252552.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
---
"@linode/manager": Fixed
---

Navigation for metrics and alerts under Monitor at `PrimaryNav.tsx` ([#11869](https://github.com/linode/manager/pull/11869))
103 changes: 94 additions & 9 deletions packages/manager/src/components/PrimaryNav/PrimaryNav.test.tsx
Original file line number Diff line number Diff line change
@@ -1,14 +1,14 @@
import { queryClientFactory } from '@linode/queries';
import * as React from 'react';

import { accountFactory } from 'src/factories';
import { HttpResponse, http, server } from 'src/mocks/testServer';
import { queryClientFactory } from '@linode/queries';
import { renderWithTheme, wrapWithTheme } from 'src/utilities/testHelpers';

import PrimaryNav from './PrimaryNav';

import type { Flags } from 'src/featureFlags';
import type { ManagerPreferences } from '@linode/utilities';
import type { Flags } from 'src/featureFlags';

const props = {
closeMenu: vi.fn(),
Expand Down Expand Up @@ -206,7 +206,7 @@ describe('PrimaryNav', () => {
expect(databaseNavItem).toBeVisible();
});

it('should show Monitor menu item if the user has the account capability', async () => {
it('should show Metrics and Alerts menu items if the user has the account capability, aclp feature flag is enabled, and aclpAlerting feature flag has any of the properties true', async () => {
const account = accountFactory.build({
capabilities: ['Akamai Cloud Pulse'],
});
Expand All @@ -219,21 +219,106 @@ describe('PrimaryNav', () => {

const flags = {
aclp: {
beta: false,
beta: true,
enabled: true,
},
aclpAlerting: {
alertDefinitions: true,
notificationChannels: false,
recentActivity: false,
},
};

const { findByText } = renderWithTheme(<PrimaryNav {...props} />, {
flags,
});
const { findAllByTestId, findByText } = renderWithTheme(
<PrimaryNav {...props} />,
{
flags,
}
);

const monitorNavItem = await findByText('Monitor');
const monitorMetricsDisplayItem = await findByText('Metrics');
const monitorAlertsDisplayItem = await findByText('Alerts');
const betaChip = await findAllByTestId('betaChip');

expect(monitorNavItem).toBeVisible();
expect(monitorMetricsDisplayItem).toBeVisible();
expect(monitorAlertsDisplayItem).toBeVisible();
expect(betaChip).toHaveLength(2);
});

it('should not show Metrics and Alerts menu items if the user has the account capability but the aclp feature flag is not enabled', async () => {
const account = accountFactory.build({
capabilities: ['Akamai Cloud Pulse'],
});

server.use(
http.get('*/account', () => {
return HttpResponse.json(account);
})
);

const flags = {
aclp: {
beta: false,
enabled: false,
},
aclpAlerting: {
alertDefinitions: true,
notificationChannels: true,
recentActivity: true,
},
};

const { queryByTestId, queryByText } = renderWithTheme(
<PrimaryNav {...props} />,
{
flags,
}
);

const monitorMetricsDisplayItem = queryByText('Metrics');
const monitorAlertsDisplayItem = queryByText('Alerts');

expect(monitorMetricsDisplayItem).toBeNull();
expect(monitorAlertsDisplayItem).toBeNull();
expect(queryByTestId('betaChip')).toBeNull();
});

it('should not show Alerts menu items if the user has the account capability, aclp feature flag is enabled, and aclpAlerting feature flag does not have any of the properties true', async () => {
const account = accountFactory.build({
capabilities: ['Akamai Cloud Pulse'],
});

server.use(
http.get('*/account', () => {
return HttpResponse.json(account);
})
);

const flags = {
aclp: {
beta: true,
enabled: true,
},
aclpAlerting: {
alertDefinitions: false,
notificationChannels: false,
recentActivity: false,
},
};

const { findByTestId, findByText, queryByText } = renderWithTheme(
<PrimaryNav {...props} />,
{
flags,
}
);

const monitorMetricsDisplayItem = await findByText('Metrics'); // Metrics should be visible
const monitorAlertsDisplayItem = queryByText('Alerts');
const betaChip = await findByTestId('betaChip');

expect(monitorMetricsDisplayItem).toBeVisible();
expect(monitorAlertsDisplayItem).toBeNull();
expect(betaChip).toBeVisible();
});
});
14 changes: 7 additions & 7 deletions packages/manager/src/components/PrimaryNav/PrimaryNav.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -91,6 +91,12 @@ export const PrimaryNav = (props: PrimaryNavProps) => {

const { isACLPEnabled } = useIsACLPEnabled();

const isAlertsEnabled =
isACLPEnabled &&
(flags.aclpAlerting?.alertDefinitions ||
flags.aclpAlerting?.recentActivity ||
flags.aclpAlerting?.notificationChannels);

const { isPlacementGroupsEnabled } = useIsPlacementGroupsEnabled();
const { isDatabasesEnabled, isDatabasesV2Beta } = useIsDatabasesEnabled();

Expand Down Expand Up @@ -226,13 +232,7 @@ export const PrimaryNav = (props: PrimaryNavProps) => {
},
{
display: 'Alerts',
hide:
!isACLPEnabled &&
!(
flags.aclpAlerting?.alertDefinitions ||
flags.aclpAlerting?.recentActivity ||
flags.aclpAlerting?.notificationChannels
),
hide: !isAlertsEnabled,
href: '/alerts',
isBeta: flags.aclp?.beta,
},
Expand Down
1 change: 1 addition & 0 deletions packages/manager/src/dev-tools/FeatureFlagTool.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -20,6 +20,7 @@ const MOCK_FEATURE_FLAGS_STORAGE_KEY = 'devTools/mock-feature-flags';
*/
const options: { flag: keyof Flags; label: string }[] = [
{ flag: 'aclp', label: 'CloudPulse' },
{ flag: 'aclpAlerting', label: 'CloudPulse Alerting' },
{ flag: 'apl', label: 'Akamai App Platform' },
{ flag: 'blockStorageEncryption', label: 'Block Storage Encryption (BSE)' },
{ flag: 'disableLargestGbPlans', label: 'Disable Largest GB Plans' },
Expand Down