Загрузка данных


import { renderHook } from '@testing-library/react';

import { useAppSelect } from '@hooks/useAppSelector';
import { useContracts } from '@modules/contracts';
import { filterByUniqIssKey } from '@utils/filterByUniqIssKey';
import { DEFAULT_SYMBOL } from '@widgets/Chart/const';

import { useChartPublicContext } from '../hooks/useChartPublicContext';

import type { Contract } from '@modules/contracts';

// Mock the dependencies
jest.mock('@hooks/useAppSelector');
jest.mock('@modules/contracts');
jest.mock('@utils/filterByUniqIssKey');

jest.mock('@api/index', () => ({
  updateMenuLocked: jest.fn(),
  widgetsController: {
    delete: jest.fn(),
  },
  widgetPropertiesController: {
    update: jest.fn(),
  },
  workspaceController: {
    update: jest.fn(),
  },
}));

jest.mock('@api/controllers/workspace', () => ({
  workspaceController: {
    update: jest.fn(),
  },
}));

describe('useChartPublicContext', () => {
  const mockUseAppSelect = useAppSelect as jest.Mock;
  const mockUseContracts = useContracts as jest.Mock;
  const mockFilterByUniqIssKey = filterByUniqIssKey as jest.Mock;

  const mockContracts = [
    {
      issKey: DEFAULT_SYMBOL,
      displayName: 'Инструмент по умолчанию',
      symbol: 'DEFAULT',
      // ... other contract properties
    },
    {
      issKey: 'MOEX:TEST1',
      displayName: 'Test Instrument 1',
      symbol: 'TEST1',
      // ... other contract properties
    },
    {
      issKey: 'MOEX:TEST2',
      displayName: 'Test Instrument 2',
      symbol: 'TEST2',
      // ... other contract properties
    },
    {
      issKey: 'MOEX:TEST3',
      displayName: 'Test Instrument 3',
      symbol: 'TEST3',
      // ... other contract properties
    },
  ] as Contract[];

  const mockWidget = {
    id: 1,
    name: 'Test Widget',
    type: 'graphic',
    master: 123,
    externalProperties: [
      {
        key: 'instrument',
        value: 'MOEX:TEST1',
      },
    ],
    // ... other widget properties
  };

  const mockPublicContext = {
    instrument: 'MOEX:TEST1',
  };

  beforeEach(() => {
    jest.clearAllMocks();

    // Mock the useAppSelect to return our test data
    mockUseAppSelect.mockImplementation((selector) => {
      if (selector.toString().includes('publicContext')) {
        return mockPublicContext;
      }

      if (selector.toString().includes('widgets')) {
        return mockWidget;
      }

      return {};
    });

    // Mock useContracts to return our test contracts
    mockUseContracts.mockReturnValue({
      contracts: mockContracts,
    });

    // Mock filterByUniqIssKey to return the same contracts
    mockFilterByUniqIssKey.mockImplementation((contracts: Contract[]) => contracts);
  });

  it('should return the correct issKey when a matching instrument is found', () => {
    // Arrange
    const mockSetCurrInstrument = jest.fn();
    const mockGetMasterInstrumentFromPublicContext = jest.fn().mockReturnValue('MOEX:TEST1');

    // Act
    const { result } = renderHook(() =>
      useChartPublicContext({
        widgetId: 1,
        setCurrInstrument: mockSetCurrInstrument,
        getMasterInstrumentFromPublicContext: mockGetMasterInstrumentFromPublicContext,
      }),
    );

    // Assert
    expect(result.current.issKey).toBe('MOEX:TEST1');
  });

  it('should pass instrument id, display name and ticker when a matching instrument is found', () => {
    // Arrange
    const mockSetCurrInstrument = jest.fn();
    const mockGetMasterInstrumentFromPublicContext = jest.fn().mockReturnValue('MOEX:TEST2');

    // Act
    renderHook(() =>
      useChartPublicContext({
        widgetId: 1,
        setCurrInstrument: mockSetCurrInstrument,
        getMasterInstrumentFromPublicContext: mockGetMasterInstrumentFromPublicContext,
      }),
    );

    // Assert
    expect(mockSetCurrInstrument).toHaveBeenCalledTimes(1);
    expect(mockSetCurrInstrument).toHaveBeenCalledWith('MOEX:TEST2', 'Test Instrument 2', 'TEST2');
  });

  it('should return undefined when no matching instrument is found', () => {
    // Arrange
    const mockSetCurrInstrument = jest.fn();
    const mockGetMasterInstrumentFromPublicContext = jest.fn().mockReturnValue('MOEX:NONEXISTENT');

    // Act
    const { result } = renderHook(() =>
      useChartPublicContext({
        widgetId: 1,
        setCurrInstrument: mockSetCurrInstrument,
        getMasterInstrumentFromPublicContext: mockGetMasterInstrumentFromPublicContext,
      }),
    );

    // Assert
    expect(result.current.issKey).toBeUndefined();
    expect(mockSetCurrInstrument).not.toHaveBeenCalled();
  });

  it('should return undefined when getMasterInstrumentFromPublicContext returns null', () => {
    // Arrange
    const mockSetCurrInstrument = jest.fn();
    const mockGetMasterInstrumentFromPublicContext = jest.fn().mockReturnValue(null);

    // Act
    const { result } = renderHook(() =>
      useChartPublicContext({
        widgetId: 1,
        setCurrInstrument: mockSetCurrInstrument,
        getMasterInstrumentFromPublicContext: mockGetMasterInstrumentFromPublicContext,
      }),
    );

    // Assert
    expect(result.current.issKey).toBeUndefined();
  });

  it('should return undefined when getMasterInstrumentFromPublicContext returns undefined', () => {
    // Arrange
    const mockSetCurrInstrument = jest.fn();
    const mockGetMasterInstrumentFromPublicContext = jest.fn().mockReturnValue(undefined);

    // Act
    const { result } = renderHook(() =>
      useChartPublicContext({
        widgetId: 1,
        setCurrInstrument: mockSetCurrInstrument,
        getMasterInstrumentFromPublicContext: mockGetMasterInstrumentFromPublicContext,
      }),
    );

    // Assert
    expect(result.current.issKey).toBeUndefined();
  });

  it('should set default instrument with display name and ticker when context value is empty', () => {
    // Arrange
    const mockSetCurrInstrument = jest.fn();
    const mockGetMasterInstrumentFromPublicContext = jest.fn().mockReturnValue(null);

    // Act
    renderHook(() =>
      useChartPublicContext({
        widgetId: 1,
        setCurrInstrument: mockSetCurrInstrument,
        getMasterInstrumentFromPublicContext: mockGetMasterInstrumentFromPublicContext,
      }),
    );

    // Assert
    expect(mockSetCurrInstrument).toHaveBeenCalledTimes(1);
    expect(mockSetCurrInstrument).toHaveBeenCalledWith(
      DEFAULT_SYMBOL,
      'Инструмент по умолчанию',
      'DEFAULT',
    );
  });

  it('should resolve instrument when widget is not found', () => {
    // Arrange
    const mockSetCurrInstrument = jest.fn();
    const mockGetMasterInstrumentFromPublicContext = jest.fn().mockReturnValue('MOEX:TEST1');

    mockUseAppSelect.mockImplementation((selector) => {
      if (selector.toString().includes('publicContext')) {
        return mockPublicContext;
      }

      if (selector.toString().includes('widgets')) {
        return null;
      }

      return {};
    });

    // Act
    const { result } = renderHook(() =>
      useChartPublicContext({
        widgetId: 999,
        setCurrInstrument: mockSetCurrInstrument,
        getMasterInstrumentFromPublicContext: mockGetMasterInstrumentFromPublicContext,
      }),
    );

    // Assert
    expect(result.current.issKey).toBe('MOEX:TEST1');
    expect(mockSetCurrInstrument).toHaveBeenCalledWith('MOEX:TEST1', 'Test Instrument 1', 'TEST1');
  });

  it('should not set instrument when contracts array is empty', () => {
    // Arrange
    const mockSetCurrInstrument = jest.fn();
    const mockGetMasterInstrumentFromPublicContext = jest.fn().mockReturnValue('MOEX:TEST1');

    mockUseContracts.mockReturnValue({
      contracts: [],
    });

    // Act
    const { result } = renderHook(() =>
      useChartPublicContext({
        widgetId: 1,
        setCurrInstrument: mockSetCurrInstrument,
        getMasterInstrumentFromPublicContext: mockGetMasterInstrumentFromPublicContext,
      }),
    );

    // Assert
    expect(result.current.issKey).toBeUndefined();
    expect(mockSetCurrInstrument).not.toHaveBeenCalled();
  });
});