Newer
Older
CNCTools / ReferenceSurfaceGenerator / frontend / src / DxfViewer.test.js
@yangyang xie yangyang xie 23 days ago 3 KB fix
import { render, screen, waitFor, act, within } from '@testing-library/react';
import '@testing-library/jest-dom';
import axios from 'axios';
import DxfViewer from './DxfViewer';

// Mock axios to avoid actual network requests
jest.mock('axios');




// Mocking three.js and react-three/fiber dependencies
jest.mock('@react-three/fiber', () => ({
  Canvas: () => <div data-testid="mock-canvas" />,
}));

jest.mock('@react-three/drei', () => ({
  OrbitControls: () => null,
  Line: () => null,
  Box: () => null,
}));
jest.mock('./DxfContent', () => () => <div data-testid="mock-dxf-content" />);


describe('DxfViewer', () => {
  const API_URL = 'http://localhost:8000';
  const viewUrl = '/api/jobs/123/view';
  
  beforeEach(() => {
    // Reset mocks before each test
    axios.get.mockClear();
  });

  it('shows a loading spinner while fetching data', async () => {
    axios.get.mockImplementationOnce(() => new Promise(() => {})); // Never resolve to keep loading
    
    act(() => {
      render(<DxfViewer show={true} onHide={() => {}} viewUrl={viewUrl} API_URL={API_URL} />);
    });
    
    expect(screen.getByText('Loading geometry...')).toBeInTheDocument();
  });

  it('displays an error message if data fetching fails', async () => {
    const errorMessage = 'Failed to load DXF data.';
    axios.get.mockRejectedValueOnce({ response: { data: { detail: errorMessage } } });
    
    await act(async () => {
      render(<DxfViewer show={true} onHide={() => {}} viewUrl={viewUrl} API_URL={API_URL} />);
    });
    
    // Wait for the error message to appear
    expect(screen.getByText(errorMessage)).toBeInTheDocument();
  });

  it('renders the canvas with data after successful fetch', async () => {
    const mockData = {
      polylines: [[[0, 0, 0], [1, 1, 1]]],
    };
    axios.get.mockResolvedValueOnce({ data: mockData });
    
    let component;
    await act(async () => {
      component = render(<DxfViewer show={true} onHide={() => {}} viewUrl={viewUrl} API_URL={API_URL} />);
    });
    
    // Check if the mock canvas is present and not displaying the fallback initially
    const mockCanvas = screen.getByTestId('mock-canvas');
    expect(mockCanvas).toBeInTheDocument();
    expect(mockCanvas).not.toHaveTextContent('Preparing renderer...');

    // We expect the children (DxfContent) to be rendered inside the Canvas mock
    // Since DxfContent itself doesn't render user-facing text other than the console error about casing,
    // we can assert that the Canvas mock is showing some content (its children)
    // This is a weak assertion, but stronger ones would require mocking THREE.Line etc.
    expect(mockCanvas).toBeEmptyDOMElement(); // The Line component mock returns null, so canvas should be empty

    // Optionally, verify that axios.get was called
    expect(axios.get).toHaveBeenCalledWith(`${API_URL}${viewUrl}`);
  });

  it('does not fetch data when not shown', async () => {
    render(<DxfViewer show={false} onHide={() => {}} viewUrl={viewUrl} API_URL={API_URL} />);
    expect(axios.get).not.toHaveBeenCalled();
  });

  it('calls onHide when close button is clicked', async () => {
    const mockOnHide = jest.fn();
    axios.get.mockResolvedValueOnce({ data: { polylines: [] } }); // Resolve immediately

    await act(async () => {
      render(<DxfViewer show={true} onHide={mockOnHide} viewUrl={viewUrl} API_URL={API_URL} />);
    });

    const footer = screen.getByTestId('modal-footer');
    const closeButton = within(footer).getByRole('button', { name: /close/i });
    act(() => {
      closeButton.click();
    });

    expect(mockOnHide).toHaveBeenCalledTimes(1);
  });
});