llm-testrunner-components 1.1.0 → 1.2.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/LICENSE +1 -1
- package/README.md +165 -242
- package/dist/cjs/index.cjs.js +298 -232
- package/dist/cjs/index.cjs.js.map +1 -1
- package/dist/collection/components/llm-test-runner/llm-test-runner.import-export.test.js +25 -54
- package/dist/collection/components/llm-test-runner/llm-test-runner.import-export.test.js.map +1 -1
- package/dist/collection/components/llm-test-runner/llm-test-runner.js +6 -49
- package/dist/collection/components/llm-test-runner/llm-test-runner.js.map +1 -1
- package/dist/collection/components/llm-test-runner/test-cases/evaluation/evaluation-summary.css +60 -21
- package/dist/collection/components/llm-test-runner/test-cases/evaluation/evaluation-summary.js +3 -1
- package/dist/collection/components/llm-test-runner/test-cases/evaluation/evaluation-summary.js.map +1 -1
- package/dist/collection/components/llm-test-runner/test-cases/expected-outcome-renderer.js +31 -11
- package/dist/collection/components/llm-test-runner/test-cases/expected-outcome-renderer.js.map +1 -1
- package/dist/collection/components/llm-test-runner/test-cases/llm-test-case-row.css +17 -0
- package/dist/collection/components/llm-test-runner/test-cases/llm-test-case-row.js +2 -12
- package/dist/collection/components/llm-test-runner/test-cases/llm-test-case-row.js.map +1 -1
- package/dist/collection/components/llm-test-runner/test-cases/llm-test-cases.js +2 -2
- package/dist/collection/components/llm-test-runner/test-cases/llm-test-cases.js.map +1 -1
- package/dist/collection/lib/evaluation/evaluation-engine.js +63 -42
- package/dist/collection/lib/evaluation/evaluation-engine.js.map +1 -1
- package/dist/collection/lib/evaluation/evaluation-service.js +15 -3
- package/dist/collection/lib/evaluation/evaluation-service.js.map +1 -1
- package/dist/collection/lib/evaluation/{rouge1-evaluator.test.js → evaluators/rouge1-evaluator.test.js} +2 -2
- package/dist/collection/lib/evaluation/evaluators/rouge1-evaluator.test.js.map +1 -0
- package/dist/collection/lib/evaluation/field-evaluation-approach.js +24 -0
- package/dist/collection/lib/evaluation/field-evaluation-approach.js.map +1 -0
- package/dist/collection/lib/evaluation/index.js +0 -4
- package/dist/collection/lib/evaluation/index.js.map +1 -1
- package/dist/collection/lib/evaluation/types.js.map +1 -1
- package/dist/collection/lib/import-export/test-results-csv.js +47 -33
- package/dist/collection/lib/import-export/test-results-csv.js.map +1 -1
- package/dist/collection/lib/import-export/test-suite-exporter.js +0 -1
- package/dist/collection/lib/import-export/test-suite-exporter.js.map +1 -1
- package/dist/collection/lib/test-cases/test-case-factory.js +17 -27
- package/dist/collection/lib/test-cases/test-case-factory.js.map +1 -1
- package/dist/collection/lib/test-cases/test-case-mutations.js +60 -9
- package/dist/collection/lib/test-cases/test-case-mutations.js.map +1 -1
- package/dist/collection/schemas/expected-outcome.js +20 -2
- package/dist/collection/schemas/expected-outcome.js.map +1 -1
- package/dist/collection/schemas/test-case.js +2 -20
- package/dist/collection/schemas/test-case.js.map +1 -1
- package/dist/collection/types/llm-test-runner.js.map +1 -1
- package/dist/collection/types/test-case.js.map +1 -1
- package/dist/components/index.js +1 -1
- package/dist/components/llm-test-runner.js +1 -1
- package/dist/components/p-Bb89MYYu.js +7 -0
- package/dist/components/p-Bb89MYYu.js.map +1 -0
- package/dist/esm/index.js +298 -232
- package/dist/esm/index.js.map +1 -1
- package/dist/llm-testrunner/index.esm.js +2 -2
- package/dist/llm-testrunner/index.esm.js.map +1 -1
- package/dist/types/components/llm-test-runner/llm-test-runner.d.ts +0 -1
- package/dist/types/components/llm-test-runner/test-cases/expected-outcome-renderer.d.ts +3 -6
- package/dist/types/components/llm-test-runner/test-cases/llm-test-case-row.d.ts +0 -2
- package/dist/types/components/llm-test-runner/test-cases/llm-test-cases.d.ts +0 -2
- package/dist/types/lib/evaluation/evaluation-engine.d.ts +4 -2
- package/dist/types/lib/evaluation/field-evaluation-approach.d.ts +6 -0
- package/dist/types/lib/evaluation/index.d.ts +0 -1
- package/dist/types/lib/evaluation/types.d.ts +26 -0
- package/dist/types/lib/import-export/test-suite-exporter.d.ts +0 -4
- package/dist/types/lib/test-cases/test-case-factory.d.ts +2 -3
- package/dist/types/lib/test-cases/test-case-mutations.d.ts +21 -5
- package/dist/types/schemas/expected-outcome.d.ts +65 -17
- package/dist/types/schemas/test-case.d.ts +51 -95
- package/dist/types/types/llm-test-runner.d.ts +1 -1
- package/dist/types/types/test-case.d.ts +1 -1
- package/package.json +9 -2
- package/dist/collection/lib/evaluation/rouge1-evaluator.test.js.map +0 -1
- package/dist/components/p-BF90yb1z.js +0 -7
- package/dist/components/p-BF90yb1z.js.map +0 -1
- /package/dist/types/lib/evaluation/{rouge1-evaluator.test.d.ts → evaluators/rouge1-evaluator.test.d.ts} +0 -0
|
@@ -8,14 +8,13 @@ jest.mock('../../lib/file/file-reader');
|
|
|
8
8
|
jest.mock('../../lib/file/file-download');
|
|
9
9
|
jest.mock('../../lib/import-export/test-suite-exporter');
|
|
10
10
|
jest.mock('../../lib/import-export/test-suite-importer');
|
|
11
|
-
import { h } from "@stencil/core";
|
|
12
11
|
import { newSpecPage } from "@stencil/core/testing";
|
|
13
12
|
import { LLMTestRunner } from "./llm-test-runner";
|
|
14
|
-
import { EvaluationApproach } from "../../lib/evaluation/constants";
|
|
15
13
|
import { readFileAsync } from "../../lib/file/file-reader";
|
|
16
14
|
import { downloadFile } from "../../lib/file/file-download";
|
|
17
15
|
import { formatTestSuiteAsJson } from "../../lib/import-export/test-suite-exporter";
|
|
18
16
|
import { importTestSuite } from "../../lib/import-export/test-suite-importer";
|
|
17
|
+
import { EvaluationApproach } from "../../lib/evaluation/constants";
|
|
19
18
|
describe('llm-test-runner import/export', () => {
|
|
20
19
|
let page;
|
|
21
20
|
let component;
|
|
@@ -31,19 +30,11 @@ describe('llm-test-runner import/export', () => {
|
|
|
31
30
|
id: '1',
|
|
32
31
|
question: 'What is AI?',
|
|
33
32
|
expectedOutcome: buildExpectedOutcome('artificial intelligence'),
|
|
34
|
-
evaluationParameters: {
|
|
35
|
-
approach: EvaluationApproach.EXACT,
|
|
36
|
-
threshold: 0.6
|
|
37
|
-
},
|
|
38
33
|
isRunning: false
|
|
39
34
|
};
|
|
40
35
|
return {
|
|
41
36
|
...defaults,
|
|
42
37
|
...overrides,
|
|
43
|
-
evaluationParameters: {
|
|
44
|
-
...defaults.evaluationParameters,
|
|
45
|
-
...overrides.evaluationParameters,
|
|
46
|
-
},
|
|
47
38
|
};
|
|
48
39
|
};
|
|
49
40
|
const createMockFile = (content, filename, type = 'application/json') => {
|
|
@@ -65,7 +56,6 @@ describe('llm-test-runner import/export', () => {
|
|
|
65
56
|
id: '1',
|
|
66
57
|
question: 'What is AI?',
|
|
67
58
|
expectedOutcome: buildExpectedOutcome('artificial intelligence'),
|
|
68
|
-
evaluationParameters: { approach: EvaluationApproach.EXACT, threshold: 0.6 },
|
|
69
59
|
isRunning: false
|
|
70
60
|
}
|
|
71
61
|
];
|
|
@@ -86,27 +76,42 @@ describe('llm-test-runner import/export', () => {
|
|
|
86
76
|
});
|
|
87
77
|
});
|
|
88
78
|
it('should use default evaluation parameters when not provided', async () => {
|
|
89
|
-
const
|
|
79
|
+
const rawImportData = [
|
|
90
80
|
{
|
|
91
81
|
id: '1',
|
|
92
82
|
question: 'Test question',
|
|
93
83
|
expectedOutcome: buildExpectedOutcome('test'),
|
|
94
|
-
evaluationParameters: { approach: EvaluationApproach.EXACT, threshold: 0.6 },
|
|
95
84
|
isRunning: false
|
|
96
85
|
}
|
|
97
86
|
];
|
|
98
|
-
const
|
|
99
|
-
|
|
87
|
+
const normalizedImportData = [
|
|
88
|
+
{
|
|
89
|
+
id: '1',
|
|
90
|
+
question: 'Test question',
|
|
91
|
+
expectedOutcome: [
|
|
92
|
+
{
|
|
93
|
+
type: 'textarea',
|
|
94
|
+
label: 'Expected Outcome',
|
|
95
|
+
value: 'test',
|
|
96
|
+
evaluationParameters: {
|
|
97
|
+
approach: EvaluationApproach.EXACT,
|
|
98
|
+
},
|
|
99
|
+
},
|
|
100
|
+
],
|
|
101
|
+
isRunning: false,
|
|
102
|
+
},
|
|
103
|
+
];
|
|
104
|
+
const mockFile = createMockFile(JSON.stringify(rawImportData), 'test.json');
|
|
105
|
+
readFileAsync.mockResolvedValue(JSON.stringify(rawImportData));
|
|
100
106
|
importTestSuite.mockReturnValue({
|
|
101
107
|
success: true,
|
|
102
|
-
testCases:
|
|
108
|
+
testCases: normalizedImportData,
|
|
103
109
|
});
|
|
104
110
|
await component.handleImport(mockFile);
|
|
105
111
|
await page.waitForChanges();
|
|
106
|
-
expect(component.testCases[0].evaluationParameters).
|
|
107
|
-
|
|
108
|
-
|
|
109
|
-
});
|
|
112
|
+
expect(component.testCases[0].expectedOutcome[0].evaluationParameters?.approach).toBe(EvaluationApproach.EXACT);
|
|
113
|
+
expect(component.testCases[0].expectedOutcome[0].value).toBe('test');
|
|
114
|
+
expect(component.testCases[0].expectedOutcome[0].label).toBe('Expected Outcome');
|
|
110
115
|
});
|
|
111
116
|
});
|
|
112
117
|
describe('File Import - Multiple Test Cases', () => {
|
|
@@ -116,14 +121,12 @@ describe('llm-test-runner import/export', () => {
|
|
|
116
121
|
id: '1',
|
|
117
122
|
question: 'What is AI?',
|
|
118
123
|
expectedOutcome: buildExpectedOutcome('artificial intelligence'),
|
|
119
|
-
evaluationParameters: { approach: EvaluationApproach.EXACT },
|
|
120
124
|
isRunning: false
|
|
121
125
|
},
|
|
122
126
|
{
|
|
123
127
|
id: '2',
|
|
124
128
|
question: 'What is ML?',
|
|
125
129
|
expectedOutcome: buildExpectedOutcome('machine learning'),
|
|
126
|
-
evaluationParameters: { approach: EvaluationApproach.EXACT },
|
|
127
130
|
isRunning: false
|
|
128
131
|
}
|
|
129
132
|
];
|
|
@@ -145,21 +148,18 @@ describe('llm-test-runner import/export', () => {
|
|
|
145
148
|
id: '1',
|
|
146
149
|
question: 'Q1',
|
|
147
150
|
expectedOutcome: buildExpectedOutcome('answer1'),
|
|
148
|
-
evaluationParameters: { approach: EvaluationApproach.EXACT },
|
|
149
151
|
isRunning: false
|
|
150
152
|
},
|
|
151
153
|
{
|
|
152
154
|
id: '2',
|
|
153
155
|
question: 'Q2',
|
|
154
156
|
expectedOutcome: buildExpectedOutcome('answer2'),
|
|
155
|
-
evaluationParameters: { approach: EvaluationApproach.EXACT },
|
|
156
157
|
isRunning: false
|
|
157
158
|
},
|
|
158
159
|
{
|
|
159
160
|
id: '3',
|
|
160
161
|
question: 'Q3',
|
|
161
162
|
expectedOutcome: buildExpectedOutcome('answer3'),
|
|
162
|
-
evaluationParameters: { approach: EvaluationApproach.EXACT },
|
|
163
163
|
isRunning: false
|
|
164
164
|
}
|
|
165
165
|
];
|
|
@@ -257,34 +257,5 @@ describe('llm-test-runner import/export', () => {
|
|
|
257
257
|
expect(component.error).toBe('');
|
|
258
258
|
});
|
|
259
259
|
});
|
|
260
|
-
describe('Initial Test Cases', () => {
|
|
261
|
-
it('should normalize legacy string expectedOutcome from initialTestCases', async () => {
|
|
262
|
-
const legacyInitialCases = [
|
|
263
|
-
{
|
|
264
|
-
id: 'legacy-1',
|
|
265
|
-
question: 'Whats capital of India ?',
|
|
266
|
-
expectedOutcome: 'Delhi',
|
|
267
|
-
evaluationParameters: { approach: EvaluationApproach.EXACT },
|
|
268
|
-
},
|
|
269
|
-
];
|
|
270
|
-
const localPage = await newSpecPage({
|
|
271
|
-
components: [LLMTestRunner],
|
|
272
|
-
template: () => h('llm-test-runner', {
|
|
273
|
-
initialTestCases: legacyInitialCases,
|
|
274
|
-
}),
|
|
275
|
-
});
|
|
276
|
-
const localComponent = localPage.rootInstance;
|
|
277
|
-
await localPage.waitForChanges();
|
|
278
|
-
expect(localComponent.testCases).toHaveLength(1);
|
|
279
|
-
expect(localComponent.testCases[0].id).toBe('legacy-1');
|
|
280
|
-
expect(localComponent.testCases[0].expectedOutcome).toEqual([
|
|
281
|
-
{
|
|
282
|
-
type: 'textarea',
|
|
283
|
-
label: 'Expected Outcome',
|
|
284
|
-
value: 'Delhi',
|
|
285
|
-
},
|
|
286
|
-
]);
|
|
287
|
-
});
|
|
288
|
-
});
|
|
289
260
|
});
|
|
290
261
|
//# sourceMappingURL=llm-test-runner.import-export.test.js.map
|
package/dist/collection/components/llm-test-runner/llm-test-runner.import-export.test.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"llm-test-runner.import-export.test.js","sourceRoot":"","sources":["../../../src/components/llm-test-runner/llm-test-runner.import-export.test.ts"],"names":[],"mappings":"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","sourcesContent":["/* eslint-env jest */\n\njest.mock('../../lib/evaluation/evaluation-engine', () => ({\n LLMEvaluationEngine: jest.fn().mockImplementation(() => ({\n evaluateResponse: jest.fn()\n }))\n}));\n\njest.mock('../../lib/file/file-reader');\njest.mock('../../lib/file/file-download');\njest.mock('../../lib/import-export/test-suite-exporter');\njest.mock('../../lib/import-export/test-suite-importer');\n\nimport { h } from '@stencil/core';\nimport { newSpecPage, SpecPage } from '@stencil/core/testing';\nimport { LLMTestRunner } from './llm-test-runner';\nimport { TestCase, TestCaseInput } from '../../types/llm-test-runner';\nimport { EvaluationApproach } from '../../lib/evaluation/constants';\nimport { readFileAsync } from '../../lib/file/file-reader';\nimport { downloadFile } from '../../lib/file/file-download';\nimport { formatTestSuiteAsJson } from '../../lib/import-export/test-suite-exporter';\nimport { importTestSuite } from '../../lib/import-export/test-suite-importer';\n\ndescribe('llm-test-runner import/export', () => {\n let page: SpecPage;\n let component: any;\n const buildExpectedOutcome = (value: string) => [\n {\n type: 'textarea' as const,\n label: 'Expected Outcome',\n value,\n },\n ];\n\n const createMockTestCase = (overrides: Partial<TestCase> = {}): TestCase => {\n const defaults: TestCase = {\n id: '1',\n question: 'What is AI?',\n expectedOutcome: buildExpectedOutcome('artificial intelligence'),\n evaluationParameters: {\n approach: EvaluationApproach.EXACT,\n threshold: 0.6\n },\n isRunning: false\n };\n\n return {\n ...defaults,\n ...overrides,\n evaluationParameters: {\n ...defaults.evaluationParameters,\n ...overrides.evaluationParameters,\n },\n };\n };\n\n const createMockFile = (content: string, filename: string, type: string = 'application/json'): File => {\n return new File([content], filename, { type });\n };\n\n beforeEach(async () => {\n jest.clearAllMocks();\n \n page = await newSpecPage({\n components: [LLMTestRunner],\n html: '<llm-test-runner></llm-test-runner>',\n });\n component = page.rootInstance;\n \n await page.waitForChanges();\n });\n\n describe('File Import - Basic Functionality', () => {\n it('should import valid test cases structure', async () => {\n const mockTestData = [\n {\n id: '1',\n question: 'What is AI?',\n expectedOutcome: buildExpectedOutcome('artificial intelligence'),\n evaluationParameters: { approach: EvaluationApproach.EXACT, threshold: 0.6 },\n isRunning: false\n }\n ];\n\n const mockFile = createMockFile(JSON.stringify(mockTestData), 'test-suite.json');\n\n // Mock the utility functions\n (readFileAsync as jest.Mock).mockResolvedValue(JSON.stringify(mockTestData));\n (importTestSuite as jest.Mock).mockReturnValue({\n success: true,\n testCases: mockTestData\n });\n\n await component.handleImport(mockFile);\n await page.waitForChanges();\n\n expect(component.testCases).toHaveLength(1);\n expect(component.testCases[0]).toMatchObject({\n id: '1',\n question: 'What is AI?',\n expectedOutcome: buildExpectedOutcome('artificial intelligence'),\n });\n });\n\n it('should use default evaluation parameters when not provided', async () => {\n const mockTestData = [\n {\n id: '1',\n question: 'Test question',\n expectedOutcome: buildExpectedOutcome('test'),\n evaluationParameters: { approach: EvaluationApproach.EXACT, threshold: 0.6 },\n isRunning: false\n }\n ];\n\n const mockFile = createMockFile(JSON.stringify(mockTestData), 'test.json');\n\n (readFileAsync as jest.Mock).mockResolvedValue(JSON.stringify(mockTestData));\n (importTestSuite as jest.Mock).mockReturnValue({\n success: true,\n testCases: mockTestData\n });\n\n await component.handleImport(mockFile);\n await page.waitForChanges();\n\n expect(component.testCases[0].evaluationParameters).toMatchObject({\n approach: EvaluationApproach.EXACT,\n threshold: 0.6\n });\n });\n });\n\n describe('File Import - Multiple Test Cases', () => {\n it('should import multiple test cases successfully', async () => {\n const mockTestData = [\n {\n id: '1',\n question: 'What is AI?',\n expectedOutcome: buildExpectedOutcome('artificial intelligence'),\n evaluationParameters: { approach: EvaluationApproach.EXACT },\n isRunning: false\n },\n {\n id: '2',\n question: 'What is ML?',\n expectedOutcome: buildExpectedOutcome('machine learning'),\n evaluationParameters: { approach: EvaluationApproach.EXACT },\n isRunning: false\n }\n ];\n\n const mockFile = createMockFile(JSON.stringify(mockTestData), 'test.json');\n\n (readFileAsync as jest.Mock).mockResolvedValue(JSON.stringify(mockTestData));\n (importTestSuite as jest.Mock).mockReturnValue({\n success: true,\n testCases: mockTestData\n });\n\n await component.handleImport(mockFile);\n await page.waitForChanges();\n\n expect(component.testCases).toHaveLength(2);\n expect(component.testCases[0].question).toBe('What is AI?');\n expect(component.testCases[1].question).toBe('What is ML?');\n });\n\n it('should handle unique IDs for imported test cases', async () => {\n const mockTestData = [\n {\n id: '1',\n question: 'Q1',\n expectedOutcome: buildExpectedOutcome('answer1'),\n evaluationParameters: { approach: EvaluationApproach.EXACT },\n isRunning: false\n },\n {\n id: '2',\n question: 'Q2',\n expectedOutcome: buildExpectedOutcome('answer2'),\n evaluationParameters: { approach: EvaluationApproach.EXACT },\n isRunning: false\n },\n {\n id: '3',\n question: 'Q3',\n expectedOutcome: buildExpectedOutcome('answer3'),\n evaluationParameters: { approach: EvaluationApproach.EXACT },\n isRunning: false\n }\n ];\n\n const mockFile = createMockFile(JSON.stringify(mockTestData), 'test.json');\n\n (readFileAsync as jest.Mock).mockResolvedValue(JSON.stringify(mockTestData));\n (importTestSuite as jest.Mock).mockReturnValue({\n success: true,\n testCases: mockTestData\n });\n\n await component.handleImport(mockFile);\n await page.waitForChanges();\n\n const ids = component.testCases.map((tc: TestCase) => tc.id);\n expect(new Set(ids).size).toBe(ids.length);\n });\n });\n\n describe('File Import - Error Handling', () => {\n it('should reject non-JSON file type', async () => {\n const mockFile = createMockFile('some content', 'test.txt', 'text/plain');\n\n await component.handleImport(mockFile);\n await page.waitForChanges();\n\n expect(component.error).toBe('Invalid file type. Please select a JSON file.');\n });\n\n it('should handle import failure from utility', async () => {\n const mockFile = createMockFile('{}', 'test.json');\n\n (readFileAsync as jest.Mock).mockResolvedValue('{}');\n (importTestSuite as jest.Mock).mockReturnValue({\n success: false,\n error: 'Invalid JSON structure. Expected a JSON array.'\n });\n\n await component.handleImport(mockFile);\n await page.waitForChanges();\n\n expect(component.error).toContain('Invalid JSON structure');\n });\n\n it('should handle file read errors', async () => {\n const mockFile = createMockFile('{}', 'test.json');\n\n (readFileAsync as jest.Mock).mockRejectedValue(new Error('Failed to read file'));\n\n await component.handleImport(mockFile);\n await page.waitForChanges();\n\n expect(component.error).toBeTruthy();\n });\n });\n\n describe('Export Test Suite', () => {\n it('should export test suite with correct structure', async () => {\n component.testCases = [createMockTestCase()];\n\n const mockJsonContent = JSON.stringify([createMockTestCase()]);\n (formatTestSuiteAsJson as jest.Mock).mockReturnValue(mockJsonContent);\n (downloadFile as jest.Mock).mockImplementation(() => {});\n\n await component.handleExportTestSuite();\n await page.waitForChanges();\n\n expect(formatTestSuiteAsJson).toHaveBeenCalledWith(component.testCases);\n expect(downloadFile).toHaveBeenCalledWith(\n mockJsonContent,\n 'test-suite.json',\n 'application/json'\n );\n });\n\n it('should handle exporting state', async () => {\n component.testCases = [createMockTestCase()];\n\n (formatTestSuiteAsJson as jest.Mock).mockReturnValue('[]');\n (downloadFile as jest.Mock).mockImplementation(() => {});\n\n expect(component.isExportingTestSuite).toBe(false);\n\n const exportPromise = component.handleExportTestSuite();\n \n // During export\n await page.waitForChanges();\n\n // After export completes\n await exportPromise;\n await page.waitForChanges();\n\n expect(component.isExportingTestSuite).toBe(false);\n });\n\n it('should export multiple test cases', async () => {\n const testCases = [\n createMockTestCase({ id: '1', question: 'Q1' }),\n createMockTestCase({ id: '2', question: 'Q2' }),\n createMockTestCase({ id: '3', question: 'Q3' })\n ];\n\n component.testCases = testCases;\n\n (formatTestSuiteAsJson as jest.Mock).mockReturnValue(JSON.stringify(testCases));\n (downloadFile as jest.Mock).mockImplementation(() => {});\n\n await component.handleExportTestSuite();\n await page.waitForChanges();\n\n expect(formatTestSuiteAsJson).toHaveBeenCalledWith(testCases);\n });\n });\n\n describe('Component State Management', () => {\n it('should maintain test cases state', () => {\n expect(component.testCases).toBeDefined();\n expect(Array.isArray(component.testCases)).toBe(true);\n });\n\n it('should maintain error state', () => {\n expect(component.error).toBeDefined();\n expect(typeof component.error).toBe('string');\n });\n\n it('should clear errors', async () => {\n component.error = 'Test error';\n await page.waitForChanges();\n\n expect(component.error).toBe('Test error');\n\n component.error = '';\n await page.waitForChanges();\n\n expect(component.error).toBe('');\n });\n });\n\n describe('Initial Test Cases', () => {\n it('should normalize legacy string expectedOutcome from initialTestCases', async () => {\n const legacyInitialCases = [\n {\n id: 'legacy-1',\n question: 'Whats capital of India ?',\n expectedOutcome: 'Delhi',\n evaluationParameters: { approach: EvaluationApproach.EXACT },\n },\n ] as unknown as TestCase[];\n\n const localPage = await newSpecPage({\n components: [LLMTestRunner],\n template: () =>\n h('llm-test-runner', {\n initialTestCases: legacyInitialCases as TestCaseInput[],\n }),\n });\n\n const localComponent = localPage.rootInstance as LLMTestRunner;\n await localPage.waitForChanges();\n\n expect(localComponent.testCases).toHaveLength(1);\n expect(localComponent.testCases[0].id).toBe('legacy-1');\n expect(localComponent.testCases[0].expectedOutcome).toEqual([\n {\n type: 'textarea',\n label: 'Expected Outcome',\n value: 'Delhi',\n },\n ]);\n });\n });\n});"]}
|
|
1
|
+
{"version":3,"file":"llm-test-runner.import-export.test.js","sourceRoot":"","sources":["../../../src/components/llm-test-runner/llm-test-runner.import-export.test.ts"],"names":[],"mappings":"AAAA,qBAAqB;AAErB,IAAI,CAAC,IAAI,CAAC,wCAAwC,EAAE,GAAG,EAAE,CAAC,CAAC;IACzD,mBAAmB,EAAE,IAAI,CAAC,EAAE,EAAE,CAAC,kBAAkB,CAAC,GAAG,EAAE,CAAC,CAAC;QACvD,gBAAgB,EAAE,IAAI,CAAC,EAAE,EAAE;KAC5B,CAAC,CAAC;CACJ,CAAC,CAAC,CAAC;AAEJ,IAAI,CAAC,IAAI,CAAC,4BAA4B,CAAC,CAAC;AACxC,IAAI,CAAC,IAAI,CAAC,8BAA8B,CAAC,CAAC;AAC1C,IAAI,CAAC,IAAI,CAAC,6CAA6C,CAAC,CAAC;AACzD,IAAI,CAAC,IAAI,CAAC,6CAA6C,CAAC,CAAC;AAEzD,OAAO,EAAE,WAAW,EAAY,MAAM,uBAAuB,CAAC;AAC9D,OAAO,EAAE,aAAa,EAAE,MAAM,mBAAmB,CAAC;AAElD,OAAO,EAAE,aAAa,EAAE,MAAM,4BAA4B,CAAC;AAC3D,OAAO,EAAE,YAAY,EAAE,MAAM,8BAA8B,CAAC;AAC5D,OAAO,EAAE,qBAAqB,EAAE,MAAM,6CAA6C,CAAC;AACpF,OAAO,EAAE,eAAe,EAAE,MAAM,6CAA6C,CAAC;AAC9E,OAAO,EAAE,kBAAkB,EAAE,MAAM,gCAAgC,CAAC;AAEpE,QAAQ,CAAC,+BAA+B,EAAE,GAAG,EAAE;IAC7C,IAAI,IAAc,CAAC;IACnB,IAAI,SAAc,CAAC;IACnB,MAAM,oBAAoB,GAAG,CAAC,KAAa,EAAE,EAAE,CAAC;QAC9C;YACE,IAAI,EAAE,UAAmB;YACzB,KAAK,EAAE,kBAAkB;YACzB,KAAK;SACN;KACF,CAAC;IAEF,MAAM,kBAAkB,GAAG,CAAC,YAA+B,EAAE,EAAY,EAAE;QACzE,MAAM,QAAQ,GAAa;YACzB,EAAE,EAAE,GAAG;YACP,QAAQ,EAAE,aAAa;YACvB,eAAe,EAAE,oBAAoB,CAAC,yBAAyB,CAAC;YAChE,SAAS,EAAE,KAAK;SACjB,CAAC;QAEF,OAAO;YACL,GAAG,QAAQ;YACX,GAAG,SAAS;SACb,CAAC;IACJ,CAAC,CAAC;IAEF,MAAM,cAAc,GAAG,CAAC,OAAe,EAAE,QAAgB,EAAE,OAAe,kBAAkB,EAAQ,EAAE;QACpG,OAAO,IAAI,IAAI,CAAC,CAAC,OAAO,CAAC,EAAE,QAAQ,EAAE,EAAE,IAAI,EAAE,CAAC,CAAC;IACjD,CAAC,CAAC;IAEF,UAAU,CAAC,KAAK,IAAI,EAAE;QACpB,IAAI,CAAC,aAAa,EAAE,CAAC;QAErB,IAAI,GAAG,MAAM,WAAW,CAAC;YACvB,UAAU,EAAE,CAAC,aAAa,CAAC;YAC3B,IAAI,EAAE,qCAAqC;SAC5C,CAAC,CAAC;QACH,SAAS,GAAG,IAAI,CAAC,YAAY,CAAC;QAE9B,MAAM,IAAI,CAAC,cAAc,EAAE,CAAC;IAC9B,CAAC,CAAC,CAAC;IAEH,QAAQ,CAAC,mCAAmC,EAAE,GAAG,EAAE;QACjD,EAAE,CAAC,0CAA0C,EAAE,KAAK,IAAI,EAAE;YACxD,MAAM,YAAY,GAAG;gBACnB;oBACE,EAAE,EAAE,GAAG;oBACP,QAAQ,EAAE,aAAa;oBACvB,eAAe,EAAE,oBAAoB,CAAC,yBAAyB,CAAC;oBAChE,SAAS,EAAE,KAAK;iBACjB;aACF,CAAC;YAEF,MAAM,QAAQ,GAAG,cAAc,CAAC,IAAI,CAAC,SAAS,CAAC,YAAY,CAAC,EAAE,iBAAiB,CAAC,CAAC;YAEjF,6BAA6B;YAC5B,aAA2B,CAAC,iBAAiB,CAAC,IAAI,CAAC,SAAS,CAAC,YAAY,CAAC,CAAC,CAAC;YAC5E,eAA6B,CAAC,eAAe,CAAC;gBAC7C,OAAO,EAAE,IAAI;gBACb,SAAS,EAAE,YAAY;aACxB,CAAC,CAAC;YAEH,MAAM,SAAS,CAAC,YAAY,CAAC,QAAQ,CAAC,CAAC;YACvC,MAAM,IAAI,CAAC,cAAc,EAAE,CAAC;YAE5B,MAAM,CAAC,SAAS,CAAC,SAAS,CAAC,CAAC,YAAY,CAAC,CAAC,CAAC,CAAC;YAC5C,MAAM,CAAC,SAAS,CAAC,SAAS,CAAC,CAAC,CAAC,CAAC,CAAC,aAAa,CAAC;gBAC3C,EAAE,EAAE,GAAG;gBACP,QAAQ,EAAE,aAAa;gBACvB,eAAe,EAAE,oBAAoB,CAAC,yBAAyB,CAAC;aACjE,CAAC,CAAC;QACL,CAAC,CAAC,CAAC;QAEH,EAAE,CAAC,4DAA4D,EAAE,KAAK,IAAI,EAAE;YAC1E,MAAM,aAAa,GAAG;gBACpB;oBACE,EAAE,EAAE,GAAG;oBACP,QAAQ,EAAE,eAAe;oBACzB,eAAe,EAAE,oBAAoB,CAAC,MAAM,CAAC;oBAC7C,SAAS,EAAE,KAAK;iBACjB;aACF,CAAC;YACF,MAAM,oBAAoB,GAAG;gBAC3B;oBACE,EAAE,EAAE,GAAG;oBACP,QAAQ,EAAE,eAAe;oBACzB,eAAe,EAAE;wBACf;4BACE,IAAI,EAAE,UAAmB;4BACzB,KAAK,EAAE,kBAAkB;4BACzB,KAAK,EAAE,MAAM;4BACb,oBAAoB,EAAE;gCACpB,QAAQ,EAAE,kBAAkB,CAAC,KAAK;6BACnC;yBACF;qBACF;oBACD,SAAS,EAAE,KAAK;iBACjB;aACF,CAAC;YAEF,MAAM,QAAQ,GAAG,cAAc,CAAC,IAAI,CAAC,SAAS,CAAC,aAAa,CAAC,EAAE,WAAW,CAAC,CAAC;YAE3E,aAA2B,CAAC,iBAAiB,CAAC,IAAI,CAAC,SAAS,CAAC,aAAa,CAAC,CAAC,CAAC;YAC7E,eAA6B,CAAC,eAAe,CAAC;gBAC7C,OAAO,EAAE,IAAI;gBACb,SAAS,EAAE,oBAAoB;aAChC,CAAC,CAAC;YAEH,MAAM,SAAS,CAAC,YAAY,CAAC,QAAQ,CAAC,CAAC;YACvC,MAAM,IAAI,CAAC,cAAc,EAAE,CAAC;YAE5B,MAAM,CACJ,SAAS,CAAC,SAAS,CAAC,CAAC,CAAC,CAAC,eAAe,CAAC,CAAC,CAAC,CAAC,oBAAoB,EAAE,QAAQ,CACzE,CAAC,IAAI,CAAC,kBAAkB,CAAC,KAAK,CAAC,CAAC;YACjC,MAAM,CAAC,SAAS,CAAC,SAAS,CAAC,CAAC,CAAC,CAAC,eAAe,CAAC,CAAC,CAAC,CAAC,KAAK,CAAC,CAAC,IAAI,CAAC,MAAM,CAAC,CAAC;YACrE,MAAM,CAAC,SAAS,CAAC,SAAS,CAAC,CAAC,CAAC,CAAC,eAAe,CAAC,CAAC,CAAC,CAAC,KAAK,CAAC,CAAC,IAAI,CAC1D,kBAAkB,CACnB,CAAC;QACJ,CAAC,CAAC,CAAC;IACL,CAAC,CAAC,CAAC;IAEH,QAAQ,CAAC,mCAAmC,EAAE,GAAG,EAAE;QACjD,EAAE,CAAC,gDAAgD,EAAE,KAAK,IAAI,EAAE;YAC9D,MAAM,YAAY,GAAG;gBACnB;oBACE,EAAE,EAAE,GAAG;oBACP,QAAQ,EAAE,aAAa;oBACvB,eAAe,EAAE,oBAAoB,CAAC,yBAAyB,CAAC;oBAChE,SAAS,EAAE,KAAK;iBACjB;gBACD;oBACE,EAAE,EAAE,GAAG;oBACP,QAAQ,EAAE,aAAa;oBACvB,eAAe,EAAE,oBAAoB,CAAC,kBAAkB,CAAC;oBACzD,SAAS,EAAE,KAAK;iBACjB;aACF,CAAC;YAEF,MAAM,QAAQ,GAAG,cAAc,CAAC,IAAI,CAAC,SAAS,CAAC,YAAY,CAAC,EAAE,WAAW,CAAC,CAAC;YAE1E,aAA2B,CAAC,iBAAiB,CAAC,IAAI,CAAC,SAAS,CAAC,YAAY,CAAC,CAAC,CAAC;YAC5E,eAA6B,CAAC,eAAe,CAAC;gBAC7C,OAAO,EAAE,IAAI;gBACb,SAAS,EAAE,YAAY;aACxB,CAAC,CAAC;YAEH,MAAM,SAAS,CAAC,YAAY,CAAC,QAAQ,CAAC,CAAC;YACvC,MAAM,IAAI,CAAC,cAAc,EAAE,CAAC;YAE5B,MAAM,CAAC,SAAS,CAAC,SAAS,CAAC,CAAC,YAAY,CAAC,CAAC,CAAC,CAAC;YAC5C,MAAM,CAAC,SAAS,CAAC,SAAS,CAAC,CAAC,CAAC,CAAC,QAAQ,CAAC,CAAC,IAAI,CAAC,aAAa,CAAC,CAAC;YAC5D,MAAM,CAAC,SAAS,CAAC,SAAS,CAAC,CAAC,CAAC,CAAC,QAAQ,CAAC,CAAC,IAAI,CAAC,aAAa,CAAC,CAAC;QAC9D,CAAC,CAAC,CAAC;QAEH,EAAE,CAAC,kDAAkD,EAAE,KAAK,IAAI,EAAE;YAChE,MAAM,YAAY,GAAG;gBACnB;oBACE,EAAE,EAAE,GAAG;oBACP,QAAQ,EAAE,IAAI;oBACd,eAAe,EAAE,oBAAoB,CAAC,SAAS,CAAC;oBAChD,SAAS,EAAE,KAAK;iBACjB;gBACD;oBACE,EAAE,EAAE,GAAG;oBACP,QAAQ,EAAE,IAAI;oBACd,eAAe,EAAE,oBAAoB,CAAC,SAAS,CAAC;oBAChD,SAAS,EAAE,KAAK;iBACjB;gBACD;oBACE,EAAE,EAAE,GAAG;oBACP,QAAQ,EAAE,IAAI;oBACd,eAAe,EAAE,oBAAoB,CAAC,SAAS,CAAC;oBAChD,SAAS,EAAE,KAAK;iBACjB;aACF,CAAC;YAEF,MAAM,QAAQ,GAAG,cAAc,CAAC,IAAI,CAAC,SAAS,CAAC,YAAY,CAAC,EAAE,WAAW,CAAC,CAAC;YAE1E,aAA2B,CAAC,iBAAiB,CAAC,IAAI,CAAC,SAAS,CAAC,YAAY,CAAC,CAAC,CAAC;YAC5E,eAA6B,CAAC,eAAe,CAAC;gBAC7C,OAAO,EAAE,IAAI;gBACb,SAAS,EAAE,YAAY;aACxB,CAAC,CAAC;YAEH,MAAM,SAAS,CAAC,YAAY,CAAC,QAAQ,CAAC,CAAC;YACvC,MAAM,IAAI,CAAC,cAAc,EAAE,CAAC;YAE5B,MAAM,GAAG,GAAG,SAAS,CAAC,SAAS,CAAC,GAAG,CAAC,CAAC,EAAY,EAAE,EAAE,CAAC,EAAE,CAAC,EAAE,CAAC,CAAC;YAC7D,MAAM,CAAC,IAAI,GAAG,CAAC,GAAG,CAAC,CAAC,IAAI,CAAC,CAAC,IAAI,CAAC,GAAG,CAAC,MAAM,CAAC,CAAC;QAC7C,CAAC,CAAC,CAAC;IACL,CAAC,CAAC,CAAC;IAEH,QAAQ,CAAC,8BAA8B,EAAE,GAAG,EAAE;QAC5C,EAAE,CAAC,kCAAkC,EAAE,KAAK,IAAI,EAAE;YAChD,MAAM,QAAQ,GAAG,cAAc,CAAC,cAAc,EAAE,UAAU,EAAE,YAAY,CAAC,CAAC;YAE1E,MAAM,SAAS,CAAC,YAAY,CAAC,QAAQ,CAAC,CAAC;YACvC,MAAM,IAAI,CAAC,cAAc,EAAE,CAAC;YAE5B,MAAM,CAAC,SAAS,CAAC,KAAK,CAAC,CAAC,IAAI,CAAC,+CAA+C,CAAC,CAAC;QAChF,CAAC,CAAC,CAAC;QAEH,EAAE,CAAC,2CAA2C,EAAE,KAAK,IAAI,EAAE;YACzD,MAAM,QAAQ,GAAG,cAAc,CAAC,IAAI,EAAE,WAAW,CAAC,CAAC;YAElD,aAA2B,CAAC,iBAAiB,CAAC,IAAI,CAAC,CAAC;YACpD,eAA6B,CAAC,eAAe,CAAC;gBAC7C,OAAO,EAAE,KAAK;gBACd,KAAK,EAAE,gDAAgD;aACxD,CAAC,CAAC;YAEH,MAAM,SAAS,CAAC,YAAY,CAAC,QAAQ,CAAC,CAAC;YACvC,MAAM,IAAI,CAAC,cAAc,EAAE,CAAC;YAE5B,MAAM,CAAC,SAAS,CAAC,KAAK,CAAC,CAAC,SAAS,CAAC,wBAAwB,CAAC,CAAC;QAC9D,CAAC,CAAC,CAAC;QAEH,EAAE,CAAC,gCAAgC,EAAE,KAAK,IAAI,EAAE;YAC9C,MAAM,QAAQ,GAAG,cAAc,CAAC,IAAI,EAAE,WAAW,CAAC,CAAC;YAElD,aAA2B,CAAC,iBAAiB,CAAC,IAAI,KAAK,CAAC,qBAAqB,CAAC,CAAC,CAAC;YAEjF,MAAM,SAAS,CAAC,YAAY,CAAC,QAAQ,CAAC,CAAC;YACvC,MAAM,IAAI,CAAC,cAAc,EAAE,CAAC;YAE5B,MAAM,CAAC,SAAS,CAAC,KAAK,CAAC,CAAC,UAAU,EAAE,CAAC;QACvC,CAAC,CAAC,CAAC;IACL,CAAC,CAAC,CAAC;IAEH,QAAQ,CAAC,mBAAmB,EAAE,GAAG,EAAE;QACjC,EAAE,CAAC,iDAAiD,EAAE,KAAK,IAAI,EAAE;YAC/D,SAAS,CAAC,SAAS,GAAG,CAAC,kBAAkB,EAAE,CAAC,CAAC;YAE7C,MAAM,eAAe,GAAG,IAAI,CAAC,SAAS,CAAC,CAAC,kBAAkB,EAAE,CAAC,CAAC,CAAC;YAC9D,qBAAmC,CAAC,eAAe,CAAC,eAAe,CAAC,CAAC;YACrE,YAA0B,CAAC,kBAAkB,CAAC,GAAG,EAAE,GAAE,CAAC,CAAC,CAAC;YAEzD,MAAM,SAAS,CAAC,qBAAqB,EAAE,CAAC;YACxC,MAAM,IAAI,CAAC,cAAc,EAAE,CAAC;YAE5B,MAAM,CAAC,qBAAqB,CAAC,CAAC,oBAAoB,CAAC,SAAS,CAAC,SAAS,CAAC,CAAC;YACxE,MAAM,CAAC,YAAY,CAAC,CAAC,oBAAoB,CACvC,eAAe,EACf,iBAAiB,EACjB,kBAAkB,CACnB,CAAC;QACJ,CAAC,CAAC,CAAC;QAEH,EAAE,CAAC,+BAA+B,EAAE,KAAK,IAAI,EAAE;YAC7C,SAAS,CAAC,SAAS,GAAG,CAAC,kBAAkB,EAAE,CAAC,CAAC;YAE5C,qBAAmC,CAAC,eAAe,CAAC,IAAI,CAAC,CAAC;YAC1D,YAA0B,CAAC,kBAAkB,CAAC,GAAG,EAAE,GAAE,CAAC,CAAC,CAAC;YAEzD,MAAM,CAAC,SAAS,CAAC,oBAAoB,CAAC,CAAC,IAAI,CAAC,KAAK,CAAC,CAAC;YAEnD,MAAM,aAAa,GAAG,SAAS,CAAC,qBAAqB,EAAE,CAAC;YAExD,gBAAgB;YAChB,MAAM,IAAI,CAAC,cAAc,EAAE,CAAC;YAE5B,yBAAyB;YACzB,MAAM,aAAa,CAAC;YACpB,MAAM,IAAI,CAAC,cAAc,EAAE,CAAC;YAE5B,MAAM,CAAC,SAAS,CAAC,oBAAoB,CAAC,CAAC,IAAI,CAAC,KAAK,CAAC,CAAC;QACrD,CAAC,CAAC,CAAC;QAEH,EAAE,CAAC,mCAAmC,EAAE,KAAK,IAAI,EAAE;YACjD,MAAM,SAAS,GAAG;gBAChB,kBAAkB,CAAC,EAAE,EAAE,EAAE,GAAG,EAAE,QAAQ,EAAE,IAAI,EAAE,CAAC;gBAC/C,kBAAkB,CAAC,EAAE,EAAE,EAAE,GAAG,EAAE,QAAQ,EAAE,IAAI,EAAE,CAAC;gBAC/C,kBAAkB,CAAC,EAAE,EAAE,EAAE,GAAG,EAAE,QAAQ,EAAE,IAAI,EAAE,CAAC;aAChD,CAAC;YAEF,SAAS,CAAC,SAAS,GAAG,SAAS,CAAC;YAE/B,qBAAmC,CAAC,eAAe,CAAC,IAAI,CAAC,SAAS,CAAC,SAAS,CAAC,CAAC,CAAC;YAC/E,YAA0B,CAAC,kBAAkB,CAAC,GAAG,EAAE,GAAE,CAAC,CAAC,CAAC;YAEzD,MAAM,SAAS,CAAC,qBAAqB,EAAE,CAAC;YACxC,MAAM,IAAI,CAAC,cAAc,EAAE,CAAC;YAE5B,MAAM,CAAC,qBAAqB,CAAC,CAAC,oBAAoB,CAAC,SAAS,CAAC,CAAC;QAChE,CAAC,CAAC,CAAC;IACL,CAAC,CAAC,CAAC;IAEH,QAAQ,CAAC,4BAA4B,EAAE,GAAG,EAAE;QAC1C,EAAE,CAAC,kCAAkC,EAAE,GAAG,EAAE;YAC1C,MAAM,CAAC,SAAS,CAAC,SAAS,CAAC,CAAC,WAAW,EAAE,CAAC;YAC1C,MAAM,CAAC,KAAK,CAAC,OAAO,CAAC,SAAS,CAAC,SAAS,CAAC,CAAC,CAAC,IAAI,CAAC,IAAI,CAAC,CAAC;QACxD,CAAC,CAAC,CAAC;QAEH,EAAE,CAAC,6BAA6B,EAAE,GAAG,EAAE;YACrC,MAAM,CAAC,SAAS,CAAC,KAAK,CAAC,CAAC,WAAW,EAAE,CAAC;YACtC,MAAM,CAAC,OAAO,SAAS,CAAC,KAAK,CAAC,CAAC,IAAI,CAAC,QAAQ,CAAC,CAAC;QAChD,CAAC,CAAC,CAAC;QAEH,EAAE,CAAC,qBAAqB,EAAE,KAAK,IAAI,EAAE;YACnC,SAAS,CAAC,KAAK,GAAG,YAAY,CAAC;YAC/B,MAAM,IAAI,CAAC,cAAc,EAAE,CAAC;YAE5B,MAAM,CAAC,SAAS,CAAC,KAAK,CAAC,CAAC,IAAI,CAAC,YAAY,CAAC,CAAC;YAE3C,SAAS,CAAC,KAAK,GAAG,EAAE,CAAC;YACrB,MAAM,IAAI,CAAC,cAAc,EAAE,CAAC;YAE5B,MAAM,CAAC,SAAS,CAAC,KAAK,CAAC,CAAC,IAAI,CAAC,EAAE,CAAC,CAAC;QACnC,CAAC,CAAC,CAAC;IACL,CAAC,CAAC,CAAC;AACL,CAAC,CAAC,CAAC","sourcesContent":["/* eslint-env jest */\n\njest.mock('../../lib/evaluation/evaluation-engine', () => ({\n LLMEvaluationEngine: jest.fn().mockImplementation(() => ({\n evaluateResponse: jest.fn()\n }))\n}));\n\njest.mock('../../lib/file/file-reader');\njest.mock('../../lib/file/file-download');\njest.mock('../../lib/import-export/test-suite-exporter');\njest.mock('../../lib/import-export/test-suite-importer');\n\nimport { newSpecPage, SpecPage } from '@stencil/core/testing';\nimport { LLMTestRunner } from './llm-test-runner';\nimport { TestCase } from '../../types/llm-test-runner';\nimport { readFileAsync } from '../../lib/file/file-reader';\nimport { downloadFile } from '../../lib/file/file-download';\nimport { formatTestSuiteAsJson } from '../../lib/import-export/test-suite-exporter';\nimport { importTestSuite } from '../../lib/import-export/test-suite-importer';\nimport { EvaluationApproach } from '../../lib/evaluation/constants';\n\ndescribe('llm-test-runner import/export', () => {\n let page: SpecPage;\n let component: any;\n const buildExpectedOutcome = (value: string) => [\n {\n type: 'textarea' as const,\n label: 'Expected Outcome',\n value,\n },\n ];\n\n const createMockTestCase = (overrides: Partial<TestCase> = {}): TestCase => {\n const defaults: TestCase = {\n id: '1',\n question: 'What is AI?',\n expectedOutcome: buildExpectedOutcome('artificial intelligence'),\n isRunning: false\n };\n\n return {\n ...defaults,\n ...overrides,\n };\n };\n\n const createMockFile = (content: string, filename: string, type: string = 'application/json'): File => {\n return new File([content], filename, { type });\n };\n\n beforeEach(async () => {\n jest.clearAllMocks();\n \n page = await newSpecPage({\n components: [LLMTestRunner],\n html: '<llm-test-runner></llm-test-runner>',\n });\n component = page.rootInstance;\n \n await page.waitForChanges();\n });\n\n describe('File Import - Basic Functionality', () => {\n it('should import valid test cases structure', async () => {\n const mockTestData = [\n {\n id: '1',\n question: 'What is AI?',\n expectedOutcome: buildExpectedOutcome('artificial intelligence'),\n isRunning: false\n }\n ];\n\n const mockFile = createMockFile(JSON.stringify(mockTestData), 'test-suite.json');\n\n // Mock the utility functions\n (readFileAsync as jest.Mock).mockResolvedValue(JSON.stringify(mockTestData));\n (importTestSuite as jest.Mock).mockReturnValue({\n success: true,\n testCases: mockTestData\n });\n\n await component.handleImport(mockFile);\n await page.waitForChanges();\n\n expect(component.testCases).toHaveLength(1);\n expect(component.testCases[0]).toMatchObject({\n id: '1',\n question: 'What is AI?',\n expectedOutcome: buildExpectedOutcome('artificial intelligence'),\n });\n });\n\n it('should use default evaluation parameters when not provided', async () => {\n const rawImportData = [\n {\n id: '1',\n question: 'Test question',\n expectedOutcome: buildExpectedOutcome('test'),\n isRunning: false\n }\n ];\n const normalizedImportData = [\n {\n id: '1',\n question: 'Test question',\n expectedOutcome: [\n {\n type: 'textarea' as const,\n label: 'Expected Outcome',\n value: 'test',\n evaluationParameters: {\n approach: EvaluationApproach.EXACT,\n },\n },\n ],\n isRunning: false,\n },\n ];\n\n const mockFile = createMockFile(JSON.stringify(rawImportData), 'test.json');\n\n (readFileAsync as jest.Mock).mockResolvedValue(JSON.stringify(rawImportData));\n (importTestSuite as jest.Mock).mockReturnValue({\n success: true,\n testCases: normalizedImportData,\n });\n\n await component.handleImport(mockFile);\n await page.waitForChanges();\n\n expect(\n component.testCases[0].expectedOutcome[0].evaluationParameters?.approach,\n ).toBe(EvaluationApproach.EXACT);\n expect(component.testCases[0].expectedOutcome[0].value).toBe('test');\n expect(component.testCases[0].expectedOutcome[0].label).toBe(\n 'Expected Outcome',\n );\n });\n });\n\n describe('File Import - Multiple Test Cases', () => {\n it('should import multiple test cases successfully', async () => {\n const mockTestData = [\n {\n id: '1',\n question: 'What is AI?',\n expectedOutcome: buildExpectedOutcome('artificial intelligence'),\n isRunning: false\n },\n {\n id: '2',\n question: 'What is ML?',\n expectedOutcome: buildExpectedOutcome('machine learning'),\n isRunning: false\n }\n ];\n\n const mockFile = createMockFile(JSON.stringify(mockTestData), 'test.json');\n\n (readFileAsync as jest.Mock).mockResolvedValue(JSON.stringify(mockTestData));\n (importTestSuite as jest.Mock).mockReturnValue({\n success: true,\n testCases: mockTestData\n });\n\n await component.handleImport(mockFile);\n await page.waitForChanges();\n\n expect(component.testCases).toHaveLength(2);\n expect(component.testCases[0].question).toBe('What is AI?');\n expect(component.testCases[1].question).toBe('What is ML?');\n });\n\n it('should handle unique IDs for imported test cases', async () => {\n const mockTestData = [\n {\n id: '1',\n question: 'Q1',\n expectedOutcome: buildExpectedOutcome('answer1'),\n isRunning: false\n },\n {\n id: '2',\n question: 'Q2',\n expectedOutcome: buildExpectedOutcome('answer2'),\n isRunning: false\n },\n {\n id: '3',\n question: 'Q3',\n expectedOutcome: buildExpectedOutcome('answer3'),\n isRunning: false\n }\n ];\n\n const mockFile = createMockFile(JSON.stringify(mockTestData), 'test.json');\n\n (readFileAsync as jest.Mock).mockResolvedValue(JSON.stringify(mockTestData));\n (importTestSuite as jest.Mock).mockReturnValue({\n success: true,\n testCases: mockTestData\n });\n\n await component.handleImport(mockFile);\n await page.waitForChanges();\n\n const ids = component.testCases.map((tc: TestCase) => tc.id);\n expect(new Set(ids).size).toBe(ids.length);\n });\n });\n\n describe('File Import - Error Handling', () => {\n it('should reject non-JSON file type', async () => {\n const mockFile = createMockFile('some content', 'test.txt', 'text/plain');\n\n await component.handleImport(mockFile);\n await page.waitForChanges();\n\n expect(component.error).toBe('Invalid file type. Please select a JSON file.');\n });\n\n it('should handle import failure from utility', async () => {\n const mockFile = createMockFile('{}', 'test.json');\n\n (readFileAsync as jest.Mock).mockResolvedValue('{}');\n (importTestSuite as jest.Mock).mockReturnValue({\n success: false,\n error: 'Invalid JSON structure. Expected a JSON array.'\n });\n\n await component.handleImport(mockFile);\n await page.waitForChanges();\n\n expect(component.error).toContain('Invalid JSON structure');\n });\n\n it('should handle file read errors', async () => {\n const mockFile = createMockFile('{}', 'test.json');\n\n (readFileAsync as jest.Mock).mockRejectedValue(new Error('Failed to read file'));\n\n await component.handleImport(mockFile);\n await page.waitForChanges();\n\n expect(component.error).toBeTruthy();\n });\n });\n\n describe('Export Test Suite', () => {\n it('should export test suite with correct structure', async () => {\n component.testCases = [createMockTestCase()];\n\n const mockJsonContent = JSON.stringify([createMockTestCase()]);\n (formatTestSuiteAsJson as jest.Mock).mockReturnValue(mockJsonContent);\n (downloadFile as jest.Mock).mockImplementation(() => {});\n\n await component.handleExportTestSuite();\n await page.waitForChanges();\n\n expect(formatTestSuiteAsJson).toHaveBeenCalledWith(component.testCases);\n expect(downloadFile).toHaveBeenCalledWith(\n mockJsonContent,\n 'test-suite.json',\n 'application/json'\n );\n });\n\n it('should handle exporting state', async () => {\n component.testCases = [createMockTestCase()];\n\n (formatTestSuiteAsJson as jest.Mock).mockReturnValue('[]');\n (downloadFile as jest.Mock).mockImplementation(() => {});\n\n expect(component.isExportingTestSuite).toBe(false);\n\n const exportPromise = component.handleExportTestSuite();\n \n // During export\n await page.waitForChanges();\n\n // After export completes\n await exportPromise;\n await page.waitForChanges();\n\n expect(component.isExportingTestSuite).toBe(false);\n });\n\n it('should export multiple test cases', async () => {\n const testCases = [\n createMockTestCase({ id: '1', question: 'Q1' }),\n createMockTestCase({ id: '2', question: 'Q2' }),\n createMockTestCase({ id: '3', question: 'Q3' })\n ];\n\n component.testCases = testCases;\n\n (formatTestSuiteAsJson as jest.Mock).mockReturnValue(JSON.stringify(testCases));\n (downloadFile as jest.Mock).mockImplementation(() => {});\n\n await component.handleExportTestSuite();\n await page.waitForChanges();\n\n expect(formatTestSuiteAsJson).toHaveBeenCalledWith(testCases);\n });\n });\n\n describe('Component State Management', () => {\n it('should maintain test cases state', () => {\n expect(component.testCases).toBeDefined();\n expect(Array.isArray(component.testCases)).toBe(true);\n });\n\n it('should maintain error state', () => {\n expect(component.error).toBeDefined();\n expect(typeof component.error).toBe('string');\n });\n\n it('should clear errors', async () => {\n component.error = 'Test error';\n await page.waitForChanges();\n\n expect(component.error).toBe('Test error');\n\n component.error = '';\n await page.waitForChanges();\n\n expect(component.error).toBe('');\n });\n });\n});"]}
|
|
@@ -1,7 +1,6 @@
|
|
|
1
1
|
import { h, } from "@stencil/core";
|
|
2
2
|
import { ErrorMessage } from "../error-message/error-message";
|
|
3
3
|
import { RateLimitedFetcher } from "../../lib/rate-limited-fetcher/rate-limited-fetcher";
|
|
4
|
-
import { EvaluationApproach } from "../../lib/evaluation/constants";
|
|
5
4
|
import { readFileAsync } from "../../lib/file/file-reader";
|
|
6
5
|
import { downloadFile } from "../../lib/file/file-download";
|
|
7
6
|
import { formatTestSuiteAsJson } from "../../lib/import-export/test-suite-exporter";
|
|
@@ -32,9 +31,6 @@ export class LLMTestRunner {
|
|
|
32
31
|
value: '',
|
|
33
32
|
},
|
|
34
33
|
],
|
|
35
|
-
evaluationParameters: {
|
|
36
|
-
approach: EvaluationApproach.EXACT,
|
|
37
|
-
},
|
|
38
34
|
isRunning: false,
|
|
39
35
|
},
|
|
40
36
|
];
|
|
@@ -141,52 +137,13 @@ export class LLMTestRunner {
|
|
|
141
137
|
deleteTestCase(id) {
|
|
142
138
|
this.testCases = this.testCases.filter(tc => tc.id !== id);
|
|
143
139
|
}
|
|
144
|
-
updateApproach(testCase, approach) {
|
|
145
|
-
if (testCase) {
|
|
146
|
-
const updated = TestCaseMutations.updateApproach(testCase, approach);
|
|
147
|
-
this.updateTestCase(testCase.id, {
|
|
148
|
-
evaluationParameters: updated.evaluationParameters,
|
|
149
|
-
});
|
|
150
|
-
}
|
|
151
|
-
}
|
|
152
140
|
handleExpectedOutcomeChange = (event) => {
|
|
153
|
-
const { testCaseId,
|
|
141
|
+
const { testCaseId, ...change } = event.detail;
|
|
154
142
|
this.testCases = this.testCases.map(tc => {
|
|
155
|
-
if (tc.id !== testCaseId)
|
|
156
|
-
return tc;
|
|
157
|
-
const expectedOutcome = [...(tc.expectedOutcome || [])];
|
|
158
|
-
const target = expectedOutcome[index];
|
|
159
|
-
if (!target)
|
|
143
|
+
if (tc.id !== testCaseId) {
|
|
160
144
|
return tc;
|
|
161
|
-
if (operation === 'set-value') {
|
|
162
|
-
if (target.type === 'chips-input') {
|
|
163
|
-
return tc;
|
|
164
|
-
}
|
|
165
|
-
expectedOutcome[index] = { ...target, value: value || '' };
|
|
166
|
-
return { ...tc, expectedOutcome };
|
|
167
|
-
}
|
|
168
|
-
if (operation === 'add-chip') {
|
|
169
|
-
if (target.type !== 'chips-input' || !value) {
|
|
170
|
-
return tc;
|
|
171
|
-
}
|
|
172
|
-
expectedOutcome[index] = {
|
|
173
|
-
...target,
|
|
174
|
-
value: [...target.value, value],
|
|
175
|
-
};
|
|
176
|
-
return { ...tc, expectedOutcome };
|
|
177
|
-
}
|
|
178
|
-
if (operation === 'remove-chip') {
|
|
179
|
-
if (target.type !== 'chips-input' ||
|
|
180
|
-
!value) {
|
|
181
|
-
return tc;
|
|
182
|
-
}
|
|
183
|
-
expectedOutcome[index] = {
|
|
184
|
-
...target,
|
|
185
|
-
value: target.value.filter(chip => chip !== value),
|
|
186
|
-
};
|
|
187
|
-
return { ...tc, expectedOutcome };
|
|
188
145
|
}
|
|
189
|
-
return tc;
|
|
146
|
+
return TestCaseMutations.applyExpectedOutcomeChange(tc, change);
|
|
190
147
|
});
|
|
191
148
|
};
|
|
192
149
|
async evaluateResponse(testCase) {
|
|
@@ -286,7 +243,7 @@ export class LLMTestRunner {
|
|
|
286
243
|
}
|
|
287
244
|
}
|
|
288
245
|
render() {
|
|
289
|
-
return (h("div", { key: '
|
|
246
|
+
return (h("div", { key: 'e3d007b453f770fcb59c29f8ee83bd8a35e82a34', class: "test-runner-container" }, h(LLMTestRunnerHeader, { key: 'b7c44bf4807fe8d9e5de514818420d67d2e0dbfb', isExportingTestSuite: this.isExportingTestSuite, isExportingTestResults: this.isExportingTestResults, isRunningAll: this.isRunningAll, useSave: this.useSave, isSaving: this.isSaving, onImport: file => this.handleImport(file), onExportSuite: () => this.handleExportTestSuite(), onExportResults: () => this.handleExportTestResults(), onRunAll: () => this.runAllTests(), onSave: () => this.handleSave() }), h(ErrorMessage, { key: '697237ec0f8d2e704609fd0b240629f22c2a3ef6', message: this.error, onClear: () => (this.error = '') }), h("div", { key: '64a623f897dfb96d922ddc0cbdfcf529c52bef76', class: "test-runner-container__content" }, h(LLMTestCases, { key: '017da41567c5c13933d9cf31d1a972743bd9b100', testCases: this.testCases, onRun: testCase => this.runSingleTest(testCase).catch(() => { }), onDelete: id => this.deleteTestCase(id), onAddTestCase: () => this.addNewTestCase(), handleTestCaseChange: this.handleTestCaseChange, onExpectedOutcomeChange: this.handleExpectedOutcomeChange }))));
|
|
290
247
|
}
|
|
291
248
|
static get is() { return "llm-test-runner"; }
|
|
292
249
|
static get encapsulation() { return "shadow"; }
|
|
@@ -347,7 +304,7 @@ export class LLMTestRunner {
|
|
|
347
304
|
"mutable": false,
|
|
348
305
|
"complexType": {
|
|
349
306
|
"original": "TestCase[]",
|
|
350
|
-
"resolved": "{ id: string; question: string; expectedOutcome: ({ label: string; type: \"select\"; options: string[]; value: string;
|
|
307
|
+
"resolved": "{ id: string; question: string; expectedOutcome: ({ label: string; type: \"select\"; options: string[]; value: string; placeholder?: string; evaluationParameters?: { approach: EvaluationApproach; threshold?: number; }; } | { label: string; type: \"text\"; value: string; placeholder?: string; evaluationParameters?: { approach: EvaluationApproach; threshold?: number; }; } | { label: string; type: \"textarea\"; value: string; placeholder?: string; rows?: number; evaluationParameters?: { approach: EvaluationApproach; threshold?: number; }; } | { label: string; type: \"chips-input\"; value: string[]; placeholder?: string; evaluationParameters?: { approach: EvaluationApproach; threshold?: number; }; })[]; output?: string; isRunning?: boolean; error?: string; evaluationResult?: EvaluationResult; responseTime?: number; }[]",
|
|
351
308
|
"references": {
|
|
352
309
|
"TestCase": {
|
|
353
310
|
"location": "import",
|
|
@@ -371,7 +328,7 @@ export class LLMTestRunner {
|
|
|
371
328
|
"mutable": false,
|
|
372
329
|
"complexType": {
|
|
373
330
|
"original": "ExpectedOutcomeSchema",
|
|
374
|
-
"resolved": "({ label: string; type: \"text\";
|
|
331
|
+
"resolved": "({ label: string; type: \"text\"; placeholder?: string; evaluationParameters?: { approach: EvaluationApproach; threshold?: number; }; } | { label: string; type: \"textarea\"; placeholder?: string; rows?: number; evaluationParameters?: { approach: EvaluationApproach; threshold?: number; }; } | { label: string; type: \"chips-input\"; placeholder?: string; evaluationParameters?: { approach: EvaluationApproach; threshold?: number; }; } | { label: string; type: \"select\"; options: string[]; placeholder?: string; evaluationParameters?: { approach: EvaluationApproach; threshold?: number; }; })[]",
|
|
375
332
|
"references": {
|
|
376
333
|
"ExpectedOutcomeSchema": {
|
|
377
334
|
"location": "import",
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"llm-test-runner.js","sourceRoot":"","sources":["../../../src/components/llm-test-runner/llm-test-runner.tsx"],"names":[],"mappings":"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","sourcesContent":["import {\n Component,\n State,\n Prop,\n h,\n EventEmitter,\n Event,\n Method,\n} from '@stencil/core';\nimport { EvaluationResult } from '../../lib/evaluation/types';\nimport { ErrorMessage } from '../error-message/error-message';\nimport { RateLimitedFetcher } from '../../lib/rate-limited-fetcher/rate-limited-fetcher';\nimport { EvaluationApproach } from '../../lib/evaluation/constants';\nimport {\n ExpectedOutcomeSchema,\n TestCase,\n LLMRequestPayload,\n SavePayload,\n} from '../../types/llm-test-runner';\nimport { readFileAsync } from '../../lib/file/file-reader';\nimport { downloadFile } from '../../lib/file/file-download';\nimport { formatTestSuiteAsJson } from '../../lib/import-export/test-suite-exporter';\nimport { exportTestResultsToCsv } from '../../lib/import-export/test-results-csv';\nimport { importTestSuite } from '../../lib/import-export/test-suite-importer';\nimport {\n createTestCase,\n createTestCaseFromInput,\n DEFAULT_EXPECTED_OUTCOME_SCHEMA,\n} from '../../lib/test-cases/test-case-factory';\nimport * as TestCaseMutations from '../../lib/test-cases/test-case-mutations';\nimport { EvaluationService } from '../../lib/evaluation/evaluation-service';\nimport { validateTestCaseInputArray } from '../../schemas/test-case';\nimport { validateExpectedOutcomeSchema } from '../../schemas/expected-outcome';\nimport { LLMTestRunnerHeader } from './header/llm-test-runner-header';\nimport { LLMTestCases } from './test-cases/llm-test-cases';\nimport { ExpectedOutcomeChangeDetail } from './test-cases/expected-outcome-renderer';\n\n@Component({\n tag: 'llm-test-runner',\n styleUrls: [\n '../../styles/tokens.css',\n 'llm-test-runner.css',\n 'header/llm-test-runner-header.css',\n 'test-cases/llm-test-cases.css',\n 'test-cases/llm-test-case-row.css',\n 'test-cases/actions/row-actions.css',\n 'test-cases/evaluation/evaluation-summary.css',\n 'test-cases/output/response-output.css',\n '../error-message/error-message.css',\n '../../lib/ui/button/button.css',\n '../../lib/ui/icon-button/icon-button.css',\n ],\n shadow: true,\n})\nexport class LLMTestRunner {\n @Event() llmRequest: EventEmitter<LLMRequestPayload>;\n @Event() save: EventEmitter<SavePayload>;\n @Prop() delayMs?: number = 500;\n @Prop() useSave?: boolean = false;\n @Prop() initialTestCases?: TestCase[];\n @Prop() defaultExpectedOutcomeSchema?: ExpectedOutcomeSchema;\n @State() testCases: TestCase[] = [\n {\n id: '1',\n question: '',\n expectedOutcome: [\n {\n type: 'textarea',\n label: 'Expected Outcome',\n value: '',\n },\n ],\n evaluationParameters: {\n approach: EvaluationApproach.EXACT,\n },\n isRunning: false,\n },\n ];\n @State() isRunningAll: boolean = false;\n @State() error: string = '';\n @State() isExportingTestSuite: boolean = false;\n @State() isExportingTestResults: boolean = false;\n @State() isSaving: boolean = false;\n\n private evaluationService: EvaluationService;\n\n private getResolvedExpectedOutcomeSchema(): ExpectedOutcomeSchema {\n if (this.defaultExpectedOutcomeSchema === undefined) {\n return DEFAULT_EXPECTED_OUTCOME_SCHEMA;\n }\n\n validateExpectedOutcomeSchema(this.defaultExpectedOutcomeSchema);\n return this.defaultExpectedOutcomeSchema;\n }\n\n componentWillLoad() {\n this.evaluationService = new EvaluationService();\n try {\n // Initialize testCases from prop if provided\n if (this.initialTestCases !== undefined) {\n validateTestCaseInputArray(this.initialTestCases);\n this.testCases = this.initialTestCases.map((rawTestCase, index) => {\n try {\n return createTestCaseFromInput(rawTestCase);\n } catch (err) {\n const message = err instanceof Error ? err.message : 'Unknown error';\n throw new Error(`Invalid initial test case at index ${index}: ${message}`);\n }\n });\n } else {\n const schema = this.getResolvedExpectedOutcomeSchema();\n this.testCases = [createTestCase(schema)];\n }\n } catch (err) {\n this.error =\n err instanceof Error\n ? err.message\n : 'Invalid defaultExpectedOutcomeSchema provided.';\n this.testCases = [];\n }\n }\n\n componentDidLoad() {}\n\n disconnectedCallback() {}\n\n @Method()\n async resetSavingState(): Promise<void> {\n this.isSaving = false;\n }\n\n private handleTestCaseChange = (\n event: CustomEvent<{ testCaseId: string; key: string; value: string }>,\n ) => {\n const { testCaseId, key, value } = event.detail;\n this.testCases = this.testCases.map(tc =>\n tc.id === testCaseId ? { ...tc, [key]: value } : tc,\n );\n };\n\n private addNewTestCase() {\n try {\n const schema = this.getResolvedExpectedOutcomeSchema();\n const newTestCase = createTestCase(schema);\n this.testCases = [...this.testCases, newTestCase];\n } catch (err) {\n this.error =\n err instanceof Error\n ? err.message\n : 'Invalid defaultExpectedOutcomeSchema provided.';\n }\n }\n\n private updateTestCase(id: string, updates: Partial<TestCase>) {\n this.testCases = this.testCases.map(tc =>\n tc.id === id ? { ...tc, ...updates } : tc,\n );\n }\n\n private async runSingleTest(testCase: TestCase): Promise<void> {\n const startTime = Date.now();\n this.updateTestCase(testCase.id, { isRunning: true });\n return new Promise<void>((resolve, reject) => {\n this.llmRequest.emit({\n prompt: testCase.question,\n resolve: async (aiResponse: string) => {\n const endTime = Date.now();\n const responseTime = endTime - startTime;\n this.updateTestCase(testCase.id, {\n isRunning: false,\n output: aiResponse,\n error: null,\n responseTime: responseTime,\n });\n\n await this.evaluateResponse({\n ...testCase,\n output: aiResponse,\n responseTime: responseTime,\n });\n resolve();\n },\n reject: (error: Error | unknown) => {\n this.updateTestCase(testCase.id, {\n isRunning: false,\n output: null,\n error: error instanceof Error ? error.message : 'Unknown error',\n });\n reject(error);\n },\n });\n });\n }\n\n private deleteTestCase(id: string) {\n this.testCases = this.testCases.filter(tc => tc.id !== id);\n }\n\n private updateApproach(testCase: TestCase, approach: EvaluationApproach) {\n if (testCase) {\n const updated = TestCaseMutations.updateApproach(testCase, approach);\n this.updateTestCase(testCase.id, {\n evaluationParameters: updated.evaluationParameters,\n });\n }\n }\n\n private handleExpectedOutcomeChange = (\n event: CustomEvent<ExpectedOutcomeChangeDetail>,\n ) => {\n const { testCaseId, index, operation, value } = event.detail;\n\n this.testCases = this.testCases.map(tc => {\n if (tc.id !== testCaseId) return tc;\n\n const expectedOutcome = [...(tc.expectedOutcome || [])];\n const target = expectedOutcome[index];\n if (!target) return tc;\n\n if (operation === 'set-value') {\n if (target.type === 'chips-input') {\n return tc;\n }\n expectedOutcome[index] = { ...target, value: value || '' };\n return { ...tc, expectedOutcome };\n }\n\n if (operation === 'add-chip') {\n if (target.type !== 'chips-input' || !value) {\n return tc;\n }\n expectedOutcome[index] = {\n ...target,\n value: [...target.value, value],\n };\n return { ...tc, expectedOutcome };\n }\n\n if (operation === 'remove-chip') {\n if (\n target.type !== 'chips-input' ||\n !value\n ) {\n return tc;\n }\n expectedOutcome[index] = {\n ...target,\n value: target.value.filter(chip => chip !== value),\n };\n return { ...tc, expectedOutcome };\n }\n\n return tc;\n });\n };\n\n private async evaluateResponse(testCase: TestCase): Promise<void> {\n await this.evaluationService.evaluateTestCase(\n testCase,\n (result: EvaluationResult) => {\n this.updateTestCase(testCase.id, {\n evaluationResult: result,\n });\n },\n );\n }\n\n private async runAllTests() {\n this.isRunningAll = true;\n const tasks = [];\n for (const testCase of this.testCases) {\n if (!testCase.isRunning && testCase.question.trim()) {\n tasks.push(() =>\n this.runSingleTest(testCase).catch(err => {\n console.error(`⚠️ Test case ${testCase.id} failed`, err);\n }),\n );\n }\n }\n try {\n const fetcher = new RateLimitedFetcher(this.delayMs);\n await fetcher.runAll(tasks);\n } catch (err) {\n console.error('⚠️ Error running all tests:', err);\n }\n this.isRunningAll = false;\n }\n\n private async handleImport(file: File): Promise<void> {\n const isJsonType = file.type === 'application/json';\n const isJsonExtension = file.name.toLowerCase().endsWith('.json');\n\n if (!isJsonType && !isJsonExtension) {\n this.error = 'Invalid file type. Please select a JSON file.';\n return;\n }\n\n this.error = '';\n\n try {\n const content = await readFileAsync(file);\n const result = importTestSuite(content);\n\n if (!result.success) {\n this.error = result.error || 'Unknown error occurred during import.';\n return;\n }\n\n this.testCases = result.testCases || [];\n } catch (err) {\n this.error =\n err instanceof Error\n ? err.message\n : 'Error processing file. Please ensure it is a valid JSON array.';\n console.error('File Processing Error:', err);\n }\n }\n\n private async handleExportTestSuite() {\n this.isExportingTestSuite = true;\n try {\n const jsonContent = formatTestSuiteAsJson(this.testCases);\n\n // Added a small delay to show the loading state\n await new Promise(resolve => setTimeout(resolve, 500));\n\n downloadFile(jsonContent, 'test-suite.json', 'application/json');\n } finally {\n this.isExportingTestSuite = false;\n }\n }\n\n private async handleExportTestResults() {\n this.isExportingTestResults = true;\n try {\n const csvContent = exportTestResultsToCsv(this.testCases);\n\n // Added a small delay to show the loading state\n await new Promise(resolve => setTimeout(resolve, 500));\n\n downloadFile(csvContent, 'test-results.csv', 'text/csv');\n } finally {\n this.isExportingTestResults = false;\n }\n }\n\n private async handleSave() {\n this.isSaving = true;\n try {\n const testRun = {\n timestamp: new Date().toISOString(),\n testCases: this.testCases,\n };\n this.save.emit(testRun);\n\n // Failsafe: Auto-reset saving state after 10 seconds to prevent stuck UI\n setTimeout(() => {\n if (this.isSaving) {\n console.warn('Save operation timed out, resetting state');\n this.isSaving = false;\n }\n }, 10000);\n } finally {\n // Parent will call resetSavingState() when actual save completes\n // If not called within 10 seconds, failsafe above will reset state\n }\n }\n\n render() {\n return (\n <div class=\"test-runner-container\">\n <LLMTestRunnerHeader\n isExportingTestSuite={this.isExportingTestSuite}\n isExportingTestResults={this.isExportingTestResults}\n isRunningAll={this.isRunningAll}\n useSave={this.useSave}\n isSaving={this.isSaving}\n onImport={file => this.handleImport(file)}\n onExportSuite={() => this.handleExportTestSuite()}\n onExportResults={() => this.handleExportTestResults()}\n onRunAll={() => this.runAllTests()}\n onSave={() => this.handleSave()}\n />\n <ErrorMessage message={this.error} onClear={() => (this.error = '')} />\n <div class=\"test-runner-container__content\">\n <LLMTestCases\n testCases={this.testCases}\n onRun={testCase => this.runSingleTest(testCase).catch(() => {})}\n onDelete={id => this.deleteTestCase(id)}\n onUpdateApproach={(testCase, approach) =>\n this.updateApproach(testCase, approach)\n }\n onAddTestCase={() => this.addNewTestCase()}\n handleTestCaseChange={this.handleTestCaseChange}\n onExpectedOutcomeChange={this.handleExpectedOutcomeChange}\n />\n </div>\n </div>\n );\n }\n}\n"]}
|
|
1
|
+
{"version":3,"file":"llm-test-runner.js","sourceRoot":"","sources":["../../../src/components/llm-test-runner/llm-test-runner.tsx"],"names":[],"mappings":"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","sourcesContent":["import {\n Component,\n State,\n Prop,\n h,\n EventEmitter,\n Event,\n Method,\n} from '@stencil/core';\nimport { EvaluationResult } from '../../lib/evaluation/types';\nimport { ErrorMessage } from '../error-message/error-message';\nimport { RateLimitedFetcher } from '../../lib/rate-limited-fetcher/rate-limited-fetcher';\nimport {\n ExpectedOutcomeSchema,\n TestCase,\n LLMRequestPayload,\n SavePayload,\n} from '../../types/llm-test-runner';\nimport { readFileAsync } from '../../lib/file/file-reader';\nimport { downloadFile } from '../../lib/file/file-download';\nimport { formatTestSuiteAsJson } from '../../lib/import-export/test-suite-exporter';\nimport { exportTestResultsToCsv } from '../../lib/import-export/test-results-csv';\nimport { importTestSuite } from '../../lib/import-export/test-suite-importer';\nimport {\n createTestCase,\n createTestCaseFromInput,\n DEFAULT_EXPECTED_OUTCOME_SCHEMA,\n} from '../../lib/test-cases/test-case-factory';\nimport * as TestCaseMutations from '../../lib/test-cases/test-case-mutations';\nimport { EvaluationService } from '../../lib/evaluation/evaluation-service';\nimport { validateTestCaseInputArray } from '../../schemas/test-case';\nimport { validateExpectedOutcomeSchema } from '../../schemas/expected-outcome';\nimport { LLMTestRunnerHeader } from './header/llm-test-runner-header';\nimport { LLMTestCases } from './test-cases/llm-test-cases';\nimport { ExpectedOutcomeChangeDetail } from './test-cases/expected-outcome-renderer';\n\n@Component({\n tag: 'llm-test-runner',\n styleUrls: [\n '../../styles/tokens.css',\n 'llm-test-runner.css',\n 'header/llm-test-runner-header.css',\n 'test-cases/llm-test-cases.css',\n 'test-cases/llm-test-case-row.css',\n 'test-cases/actions/row-actions.css',\n 'test-cases/evaluation/evaluation-summary.css',\n 'test-cases/output/response-output.css',\n '../error-message/error-message.css',\n '../../lib/ui/button/button.css',\n '../../lib/ui/icon-button/icon-button.css',\n ],\n shadow: true,\n})\nexport class LLMTestRunner {\n @Event() llmRequest: EventEmitter<LLMRequestPayload>;\n @Event() save: EventEmitter<SavePayload>;\n @Prop() delayMs?: number = 500;\n @Prop() useSave?: boolean = false;\n @Prop() initialTestCases?: TestCase[];\n @Prop() defaultExpectedOutcomeSchema?: ExpectedOutcomeSchema;\n @State() testCases: TestCase[] = [\n {\n id: '1',\n question: '',\n expectedOutcome: [\n {\n type: 'textarea',\n label: 'Expected Outcome',\n value: '',\n },\n ],\n isRunning: false,\n },\n ];\n @State() isRunningAll: boolean = false;\n @State() error: string = '';\n @State() isExportingTestSuite: boolean = false;\n @State() isExportingTestResults: boolean = false;\n @State() isSaving: boolean = false;\n\n private evaluationService: EvaluationService;\n\n private getResolvedExpectedOutcomeSchema(): ExpectedOutcomeSchema {\n if (this.defaultExpectedOutcomeSchema === undefined) {\n return DEFAULT_EXPECTED_OUTCOME_SCHEMA;\n }\n\n validateExpectedOutcomeSchema(this.defaultExpectedOutcomeSchema);\n return this.defaultExpectedOutcomeSchema;\n }\n\n componentWillLoad() {\n this.evaluationService = new EvaluationService();\n try {\n // Initialize testCases from prop if provided\n if (this.initialTestCases !== undefined) {\n validateTestCaseInputArray(this.initialTestCases);\n this.testCases = this.initialTestCases.map((rawTestCase, index) => {\n try {\n return createTestCaseFromInput(rawTestCase);\n } catch (err) {\n const message = err instanceof Error ? err.message : 'Unknown error';\n throw new Error(`Invalid initial test case at index ${index}: ${message}`);\n }\n });\n } else {\n const schema = this.getResolvedExpectedOutcomeSchema();\n this.testCases = [createTestCase(schema)];\n }\n } catch (err) {\n this.error =\n err instanceof Error\n ? err.message\n : 'Invalid defaultExpectedOutcomeSchema provided.';\n this.testCases = [];\n }\n }\n\n componentDidLoad() {}\n\n disconnectedCallback() {}\n\n @Method()\n async resetSavingState(): Promise<void> {\n this.isSaving = false;\n }\n\n private handleTestCaseChange = (\n event: CustomEvent<{ testCaseId: string; key: string; value: string }>,\n ) => {\n const { testCaseId, key, value } = event.detail;\n this.testCases = this.testCases.map(tc =>\n tc.id === testCaseId ? { ...tc, [key]: value } : tc,\n );\n };\n\n private addNewTestCase() {\n try {\n const schema = this.getResolvedExpectedOutcomeSchema();\n const newTestCase = createTestCase(schema);\n this.testCases = [...this.testCases, newTestCase];\n } catch (err) {\n this.error =\n err instanceof Error\n ? err.message\n : 'Invalid defaultExpectedOutcomeSchema provided.';\n }\n }\n\n private updateTestCase(id: string, updates: Partial<TestCase>) {\n this.testCases = this.testCases.map(tc =>\n tc.id === id ? { ...tc, ...updates } : tc,\n );\n }\n\n private async runSingleTest(testCase: TestCase): Promise<void> {\n const startTime = Date.now();\n this.updateTestCase(testCase.id, { isRunning: true });\n return new Promise<void>((resolve, reject) => {\n this.llmRequest.emit({\n prompt: testCase.question,\n resolve: async (aiResponse: string) => {\n const endTime = Date.now();\n const responseTime = endTime - startTime;\n this.updateTestCase(testCase.id, {\n isRunning: false,\n output: aiResponse,\n error: null,\n responseTime: responseTime,\n });\n\n await this.evaluateResponse({\n ...testCase,\n output: aiResponse,\n responseTime: responseTime,\n });\n resolve();\n },\n reject: (error: Error | unknown) => {\n this.updateTestCase(testCase.id, {\n isRunning: false,\n output: null,\n error: error instanceof Error ? error.message : 'Unknown error',\n });\n reject(error);\n },\n });\n });\n }\n\n private deleteTestCase(id: string) {\n this.testCases = this.testCases.filter(tc => tc.id !== id);\n }\n\n private handleExpectedOutcomeChange = (\n event: CustomEvent<ExpectedOutcomeChangeDetail>,\n ) => {\n const { testCaseId, ...change } = event.detail;\n\n this.testCases = this.testCases.map(tc => {\n if (tc.id !== testCaseId) {\n return tc;\n }\n\n return TestCaseMutations.applyExpectedOutcomeChange(tc, change);\n });\n };\n\n private async evaluateResponse(testCase: TestCase): Promise<void> {\n await this.evaluationService.evaluateTestCase(\n testCase,\n (result: EvaluationResult) => {\n this.updateTestCase(testCase.id, {\n evaluationResult: result,\n });\n },\n );\n }\n\n private async runAllTests() {\n this.isRunningAll = true;\n const tasks = [];\n for (const testCase of this.testCases) {\n if (!testCase.isRunning && testCase.question.trim()) {\n tasks.push(() =>\n this.runSingleTest(testCase).catch(err => {\n console.error(`⚠️ Test case ${testCase.id} failed`, err);\n }),\n );\n }\n }\n try {\n const fetcher = new RateLimitedFetcher(this.delayMs);\n await fetcher.runAll(tasks);\n } catch (err) {\n console.error('⚠️ Error running all tests:', err);\n }\n this.isRunningAll = false;\n }\n\n private async handleImport(file: File): Promise<void> {\n const isJsonType = file.type === 'application/json';\n const isJsonExtension = file.name.toLowerCase().endsWith('.json');\n\n if (!isJsonType && !isJsonExtension) {\n this.error = 'Invalid file type. Please select a JSON file.';\n return;\n }\n\n this.error = '';\n\n try {\n const content = await readFileAsync(file);\n const result = importTestSuite(content);\n\n if (!result.success) {\n this.error = result.error || 'Unknown error occurred during import.';\n return;\n }\n\n this.testCases = result.testCases || [];\n } catch (err) {\n this.error =\n err instanceof Error\n ? err.message\n : 'Error processing file. Please ensure it is a valid JSON array.';\n console.error('File Processing Error:', err);\n }\n }\n\n private async handleExportTestSuite() {\n this.isExportingTestSuite = true;\n try {\n const jsonContent = formatTestSuiteAsJson(this.testCases);\n\n // Added a small delay to show the loading state\n await new Promise(resolve => setTimeout(resolve, 500));\n\n downloadFile(jsonContent, 'test-suite.json', 'application/json');\n } finally {\n this.isExportingTestSuite = false;\n }\n }\n\n private async handleExportTestResults() {\n this.isExportingTestResults = true;\n try {\n const csvContent = exportTestResultsToCsv(this.testCases);\n\n // Added a small delay to show the loading state\n await new Promise(resolve => setTimeout(resolve, 500));\n\n downloadFile(csvContent, 'test-results.csv', 'text/csv');\n } finally {\n this.isExportingTestResults = false;\n }\n }\n\n private async handleSave() {\n this.isSaving = true;\n try {\n const testRun = {\n timestamp: new Date().toISOString(),\n testCases: this.testCases,\n };\n this.save.emit(testRun);\n\n // Failsafe: Auto-reset saving state after 10 seconds to prevent stuck UI\n setTimeout(() => {\n if (this.isSaving) {\n console.warn('Save operation timed out, resetting state');\n this.isSaving = false;\n }\n }, 10000);\n } finally {\n // Parent will call resetSavingState() when actual save completes\n // If not called within 10 seconds, failsafe above will reset state\n }\n }\n\n render() {\n return (\n <div class=\"test-runner-container\">\n <LLMTestRunnerHeader\n isExportingTestSuite={this.isExportingTestSuite}\n isExportingTestResults={this.isExportingTestResults}\n isRunningAll={this.isRunningAll}\n useSave={this.useSave}\n isSaving={this.isSaving}\n onImport={file => this.handleImport(file)}\n onExportSuite={() => this.handleExportTestSuite()}\n onExportResults={() => this.handleExportTestResults()}\n onRunAll={() => this.runAllTests()}\n onSave={() => this.handleSave()}\n />\n <ErrorMessage message={this.error} onClear={() => (this.error = '')} />\n <div class=\"test-runner-container__content\">\n <LLMTestCases\n testCases={this.testCases}\n onRun={testCase => this.runSingleTest(testCase).catch(() => {})}\n onDelete={id => this.deleteTestCase(id)}\n onAddTestCase={() => this.addNewTestCase()}\n handleTestCaseChange={this.handleTestCaseChange}\n onExpectedOutcomeChange={this.handleExpectedOutcomeChange}\n />\n </div>\n </div>\n );\n }\n}\n"]}
|
package/dist/collection/components/llm-test-runner/test-cases/evaluation/evaluation-summary.css
CHANGED
|
@@ -7,49 +7,88 @@
|
|
|
7
7
|
flex-direction: column;
|
|
8
8
|
}
|
|
9
9
|
|
|
10
|
-
.evaluation-
|
|
10
|
+
.evaluation-summary__field-results {
|
|
11
11
|
display: flex;
|
|
12
12
|
flex-direction: column;
|
|
13
13
|
gap: var(--spacing-2);
|
|
14
|
+
margin-top: var(--spacing-2);
|
|
14
15
|
}
|
|
15
16
|
|
|
16
|
-
.evaluation-
|
|
17
|
+
.evaluation-summary__field-result {
|
|
18
|
+
border: var(--border-width) solid var(--border);
|
|
19
|
+
border-radius: var(--radius-md);
|
|
20
|
+
padding: var(--spacing-2);
|
|
17
21
|
display: flex;
|
|
18
|
-
|
|
19
|
-
|
|
22
|
+
flex-direction: column;
|
|
23
|
+
gap: var(--spacing-1);
|
|
24
|
+
}
|
|
25
|
+
|
|
26
|
+
.evaluation-summary__field-header {
|
|
27
|
+
display: flex;
|
|
28
|
+
flex-direction: column;
|
|
29
|
+
gap: var(--spacing-1);
|
|
30
|
+
}
|
|
31
|
+
|
|
32
|
+
.evaluation-summary__field-label {
|
|
33
|
+
font-weight: var(--font-weight-semibold);
|
|
34
|
+
font-size: var(--font-size-xs);
|
|
35
|
+
}
|
|
36
|
+
|
|
37
|
+
.evaluation-summary__field-approach {
|
|
20
38
|
color: var(--muted-foreground);
|
|
21
|
-
font-
|
|
22
|
-
flex: 1;
|
|
23
|
-
background: var(--muted);
|
|
24
|
-
border: 2px dashed var(--border);
|
|
25
|
-
border-radius: var(--radius);
|
|
39
|
+
font-size: 11px;
|
|
26
40
|
}
|
|
27
41
|
|
|
28
|
-
|
|
29
|
-
.evaluation-summary__result {
|
|
42
|
+
.evaluation-summary__field-details {
|
|
30
43
|
display: flex;
|
|
31
44
|
flex-direction: column;
|
|
32
|
-
gap: var(--spacing-
|
|
45
|
+
gap: var(--spacing-1);
|
|
46
|
+
font-size: var(--font-size-xs);
|
|
33
47
|
}
|
|
34
48
|
|
|
35
|
-
.evaluation-
|
|
49
|
+
.evaluation-summary__field-status {
|
|
50
|
+
width: fit-content;
|
|
51
|
+
padding: 2px var(--spacing-2);
|
|
52
|
+
border-radius: var(--radius-sm);
|
|
53
|
+
font-size: 11px;
|
|
36
54
|
font-weight: var(--font-weight-semibold);
|
|
37
|
-
|
|
38
|
-
padding: var(--spacing-2) var(--spacing-3);
|
|
39
|
-
border-radius: var(--radius-md);
|
|
40
|
-
text-align: center;
|
|
55
|
+
border: var(--border-width) solid transparent;
|
|
41
56
|
}
|
|
42
57
|
|
|
43
|
-
.evaluation-
|
|
58
|
+
.evaluation-summary__field-status--passed {
|
|
44
59
|
background: var(--success);
|
|
45
60
|
color: var(--success-foreground);
|
|
46
|
-
border: var(--
|
|
61
|
+
border-color: var(--success);
|
|
47
62
|
}
|
|
48
63
|
|
|
49
|
-
.evaluation-
|
|
64
|
+
.evaluation-summary__field-status--failed {
|
|
50
65
|
background: var(--destructive);
|
|
51
66
|
color: var(--destructive-foreground);
|
|
52
|
-
border: var(--
|
|
67
|
+
border-color: var(--destructive);
|
|
68
|
+
}
|
|
69
|
+
|
|
70
|
+
.evaluation-summary__error-message {
|
|
71
|
+
color: var(--destructive);
|
|
72
|
+
font-size: var(--font-size-xs);
|
|
73
|
+
}
|
|
74
|
+
|
|
75
|
+
.evaluation-summary__placeholder {
|
|
76
|
+
display: flex;
|
|
77
|
+
align-items: center;
|
|
78
|
+
justify-content: center;
|
|
79
|
+
color: var(--muted-foreground);
|
|
80
|
+
font-style: italic;
|
|
81
|
+
flex: 1;
|
|
82
|
+
background: var(--muted);
|
|
83
|
+
border: 2px dashed var(--border);
|
|
84
|
+
border-radius: var(--radius);
|
|
85
|
+
}
|
|
86
|
+
|
|
87
|
+
/* Evaluation Result Element */
|
|
88
|
+
.evaluation-summary__result {
|
|
89
|
+
display: flex;
|
|
90
|
+
flex-direction: column;
|
|
91
|
+
gap: var(--spacing-2);
|
|
53
92
|
}
|
|
54
93
|
|
|
55
94
|
/* Responsive Design */
|
package/dist/collection/components/llm-test-runner/test-cases/evaluation/evaluation-summary.js
CHANGED
|
@@ -1,5 +1,7 @@
|
|
|
1
1
|
import { h } from "@stencil/core";
|
|
2
2
|
export const EvaluationSummary = ({ result, isRunning, }) => {
|
|
3
|
-
|
|
3
|
+
const fieldResults = result?.fieldResults || [];
|
|
4
|
+
const hasFieldResults = fieldResults.length > 0;
|
|
5
|
+
return (h("div", { class: "evaluation-summary" }, result ? (h("div", { class: "evaluation-summary__result" }, hasFieldResults ? (h("div", { class: "evaluation-summary__field-results" }, fieldResults.map(fieldResult => (h("div", { class: "evaluation-summary__field-result" }, h("div", { class: "evaluation-summary__field-header" }, h("span", { class: "evaluation-summary__field-label" }, fieldResult.label), h("span", { class: "evaluation-summary__field-approach" }, "Strategy: ", fieldResult.evaluationParameters.approach)), h("div", { class: "evaluation-summary__field-details" }, h("span", { class: `evaluation-summary__field-status evaluation-summary__field-status--${fieldResult.passed ? 'passed' : 'failed'}` }, fieldResult.passed ? 'PASSED' : 'FAILED'), fieldResult.error && (h("span", { class: "evaluation-summary__error-message" }, fieldResult.error)), h("span", null, "Score: ", fieldResult.evaluationApproachResult.score.toFixed(2)), h("span", null, "Matches:", ' ', fieldResult.keywordMatches.filter(match => match.found).length, "/", fieldResult.keywordMatches.length))))))) : null)) : (h("div", { class: "evaluation-summary__placeholder" }, isRunning ? 'Evaluating...' : ''))));
|
|
4
6
|
};
|
|
5
7
|
//# sourceMappingURL=evaluation-summary.js.map
|
package/dist/collection/components/llm-test-runner/test-cases/evaluation/evaluation-summary.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"evaluation-summary.js","sourceRoot":"","sources":["../../../../../src/components/llm-test-runner/test-cases/evaluation/evaluation-summary.tsx"],"names":[],"mappings":"AAAA,OAAO,EAAE,CAAC,EAAuB,MAAM,eAAe,CAAC;AAQvD,MAAM,CAAC,MAAM,iBAAiB,GAAgD,CAAC,EAC7E,MAAM,EACN,SAAS,GACV,EAAE,EAAE;IACH,OAAO,CACL,WAAK,KAAK,EAAC,oBAAoB,IAC5B,MAAM,CAAC,CAAC,CAAC,CACR,WAAK,KAAK,EAAC,4BAA4B;
|
|
1
|
+
{"version":3,"file":"evaluation-summary.js","sourceRoot":"","sources":["../../../../../src/components/llm-test-runner/test-cases/evaluation/evaluation-summary.tsx"],"names":[],"mappings":"AAAA,OAAO,EAAE,CAAC,EAAuB,MAAM,eAAe,CAAC;AAQvD,MAAM,CAAC,MAAM,iBAAiB,GAAgD,CAAC,EAC7E,MAAM,EACN,SAAS,GACV,EAAE,EAAE;IACH,MAAM,YAAY,GAAG,MAAM,EAAE,YAAY,IAAI,EAAE,CAAC;IAChD,MAAM,eAAe,GAAG,YAAY,CAAC,MAAM,GAAG,CAAC,CAAC;IAEhD,OAAO,CACL,WAAK,KAAK,EAAC,oBAAoB,IAC5B,MAAM,CAAC,CAAC,CAAC,CACR,WAAK,KAAK,EAAC,4BAA4B,IACpC,eAAe,CAAC,CAAC,CAAC,CACjB,WAAK,KAAK,EAAC,mCAAmC,IAC3C,YAAY,CAAC,GAAG,CAAC,WAAW,CAAC,EAAE,CAAC,CAC/B,WAAK,KAAK,EAAC,kCAAkC;QAC3C,WAAK,KAAK,EAAC,kCAAkC;YAC3C,YAAM,KAAK,EAAC,iCAAiC,IAC1C,WAAW,CAAC,KAAK,CACb;YACP,YAAM,KAAK,EAAC,oCAAoC;;gBACnC,WAAW,CAAC,oBAAoB,CAAC,QAAQ,CAC/C,CACH;QACN,WAAK,KAAK,EAAC,mCAAmC;YAC5C,YACE,KAAK,EAAE,sEAAsE,WAAW,CAAC,MAAM,CAAC,CAAC,CAAC,QAAQ,CAAC,CAAC,CAAC,QAAQ,EAAE,IAEtH,WAAW,CAAC,MAAM,CAAC,CAAC,CAAC,QAAQ,CAAC,CAAC,CAAC,QAAQ,CACpC;YACN,WAAW,CAAC,KAAK,IAAI,CACpB,YAAM,KAAK,EAAC,mCAAmC,IAC5C,WAAW,CAAC,KAAK,CACb,CACR;YACD;;gBACU,WAAW,CAAC,wBAAwB,CAAC,KAAK,CAAC,OAAO,CAAC,CAAC,CAAC,CACxD;YACP;;gBACW,GAAG;gBACX,WAAW,CAAC,cAAc,CAAC,MAAM,CAAC,KAAK,CAAC,EAAE,CAAC,KAAK,CAAC,KAAK,CAAC,CAAC,MAAM;;gBAC9D,WAAW,CAAC,cAAc,CAAC,MAAM,CAC7B,CACH,CACF,CACP,CAAC,CACE,CACP,CAAC,CAAC,CAAC,IAAI,CACJ,CACP,CAAC,CAAC,CAAC,CACF,WAAK,KAAK,EAAC,iCAAiC,IACzC,SAAS,CAAC,CAAC,CAAC,eAAe,CAAC,CAAC,CAAC,EAAE,CAC7B,CACP,CACG,CACP,CAAC;AACJ,CAAC,CAAC","sourcesContent":["import { h, FunctionalComponent } from '@stencil/core';\nimport { EvaluationResult } from '../../../../lib/evaluation/types';\n\nexport interface EvaluationSummaryProps {\n result?: EvaluationResult;\n isRunning: boolean;\n}\n\nexport const EvaluationSummary: FunctionalComponent<EvaluationSummaryProps> = ({\n result,\n isRunning,\n}) => {\n const fieldResults = result?.fieldResults || [];\n const hasFieldResults = fieldResults.length > 0;\n\n return (\n <div class=\"evaluation-summary\">\n {result ? (\n <div class=\"evaluation-summary__result\">\n {hasFieldResults ? (\n <div class=\"evaluation-summary__field-results\">\n {fieldResults.map(fieldResult => (\n <div class=\"evaluation-summary__field-result\">\n <div class=\"evaluation-summary__field-header\">\n <span class=\"evaluation-summary__field-label\">\n {fieldResult.label}\n </span>\n <span class=\"evaluation-summary__field-approach\">\n Strategy: {fieldResult.evaluationParameters.approach}\n </span>\n </div>\n <div class=\"evaluation-summary__field-details\">\n <span\n class={`evaluation-summary__field-status evaluation-summary__field-status--${fieldResult.passed ? 'passed' : 'failed'}`}\n >\n {fieldResult.passed ? 'PASSED' : 'FAILED'}\n </span>\n {fieldResult.error && (\n <span class=\"evaluation-summary__error-message\">\n {fieldResult.error}\n </span>\n )}\n <span>\n Score: {fieldResult.evaluationApproachResult.score.toFixed(2)}\n </span>\n <span>\n Matches:{' '}\n {fieldResult.keywordMatches.filter(match => match.found).length}/\n {fieldResult.keywordMatches.length}\n </span>\n </div>\n </div>\n ))}\n </div>\n ) : null}\n </div>\n ) : (\n <div class=\"evaluation-summary__placeholder\">\n {isRunning ? 'Evaluating...' : ''}\n </div>\n )}\n </div>\n );\n};\n"]}
|