From c0df88f02f8f2ef3159ca68840b3b631b8f316f4 Mon Sep 17 00:00:00 2001 From: Rohit Jain <60229265+Rohit0301@users.noreply.github.com> Date: Thu, 16 Oct 2025 14:18:59 +0530 Subject: [PATCH] Fixes 23223: Mentions from incidents/entities not showing in Notifications (#23874) * Fix: Notifications not showing the mentions from incident/entity * Fix: Fixed the unit test * Playwright: Added test for verifing incident manager mention notification * Fix: Addressed PR comments * Fix: fixed code smells * Playwright: Fixed the playwright tests --------- Co-authored-by: Ashish Gupta --- .../e2e/Features/ActivityFeed.spec.ts | 3 +-- .../e2e/Features/IncidentManager.spec.ts | 24 ++++++++++++++++++- .../ui/playwright/utils/activityFeed.ts | 8 ------- .../resources/ui/playwright/utils/entity.ts | 2 +- .../ui/src/components/NavBar/NavBar.tsx | 15 +++++------- .../NotificationBox.component.tsx | 17 +++++++------ .../NotificationBox.interface.ts | 1 + .../NotificationBox/NotificationBox.test.tsx | 1 + .../NotificationBox/NotificationBox.utils.tsx | 2 +- 9 files changed, 44 insertions(+), 29 deletions(-) diff --git a/openmetadata-ui/src/main/resources/ui/playwright/e2e/Features/ActivityFeed.spec.ts b/openmetadata-ui/src/main/resources/ui/playwright/e2e/Features/ActivityFeed.spec.ts index 4056d8ee1eb..e2276d045a6 100644 --- a/openmetadata-ui/src/main/resources/ui/playwright/e2e/Features/ActivityFeed.spec.ts +++ b/openmetadata-ui/src/main/resources/ui/playwright/e2e/Features/ActivityFeed.spec.ts @@ -536,8 +536,7 @@ test.describe('Mention notifications in Notification Box', () => { const mentionsFeedResponse = adminPage.waitForResponse( (response) => response.url().includes('/api/v1/feed') && - response.url().includes('filterType=MENTIONS') && - response.url().includes('type=Conversation') + response.url().includes('filterType=MENTIONS') ); await mentionsTab.click(); diff --git a/openmetadata-ui/src/main/resources/ui/playwright/e2e/Features/IncidentManager.spec.ts b/openmetadata-ui/src/main/resources/ui/playwright/e2e/Features/IncidentManager.spec.ts index 7ae9db43dbe..c889fb85d66 100644 --- a/openmetadata-ui/src/main/resources/ui/playwright/e2e/Features/IncidentManager.spec.ts +++ b/openmetadata-ui/src/main/resources/ui/playwright/e2e/Features/IncidentManager.spec.ts @@ -17,6 +17,7 @@ import { SidebarItem } from '../../constant/sidebar'; import { EntityTypeEndpoint } from '../../support/entity/Entity.interface'; import { TableClass } from '../../support/entity/TableClass'; import { UserClass } from '../../support/user/UserClass'; +import { addMentionCommentInFeed } from '../../utils/activityFeed'; import { performAdminLogin } from '../../utils/admin'; import { resetTokenFromBotPage } from '../../utils/bot'; import { @@ -25,7 +26,7 @@ import { getApiContext, redirectToHomePage, } from '../../utils/common'; -import { addOwner } from '../../utils/entity'; +import { addOwner, waitForAllLoadersToDisappear } from '../../utils/entity'; import { acknowledgeTask, assignIncident, @@ -208,6 +209,27 @@ test.describe('Incident Manager', PLAYWRIGHT_INGESTION_TAG_OBJ, () => { await updateAssignee; }); + await test.step( + 'Verify that notifications correctly display mentions for the incident manager', + async () => { + const testcaseName = await page + .getByTestId('entity-header-name') + .innerText(); + await addMentionCommentInFeed(page, 'admin', true); + + await adminPage.waitForLoadState('networkidle'); + await waitForAllLoadersToDisappear(adminPage); + await adminPage.getByRole('button', { name: 'Notifications' }).click(); + await adminPage.getByText('Mentions').click(); + await adminPage.waitForLoadState('networkidle'); + await waitForAllLoadersToDisappear(adminPage); + + await expect(adminPage.getByLabel('Mentions')).toContainText( + `mentioned you on the testCase ${testcaseName}` + ); + } + ); + await test.step( "Re-assign incident from test case page's header", async () => { diff --git a/openmetadata-ui/src/main/resources/ui/playwright/utils/activityFeed.ts b/openmetadata-ui/src/main/resources/ui/playwright/utils/activityFeed.ts index 14688e1893d..a4183cf1c57 100644 --- a/openmetadata-ui/src/main/resources/ui/playwright/utils/activityFeed.ts +++ b/openmetadata-ui/src/main/resources/ui/playwright/utils/activityFeed.ts @@ -128,14 +128,6 @@ export const addMentionCommentInFeed = async ( await page.waitForSelector('[data-testid="loader"]', { state: 'detached' }); - const firstMessage = getNthFeedMessage(page, 0); - - await expect(firstMessage).toBeVisible(); - - await firstMessage.locator('[data-testid="reply-count"]').click(); - await page.waitForSelector('.ant-drawer-content', { - state: 'visible', - }); await page.getByTestId('comments-input-field').click(); const userSuggestionsResponse = page.waitForResponse( diff --git a/openmetadata-ui/src/main/resources/ui/playwright/utils/entity.ts b/openmetadata-ui/src/main/resources/ui/playwright/utils/entity.ts index 3689050e1d4..b4753d0c652 100644 --- a/openmetadata-ui/src/main/resources/ui/playwright/utils/entity.ts +++ b/openmetadata-ui/src/main/resources/ui/playwright/utils/entity.ts @@ -103,7 +103,7 @@ export const addOwner = async ({ await page.getByTestId(initiatorId).click(); if (type === 'Users') { const userListResponse = page.waitForResponse( - '/api/v1/search/query?q=&index=user_search_index&*' + '/api/v1/search/query?q=*&index=user_search_index&*' ); await page.getByRole('tab', { name: type }).click(); await userListResponse; diff --git a/openmetadata-ui/src/main/resources/ui/src/components/NavBar/NavBar.tsx b/openmetadata-ui/src/main/resources/ui/src/components/NavBar/NavBar.tsx index 1b787eddf90..b27dd4fc2f5 100644 --- a/openmetadata-ui/src/main/resources/ui/src/components/NavBar/NavBar.tsx +++ b/openmetadata-ui/src/main/resources/ui/src/components/NavBar/NavBar.tsx @@ -52,11 +52,7 @@ import { useTourProvider } from '../../context/TourProvider/TourProvider'; import { useWebSocketConnector } from '../../context/WebSocketProvider/WebSocketProvider'; import { EntityTabs, EntityType } from '../../enums/entity.enum'; import { EntityReference } from '../../generated/entity/type'; -import { - BackgroundJob, - EnumCleanupArgs, - JobType, -} from '../../generated/jobs/backgroundJob'; +import { BackgroundJob, JobType } from '../../generated/jobs/backgroundJob'; import { useCurrentUserPreferences } from '../../hooks/currentUserStore/useCurrentUserStore'; import { useApplicationStore } from '../../hooks/useApplicationStore'; import useCustomLocation from '../../hooks/useCustomLocation/useCustomLocation'; @@ -248,7 +244,7 @@ const NavBar = () => { const { jobArgs, status, jobType } = backgroundJobData; if (jobType === JobType.CustomPropertyEnumCleanup) { - const enumCleanupArgs = jobArgs as EnumCleanupArgs; + const enumCleanupArgs = jobArgs; if (!enumCleanupArgs.entityType) { showErrorToast( { @@ -280,11 +276,11 @@ const NavBar = () => { icon: Logo, }); notification.onclick = () => { - const isChrome = window.navigator.userAgent.indexOf('Chrome'); + const isChrome = globalThis.navigator.userAgent.indexOf('Chrome'); // Applying logic to open a new window onclick of browser notification from chrome // As it does not open the concerned tab by default. if (isChrome > -1) { - window.open(path); + globalThis.open(path); } else { navigate(path); } @@ -317,7 +313,7 @@ const NavBar = () => { const now = Date.now(); if (lastFetchTime) { - const timeSinceLastFetch = now - parseInt(lastFetchTime); + const timeSinceLastFetch = now - Number.parseInt(lastFetchTime); if (timeSinceLastFetch < ONE_HOUR_MS) { // Less than 1 hour since last fetch, skip API call return; @@ -532,6 +528,7 @@ const NavBar = () => { className="cursor-pointer" dropdownRender={() => ( 0 ) { @@ -85,9 +87,10 @@ const NotificationBox = ({ ) .sort((a, b) => (b.postTs ?? 0) - (a.postTs ?? 0))[0]; - if (mentionPost && mentionPost.postTs !== undefined) { + if (mentionPost?.postTs !== undefined) { actualUser = mentionPost.from; actualTimestamp = mentionPost.postTs; + feedType = ThreadType.Conversation; } } @@ -96,7 +99,7 @@ const NotificationBox = ({ createdBy={actualUser} entityFQN={entityFQN as string} entityType={entityType as string} - feedType={feed.type || ThreadType.Conversation} + feedType={feedType} key={`${actualUser} ${mainFeed.id}`} task={feed} timestamp={actualTimestamp} @@ -106,8 +109,8 @@ const NotificationBox = ({ }, [notifications]); const getNotificationData = ( - threadType: ThreadType, - feedFilter: FeedFilter + feedFilter: FeedFilter, + threadType?: ThreadType ) => { setIsLoading(true); getFeedsWithFilter(currentUser?.id, feedFilter, undefined, threadType) @@ -132,7 +135,7 @@ const NotificationBox = ({ onTabChange(key); const { threadType, feedFilter } = getFilters(key as ThreadType); - getNotificationData(threadType, feedFilter); + getNotificationData(feedFilter, threadType); setViewAllPath( getUserPath( @@ -156,7 +159,7 @@ const NotificationBox = ({ ); useEffect(() => { - getNotificationData(ThreadType.Task, FeedFilter.ASSIGNED_TO); + getNotificationData(FeedFilter.ASSIGNED_TO, ThreadType.Task); }, []); const getTabTitle = (name: string, key: string) => { diff --git a/openmetadata-ui/src/main/resources/ui/src/components/NotificationBox/NotificationBox.interface.ts b/openmetadata-ui/src/main/resources/ui/src/components/NotificationBox/NotificationBox.interface.ts index ee99496a6bc..b68af01004f 100644 --- a/openmetadata-ui/src/main/resources/ui/src/components/NotificationBox/NotificationBox.interface.ts +++ b/openmetadata-ui/src/main/resources/ui/src/components/NotificationBox/NotificationBox.interface.ts @@ -12,6 +12,7 @@ */ export interface NotificationBoxProp { + activeTab: string; hasMentionNotification: boolean; hasTaskNotification: boolean; onMarkMentionsNotificationRead: () => void; diff --git a/openmetadata-ui/src/main/resources/ui/src/components/NotificationBox/NotificationBox.test.tsx b/openmetadata-ui/src/main/resources/ui/src/components/NotificationBox/NotificationBox.test.tsx index 272f0e6a516..62c13481283 100644 --- a/openmetadata-ui/src/main/resources/ui/src/components/NotificationBox/NotificationBox.test.tsx +++ b/openmetadata-ui/src/main/resources/ui/src/components/NotificationBox/NotificationBox.test.tsx @@ -61,6 +61,7 @@ const mockShowErrorToast = jest.fn(); const mockOnMarkTaskNotificationRead = jest.fn(); const mockProps = { + activeTab: ThreadType.Task, hasMentionNotification: true, hasTaskNotification: true, onMarkMentionsNotificationRead: jest.fn(), diff --git a/openmetadata-ui/src/main/resources/ui/src/components/NotificationBox/NotificationBox.utils.tsx b/openmetadata-ui/src/main/resources/ui/src/components/NotificationBox/NotificationBox.utils.tsx index ac3eb626a45..5ddb863e62e 100644 --- a/openmetadata-ui/src/main/resources/ui/src/components/NotificationBox/NotificationBox.utils.tsx +++ b/openmetadata-ui/src/main/resources/ui/src/components/NotificationBox/NotificationBox.utils.tsx @@ -47,7 +47,7 @@ export const tabsInfo = [ ]; export const getFilters = (activeTab: ThreadType) => ({ - threadType: activeTab, + threadType: activeTab === ThreadType.Task ? activeTab : undefined, feedFilter: activeTab === ThreadType.Task ? FeedFilter.ASSIGNED_TO