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);
});
});