test: added tests for the warningSidebar

ref: N25B-450
This commit is contained in:
JGerla
2026-01-22 13:54:24 +01:00
parent 9f359de953
commit 9c64455a19
2 changed files with 159 additions and 4 deletions

View File

@@ -117,10 +117,6 @@ function WarningListItem(props: { warning: EditorWarning }) {
<div className={styles.meta}>
{props.warning.type}
{/*{props.warning.scope.id}*/}
{/*{props.warning.scope.handleId && (*/}
{/* <span className={styles.handle}>@{props.warning.scope.handleId}</span>*/}
{/*)}*/}
</div>
</div>
);

View File

@@ -0,0 +1,159 @@
import {fireEvent, render, screen} from '@testing-library/react';
import '@testing-library/jest-dom';
import {useReactFlow, useStoreApi} from "@xyflow/react";
import {
type EditorWarning,
globalWarning
} from "../../../../../src/pages/VisProgPage/visualProgrammingUI/components/EditorWarnings.tsx";
import {WarningsSidebar} from "../../../../../src/pages/VisProgPage/visualProgrammingUI/components/WarningSidebar.tsx";
import useFlowStore from "../../../../../src/pages/VisProgPage/visualProgrammingUI/VisProgStores.tsx";
jest.mock('@xyflow/react', () => ({
useReactFlow: jest.fn(),
useStoreApi: jest.fn(),
}));
jest.mock('../../../../../src/pages/VisProgPage/visualProgrammingUI/VisProgStores.tsx');
function makeWarning(
overrides?: Partial<EditorWarning>
): EditorWarning {
return {
scope: { id: 'node-1' },
type: 'MISSING_INPUT',
severity: 'ERROR',
description: 'Missing input',
...overrides,
};
}
describe('WarningsSidebar', () => {
let getStateSpy: jest.SpyInstance;
const setCenter = jest.fn(() => Promise.resolve());
const getNode = jest.fn();
const addSelectedNodes = jest.fn();
beforeEach(() => {
jest.clearAllMocks();
// React Flow hooks
(useReactFlow as jest.Mock).mockReturnValue({
getNode,
setCenter,
});
(useStoreApi as jest.Mock).mockReturnValue({
getState: () => ({ addSelectedNodes }),
});
// Use spyOn to override store
const mockWarnings = [
makeWarning({ description: 'Node warning', scope: { id: 'node-1' } }),
makeWarning({
description: 'Global warning',
scope: { id: globalWarning },
type: 'INCOMPLETE_PROGRAM',
severity: 'WARNING',
}),
makeWarning({
description: 'Info warning',
scope: { id: 'node-2' },
severity: 'INFO',
}),
];
getStateSpy = jest
.spyOn(useFlowStore, 'getState')
.mockReturnValue({
getWarnings: () => mockWarnings,
} as any);
});
afterEach(() => {
getStateSpy.mockRestore();
});
it('renders warnings header', () => {
render(<WarningsSidebar />);
expect(screen.getByText('Warnings')).toBeInTheDocument();
});
it('renders all warning descriptions', () => {
render(<WarningsSidebar />);
expect(screen.getByText('Node warning')).toBeInTheDocument();
expect(screen.getByText('Global warning')).toBeInTheDocument();
expect(screen.getByText('Info warning')).toBeInTheDocument();
});
it('splits global and other warnings correctly', () => {
render(<WarningsSidebar />);
expect(screen.getByText('global:')).toBeInTheDocument();
expect(screen.getByText('other:')).toBeInTheDocument();
});
it('shows empty state when no warnings exist', () => {
getStateSpy.mockReturnValueOnce({
getWarnings: () => [],
} as any);
render(<WarningsSidebar />);
expect(screen.getByText('No warnings!')).toBeInTheDocument();
});
it('filters by severity', () => {
render(<WarningsSidebar />);
fireEvent.click(screen.getByText('ERROR'));
expect(screen.getByText('Node warning')).toBeInTheDocument();
expect(screen.queryByText('Global warning')).not.toBeInTheDocument();
expect(screen.queryByText('Info warning')).not.toBeInTheDocument();
});
it('filters INFO severity correctly', () => {
render(<WarningsSidebar />);
fireEvent.click(screen.getByText('INFO'));
expect(screen.getByText('Info warning')).toBeInTheDocument();
expect(screen.queryByText('Node warning')).not.toBeInTheDocument();
expect(screen.queryByText('Global warning')).not.toBeInTheDocument();
});
it('clicking node warning jumps to node', async () => {
getNode.mockReturnValue({
id: 'node-1',
position: { x: 100, y: 200 },
width: 50,
height: 50,
});
render(<WarningsSidebar />);
fireEvent.click(screen.getByText('Node warning'));
expect(setCenter).toHaveBeenCalledWith(
125,
225,
expect.objectContaining({ zoom: 2 })
);
await Promise.resolve();
expect(addSelectedNodes).toHaveBeenCalledWith(['node-1']);
});
it('clicking global warning does NOT jump', () => {
render(<WarningsSidebar />);
fireEvent.click(screen.getByText('Global warning'));
expect(setCenter).not.toHaveBeenCalled();
expect(addSelectedNodes).not.toHaveBeenCalled();
});
it('does nothing if node does not exist', () => {
getNode.mockReturnValue(undefined);
render(<WarningsSidebar />);
fireEvent.click(screen.getByText('Node warning'));
expect(setCenter).not.toHaveBeenCalled();
});
});