Files
pepperplus-ui/test/pages/visProgPage/visualProgrammingUI/HandleRuleLogic.test.ts
2026-01-28 11:20:56 +01:00

89 lines
3.2 KiB
TypeScript

// This program has been developed by students from the bachelor Computer Science at Utrecht
// University within the Software Project course.
// © Copyright Utrecht University (Department of Information and Computing Sciences)
import {renderHook} from "@testing-library/react";
import type {Connection} from "@xyflow/react";
import {
ruleResult,
type RuleResult,
useHandleRules
} from "../../../../src/pages/VisProgPage/visualProgrammingUI/HandleRuleLogic.ts";
import useFlowStore from "../../../../src/pages/VisProgPage/visualProgrammingUI/VisProgStores.tsx";
describe('useHandleRules', () => {
it('should register rules on mount and validate connection', () => {
const rules = [() => ({ isSatisfied: true } as RuleResult)];
const { result } = renderHook(() => useHandleRules('node1', 'h1', 'target', rules));
// Confirm rules registered
const storedRules = useFlowStore.getState().getTargetRules('node1', 'h1');
expect(storedRules).toEqual(rules);
// Validate a connection
const connection = { source: 'node2', sourceHandle: 'h2', target: 'node1', targetHandle: 'h1' };
const validation = result.current(connection);
expect(validation).toEqual(ruleResult.satisfied);
});
it('should throw error if targetHandle missing', () => {
const rules: any[] = [];
const { result } = renderHook(() => useHandleRules('node1', 'h1', 'target', rules));
expect(() =>
result.current({ source: 'a', target: 'b', targetHandle: null, sourceHandle: null })
).toThrow('No target handle was provided');
});
});
describe('useHandleRules with multiple failed rules', () => {
it('should return the first failed rule message and consider connectionCount', () => {
// Mock rules for the target handle
const failingRules = [
(_conn: any, ctx: any) => {
if (ctx.connectionCount >= 1) {
return { isSatisfied: false, message: 'Max connections reached' } as RuleResult;
}
return { isSatisfied: true } as RuleResult;
},
() => ({ isSatisfied: false, message: 'Other rule failed' } as RuleResult),
() => ({ isSatisfied: true } as RuleResult),
];
// Register rules for the target handle
useFlowStore.getState().registerRules('targetNode', 'targetHandle', failingRules);
// Add one existing edge to simulate connectionCount
useFlowStore.setState({
edges: [
{
id: 'edge-1',
source: 'sourceNode',
sourceHandle: 'sourceHandle',
target: 'targetNode',
targetHandle: 'targetHandle',
},
],
});
// Create hook for a source node handle
const rulesForSource = [
(_c: Connection) => ({ isSatisfied: true } as RuleResult)
];
const { result } = renderHook(() =>
useHandleRules('sourceNode', 'sourceHandle', 'source', rulesForSource)
);
const connection = {
source: 'sourceNode',
sourceHandle: 'sourceHandle',
target: 'targetNode',
targetHandle: 'targetHandle',
};
const validation = result.current(connection);
// Should fail with first failing rule message
expect(validation).toEqual(ruleResult.notSatisfied('Max connections reached'));
});
});