diff --git a/x-pack/solutions/security/plugins/session_view/public/components/tty_player/hooks.test.tsx b/x-pack/solutions/security/plugins/session_view/public/components/tty_player/hooks.test.tsx index 5531210e10a3c..802b833c3e83f 100644 --- a/x-pack/solutions/security/plugins/session_view/public/components/tty_player/hooks.test.tsx +++ b/x-pack/solutions/security/plugins/session_view/public/components/tty_player/hooks.test.tsx @@ -63,38 +63,38 @@ describe('TTYPlayer/hooks', () => { }); it('mounts and renders the first line of output', async () => { - const { result: xTermResult } = renderHook((props) => useXtermPlayer(props), { + const { result: xTermResult } = renderHook(useXtermPlayer, { initialProps, }); const { terminal, currentLine, seekToLine } = xTermResult.current; // there is a minor delay in updates to xtermjs after writeln is called. - jest.advanceTimersByTime(100); + await act(async () => jest.advanceTimersByTime(100)); // check that first line rendered in xtermjs expect(terminal.buffer.active.getLine(0)?.translateToString(true)).toBe('256'); expect(currentLine).toBe(0); - act(() => { + await act(async () => { seekToLine(VIM_LINE_START); // line where vim output starts }); - jest.advanceTimersByTime(100); + await act(async () => jest.advanceTimersByTime(100)); expect(terminal.buffer.active.getLine(0)?.translateToString(true)).toBe('#!/bin/env bash'); }); it('allows the user to seek to any line of output', async () => { - const { result: xTermResult } = renderHook((props) => useXtermPlayer(props), { + const { result: xTermResult } = renderHook(useXtermPlayer, { initialProps, }); - act(() => { + await act(async () => { xTermResult.current.seekToLine(VIM_LINE_START); // line where vim output starts }); - jest.advanceTimersByTime(100); + await act(async () => jest.advanceTimersByTime(100)); const { terminal, currentLine } = xTermResult.current; @@ -103,64 +103,68 @@ describe('TTYPlayer/hooks', () => { }); it('allows the user to play', async () => { - const { result, rerender } = renderHook((props) => useXtermPlayer(props), { + const { result, rerender } = renderHook(useXtermPlayer, { initialProps, }); rerender({ ...initialProps, isPlaying: true }); - act(() => { - jest.advanceTimersByTime(DEFAULT_TTY_PLAYSPEED_MS * 10); - }); + await act(async () => jest.advanceTimersByTime(DEFAULT_TTY_PLAYSPEED_MS * 10)); expect(result.current.currentLine).toBe(10); }); it('allows the user to stop', async () => { - const { result, rerender } = renderHook((props) => useXtermPlayer(props), { + const { result, rerender } = renderHook(useXtermPlayer, { initialProps, }); rerender({ ...initialProps, isPlaying: true }); - act(() => { - jest.advanceTimersByTime(DEFAULT_TTY_PLAYSPEED_MS * 10); - }); + + await act(async () => jest.advanceTimersByTime(DEFAULT_TTY_PLAYSPEED_MS * 10)); + + expect(result.current.currentLine).toBe(10); + rerender({ ...initialProps, isPlaying: false }); - act(() => { - jest.advanceTimersByTime(DEFAULT_TTY_PLAYSPEED_MS * 10); - }); + + await act(async () => jest.advanceTimersByTime(DEFAULT_TTY_PLAYSPEED_MS * 10)); + expect(result.current.currentLine).toBe(10); // should not have advanced }); it('should stop when it reaches the end of the array of lines', async () => { - const { result, rerender } = renderHook((props) => useXtermPlayer(props), { + const { result, rerender } = renderHook(useXtermPlayer, { initialProps, }); rerender({ ...initialProps, isPlaying: true }); - act(() => { - jest.advanceTimersByTime(DEFAULT_TTY_PLAYSPEED_MS * initialProps.lines.length + 100); - }); + + await act(async () => + jest.advanceTimersByTime(DEFAULT_TTY_PLAYSPEED_MS * initialProps.lines.length + 100) + ); + expect(result.current.currentLine).toBe(initialProps.lines.length - 1); }); it('should not print the first line twice after playback starts', async () => { - const { result, rerender } = renderHook((props) => useXtermPlayer(props), { + const { result, rerender } = renderHook(useXtermPlayer, { initialProps, }); rerender({ ...initialProps, isPlaying: true }); - act(() => { + + await act(async () => { // advance render loop jest.advanceTimersByTime(DEFAULT_TTY_PLAYSPEED_MS); }); + rerender({ ...initialProps, isPlaying: false }); expect(result.current.terminal.buffer.active.getLine(0)?.translateToString(true)).toBe('256'); }); it('ensure the first few render loops have printed the right lines', async () => { - const { result, rerender } = renderHook((props) => useXtermPlayer(props), { + const { result, rerender } = renderHook(useXtermPlayer, { initialProps, }); @@ -168,7 +172,7 @@ describe('TTYPlayer/hooks', () => { rerender({ ...initialProps, isPlaying: true }); - act(() => { + await act(async () => { // advance render loop jest.advanceTimersByTime(DEFAULT_TTY_PLAYSPEED_MS * LOOPS); }); @@ -193,7 +197,7 @@ describe('TTYPlayer/hooks', () => { }); it('will allow a plain text search highlight on the last line printed', async () => { - const { result: xTermResult } = renderHook((props) => useXtermPlayer(props), { + const { result: xTermResult } = renderHook(useXtermPlayer, { initialProps, }); diff --git a/x-pack/solutions/security/plugins/session_view/public/components/tty_player/hooks.ts b/x-pack/solutions/security/plugins/session_view/public/components/tty_player/hooks.ts index a1f039f9caad0..7f67a49ab4659 100644 --- a/x-pack/solutions/security/plugins/session_view/public/components/tty_player/hooks.ts +++ b/x-pack/solutions/security/plugins/session_view/public/components/tty_player/hooks.ts @@ -318,21 +318,26 @@ export const useXtermPlayer = ({ useEffect(() => { if (isPlaying) { - const timer = setTimeout(() => { - if (!hasNextPage && currentLine === lines.length - 1) { - setIsPlaying(false); - } else { - const nextLine = Math.min(lines.length - 1, currentLine + 1); - render(nextLine, false); - setCurrentLine(nextLine); - } - }, playSpeed); + const timer = setInterval( + () => + setCurrentLine((_currentLine) => { + if (!hasNextPage && _currentLine === lines.length - 1) { + setIsPlaying(false); + return _currentLine; + } else { + const nextLine = Math.min(lines.length - 1, _currentLine + 1); + render(nextLine, false); + return nextLine; + } + }), + playSpeed + ); return () => { - clearTimeout(timer); + clearInterval(timer); }; } - }, [lines, currentLine, isPlaying, playSpeed, render, hasNextPage, fetchNextPage, setIsPlaying]); + }, [lines, isPlaying, playSpeed, render, hasNextPage, fetchNextPage, setIsPlaying]); const seekToLine = useCallback( (index: any) => {