feat: fix a lot of small changes to match cb, add functionality for all plans, add tests for the new plan editor. even more i dont really know anymore.
ref: N25B-412
This commit is contained in:
@@ -425,7 +425,6 @@ describe('NormNode', () => {
|
||||
label: 'Safety Norm',
|
||||
norm: 'Never harm humans',
|
||||
critical: false,
|
||||
basic_beliefs: [],
|
||||
});
|
||||
});
|
||||
|
||||
@@ -917,17 +916,8 @@ describe('NormNode', () => {
|
||||
}
|
||||
};
|
||||
|
||||
const mockBelief2: Node = {
|
||||
id: 'basic_belief-2',
|
||||
type: 'basic_belief',
|
||||
position: {x:300, y:300},
|
||||
data: {
|
||||
...JSON.parse(JSON.stringify(BasicBeliefNodeDefaults))
|
||||
}
|
||||
};
|
||||
|
||||
useFlowStore.setState({
|
||||
nodes: [mockNode, mockBelief1, mockBelief2],
|
||||
nodes: [mockNode, mockBelief1],
|
||||
edges: [],
|
||||
});
|
||||
|
||||
@@ -938,16 +928,11 @@ describe('NormNode', () => {
|
||||
sourceHandle: null,
|
||||
targetHandle: null,
|
||||
});
|
||||
useFlowStore.getState().onConnect({
|
||||
source: 'basic_belief-2',
|
||||
target: 'norm-1',
|
||||
sourceHandle: null,
|
||||
targetHandle: null,
|
||||
});
|
||||
|
||||
|
||||
|
||||
const state = useFlowStore.getState();
|
||||
const updatedNorm = state.nodes.find(n => n.id === 'norm-1');
|
||||
expect(updatedNorm?.data.conditions).toEqual(["basic_belief-1", "basic_belief-2"]);
|
||||
expect(updatedNorm?.data.condition).toEqual("basic_belief-1");
|
||||
});
|
||||
});
|
||||
});
|
||||
@@ -1,6 +1,5 @@
|
||||
import { describe, it, beforeEach } from '@jest/globals';
|
||||
import { screen, waitFor } from '@testing-library/react';
|
||||
import userEvent from '@testing-library/user-event';
|
||||
import { screen } from '@testing-library/react';
|
||||
import { renderWithProviders } from '../../../../test-utils/test-utils.tsx';
|
||||
import TriggerNode, {
|
||||
TriggerReduce,
|
||||
@@ -11,12 +10,15 @@ import TriggerNode, {
|
||||
import useFlowStore from '../../../../../src/pages/VisProgPage/visualProgrammingUI/VisProgStores';
|
||||
import type { Node } from '@xyflow/react';
|
||||
import '@testing-library/jest-dom';
|
||||
import { TriggerNodeDefaults } from '../../../../../src/pages/VisProgPage/visualProgrammingUI/nodes/TriggerNode.default.ts';
|
||||
import { BasicBeliefNodeDefaults } from '../../../../../src/pages/VisProgPage/visualProgrammingUI/nodes/BasicBeliefNode.default.ts';
|
||||
import { defaultPlan } from '../../../../../src/pages/VisProgPage/visualProgrammingUI/components/Plan.default.ts';
|
||||
import { NormNodeDefaults } from '../../../../../src/pages/VisProgPage/visualProgrammingUI/nodes/NormNode.default.ts';
|
||||
|
||||
describe('TriggerNode', () => {
|
||||
let user: ReturnType<typeof userEvent.setup>;
|
||||
|
||||
beforeEach(() => {
|
||||
user = userEvent.setup();
|
||||
jest.clearAllMocks();
|
||||
});
|
||||
|
||||
describe('Rendering', () => {
|
||||
@@ -26,11 +28,7 @@ describe('TriggerNode', () => {
|
||||
type: 'trigger',
|
||||
position: { x: 0, y: 0 },
|
||||
data: {
|
||||
label: 'Keyword Trigger',
|
||||
droppable: true,
|
||||
triggerType: 'keywords',
|
||||
triggers: [],
|
||||
hasReduce: true,
|
||||
...JSON.parse(JSON.stringify(TriggerNodeDefaults)),
|
||||
},
|
||||
};
|
||||
|
||||
@@ -51,161 +49,59 @@ describe('TriggerNode', () => {
|
||||
/>
|
||||
);
|
||||
|
||||
expect(screen.getByText(/Triggers when the keyword is spoken/i)).toBeInTheDocument();
|
||||
expect(screen.getByPlaceholderText('...')).toBeInTheDocument();
|
||||
});
|
||||
|
||||
it('should render TriggerNode with emotion type', () => {
|
||||
const mockNode: Node<TriggerNodeData> = {
|
||||
id: 'trigger-2',
|
||||
type: 'trigger',
|
||||
position: { x: 0, y: 0 },
|
||||
data: {
|
||||
label: 'Emotion Trigger',
|
||||
droppable: true,
|
||||
triggerType: 'emotion',
|
||||
triggers: [],
|
||||
hasReduce: true,
|
||||
},
|
||||
};
|
||||
|
||||
renderWithProviders(
|
||||
<TriggerNode
|
||||
id={mockNode.id}
|
||||
type={mockNode.type as string}
|
||||
data={mockNode.data as any}
|
||||
selected={false}
|
||||
isConnectable={true}
|
||||
zIndex={0}
|
||||
dragging={false}
|
||||
selectable={true}
|
||||
deletable={true}
|
||||
draggable={true}
|
||||
positionAbsoluteX={0}
|
||||
positionAbsoluteY={0}
|
||||
/>
|
||||
);
|
||||
|
||||
expect(screen.getByText(/Emotion\?/i)).toBeInTheDocument();
|
||||
});
|
||||
});
|
||||
|
||||
describe('User Interactions', () => {
|
||||
it('should add a new keyword', async () => {
|
||||
const mockNode: Node<TriggerNodeData> = {
|
||||
id: 'trigger-1',
|
||||
type: 'trigger',
|
||||
position: { x: 0, y: 0 },
|
||||
data: {
|
||||
label: 'Keyword Trigger',
|
||||
droppable: true,
|
||||
triggerType: 'keywords',
|
||||
triggers: [],
|
||||
hasReduce: true,
|
||||
},
|
||||
};
|
||||
|
||||
useFlowStore.setState({ nodes: [mockNode], edges: [] });
|
||||
|
||||
renderWithProviders(
|
||||
<TriggerNode
|
||||
id={mockNode.id}
|
||||
type={mockNode.type as string}
|
||||
data={mockNode.data as any}
|
||||
selected={false}
|
||||
isConnectable={true}
|
||||
zIndex={0}
|
||||
dragging={false}
|
||||
selectable={true}
|
||||
deletable={true}
|
||||
draggable={true}
|
||||
positionAbsoluteX={0}
|
||||
positionAbsoluteY={0}
|
||||
/>
|
||||
);
|
||||
|
||||
const input = screen.getByPlaceholderText('...');
|
||||
await user.type(input, 'hello{enter}');
|
||||
|
||||
await waitFor(() => {
|
||||
const node = useFlowStore.getState().nodes.find(n => n.id === 'trigger-1') as Node<TriggerNodeData> | undefined;
|
||||
expect(node?.data.triggers.length).toBe(1);
|
||||
expect(node?.data.triggers[0].keyword).toBe('hello');
|
||||
});
|
||||
|
||||
});
|
||||
|
||||
it('should remove a keyword when cleared', async () => {
|
||||
const mockNode: Node<TriggerNodeData> = {
|
||||
id: 'trigger-1',
|
||||
type: 'trigger',
|
||||
position: { x: 0, y: 0 },
|
||||
data: {
|
||||
label: 'Keyword Trigger',
|
||||
droppable: true,
|
||||
triggerType: 'keywords',
|
||||
triggers: [{ id: 'kw1', keyword: 'hello' }],
|
||||
hasReduce: true,
|
||||
},
|
||||
};
|
||||
|
||||
useFlowStore.setState({ nodes: [mockNode], edges: [] });
|
||||
|
||||
renderWithProviders(
|
||||
<TriggerNode
|
||||
id={mockNode.id}
|
||||
type={mockNode.type as string}
|
||||
data={mockNode.data as any}
|
||||
selected={false}
|
||||
isConnectable={true}
|
||||
zIndex={0}
|
||||
dragging={false}
|
||||
selectable={true}
|
||||
deletable={true}
|
||||
draggable={true}
|
||||
positionAbsoluteX={0}
|
||||
positionAbsoluteY={0}
|
||||
/>
|
||||
);
|
||||
|
||||
const input = screen.getByDisplayValue('hello');
|
||||
for (let i = 0; i < 'hello'.length; i++) {
|
||||
await user.type(input, '{backspace}');
|
||||
}
|
||||
await user.type(input, '{enter}');
|
||||
|
||||
await waitFor(() => {
|
||||
const node = useFlowStore.getState().nodes.find(n => n.id === 'trigger-1') as Node<TriggerNodeData> | undefined;
|
||||
expect(node?.data.triggers.length).toBe(0);
|
||||
});
|
||||
|
||||
expect(screen.getByText(/Triggers when the condition is met/i)).toBeInTheDocument();
|
||||
expect(screen.getByText(/Belief is currently/i)).toBeInTheDocument();
|
||||
expect(screen.getByText(/Plan is currently/i)).toBeInTheDocument();
|
||||
});
|
||||
});
|
||||
|
||||
describe('TriggerReduce Function', () => {
|
||||
it('should reduce a trigger node to its essential data', () => {
|
||||
const conditionNode: Node = {
|
||||
id: 'belief-1',
|
||||
type: 'basic_belief',
|
||||
position: { x: 0, y: 0 },
|
||||
data: {
|
||||
...JSON.parse(JSON.stringify(BasicBeliefNodeDefaults)),
|
||||
},
|
||||
};
|
||||
|
||||
const triggerNode: Node = {
|
||||
id: 'trigger-1',
|
||||
type: 'trigger',
|
||||
position: { x: 0, y: 0 },
|
||||
data: {
|
||||
label: 'Keyword Trigger',
|
||||
droppable: true,
|
||||
triggerType: 'keywords',
|
||||
triggers: [{ id: 'kw1', keyword: 'hello' }],
|
||||
hasReduce: true,
|
||||
...JSON.parse(JSON.stringify(TriggerNodeDefaults)),
|
||||
condition: "belief-1",
|
||||
plan: defaultPlan
|
||||
},
|
||||
};
|
||||
|
||||
const allNodes: Node[] = [triggerNode];
|
||||
const result = TriggerReduce(triggerNode, allNodes);
|
||||
useFlowStore.setState({
|
||||
nodes: [conditionNode, triggerNode],
|
||||
edges: [],
|
||||
});
|
||||
|
||||
useFlowStore.getState().onConnect({
|
||||
source: 'belief-1',
|
||||
target: 'trigger-1',
|
||||
sourceHandle: null,
|
||||
targetHandle: null,
|
||||
});
|
||||
|
||||
const result = TriggerReduce(triggerNode, useFlowStore.getState().nodes);
|
||||
|
||||
expect(result).toEqual({
|
||||
id: 'trigger-1',
|
||||
type: 'keywords',
|
||||
label: 'Keyword Trigger',
|
||||
keywords: [{ id: 'kw1', keyword: 'hello' }],
|
||||
});
|
||||
condition: {
|
||||
id: "belief-1",
|
||||
keyword: "help",
|
||||
},
|
||||
plan: {
|
||||
name: "Default Plan",
|
||||
id: expect.anything(),
|
||||
steps: [],
|
||||
},});
|
||||
});
|
||||
});
|
||||
|
||||
@@ -217,11 +113,8 @@ describe('TriggerNode', () => {
|
||||
type: 'trigger',
|
||||
position: { x: 0, y: 0 },
|
||||
data: {
|
||||
...JSON.parse(JSON.stringify(TriggerNodeDefaults)),
|
||||
label: 'Trigger 1',
|
||||
droppable: true,
|
||||
triggerType: 'keywords',
|
||||
triggers: [],
|
||||
hasReduce: true,
|
||||
},
|
||||
};
|
||||
|
||||
@@ -230,10 +123,8 @@ describe('TriggerNode', () => {
|
||||
type: 'norm',
|
||||
position: { x: 100, y: 0 },
|
||||
data: {
|
||||
...JSON.parse(JSON.stringify(NormNodeDefaults)),
|
||||
label: 'Norm 1',
|
||||
droppable: true,
|
||||
norm: 'test',
|
||||
hasReduce: true,
|
||||
},
|
||||
};
|
||||
|
||||
|
||||
@@ -187,7 +187,7 @@ describe('Universal Nodes', () => {
|
||||
// Verify the correct structure is present using NodesInPhase
|
||||
expect(result).toHaveLength(nodeType !== 'phase' ? 1 : 2);
|
||||
expect(result[0]).toHaveProperty('id', 'phase-1');
|
||||
expect(result[0]).toHaveProperty('label', 'Test Phase');
|
||||
expect(result[0]).toHaveProperty('name', 'Test Phase');
|
||||
|
||||
// Restore mocks
|
||||
phaseReduceSpy.mockRestore();
|
||||
|
||||
Reference in New Issue
Block a user