import { it, expect, beforeEach, jest } from '@jest/globals'; import TabSessionManager from '../app/player/web/TabManager'; import SimpleStore from '../app/player/common/SimpleStore'; import { TYPES as EVENT_TYPES } from '../app/types/session/event'; import { MType } from '../app/player/web/messages/raw.gen'; jest.mock('@medv/finder', () => ({ default: jest.fn(() => 'mocked network-proxy content') })); jest.mock('syncod', () => { return { Decoder: jest.fn().mockImplementation(() => ({ decode: jest.fn(), set: jest.fn() })), }; }); jest.mock('js-untar', () => ({ __esModule: true, default: jest.fn(), })); class FakeScreen { displayFrame = jest.fn(); window: any = null; document: any = { body: { querySelector: jest.fn(), style: {} } }; } const session = { isMobile: false } as any; const setSize = jest.fn(); let store: SimpleStore; let manager: TabSessionManager; beforeEach(() => { jest.useFakeTimers(); store = new SimpleStore({ tabStates: { tab1: { ...TabSessionManager.INITIAL_STATE } }, tabNames: {}, eventCount: 0, }); manager = new TabSessionManager(session, store as any, new FakeScreen() as any, 'tab1', setSize, 0); jest.runOnlyPendingTimers(); jest.useRealTimers(); }); it('updateLists should append location events and update store', () => { const event = { time: 1, key: 1, type: EVENT_TYPES.LOCATION } as any; manager.updateLists({ event: [event] }); // @ts-ignore private access expect((manager as any).locationEventManager.list[0]).toBe(event); expect(store.get().tabStates['tab1'].eventList).toEqual([event]); expect(store.get().eventCount).toBe(1); }); it('resetMessageManagers should clear managers', () => { // @ts-ignore private access (manager as any).locationEventManager.append({ time: 1 }); // @ts-ignore private access (manager as any).scrollManager.append({ time: 2 }); const oldPages = (manager as any).pagesManager; manager.resetMessageManagers(); // @ts-ignore private access expect((manager as any).locationEventManager.list.length).toBe(0); // @ts-ignore private access expect((manager as any).scrollManager.list.length).toBe(0); // @ts-ignore private access expect((manager as any).pagesManager).not.toBe(oldPages); }); it('onFileReadSuccess should update store with lists and performance data', () => { (manager as any).performanceTrackManager['chart'] = [{ time: 1, usedHeap: 0, totalHeap: 0, fps: null, cpu: null, nodesCount: 0 }]; (manager as any).performanceTrackManager['cpuAvailable'] = true; (manager as any).performanceTrackManager['fpsAvailable'] = true; manager.locationManager.append({ time: 2, url: 'http://example.com' } as any); manager.onFileReadSuccess(); const state = store.get().tabStates['tab1']; expect(state.performanceChartData.length).toBe(1); expect(state.performanceAvailability).toEqual({ cpu: true, fps: true, heap: false, nodes: true }); expect(state.urlsList[0].url).toBe('http://example.com'); }); it('decodeMessage should delegate to decoder', () => { const msg = { tp: MType.Timestamp, time: 0 } as any; const decoder = (manager as any).decoder; manager.decodeMessage(msg); expect(decoder.decode).toHaveBeenCalledWith(msg); }); it('sortDomRemoveMessages comparator should prioritize head nodes', () => { const mock = { sortPages: jest.fn() }; // @ts-ignore private access (manager as any).pagesManager = mock; const msgs = [ { id: 1, parentID: 1, tp: MType.RemoveNode, time: 10 }, { id: 2, parentID: 2, tp: MType.RemoveNode, time: 10 }, { id: 3, parentID: 2, tp: MType.CreateElementNode, time: 10 }, ] as any[]; manager.sortDomRemoveMessages(msgs); const comparator = mock.sortPages.mock.calls[0][0]; expect(comparator(msgs[0], msgs[2])).toBe(-1); expect(comparator(msgs[2], msgs[0])).toBe(1); expect(comparator(msgs[0], msgs[1])).toBe(-1); expect(comparator(msgs[1], msgs[0])).toBe(1); });