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


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

import React from 'react';

import { InstrumentSearch } from '@components/InstrumentSearch';

import { SymbolSearchModal } from '../components/MoexChart/components/SymbolSearchModal';

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

jest.mock('@components/InstrumentSearch', () => ({
  InstrumentSearch: jest.fn(() => null),
}));

interface InstrumentSearchMockProps {
  widgetId: number;
  variant: string;
  isOpen: boolean;
  setOpen: (isOpen: boolean) => void;
  addInstruments: (instruments: Contract[]) => void;
}

describe('SymbolSearchModal', () => {
  const mockInstrumentSearch = InstrumentSearch as jest.Mock;

  const mockSetOpen = jest.fn();
  const mockOnSymbolChange = jest.fn();

  const renderComponent = (): InstrumentSearchMockProps => {
    render(
      <SymbolSearchModal
        widgetId={42}
        isOpen
        setOpen={mockSetOpen}
        onSymbolChange={mockOnSymbolChange}
      />,
    );

    return mockInstrumentSearch.mock.calls[0]?.[0] as InstrumentSearchMockProps;
  };

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

  it('should pass modal properties to instrument search', () => {
    // Arrange & Act
    const instrumentSearchProps = renderComponent();

    // Assert
    expect(instrumentSearchProps.widgetId).toBe(42);
    expect(instrumentSearchProps.variant).toBe('single');
    expect(instrumentSearchProps.isOpen).toBe(true);
    expect(instrumentSearchProps.setOpen).toBe(mockSetOpen);
    expect(instrumentSearchProps.addInstruments).toEqual(expect.any(Function));
  });

  it('should pass selected instrument after instrument selection', () => {
    // Arrange
    const instrumentSearchProps = renderComponent();

    const instrument = {
      issKey: 'MXSE:TQBR:SBER',
      displayName: 'Сбербанк',
      symbol: 'SBER',
    } as Contract;

    // Act
    instrumentSearchProps.addInstruments([instrument]);

    // Assert
    expect(mockOnSymbolChange).toHaveBeenCalledTimes(1);
    expect(mockOnSymbolChange).toHaveBeenCalledWith(instrument);
  });

  it('should pass all required symbol metadata after instrument selection', () => {
    // Arrange
    const instrumentSearchProps = renderComponent();

    const instrument = {
      issKey: 'MXSE:TQBR:GAZP',
      displayName: 'Газпром',
      symbol: 'GAZP',
    } as Contract;

    // Act
    instrumentSearchProps.addInstruments([instrument]);

    // Assert
    expect(mockOnSymbolChange).toHaveBeenCalledWith(
      expect.objectContaining({
        issKey: 'MXSE:TQBR:GAZP',
        displayName: 'Газпром',
        symbol: 'GAZP',
      }),
    );
  });

  it('should close modal after instrument selection', () => {
    // Arrange
    const instrumentSearchProps = renderComponent();

    const instrument = {
      issKey: 'MXSE:TQBR:SBER',
      displayName: 'Сбербанк',
      symbol: 'SBER',
    } as Contract;

    // Act
    instrumentSearchProps.addInstruments([instrument]);

    // Assert
    expect(mockSetOpen).toHaveBeenCalledTimes(1);
    expect(mockSetOpen).toHaveBeenCalledWith(false);
  });

  it('should not change symbol when instruments list is empty', () => {
    // Arrange
    const instrumentSearchProps = renderComponent();

    // Act
    instrumentSearchProps.addInstruments([]);

    // Assert
    expect(mockOnSymbolChange).not.toHaveBeenCalled();
    expect(mockSetOpen).not.toHaveBeenCalled();
  });

  it('should not change symbol when selected instrument has no issKey', () => {
    // Arrange
    const instrumentSearchProps = renderComponent();

    const instrument = {
      displayName: 'Сбербанк',
      symbol: 'SBER',
    } as Contract;

    // Act
    instrumentSearchProps.addInstruments([instrument]);

    // Assert
    expect(mockOnSymbolChange).not.toHaveBeenCalled();
    expect(mockSetOpen).not.toHaveBeenCalled();
  });

  it('should not change symbol when selected instrument has empty issKey', () => {
    // Arrange
    const instrumentSearchProps = renderComponent();

    const instrument = {
      issKey: '',
      displayName: 'Сбербанк',
      symbol: 'SBER',
    } as Contract;

    // Act
    instrumentSearchProps.addInstruments([instrument]);

    // Assert
    expect(mockOnSymbolChange).not.toHaveBeenCalled();
    expect(mockSetOpen).not.toHaveBeenCalled();
  });

  it('should pass instrument with empty optional display metadata', () => {
    // Arrange
    const instrumentSearchProps = renderComponent();

    const instrument = {
      issKey: 'MXSE:TQBR:SBER',
      displayName: '',
      symbol: '',
    } as Contract;

    // Act
    instrumentSearchProps.addInstruments([instrument]);

    // Assert
    expect(mockOnSymbolChange).toHaveBeenCalledTimes(1);
    expect(mockOnSymbolChange).toHaveBeenCalledWith(instrument);
    expect(mockSetOpen).toHaveBeenCalledWith(false);
  });
});