llm-testrunner-components 1.2.2 → 1.2.4

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.
Files changed (98) hide show
  1. package/dist/cjs/{app-chips_4.cjs.entry.js → app-chips_5.cjs.entry.js} +41 -6
  2. package/dist/cjs/app-chips_5.cjs.entry.js.map +1 -0
  3. package/dist/cjs/index.cjs.js +235 -44
  4. package/dist/cjs/index.cjs.js.map +1 -1
  5. package/dist/cjs/llm-testrunner.cjs.js +1 -1
  6. package/dist/cjs/loader.cjs.js +1 -1
  7. package/dist/collection/collection-manifest.json +1 -0
  8. package/dist/collection/components/llm-test-runner/llm-test-runner.import-export.test.js +22 -12
  9. package/dist/collection/components/llm-test-runner/llm-test-runner.import-export.test.js.map +1 -1
  10. package/dist/collection/components/llm-test-runner/llm-test-runner.js +91 -30
  11. package/dist/collection/components/llm-test-runner/llm-test-runner.js.map +1 -1
  12. package/dist/collection/components/llm-test-runner/test-cases/chat-history.css +101 -0
  13. package/dist/collection/components/llm-test-runner/test-cases/chat-history.js +105 -0
  14. package/dist/collection/components/llm-test-runner/test-cases/chat-history.js.map +1 -0
  15. package/dist/collection/components/llm-test-runner/test-cases/expected-outcome-renderer.js +37 -4
  16. package/dist/collection/components/llm-test-runner/test-cases/expected-outcome-renderer.js.map +1 -1
  17. package/dist/collection/components/llm-test-runner/test-cases/llm-test-case-row.js +12 -2
  18. package/dist/collection/components/llm-test-runner/test-cases/llm-test-case-row.js.map +1 -1
  19. package/dist/collection/components/llm-test-runner/test-cases/llm-test-cases.js +2 -2
  20. package/dist/collection/components/llm-test-runner/test-cases/llm-test-cases.js.map +1 -1
  21. package/dist/collection/index.js.map +1 -1
  22. package/dist/collection/lib/evaluation/evaluation-service.js +14 -7
  23. package/dist/collection/lib/evaluation/evaluation-service.js.map +1 -1
  24. package/dist/collection/lib/form/components/app-chips.js +1 -1
  25. package/dist/collection/lib/form/components/app-select.js +1 -1
  26. package/dist/collection/lib/form/components/app-textarea.css +17 -0
  27. package/dist/collection/lib/form/components/app-textarea.js +4 -1
  28. package/dist/collection/lib/form/components/app-textarea.js.map +1 -1
  29. package/dist/collection/lib/import-export/test-suite-exporter.js +4 -0
  30. package/dist/collection/lib/import-export/test-suite-exporter.js.map +1 -1
  31. package/dist/collection/lib/test-cases/dynamic-expected-outcome-resolver.js +44 -0
  32. package/dist/collection/lib/test-cases/dynamic-expected-outcome-resolver.js.map +1 -0
  33. package/dist/collection/lib/test-cases/test-case-factory.js +2 -0
  34. package/dist/collection/lib/test-cases/test-case-factory.js.map +1 -1
  35. package/dist/collection/lib/test-cases/test-case-mutations.js +35 -0
  36. package/dist/collection/lib/test-cases/test-case-mutations.js.map +1 -1
  37. package/dist/collection/schemas/expected-outcome.js +15 -1
  38. package/dist/collection/schemas/expected-outcome.js.map +1 -1
  39. package/dist/collection/schemas/test-case.js +6 -0
  40. package/dist/collection/schemas/test-case.js.map +1 -1
  41. package/dist/collection/types/expected-outcome.js.map +1 -1
  42. package/dist/collection/types/llm-test-runner.js.map +1 -1
  43. package/dist/collection/types/test-case.js.map +1 -1
  44. package/dist/components/app-chips.js +1 -1
  45. package/dist/components/app-select.js +1 -1
  46. package/dist/components/app-textarea.js +1 -1
  47. package/dist/components/chat-history.d.ts +11 -0
  48. package/dist/components/chat-history.js +2 -0
  49. package/dist/components/chat-history.js.map +1 -0
  50. package/dist/components/index.js +1 -1
  51. package/dist/components/llm-test-runner.js +1 -1
  52. package/dist/components/{p-CJBscebi.js → p-B87Lt3z4.js} +3 -3
  53. package/dist/components/p-B87Lt3z4.js.map +1 -0
  54. package/dist/components/p-Bx2jqguC.js +2 -0
  55. package/dist/components/p-Bx2jqguC.js.map +1 -0
  56. package/dist/components/p-D2qDAxFN.js +2 -0
  57. package/dist/components/p-D2qDAxFN.js.map +1 -0
  58. package/dist/components/{p-Dv7cB5FU.js → p-D4dHUFN9.js} +2 -2
  59. package/dist/components/{p-CE5-1jfZ.js → p-eN2dLrsr.js} +2 -2
  60. package/dist/esm/{app-chips_4.entry.js → app-chips_5.entry.js} +41 -7
  61. package/dist/esm/app-chips_5.entry.js.map +1 -0
  62. package/dist/esm/index.js +235 -44
  63. package/dist/esm/index.js.map +1 -1
  64. package/dist/esm/llm-testrunner.js +1 -1
  65. package/dist/esm/loader.js +1 -1
  66. package/dist/llm-testrunner/index.esm.js +2 -2
  67. package/dist/llm-testrunner/index.esm.js.map +1 -1
  68. package/dist/llm-testrunner/llm-testrunner.esm.js +1 -1
  69. package/dist/llm-testrunner/p-21202f12.entry.js +2 -0
  70. package/dist/llm-testrunner/p-21202f12.entry.js.map +1 -0
  71. package/dist/react/components.d.ts +6 -1
  72. package/dist/react/components.d.ts.map +1 -1
  73. package/dist/react/components.js +9 -0
  74. package/dist/types/components/llm-test-runner/llm-test-runner.d.ts +6 -0
  75. package/dist/types/components/llm-test-runner/test-cases/chat-history.d.ts +14 -0
  76. package/dist/types/components/llm-test-runner/test-cases/expected-outcome-renderer.d.ts +1 -0
  77. package/dist/types/components/llm-test-runner/test-cases/llm-test-case-row.d.ts +6 -0
  78. package/dist/types/components/llm-test-runner/test-cases/llm-test-cases.d.ts +3 -0
  79. package/dist/types/components.d.ts +55 -0
  80. package/dist/types/index.d.ts +1 -1
  81. package/dist/types/lib/import-export/test-suite-exporter.d.ts +4 -0
  82. package/dist/types/lib/test-cases/dynamic-expected-outcome-resolver.d.ts +7 -0
  83. package/dist/types/lib/test-cases/test-case-mutations.d.ts +9 -1
  84. package/dist/types/schemas/expected-outcome.d.ts +16 -1
  85. package/dist/types/schemas/test-case.d.ts +34 -2
  86. package/dist/types/types/expected-outcome.d.ts +1 -1
  87. package/dist/types/types/llm-test-runner.d.ts +3 -2
  88. package/dist/types/types/test-case.d.ts +1 -1
  89. package/package.json +1 -1
  90. package/dist/cjs/app-chips_4.cjs.entry.js.map +0 -1
  91. package/dist/components/p-BZrzx5jG.js +0 -2
  92. package/dist/components/p-BZrzx5jG.js.map +0 -1
  93. package/dist/components/p-CJBscebi.js.map +0 -1
  94. package/dist/esm/app-chips_4.entry.js.map +0 -1
  95. package/dist/llm-testrunner/p-2cc09217.entry.js +0 -2
  96. package/dist/llm-testrunner/p-2cc09217.entry.js.map +0 -1
  97. /package/dist/components/{p-Dv7cB5FU.js.map → p-D4dHUFN9.js.map} +0 -0
  98. /package/dist/components/{p-CE5-1jfZ.js.map → p-eN2dLrsr.js.map} +0 -0
@@ -19,7 +19,7 @@ var patchBrowser = () => {
19
19
 
20
20
  patchBrowser().then(async (options) => {
21
21
  await appGlobals.globalScripts();
22
- return index.bootstrapLazy([["app-chips_4.cjs",[[513,"llm-test-runner",{"delayMs":[2,"delay-ms"],"useSave":[4,"use-save"],"usePromptEditor":[4,"use-prompt-editor"],"initialTestCases":[16],"defaultExpectedOutcomeSchema":[16],"testCases":[32],"isRunningAll":[32],"error":[32],"isExportingTestSuite":[32],"isExportingTestResults":[32],"isSaving":[32],"resetSavingState":[64],"getTestCases":[64]}],[513,"app-chips",{"value":[16],"config":[16]}],[513,"app-select",{"value":[1],"config":[16]}],[513,"app-textarea",{"value":[1],"config":[16]}]]]], options);
22
+ return index.bootstrapLazy([["app-chips_5.cjs",[[513,"llm-test-runner",{"delayMs":[2,"delay-ms"],"useSave":[4,"use-save"],"usePromptEditor":[4,"use-prompt-editor"],"resolveExpectedOutcome":[16],"initialTestCases":[16],"defaultExpectedOutcomeSchema":[16],"testCases":[32],"isRunningAll":[32],"error":[32],"isExportingTestSuite":[32],"isExportingTestResults":[32],"isSaving":[32],"resetSavingState":[64],"getTestCases":[64]}],[513,"app-chips",{"value":[16],"config":[16]}],[513,"app-select",{"value":[1],"config":[16]}],[513,"app-textarea",{"value":[1],"config":[16]}],[513,"chat-history",{"chatHistoryEnabled":[4,"chat-history-enabled"],"chatHistoryValue":[1,"chat-history-value"]}]]]], options);
23
23
  });
24
24
 
25
25
  exports.setNonce = index.setNonce;
@@ -6,7 +6,7 @@ var appGlobals = require('./app-globals-Chb-oJtg.js');
6
6
  const defineCustomElements = async (win, options) => {
7
7
  if (typeof window === 'undefined') return undefined;
8
8
  await appGlobals.globalScripts();
9
- return index.bootstrapLazy([["app-chips_4.cjs",[[513,"llm-test-runner",{"delayMs":[2,"delay-ms"],"useSave":[4,"use-save"],"usePromptEditor":[4,"use-prompt-editor"],"initialTestCases":[16],"defaultExpectedOutcomeSchema":[16],"testCases":[32],"isRunningAll":[32],"error":[32],"isExportingTestSuite":[32],"isExportingTestResults":[32],"isSaving":[32],"resetSavingState":[64],"getTestCases":[64]}],[513,"app-chips",{"value":[16],"config":[16]}],[513,"app-select",{"value":[1],"config":[16]}],[513,"app-textarea",{"value":[1],"config":[16]}]]]], options);
9
+ return index.bootstrapLazy([["app-chips_5.cjs",[[513,"llm-test-runner",{"delayMs":[2,"delay-ms"],"useSave":[4,"use-save"],"usePromptEditor":[4,"use-prompt-editor"],"resolveExpectedOutcome":[16],"initialTestCases":[16],"defaultExpectedOutcomeSchema":[16],"testCases":[32],"isRunningAll":[32],"error":[32],"isExportingTestSuite":[32],"isExportingTestResults":[32],"isSaving":[32],"resetSavingState":[64],"getTestCases":[64]}],[513,"app-chips",{"value":[16],"config":[16]}],[513,"app-select",{"value":[1],"config":[16]}],[513,"app-textarea",{"value":[1],"config":[16]}],[513,"chat-history",{"chatHistoryEnabled":[4,"chat-history-enabled"],"chatHistoryValue":[1,"chat-history-value"]}]]]], options);
10
10
  };
11
11
 
12
12
  exports.setNonce = index.setNonce;
@@ -1,5 +1,6 @@
1
1
  {
2
2
  "entries": [
3
+ "components/llm-test-runner/test-cases/chat-history.js",
3
4
  "components/llm-test-runner/llm-test-runner.js",
4
5
  "lib/form/components/app-chips.js",
5
6
  "lib/form/components/app-select.js",
@@ -15,6 +15,7 @@ import { downloadFile } from "../../lib/file/file-download";
15
15
  import { formatTestSuiteAsJson } from "../../lib/import-export/test-suite-exporter";
16
16
  import { importTestSuite } from "../../lib/import-export/test-suite-importer";
17
17
  import { EvaluationApproach } from "../../lib/evaluation/constants";
18
+ const emptyChatHistory = { enabled: false, value: '' };
18
19
  describe('llm-test-runner import/export', () => {
19
20
  let page;
20
21
  let component;
@@ -30,7 +31,8 @@ describe('llm-test-runner import/export', () => {
30
31
  id: '1',
31
32
  question: 'What is AI?',
32
33
  expectedOutcome: buildExpectedOutcome('artificial intelligence'),
33
- isRunning: false
34
+ chatHistory: { enabled: false, value: '' },
35
+ isRunning: false,
34
36
  };
35
37
  return {
36
38
  ...defaults,
@@ -56,8 +58,9 @@ describe('llm-test-runner import/export', () => {
56
58
  id: '1',
57
59
  question: 'What is AI?',
58
60
  expectedOutcome: buildExpectedOutcome('artificial intelligence'),
59
- isRunning: false
60
- }
61
+ chatHistory: { ...emptyChatHistory },
62
+ isRunning: false,
63
+ },
61
64
  ];
62
65
  const mockFile = createMockFile(JSON.stringify(mockTestData), 'test-suite.json');
63
66
  // Mock the utility functions
@@ -81,8 +84,9 @@ describe('llm-test-runner import/export', () => {
81
84
  id: '1',
82
85
  question: 'Test question',
83
86
  expectedOutcome: buildExpectedOutcome('test'),
84
- isRunning: false
85
- }
87
+ chatHistory: { ...emptyChatHistory },
88
+ isRunning: false,
89
+ },
86
90
  ];
87
91
  const normalizedImportData = [
88
92
  {
@@ -98,6 +102,7 @@ describe('llm-test-runner import/export', () => {
98
102
  },
99
103
  },
100
104
  ],
105
+ chatHistory: { ...emptyChatHistory },
101
106
  isRunning: false,
102
107
  },
103
108
  ];
@@ -121,14 +126,16 @@ describe('llm-test-runner import/export', () => {
121
126
  id: '1',
122
127
  question: 'What is AI?',
123
128
  expectedOutcome: buildExpectedOutcome('artificial intelligence'),
124
- isRunning: false
129
+ chatHistory: { ...emptyChatHistory },
130
+ isRunning: false,
125
131
  },
126
132
  {
127
133
  id: '2',
128
134
  question: 'What is ML?',
129
135
  expectedOutcome: buildExpectedOutcome('machine learning'),
130
- isRunning: false
131
- }
136
+ chatHistory: { ...emptyChatHistory },
137
+ isRunning: false,
138
+ },
132
139
  ];
133
140
  const mockFile = createMockFile(JSON.stringify(mockTestData), 'test.json');
134
141
  readFileAsync.mockResolvedValue(JSON.stringify(mockTestData));
@@ -148,20 +155,23 @@ describe('llm-test-runner import/export', () => {
148
155
  id: '1',
149
156
  question: 'Q1',
150
157
  expectedOutcome: buildExpectedOutcome('answer1'),
151
- isRunning: false
158
+ chatHistory: { ...emptyChatHistory },
159
+ isRunning: false,
152
160
  },
153
161
  {
154
162
  id: '2',
155
163
  question: 'Q2',
156
164
  expectedOutcome: buildExpectedOutcome('answer2'),
157
- isRunning: false
165
+ chatHistory: { ...emptyChatHistory },
166
+ isRunning: false,
158
167
  },
159
168
  {
160
169
  id: '3',
161
170
  question: 'Q3',
162
171
  expectedOutcome: buildExpectedOutcome('answer3'),
163
- isRunning: false
164
- }
172
+ chatHistory: { ...emptyChatHistory },
173
+ isRunning: false,
174
+ },
165
175
  ];
166
176
  const mockFile = createMockFile(JSON.stringify(mockTestData), 'test.json');
167
177
  readFileAsync.mockResolvedValue(JSON.stringify(mockTestData));
@@ -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 { 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
+ {"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 { 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\nconst emptyChatHistory = { enabled: false, value: '' } as const;\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 chatHistory: { enabled: false, value: '' },\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 chatHistory: { ...emptyChatHistory },\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 chatHistory: { ...emptyChatHistory },\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 chatHistory: { ...emptyChatHistory },\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 chatHistory: { ...emptyChatHistory },\n isRunning: false,\n },\n {\n id: '2',\n question: 'What is ML?',\n expectedOutcome: buildExpectedOutcome('machine learning'),\n chatHistory: { ...emptyChatHistory },\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 chatHistory: { ...emptyChatHistory },\n isRunning: false,\n },\n {\n id: '2',\n question: 'Q2',\n expectedOutcome: buildExpectedOutcome('answer2'),\n chatHistory: { ...emptyChatHistory },\n isRunning: false,\n },\n {\n id: '3',\n question: 'Q3',\n expectedOutcome: buildExpectedOutcome('answer3'),\n chatHistory: { ...emptyChatHistory },\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});"]}
@@ -7,6 +7,7 @@ import { formatTestSuiteAsJson } from "../../lib/import-export/test-suite-export
7
7
  import { exportTestResultsToCsv } from "../../lib/import-export/test-results-csv";
8
8
  import { importTestSuite } from "../../lib/import-export/test-suite-importer";
9
9
  import { createTestCase, createTestCaseFromInput, DEFAULT_EXPECTED_OUTCOME_SCHEMA, } from "../../lib/test-cases/test-case-factory";
10
+ import { resolveDynamicExpectedOutcomes, } from "../../lib/test-cases/dynamic-expected-outcome-resolver";
10
11
  import * as TestCaseMutations from "../../lib/test-cases/test-case-mutations";
11
12
  import { EvaluationService } from "../../lib/evaluation/evaluation-service";
12
13
  import { validateTestCaseInputArray } from "../../schemas/test-case";
@@ -19,6 +20,7 @@ export class LLMTestRunner {
19
20
  delayMs = 500;
20
21
  useSave = false;
21
22
  usePromptEditor = false;
23
+ resolveExpectedOutcome;
22
24
  initialTestCases;
23
25
  defaultExpectedOutcomeSchema;
24
26
  testCases = [
@@ -32,6 +34,7 @@ export class LLMTestRunner {
32
34
  value: '',
33
35
  },
34
36
  ],
37
+ chatHistory: { enabled: false, value: '' },
35
38
  isRunning: false,
36
39
  },
37
40
  ];
@@ -89,6 +92,12 @@ export class LLMTestRunner {
89
92
  const { testCaseId, key, value } = event.detail;
90
93
  this.testCases = this.testCases.map(tc => tc.id === testCaseId ? { ...tc, [key]: value } : tc);
91
94
  };
95
+ handleChatHistoryChange = (event) => {
96
+ const { testCaseId, enabled, value } = event.detail;
97
+ this.updateTestCase(testCaseId, {
98
+ chatHistory: { enabled, value },
99
+ });
100
+ };
92
101
  addNewTestCase() {
93
102
  try {
94
103
  const schema = this.getResolvedExpectedOutcomeSchema();
@@ -105,38 +114,66 @@ export class LLMTestRunner {
105
114
  updateTestCase(id, updates) {
106
115
  this.testCases = this.testCases.map(tc => tc.id === id ? { ...tc, ...updates } : tc);
107
116
  }
117
+ requestLlmText(testCase) {
118
+ return new Promise((resolve, reject) => {
119
+ const payload = {
120
+ prompt: testCase.question,
121
+ resolve,
122
+ reject,
123
+ };
124
+ if (testCase.chatHistory?.enabled) {
125
+ payload.chatHistory = testCase.chatHistory.value;
126
+ }
127
+ this.llmRequest.emit(payload);
128
+ });
129
+ }
130
+ throwError(reason) {
131
+ throw reason instanceof Error ? reason : new Error(String(reason));
132
+ }
133
+ addErrorMessage(reason, fallback) {
134
+ return reason instanceof Error ? reason.message : fallback;
135
+ }
108
136
  async runSingleTest(testCase) {
109
137
  const startTime = Date.now();
110
138
  this.updateTestCase(testCase.id, { isRunning: true });
111
- return new Promise((resolve, reject) => {
112
- this.llmRequest.emit({
113
- prompt: testCase.question,
114
- resolve: async (aiResponse) => {
115
- const endTime = Date.now();
116
- const responseTime = endTime - startTime;
117
- this.updateTestCase(testCase.id, {
118
- isRunning: false,
119
- output: aiResponse,
120
- error: null,
121
- responseTime: responseTime,
122
- });
123
- await this.evaluateResponse({
124
- ...testCase,
125
- output: aiResponse,
126
- responseTime: responseTime,
127
- });
128
- resolve();
129
- },
130
- reject: (error) => {
131
- this.updateTestCase(testCase.id, {
132
- isRunning: false,
133
- output: null,
134
- error: error instanceof Error ? error.message : 'Unknown error',
135
- });
136
- reject(error);
137
- },
139
+ const [llmSettled, resolutionSettled] = await Promise.allSettled([
140
+ this.requestLlmText(testCase),
141
+ resolveDynamicExpectedOutcomes(testCase, this.resolveExpectedOutcome),
142
+ ]);
143
+ const responseTime = Date.now() - startTime;
144
+ if (llmSettled.status === 'rejected') {
145
+ this.updateTestCase(testCase.id, {
146
+ isRunning: false,
147
+ output: null,
148
+ error: this.addErrorMessage(llmSettled.reason, 'Unknown error'),
149
+ responseTime,
138
150
  });
151
+ this.throwError(llmSettled.reason);
152
+ }
153
+ const aiResponse = llmSettled.value;
154
+ if (resolutionSettled.status === 'rejected') {
155
+ this.updateTestCase(testCase.id, {
156
+ isRunning: false,
157
+ output: aiResponse,
158
+ error: this.addErrorMessage(resolutionSettled.reason, 'Failed to resolve dynamic expected outcome.'),
159
+ responseTime,
160
+ });
161
+ this.throwError(resolutionSettled.reason);
162
+ }
163
+ const resolvedTestCase = resolutionSettled.value;
164
+ const forEvaluationTestCase = {
165
+ ...resolvedTestCase,
166
+ output: aiResponse,
167
+ responseTime,
168
+ };
169
+ this.updateTestCase(testCase.id, {
170
+ isRunning: false,
171
+ output: aiResponse,
172
+ error: null,
173
+ responseTime,
174
+ expectedOutcome: forEvaluationTestCase.expectedOutcome,
139
175
  });
176
+ await this.evaluateResponse(forEvaluationTestCase);
140
177
  }
141
178
  deleteTestCase(id) {
142
179
  this.testCases = this.testCases.filter(tc => tc.id !== id);
@@ -247,7 +284,7 @@ export class LLMTestRunner {
247
284
  }
248
285
  }
249
286
  render() {
250
- return (h("div", { key: '29cf8a93402ebad6f6df43e147fa10406577c9aa', class: "test-runner-container" }, h(LLMTestRunnerHeader, { key: 'a07d3d1d823f8d473808752932cd1b2ab72d9e08', isExportingTestSuite: this.isExportingTestSuite, isExportingTestResults: this.isExportingTestResults, isRunningAll: this.isRunningAll, useSave: this.useSave, isSaving: this.isSaving, usePromptEditor: this.usePromptEditor, onImport: file => this.handleImport(file), onExportSuite: () => this.handleExportTestSuite(), onExportResults: () => this.handleExportTestResults(), onRunAll: () => this.runAllTests(), onSave: () => this.handleSave() }), h(ErrorMessage, { key: 'ec68912728b06fc4a76c330fb1b7d5acde92c3d1', message: this.error, onClear: () => (this.error = '') }), h("div", { key: 'ce308dd4bd5437c94ae6e3e8a28970b799865281', class: "test-runner-container__content" }, h(LLMTestCases, { key: '3368df0bb7de4d099da1fad400f59dfc9a2cfb62', testCases: this.testCases, onRun: testCase => this.runSingleTest(testCase).catch(() => { }), onDelete: id => this.deleteTestCase(id), onAddTestCase: () => this.addNewTestCase(), handleTestCaseChange: this.handleTestCaseChange, onExpectedOutcomeChange: this.handleExpectedOutcomeChange }))));
287
+ return (h("div", { key: 'cc808096f929b2e1c570c53144aab195d177c187', class: "test-runner-container" }, h(LLMTestRunnerHeader, { key: 'b91cf3df7df0e95bfd4908a2f91c7310b5b7a09a', isExportingTestSuite: this.isExportingTestSuite, isExportingTestResults: this.isExportingTestResults, isRunningAll: this.isRunningAll, useSave: this.useSave, isSaving: this.isSaving, usePromptEditor: this.usePromptEditor, onImport: file => this.handleImport(file), onExportSuite: () => this.handleExportTestSuite(), onExportResults: () => this.handleExportTestResults(), onRunAll: () => this.runAllTests(), onSave: () => this.handleSave() }), h(ErrorMessage, { key: 'c7991497173fa9843e7aa42f5283d0897ddff2e2', message: this.error, onClear: () => (this.error = '') }), h("div", { key: '2b57132564442b8047d8672c6adcba62cdc9ae87', class: "test-runner-container__content" }, h(LLMTestCases, { key: '146e9d8c76a34980a2a274dd856887c22e1ed0e9', testCases: this.testCases, dynamicResolutionSupported: !!this.resolveExpectedOutcome, onRun: testCase => this.runSingleTest(testCase).catch(() => { }), onDelete: id => this.deleteTestCase(id), onAddTestCase: () => this.addNewTestCase(), handleTestCaseChange: this.handleTestCaseChange, onExpectedOutcomeChange: this.handleExpectedOutcomeChange, onChatHistoryChange: this.handleChatHistoryChange }))));
251
288
  }
252
289
  static get is() { return "llm-test-runner"; }
253
290
  static get encapsulation() { return "shadow"; }
@@ -323,12 +360,36 @@ export class LLMTestRunner {
323
360
  "attribute": "use-prompt-editor",
324
361
  "defaultValue": "false"
325
362
  },
363
+ "resolveExpectedOutcome": {
364
+ "type": "unknown",
365
+ "mutable": false,
366
+ "complexType": {
367
+ "original": "ExpectedOutcomeResolver",
368
+ "resolved": "(resolutionQuery: string, context: { testCase: { id: string; question: string; expectedOutcome: ({ 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; }; outcomeMode?: \"static\" | \"dynamic\"; resolutionQuery?: string; } | { label: string; type: \"chips-input\"; value: string[]; placeholder?: string; evaluationParameters?: { approach: EvaluationApproach; threshold?: number; }; } | { label: string; type: \"select\"; options: string[]; value: string; placeholder?: string; evaluationParameters?: { approach: EvaluationApproach; threshold?: number; }; })[]; chatHistory: { enabled: boolean; value: string; }; output?: string; isRunning?: boolean; error?: string; evaluationResult?: EvaluationResult; responseTime?: number; }; fieldIndex: number; }) => Promise<string>",
369
+ "references": {
370
+ "ExpectedOutcomeResolver": {
371
+ "location": "import",
372
+ "path": "../../lib/test-cases/dynamic-expected-outcome-resolver",
373
+ "id": "src/lib/test-cases/dynamic-expected-outcome-resolver.ts::ExpectedOutcomeResolver",
374
+ "referenceLocation": "ExpectedOutcomeResolver"
375
+ }
376
+ }
377
+ },
378
+ "required": false,
379
+ "optional": true,
380
+ "docs": {
381
+ "tags": [],
382
+ "text": ""
383
+ },
384
+ "getter": false,
385
+ "setter": false
386
+ },
326
387
  "initialTestCases": {
327
388
  "type": "unknown",
328
389
  "mutable": false,
329
390
  "complexType": {
330
391
  "original": "TestCase[]",
331
- "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; }[]",
392
+ "resolved": "{ id: string; question: string; expectedOutcome: ({ 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; }; outcomeMode?: \"static\" | \"dynamic\"; resolutionQuery?: string; } | { label: string; type: \"chips-input\"; value: string[]; placeholder?: string; evaluationParameters?: { approach: EvaluationApproach; threshold?: number; }; } | { label: string; type: \"select\"; options: string[]; value: string; placeholder?: string; evaluationParameters?: { approach: EvaluationApproach; threshold?: number; }; })[]; chatHistory: { enabled: boolean; value: string; }; output?: string; isRunning?: boolean; error?: string; evaluationResult?: EvaluationResult; responseTime?: number; }[]",
332
393
  "references": {
333
394
  "TestCase": {
334
395
  "location": "import",
@@ -471,7 +532,7 @@ export class LLMTestRunner {
471
532
  "referenceLocation": "TestCase"
472
533
  }
473
534
  },
474
- "return": "Promise<{ 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; }[]>"
535
+ "return": "Promise<{ id: string; question: string; expectedOutcome: ({ 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; }; outcomeMode?: \"static\" | \"dynamic\"; resolutionQuery?: string; } | { label: string; type: \"chips-input\"; value: string[]; placeholder?: string; evaluationParameters?: { approach: EvaluationApproach; threshold?: number; }; } | { label: string; type: \"select\"; options: string[]; value: string; placeholder?: string; evaluationParameters?: { approach: EvaluationApproach; threshold?: number; }; })[]; chatHistory: { enabled: boolean; value: string; }; output?: string; isRunning?: boolean; error?: string; evaluationResult?: EvaluationResult; responseTime?: number; }[]>"
475
536
  },
476
537
  "docs": {
477
538
  "text": "",
@@ -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 {\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() usePromptEditor?: 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 @Method()\n async getTestCases(): Promise<TestCase[]> {\n return this.testCases;\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 usePromptEditor={this.usePromptEditor}\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"]}
1
+ {"version":3,"file":"llm-test-runner.js","sourceRoot":"","sources":["../../../src/components/llm-test-runner/llm-test-runner.tsx"],"names":[],"mappings":"AAAA,OAAO,EACL,SAAS,EACT,KAAK,EACL,IAAI,EACJ,CAAC,EAED,KAAK,EACL,MAAM,GACP,MAAM,eAAe,CAAC;AAEvB,OAAO,EAAE,YAAY,EAAE,MAAM,gCAAgC,CAAC;AAC9D,OAAO,EAAE,kBAAkB,EAAE,MAAM,qDAAqD,CAAC;AAOzF,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,sBAAsB,EAAE,MAAM,0CAA0C,CAAC;AAClF,OAAO,EAAE,eAAe,EAAE,MAAM,6CAA6C,CAAC;AAC9E,OAAO,EACL,cAAc,EACd,uBAAuB,EACvB,+BAA+B,GAChC,MAAM,wCAAwC,CAAC;AAChD,OAAO,EAEL,8BAA8B,GAC/B,MAAM,wDAAwD,CAAC;AAChE,OAAO,KAAK,iBAAiB,MAAM,0CAA0C,CAAC;AAC9E,OAAO,EAAE,iBAAiB,EAAE,MAAM,yCAAyC,CAAC;AAC5E,OAAO,EAAE,0BAA0B,EAAE,MAAM,yBAAyB,CAAC;AACrE,OAAO,EAAE,6BAA6B,EAAE,MAAM,gCAAgC,CAAC;AAC/E,OAAO,EAAE,mBAAmB,EAAE,MAAM,iCAAiC,CAAC;AACtE,OAAO,EAAE,YAAY,EAAE,MAAM,6BAA6B,CAAC;AAqB3D,MAAM,OAAO,aAAa;IACf,UAAU,CAAkC;IAC5C,IAAI,CAA4B;IACjC,OAAO,GAAY,GAAG,CAAC;IACvB,OAAO,GAAa,KAAK,CAAC;IAC1B,eAAe,GAAa,KAAK,CAAC;IAClC,sBAAsB,CAA2B;IACjD,gBAAgB,CAAc;IAC9B,4BAA4B,CAAyB;IACpD,SAAS,GAAe;QAC/B;YACE,EAAE,EAAE,GAAG;YACP,QAAQ,EAAE,EAAE;YACZ,eAAe,EAAE;gBACf;oBACE,IAAI,EAAE,UAAU;oBAChB,KAAK,EAAE,kBAAkB;oBACzB,KAAK,EAAE,EAAE;iBACV;aACF;YACD,WAAW,EAAE,EAAE,OAAO,EAAE,KAAK,EAAE,KAAK,EAAE,EAAE,EAAE;YAC1C,SAAS,EAAE,KAAK;SACjB;KACF,CAAC;IACO,YAAY,GAAY,KAAK,CAAC;IAC9B,KAAK,GAAW,EAAE,CAAC;IACnB,oBAAoB,GAAY,KAAK,CAAC;IACtC,sBAAsB,GAAY,KAAK,CAAC;IACxC,QAAQ,GAAY,KAAK,CAAC;IAE3B,iBAAiB,CAAoB;IAErC,gCAAgC;QACtC,IAAI,IAAI,CAAC,4BAA4B,KAAK,SAAS,EAAE,CAAC;YACpD,OAAO,+BAA+B,CAAC;QACzC,CAAC;QAED,6BAA6B,CAAC,IAAI,CAAC,4BAA4B,CAAC,CAAC;QACjE,OAAO,IAAI,CAAC,4BAA4B,CAAC;IAC3C,CAAC;IAED,iBAAiB;QACf,IAAI,CAAC,iBAAiB,GAAG,IAAI,iBAAiB,EAAE,CAAC;QACjD,IAAI,CAAC;YACH,6CAA6C;YAC7C,IAAI,IAAI,CAAC,gBAAgB,KAAK,SAAS,EAAE,CAAC;gBACxC,0BAA0B,CAAC,IAAI,CAAC,gBAAgB,CAAC,CAAC;gBAClD,IAAI,CAAC,SAAS,GAAG,IAAI,CAAC,gBAAgB,CAAC,GAAG,CAAC,CAAC,WAAW,EAAE,KAAK,EAAE,EAAE;oBAChE,IAAI,CAAC;wBACH,OAAO,uBAAuB,CAAC,WAAW,CAAC,CAAC;oBAC9C,CAAC;oBAAC,OAAO,GAAG,EAAE,CAAC;wBACb,MAAM,OAAO,GAAG,GAAG,YAAY,KAAK,CAAC,CAAC,CAAC,GAAG,CAAC,OAAO,CAAC,CAAC,CAAC,eAAe,CAAC;wBACrE,MAAM,IAAI,KAAK,CAAC,sCAAsC,KAAK,KAAK,OAAO,EAAE,CAAC,CAAC;oBAC7E,CAAC;gBACH,CAAC,CAAC,CAAC;YACL,CAAC;iBAAM,CAAC;gBACN,MAAM,MAAM,GAAG,IAAI,CAAC,gCAAgC,EAAE,CAAC;gBACvD,IAAI,CAAC,SAAS,GAAG,CAAC,cAAc,CAAC,MAAM,CAAC,CAAC,CAAC;YAC5C,CAAC;QACH,CAAC;QAAC,OAAO,GAAG,EAAE,CAAC;YACb,IAAI,CAAC,KAAK;gBACR,GAAG,YAAY,KAAK;oBAClB,CAAC,CAAC,GAAG,CAAC,OAAO;oBACb,CAAC,CAAC,gDAAgD,CAAC;YACvD,IAAI,CAAC,SAAS,GAAG,EAAE,CAAC;QACtB,CAAC;IACH,CAAC;IAED,gBAAgB,KAAI,CAAC;IAErB,oBAAoB,KAAI,CAAC;IAGzB,KAAK,CAAC,gBAAgB;QACpB,IAAI,CAAC,QAAQ,GAAG,KAAK,CAAC;IACxB,CAAC;IAGD,KAAK,CAAC,YAAY;QAChB,OAAO,IAAI,CAAC,SAAS,CAAC;IACxB,CAAC;IAEO,oBAAoB,GAAG,CAC7B,KAAsE,EACtE,EAAE;QACF,MAAM,EAAE,UAAU,EAAE,GAAG,EAAE,KAAK,EAAE,GAAG,KAAK,CAAC,MAAM,CAAC;QAChD,IAAI,CAAC,SAAS,GAAG,IAAI,CAAC,SAAS,CAAC,GAAG,CAAC,EAAE,CAAC,EAAE,CACvC,EAAE,CAAC,EAAE,KAAK,UAAU,CAAC,CAAC,CAAC,EAAE,GAAG,EAAE,EAAE,CAAC,GAAG,CAAC,EAAE,KAAK,EAAE,CAAC,CAAC,CAAC,EAAE,CACpD,CAAC;IACJ,CAAC,CAAC;IAEM,uBAAuB,GAAG,CAChC,KAA8C,EAC9C,EAAE;QACF,MAAM,EAAE,UAAU,EAAE,OAAO,EAAE,KAAK,EAAE,GAAG,KAAK,CAAC,MAAM,CAAC;QACpD,IAAI,CAAC,cAAc,CAAC,UAAU,EAAE;YAC9B,WAAW,EAAE,EAAE,OAAO,EAAE,KAAK,EAAE;SAChC,CAAC,CAAC;IACL,CAAC,CAAC;IAEM,cAAc;QACpB,IAAI,CAAC;YACH,MAAM,MAAM,GAAG,IAAI,CAAC,gCAAgC,EAAE,CAAC;YACvD,MAAM,WAAW,GAAG,cAAc,CAAC,MAAM,CAAC,CAAC;YAC3C,IAAI,CAAC,SAAS,GAAG,CAAC,GAAG,IAAI,CAAC,SAAS,EAAE,WAAW,CAAC,CAAC;QACpD,CAAC;QAAC,OAAO,GAAG,EAAE,CAAC;YACb,IAAI,CAAC,KAAK;gBACR,GAAG,YAAY,KAAK;oBAClB,CAAC,CAAC,GAAG,CAAC,OAAO;oBACb,CAAC,CAAC,gDAAgD,CAAC;QACzD,CAAC;IACH,CAAC;IAEO,cAAc,CAAC,EAAU,EAAE,OAA0B;QAC3D,IAAI,CAAC,SAAS,GAAG,IAAI,CAAC,SAAS,CAAC,GAAG,CAAC,EAAE,CAAC,EAAE,CACvC,EAAE,CAAC,EAAE,KAAK,EAAE,CAAC,CAAC,CAAC,EAAE,GAAG,EAAE,EAAE,GAAG,OAAO,EAAE,CAAC,CAAC,CAAC,EAAE,CAC1C,CAAC;IACJ,CAAC;IAEO,cAAc,CAAC,QAAkB;QACvC,OAAO,IAAI,OAAO,CAAC,CAAC,OAAO,EAAE,MAAM,EAAE,EAAE;YACrC,MAAM,OAAO,GAAsB;gBACjC,MAAM,EAAE,QAAQ,CAAC,QAAQ;gBACzB,OAAO;gBACP,MAAM;aACP,CAAC;YACF,IAAI,QAAQ,CAAC,WAAW,EAAE,OAAO,EAAE,CAAC;gBAClC,OAAO,CAAC,WAAW,GAAG,QAAQ,CAAC,WAAW,CAAC,KAAK,CAAC;YACnD,CAAC;YACD,IAAI,CAAC,UAAU,CAAC,IAAI,CAAC,OAAO,CAAC,CAAC;QAChC,CAAC,CAAC,CAAC;IACL,CAAC;IAEO,UAAU,CAAC,MAAe;QAChC,MAAM,MAAM,YAAY,KAAK,CAAC,CAAC,CAAC,MAAM,CAAC,CAAC,CAAC,IAAI,KAAK,CAAC,MAAM,CAAC,MAAM,CAAC,CAAC,CAAC;IACrE,CAAC;IAEO,eAAe,CAAC,MAAe,EAAE,QAAgB;QACvD,OAAO,MAAM,YAAY,KAAK,CAAC,CAAC,CAAC,MAAM,CAAC,OAAO,CAAC,CAAC,CAAC,QAAQ,CAAC;IAC7D,CAAC;IAEO,KAAK,CAAC,aAAa,CAAC,QAAkB;QAC5C,MAAM,SAAS,GAAG,IAAI,CAAC,GAAG,EAAE,CAAC;QAC7B,IAAI,CAAC,cAAc,CAAC,QAAQ,CAAC,EAAE,EAAE,EAAE,SAAS,EAAE,IAAI,EAAE,CAAC,CAAC;QACtD,MAAM,CAAC,UAAU,EAAE,iBAAiB,CAAC,GAAG,MAAM,OAAO,CAAC,UAAU,CAAC;YAC/D,IAAI,CAAC,cAAc,CAAC,QAAQ,CAAC;YAC7B,8BAA8B,CAAC,QAAQ,EAAE,IAAI,CAAC,sBAAsB,CAAC;SACtE,CAAC,CAAC;QAEH,MAAM,YAAY,GAAG,IAAI,CAAC,GAAG,EAAE,GAAG,SAAS,CAAC;QAE5C,IAAI,UAAU,CAAC,MAAM,KAAK,UAAU,EAAE,CAAC;YACrC,IAAI,CAAC,cAAc,CAAC,QAAQ,CAAC,EAAE,EAAE;gBAC/B,SAAS,EAAE,KAAK;gBAChB,MAAM,EAAE,IAAI;gBACZ,KAAK,EAAE,IAAI,CAAC,eAAe,CAAC,UAAU,CAAC,MAAM,EAAE,eAAe,CAAC;gBAC/D,YAAY;aACb,CAAC,CAAC;YACH,IAAI,CAAC,UAAU,CAAC,UAAU,CAAC,MAAM,CAAC,CAAC;QACrC,CAAC;QACD,MAAM,UAAU,GAAG,UAAU,CAAC,KAAK,CAAC;QAEpC,IAAI,iBAAiB,CAAC,MAAM,KAAK,UAAU,EAAE,CAAC;YAC5C,IAAI,CAAC,cAAc,CAAC,QAAQ,CAAC,EAAE,EAAE;gBAC/B,SAAS,EAAE,KAAK;gBAChB,MAAM,EAAE,UAAU;gBAClB,KAAK,EAAE,IAAI,CAAC,eAAe,CACzB,iBAAiB,CAAC,MAAM,EACxB,6CAA6C,CAC9C;gBACD,YAAY;aACb,CAAC,CAAC;YACH,IAAI,CAAC,UAAU,CAAC,iBAAiB,CAAC,MAAM,CAAC,CAAC;QAC5C,CAAC;QACD,MAAM,gBAAgB,GAAG,iBAAiB,CAAC,KAAK,CAAC;QAEjD,MAAM,qBAAqB,GAAa;YACtC,GAAG,gBAAgB;YACnB,MAAM,EAAE,UAAU;YAClB,YAAY;SACb,CAAC;QAEF,IAAI,CAAC,cAAc,CAAC,QAAQ,CAAC,EAAE,EAAE;YAC/B,SAAS,EAAE,KAAK;YAChB,MAAM,EAAE,UAAU;YAClB,KAAK,EAAE,IAAI;YACX,YAAY;YACZ,eAAe,EAAE,qBAAqB,CAAC,eAAe;SACvD,CAAC,CAAC;QAEH,MAAM,IAAI,CAAC,gBAAgB,CAAC,qBAAqB,CAAC,CAAC;IACrD,CAAC;IAEO,cAAc,CAAC,EAAU;QAC/B,IAAI,CAAC,SAAS,GAAG,IAAI,CAAC,SAAS,CAAC,MAAM,CAAC,EAAE,CAAC,EAAE,CAAC,EAAE,CAAC,EAAE,KAAK,EAAE,CAAC,CAAC;IAC7D,CAAC;IAEO,2BAA2B,GAAG,CACpC,KAA+C,EAC/C,EAAE;QACF,MAAM,EAAE,UAAU,EAAE,GAAG,MAAM,EAAE,GAAG,KAAK,CAAC,MAAM,CAAC;QAE/C,IAAI,CAAC,SAAS,GAAG,IAAI,CAAC,SAAS,CAAC,GAAG,CAAC,EAAE,CAAC,EAAE;YACvC,IAAI,EAAE,CAAC,EAAE,KAAK,UAAU,EAAE,CAAC;gBACzB,OAAO,EAAE,CAAC;YACZ,CAAC;YAED,OAAO,iBAAiB,CAAC,0BAA0B,CAAC,EAAE,EAAE,MAAM,CAAC,CAAC;QAClE,CAAC,CAAC,CAAC;IACL,CAAC,CAAC;IAEM,KAAK,CAAC,gBAAgB,CAAC,QAAkB;QAC/C,MAAM,IAAI,CAAC,iBAAiB,CAAC,gBAAgB,CAC3C,QAAQ,EACR,CAAC,MAAwB,EAAE,EAAE;YAC3B,IAAI,CAAC,cAAc,CAAC,QAAQ,CAAC,EAAE,EAAE;gBAC/B,gBAAgB,EAAE,MAAM;aACzB,CAAC,CAAC;QACL,CAAC,CACF,CAAC;IACJ,CAAC;IAEO,KAAK,CAAC,WAAW;QACvB,IAAI,CAAC,YAAY,GAAG,IAAI,CAAC;QACzB,MAAM,KAAK,GAAG,EAAE,CAAC;QACjB,KAAK,MAAM,QAAQ,IAAI,IAAI,CAAC,SAAS,EAAE,CAAC;YACtC,IAAI,CAAC,QAAQ,CAAC,SAAS,IAAI,QAAQ,CAAC,QAAQ,CAAC,IAAI,EAAE,EAAE,CAAC;gBACpD,KAAK,CAAC,IAAI,CAAC,GAAG,EAAE,CACd,IAAI,CAAC,aAAa,CAAC,QAAQ,CAAC,CAAC,KAAK,CAAC,GAAG,CAAC,EAAE;oBACvC,OAAO,CAAC,KAAK,CAAC,gBAAgB,QAAQ,CAAC,EAAE,SAAS,EAAE,GAAG,CAAC,CAAC;gBAC3D,CAAC,CAAC,CACH,CAAC;YACJ,CAAC;QACH,CAAC;QACD,IAAI,CAAC;YACH,MAAM,OAAO,GAAG,IAAI,kBAAkB,CAAC,IAAI,CAAC,OAAO,CAAC,CAAC;YACrD,MAAM,OAAO,CAAC,MAAM,CAAC,KAAK,CAAC,CAAC;QAC9B,CAAC;QAAC,OAAO,GAAG,EAAE,CAAC;YACb,OAAO,CAAC,KAAK,CAAC,6BAA6B,EAAE,GAAG,CAAC,CAAC;QACpD,CAAC;QACD,IAAI,CAAC,YAAY,GAAG,KAAK,CAAC;IAC5B,CAAC;IAEO,KAAK,CAAC,YAAY,CAAC,IAAU;QACnC,MAAM,UAAU,GAAG,IAAI,CAAC,IAAI,KAAK,kBAAkB,CAAC;QACpD,MAAM,eAAe,GAAG,IAAI,CAAC,IAAI,CAAC,WAAW,EAAE,CAAC,QAAQ,CAAC,OAAO,CAAC,CAAC;QAElE,IAAI,CAAC,UAAU,IAAI,CAAC,eAAe,EAAE,CAAC;YACpC,IAAI,CAAC,KAAK,GAAG,+CAA+C,CAAC;YAC7D,OAAO;QACT,CAAC;QAED,IAAI,CAAC,KAAK,GAAG,EAAE,CAAC;QAEhB,IAAI,CAAC;YACH,MAAM,OAAO,GAAG,MAAM,aAAa,CAAC,IAAI,CAAC,CAAC;YAC1C,MAAM,MAAM,GAAG,eAAe,CAAC,OAAO,CAAC,CAAC;YAExC,IAAI,CAAC,MAAM,CAAC,OAAO,EAAE,CAAC;gBACpB,IAAI,CAAC,KAAK,GAAG,MAAM,CAAC,KAAK,IAAI,uCAAuC,CAAC;gBACrE,OAAO;YACT,CAAC;YAED,IAAI,CAAC,SAAS,GAAG,MAAM,CAAC,SAAS,IAAI,EAAE,CAAC;QAC1C,CAAC;QAAC,OAAO,GAAG,EAAE,CAAC;YACb,IAAI,CAAC,KAAK;gBACR,GAAG,YAAY,KAAK;oBAClB,CAAC,CAAC,GAAG,CAAC,OAAO;oBACb,CAAC,CAAC,gEAAgE,CAAC;YACvE,OAAO,CAAC,KAAK,CAAC,wBAAwB,EAAE,GAAG,CAAC,CAAC;QAC/C,CAAC;IACH,CAAC;IAEO,KAAK,CAAC,qBAAqB;QACjC,IAAI,CAAC,oBAAoB,GAAG,IAAI,CAAC;QACjC,IAAI,CAAC;YACH,MAAM,WAAW,GAAG,qBAAqB,CAAC,IAAI,CAAC,SAAS,CAAC,CAAC;YAE1D,gDAAgD;YAChD,MAAM,IAAI,OAAO,CAAC,OAAO,CAAC,EAAE,CAAC,UAAU,CAAC,OAAO,EAAE,GAAG,CAAC,CAAC,CAAC;YAEvD,YAAY,CAAC,WAAW,EAAE,iBAAiB,EAAE,kBAAkB,CAAC,CAAC;QACnE,CAAC;gBAAS,CAAC;YACT,IAAI,CAAC,oBAAoB,GAAG,KAAK,CAAC;QACpC,CAAC;IACH,CAAC;IAEO,KAAK,CAAC,uBAAuB;QACnC,IAAI,CAAC,sBAAsB,GAAG,IAAI,CAAC;QACnC,IAAI,CAAC;YACH,MAAM,UAAU,GAAG,sBAAsB,CAAC,IAAI,CAAC,SAAS,CAAC,CAAC;YAE1D,gDAAgD;YAChD,MAAM,IAAI,OAAO,CAAC,OAAO,CAAC,EAAE,CAAC,UAAU,CAAC,OAAO,EAAE,GAAG,CAAC,CAAC,CAAC;YAEvD,YAAY,CAAC,UAAU,EAAE,kBAAkB,EAAE,UAAU,CAAC,CAAC;QAC3D,CAAC;gBAAS,CAAC;YACT,IAAI,CAAC,sBAAsB,GAAG,KAAK,CAAC;QACtC,CAAC;IACH,CAAC;IAEO,KAAK,CAAC,UAAU;QACtB,IAAI,CAAC,QAAQ,GAAG,IAAI,CAAC;QACrB,IAAI,CAAC;YACH,MAAM,OAAO,GAAG;gBACd,SAAS,EAAE,IAAI,IAAI,EAAE,CAAC,WAAW,EAAE;gBACnC,SAAS,EAAE,IAAI,CAAC,SAAS;aAC1B,CAAC;YACF,IAAI,CAAC,IAAI,CAAC,IAAI,CAAC,OAAO,CAAC,CAAC;YAExB,yEAAyE;YACzE,UAAU,CAAC,GAAG,EAAE;gBACd,IAAI,IAAI,CAAC,QAAQ,EAAE,CAAC;oBAClB,OAAO,CAAC,IAAI,CAAC,2CAA2C,CAAC,CAAC;oBAC1D,IAAI,CAAC,QAAQ,GAAG,KAAK,CAAC;gBACxB,CAAC;YACH,CAAC,EAAE,KAAK,CAAC,CAAC;QACZ,CAAC;gBAAS,CAAC;YACT,iEAAiE;YACjE,mEAAmE;QACrE,CAAC;IACH,CAAC;IAED,MAAM;QACJ,OAAO,CACL,4DAAK,KAAK,EAAC,uBAAuB;YAChC,EAAC,mBAAmB,qDAClB,oBAAoB,EAAE,IAAI,CAAC,oBAAoB,EAC/C,sBAAsB,EAAE,IAAI,CAAC,sBAAsB,EACnD,YAAY,EAAE,IAAI,CAAC,YAAY,EAC/B,OAAO,EAAE,IAAI,CAAC,OAAO,EACrB,QAAQ,EAAE,IAAI,CAAC,QAAQ,EACvB,eAAe,EAAE,IAAI,CAAC,eAAe,EACrC,QAAQ,EAAE,IAAI,CAAC,EAAE,CAAC,IAAI,CAAC,YAAY,CAAC,IAAI,CAAC,EACzC,aAAa,EAAE,GAAG,EAAE,CAAC,IAAI,CAAC,qBAAqB,EAAE,EACjD,eAAe,EAAE,GAAG,EAAE,CAAC,IAAI,CAAC,uBAAuB,EAAE,EACrD,QAAQ,EAAE,GAAG,EAAE,CAAC,IAAI,CAAC,WAAW,EAAE,EAClC,MAAM,EAAE,GAAG,EAAE,CAAC,IAAI,CAAC,UAAU,EAAE,GAC/B;YACF,EAAC,YAAY,qDAAC,OAAO,EAAE,IAAI,CAAC,KAAK,EAAE,OAAO,EAAE,GAAG,EAAE,CAAC,CAAC,IAAI,CAAC,KAAK,GAAG,EAAE,CAAC,GAAI;YACvE,4DAAK,KAAK,EAAC,gCAAgC;gBACzC,EAAC,YAAY,qDACX,SAAS,EAAE,IAAI,CAAC,SAAS,EACzB,0BAA0B,EAAE,CAAC,CAAC,IAAI,CAAC,sBAAsB,EACzD,KAAK,EAAE,QAAQ,CAAC,EAAE,CAAC,IAAI,CAAC,aAAa,CAAC,QAAQ,CAAC,CAAC,KAAK,CAAC,GAAG,EAAE,GAAE,CAAC,CAAC,EAC/D,QAAQ,EAAE,EAAE,CAAC,EAAE,CAAC,IAAI,CAAC,cAAc,CAAC,EAAE,CAAC,EACvC,aAAa,EAAE,GAAG,EAAE,CAAC,IAAI,CAAC,cAAc,EAAE,EAC1C,oBAAoB,EAAE,IAAI,CAAC,oBAAoB,EAC/C,uBAAuB,EAAE,IAAI,CAAC,2BAA2B,EACzD,mBAAmB,EAAE,IAAI,CAAC,uBAAuB,GACjD,CACE,CACF,CACP,CAAC;IACJ,CAAC;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;CACF","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 {\n type ExpectedOutcomeResolver,\n resolveDynamicExpectedOutcomes,\n} from '../../lib/test-cases/dynamic-expected-outcome-resolver';\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';\nimport type { ChatHistoryRowChangeDetail } from './test-cases/llm-test-case-row';\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() usePromptEditor?: boolean = false;\n @Prop() resolveExpectedOutcome?: ExpectedOutcomeResolver;\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 chatHistory: { enabled: false, value: '' },\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 @Method()\n async getTestCases(): Promise<TestCase[]> {\n return this.testCases;\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 handleChatHistoryChange = (\n event: CustomEvent<ChatHistoryRowChangeDetail>,\n ) => {\n const { testCaseId, enabled, value } = event.detail;\n this.updateTestCase(testCaseId, {\n chatHistory: { enabled, value },\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 requestLlmText(testCase: TestCase): Promise<string> {\n return new Promise((resolve, reject) => {\n const payload: LLMRequestPayload = {\n prompt: testCase.question,\n resolve,\n reject,\n };\n if (testCase.chatHistory?.enabled) {\n payload.chatHistory = testCase.chatHistory.value;\n }\n this.llmRequest.emit(payload);\n });\n }\n\n private throwError(reason: unknown): never {\n throw reason instanceof Error ? reason : new Error(String(reason));\n }\n\n private addErrorMessage(reason: unknown, fallback: string): string {\n return reason instanceof Error ? reason.message : fallback;\n }\n\n private async runSingleTest(testCase: TestCase): Promise<void> {\n const startTime = Date.now();\n this.updateTestCase(testCase.id, { isRunning: true });\n const [llmSettled, resolutionSettled] = await Promise.allSettled([\n this.requestLlmText(testCase),\n resolveDynamicExpectedOutcomes(testCase, this.resolveExpectedOutcome),\n ]);\n\n const responseTime = Date.now() - startTime;\n\n if (llmSettled.status === 'rejected') {\n this.updateTestCase(testCase.id, {\n isRunning: false,\n output: null,\n error: this.addErrorMessage(llmSettled.reason, 'Unknown error'),\n responseTime,\n });\n this.throwError(llmSettled.reason);\n }\n const aiResponse = llmSettled.value;\n\n if (resolutionSettled.status === 'rejected') {\n this.updateTestCase(testCase.id, {\n isRunning: false,\n output: aiResponse,\n error: this.addErrorMessage(\n resolutionSettled.reason,\n 'Failed to resolve dynamic expected outcome.',\n ),\n responseTime,\n });\n this.throwError(resolutionSettled.reason);\n }\n const resolvedTestCase = resolutionSettled.value;\n\n const forEvaluationTestCase: TestCase = {\n ...resolvedTestCase,\n output: aiResponse,\n responseTime,\n };\n\n this.updateTestCase(testCase.id, {\n isRunning: false,\n output: aiResponse,\n error: null,\n responseTime,\n expectedOutcome: forEvaluationTestCase.expectedOutcome,\n });\n\n await this.evaluateResponse(forEvaluationTestCase);\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 usePromptEditor={this.usePromptEditor}\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 dynamicResolutionSupported={!!this.resolveExpectedOutcome}\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 onChatHistoryChange={this.handleChatHistoryChange}\n />\n </div>\n </div>\n );\n }\n}\n"]}