import { render, screen, fireEvent } from '@testing-library/react';
import { describe, it, expect, vi } from 'vitest';
import { Ladder } from './Ladder';
import { Program, RungElement } from '../../engine/types';
describe('Ladder Component', () => {
const mockOnElementClick = vi.fn();
const mockOnDropElement = vi.fn();
const mockOnMoveElement = vi.fn();
const mockProgram: Program = {
name: 'Test Program',
cycleTime: 100,
rungs: [
{
id: 'rung-1',
enabled: true,
series: [
{
type: 'contact',
contactType: 'NO',
address: 'I:0.0',
} as RungElement,
{
type: 'coil',
coilType: 'OUTPUT',
address: 'Q:0.0',
} as RungElement,
],
},
],
};
const mockEngineState: any = {
inputs: new Map([['I:0.0', { address: 'I:0.0', value: true }]]),
outputs: new Map(),
};
it('renders the correct number of rungs', () => {
render(
<Ladder
program={mockProgram}
engineState={mockEngineState}
onElementClick={mockOnElementClick}
onDropElement={mockOnDropElement}
onMoveElement={mockOnMoveElement}
/>
);
expect(screen.getByText('1')).toBeInTheDocument();
});
it('calls onElementClick when an element is clicked', () => {
render(
<Ladder
program={mockProgram}
engineState={mockEngineState}
onElementClick={mockOnElementClick}
onDropElement={mockOnDropElement}
onMoveElement={mockOnMoveElement}
/>
);
// Click on the element text
const elementText = screen.getByText('I:0.0');
fireEvent.click(elementText);
expect(mockOnElementClick).toHaveBeenCalledWith(0, 0, mockProgram.rungs[0].series[0]);
});
it('calls onDropElement when an element is dropped on a rung', () => {
render(
<Ladder
program={mockProgram}
engineState={mockEngineState}
onElementClick={mockOnElementClick}
onDropElement={mockOnDropElement}
onMoveElement={mockOnMoveElement}
/>
);
// The drop zone is a transparent rect inside the rung group
const svg = document.querySelector('svg');
const dropRect = svg?.querySelector('rect[fill="transparent"]');
if (!dropRect) throw new Error('Drop zone rect not found');
fireEvent.drop(dropRect, {
dataTransfer: {
getData: (type: string) => type === 'text/plain' ? 'contact-no' : '',
} as any,
});
expect(mockOnDropElement).toHaveBeenCalledWith('contact-no', 0);
});
});