mirror of
				https://github.com/open-metadata/OpenMetadata.git
				synced 2025-10-31 10:39:30 +00:00 
			
		
		
		
	PLAYWRIGHT: fix activity feed aut flaky failures (#18101)
* fix activity feed aut flaky failures * remove the unwanted class and arrange it in common place * added custom hook to check floating button element in dom (cherry picked from commit 9a116d676de1b9f580b55c92625ce338c180e5f2)
This commit is contained in:
		
							parent
							
								
									e5d43bce96
								
							
						
					
					
						commit
						55bb4757ba
					
				| @ -211,8 +211,6 @@ test.describe('Activity feed', () => { | |||||||
| 
 | 
 | ||||||
|     await toastNotification(page, /Task resolved successfully/); |     await toastNotification(page, /Task resolved successfully/); | ||||||
| 
 | 
 | ||||||
|     await page.waitForLoadState('networkidle'); |  | ||||||
| 
 |  | ||||||
|     await checkTaskCount(page, 0, 2); |     await checkTaskCount(page, 0, 2); | ||||||
|   }); |   }); | ||||||
| 
 | 
 | ||||||
| @ -372,8 +370,6 @@ test.describe('Activity feed', () => { | |||||||
| 
 | 
 | ||||||
|     await toastNotification(page, /Task resolved successfully/); |     await toastNotification(page, /Task resolved successfully/); | ||||||
| 
 | 
 | ||||||
|     await page.waitForLoadState('networkidle'); |  | ||||||
| 
 |  | ||||||
|     await checkTaskCount(page, 0, 2); |     await checkTaskCount(page, 0, 2); | ||||||
|   }); |   }); | ||||||
| 
 | 
 | ||||||
| @ -434,8 +430,6 @@ test.describe('Activity feed', () => { | |||||||
| 
 | 
 | ||||||
|     await toastNotification(page, 'Task closed successfully.'); |     await toastNotification(page, 'Task closed successfully.'); | ||||||
| 
 | 
 | ||||||
|     await page.waitForLoadState('networkidle'); |  | ||||||
| 
 |  | ||||||
|     await checkTaskCount(page, 0, 1); |     await checkTaskCount(page, 0, 1); | ||||||
|   }); |   }); | ||||||
| 
 | 
 | ||||||
| @ -456,12 +450,8 @@ test.describe('Activity feed', () => { | |||||||
|     await createDescriptionTask(page, value); |     await createDescriptionTask(page, value); | ||||||
|     await openTaskAfterDescriptionResponse; |     await openTaskAfterDescriptionResponse; | ||||||
| 
 | 
 | ||||||
|     await page.waitForLoadState('networkidle'); |  | ||||||
| 
 |  | ||||||
|     // open task count after description
 |     // open task count after description
 | ||||||
|     const openTask1 = await page.getByTestId('open-task').textContent(); |     await checkTaskCount(page, 1, 0); | ||||||
| 
 |  | ||||||
|     expect(openTask1).toContain('1 Open'); |  | ||||||
| 
 | 
 | ||||||
|     await page.getByTestId('schema').click(); |     await page.getByTestId('schema').click(); | ||||||
| 
 | 
 | ||||||
| @ -472,8 +462,6 @@ test.describe('Activity feed', () => { | |||||||
|     await createTagTask(page, { ...value, tag: 'PII.None' }); |     await createTagTask(page, { ...value, tag: 'PII.None' }); | ||||||
|     await openTaskAfterTagResponse; |     await openTaskAfterTagResponse; | ||||||
| 
 | 
 | ||||||
|     await page.waitForLoadState('networkidle'); |  | ||||||
| 
 |  | ||||||
|     // open task count after description
 |     // open task count after description
 | ||||||
|     await checkTaskCount(page, 2, 0); |     await checkTaskCount(page, 2, 0); | ||||||
| 
 | 
 | ||||||
| @ -493,7 +481,6 @@ test.describe('Activity feed', () => { | |||||||
|     await commentWithCloseTask; |     await commentWithCloseTask; | ||||||
| 
 | 
 | ||||||
|     await toastNotification(page, 'Task closed successfully.'); |     await toastNotification(page, 'Task closed successfully.'); | ||||||
|     await page.waitForLoadState('networkidle'); |  | ||||||
|     // open task count after closing one task
 |     // open task count after closing one task
 | ||||||
|     await checkTaskCount(page, 1, 1); |     await checkTaskCount(page, 1, 1); | ||||||
| 
 | 
 | ||||||
| @ -857,7 +844,11 @@ base.describe('Activity feed with Data Consumer User', () => { | |||||||
|           page2.locator('[data-testid="edit-accept-task-dropdown"]') |           page2.locator('[data-testid="edit-accept-task-dropdown"]') | ||||||
|         ).not.toBeVisible(); |         ).not.toBeVisible(); | ||||||
| 
 | 
 | ||||||
|  |         const tagsSuggestionResponse = page2.waitForResponse( | ||||||
|  |           '/api/v1/search/query?q=***' | ||||||
|  |         ); | ||||||
|         await page2.getByRole('button', { name: 'Add Tags' }).click(); |         await page2.getByRole('button', { name: 'Add Tags' }).click(); | ||||||
|  |         await tagsSuggestionResponse; | ||||||
| 
 | 
 | ||||||
|         await page2.waitForSelector('[role="dialog"].ant-modal'); |         await page2.waitForSelector('[role="dialog"].ant-modal'); | ||||||
| 
 | 
 | ||||||
|  | |||||||
| @ -154,6 +154,8 @@ export const checkTaskCount = async ( | |||||||
|   openTask = 0, |   openTask = 0, | ||||||
|   closedTask = 0 |   closedTask = 0 | ||||||
| ) => { | ) => { | ||||||
|  |   await page.waitForLoadState('networkidle'); | ||||||
|  | 
 | ||||||
|   const openTaskElement = await page.getByTestId('open-task').textContent(); |   const openTaskElement = await page.getByTestId('open-task').textContent(); | ||||||
| 
 | 
 | ||||||
|   expect(openTaskElement).toContain(`${openTask} Open`); |   expect(openTaskElement).toContain(`${openTask} Open`); | ||||||
|  | |||||||
| @ -16,6 +16,7 @@ import classNames from 'classnames'; | |||||||
| import React, { FC } from 'react'; | import React, { FC } from 'react'; | ||||||
| import { useTranslation } from 'react-i18next'; | import { useTranslation } from 'react-i18next'; | ||||||
| import { Thread, ThreadType } from '../../../generated/entity/feed/thread'; | import { Thread, ThreadType } from '../../../generated/entity/feed/thread'; | ||||||
|  | import { useReserveSidebar } from '../../../hooks/useReserveSidebar'; | ||||||
| import Loader from '../../common/Loader/Loader'; | import Loader from '../../common/Loader/Loader'; | ||||||
| import ActivityFeedEditor from '../ActivityFeedEditor/ActivityFeedEditor'; | import ActivityFeedEditor from '../ActivityFeedEditor/ActivityFeedEditor'; | ||||||
| import FeedPanelBodyV1 from '../ActivityFeedPanel/FeedPanelBodyV1'; | import FeedPanelBodyV1 from '../ActivityFeedPanel/FeedPanelBodyV1'; | ||||||
| @ -33,6 +34,7 @@ const ActivityFeedDrawer: FC<ActivityFeedDrawerProps> = ({ | |||||||
|   className, |   className, | ||||||
| }) => { | }) => { | ||||||
|   const { t } = useTranslation(); |   const { t } = useTranslation(); | ||||||
|  |   const { isSidebarReserve } = useReserveSidebar(); | ||||||
|   const { |   const { | ||||||
|     focusReplyEditor, |     focusReplyEditor, | ||||||
|     isDrawerLoading, |     isDrawerLoading, | ||||||
| @ -71,7 +73,12 @@ const ActivityFeedDrawer: FC<ActivityFeedDrawerProps> = ({ | |||||||
|       {isDrawerLoading ? ( |       {isDrawerLoading ? ( | ||||||
|         <Loader /> |         <Loader /> | ||||||
|       ) : ( |       ) : ( | ||||||
|         <Row gutter={[0, 16]} id="feed-panel"> |         <Row | ||||||
|  |           className={classNames({ | ||||||
|  |             ['reserve-right-sidebar']: isSidebarReserve, | ||||||
|  |           })} | ||||||
|  |           gutter={[0, 16]} | ||||||
|  |           id="feed-panel"> | ||||||
|           <Col span={24}> |           <Col span={24}> | ||||||
|             <FeedPanelBodyV1 |             <FeedPanelBodyV1 | ||||||
|               isOpenInDrawer |               isOpenInDrawer | ||||||
| @ -85,7 +92,11 @@ const ActivityFeedDrawer: FC<ActivityFeedDrawerProps> = ({ | |||||||
|             /> |             /> | ||||||
|           </Col> |           </Col> | ||||||
|           <Col span={24}> |           <Col span={24}> | ||||||
|             <ActivityFeedEditor focused={focusReplyEditor} onSave={onSave} /> |             <ActivityFeedEditor | ||||||
|  |               className="activity-feed-editor-drawer" | ||||||
|  |               focused={focusReplyEditor} | ||||||
|  |               onSave={onSave} | ||||||
|  |             /> | ||||||
|           </Col> |           </Col> | ||||||
|         </Row> |         </Row> | ||||||
|       )} |       )} | ||||||
|  | |||||||
| @ -17,6 +17,7 @@ import React, { useCallback, useEffect, useMemo } from 'react'; | |||||||
| import { useTranslation } from 'react-i18next'; | import { useTranslation } from 'react-i18next'; | ||||||
| import { useLimitStore } from '../../context/LimitsProvider/useLimitsStore'; | import { useLimitStore } from '../../context/LimitsProvider/useLimitsStore'; | ||||||
| import { useApplicationStore } from '../../hooks/useApplicationStore'; | import { useApplicationStore } from '../../hooks/useApplicationStore'; | ||||||
|  | import { useReserveSidebar } from '../../hooks/useReserveSidebar'; | ||||||
| import { getLimitConfig } from '../../rest/limitsAPI'; | import { getLimitConfig } from '../../rest/limitsAPI'; | ||||||
| import applicationRoutesClass from '../../utils/ApplicationRoutesClassBase'; | import applicationRoutesClass from '../../utils/ApplicationRoutesClassBase'; | ||||||
| import Appbar from '../AppBar/Appbar'; | import Appbar from '../AppBar/Appbar'; | ||||||
| @ -29,6 +30,7 @@ const AppContainer = () => { | |||||||
|   const { i18n } = useTranslation(); |   const { i18n } = useTranslation(); | ||||||
|   const { Header, Sider, Content } = Layout; |   const { Header, Sider, Content } = Layout; | ||||||
|   const { currentUser } = useApplicationStore(); |   const { currentUser } = useApplicationStore(); | ||||||
|  |   const { isSidebarReserve } = useReserveSidebar(); | ||||||
|   const AuthenticatedRouter = applicationRoutesClass.getRouteElements(); |   const AuthenticatedRouter = applicationRoutesClass.getRouteElements(); | ||||||
|   const ApplicationExtras = applicationsClassBase.getApplicationExtension(); |   const ApplicationExtras = applicationsClassBase.getApplicationExtension(); | ||||||
|   const isDirectionRTL = useMemo(() => i18n.dir() === 'rtl', [i18n]); |   const isDirectionRTL = useMemo(() => i18n.dir() === 'rtl', [i18n]); | ||||||
| @ -56,7 +58,7 @@ const AppContainer = () => { | |||||||
|       <Layout |       <Layout | ||||||
|         className={classNames('app-container', { |         className={classNames('app-container', { | ||||||
|           ['extra-banner']: Boolean(bannerDetails), |           ['extra-banner']: Boolean(bannerDetails), | ||||||
|           ['reserve-right-sidebar']: Boolean(ApplicationExtras), |           ['reserve-right-sidebar']: isSidebarReserve, | ||||||
|         })}> |         })}> | ||||||
|         <Sider |         <Sider | ||||||
|           className={classNames('left-sidebar-col', { |           className={classNames('left-sidebar-col', { | ||||||
|  | |||||||
| @ -0,0 +1,36 @@ | |||||||
|  | /* | ||||||
|  |  *  Copyright 2024 Collate. | ||||||
|  |  *  Licensed under the Apache License, Version 2.0 (the "License"); | ||||||
|  |  *  you may not use this file except in compliance with the License. | ||||||
|  |  *  You may obtain a copy of the License at | ||||||
|  |  *  http://www.apache.org/licenses/LICENSE-2.0
 | ||||||
|  |  *  Unless required by applicable law or agreed to in writing, software | ||||||
|  |  *  distributed under the License is distributed on an "AS IS" BASIS, | ||||||
|  |  *  WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. | ||||||
|  |  *  See the License for the specific language governing permissions and | ||||||
|  |  *  limitations under the License. | ||||||
|  |  */ | ||||||
|  | import { renderHook } from '@testing-library/react-hooks'; | ||||||
|  | import { useReserveSidebar } from './useReserveSidebar'; | ||||||
|  | 
 | ||||||
|  | describe('useReserveSidebar', () => { | ||||||
|  |   it('should return false when .floating-button-container is not present', () => { | ||||||
|  |     const { result } = renderHook(() => useReserveSidebar()); | ||||||
|  | 
 | ||||||
|  |     expect(result.current.isSidebarReserve).toBe(false); | ||||||
|  |   }); | ||||||
|  | 
 | ||||||
|  |   it('should return true when .floating-button-container is present', () => { | ||||||
|  |     // Create a mock element and append it to the document body
 | ||||||
|  |     const floatingButtonContainer = document.createElement('div'); | ||||||
|  |     floatingButtonContainer.className = 'floating-button-container'; | ||||||
|  |     document.body.appendChild(floatingButtonContainer); | ||||||
|  | 
 | ||||||
|  |     const { result } = renderHook(() => useReserveSidebar()); | ||||||
|  | 
 | ||||||
|  |     expect(result.current.isSidebarReserve).toBe(true); | ||||||
|  | 
 | ||||||
|  |     // Clean up the mock element
 | ||||||
|  |     document.body.removeChild(floatingButtonContainer); | ||||||
|  |   }); | ||||||
|  | }); | ||||||
| @ -0,0 +1,32 @@ | |||||||
|  | /* | ||||||
|  |  *  Copyright 2024 Collate. | ||||||
|  |  *  Licensed under the Apache License, Version 2.0 (the "License"); | ||||||
|  |  *  you may not use this file except in compliance with the License. | ||||||
|  |  *  You may obtain a copy of the License at | ||||||
|  |  *  http://www.apache.org/licenses/LICENSE-2.0
 | ||||||
|  |  *  Unless required by applicable law or agreed to in writing, software | ||||||
|  |  *  distributed under the License is distributed on an "AS IS" BASIS, | ||||||
|  |  *  WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. | ||||||
|  |  *  See the License for the specific language governing permissions and | ||||||
|  |  *  limitations under the License. | ||||||
|  |  */ | ||||||
|  | import { useEffect, useState } from 'react'; | ||||||
|  | 
 | ||||||
|  | type ReserverSidebar = { isSidebarReserve: boolean }; | ||||||
|  | 
 | ||||||
|  | /** | ||||||
|  |  * @description Hook to get the if the sidebar should have some reserved space in case of floating button | ||||||
|  |  * @returns {isSidebarReserve: boolean} - boolean value to check if the sidebar should have some reserved space | ||||||
|  |  */ | ||||||
|  | export const useReserveSidebar = (): ReserverSidebar => { | ||||||
|  |   const [isSidebarReserve, setIsSidebarReserve] = useState<boolean>(false); | ||||||
|  | 
 | ||||||
|  |   useEffect(() => { | ||||||
|  |     const element = document.querySelector('.floating-button-container'); | ||||||
|  |     setIsSidebarReserve(Boolean(element)); | ||||||
|  |   }, []); | ||||||
|  | 
 | ||||||
|  |   return { | ||||||
|  |     isSidebarReserve, | ||||||
|  |   }; | ||||||
|  | }; | ||||||
| @ -824,6 +824,7 @@ a[href].link-text-grey, | |||||||
|   .appearance-cta-buttons { |   .appearance-cta-buttons { | ||||||
|     padding-right: 64px; |     padding-right: 64px; | ||||||
|   } |   } | ||||||
|  |   .activity-feed-editor-drawer, | ||||||
|   .policies-list-table, |   .policies-list-table, | ||||||
|   .roles-list-table, |   .roles-list-table, | ||||||
|   .list-table { |   .list-table { | ||||||
|  | |||||||
		Loading…
	
	
			
			x
			
			
		
	
		Reference in New Issue
	
	Block a user
	 Ashish Gupta
						Ashish Gupta