llm-testrunner-components 1.0.6 → 1.0.9
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/README.md +101 -100
- package/dist/cjs/app-chips_5.cjs.entry.js +158 -0
- package/dist/cjs/app-chips_5.cjs.entry.js.map +1 -0
- package/dist/cjs/app-globals-Chb-oJtg.js +34 -0
- package/dist/cjs/app-globals-Chb-oJtg.js.map +1 -0
- package/dist/cjs/index-By1scwl6.js +25542 -0
- package/dist/cjs/index-By1scwl6.js.map +1 -0
- package/dist/cjs/index-CgmLNwZO.js +21460 -0
- package/dist/cjs/index-CgmLNwZO.js.map +1 -0
- package/dist/cjs/index.cjs.js +5 -483
- package/dist/cjs/index.cjs.js.map +1 -1
- package/dist/cjs/llm-testrunner.cjs.js +6 -4
- package/dist/cjs/llm-testrunner.cjs.js.map +1 -1
- package/dist/cjs/loader.cjs.js +5 -3
- package/dist/collection/collection-manifest.json +8 -3
- package/dist/collection/components/error-message/error-message.css +34 -0
- package/dist/collection/components/error-message/error-message.js +2 -2
- package/dist/collection/components/error-message/error-message.js.map +1 -1
- package/dist/collection/components/llm-test-runner/header/llm-test-runner-header.css +60 -0
- package/dist/collection/components/llm-test-runner/header/llm-test-runner-header.js +18 -0
- package/dist/collection/components/llm-test-runner/header/llm-test-runner-header.js.map +1 -0
- package/dist/collection/components/llm-test-runner/llm-test-runner.css +17 -657
- package/dist/collection/components/llm-test-runner/llm-test-runner.import-export.test.js +253 -0
- package/dist/collection/components/llm-test-runner/llm-test-runner.import-export.test.js.map +1 -0
- package/dist/collection/components/llm-test-runner/llm-test-runner.js +191 -200
- package/dist/collection/components/llm-test-runner/llm-test-runner.js.map +1 -1
- package/dist/collection/components/llm-test-runner/test-cases/actions/row-actions.css +28 -0
- package/dist/collection/components/llm-test-runner/test-cases/actions/row-actions.js +6 -0
- package/dist/collection/components/llm-test-runner/test-cases/actions/row-actions.js.map +1 -0
- package/dist/collection/components/llm-test-runner/test-cases/evaluation/evaluation-summary.css +67 -0
- package/dist/collection/components/llm-test-runner/test-cases/evaluation/evaluation-summary.js +5 -0
- package/dist/collection/components/llm-test-runner/test-cases/evaluation/evaluation-summary.js.map +1 -0
- package/dist/collection/components/llm-test-runner/test-cases/llm-test-case-row.css +42 -0
- package/dist/collection/components/llm-test-runner/test-cases/llm-test-case-row.js +39 -0
- package/dist/collection/components/llm-test-runner/test-cases/llm-test-case-row.js.map +1 -0
- package/dist/collection/components/llm-test-runner/test-cases/llm-test-cases.css +39 -0
- package/dist/collection/components/llm-test-runner/test-cases/llm-test-cases.js +7 -0
- package/dist/collection/components/llm-test-runner/test-cases/llm-test-cases.js.map +1 -0
- package/dist/collection/components/llm-test-runner/test-cases/output/response-output.css +51 -0
- package/dist/collection/components/llm-test-runner/test-cases/output/response-output.js +5 -0
- package/dist/collection/components/llm-test-runner/test-cases/output/response-output.js.map +1 -0
- package/dist/collection/global/env.js +3 -1
- package/dist/collection/global/env.js.map +1 -1
- package/dist/collection/index.js.map +1 -1
- package/dist/collection/lib/evaluation/constants.js +14 -0
- package/dist/collection/lib/evaluation/constants.js.map +1 -0
- package/dist/collection/lib/evaluation/evaluation-engine.js +45 -45
- package/dist/collection/lib/evaluation/evaluation-engine.js.map +1 -1
- package/dist/collection/lib/evaluation/evaluation-service.js +33 -0
- package/dist/collection/lib/evaluation/evaluation-service.js.map +1 -0
- package/dist/collection/lib/evaluation/evaluators/bleu/bleu-evaluator.js +116 -0
- package/dist/collection/lib/evaluation/evaluators/bleu/bleu-evaluator.js.map +1 -0
- package/dist/collection/lib/evaluation/evaluators/bleu/tests/bleu.test.js +352 -0
- package/dist/collection/lib/evaluation/evaluators/bleu/tests/bleu.test.js.map +1 -0
- package/dist/collection/lib/evaluation/evaluators/exact/exact.js +44 -0
- package/dist/collection/lib/evaluation/evaluators/exact/exact.js.map +1 -0
- package/dist/collection/lib/evaluation/evaluators/rouge1-evaluator.js +88 -0
- package/dist/collection/lib/evaluation/evaluators/rouge1-evaluator.js.map +1 -0
- package/dist/collection/lib/evaluation/evaluators/rougeL-evaluator.js +82 -0
- package/dist/collection/lib/evaluation/evaluators/rougeL-evaluator.js.map +1 -0
- package/dist/collection/lib/evaluation/evaluators/rougeL-evaluator.test.js +326 -0
- package/dist/collection/lib/evaluation/evaluators/rougeL-evaluator.test.js.map +1 -0
- package/dist/collection/lib/evaluation/evaluators/semantic/SemanticEvaluator.js +69 -0
- package/dist/collection/lib/evaluation/evaluators/semantic/SemanticEvaluator.js.map +1 -0
- package/dist/collection/lib/evaluation/evaluators/semantic/evaluate-keywords.js +56 -0
- package/dist/collection/lib/evaluation/evaluators/semantic/evaluate-keywords.js.map +1 -0
- package/dist/collection/lib/evaluation/evaluators/semantic/index.js +7 -0
- package/dist/collection/lib/evaluation/evaluators/semantic/index.js.map +1 -0
- package/dist/collection/lib/evaluation/evaluators/semantic/model-loader.js +19 -0
- package/dist/collection/lib/evaluation/evaluators/semantic/model-loader.js.map +1 -0
- package/dist/collection/lib/evaluation/evaluators/semantic/similarity-utils.js +16 -0
- package/dist/collection/lib/evaluation/evaluators/semantic/similarity-utils.js.map +1 -0
- package/dist/collection/lib/evaluation/evaluators/semantic/tests/evaluate-keywords.test.js +65 -0
- package/dist/collection/lib/evaluation/evaluators/semantic/tests/evaluate-keywords.test.js.map +1 -0
- package/dist/collection/lib/evaluation/evaluators/semantic/text-utils.js +5 -0
- package/dist/collection/lib/evaluation/evaluators/semantic/text-utils.js.map +1 -0
- package/dist/collection/lib/evaluation/index.js.map +1 -1
- package/dist/collection/lib/evaluation/rouge1-evaluator.test.js +117 -0
- package/dist/collection/lib/evaluation/rouge1-evaluator.test.js.map +1 -0
- package/dist/collection/lib/evaluation/types.js.map +1 -1
- package/dist/collection/lib/file/file-download.js +18 -0
- package/dist/collection/lib/file/file-download.js.map +1 -0
- package/dist/collection/lib/file/file-reader.js +14 -0
- package/dist/collection/lib/file/file-reader.js.map +1 -0
- package/dist/collection/lib/form/components/app-chips.css +97 -0
- package/dist/collection/lib/form/components/app-chips.js +155 -0
- package/dist/collection/lib/form/components/app-chips.js.map +1 -0
- package/dist/collection/lib/form/components/app-select.css +28 -0
- package/dist/collection/lib/form/components/app-select.js +101 -0
- package/dist/collection/lib/form/components/app-select.js.map +1 -0
- package/dist/collection/lib/form/components/app-textarea.css +38 -0
- package/dist/collection/lib/form/components/app-textarea.js +126 -0
- package/dist/collection/lib/form/components/app-textarea.js.map +1 -0
- package/dist/collection/lib/form/form-builder.js +171 -0
- package/dist/collection/lib/form/form-builder.js.map +1 -0
- package/dist/collection/lib/form/schema/base-input-field-config.js +2 -0
- package/dist/collection/lib/form/schema/base-input-field-config.js.map +1 -0
- package/dist/collection/lib/form/schema/form-control-config.js +2 -0
- package/dist/collection/lib/form/schema/form-control-config.js.map +1 -0
- package/dist/collection/lib/form/schema/index.js +8 -0
- package/dist/collection/lib/form/schema/index.js.map +1 -0
- package/dist/collection/lib/import-export/test-results-csv.js +65 -0
- package/dist/collection/lib/import-export/test-results-csv.js.map +1 -0
- package/dist/collection/lib/import-export/test-suite-exporter.js +15 -0
- package/dist/collection/lib/import-export/test-suite-exporter.js.map +1 -0
- package/dist/collection/lib/import-export/test-suite-importer.js +44 -0
- package/dist/collection/lib/import-export/test-suite-importer.js.map +1 -0
- package/dist/collection/lib/rate-limited-fetcher/rate-limited-fetcher.js +6 -6
- package/dist/collection/lib/rate-limited-fetcher/rate-limited-fetcher.js.map +1 -1
- package/dist/collection/lib/test-cases/test-case-factory.js +56 -0
- package/dist/collection/lib/test-cases/test-case-factory.js.map +1 -0
- package/dist/collection/lib/test-cases/test-case-mutations.js +16 -0
- package/dist/collection/lib/test-cases/test-case-mutations.js.map +1 -0
- package/dist/collection/lib/ui/button/button.css +113 -0
- package/dist/collection/lib/ui/button/button.js +21 -0
- package/dist/collection/lib/ui/button/button.js.map +1 -0
- package/dist/collection/lib/ui/button/index.js +2 -0
- package/dist/collection/lib/ui/button/index.js.map +1 -0
- package/dist/collection/lib/ui/icon-button/icon-button.css +77 -0
- package/dist/collection/lib/ui/icon-button/icon-button.js +19 -0
- package/dist/collection/lib/ui/icon-button/icon-button.js.map +1 -0
- package/dist/collection/lib/ui/icon-button/index.js +2 -0
- package/dist/collection/lib/ui/icon-button/index.js.map +1 -0
- package/dist/collection/services/adapters.js +2 -0
- package/dist/collection/services/adapters.js.map +1 -0
- package/dist/collection/services/models/gemini.js +17 -0
- package/dist/collection/services/models/gemini.js.map +1 -0
- package/dist/collection/styles/tokens.css +180 -0
- package/dist/collection/types/evaluation.js +2 -0
- package/dist/collection/types/evaluation.js.map +1 -0
- package/dist/collection/types/llm-test-runner.js +2 -0
- package/dist/collection/types/llm-test-runner.js.map +1 -0
- package/dist/components/app-chips.d.ts +11 -0
- package/dist/components/app-chips.js +2 -0
- package/dist/components/app-chips.js.map +1 -0
- package/dist/components/app-select.d.ts +11 -0
- package/dist/components/app-select.js +2 -0
- package/dist/components/app-select.js.map +1 -0
- package/dist/components/app-textarea.d.ts +11 -0
- package/dist/components/app-textarea.js +2 -0
- package/dist/components/app-textarea.js.map +1 -0
- package/dist/components/form-builder.d.ts +11 -0
- package/dist/components/form-builder.js +2 -0
- package/dist/components/form-builder.js.map +1 -0
- package/dist/components/index.d.ts +2 -0
- package/dist/components/index.js +1 -13
- package/dist/components/index.js.map +1 -1
- package/dist/components/llm-test-runner.js +1 -8
- package/dist/components/llm-test-runner.js.map +1 -1
- package/dist/components/p--2rdv_J9.js +2 -0
- package/dist/components/p--2rdv_J9.js.map +1 -0
- package/dist/components/p-B7J48VNq.js +2 -0
- package/dist/components/p-B7J48VNq.js.map +1 -0
- package/dist/components/p-BCB1rjPS.js +7 -0
- package/dist/components/p-BCB1rjPS.js.map +1 -0
- package/dist/components/p-BQhb2H_a.js +2 -0
- package/dist/components/p-BQhb2H_a.js.map +1 -0
- package/dist/components/p-D9BrlHdP.js +297 -0
- package/dist/components/p-D9BrlHdP.js.map +1 -0
- package/dist/components/p-DtCkZ1g2.js +2 -0
- package/dist/components/p-DtCkZ1g2.js.map +1 -0
- package/dist/esm/app-chips_5.entry.js +153 -0
- package/dist/esm/app-chips_5.entry.js.map +1 -0
- package/dist/esm/app-globals-DbR5vV7d.js +32 -0
- package/dist/esm/app-globals-DbR5vV7d.js.map +1 -0
- package/dist/esm/index-Bvg6mh1M.js +25539 -0
- package/dist/esm/index-Bvg6mh1M.js.map +1 -0
- package/dist/esm/index-DxzhGhec.js +21450 -0
- package/dist/esm/index-DxzhGhec.js.map +1 -0
- package/dist/esm/index.js +4 -486
- package/dist/esm/index.js.map +1 -1
- package/dist/esm/llm-testrunner.js +7 -5
- package/dist/esm/llm-testrunner.js.map +1 -1
- package/dist/esm/loader.js +6 -4
- package/dist/llm-testrunner/index.esm.js +1 -1
- package/dist/llm-testrunner/index.esm.js.map +1 -1
- package/dist/llm-testrunner/llm-testrunner.esm.js +1 -1
- package/dist/llm-testrunner/llm-testrunner.esm.js.map +1 -1
- package/dist/llm-testrunner/p-3f04b0fb.entry.js +2 -0
- package/dist/llm-testrunner/p-3f04b0fb.entry.js.map +1 -0
- package/dist/llm-testrunner/p-DFds8y01.js +7 -0
- package/dist/llm-testrunner/p-DFds8y01.js.map +1 -0
- package/dist/llm-testrunner/p-DxzhGhec.js +298 -0
- package/dist/llm-testrunner/p-DxzhGhec.js.map +1 -0
- package/dist/llm-testrunner/p-GQwFOmwJ.js +2 -0
- package/dist/llm-testrunner/p-GQwFOmwJ.js.map +1 -0
- package/dist/react/components.d.ts +32 -2
- package/dist/react/components.d.ts.map +1 -1
- package/dist/react/components.js +44 -2
- package/dist/types/components/llm-test-runner/header/llm-test-runner-header.d.ts +14 -0
- package/dist/types/components/llm-test-runner/llm-test-runner.d.ts +13 -29
- package/dist/types/components/llm-test-runner/llm-test-runner.import-export.test.d.ts +1 -0
- package/dist/types/components/llm-test-runner/test-cases/actions/row-actions.d.ts +8 -0
- package/dist/types/components/llm-test-runner/test-cases/evaluation/evaluation-summary.d.ts +7 -0
- package/dist/types/components/llm-test-runner/test-cases/llm-test-case-row.d.ts +25 -0
- package/dist/types/components/llm-test-runner/test-cases/llm-test-cases.d.ts +26 -0
- package/dist/types/components/llm-test-runner/test-cases/output/response-output.d.ts +6 -0
- package/dist/types/components.d.ts +199 -4
- package/dist/types/global/env.d.ts +2 -0
- package/dist/types/index.d.ts +1 -1
- package/dist/types/lib/evaluation/constants.d.ts +11 -0
- package/dist/types/lib/evaluation/evaluation-engine.d.ts +0 -4
- package/dist/types/lib/evaluation/evaluation-service.d.ts +15 -0
- package/dist/types/lib/evaluation/evaluators/bleu/bleu-evaluator.d.ts +18 -0
- package/dist/types/lib/evaluation/evaluators/bleu/tests/bleu.test.d.ts +1 -0
- package/dist/types/lib/evaluation/evaluators/exact/exact.d.ts +2 -0
- package/dist/types/lib/evaluation/evaluators/rouge1-evaluator.d.ts +17 -0
- package/dist/types/lib/evaluation/evaluators/rougeL-evaluator.d.ts +2 -0
- package/dist/types/lib/evaluation/evaluators/rougeL-evaluator.test.d.ts +1 -0
- package/dist/types/lib/evaluation/evaluators/semantic/SemanticEvaluator.d.ts +6 -0
- package/dist/types/lib/evaluation/evaluators/semantic/evaluate-keywords.d.ts +7 -0
- package/dist/types/lib/evaluation/evaluators/semantic/index.d.ts +2 -0
- package/dist/types/lib/evaluation/evaluators/semantic/model-loader.d.ts +1 -0
- package/dist/types/lib/evaluation/evaluators/semantic/similarity-utils.d.ts +1 -0
- package/dist/types/lib/evaluation/evaluators/semantic/tests/evaluate-keywords.test.d.ts +1 -0
- package/dist/types/lib/evaluation/evaluators/semantic/text-utils.d.ts +1 -0
- package/dist/types/lib/evaluation/index.d.ts +2 -2
- package/dist/types/lib/evaluation/rouge1-evaluator.test.d.ts +1 -0
- package/dist/types/lib/evaluation/types.d.ts +19 -7
- package/dist/types/lib/file/file-download.d.ts +7 -0
- package/dist/types/lib/file/file-reader.d.ts +6 -0
- package/dist/types/lib/form/components/app-chips.d.ts +20 -0
- package/dist/types/lib/form/components/app-select.d.ts +7 -0
- package/dist/types/lib/form/components/app-textarea.d.ts +14 -0
- package/dist/types/lib/form/form-builder.d.ts +24 -0
- package/dist/types/lib/form/schema/base-input-field-config.d.ts +37 -0
- package/dist/types/lib/form/schema/form-control-config.d.ts +13 -0
- package/dist/types/lib/form/schema/index.d.ts +9 -0
- package/dist/types/lib/import-export/test-results-csv.d.ts +13 -0
- package/dist/types/lib/import-export/test-suite-exporter.d.ts +16 -0
- package/dist/types/lib/import-export/test-suite-importer.d.ts +12 -0
- package/dist/types/lib/rate-limited-fetcher/rate-limited-fetcher.d.ts +1 -1
- package/dist/types/lib/test-cases/test-case-factory.d.ts +12 -0
- package/dist/types/lib/test-cases/test-case-mutations.d.ts +9 -0
- package/dist/types/lib/ui/button/button.d.ts +13 -0
- package/dist/types/lib/ui/button/index.d.ts +2 -0
- package/dist/types/lib/ui/icon-button/icon-button.d.ts +11 -0
- package/dist/types/lib/ui/icon-button/index.d.ts +2 -0
- package/dist/types/services/adapters.d.ts +3 -0
- package/dist/types/services/models/gemini.d.ts +11 -0
- package/dist/types/stencil-public-runtime.d.ts +110 -6
- package/dist/types/types/evaluation.d.ts +9 -0
- package/dist/types/types/llm-test-runner.d.ts +22 -0
- package/package.json +30 -6
- package/dist/cjs/app-globals-CbbEbofA.js +0 -14
- package/dist/cjs/app-globals-CbbEbofA.js.map +0 -1
- package/dist/cjs/index-D-FySkoV.js +0 -1470
- package/dist/cjs/index-D-FySkoV.js.map +0 -1
- package/dist/cjs/llm-test-runner.cjs.entry.js +0 -9
- package/dist/cjs/llm-test-runner.entry.cjs.js.map +0 -1
- package/dist/components/p-CYUbsbxt.js +0 -1770
- package/dist/components/p-CYUbsbxt.js.map +0 -1
- package/dist/esm/app-globals-BOQOUavG.js +0 -12
- package/dist/esm/app-globals-BOQOUavG.js.map +0 -1
- package/dist/esm/index-cncubhtM.js +0 -1463
- package/dist/esm/index-cncubhtM.js.map +0 -1
- package/dist/esm/llm-test-runner.entry.js +0 -3
- package/dist/esm/llm-test-runner.entry.js.map +0 -1
- package/dist/llm-testrunner/llm-test-runner.entry.esm.js.map +0 -1
- package/dist/llm-testrunner/loader.esm.js.map +0 -1
- package/dist/llm-testrunner/p-BOQOUavG.js +0 -2
- package/dist/llm-testrunner/p-BOQOUavG.js.map +0 -1
- package/dist/llm-testrunner/p-cncubhtM.js +0 -3
- package/dist/llm-testrunner/p-cncubhtM.js.map +0 -1
- package/dist/llm-testrunner/p-f68fd660.entry.js +0 -2
- package/dist/llm-testrunner/p-f68fd660.entry.js.map +0 -1
|
@@ -0,0 +1,65 @@
|
|
|
1
|
+
import { jest, describe, it, expect } from "@jest/globals";
|
|
2
|
+
import { evaluateKeywordsSemantically } from "../evaluate-keywords";
|
|
3
|
+
import { DEFAULT_SEMANTIC_PASS_SCORE as DEFAULT_SEMANTIC_THRESHOLD, EvaluationApproach } from "../../../constants";
|
|
4
|
+
describe('evaluateKeywordsSemantically (only extractor mocked)', () => {
|
|
5
|
+
it('should return empty array when no keywords provided', async () => {
|
|
6
|
+
const mockExtractor = jest.fn();
|
|
7
|
+
const result = await evaluateKeywordsSemantically(mockExtractor, 'some response', [], DEFAULT_SEMANTIC_THRESHOLD);
|
|
8
|
+
expect(result).toEqual([]);
|
|
9
|
+
});
|
|
10
|
+
it('should return matches above threshold', async () => {
|
|
11
|
+
const response = 'The quick brown fox';
|
|
12
|
+
const keywords = ['fast', 'animal'];
|
|
13
|
+
const mockExtractor = jest.fn();
|
|
14
|
+
mockExtractor.mockImplementation(async (text) => {
|
|
15
|
+
const data = new Float32Array(text.length).fill(1);
|
|
16
|
+
return { data };
|
|
17
|
+
});
|
|
18
|
+
const cosSpy = jest.spyOn(require('../similarity-utils'), 'cosineSimilarity');
|
|
19
|
+
cosSpy
|
|
20
|
+
.mockReturnValueOnce(0.91) // these are the similarity scores for the keyword 'fast' in the response.
|
|
21
|
+
.mockReturnValueOnce(0.4)
|
|
22
|
+
.mockReturnValueOnce(0.3)
|
|
23
|
+
.mockReturnValueOnce(0.85)
|
|
24
|
+
.mockReturnValueOnce(0.6) // these are the similarity scores for the keyword 'animal' in the response.
|
|
25
|
+
.mockReturnValueOnce(0.5)
|
|
26
|
+
.mockReturnValueOnce(0.7)
|
|
27
|
+
.mockReturnValueOnce(0.8);
|
|
28
|
+
const result = await evaluateKeywordsSemantically(mockExtractor, response, keywords, DEFAULT_SEMANTIC_THRESHOLD);
|
|
29
|
+
expect(result).toHaveLength(2);
|
|
30
|
+
expect(result).toEqual([
|
|
31
|
+
{
|
|
32
|
+
keyword: 'fast',
|
|
33
|
+
found: true,
|
|
34
|
+
evaluationApproachResult: { score: 0.91, approachUsed: EvaluationApproach.SEMANTIC },
|
|
35
|
+
},
|
|
36
|
+
{
|
|
37
|
+
keyword: 'animal',
|
|
38
|
+
found: true,
|
|
39
|
+
evaluationApproachResult: { score: 0.8, approachUsed: EvaluationApproach.SEMANTIC },
|
|
40
|
+
},
|
|
41
|
+
]);
|
|
42
|
+
});
|
|
43
|
+
it('should mark below-threshold as not found', async () => {
|
|
44
|
+
const response = 'A sunny day';
|
|
45
|
+
const keywords = ['rain'];
|
|
46
|
+
const mockExtractor = jest.fn();
|
|
47
|
+
mockExtractor.mockImplementation(async (text) => {
|
|
48
|
+
return { data: new Float32Array(text.length).fill(1) };
|
|
49
|
+
});
|
|
50
|
+
const cosSpy = jest.spyOn(require('../similarity-utils'), 'cosineSimilarity');
|
|
51
|
+
cosSpy
|
|
52
|
+
.mockReturnValueOnce(0.5) // this is the similarity score for the keyword 'rain' in the response.
|
|
53
|
+
.mockReturnValueOnce(0.49)
|
|
54
|
+
.mockReturnValueOnce(0.4);
|
|
55
|
+
const result = await evaluateKeywordsSemantically(mockExtractor, response, keywords, DEFAULT_SEMANTIC_THRESHOLD);
|
|
56
|
+
expect(result).toEqual([
|
|
57
|
+
{
|
|
58
|
+
keyword: 'rain',
|
|
59
|
+
found: false,
|
|
60
|
+
evaluationApproachResult: { score: 0.5, approachUsed: EvaluationApproach.SEMANTIC },
|
|
61
|
+
},
|
|
62
|
+
]);
|
|
63
|
+
});
|
|
64
|
+
});
|
|
65
|
+
//# sourceMappingURL=evaluate-keywords.test.js.map
|
package/dist/collection/lib/evaluation/evaluators/semantic/tests/evaluate-keywords.test.js.map
ADDED
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"evaluate-keywords.test.js","sourceRoot":"","sources":["../../../../../../src/lib/evaluation/evaluators/semantic/tests/evaluate-keywords.test.ts"],"names":[],"mappings":"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","sourcesContent":["import { jest, describe, it, expect } from '@jest/globals';\nimport { evaluateKeywordsSemantically } from '../evaluate-keywords';\nimport { FeatureExtractionPipeline } from '@xenova/transformers';\nimport { \n DEFAULT_SEMANTIC_PASS_SCORE as DEFAULT_SEMANTIC_THRESHOLD,\n EvaluationApproach \n} from '../../../constants';\n\ndescribe('evaluateKeywordsSemantically (only extractor mocked)', () => {\n it('should return empty array when no keywords provided', async () => {\n const mockExtractor = jest.fn() as jest.Mock;\n const result = await evaluateKeywordsSemantically(\n mockExtractor as unknown as FeatureExtractionPipeline,\n 'some response',\n [],\n DEFAULT_SEMANTIC_THRESHOLD,\n );\n\n expect(result).toEqual([]);\n });\n\n it('should return matches above threshold', async () => {\n const response = 'The quick brown fox';\n const keywords = ['fast', 'animal'];\n const mockExtractor = jest.fn() as jest.Mock;\n mockExtractor.mockImplementation(async (text: string) => {\n const data = new Float32Array(text.length).fill(1);\n return { data };\n });\n\n const cosSpy = jest.spyOn(\n require('../similarity-utils'),\n 'cosineSimilarity',\n );\n cosSpy\n .mockReturnValueOnce(0.91) // these are the similarity scores for the keyword 'fast' in the response.\n .mockReturnValueOnce(0.4)\n .mockReturnValueOnce(0.3)\n .mockReturnValueOnce(0.85)\n .mockReturnValueOnce(0.6) // these are the similarity scores for the keyword 'animal' in the response.\n .mockReturnValueOnce(0.5)\n .mockReturnValueOnce(0.7)\n .mockReturnValueOnce(0.8);\n\n const result = await evaluateKeywordsSemantically(\n mockExtractor as unknown as FeatureExtractionPipeline,\n response,\n keywords,\n DEFAULT_SEMANTIC_THRESHOLD,\n );\n\n expect(result).toHaveLength(2);\n expect(result).toEqual([\n {\n keyword: 'fast',\n found: true,\n evaluationApproachResult: { score: 0.91, approachUsed: EvaluationApproach.SEMANTIC },\n },\n {\n keyword: 'animal',\n found: true,\n evaluationApproachResult: { score: 0.8, approachUsed: EvaluationApproach.SEMANTIC },\n },\n ]);\n });\n\n it('should mark below-threshold as not found', async () => {\n const response = 'A sunny day';\n const keywords = ['rain'];\n const mockExtractor = jest.fn() as jest.Mock;\n mockExtractor.mockImplementation(async (text: string) => {\n return { data: new Float32Array(text.length).fill(1) };\n });\n\n const cosSpy = jest.spyOn(\n require('../similarity-utils'),\n 'cosineSimilarity',\n );\n cosSpy\n .mockReturnValueOnce(0.5) // this is the similarity score for the keyword 'rain' in the response.\n .mockReturnValueOnce(0.49)\n .mockReturnValueOnce(0.4);\n\n const result = await evaluateKeywordsSemantically(\n mockExtractor as unknown as FeatureExtractionPipeline,\n response,\n keywords,\n DEFAULT_SEMANTIC_THRESHOLD,\n );\n\n expect(result).toEqual([\n {\n keyword: 'rain',\n found: false,\n evaluationApproachResult: { score: 0.5, approachUsed: EvaluationApproach.SEMANTIC },\n },\n ]);\n });\n});"]}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"text-utils.js","sourceRoot":"","sources":["../../../../../src/lib/evaluation/evaluators/semantic/text-utils.ts"],"names":[],"mappings":"AAAA,mDAAmD;AACnD,MAAM,UAAU,cAAc,CAAC,IAAY;IACzC,OAAO,CAAC,GAAG,IAAI,GAAG,CAAC,IAAI,CAAC,WAAW,EAAE,CAAC,KAAK,CAAC,QAAQ,CAAC,CAAC,CAAC,CAAC;AAC1D,CAAC","sourcesContent":["// Splits the response into unique lowercase words.\nexport function splitIntoWords(text: string): string[] {\n return [...new Set(text.toLowerCase().split(/[^\\w]+/))];\n}\n"]}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"index.js","sourceRoot":"","sources":["../../../src/lib/evaluation/index.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,mBAAmB,EAAE,MAAM,qBAAqB,CAAC;
|
|
1
|
+
{"version":3,"file":"index.js","sourceRoot":"","sources":["../../../src/lib/evaluation/index.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,mBAAmB,EAAE,MAAM,qBAAqB,CAAC;AAQ1D,OAAO,EAAE,mBAAmB,EAAE,CAAC;AAQ/B,MAAM,CAAC,KAAK,UAAU,mBAAmB,CACvC,OAA0B,EAC1B,QAA4B;IAE5B,MAAM,MAAM,GAAG,IAAI,mBAAmB,EAAE,CAAC;IACzC,MAAM,MAAM,CAAC,gBAAgB,CAAC,OAAO,EAAE,QAAQ,CAAC,CAAC;AACnD,CAAC","sourcesContent":["import { LLMEvaluationEngine } from './evaluation-engine';\nimport type {\n EvaluationRequest,\n EvaluationResult,\n KeywordMatch,\n EvaluationCallback,\n} from './types';\n\nexport { LLMEvaluationEngine };\nexport type {\n EvaluationRequest,\n EvaluationResult,\n KeywordMatch,\n EvaluationCallback,\n};\n\nexport async function evaluateLLMResponse(\n request: EvaluationRequest,\n callback: EvaluationCallback,\n): Promise<void> {\n const engine = new LLMEvaluationEngine();\n await engine.evaluateResponse(request, callback);\n}\n"]}
|
|
@@ -0,0 +1,117 @@
|
|
|
1
|
+
import { describe, it, expect } from "@jest/globals";
|
|
2
|
+
import { DEFAULT_ROUGE_PASS_SCORE, EvaluationApproach } from "./constants";
|
|
3
|
+
// Using integration tests with actual js-rouge library (no mocks).
|
|
4
|
+
// This approach tests the real ROUGE-1 scoring behavior rather than just orchestration logic.
|
|
5
|
+
import { performRouge1Evaluation } from "./evaluators/rouge1-evaluator";
|
|
6
|
+
const mockRequest = {
|
|
7
|
+
testCaseId: 'test-000',
|
|
8
|
+
question: 'What is your name?',
|
|
9
|
+
actualResponse: 'I am a large language model',
|
|
10
|
+
expectedOutcome: 'model\nlanguage',
|
|
11
|
+
evaluationParameters: {
|
|
12
|
+
approach: EvaluationApproach.ROUGE_1,
|
|
13
|
+
threshold: 0.5,
|
|
14
|
+
},
|
|
15
|
+
};
|
|
16
|
+
const mockRequestNoThreshold = {
|
|
17
|
+
...mockRequest,
|
|
18
|
+
evaluationParameters: {
|
|
19
|
+
approach: EvaluationApproach.ROUGE_1,
|
|
20
|
+
threshold: undefined,
|
|
21
|
+
},
|
|
22
|
+
};
|
|
23
|
+
describe('performRouge1Evaluation', () => {
|
|
24
|
+
describe('Basic functionality', () => {
|
|
25
|
+
it('should pass when response contains exact keyword matches', async () => {
|
|
26
|
+
const request = {
|
|
27
|
+
...mockRequest,
|
|
28
|
+
actualResponse: 'This is a language model system',
|
|
29
|
+
expectedOutcome: 'language\nmodel',
|
|
30
|
+
};
|
|
31
|
+
const result = await performRouge1Evaluation(request);
|
|
32
|
+
expect(result.passed).toBe(true);
|
|
33
|
+
expect(result.keywordMatches.length).toBe(2);
|
|
34
|
+
expect(result.keywordMatches[0].found).toBe(true);
|
|
35
|
+
expect(result.keywordMatches[0].evaluationApproachResult.score).toBeGreaterThan(0.5);
|
|
36
|
+
expect(result.keywordMatches[1].found).toBe(true);
|
|
37
|
+
expect(result.keywordMatches[1].evaluationApproachResult.score).toBeGreaterThan(0.5);
|
|
38
|
+
});
|
|
39
|
+
it('should fail when keywords are not sufficiently present', async () => {
|
|
40
|
+
const request = {
|
|
41
|
+
...mockRequest,
|
|
42
|
+
actualResponse: 'This is completely unrelated content about cooking',
|
|
43
|
+
expectedOutcome: 'machine learning\nartificial intelligence',
|
|
44
|
+
};
|
|
45
|
+
const result = await performRouge1Evaluation(request);
|
|
46
|
+
expect(result.passed).toBe(false);
|
|
47
|
+
expect(result.keywordMatches[0].found).toBe(false);
|
|
48
|
+
expect(result.keywordMatches[0].evaluationApproachResult.score).toBeLessThan(0.5);
|
|
49
|
+
expect(result.keywordMatches[1].found).toBe(false);
|
|
50
|
+
expect(result.keywordMatches[1].evaluationApproachResult.score).toBeLessThan(0.5);
|
|
51
|
+
});
|
|
52
|
+
it('should partially pass when only some keywords meet threshold', async () => {
|
|
53
|
+
const request = {
|
|
54
|
+
...mockRequest,
|
|
55
|
+
actualResponse: 'Machine learning is fascinating',
|
|
56
|
+
expectedOutcome: 'machine learning\ndatabase systems',
|
|
57
|
+
};
|
|
58
|
+
const result = await performRouge1Evaluation(request);
|
|
59
|
+
expect(result.passed).toBe(false);
|
|
60
|
+
expect(result.keywordMatches[0].found).toBe(true);
|
|
61
|
+
expect(result.keywordMatches[0].evaluationApproachResult.score).toBeGreaterThanOrEqual(0.5);
|
|
62
|
+
expect(result.keywordMatches[1].found).toBe(false);
|
|
63
|
+
expect(result.keywordMatches[1].evaluationApproachResult.score).toBeLessThan(0.5);
|
|
64
|
+
});
|
|
65
|
+
});
|
|
66
|
+
describe('Threshold handling', () => {
|
|
67
|
+
it('should use default threshold when not provided', async () => {
|
|
68
|
+
const result = await performRouge1Evaluation(mockRequestNoThreshold);
|
|
69
|
+
expect(result.evaluationParameters.threshold).toBe(DEFAULT_ROUGE_PASS_SCORE);
|
|
70
|
+
});
|
|
71
|
+
it('should pass all keywords with threshold 0.0', async () => {
|
|
72
|
+
const request = {
|
|
73
|
+
...mockRequest,
|
|
74
|
+
actualResponse: 'completely unrelated text about cooking',
|
|
75
|
+
expectedOutcome: 'quantum physics\nmathematics',
|
|
76
|
+
evaluationParameters: {
|
|
77
|
+
approach: EvaluationApproach.ROUGE_1,
|
|
78
|
+
threshold: 0.0,
|
|
79
|
+
},
|
|
80
|
+
};
|
|
81
|
+
const result = await performRouge1Evaluation(request);
|
|
82
|
+
expect(result.passed).toBe(true);
|
|
83
|
+
expect(result.keywordMatches.every(m => m.found)).toBe(true);
|
|
84
|
+
expect(result.evaluationParameters.threshold).toBe(0.0);
|
|
85
|
+
});
|
|
86
|
+
it('should fail when threshold is 1.0 and match is not perfect', async () => {
|
|
87
|
+
const request = {
|
|
88
|
+
...mockRequest,
|
|
89
|
+
actualResponse: 'This is about learning concepts',
|
|
90
|
+
expectedOutcome: 'machine learning',
|
|
91
|
+
evaluationParameters: {
|
|
92
|
+
approach: EvaluationApproach.ROUGE_1,
|
|
93
|
+
threshold: 1.0,
|
|
94
|
+
},
|
|
95
|
+
};
|
|
96
|
+
const result = await performRouge1Evaluation(request);
|
|
97
|
+
expect(result.evaluationParameters.threshold).toBe(1.0);
|
|
98
|
+
expect(result.keywordMatches[0].evaluationApproachResult.score).toBeLessThan(1.0);
|
|
99
|
+
});
|
|
100
|
+
});
|
|
101
|
+
describe('Edge cases', () => {
|
|
102
|
+
it('should handle empty actualResponse', async () => {
|
|
103
|
+
const request = { ...mockRequest, actualResponse: '' };
|
|
104
|
+
const result = await performRouge1Evaluation(request);
|
|
105
|
+
expect(result.passed).toBe(false);
|
|
106
|
+
expect(result.keywordMatches[0].evaluationApproachResult.score).toBe(0);
|
|
107
|
+
expect(result.keywordMatches[1].evaluationApproachResult.score).toBe(0);
|
|
108
|
+
});
|
|
109
|
+
it('should handle empty expectedOutcome string', async () => {
|
|
110
|
+
const request = { ...mockRequest, expectedOutcome: '' };
|
|
111
|
+
const result = await performRouge1Evaluation(request);
|
|
112
|
+
expect(result.passed).toBe(true);
|
|
113
|
+
expect(result.keywordMatches.length).toBe(0);
|
|
114
|
+
});
|
|
115
|
+
});
|
|
116
|
+
});
|
|
117
|
+
//# sourceMappingURL=rouge1-evaluator.test.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"rouge1-evaluator.test.js","sourceRoot":"","sources":["../../../src/lib/evaluation/rouge1-evaluator.test.ts"],"names":[],"mappings":"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","sourcesContent":["import { describe, it, expect } from '@jest/globals';\nimport { EvaluationRequest } from './types';\nimport { DEFAULT_ROUGE_PASS_SCORE, EvaluationApproach } from './constants';\n// Using integration tests with actual js-rouge library (no mocks).\n// This approach tests the real ROUGE-1 scoring behavior rather than just orchestration logic.\nimport { performRouge1Evaluation } from './evaluators/rouge1-evaluator';\n\nconst mockRequest: EvaluationRequest = {\n testCaseId: 'test-000',\n question: 'What is your name?',\n actualResponse: 'I am a large language model',\n expectedOutcome: 'model\\nlanguage',\n evaluationParameters: {\n approach: EvaluationApproach.ROUGE_1,\n threshold: 0.5,\n },\n};\n\nconst mockRequestNoThreshold: EvaluationRequest = {\n ...mockRequest,\n evaluationParameters: {\n approach: EvaluationApproach.ROUGE_1,\n threshold: undefined,\n },\n};\n\ndescribe('performRouge1Evaluation', () => {\n describe('Basic functionality', () => {\n it('should pass when response contains exact keyword matches', async () => {\n const request: EvaluationRequest = {\n ...mockRequest,\n actualResponse: 'This is a language model system',\n expectedOutcome: 'language\\nmodel',\n };\n\n const result = await performRouge1Evaluation(request);\n\n expect(result.passed).toBe(true);\n expect(result.keywordMatches.length).toBe(2);\n expect(result.keywordMatches[0].found).toBe(true);\n expect(\n result.keywordMatches[0].evaluationApproachResult.score,\n ).toBeGreaterThan(0.5);\n expect(result.keywordMatches[1].found).toBe(true);\n expect(\n result.keywordMatches[1].evaluationApproachResult.score,\n ).toBeGreaterThan(0.5);\n });\n\n it('should fail when keywords are not sufficiently present', async () => {\n const request: EvaluationRequest = {\n ...mockRequest,\n actualResponse: 'This is completely unrelated content about cooking',\n expectedOutcome: 'machine learning\\nartificial intelligence',\n };\n\n const result = await performRouge1Evaluation(request);\n\n expect(result.passed).toBe(false);\n expect(result.keywordMatches[0].found).toBe(false);\n expect(\n result.keywordMatches[0].evaluationApproachResult.score,\n ).toBeLessThan(0.5);\n expect(result.keywordMatches[1].found).toBe(false);\n expect(\n result.keywordMatches[1].evaluationApproachResult.score,\n ).toBeLessThan(0.5);\n });\n\n it('should partially pass when only some keywords meet threshold', async () => {\n const request: EvaluationRequest = {\n ...mockRequest,\n actualResponse: 'Machine learning is fascinating',\n expectedOutcome: 'machine learning\\ndatabase systems',\n };\n\n const result = await performRouge1Evaluation(request);\n\n expect(result.passed).toBe(false);\n expect(result.keywordMatches[0].found).toBe(true);\n expect(\n result.keywordMatches[0].evaluationApproachResult.score,\n ).toBeGreaterThanOrEqual(0.5);\n expect(result.keywordMatches[1].found).toBe(false);\n expect(\n result.keywordMatches[1].evaluationApproachResult.score,\n ).toBeLessThan(0.5);\n });\n });\n\n describe('Threshold handling', () => {\n it('should use default threshold when not provided', async () => {\n const result = await performRouge1Evaluation(mockRequestNoThreshold);\n\n expect(result.evaluationParameters.threshold).toBe(\n DEFAULT_ROUGE_PASS_SCORE,\n );\n });\n\n it('should pass all keywords with threshold 0.0', async () => {\n const request: EvaluationRequest = {\n ...mockRequest,\n actualResponse: 'completely unrelated text about cooking',\n expectedOutcome: 'quantum physics\\nmathematics',\n evaluationParameters: {\n approach: EvaluationApproach.ROUGE_1,\n threshold: 0.0,\n },\n };\n\n const result = await performRouge1Evaluation(request);\n\n expect(result.passed).toBe(true);\n expect(result.keywordMatches.every(m => m.found)).toBe(true);\n expect(result.evaluationParameters.threshold).toBe(0.0);\n });\n\n it('should fail when threshold is 1.0 and match is not perfect', async () => {\n const request: EvaluationRequest = {\n ...mockRequest,\n actualResponse: 'This is about learning concepts',\n expectedOutcome: 'machine learning',\n evaluationParameters: {\n approach: EvaluationApproach.ROUGE_1,\n threshold: 1.0,\n },\n };\n\n const result = await performRouge1Evaluation(request);\n\n expect(result.evaluationParameters.threshold).toBe(1.0);\n expect(\n result.keywordMatches[0].evaluationApproachResult.score,\n ).toBeLessThan(1.0);\n });\n });\n\n describe('Edge cases', () => {\n it('should handle empty actualResponse', async () => {\n const request = { ...mockRequest, actualResponse: '' };\n\n const result = await performRouge1Evaluation(request);\n\n expect(result.passed).toBe(false);\n expect(result.keywordMatches[0].evaluationApproachResult.score).toBe(0);\n expect(result.keywordMatches[1].evaluationApproachResult.score).toBe(0);\n });\n\n it('should handle empty expectedOutcome string', async () => {\n const request = { ...mockRequest, expectedOutcome: '' };\n\n const result = await performRouge1Evaluation(request);\n\n expect(result.passed).toBe(true);\n expect(result.keywordMatches.length).toBe(0);\n });\n });\n});\n"]}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"types.js","sourceRoot":"","sources":["../../../src/lib/evaluation/types.ts"],"names":[],"mappings":"","sourcesContent":["
|
|
1
|
+
{"version":3,"file":"types.js","sourceRoot":"","sources":["../../../src/lib/evaluation/types.ts"],"names":[],"mappings":"","sourcesContent":["import {\n EvaluationParameters,\n EvaluationApproachResult,\n} from '../../types/evaluation';\n\nexport interface EvaluationRequest {\n testCaseId: string;\n question: string;\n expectedOutcome: string;\n actualResponse: string;\n evaluationParameters: EvaluationParameters;\n}\n\nexport interface EvaluationResult {\n testCaseId: string;\n passed: boolean;\n keywordMatches: KeywordMatch[];\n timestamp?: string;\n evaluationParameters: EvaluationParameters;\n evaluationApproachResult: EvaluationApproachResult;\n}\n\nexport interface KeywordMatch {\n keyword: string;\n found: boolean;\n evaluationApproachResult: EvaluationApproachResult;\n}\n\nexport type EvaluationCallback = (result: EvaluationResult) => void;\n\nexport interface RougeKeywordDetails {\n rouge1: number;\n rougeL: number;\n scoreUsed: string;\n approach: string;\n}\n\nexport interface Rouge1OverallDetails {\n keywordsPassed: number;\n totalKeywords: number;\n passRate: string;\n thresholdUsed: number;\n approach: string;\n}\n"]}
|
|
@@ -0,0 +1,18 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Downloads a file to the user's device
|
|
3
|
+
* @param content - The content to download
|
|
4
|
+
* @param filename - The name of the file to download
|
|
5
|
+
* @param mimeType - The MIME type of the file
|
|
6
|
+
*/
|
|
7
|
+
export function downloadFile(content, filename, mimeType) {
|
|
8
|
+
const blob = new Blob([content], { type: mimeType });
|
|
9
|
+
const url = URL.createObjectURL(blob);
|
|
10
|
+
const link = document.createElement('a');
|
|
11
|
+
link.href = url;
|
|
12
|
+
link.download = filename;
|
|
13
|
+
document.body.appendChild(link);
|
|
14
|
+
link.click();
|
|
15
|
+
document.body.removeChild(link);
|
|
16
|
+
URL.revokeObjectURL(url);
|
|
17
|
+
}
|
|
18
|
+
//# sourceMappingURL=file-download.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"file-download.js","sourceRoot":"","sources":["../../../src/lib/file/file-download.ts"],"names":[],"mappings":"AAAA;;;;;GAKG;AACH,MAAM,UAAU,YAAY,CAC1B,OAAe,EACf,QAAgB,EAChB,QAAgB;IAEhB,MAAM,IAAI,GAAG,IAAI,IAAI,CAAC,CAAC,OAAO,CAAC,EAAE,EAAE,IAAI,EAAE,QAAQ,EAAE,CAAC,CAAC;IACrD,MAAM,GAAG,GAAG,GAAG,CAAC,eAAe,CAAC,IAAI,CAAC,CAAC;IACtC,MAAM,IAAI,GAAG,QAAQ,CAAC,aAAa,CAAC,GAAG,CAAC,CAAC;IACzC,IAAI,CAAC,IAAI,GAAG,GAAG,CAAC;IAChB,IAAI,CAAC,QAAQ,GAAG,QAAQ,CAAC;IACzB,QAAQ,CAAC,IAAI,CAAC,WAAW,CAAC,IAAI,CAAC,CAAC;IAChC,IAAI,CAAC,KAAK,EAAE,CAAC;IACb,QAAQ,CAAC,IAAI,CAAC,WAAW,CAAC,IAAI,CAAC,CAAC;IAChC,GAAG,CAAC,eAAe,CAAC,GAAG,CAAC,CAAC;AAC3B,CAAC","sourcesContent":["/**\n * Downloads a file to the user's device\n * @param content - The content to download\n * @param filename - The name of the file to download\n * @param mimeType - The MIME type of the file\n */\nexport function downloadFile(\n content: string,\n filename: string,\n mimeType: string,\n): void {\n const blob = new Blob([content], { type: mimeType });\n const url = URL.createObjectURL(blob);\n const link = document.createElement('a');\n link.href = url;\n link.download = filename;\n document.body.appendChild(link);\n link.click();\n document.body.removeChild(link);\n URL.revokeObjectURL(url);\n}\n\n"]}
|
|
@@ -0,0 +1,14 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Reads a file asynchronously and returns its content as a string
|
|
3
|
+
* @param file - The File object to read
|
|
4
|
+
* @returns Promise that resolves with the file content as a string
|
|
5
|
+
*/
|
|
6
|
+
export function readFileAsync(file) {
|
|
7
|
+
return new Promise((resolve, reject) => {
|
|
8
|
+
const reader = new FileReader();
|
|
9
|
+
reader.onload = () => resolve(reader.result);
|
|
10
|
+
reader.onerror = () => reject(reader.error);
|
|
11
|
+
reader.readAsText(file);
|
|
12
|
+
});
|
|
13
|
+
}
|
|
14
|
+
//# sourceMappingURL=file-reader.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"file-reader.js","sourceRoot":"","sources":["../../../src/lib/file/file-reader.ts"],"names":[],"mappings":"AAAA;;;;GAIG;AACH,MAAM,UAAU,aAAa,CAAC,IAAU;IACtC,OAAO,IAAI,OAAO,CAAC,CAAC,OAAO,EAAE,MAAM,EAAE,EAAE;QACrC,MAAM,MAAM,GAAG,IAAI,UAAU,EAAE,CAAC;QAChC,MAAM,CAAC,MAAM,GAAG,GAAG,EAAE,CAAC,OAAO,CAAC,MAAM,CAAC,MAAgB,CAAC,CAAC;QACvD,MAAM,CAAC,OAAO,GAAG,GAAG,EAAE,CAAC,MAAM,CAAC,MAAM,CAAC,KAAK,CAAC,CAAC;QAC5C,MAAM,CAAC,UAAU,CAAC,IAAI,CAAC,CAAC;IAC1B,CAAC,CAAC,CAAC;AACL,CAAC","sourcesContent":["/**\n * Reads a file asynchronously and returns its content as a string\n * @param file - The File object to read\n * @returns Promise that resolves with the file content as a string\n */\nexport function readFileAsync(file: File): Promise<string> {\n return new Promise((resolve, reject) => {\n const reader = new FileReader();\n reader.onload = () => resolve(reader.result as string);\n reader.onerror = () => reject(reader.error);\n reader.readAsText(file);\n });\n}\n\n"]}
|
|
@@ -0,0 +1,97 @@
|
|
|
1
|
+
.app-chips {
|
|
2
|
+
margin-bottom: var(--spacing-4);
|
|
3
|
+
}
|
|
4
|
+
|
|
5
|
+
.app-chips__label {
|
|
6
|
+
display: block;
|
|
7
|
+
margin-bottom: var(--spacing-2);
|
|
8
|
+
font-weight: var(--font-weight-medium);
|
|
9
|
+
color: var(--foreground);
|
|
10
|
+
font-size: var(--font-size-sm);
|
|
11
|
+
}
|
|
12
|
+
|
|
13
|
+
.app-chips__container {
|
|
14
|
+
display: flex;
|
|
15
|
+
flex-wrap: wrap;
|
|
16
|
+
gap: var(--spacing-2);
|
|
17
|
+
align-items: center;
|
|
18
|
+
}
|
|
19
|
+
|
|
20
|
+
.app-chips__chip {
|
|
21
|
+
display: inline-flex;
|
|
22
|
+
align-items: center;
|
|
23
|
+
gap: var(--spacing-2);
|
|
24
|
+
padding: var(--spacing-1) var(--spacing-2);
|
|
25
|
+
font-size: var(--font-size-xs);
|
|
26
|
+
font-weight: var(--font-weight-medium);
|
|
27
|
+
border-radius: var(--radius-md);
|
|
28
|
+
background: var(--accent);
|
|
29
|
+
border: var(--border-width) solid var(--border);
|
|
30
|
+
}
|
|
31
|
+
|
|
32
|
+
/* Keyword-style chip override (non-URL chips) */
|
|
33
|
+
.app-chips__chip:not(:has(a)) {
|
|
34
|
+
background: var(--info);
|
|
35
|
+
color: var(--info-foreground);
|
|
36
|
+
border: none;
|
|
37
|
+
border-radius: var(--radius-2xl);
|
|
38
|
+
}
|
|
39
|
+
|
|
40
|
+
.app-chips__link {
|
|
41
|
+
color: var(--info);
|
|
42
|
+
text-decoration: none;
|
|
43
|
+
max-width: 200px;
|
|
44
|
+
overflow: hidden;
|
|
45
|
+
text-overflow: ellipsis;
|
|
46
|
+
white-space: nowrap;
|
|
47
|
+
}
|
|
48
|
+
|
|
49
|
+
.app-chips__link:hover {
|
|
50
|
+
text-decoration: underline;
|
|
51
|
+
}
|
|
52
|
+
|
|
53
|
+
.app-chips__remove {
|
|
54
|
+
background: none;
|
|
55
|
+
border: none;
|
|
56
|
+
cursor: pointer;
|
|
57
|
+
font-size: var(--font-size-xs);
|
|
58
|
+
padding: 0;
|
|
59
|
+
width: var(--spacing-4);
|
|
60
|
+
height: var(--spacing-4);
|
|
61
|
+
display: flex;
|
|
62
|
+
align-items: center;
|
|
63
|
+
justify-content: center;
|
|
64
|
+
border-radius: var(--radius-full);
|
|
65
|
+
color: var(--muted-foreground);
|
|
66
|
+
opacity: var(--opacity-muted);
|
|
67
|
+
}
|
|
68
|
+
|
|
69
|
+
.app-chips__chip:not(:has(a)) .app-chips__remove {
|
|
70
|
+
color: var(--info-foreground);
|
|
71
|
+
opacity: var(--opacity-hover);
|
|
72
|
+
}
|
|
73
|
+
|
|
74
|
+
.app-chips__remove:hover {
|
|
75
|
+
opacity: 1;
|
|
76
|
+
background: var(--muted);
|
|
77
|
+
}
|
|
78
|
+
|
|
79
|
+
.app-chips__chip:not(:has(a)) .app-chips__remove:hover {
|
|
80
|
+
background: rgba(255, 255, 255, 0.2);
|
|
81
|
+
}
|
|
82
|
+
|
|
83
|
+
.app-chips__input {
|
|
84
|
+
border: var(--border-width) solid var(--input);
|
|
85
|
+
border-radius: var(--radius-md);
|
|
86
|
+
padding: var(--spacing-2);
|
|
87
|
+
font-size: var(--font-size-xs);
|
|
88
|
+
outline: none;
|
|
89
|
+
min-width: 120px;
|
|
90
|
+
background: var(--background);
|
|
91
|
+
color: var(--foreground);
|
|
92
|
+
}
|
|
93
|
+
|
|
94
|
+
.app-chips__input:focus {
|
|
95
|
+
border-color: var(--ring);
|
|
96
|
+
box-shadow: 0 0 0 2px rgba(59, 130, 246, 0.1);
|
|
97
|
+
}
|
|
@@ -0,0 +1,155 @@
|
|
|
1
|
+
import { h } from "@stencil/core";
|
|
2
|
+
export class AppChips {
|
|
3
|
+
value = [];
|
|
4
|
+
config;
|
|
5
|
+
testCaseId;
|
|
6
|
+
addChip;
|
|
7
|
+
removeChip;
|
|
8
|
+
emitAddChip(val) {
|
|
9
|
+
this.addChip.emit({
|
|
10
|
+
key: this.config.name,
|
|
11
|
+
value: val,
|
|
12
|
+
testCaseId: this.testCaseId,
|
|
13
|
+
});
|
|
14
|
+
}
|
|
15
|
+
emitRemoveChip(index) {
|
|
16
|
+
this.removeChip.emit({
|
|
17
|
+
key: this.config.name,
|
|
18
|
+
index,
|
|
19
|
+
testCaseId: this.testCaseId,
|
|
20
|
+
});
|
|
21
|
+
}
|
|
22
|
+
render() {
|
|
23
|
+
const c = this.config;
|
|
24
|
+
const allowedAttrs = {
|
|
25
|
+
placeholder: c.placeholder,
|
|
26
|
+
required: c.required,
|
|
27
|
+
disabled: c.disabled,
|
|
28
|
+
readOnly: c.readOnly,
|
|
29
|
+
id: c.name,
|
|
30
|
+
name: c.name,
|
|
31
|
+
autocomplete: c.autocomplete,
|
|
32
|
+
};
|
|
33
|
+
return (h("div", { key: '80363b5a83bffa034454e85213bc554d0685675d', class: "app-chips" }, c.label && (h("label", { key: '9e6641828170ec9dcb8f2e3cee0e8d04e55c676b', class: "app-chips__label", htmlFor: c.name }, c.label)), h("div", { key: '4aa19ca62522e7d3c51d37e52162806a62c7ad23', class: "app-chips__container" }, this.value.map((chip, index) => (h("span", { class: "app-chips__chip", key: index }, c.type === 'url' ? (h("a", { href: chip, target: "_blank", rel: "noopener noreferrer", class: "app-chips__link" }, chip)) : (chip), h("button", { class: "app-chips__remove", type: "button", onClick: () => this.emitRemoveChip(index) }, "\u00D7")))), h("input", { key: '82ec8242da85728f8b3838e58eaf13b583179a26', class: "app-chips__input", type: c.type || 'text', ...allowedAttrs, onKeyDown: (e) => {
|
|
34
|
+
if (e.key === 'Enter') {
|
|
35
|
+
const input = e.target;
|
|
36
|
+
const val = input.value.trim();
|
|
37
|
+
if (!val)
|
|
38
|
+
return;
|
|
39
|
+
this.emitAddChip(val);
|
|
40
|
+
input.value = '';
|
|
41
|
+
}
|
|
42
|
+
} }))));
|
|
43
|
+
}
|
|
44
|
+
static get is() { return "app-chips"; }
|
|
45
|
+
static get encapsulation() { return "shadow"; }
|
|
46
|
+
static get originalStyleUrls() {
|
|
47
|
+
return {
|
|
48
|
+
"$": ["app-chips.css"]
|
|
49
|
+
};
|
|
50
|
+
}
|
|
51
|
+
static get styleUrls() {
|
|
52
|
+
return {
|
|
53
|
+
"$": ["app-chips.css"]
|
|
54
|
+
};
|
|
55
|
+
}
|
|
56
|
+
static get properties() {
|
|
57
|
+
return {
|
|
58
|
+
"value": {
|
|
59
|
+
"type": "unknown",
|
|
60
|
+
"mutable": false,
|
|
61
|
+
"complexType": {
|
|
62
|
+
"original": "string[]",
|
|
63
|
+
"resolved": "string[]",
|
|
64
|
+
"references": {}
|
|
65
|
+
},
|
|
66
|
+
"required": false,
|
|
67
|
+
"optional": false,
|
|
68
|
+
"docs": {
|
|
69
|
+
"tags": [],
|
|
70
|
+
"text": ""
|
|
71
|
+
},
|
|
72
|
+
"getter": false,
|
|
73
|
+
"setter": false,
|
|
74
|
+
"defaultValue": "[]"
|
|
75
|
+
},
|
|
76
|
+
"config": {
|
|
77
|
+
"type": "unknown",
|
|
78
|
+
"mutable": false,
|
|
79
|
+
"complexType": {
|
|
80
|
+
"original": "ChipsConfig",
|
|
81
|
+
"resolved": "ChipsConfig",
|
|
82
|
+
"references": {
|
|
83
|
+
"ChipsConfig": {
|
|
84
|
+
"location": "import",
|
|
85
|
+
"path": "../schema",
|
|
86
|
+
"id": "src/lib/form/schema/index.ts::ChipsConfig",
|
|
87
|
+
"referenceLocation": "ChipsConfig"
|
|
88
|
+
}
|
|
89
|
+
}
|
|
90
|
+
},
|
|
91
|
+
"required": false,
|
|
92
|
+
"optional": false,
|
|
93
|
+
"docs": {
|
|
94
|
+
"tags": [],
|
|
95
|
+
"text": ""
|
|
96
|
+
},
|
|
97
|
+
"getter": false,
|
|
98
|
+
"setter": false
|
|
99
|
+
},
|
|
100
|
+
"testCaseId": {
|
|
101
|
+
"type": "string",
|
|
102
|
+
"mutable": false,
|
|
103
|
+
"complexType": {
|
|
104
|
+
"original": "string",
|
|
105
|
+
"resolved": "string",
|
|
106
|
+
"references": {}
|
|
107
|
+
},
|
|
108
|
+
"required": false,
|
|
109
|
+
"optional": false,
|
|
110
|
+
"docs": {
|
|
111
|
+
"tags": [],
|
|
112
|
+
"text": ""
|
|
113
|
+
},
|
|
114
|
+
"getter": false,
|
|
115
|
+
"setter": false,
|
|
116
|
+
"reflect": false,
|
|
117
|
+
"attribute": "test-case-id"
|
|
118
|
+
}
|
|
119
|
+
};
|
|
120
|
+
}
|
|
121
|
+
static get events() {
|
|
122
|
+
return [{
|
|
123
|
+
"method": "addChip",
|
|
124
|
+
"name": "addChip",
|
|
125
|
+
"bubbles": true,
|
|
126
|
+
"cancelable": true,
|
|
127
|
+
"composed": true,
|
|
128
|
+
"docs": {
|
|
129
|
+
"tags": [],
|
|
130
|
+
"text": ""
|
|
131
|
+
},
|
|
132
|
+
"complexType": {
|
|
133
|
+
"original": "{\n key: string;\n value: string;\n testCaseId: string;\n }",
|
|
134
|
+
"resolved": "{ key: string; value: string; testCaseId: string; }",
|
|
135
|
+
"references": {}
|
|
136
|
+
}
|
|
137
|
+
}, {
|
|
138
|
+
"method": "removeChip",
|
|
139
|
+
"name": "removeChip",
|
|
140
|
+
"bubbles": true,
|
|
141
|
+
"cancelable": true,
|
|
142
|
+
"composed": true,
|
|
143
|
+
"docs": {
|
|
144
|
+
"tags": [],
|
|
145
|
+
"text": ""
|
|
146
|
+
},
|
|
147
|
+
"complexType": {
|
|
148
|
+
"original": "{\n key: string;\n index: number;\n testCaseId: string;\n }",
|
|
149
|
+
"resolved": "{ key: string; index: number; testCaseId: string; }",
|
|
150
|
+
"references": {}
|
|
151
|
+
}
|
|
152
|
+
}];
|
|
153
|
+
}
|
|
154
|
+
}
|
|
155
|
+
//# sourceMappingURL=app-chips.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"app-chips.js","sourceRoot":"","sources":["../../../../src/lib/form/components/app-chips.tsx"],"names":[],"mappings":"AAAA,OAAO,EAAE,SAAS,EAAE,IAAI,EAAE,CAAC,EAAE,KAAK,EAAgB,MAAM,eAAe,CAAC;AAQxE,MAAM,OAAO,QAAQ;IACX,KAAK,GAAa,EAAE,CAAC;IACrB,MAAM,CAAc;IACpB,UAAU,CAAS;IAElB,OAAO,CAIb;IAEM,UAAU,CAIhB;IAEK,WAAW,CAAC,GAAW;QAC7B,IAAI,CAAC,OAAO,CAAC,IAAI,CAAC;YAChB,GAAG,EAAE,IAAI,CAAC,MAAM,CAAC,IAAI;YACrB,KAAK,EAAE,GAAG;YACV,UAAU,EAAE,IAAI,CAAC,UAAU;SAC5B,CAAC,CAAC;IACL,CAAC;IAEO,cAAc,CAAC,KAAa;QAClC,IAAI,CAAC,UAAU,CAAC,IAAI,CAAC;YACnB,GAAG,EAAE,IAAI,CAAC,MAAM,CAAC,IAAI;YACrB,KAAK;YACL,UAAU,EAAE,IAAI,CAAC,UAAU;SAC5B,CAAC,CAAC;IACL,CAAC;IAED,MAAM;QACJ,MAAM,CAAC,GAAG,IAAI,CAAC,MAAM,CAAC;QAEtB,MAAM,YAAY,GAAG;YACnB,WAAW,EAAE,CAAC,CAAC,WAAW;YAC1B,QAAQ,EAAE,CAAC,CAAC,QAAQ;YACpB,QAAQ,EAAE,CAAC,CAAC,QAAQ;YACpB,QAAQ,EAAE,CAAC,CAAC,QAAQ;YACpB,EAAE,EAAE,CAAC,CAAC,IAAI;YACV,IAAI,EAAE,CAAC,CAAC,IAAI;YACZ,YAAY,EAAE,CAAC,CAAC,YAAY;SAC7B,CAAC;QAEF,OAAO,CACL,4DAAK,KAAK,EAAC,WAAW;YACnB,CAAC,CAAC,KAAK,IAAI,CACV,8DAAO,KAAK,EAAC,kBAAkB,EAAC,OAAO,EAAE,CAAC,CAAC,IAAI,IAC5C,CAAC,CAAC,KAAK,CACF,CACT;YAED,4DAAK,KAAK,EAAC,sBAAsB;gBAC9B,IAAI,CAAC,KAAK,CAAC,GAAG,CAAC,CAAC,IAAI,EAAE,KAAK,EAAE,EAAE,CAAC,CAC/B,YAAM,KAAK,EAAC,iBAAiB,EAAC,GAAG,EAAE,KAAK;oBACrC,CAAC,CAAC,IAAI,KAAK,KAAK,CAAC,CAAC,CAAC,CAClB,SACE,IAAI,EAAE,IAAI,EACV,MAAM,EAAC,QAAQ,EACf,GAAG,EAAC,qBAAqB,EACzB,KAAK,EAAC,iBAAiB,IAEtB,IAAI,CACH,CACL,CAAC,CAAC,CAAC,CACF,IAAI,CACL;oBAED,cACE,KAAK,EAAC,mBAAmB,EACzB,IAAI,EAAC,QAAQ,EACb,OAAO,EAAE,GAAG,EAAE,CAAC,IAAI,CAAC,cAAc,CAAC,KAAK,CAAC,aAGlC,CACJ,CACR,CAAC;gBAEF,8DACE,KAAK,EAAC,kBAAkB,EACxB,IAAI,EAAE,CAAC,CAAC,IAAI,IAAI,MAAM,KAClB,YAAY,EAChB,SAAS,EAAE,CAAC,CAAgB,EAAE,EAAE;wBAC9B,IAAI,CAAC,CAAC,GAAG,KAAK,OAAO,EAAE,CAAC;4BACtB,MAAM,KAAK,GAAG,CAAC,CAAC,MAA0B,CAAC;4BAC3C,MAAM,GAAG,GAAG,KAAK,CAAC,KAAK,CAAC,IAAI,EAAE,CAAC;4BAC/B,IAAI,CAAC,GAAG;gCAAE,OAAO;4BAEjB,IAAI,CAAC,WAAW,CAAC,GAAG,CAAC,CAAC;4BACtB,KAAK,CAAC,KAAK,GAAG,EAAE,CAAC;wBACnB,CAAC;oBACH,CAAC,GACD,CACE,CACF,CACP,CAAC;IACJ,CAAC;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;CACF","sourcesContent":["import { Component, Prop, h, Event, EventEmitter } from '@stencil/core';\nimport { ChipsConfig } from '../schema';\n\n@Component({\n tag: 'app-chips',\n styleUrl: 'app-chips.css',\n shadow: true,\n})\nexport class AppChips {\n @Prop() value: string[] = [];\n @Prop() config: ChipsConfig;\n @Prop() testCaseId: string;\n\n @Event() addChip: EventEmitter<{\n key: string;\n value: string;\n testCaseId: string;\n }>;\n\n @Event() removeChip: EventEmitter<{\n key: string;\n index: number;\n testCaseId: string;\n }>;\n\n private emitAddChip(val: string) {\n this.addChip.emit({\n key: this.config.name,\n value: val,\n testCaseId: this.testCaseId,\n });\n }\n\n private emitRemoveChip(index: number) {\n this.removeChip.emit({\n key: this.config.name,\n index,\n testCaseId: this.testCaseId,\n });\n }\n\n render() {\n const c = this.config;\n\n const allowedAttrs = {\n placeholder: c.placeholder,\n required: c.required,\n disabled: c.disabled,\n readOnly: c.readOnly,\n id: c.name,\n name: c.name,\n autocomplete: c.autocomplete,\n };\n\n return (\n <div class=\"app-chips\">\n {c.label && (\n <label class=\"app-chips__label\" htmlFor={c.name}>\n {c.label}\n </label>\n )}\n\n <div class=\"app-chips__container\">\n {this.value.map((chip, index) => (\n <span class=\"app-chips__chip\" key={index}>\n {c.type === 'url' ? (\n <a\n href={chip}\n target=\"_blank\"\n rel=\"noopener noreferrer\"\n class=\"app-chips__link\"\n >\n {chip}\n </a>\n ) : (\n chip\n )}\n\n <button\n class=\"app-chips__remove\"\n type=\"button\"\n onClick={() => this.emitRemoveChip(index)}\n >\n ×\n </button>\n </span>\n ))}\n\n <input\n class=\"app-chips__input\"\n type={c.type || 'text'}\n {...allowedAttrs}\n onKeyDown={(e: KeyboardEvent) => {\n if (e.key === 'Enter') {\n const input = e.target as HTMLInputElement;\n const val = input.value.trim();\n if (!val) return;\n\n this.emitAddChip(val);\n input.value = '';\n }\n }}\n />\n </div>\n </div>\n );\n }\n}\n"]}
|
|
@@ -0,0 +1,28 @@
|
|
|
1
|
+
.app-select {
|
|
2
|
+
margin-bottom: var(--spacing-4);
|
|
3
|
+
}
|
|
4
|
+
|
|
5
|
+
.app-select__label {
|
|
6
|
+
display: block;
|
|
7
|
+
margin-bottom: var(--spacing-2);
|
|
8
|
+
font-weight: var(--font-weight-medium);
|
|
9
|
+
color: var(--foreground);
|
|
10
|
+
font-size: var(--font-size-sm);
|
|
11
|
+
}
|
|
12
|
+
|
|
13
|
+
.app-select__select {
|
|
14
|
+
border: var(--border-width) solid var(--input);
|
|
15
|
+
border-radius: var(--radius-md);
|
|
16
|
+
font-size: var(--font-size-sm);
|
|
17
|
+
font-weight: var(--font-weight-medium);
|
|
18
|
+
padding: var(--spacing-1) var(--spacing-2);
|
|
19
|
+
outline: none;
|
|
20
|
+
background: var(--background);
|
|
21
|
+
width: 145px;
|
|
22
|
+
color: var(--foreground);
|
|
23
|
+
}
|
|
24
|
+
|
|
25
|
+
.app-select__select:focus {
|
|
26
|
+
border-color: var(--ring);
|
|
27
|
+
box-shadow: 0 0 0 2px rgba(59, 130, 246, 0.1);
|
|
28
|
+
}
|