Files
alighasami 3d5eaf9445
Security: Sync from Public / sync-from-public (push) Has been cancelled
Test: Benchmark Nightly / build (push) Has been cancelled
Test: Benchmark Nightly / Notify Cats on failure (push) Has been cancelled
CI: Python / Checks (push) Has been cancelled
Test: Evals Python / Workflow Comparison Python (push) Has been cancelled
Util: Check Docs URLs / check-docs-urls (push) Has been cancelled
Test: Visual Storybook / Cloudflare Pages (push) Has been cancelled
Test: E2E Performance / build-and-test-performance (push) Has been cancelled
Test: Workflows Nightly / Run Workflow Tests (push) Has been cancelled
Util: Cleanup CI Docker Images / Delete stale CI images (push) Has been cancelled
Test: Benchmark Destroy Env / build (push) Has been cancelled
Util: Update Node Popularity / update-popularity (push) Has been cancelled
Test: E2E Coverage Weekly / Coverage Tests (push) Has been cancelled
first commit
2026-03-17 16:22:57 +03:30

98 lines
2.8 KiB
TypeScript

import type { BaseChatModel } from '@langchain/core/language_models/chat_models';
import { mock } from 'jest-mock-extended';
import type { SimpleWorkflow } from '@/types/workflow';
import { evaluateWorkflowPairwise, type PairwiseEvaluationInput } from './judge-chain';
import * as baseEvaluator from '../llm-judge/evaluators/base';
// Mock the base evaluator module
jest.mock('../llm-judge/evaluators/base', () => ({
createEvaluatorChain: jest.fn(),
invokeEvaluatorChain: jest.fn(),
}));
describe('evaluateWorkflowPairwise', () => {
const mockLlm = mock<BaseChatModel>();
const mockWorkflow: SimpleWorkflow = {
nodes: [],
connections: {},
name: 'Test Workflow',
};
const input: PairwiseEvaluationInput = {
evalCriteria: {
dos: 'Do this',
donts: "Don't do that",
},
workflowJSON: mockWorkflow,
};
beforeEach(() => {
jest.clearAllMocks();
});
it('should return structured result from invokeEvaluatorChain', async () => {
const mockResult = {
violations: [],
passes: [
{ rule: 'Do this', justification: 'Done' },
{ rule: "Don't do that", justification: 'Not done' },
],
};
jest.mocked(baseEvaluator.invokeEvaluatorChain).mockResolvedValue(mockResult);
const result = await evaluateWorkflowPairwise(mockLlm, input);
expect(result).toEqual({
...mockResult,
primaryPass: true,
diagnosticScore: 1,
});
expect(baseEvaluator.createEvaluatorChain).toHaveBeenCalledWith(
mockLlm,
expect.anything(), // schema
expect.stringContaining('expert n8n workflow auditor'), // system prompt
expect.stringContaining('<task_context>'), // human template
);
expect(baseEvaluator.invokeEvaluatorChain).toHaveBeenCalledWith(
undefined, // The chain (undefined because createEvaluatorChain mock returns undefined)
expect.objectContaining({
userPrompt: expect.stringContaining('<do>'),
generatedWorkflow: input.workflowJSON,
}),
undefined, // config parameter (not passed in this test)
);
});
it('should calculate diagnosticScore correctly with violations', async () => {
const mockResult = {
violations: [{ rule: "Don't do that", justification: 'Did it' }],
passes: [{ rule: 'Do this', justification: 'Done' }],
};
jest.mocked(baseEvaluator.invokeEvaluatorChain).mockResolvedValue(mockResult);
const result = await evaluateWorkflowPairwise(mockLlm, input);
expect(result.primaryPass).toBe(false);
expect(result.diagnosticScore).toBe(0.5);
});
it('should return diagnosticScore 0 when no rules evaluated', async () => {
const mockResult = {
violations: [],
passes: [],
};
jest.mocked(baseEvaluator.invokeEvaluatorChain).mockResolvedValue(mockResult);
const result = await evaluateWorkflowPairwise(mockLlm, input);
expect(result.primaryPass).toBe(true);
expect(result.diagnosticScore).toBe(0);
});
});