buster/apps/web/src/layouts/ChatLayout/ChatLayoutContext/useSelectedFile/useSelectedFile.test.tsx

161 lines
4.7 KiB
TypeScript

import { act, renderHook } from '@testing-library/react';
import { beforeEach, describe, expect, it, type MockedFunction, vi } from 'vitest';
import type { FileType } from '@/api/asset_interfaces/chat';
import type { AppSplitterRef } from '@/components/ui/layouts/AppSplitter';
import { BusterRoutes } from '@/routes';
import type { SelectedFile } from '../../interfaces';
import type { FileViewSecondary } from '../useLayoutConfig';
import { createSelectedFile } from './createSelectedFile';
import { useSelectedFile } from './useSelectedFile';
// Mock dependencies
vi.mock('./createSelectedFile');
// Mock the BusterAppLayout context
const mockOnChangePage = vi.fn();
vi.mock('@/context/BusterAppLayout', () => ({
useAppLayoutContextSelector: vi.fn((selector) => mockOnChangePage)
}));
const mockCreateSelectedFile = createSelectedFile as MockedFunction<typeof createSelectedFile>;
describe('useSelectedFile', () => {
const mockAnimateOpenSplitter = vi.fn();
const mockAppSplitterRef = {
current: {
isSideClosed: vi.fn((side: 'left' | 'right') => false),
setSplitSizes: vi.fn(),
animateWidth: vi.fn(),
sizes: [0, 0, 0],
getSizesInPixels: vi.fn()
} as AppSplitterRef
};
const mockChatParams = {
chatId: '123',
isVersionHistoryMode: false,
metricId: undefined,
dashboardId: undefined,
collectionId: undefined,
datasetId: undefined,
messageId: undefined,
currentRoute: BusterRoutes.APP_CHAT_ID,
secondaryView: undefined as FileViewSecondary | undefined,
metricVersionNumber: undefined,
dashboardVersionNumber: undefined,
reportId: undefined,
reportVersionNumber: undefined
} satisfies Parameters<typeof useSelectedFile>[0]['chatParams'];
beforeEach(() => {
vi.clearAllMocks();
});
it('should initialize with null selected file when no chat params are provided', () => {
mockCreateSelectedFile.mockReturnValue(null);
const { result } = renderHook(() =>
useSelectedFile({
animateOpenSplitter: mockAnimateOpenSplitter,
appSplitterRef: mockAppSplitterRef,
chatParams: mockChatParams
})
);
expect(result.current.selectedFile).toBeNull();
});
it('should initialize with selected file when valid chat params are provided', () => {
const mockFile: SelectedFile = {
id: '456',
type: 'metric' as FileType,
versionNumber: 1
};
mockCreateSelectedFile.mockReturnValue(mockFile);
const { result } = renderHook(() =>
useSelectedFile({
animateOpenSplitter: mockAnimateOpenSplitter,
appSplitterRef: mockAppSplitterRef,
chatParams: {
...mockChatParams,
metricId: '456',
metricVersionNumber: 1
}
})
);
expect(result.current.selectedFile).toEqual(mockFile);
});
it('should handle setting a new selected file', async () => {
mockCreateSelectedFile.mockReturnValue(null);
const newFile: SelectedFile = {
id: '789',
type: 'metric' as FileType,
versionNumber: 1
};
const { result } = renderHook(() =>
useSelectedFile({
animateOpenSplitter: mockAnimateOpenSplitter,
appSplitterRef: mockAppSplitterRef,
chatParams: mockChatParams
})
);
await act(async () => {
await result.current.onSetSelectedFile(newFile);
});
expect(mockAnimateOpenSplitter).toHaveBeenCalledWith('both');
expect(mockOnChangePage).toHaveBeenCalledWith(
'/app/chats/123/metrics/789/chart?metric_version_number=1'
);
});
it('should collapse splitter when setting same file that is already open', async () => {
const currentFile: SelectedFile = {
id: '789',
type: 'metric' as FileType,
versionNumber: 1
};
mockCreateSelectedFile.mockReturnValue(currentFile);
const { result } = renderHook(() =>
useSelectedFile({
animateOpenSplitter: mockAnimateOpenSplitter,
appSplitterRef: mockAppSplitterRef,
chatParams: {
...mockChatParams,
metricId: '789',
metricVersionNumber: 1
}
})
);
await act(async () => {
await result.current.onSetSelectedFile(currentFile);
});
expect(mockAnimateOpenSplitter).toHaveBeenCalledWith('left');
});
it('should handle setting selected file to null', async () => {
mockCreateSelectedFile.mockReturnValue(null);
const { result } = renderHook(() =>
useSelectedFile({
animateOpenSplitter: mockAnimateOpenSplitter,
appSplitterRef: mockAppSplitterRef,
chatParams: mockChatParams
})
);
await act(async () => {
await result.current.onSetSelectedFile(null);
});
expect(mockAnimateOpenSplitter).toHaveBeenCalledWith('left');
});
});