import type { InputVar } from '../types' import type { PromptVariable } from '@/models/debug' import { screen } from '@testing-library/react' import userEvent from '@testing-library/user-event' import { useNodes } from 'reactflow' import Features from '../features' import { InputVarType } from '../types' import { createStartNode } from './fixtures' import { renderWorkflowFlowComponent } from './workflow-test-env' const mockHandleAddVariable = vi.fn() const mockUpdateFeatures = vi.fn() const mockFeaturesStore = { getState: () => ({ features: { opening: { enabled: false, opening_statement: '', suggested_questions: [], }, suggested: false, text2speech: false, speech2text: false, citation: false, moderation: false, file: false, }, }), } let mockIsChatMode = true let mockNodesReadOnly = false vi.mock('../hooks', async () => { const actual = await vi.importActual('../hooks') return { ...actual, useIsChatMode: () => mockIsChatMode, useNodesReadOnly: () => ({ nodesReadOnly: mockNodesReadOnly, }), } }) vi.mock('../nodes/start/use-config', () => ({ default: () => ({ handleAddVariable: mockHandleAddVariable, }), })) vi.mock('@/service/workflow', () => ({ updateFeatures: (...args: unknown[]) => mockUpdateFeatures(...args), })) vi.mock('@/app/components/base/features/hooks', () => ({ useFeaturesStore: () => mockFeaturesStore, })) vi.mock('@/app/components/base/features/new-feature-panel', () => ({ default: ({ show, isChatMode, disabled, onChange, onClose, onAutoAddPromptVariable, workflowVariables, }: { show: boolean isChatMode: boolean disabled: boolean onChange: () => void onClose: () => void onAutoAddPromptVariable: (variables: PromptVariable[]) => void workflowVariables: InputVar[] }) => { if (!show) return null return (
{isChatMode ? 'chat mode' : 'completion mode'}
{disabled ? 'panel disabled' : 'panel enabled'}
) }, })) const startNode = createStartNode({ id: 'start-node', data: { variables: [{ variable: 'existing_variable', label: 'Existing Variable' }], }, }) const DelayedFeatures = () => { const nodes = useNodes() if (!nodes.length) return null return } const renderFeatures = (options?: Omit[1], 'nodes' | 'edges'>) => { const mergedInitialStoreState = { appId: 'app-1', ...(options?.initialStoreState || {}), } return renderWorkflowFlowComponent( , { nodes: [startNode], edges: [], ...options, initialStoreState: mergedInitialStoreState, }, ) } describe('Features', () => { beforeEach(() => { vi.clearAllMocks() mockIsChatMode = true mockNodesReadOnly = false mockUpdateFeatures.mockResolvedValue(undefined) }) describe('Rendering', () => { it('should pass workflow context to the feature panel', () => { renderFeatures() expect(screen.getByText('chat mode')).toBeInTheDocument() expect(screen.getByText('panel enabled')).toBeInTheDocument() expect(screen.getByRole('list', { name: 'workflow variables' })).toHaveTextContent('Existing Variable:existing_variable') }) }) describe('User Interactions', () => { it('should sync the draft and open the workflow feature panel when users change features', async () => { const user = userEvent.setup() const { store } = renderFeatures() await user.click(screen.getByRole('button', { name: 'open features' })) await vi.waitFor(() => { expect(mockUpdateFeatures).toHaveBeenCalledTimes(1) expect(store.getState().showFeaturesPanel).toBe(true) }) }) it('should close the workflow feature panel and transform required prompt variables', async () => { const user = userEvent.setup() const { store } = renderFeatures({ initialStoreState: { showFeaturesPanel: true, }, }) await user.click(screen.getByRole('button', { name: 'close features' })) expect(store.getState().showFeaturesPanel).toBe(false) await user.click(screen.getByRole('button', { name: 'add required variable' })) expect(mockHandleAddVariable).toHaveBeenCalledWith({ variable: 'opening_statement', label: 'Opening Statement', type: InputVarType.textInput, max_length: 200, required: true, options: [], }) }) it('should default prompt variables to optional when required is omitted', async () => { const user = userEvent.setup() renderFeatures() await user.click(screen.getByRole('button', { name: 'add optional variable' })) expect(mockHandleAddVariable).toHaveBeenCalledWith({ variable: 'optional_statement', label: 'Optional Statement', type: InputVarType.textInput, max_length: 120, required: false, options: [], }) }) }) })