/* eslint-disable @typescript-eslint/ban-ts-comment */ import {renderHook, WrapperComponent} from '@testing-library/react-hooks'; import {act} from '@testing-library/react-native'; import useRenderPassReport from '../../hooks/useRenderPassReport'; import renderPassReportGenerator from '../../RenderPassReportGenerator'; import {StateController} from '../../state-machine'; import profilerTestWrapper from '../profilerTestWrapper'; jest.mock('../../RenderPassReportGenerator', () => { const renderPassReportGenerator = jest.fn(); return renderPassReportGenerator; }); describe('useRenderPassReport', () => { let stateController: StateController; let wrapper: WrapperComponent; beforeEach(() => { // @ts-ignore renderPassReportGenerator.mockReturnValue(Promise.resolve(null)); ({wrapper, stateController} = profilerTestWrapper()); }); afterEach(() => { jest.resetAllMocks(); }); it('subscribes to changes from the state controller', () => { expect(stateController.addStateChangedListener).not.toHaveBeenCalled(); renderHook( () => useRenderPassReport({ destinationScreen: 'foo', }), {wrapper}, ); expect(stateController.addStateChangedListener).toHaveBeenCalledTimes(1); }); it('ignores state changes from screens that the user does not care about', () => { const report = renderHook( () => useRenderPassReport({ destinationScreen: 'foo', }), {wrapper}, ).result.current; // @ts-ignore stateController.addStateChangedListener.mock.calls[0][0]('bar', {name: 'old state'}, {name: 'new state'}); expect(renderPassReportGenerator).not.toHaveBeenCalled(); expect(report).toBeUndefined(); }); it('passes the state changes to the renderPassReportGenerator', () => { const report = renderHook( () => useRenderPassReport({ destinationScreen: new RegExp('^f[o]+$'), }), {wrapper}, ).result.current; const stateChangeArgs = ['fooooo', {name: 'old state'}, {name: 'new state'}]; expect(renderPassReportGenerator).not.toHaveBeenCalled(); // @ts-ignore stateController.addStateChangedListener.mock.calls[0][0](...stateChangeArgs); expect(renderPassReportGenerator).toHaveBeenCalledTimes(1); expect(renderPassReportGenerator).toHaveBeenCalledWith(stateChangeArgs[2]); expect(report).toBeUndefined(); }); it('updates the output result if renderPassReportGenerator prepares a report', async () => { const mockReport = {tti: 10}; // @ts-ignore renderPassReportGenerator.mockReturnValue(Promise.resolve(mockReport)); const renderHookResult = renderHook( () => useRenderPassReport({ destinationScreen: 'foo', }), {wrapper}, ); const stateChangeArgs = ['foo', {name: 'old state'}, {name: 'new state'}]; await act(async () => { // @ts-ignore stateController.addStateChangedListener.mock.calls[0][0](...stateChangeArgs); // Flush the report preparation promise await new Promise(resolve => setImmediate(resolve)); }); expect(renderHookResult.result.current).toBe(mockReport); }); it('does not unsubscribe and re-subscribe if the hook is re-rendered with a regex destinationScreen', () => { expect(stateController.addStateChangedListener).not.toHaveBeenCalled(); const renderHookResult = renderHook( () => useRenderPassReport({ destinationScreen: new RegExp('.*'), }), {wrapper}, ); expect(stateController.addStateChangedListener).toHaveBeenCalledTimes(1); expect(stateController.removeStateChangedListener).not.toHaveBeenCalled(); renderHookResult.rerender(); expect(stateController.addStateChangedListener).toHaveBeenCalledTimes(1); expect(stateController.removeStateChangedListener).not.toHaveBeenCalled(); }); });