| 
									
										
										
										
											2024-01-12 19:22:03 +08:00
										 |  |  | import { act, render, screen } from '@testing-library/react'; | 
					
						
							| 
									
										
										
										
											2024-08-15 23:17:47 +08:00
										 |  |  | import userEvent from '@testing-library/user-event'; | 
					
						
							| 
									
										
										
										
											2024-06-25 19:43:47 +08:00
										 |  |  | import { useEffect, useRef, useState } from 'react'; | 
					
						
							| 
									
										
										
										
											2024-01-12 19:22:03 +08:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2025-03-25 17:48:36 +08:00
										 |  |  | import { CoreApp, LogRowModel, dateTimeForTimeZone, rangeUtil } from '@grafana/data'; | 
					
						
							| 
									
										
										
										
											2024-02-02 20:45:20 +08:00
										 |  |  | import { config } from '@grafana/runtime'; | 
					
						
							| 
									
										
										
										
											2024-01-12 19:22:03 +08:00
										 |  |  | import { LogsSortOrder } from '@grafana/schema'; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | import { InfiniteScroll, Props, SCROLLING_THRESHOLD } from './InfiniteScroll'; | 
					
						
							|  |  |  | import { createLogRow } from './__mocks__/logRow'; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | const defaultTz = 'browser'; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | const absoluteRange = { | 
					
						
							|  |  |  |   from: 1702578600000, | 
					
						
							|  |  |  |   to: 1702578900000, | 
					
						
							|  |  |  | }; | 
					
						
							| 
									
										
										
										
											2025-03-25 17:48:36 +08:00
										 |  |  | const defaultRange = rangeUtil.convertRawToRange({ | 
					
						
							| 
									
										
										
										
											2024-01-12 19:22:03 +08:00
										 |  |  |   from: dateTimeForTimeZone(defaultTz, absoluteRange.from), | 
					
						
							|  |  |  |   to: dateTimeForTimeZone(defaultTz, absoluteRange.to), | 
					
						
							|  |  |  | }); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | const defaultProps: Omit<Props, 'children'> = { | 
					
						
							|  |  |  |   loading: false, | 
					
						
							|  |  |  |   loadMoreLogs: jest.fn(), | 
					
						
							|  |  |  |   range: defaultRange, | 
					
						
							|  |  |  |   rows: [], | 
					
						
							|  |  |  |   sortOrder: LogsSortOrder.Descending, | 
					
						
							|  |  |  |   timeZone: 'browser', | 
					
						
							| 
									
										
										
										
											2024-12-19 02:03:47 +08:00
										 |  |  |   scrollElement: null, | 
					
						
							| 
									
										
										
										
											2024-01-12 19:22:03 +08:00
										 |  |  | }; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | function ScrollWithWrapper({ children, ...props }: Props) { | 
					
						
							|  |  |  |   const [initialized, setInitialized] = useState(false); | 
					
						
							|  |  |  |   const scrollRef = useRef<HTMLDivElement | null>(null); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |   useEffect(() => { | 
					
						
							|  |  |  |     // Required to get the ref
 | 
					
						
							|  |  |  |     if (scrollRef.current && !initialized) { | 
					
						
							|  |  |  |       setInitialized(true); | 
					
						
							|  |  |  |     } | 
					
						
							|  |  |  |   }, [initialized]); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |   return ( | 
					
						
							|  |  |  |     <div style={{ height: 40, overflowY: 'scroll' }} ref={scrollRef} data-testid="scroll-element"> | 
					
						
							|  |  |  |       {initialized && ( | 
					
						
							| 
									
										
										
										
											2024-03-15 20:52:55 +08:00
										 |  |  |         <InfiniteScroll {...props} scrollElement={scrollRef.current!} topScrollEnabled> | 
					
						
							| 
									
										
										
										
											2024-01-12 19:22:03 +08:00
										 |  |  |           {children} | 
					
						
							|  |  |  |         </InfiniteScroll> | 
					
						
							|  |  |  |       )} | 
					
						
							|  |  |  |     </div> | 
					
						
							|  |  |  |   ); | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2024-08-15 23:17:47 +08:00
										 |  |  | function setup( | 
					
						
							|  |  |  |   loadMoreMock: () => void, | 
					
						
							|  |  |  |   startPosition: number, | 
					
						
							|  |  |  |   rows: LogRowModel[], | 
					
						
							|  |  |  |   order: LogsSortOrder, | 
					
						
							|  |  |  |   app?: CoreApp | 
					
						
							|  |  |  | ) { | 
					
						
							| 
									
										
										
										
											2024-02-02 20:45:20 +08:00
										 |  |  |   const { element, events } = getMockElement(startPosition); | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2025-03-21 05:14:02 +08:00
										 |  |  |   function scrollTo(position: number, timeStamp?: number) { | 
					
						
							| 
									
										
										
										
											2024-02-02 20:45:20 +08:00
										 |  |  |     element.scrollTop = position; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     act(() => { | 
					
						
							| 
									
										
										
										
											2025-03-21 05:14:02 +08:00
										 |  |  |       const event = new Event('scroll'); | 
					
						
							|  |  |  |       if (timeStamp) { | 
					
						
							|  |  |  |         jest.spyOn(event, 'timeStamp', 'get').mockReturnValue(timeStamp); | 
					
						
							|  |  |  |       } | 
					
						
							|  |  |  |       events['scroll'](event); | 
					
						
							| 
									
										
										
										
											2024-02-02 20:45:20 +08:00
										 |  |  |     }); | 
					
						
							| 
									
										
										
										
											2024-03-15 20:52:55 +08:00
										 |  |  | 
 | 
					
						
							|  |  |  |     // When scrolling top, we wait for the user to reach the top, and then for a new scrolling event
 | 
					
						
							|  |  |  |     // in the same direction before triggering a new query.
 | 
					
						
							|  |  |  |     if (position === 0) { | 
					
						
							|  |  |  |       wheel(-1); | 
					
						
							|  |  |  |     } | 
					
						
							| 
									
										
										
										
											2024-02-02 20:45:20 +08:00
										 |  |  |   } | 
					
						
							| 
									
										
										
										
											2024-11-20 01:12:41 +08:00
										 |  |  |   function wheel(deltaY: number, timeStamp?: number) { | 
					
						
							| 
									
										
										
										
											2024-03-15 20:52:55 +08:00
										 |  |  |     element.scrollTop += deltaY; | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2024-02-02 20:45:20 +08:00
										 |  |  |     act(() => { | 
					
						
							|  |  |  |       const event = new WheelEvent('wheel', { deltaY }); | 
					
						
							| 
									
										
										
										
											2024-11-20 01:12:41 +08:00
										 |  |  |       if (timeStamp) { | 
					
						
							|  |  |  |         jest.spyOn(event, 'timeStamp', 'get').mockReturnValue(timeStamp); | 
					
						
							|  |  |  |       } | 
					
						
							| 
									
										
										
										
											2024-02-02 20:45:20 +08:00
										 |  |  |       events['wheel'](event); | 
					
						
							|  |  |  |     }); | 
					
						
							|  |  |  |   } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |   render( | 
					
						
							|  |  |  |     <InfiniteScroll | 
					
						
							|  |  |  |       {...defaultProps} | 
					
						
							|  |  |  |       sortOrder={order} | 
					
						
							|  |  |  |       rows={rows} | 
					
						
							|  |  |  |       scrollElement={element as unknown as HTMLDivElement} | 
					
						
							|  |  |  |       loadMoreLogs={loadMoreMock} | 
					
						
							| 
									
										
										
										
											2024-03-15 20:52:55 +08:00
										 |  |  |       topScrollEnabled | 
					
						
							| 
									
										
										
										
											2024-08-15 23:17:47 +08:00
										 |  |  |       app={app} | 
					
						
							| 
									
										
										
										
											2024-02-02 20:45:20 +08:00
										 |  |  |     > | 
					
						
							|  |  |  |       <div data-testid="contents" style={{ height: 100 }} /> | 
					
						
							|  |  |  |     </InfiniteScroll> | 
					
						
							|  |  |  |   ); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |   return { element, events, scrollTo, wheel }; | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | beforeAll(() => { | 
					
						
							|  |  |  |   config.featureToggles.logsInfiniteScrolling = true; | 
					
						
							|  |  |  | }); | 
					
						
							|  |  |  | afterAll(() => { | 
					
						
							|  |  |  |   config.featureToggles.logsInfiniteScrolling = false; | 
					
						
							|  |  |  | }); | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2024-01-12 19:22:03 +08:00
										 |  |  | describe('InfiniteScroll', () => { | 
					
						
							|  |  |  |   test('Wraps components without adding DOM elements', async () => { | 
					
						
							|  |  |  |     const { container } = render( | 
					
						
							|  |  |  |       <ScrollWithWrapper {...defaultProps}> | 
					
						
							|  |  |  |         <div data-testid="contents" /> | 
					
						
							|  |  |  |       </ScrollWithWrapper> | 
					
						
							|  |  |  |     ); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     expect(await screen.findByTestId('contents')).toBeInTheDocument(); | 
					
						
							|  |  |  |     expect(container).toMatchInlineSnapshot(`
 | 
					
						
							|  |  |  |       <div> | 
					
						
							|  |  |  |         <div | 
					
						
							|  |  |  |           data-testid="scroll-element" | 
					
						
							|  |  |  |           style="height: 40px; overflow-y: scroll;" | 
					
						
							|  |  |  |         > | 
					
						
							|  |  |  |           <div | 
					
						
							|  |  |  |             data-testid="contents" | 
					
						
							|  |  |  |           /> | 
					
						
							|  |  |  |         </div> | 
					
						
							|  |  |  |       </div> | 
					
						
							|  |  |  | `);
 | 
					
						
							|  |  |  |   }); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |   describe.each([LogsSortOrder.Descending, LogsSortOrder.Ascending])( | 
					
						
							|  |  |  |     'When the sort order is %s', | 
					
						
							|  |  |  |     (order: LogsSortOrder) => { | 
					
						
							|  |  |  |       let rows: LogRowModel[]; | 
					
						
							|  |  |  |       beforeEach(() => { | 
					
						
							|  |  |  |         rows = createLogRows(absoluteRange.from + 2 * SCROLLING_THRESHOLD, absoluteRange.to - 2 * SCROLLING_THRESHOLD); | 
					
						
							|  |  |  |       }); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |       test.each([ | 
					
						
							|  |  |  |         ['top', 10, 0], | 
					
						
							| 
									
										
										
										
											2024-02-02 20:45:20 +08:00
										 |  |  |         ['bottom', 50, 60], | 
					
						
							|  |  |  |       ])( | 
					
						
							|  |  |  |         'Requests more logs when scrolling %s', | 
					
						
							|  |  |  |         async (direction: string, startPosition: number, endPosition: number) => { | 
					
						
							|  |  |  |           const loadMoreMock = jest.fn(); | 
					
						
							|  |  |  |           const { scrollTo, element } = setup(loadMoreMock, startPosition, rows, order); | 
					
						
							| 
									
										
										
										
											2024-01-12 19:22:03 +08:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2024-02-02 20:45:20 +08:00
										 |  |  |           expect(await screen.findByTestId('contents')).toBeInTheDocument(); | 
					
						
							| 
									
										
										
										
											2024-01-12 19:22:03 +08:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2025-03-21 05:14:02 +08:00
										 |  |  |           scrollTo(endPosition - 1, 1); | 
					
						
							|  |  |  |           scrollTo(endPosition, 600); | 
					
						
							| 
									
										
										
										
											2024-01-12 19:22:03 +08:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2024-02-02 20:45:20 +08:00
										 |  |  |           expect(loadMoreMock).toHaveBeenCalled(); | 
					
						
							|  |  |  |           expect(await screen.findByTestId('Spinner')).toBeInTheDocument(); | 
					
						
							|  |  |  |           if (direction === 'bottom') { | 
					
						
							|  |  |  |             // Bottom loader visibility trick
 | 
					
						
							|  |  |  |             expect(element.scrollTo).toHaveBeenCalled(); | 
					
						
							|  |  |  |           } else { | 
					
						
							|  |  |  |             expect(element.scrollTo).not.toHaveBeenCalled(); | 
					
						
							|  |  |  |           } | 
					
						
							|  |  |  |         } | 
					
						
							|  |  |  |       ); | 
					
						
							| 
									
										
										
										
											2024-01-12 19:22:03 +08:00
										 |  |  | 
 | 
					
						
							|  |  |  |       test.each([ | 
					
						
							|  |  |  |         ['up', -5, 0], | 
					
						
							| 
									
										
										
										
											2024-11-20 01:12:41 +08:00
										 |  |  |         ['down', 5, 60], | 
					
						
							| 
									
										
										
										
											2024-01-12 19:22:03 +08:00
										 |  |  |       ])( | 
					
						
							|  |  |  |         'Requests more logs when moving the mousewheel %s', | 
					
						
							|  |  |  |         async (_: string, deltaY: number, startPosition: number) => { | 
					
						
							|  |  |  |           const loadMoreMock = jest.fn(); | 
					
						
							| 
									
										
										
										
											2024-02-02 20:45:20 +08:00
										 |  |  |           const { wheel } = setup(loadMoreMock, startPosition, rows, order); | 
					
						
							| 
									
										
										
										
											2024-01-12 19:22:03 +08:00
										 |  |  | 
 | 
					
						
							|  |  |  |           expect(await screen.findByTestId('contents')).toBeInTheDocument(); | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2025-03-21 05:14:02 +08:00
										 |  |  |           wheel(deltaY, 1); | 
					
						
							|  |  |  |           wheel(deltaY, 600); | 
					
						
							| 
									
										
										
										
											2024-01-12 19:22:03 +08:00
										 |  |  | 
 | 
					
						
							|  |  |  |           expect(loadMoreMock).toHaveBeenCalled(); | 
					
						
							|  |  |  |           expect(await screen.findByTestId('Spinner')).toBeInTheDocument(); | 
					
						
							|  |  |  |         } | 
					
						
							|  |  |  |       ); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |       test('Does not request more logs when there is no scroll', async () => { | 
					
						
							|  |  |  |         const loadMoreMock = jest.fn(); | 
					
						
							| 
									
										
										
										
											2024-02-02 20:45:20 +08:00
										 |  |  |         const { scrollTo, element } = setup(loadMoreMock, 0, rows, order); | 
					
						
							| 
									
										
										
										
											2024-01-12 19:22:03 +08:00
										 |  |  | 
 | 
					
						
							|  |  |  |         expect(await screen.findByTestId('contents')).toBeInTheDocument(); | 
					
						
							|  |  |  |         element.clientHeight = 40; | 
					
						
							|  |  |  |         element.scrollHeight = element.clientHeight; | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2025-03-21 05:14:02 +08:00
										 |  |  |         scrollTo(39, 1); | 
					
						
							|  |  |  |         scrollTo(40, 600); | 
					
						
							| 
									
										
										
										
											2024-01-12 19:22:03 +08:00
										 |  |  | 
 | 
					
						
							|  |  |  |         expect(loadMoreMock).not.toHaveBeenCalled(); | 
					
						
							|  |  |  |         expect(screen.queryByTestId('Spinner')).not.toBeInTheDocument(); | 
					
						
							|  |  |  |       }); | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2024-01-18 04:12:09 +08:00
										 |  |  |       test('Requests newer logs from the most recent timestamp', async () => { | 
					
						
							| 
									
										
										
										
											2024-02-02 20:45:20 +08:00
										 |  |  |         const startPosition = order === LogsSortOrder.Descending ? 10 : 50; // Scroll top
 | 
					
						
							|  |  |  |         const endPosition = order === LogsSortOrder.Descending ? 0 : 60; // Scroll bottom
 | 
					
						
							| 
									
										
										
										
											2024-01-18 04:12:09 +08:00
										 |  |  | 
 | 
					
						
							|  |  |  |         const loadMoreMock = jest.fn(); | 
					
						
							| 
									
										
										
										
											2024-02-02 20:45:20 +08:00
										 |  |  |         const { scrollTo } = setup(loadMoreMock, startPosition, rows, order); | 
					
						
							| 
									
										
										
										
											2024-01-18 04:12:09 +08:00
										 |  |  | 
 | 
					
						
							|  |  |  |         expect(await screen.findByTestId('contents')).toBeInTheDocument(); | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2025-03-21 05:14:02 +08:00
										 |  |  |         scrollTo(endPosition - 1, 1); | 
					
						
							|  |  |  |         scrollTo(endPosition, 600); | 
					
						
							| 
									
										
										
										
											2024-01-18 04:12:09 +08:00
										 |  |  | 
 | 
					
						
							|  |  |  |         expect(loadMoreMock).toHaveBeenCalledWith({ | 
					
						
							|  |  |  |           from: rows[rows.length - 1].timeEpochMs, | 
					
						
							|  |  |  |           to: absoluteRange.to, | 
					
						
							|  |  |  |         }); | 
					
						
							|  |  |  |       }); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |       test('Requests older logs from the oldest timestamp', async () => { | 
					
						
							| 
									
										
										
										
											2024-02-02 20:45:20 +08:00
										 |  |  |         const startPosition = order === LogsSortOrder.Ascending ? 10 : 50; // Scroll top
 | 
					
						
							|  |  |  |         const endPosition = order === LogsSortOrder.Ascending ? 0 : 60; // Scroll bottom
 | 
					
						
							| 
									
										
										
										
											2024-01-18 04:12:09 +08:00
										 |  |  | 
 | 
					
						
							|  |  |  |         const loadMoreMock = jest.fn(); | 
					
						
							| 
									
										
										
										
											2024-02-02 20:45:20 +08:00
										 |  |  |         const { scrollTo } = setup(loadMoreMock, startPosition, rows, order); | 
					
						
							| 
									
										
										
										
											2024-01-18 04:12:09 +08:00
										 |  |  | 
 | 
					
						
							|  |  |  |         expect(await screen.findByTestId('contents')).toBeInTheDocument(); | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2025-03-21 05:14:02 +08:00
										 |  |  |         scrollTo(endPosition - 1, 1); | 
					
						
							|  |  |  |         scrollTo(endPosition, 600); | 
					
						
							| 
									
										
										
										
											2024-01-18 04:12:09 +08:00
										 |  |  | 
 | 
					
						
							|  |  |  |         expect(loadMoreMock).toHaveBeenCalledWith({ | 
					
						
							|  |  |  |           from: absoluteRange.from, | 
					
						
							|  |  |  |           to: rows[0].timeEpochMs, | 
					
						
							|  |  |  |         }); | 
					
						
							|  |  |  |       }); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |       describe('With absolute range matching visible range', () => { | 
					
						
							| 
									
										
										
										
											2024-01-12 19:22:03 +08:00
										 |  |  |         test.each([ | 
					
						
							|  |  |  |           ['top', 10, 0], | 
					
						
							| 
									
										
										
										
											2024-02-02 20:45:20 +08:00
										 |  |  |           ['bottom', 50, 60], | 
					
						
							| 
									
										
										
										
											2024-01-12 19:22:03 +08:00
										 |  |  |         ])( | 
					
						
							|  |  |  |           'It does not request more when scrolling %s', | 
					
						
							|  |  |  |           async (_: string, startPosition: number, endPosition: number) => { | 
					
						
							| 
									
										
										
										
											2024-01-18 04:12:09 +08:00
										 |  |  |             // Visible range matches the current range
 | 
					
						
							| 
									
										
										
										
											2024-01-12 19:22:03 +08:00
										 |  |  |             const rows = createLogRows(absoluteRange.from, absoluteRange.to); | 
					
						
							|  |  |  |             const loadMoreMock = jest.fn(); | 
					
						
							| 
									
										
										
										
											2024-02-02 20:45:20 +08:00
										 |  |  |             const { scrollTo } = setup(loadMoreMock, startPosition, rows, order); | 
					
						
							| 
									
										
										
										
											2024-01-12 19:22:03 +08:00
										 |  |  | 
 | 
					
						
							|  |  |  |             expect(await screen.findByTestId('contents')).toBeInTheDocument(); | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2025-03-21 05:14:02 +08:00
										 |  |  |             scrollTo(endPosition - 1, 1); | 
					
						
							|  |  |  |             scrollTo(endPosition, 600); | 
					
						
							| 
									
										
										
										
											2024-01-12 19:22:03 +08:00
										 |  |  | 
 | 
					
						
							|  |  |  |             expect(loadMoreMock).not.toHaveBeenCalled(); | 
					
						
							|  |  |  |             expect(screen.queryByTestId('Spinner')).not.toBeInTheDocument(); | 
					
						
							| 
									
										
										
										
											2024-01-18 04:12:09 +08:00
										 |  |  |             expect(await screen.findByTestId('end-of-range')).toBeInTheDocument(); | 
					
						
							| 
									
										
										
										
											2024-01-12 19:22:03 +08:00
										 |  |  |           } | 
					
						
							|  |  |  |         ); | 
					
						
							|  |  |  |       }); | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2024-01-18 04:12:09 +08:00
										 |  |  |       describe('With relative range matching visible range', () => { | 
					
						
							| 
									
										
										
										
											2024-01-12 19:22:03 +08:00
										 |  |  |         test.each([ | 
					
						
							|  |  |  |           ['top', 10, 0], | 
					
						
							| 
									
										
										
										
											2024-02-02 20:45:20 +08:00
										 |  |  |           ['bottom', 50, 60], | 
					
						
							| 
									
										
										
										
											2024-01-12 19:22:03 +08:00
										 |  |  |         ])( | 
					
						
							|  |  |  |           'It does not request more when scrolling %s', | 
					
						
							|  |  |  |           async (_: string, startPosition: number, endPosition: number) => { | 
					
						
							| 
									
										
										
										
											2024-01-18 04:12:09 +08:00
										 |  |  |             // Visible range matches the current range
 | 
					
						
							| 
									
										
										
										
											2024-01-12 19:22:03 +08:00
										 |  |  |             const rows = createLogRows(absoluteRange.from, absoluteRange.to); | 
					
						
							|  |  |  |             const loadMoreMock = jest.fn(); | 
					
						
							| 
									
										
										
										
											2024-02-02 20:45:20 +08:00
										 |  |  |             const { scrollTo } = setup(loadMoreMock, startPosition, rows, order); | 
					
						
							| 
									
										
										
										
											2024-01-12 19:22:03 +08:00
										 |  |  | 
 | 
					
						
							|  |  |  |             expect(await screen.findByTestId('contents')).toBeInTheDocument(); | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2025-03-21 05:14:02 +08:00
										 |  |  |             scrollTo(endPosition - 1, 1); | 
					
						
							|  |  |  |             scrollTo(endPosition, 600); | 
					
						
							| 
									
										
										
										
											2024-01-12 19:22:03 +08:00
										 |  |  | 
 | 
					
						
							|  |  |  |             expect(loadMoreMock).not.toHaveBeenCalled(); | 
					
						
							|  |  |  |             expect(screen.queryByTestId('Spinner')).not.toBeInTheDocument(); | 
					
						
							| 
									
										
										
										
											2024-01-18 04:12:09 +08:00
										 |  |  |             expect(await screen.findByTestId('end-of-range')).toBeInTheDocument(); | 
					
						
							| 
									
										
										
										
											2024-01-12 19:22:03 +08:00
										 |  |  |           } | 
					
						
							|  |  |  |         ); | 
					
						
							|  |  |  |       }); | 
					
						
							| 
									
										
										
										
											2024-11-20 01:12:41 +08:00
										 |  |  | 
 | 
					
						
							|  |  |  |       describe('Chain of events', () => { | 
					
						
							|  |  |  |         test('Ingnores chains of events', async () => { | 
					
						
							|  |  |  |           const loadMoreMock = jest.fn(); | 
					
						
							|  |  |  |           const { wheel } = setup(loadMoreMock, 57, rows, order); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |           expect(await screen.findByTestId('contents')).toBeInTheDocument(); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |           const timeStamps = [1, 2, 3, 4]; | 
					
						
							|  |  |  |           timeStamps.forEach((timeStamp) => { | 
					
						
							|  |  |  |             wheel(1, timeStamp); | 
					
						
							|  |  |  |           }); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |           expect(loadMoreMock).not.toHaveBeenCalled(); | 
					
						
							|  |  |  |         }); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |         test('Detects when chain of events ends', async () => { | 
					
						
							|  |  |  |           const loadMoreMock = jest.fn(); | 
					
						
							|  |  |  |           const { wheel } = setup(loadMoreMock, 57, rows, order); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |           expect(await screen.findByTestId('contents')).toBeInTheDocument(); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |           const timeStamps = [1, 2, 3, 600, 1]; | 
					
						
							|  |  |  |           timeStamps.forEach((timeStamp) => { | 
					
						
							|  |  |  |             wheel(1, timeStamp); | 
					
						
							|  |  |  |           }); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |           expect(loadMoreMock).toHaveBeenCalledTimes(1); | 
					
						
							|  |  |  |         }); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |         test('Detects when the user wants to scroll', async () => { | 
					
						
							|  |  |  |           const loadMoreMock = jest.fn(); | 
					
						
							|  |  |  |           const { wheel } = setup(loadMoreMock, 57, rows, order); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |           expect(await screen.findByTestId('contents')).toBeInTheDocument(); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |           for (let i = 0; i <= 25; i++) { | 
					
						
							|  |  |  |             wheel(1, 399 * i + 399); | 
					
						
							|  |  |  |           } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |           expect(loadMoreMock).toHaveBeenCalledTimes(1); | 
					
						
							|  |  |  |         }); | 
					
						
							|  |  |  |       }); | 
					
						
							| 
									
										
										
										
											2024-01-12 19:22:03 +08:00
										 |  |  |     } | 
					
						
							|  |  |  |   ); | 
					
						
							| 
									
										
										
										
											2024-08-15 23:17:47 +08:00
										 |  |  | 
 | 
					
						
							|  |  |  |   describe('In Explore', () => { | 
					
						
							|  |  |  |     test('Requests older logs from the oldest timestamp', async () => { | 
					
						
							|  |  |  |       const loadMoreMock = jest.fn(); | 
					
						
							|  |  |  |       const rows = createLogRows( | 
					
						
							|  |  |  |         absoluteRange.from + 2 * SCROLLING_THRESHOLD, | 
					
						
							|  |  |  |         absoluteRange.to - 2 * SCROLLING_THRESHOLD | 
					
						
							|  |  |  |       ); | 
					
						
							|  |  |  |       setup(loadMoreMock, 0, rows, LogsSortOrder.Ascending, CoreApp.Explore); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |       expect(await screen.findByTestId('contents')).toBeInTheDocument(); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |       await screen.findByText('Older logs'); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |       await userEvent.click(screen.getByText('Older logs')); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |       expect(loadMoreMock).toHaveBeenCalledWith({ | 
					
						
							|  |  |  |         from: absoluteRange.from, | 
					
						
							|  |  |  |         to: rows[0].timeEpochMs, | 
					
						
							|  |  |  |       }); | 
					
						
							|  |  |  |     }); | 
					
						
							|  |  |  |   }); | 
					
						
							| 
									
										
										
										
											2024-01-12 19:22:03 +08:00
										 |  |  | }); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | function createLogRows(from: number, to: number) { | 
					
						
							|  |  |  |   const rows = [createLogRow({ entry: 'line1' }), createLogRow({ entry: 'line2' })]; | 
					
						
							|  |  |  |   // Time field
 | 
					
						
							|  |  |  |   rows[0].dataFrame.fields[0].values = [from, to]; | 
					
						
							|  |  |  |   rows[0].timeEpochMs = from; | 
					
						
							|  |  |  |   rows[1].dataFrame.fields[0].values = [from, to]; | 
					
						
							|  |  |  |   rows[1].timeEpochMs = to; | 
					
						
							|  |  |  |   return rows; | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | // JSDOM doesn't support layout, so we will mock the expected attribute values for the test cases.
 | 
					
						
							|  |  |  | function getMockElement(scrollTop: number) { | 
					
						
							|  |  |  |   const events: Record<string, (e: Event | WheelEvent) => void> = {}; | 
					
						
							|  |  |  |   const element = { | 
					
						
							|  |  |  |     addEventListener: (event: string, callback: (e: Event | WheelEvent) => void) => { | 
					
						
							|  |  |  |       events[event] = callback; | 
					
						
							|  |  |  |     }, | 
					
						
							|  |  |  |     removeEventListener: jest.fn(), | 
					
						
							|  |  |  |     stopImmediatePropagation: jest.fn(), | 
					
						
							|  |  |  |     scrollHeight: 100, | 
					
						
							|  |  |  |     clientHeight: 40, | 
					
						
							|  |  |  |     scrollTop, | 
					
						
							| 
									
										
										
										
											2024-02-02 20:45:20 +08:00
										 |  |  |     scrollTo: jest.fn(), | 
					
						
							| 
									
										
										
										
											2024-08-15 23:17:47 +08:00
										 |  |  |     scroll: jest.fn(), | 
					
						
							| 
									
										
										
										
											2024-01-12 19:22:03 +08:00
										 |  |  |   }; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |   return { element, events }; | 
					
						
							|  |  |  | } |