From c9ed9427271a9950004624c7079c7ca4cf94b536 Mon Sep 17 00:00:00 2001 From: ankitaakamai Date: Thu, 27 Mar 2025 13:06:25 +0530 Subject: [PATCH 1/6] upcoming:[DI-24112] - Add UTs for new components --- .../AlertsListing/GroupedAlerts.test.tsx | 114 ++++++++++++++++++ .../CloudPulse/Utils/UserPreference.test.ts | 52 ++++++++ 2 files changed, 166 insertions(+) create mode 100644 packages/manager/src/features/CloudPulse/Alerts/AlertsListing/GroupedAlerts.test.tsx create mode 100644 packages/manager/src/features/CloudPulse/Utils/UserPreference.test.ts diff --git a/packages/manager/src/features/CloudPulse/Alerts/AlertsListing/GroupedAlerts.test.tsx b/packages/manager/src/features/CloudPulse/Alerts/AlertsListing/GroupedAlerts.test.tsx new file mode 100644 index 00000000000..cbe8bfbc797 --- /dev/null +++ b/packages/manager/src/features/CloudPulse/Alerts/AlertsListing/GroupedAlerts.test.tsx @@ -0,0 +1,114 @@ +import userEvent from '@testing-library/user-event'; +import * as React from 'react'; +import { vi } from 'vitest'; + +import { alertFactory } from 'src/factories'; +import { renderWithTheme } from 'src/utilities/testHelpers'; + +import { GroupedAlertsTable } from './GroupedAlerts'; + +import type { Item } from '../constants'; +import type { Alert, AlertServiceType } from '@linode/api-v4'; +import type { GroupedBy } from '@linode/utilities'; + +const mockScrollToElement = vi.hoisted(() => vi.fn()); + +vi.mock('../Utils/AlertResourceUtils', () => ({ + scrollToElement: mockScrollToElement, +})); + +const mockHandleDetails = vi.fn(); +const mockHandleEdit = vi.fn(); +const mockHandleStatusChange = vi.fn(); + +const mockServices: Item[] = [ + { label: 'Linode', value: 'linode' }, + { label: 'Databases', value: 'dbaas' }, +]; + +const mockAlerts: GroupedBy = [ + [ + 'tag1', + [ + alertFactory.build({ label: 'Alert 1', tags: ['tag1'] }), + alertFactory.build({ label: 'Alert 2', tags: ['tag1'] }), + ], + ], + ['tag2', [alertFactory.build({ label: 'Alert 3', tags: ['tag2'] })]], +]; + +describe('GroupedAlertsTable', () => { + it('should render grouped alerts by tag', () => { + const { getByText } = renderWithTheme( + + ); + + expect(getByText('tag1')).toBeInTheDocument(); + expect(getByText('tag2')).toBeInTheDocument(); + expect(getByText('Alert 1')).toBeInTheDocument(); + expect(getByText('Alert 2')).toBeInTheDocument(); + expect(getByText('Alert 3')).toBeInTheDocument(); + }); + + it('should handle pagination properly', async () => { + const alerts: GroupedBy = [ + [ + 'tag1', + Array(50) + .fill(null) + .map(() => alertFactory.build({ tags: ['tag1'] })), + ], + ]; + + const { getByRole } = renderWithTheme( + + ); + + expect(getByRole('button', { name: 'page 1' })).toBeInTheDocument(); + await userEvent.click(getByRole('button', { name: 'Go to next page' })); + expect(getByRole('button', { name: 'page 2' })).toBeInTheDocument(); + }); + + it('should scroll to tag header when switching pages within tag pagination', async () => { + const manyAlerts: GroupedBy = [ + [ + 'tag1', + Array(50) + .fill(null) + .map(() => alertFactory.build({ tags: ['tag1'] })), + ], + ]; + + const { container, getByRole } = renderWithTheme( + + ); + + // Find and click next page within tag1's pagination + const nextPageButton = getByRole('button', { name: 'Go to next page' }); + await userEvent.click(nextPageButton); + + const tagHeader = container.querySelector('h2[data-qa-tag-header]'); + expect(tagHeader?.textContent).toBe('tag1'); + + // Ensure that the user is scrolled to the tag header + expect(mockScrollToElement).toHaveBeenCalledWith(tagHeader); + }); +}); diff --git a/packages/manager/src/features/CloudPulse/Utils/UserPreference.test.ts b/packages/manager/src/features/CloudPulse/Utils/UserPreference.test.ts new file mode 100644 index 00000000000..b74ab806160 --- /dev/null +++ b/packages/manager/src/features/CloudPulse/Utils/UserPreference.test.ts @@ -0,0 +1,52 @@ +import { vi } from 'vitest'; + +import { usePreferencesToggle } from './UserPreference'; + +const queryMocks = vi.hoisted(() => ({ + useMutatePreferences: vi.fn(), + usePreferences: vi.fn(), +})); + +vi.mock('@linode/queries', () => ({ + useMutatePreferences: queryMocks.useMutatePreferences, + usePreferences: queryMocks.usePreferences, +})); + +describe('usePreferencesToggle', () => { + it('should initialize with undefined preference', () => { + queryMocks.usePreferences.mockReturnValue({ data: undefined }); + queryMocks.useMutatePreferences.mockReturnValue({ + mutateAsync: vi.fn().mockResolvedValue(undefined), + }); + const result = usePreferencesToggle('alertsGroupByTag', [false, true]); + expect(result.preference).toBeUndefined(); + }); + + it('should toggle from undefined to second option', async () => { + const mockMutate = vi.fn().mockResolvedValue(undefined); + queryMocks.usePreferences.mockReturnValue({ data: undefined }); + queryMocks.useMutatePreferences.mockReturnValue({ + mutateAsync: mockMutate, + }); + + const result = usePreferencesToggle('alertsGroupByTag', [false, true]); + + const newValue = result.toggle(); + expect(newValue).toBe(true); + expect(mockMutate).toHaveBeenCalledWith({ alertsGroupByTag: true }); + }); + + it('should toggle between options', async () => { + const mockMutate = vi.fn().mockResolvedValue(undefined); + queryMocks.usePreferences.mockReturnValue({ data: false }); + queryMocks.useMutatePreferences.mockReturnValue({ + mutateAsync: mockMutate, + }); + + const result = usePreferencesToggle('alertsGroupByTag', [false, true]); + + const newValue = result.toggle(); + expect(newValue).toBe(true); + expect(mockMutate).toHaveBeenCalledWith({ alertsGroupByTag: true }); + }); +}); From 9f072864143142fc1e1459b356aaffb453cb9341 Mon Sep 17 00:00:00 2001 From: ankitaakamai Date: Thu, 3 Apr 2025 09:50:36 +0530 Subject: [PATCH 2/6] upcoming:[DI-24112] - Add new unit tests --- ...upedAlerts.test.tsx => GroupedAlertsTable.test.tsx} | 2 +- .../features/CloudPulse/Utils/UserPreference.test.ts | 10 +++++----- 2 files changed, 6 insertions(+), 6 deletions(-) rename packages/manager/src/features/CloudPulse/Alerts/AlertsListing/{GroupedAlerts.test.tsx => GroupedAlertsTable.test.tsx} (98%) diff --git a/packages/manager/src/features/CloudPulse/Alerts/AlertsListing/GroupedAlerts.test.tsx b/packages/manager/src/features/CloudPulse/Alerts/AlertsListing/GroupedAlertsTable.test.tsx similarity index 98% rename from packages/manager/src/features/CloudPulse/Alerts/AlertsListing/GroupedAlerts.test.tsx rename to packages/manager/src/features/CloudPulse/Alerts/AlertsListing/GroupedAlertsTable.test.tsx index cbe8bfbc797..2e519129e05 100644 --- a/packages/manager/src/features/CloudPulse/Alerts/AlertsListing/GroupedAlerts.test.tsx +++ b/packages/manager/src/features/CloudPulse/Alerts/AlertsListing/GroupedAlertsTable.test.tsx @@ -5,7 +5,7 @@ import { vi } from 'vitest'; import { alertFactory } from 'src/factories'; import { renderWithTheme } from 'src/utilities/testHelpers'; -import { GroupedAlertsTable } from './GroupedAlerts'; +import { GroupedAlertsTable } from './GroupedAlertsTable'; import type { Item } from '../constants'; import type { Alert, AlertServiceType } from '@linode/api-v4'; diff --git a/packages/manager/src/features/CloudPulse/Utils/UserPreference.test.ts b/packages/manager/src/features/CloudPulse/Utils/UserPreference.test.ts index b74ab806160..f0c58ce5cf0 100644 --- a/packages/manager/src/features/CloudPulse/Utils/UserPreference.test.ts +++ b/packages/manager/src/features/CloudPulse/Utils/UserPreference.test.ts @@ -18,7 +18,7 @@ describe('usePreferencesToggle', () => { queryMocks.useMutatePreferences.mockReturnValue({ mutateAsync: vi.fn().mockResolvedValue(undefined), }); - const result = usePreferencesToggle('alertsGroupByTag', [false, true]); + const result = usePreferencesToggle('aclpAlertsGroupByTag', [false, true]); expect(result.preference).toBeUndefined(); }); @@ -29,11 +29,11 @@ describe('usePreferencesToggle', () => { mutateAsync: mockMutate, }); - const result = usePreferencesToggle('alertsGroupByTag', [false, true]); + const result = usePreferencesToggle('aclpAlertsGroupByTag', [false, true]); const newValue = result.toggle(); expect(newValue).toBe(true); - expect(mockMutate).toHaveBeenCalledWith({ alertsGroupByTag: true }); + expect(mockMutate).toHaveBeenCalledWith({ aclpAlertsGroupByTag: true }); }); it('should toggle between options', async () => { @@ -43,10 +43,10 @@ describe('usePreferencesToggle', () => { mutateAsync: mockMutate, }); - const result = usePreferencesToggle('alertsGroupByTag', [false, true]); + const result = usePreferencesToggle('aclpAlertsGroupByTag', [false, true]); const newValue = result.toggle(); expect(newValue).toBe(true); - expect(mockMutate).toHaveBeenCalledWith({ alertsGroupByTag: true }); + expect(mockMutate).toHaveBeenCalledWith({ aclpAlertsGroupByTag: true }); }); }); From 8147dc34323a5c9e92063391b209d9ec7ad9e51c Mon Sep 17 00:00:00 2001 From: ankitaakamai Date: Wed, 16 Apr 2025 13:10:17 +0530 Subject: [PATCH 3/6] upcoming:[DI-24112] - Linting and fallback fixes --- .../AlertsListing/GroupedAlertsTable.test.tsx | 33 +++++++++++-------- .../CloudPulse/Utils/UserPreference.test.ts | 18 ++++++++-- .../CloudPulse/Utils/UserPreference.ts | 2 +- 3 files changed, 35 insertions(+), 18 deletions(-) diff --git a/packages/manager/src/features/CloudPulse/Alerts/AlertsListing/GroupedAlertsTable.test.tsx b/packages/manager/src/features/CloudPulse/Alerts/AlertsListing/GroupedAlertsTable.test.tsx index 2e519129e05..fe06386fe04 100644 --- a/packages/manager/src/features/CloudPulse/Alerts/AlertsListing/GroupedAlertsTable.test.tsx +++ b/packages/manager/src/features/CloudPulse/Alerts/AlertsListing/GroupedAlertsTable.test.tsx @@ -1,3 +1,4 @@ +import { screen } from '@testing-library/react'; import userEvent from '@testing-library/user-event'; import * as React from 'react'; import { vi } from 'vitest'; @@ -39,7 +40,7 @@ const mockAlerts: GroupedBy = [ describe('GroupedAlertsTable', () => { it('should render grouped alerts by tag', () => { - const { getByText } = renderWithTheme( + renderWithTheme( { /> ); - expect(getByText('tag1')).toBeInTheDocument(); - expect(getByText('tag2')).toBeInTheDocument(); - expect(getByText('Alert 1')).toBeInTheDocument(); - expect(getByText('Alert 2')).toBeInTheDocument(); - expect(getByText('Alert 3')).toBeInTheDocument(); + expect(screen.getByText('tag1')).toBeVisible(); + expect(screen.getByText('tag2')).toBeVisible(); + expect(screen.getByText('Alert 1')).toBeVisible(); + expect(screen.getByText('Alert 2')).toBeVisible(); + expect(screen.getByText('Alert 3')).toBeVisible(); }); it('should handle pagination properly', async () => { @@ -66,7 +67,7 @@ describe('GroupedAlertsTable', () => { ], ]; - const { getByRole } = renderWithTheme( + renderWithTheme( { /> ); - expect(getByRole('button', { name: 'page 1' })).toBeInTheDocument(); - await userEvent.click(getByRole('button', { name: 'Go to next page' })); - expect(getByRole('button', { name: 'page 2' })).toBeInTheDocument(); + expect(screen.getByRole('button', { name: 'page 1' })).toBeVisible(); + await userEvent.click( + screen.getByRole('button', { name: 'Go to next page' }) + ); + expect(screen.getByRole('button', { name: 'page 2' })).toBeVisible(); }); it('should scroll to tag header when switching pages within tag pagination', async () => { @@ -91,7 +94,7 @@ describe('GroupedAlertsTable', () => { ], ]; - const { container, getByRole } = renderWithTheme( + renderWithTheme( { ); // Find and click next page within tag1's pagination - const nextPageButton = getByRole('button', { name: 'Go to next page' }); + const nextPageButton = screen.getByRole('button', { + name: 'Go to next page', + }); await userEvent.click(nextPageButton); - const tagHeader = container.querySelector('h2[data-qa-tag-header]'); - expect(tagHeader?.textContent).toBe('tag1'); + const tagHeader = screen.getByRole('heading', { name: 'tag1' }); + expect(tagHeader).toBeVisible(); // Ensure that the user is scrolled to the tag header expect(mockScrollToElement).toHaveBeenCalledWith(tagHeader); diff --git a/packages/manager/src/features/CloudPulse/Utils/UserPreference.test.ts b/packages/manager/src/features/CloudPulse/Utils/UserPreference.test.ts index f0c58ce5cf0..20d401a56dc 100644 --- a/packages/manager/src/features/CloudPulse/Utils/UserPreference.test.ts +++ b/packages/manager/src/features/CloudPulse/Utils/UserPreference.test.ts @@ -18,7 +18,11 @@ describe('usePreferencesToggle', () => { queryMocks.useMutatePreferences.mockReturnValue({ mutateAsync: vi.fn().mockResolvedValue(undefined), }); - const result = usePreferencesToggle('aclpAlertsGroupByTag', [false, true]); + const result = usePreferencesToggle({ + preferenceKey: 'aclpAlertsGroupByTag', + options: [false, true], + defaultValue: false, + }); expect(result.preference).toBeUndefined(); }); @@ -29,7 +33,11 @@ describe('usePreferencesToggle', () => { mutateAsync: mockMutate, }); - const result = usePreferencesToggle('aclpAlertsGroupByTag', [false, true]); + const result = usePreferencesToggle({ + preferenceKey: 'aclpAlertsGroupByTag', + options: [false, true], + defaultValue: false, + }); const newValue = result.toggle(); expect(newValue).toBe(true); @@ -43,7 +51,11 @@ describe('usePreferencesToggle', () => { mutateAsync: mockMutate, }); - const result = usePreferencesToggle('aclpAlertsGroupByTag', [false, true]); + const result = usePreferencesToggle({ + preferenceKey: 'aclpAlertsGroupByTag', + options: [false, true], + defaultValue: false, + }); const newValue = result.toggle(); expect(newValue).toBe(true); diff --git a/packages/manager/src/features/CloudPulse/Utils/UserPreference.ts b/packages/manager/src/features/CloudPulse/Utils/UserPreference.ts index 5541d155f83..c8985199e51 100644 --- a/packages/manager/src/features/CloudPulse/Utils/UserPreference.ts +++ b/packages/manager/src/features/CloudPulse/Utils/UserPreference.ts @@ -108,7 +108,7 @@ export const usePreferencesToggle = ({ // if the preference is undefined, set it to false if (preference === undefined) { - newPreferenceToSet = defaultValue; + newPreferenceToSet = options[defaultValue === options[0] ? 1 : 0]; } else if (preference === options[0]) { newPreferenceToSet = options[1]; } else { From 2f7220bf1b779b7e6da93608e405808c6b519e9c Mon Sep 17 00:00:00 2001 From: ankitaakamai Date: Wed, 16 Apr 2025 13:44:08 +0530 Subject: [PATCH 4/6] upcoming:[DI-24112] - Update UT --- .../AlertsListing/GroupedAlertsTable.test.tsx | 14 ++------------ 1 file changed, 2 insertions(+), 12 deletions(-) diff --git a/packages/manager/src/features/CloudPulse/Alerts/AlertsListing/GroupedAlertsTable.test.tsx b/packages/manager/src/features/CloudPulse/Alerts/AlertsListing/GroupedAlertsTable.test.tsx index fe06386fe04..511ff06e6a1 100644 --- a/packages/manager/src/features/CloudPulse/Alerts/AlertsListing/GroupedAlertsTable.test.tsx +++ b/packages/manager/src/features/CloudPulse/Alerts/AlertsListing/GroupedAlertsTable.test.tsx @@ -59,12 +59,7 @@ describe('GroupedAlertsTable', () => { it('should handle pagination properly', async () => { const alerts: GroupedBy = [ - [ - 'tag1', - Array(50) - .fill(null) - .map(() => alertFactory.build({ tags: ['tag1'] })), - ], + ['tag1', alertFactory.buildList(50, { tags: ['tag1'] })], ]; renderWithTheme( @@ -86,12 +81,7 @@ describe('GroupedAlertsTable', () => { it('should scroll to tag header when switching pages within tag pagination', async () => { const manyAlerts: GroupedBy = [ - [ - 'tag1', - Array(50) - .fill(null) - .map(() => alertFactory.build({ tags: ['tag1'] })), - ], + ['tag1', alertFactory.buildList(50, { tags: ['tag1'] })], ]; renderWithTheme( From a055472c8b4bd6188aad2a284f407395e16527dd Mon Sep 17 00:00:00 2001 From: ankitaakamai Date: Wed, 16 Apr 2025 13:46:25 +0530 Subject: [PATCH 5/6] upcoming:[DI-24112] - Update UT --- .../Alerts/AlertsListing/GroupedAlertsTable.test.tsx | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/packages/manager/src/features/CloudPulse/Alerts/AlertsListing/GroupedAlertsTable.test.tsx b/packages/manager/src/features/CloudPulse/Alerts/AlertsListing/GroupedAlertsTable.test.tsx index 511ff06e6a1..c922a49751d 100644 --- a/packages/manager/src/features/CloudPulse/Alerts/AlertsListing/GroupedAlertsTable.test.tsx +++ b/packages/manager/src/features/CloudPulse/Alerts/AlertsListing/GroupedAlertsTable.test.tsx @@ -80,13 +80,13 @@ describe('GroupedAlertsTable', () => { }); it('should scroll to tag header when switching pages within tag pagination', async () => { - const manyAlerts: GroupedBy = [ + const alerts: GroupedBy = [ ['tag1', alertFactory.buildList(50, { tags: ['tag1'] })], ]; renderWithTheme( Date: Wed, 16 Apr 2025 15:17:33 +0530 Subject: [PATCH 6/6] upcoming:[DI-24112] - Add changeset --- .../.changeset/pr-12042-upcoming-features-1744796837347.md | 5 +++++ 1 file changed, 5 insertions(+) create mode 100644 packages/manager/.changeset/pr-12042-upcoming-features-1744796837347.md diff --git a/packages/manager/.changeset/pr-12042-upcoming-features-1744796837347.md b/packages/manager/.changeset/pr-12042-upcoming-features-1744796837347.md new file mode 100644 index 00000000000..8a2e5ac94a6 --- /dev/null +++ b/packages/manager/.changeset/pr-12042-upcoming-features-1744796837347.md @@ -0,0 +1,5 @@ +--- +"@linode/manager": Upcoming Features +--- + +Add unit tests in `GroupedAlertsTable.test.ts` and `UserPreference.test.ts` and fix preferences for alerts grouping at CloudPulse ([#12042](https://github.com/linode/manager/pull/12042))