From 9f359de953632eaf127333ad32eb5335c2571ae1 Mon Sep 17 00:00:00 2001 From: JGerla Date: Thu, 22 Jan 2026 13:31:02 +0100 Subject: [PATCH] test: added tests for editorwarnings ref: N25B-450 --- .../components/EditorWarnings.test.tsx | 156 ++++++++++++++++++ test/setupFlowTests.ts | 53 +++--- 2 files changed, 186 insertions(+), 23 deletions(-) create mode 100644 test/pages/visProgPage/visualProgrammingUI/components/EditorWarnings.test.tsx diff --git a/test/pages/visProgPage/visualProgrammingUI/components/EditorWarnings.test.tsx b/test/pages/visProgPage/visualProgrammingUI/components/EditorWarnings.test.tsx new file mode 100644 index 0000000..a3c2935 --- /dev/null +++ b/test/pages/visProgPage/visualProgrammingUI/components/EditorWarnings.test.tsx @@ -0,0 +1,156 @@ +import { describe, it, expect} from '@jest/globals'; +import { + type EditorWarning, warningSummary +} from "../../../../../src/pages/VisProgPage/visualProgrammingUI/components/EditorWarnings.tsx"; +import useFlowStore from "../../../../../src/pages/VisProgPage/visualProgrammingUI/VisProgStores.tsx"; + + +function makeWarning( + overrides?: Partial +): EditorWarning { + return { + scope: { id: 'node-1' }, + type: 'MISSING_INPUT', + severity: 'ERROR', + description: 'Missing input', + ...overrides, + }; +} + +describe("editorWarnings", () => { + describe('registerWarning', () => { + it('registers a node-level warning', () => { + const warning = makeWarning(); + const {registerWarning, getWarnings} = useFlowStore.getState() + registerWarning(warning); + + const warnings = getWarnings(); + expect(warnings).toHaveLength(1); + expect(warnings[0]).toEqual(warning); + }); + + it('registers a handle-level warning with scoped key', () => { + const warning = makeWarning({ + scope: { id: 'node-1', handleId: 'input-1' }, + }); + const {registerWarning, editorWarningRegistry} = useFlowStore.getState() + registerWarning(warning); + + const nodeWarnings = editorWarningRegistry.get('node-1'); + + expect(nodeWarnings?.has('MISSING_INPUT:input-1')).toBe(true); + }); + + it('updates severityIndex correctly', () => { + const {registerWarning, severityIndex} = useFlowStore.getState() + registerWarning(makeWarning()); + + console.log(severityIndex); + expect(severityIndex.get('ERROR')!.size).toBe(1); + }); + }); + + describe('getWarningsBySeverity', () => { + it('returns only warnings of requested severity', () => { + const {registerWarning, getWarningsBySeverity} = useFlowStore.getState() + registerWarning( + makeWarning({ severity: 'ERROR' }) + ); + + registerWarning( + makeWarning({ + severity: 'WARNING', + type: 'MISSING_OUTPUT', + }) + ); + + const errors = getWarningsBySeverity('ERROR'); + const warnings = getWarningsBySeverity('WARNING'); + + expect(errors).toHaveLength(1); + expect(warnings).toHaveLength(1); + }); + }); + + describe('isProgramValid', () => { + it('returns true when no ERROR warnings exist', () => { + expect(useFlowStore.getState().isProgramValid()).toBe(true); + }); + + it('returns false when ERROR warnings exist', () => { + const {registerWarning, isProgramValid} = useFlowStore.getState() + registerWarning(makeWarning()); + expect(isProgramValid()).toBe(false); + }); + }); + + describe('unregisterWarning', () => { + it('removes warning from registry and severityIndex', () => { + const warning = makeWarning(); + const { + registerWarning, + getWarnings, + unregisterWarning, + severityIndex + } = useFlowStore.getState() + + registerWarning(warning); + + unregisterWarning('node-1', 'MISSING_INPUT'); + + expect(getWarnings()).toHaveLength(0); + expect(severityIndex.get('ERROR')!.size).toBe(0); + }); + + it('does nothing if warning does not exist', () => { + expect(() => + useFlowStore.getState().unregisterWarning('node-1', 'DOES_NOT_EXIST') + ).not.toThrow(); + }); + }); + + describe('unregisterWarningsForId', () => { + it('removes all warnings for a node', () => { + const {registerWarning, unregisterWarningsForId, getWarnings, severityIndex} = useFlowStore.getState() + registerWarning( + makeWarning({ + scope: { id: 'node-1', handleId: 'h1' }, + }) + ); + + registerWarning( + makeWarning({ + scope: { id: 'node-1' }, + type: 'MISSING_OUTPUT', + severity: 'WARNING', + }) + ); + + unregisterWarningsForId('node-1'); + + expect(getWarnings()).toHaveLength(0); + expect( + severityIndex.get('ERROR')!.size + ).toBe(0); + expect( + severityIndex.get('WARNING')!.size + ).toBe(0); + }); + }); + + describe('warningSummary', () => { + it('returns correct counts and validity', () => { + const {registerWarning} = useFlowStore.getState() + registerWarning( + makeWarning({ severity: 'ERROR' }) + ); + + const summary = warningSummary(); + + expect(summary.error).toBe(1); + expect(summary.warning).toBe(0); + expect(summary.info).toBe(0); + expect(summary.isValid).toBe(false); + }); + }); +}) diff --git a/test/setupFlowTests.ts b/test/setupFlowTests.ts index fbf637b..caeda94 100644 --- a/test/setupFlowTests.ts +++ b/test/setupFlowTests.ts @@ -3,7 +3,6 @@ import { cleanup } from '@testing-library/react'; import { type CompositeWarningKey, type SeverityIndex, - type WarningRegistry } from "../src/pages/VisProgPage/visualProgrammingUI/components/EditorWarnings.tsx"; import useFlowStore from '../src/pages/VisProgPage/visualProgrammingUI/VisProgStores.tsx'; @@ -74,33 +73,41 @@ export const mockReactFlow = () => { }; -const emptySeverityIndex : SeverityIndex = new Map([ - ['INFO', new Set()], - ['WARNING', new Set()], - ['ERROR', new Set()], -]); - -const emptyWarningRegistry : WarningRegistry = new Map(); - -const defaultState = { - nodes: [], - edges: [], - past: [], - future: [], - isBatchAction: false, - edgeReconnectSuccessful: true, - ruleRegistry: new Map(), - editorWarningRegistry: emptyWarningRegistry, - severityIndex: emptySeverityIndex, -} - beforeAll(() => { - useFlowStore.setState(defaultState); + useFlowStore.setState({ + nodes: [], + edges: [], + past: [], + future: [], + isBatchAction: false, + edgeReconnectSuccessful: true, + ruleRegistry: new Map(), + editorWarningRegistry: new Map(), + severityIndex: new Map([ + ['INFO', new Set()], + ['WARNING', new Set()], + ['ERROR', new Set()], + ]) as SeverityIndex, + }); }); afterEach(() => { cleanup(); - useFlowStore.setState(defaultState); + useFlowStore.setState({ + nodes: [], + edges: [], + past: [], + future: [], + isBatchAction: false, + edgeReconnectSuccessful: true, + ruleRegistry: new Map(), + editorWarningRegistry: new Map(), + severityIndex: new Map([ + ['INFO', new Set()], + ['WARNING', new Set()], + ['ERROR', new Set()], + ]) as SeverityIndex, + }); }); if (typeof HTMLDialogElement !== 'undefined') {