@memberjunction/testing-engine 0.0.1 → 2.119.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +403 -29
- package/dist/drivers/AgentEvalDriver.d.ts +197 -0
- package/dist/drivers/AgentEvalDriver.d.ts.map +1 -0
- package/dist/drivers/AgentEvalDriver.js +370 -0
- package/dist/drivers/AgentEvalDriver.js.map +1 -0
- package/dist/drivers/BaseTestDriver.d.ts +145 -0
- package/dist/drivers/BaseTestDriver.d.ts.map +1 -0
- package/dist/drivers/BaseTestDriver.js +266 -0
- package/dist/drivers/BaseTestDriver.js.map +1 -0
- package/dist/drivers/index.d.ts +6 -0
- package/dist/drivers/index.d.ts.map +1 -0
- package/dist/drivers/index.js +22 -0
- package/dist/drivers/index.js.map +1 -0
- package/dist/engine/TestEngine.d.ts +148 -0
- package/dist/engine/TestEngine.d.ts.map +1 -0
- package/dist/engine/TestEngine.js +490 -0
- package/dist/engine/TestEngine.js.map +1 -0
- package/dist/index.d.ts +20 -0
- package/dist/index.d.ts.map +1 -0
- package/dist/index.js +42 -0
- package/dist/index.js.map +1 -0
- package/dist/oracles/ExactMatchOracle.d.ts +98 -0
- package/dist/oracles/ExactMatchOracle.d.ts.map +1 -0
- package/dist/oracles/ExactMatchOracle.js +355 -0
- package/dist/oracles/ExactMatchOracle.js.map +1 -0
- package/dist/oracles/IOracle.d.ts +47 -0
- package/dist/oracles/IOracle.d.ts.map +1 -0
- package/dist/oracles/IOracle.js +7 -0
- package/dist/oracles/IOracle.js.map +1 -0
- package/dist/oracles/LLMJudgeOracle.d.ts +65 -0
- package/dist/oracles/LLMJudgeOracle.d.ts.map +1 -0
- package/dist/oracles/LLMJudgeOracle.js +214 -0
- package/dist/oracles/LLMJudgeOracle.js.map +1 -0
- package/dist/oracles/SQLValidatorOracle.d.ts +78 -0
- package/dist/oracles/SQLValidatorOracle.d.ts.map +1 -0
- package/dist/oracles/SQLValidatorOracle.js +215 -0
- package/dist/oracles/SQLValidatorOracle.js.map +1 -0
- package/dist/oracles/SchemaValidatorOracle.d.ts +61 -0
- package/dist/oracles/SchemaValidatorOracle.d.ts.map +1 -0
- package/dist/oracles/SchemaValidatorOracle.js +193 -0
- package/dist/oracles/SchemaValidatorOracle.js.map +1 -0
- package/dist/oracles/TraceValidatorOracle.d.ts +41 -0
- package/dist/oracles/TraceValidatorOracle.d.ts.map +1 -0
- package/dist/oracles/TraceValidatorOracle.js +159 -0
- package/dist/oracles/TraceValidatorOracle.js.map +1 -0
- package/dist/oracles/index.d.ts +10 -0
- package/dist/oracles/index.d.ts.map +1 -0
- package/dist/oracles/index.js +26 -0
- package/dist/oracles/index.js.map +1 -0
- package/dist/types.d.ts +428 -0
- package/dist/types.d.ts.map +1 -0
- package/dist/types.js +6 -0
- package/dist/types.js.map +1 -0
- package/dist/utils/cost-calculator.d.ts +92 -0
- package/dist/utils/cost-calculator.d.ts.map +1 -0
- package/dist/utils/cost-calculator.js +137 -0
- package/dist/utils/cost-calculator.js.map +1 -0
- package/dist/utils/result-formatter.d.ts +98 -0
- package/dist/utils/result-formatter.d.ts.map +1 -0
- package/dist/utils/result-formatter.js +252 -0
- package/dist/utils/result-formatter.js.map +1 -0
- package/dist/utils/scoring.d.ts +64 -0
- package/dist/utils/scoring.d.ts.map +1 -0
- package/dist/utils/scoring.js +140 -0
- package/dist/utils/scoring.js.map +1 -0
- package/package.json +36 -7
|
@@ -0,0 +1,214 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
/**
|
|
3
|
+
* @fileoverview LLM Judge oracle implementation
|
|
4
|
+
* @module @memberjunction/testing-engine
|
|
5
|
+
*/
|
|
6
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
7
|
+
exports.LLMJudgeOracle = void 0;
|
|
8
|
+
const ai_core_plus_1 = require("@memberjunction/ai-core-plus");
|
|
9
|
+
const ai_prompts_1 = require("@memberjunction/ai-prompts");
|
|
10
|
+
const aiengine_1 = require("@memberjunction/aiengine");
|
|
11
|
+
/**
|
|
12
|
+
* LLM Judge Oracle.
|
|
13
|
+
*
|
|
14
|
+
* Uses an LLM to evaluate output quality based on custom criteria.
|
|
15
|
+
* Provides semantic evaluation beyond deterministic checks.
|
|
16
|
+
*
|
|
17
|
+
* Configuration:
|
|
18
|
+
* - criteria: Array of validation criteria (required)
|
|
19
|
+
* - model: Model to use for judging (default: from prompt or default model)
|
|
20
|
+
* - temperature: Temperature for LLM (default: 0.1 for consistency)
|
|
21
|
+
* - promptTemplate: Custom prompt template (optional, uses default if not provided)
|
|
22
|
+
* - strictMode: Require all criteria to pass (default: false, uses weighted scoring)
|
|
23
|
+
*
|
|
24
|
+
* @example
|
|
25
|
+
* ```typescript
|
|
26
|
+
* const oracle = new LLMJudgeOracle();
|
|
27
|
+
* const result = await oracle.evaluate({
|
|
28
|
+
* actualOutput: { response: 'Sales by region report created successfully' },
|
|
29
|
+
* expectedOutput: {
|
|
30
|
+
* judgeValidationCriteria: [
|
|
31
|
+
* 'Response accurately answers the user\'s question',
|
|
32
|
+
* 'Response includes actionable information',
|
|
33
|
+
* 'Response is professional and clear'
|
|
34
|
+
* ]
|
|
35
|
+
* },
|
|
36
|
+
* contextUser
|
|
37
|
+
* }, {
|
|
38
|
+
* model: 'claude-sonnet-4',
|
|
39
|
+
* temperature: 0.1
|
|
40
|
+
* });
|
|
41
|
+
* ```
|
|
42
|
+
*/
|
|
43
|
+
class LLMJudgeOracle {
|
|
44
|
+
constructor() {
|
|
45
|
+
this.type = 'llm-judge';
|
|
46
|
+
/**
|
|
47
|
+
* Default prompt template for LLM judge.
|
|
48
|
+
* @private
|
|
49
|
+
*/
|
|
50
|
+
this.defaultPromptTemplate = `You are an expert AI evaluator. Your task is to judge whether an AI agent's output meets the specified validation criteria.
|
|
51
|
+
|
|
52
|
+
**Input:**
|
|
53
|
+
{{input}}
|
|
54
|
+
|
|
55
|
+
**Expected Output Requirements:**
|
|
56
|
+
{{expected}}
|
|
57
|
+
|
|
58
|
+
**Actual Output:**
|
|
59
|
+
{{actual}}
|
|
60
|
+
|
|
61
|
+
**Validation Criteria:**
|
|
62
|
+
{{criteria}}
|
|
63
|
+
|
|
64
|
+
**Instructions:**
|
|
65
|
+
For each criterion, evaluate whether the actual output satisfies it. Provide:
|
|
66
|
+
1. A score from 0.0 to 1.0 for each criterion
|
|
67
|
+
2. A brief explanation for each score
|
|
68
|
+
3. An overall assessment
|
|
69
|
+
|
|
70
|
+
Respond in JSON format:
|
|
71
|
+
{
|
|
72
|
+
"criteriaScores": [
|
|
73
|
+
{ "criterion": "...", "score": 0.0-1.0, "explanation": "..." }
|
|
74
|
+
],
|
|
75
|
+
"overallScore": 0.0-1.0,
|
|
76
|
+
"overallAssessment": "...",
|
|
77
|
+
"passed": true/false
|
|
78
|
+
}`;
|
|
79
|
+
}
|
|
80
|
+
/**
|
|
81
|
+
* Evaluate output using LLM judge.
|
|
82
|
+
*
|
|
83
|
+
* @param input - Oracle input with expected criteria and actual output
|
|
84
|
+
* @param config - Oracle configuration
|
|
85
|
+
* @returns Oracle result with LLM judgment
|
|
86
|
+
*/
|
|
87
|
+
async evaluate(input, config) {
|
|
88
|
+
try {
|
|
89
|
+
// Ensure AIEngine is configured
|
|
90
|
+
await aiengine_1.AIEngine.Instance.Config(false, input.contextUser);
|
|
91
|
+
// Get criteria from expected outcomes or config
|
|
92
|
+
const criteria = input.expectedOutput?.judgeValidationCriteria ||
|
|
93
|
+
config.criteria;
|
|
94
|
+
if (!criteria || criteria.length === 0) {
|
|
95
|
+
return {
|
|
96
|
+
oracleType: this.type,
|
|
97
|
+
passed: false,
|
|
98
|
+
score: 0,
|
|
99
|
+
message: 'No validation criteria provided'
|
|
100
|
+
};
|
|
101
|
+
}
|
|
102
|
+
// Find the LLM Judge prompt from AIEngine
|
|
103
|
+
const judgePrompt = aiengine_1.AIEngine.Instance.Prompts.find(p => p.Name === 'Test LLM Judge' || p.Name.toLowerCase().includes('llm judge'));
|
|
104
|
+
if (!judgePrompt) {
|
|
105
|
+
return {
|
|
106
|
+
oracleType: this.type,
|
|
107
|
+
passed: false,
|
|
108
|
+
score: 0,
|
|
109
|
+
message: 'LLM Judge prompt not found in AIEngine.Instance.Prompts. Please create a prompt named "Test LLM Judge".'
|
|
110
|
+
};
|
|
111
|
+
}
|
|
112
|
+
// Prepare data for prompt template
|
|
113
|
+
const inputDefinition = input.test.InputDefinition ?
|
|
114
|
+
(typeof input.test.InputDefinition === 'string' ?
|
|
115
|
+
JSON.parse(input.test.InputDefinition) :
|
|
116
|
+
input.test.InputDefinition) :
|
|
117
|
+
{};
|
|
118
|
+
const promptData = {
|
|
119
|
+
input: JSON.stringify(inputDefinition, null, 2),
|
|
120
|
+
expected: JSON.stringify(input.expectedOutput, null, 2),
|
|
121
|
+
actual: JSON.stringify(input.actualOutput, null, 2),
|
|
122
|
+
criteria: criteria.map((c, i) => `${i + 1}. ${c}`).join('\n')
|
|
123
|
+
};
|
|
124
|
+
// Execute LLM judgment
|
|
125
|
+
const promptParams = new ai_core_plus_1.AIPromptParams();
|
|
126
|
+
promptParams.prompt = judgePrompt;
|
|
127
|
+
promptParams.data = promptData;
|
|
128
|
+
promptParams.contextUser = input.contextUser;
|
|
129
|
+
const runner = new ai_prompts_1.AIPromptRunner();
|
|
130
|
+
const result = await runner.ExecutePrompt(promptParams);
|
|
131
|
+
if (!result.success) {
|
|
132
|
+
return {
|
|
133
|
+
oracleType: this.type,
|
|
134
|
+
passed: false,
|
|
135
|
+
score: 0,
|
|
136
|
+
message: `LLM judgment failed: ${result.errorMessage}`
|
|
137
|
+
};
|
|
138
|
+
}
|
|
139
|
+
// Parse LLM response
|
|
140
|
+
const judgment = this.parseJudgment(result.result);
|
|
141
|
+
// Determine pass/fail
|
|
142
|
+
const strictMode = config.strictMode;
|
|
143
|
+
const passed = strictMode
|
|
144
|
+
? judgment.criteriaScores.every(s => s.score >= 0.8)
|
|
145
|
+
: judgment.overallScore >= 0.7;
|
|
146
|
+
return {
|
|
147
|
+
oracleType: this.type,
|
|
148
|
+
passed,
|
|
149
|
+
score: judgment.overallScore,
|
|
150
|
+
message: judgment.overallAssessment,
|
|
151
|
+
details: {
|
|
152
|
+
criteriaScores: judgment.criteriaScores,
|
|
153
|
+
llmModel: config.model || 'default',
|
|
154
|
+
llmCost: result.cost
|
|
155
|
+
}
|
|
156
|
+
};
|
|
157
|
+
}
|
|
158
|
+
catch (error) {
|
|
159
|
+
return {
|
|
160
|
+
oracleType: this.type,
|
|
161
|
+
passed: false,
|
|
162
|
+
score: 0,
|
|
163
|
+
message: `LLM judge error: ${error.message}`
|
|
164
|
+
};
|
|
165
|
+
}
|
|
166
|
+
}
|
|
167
|
+
/**
|
|
168
|
+
* Build prompt for LLM judge.
|
|
169
|
+
* @private
|
|
170
|
+
*/
|
|
171
|
+
buildPrompt(input, criteria, customTemplate) {
|
|
172
|
+
const template = customTemplate || this.defaultPromptTemplate;
|
|
173
|
+
// Format input data
|
|
174
|
+
const inputStr = JSON.stringify(input.test.InputDefinition, null, 2);
|
|
175
|
+
const expectedStr = JSON.stringify(input.expectedOutput, null, 2);
|
|
176
|
+
const actualStr = JSON.stringify(input.actualOutput, null, 2);
|
|
177
|
+
const criteriaStr = criteria.map((c, i) => `${i + 1}. ${c}`).join('\n');
|
|
178
|
+
// Replace placeholders
|
|
179
|
+
return template
|
|
180
|
+
.replace('{{input}}', inputStr)
|
|
181
|
+
.replace('{{expected}}', expectedStr)
|
|
182
|
+
.replace('{{actual}}', actualStr)
|
|
183
|
+
.replace('{{criteria}}', criteriaStr);
|
|
184
|
+
}
|
|
185
|
+
/**
|
|
186
|
+
* Parse LLM judgment response.
|
|
187
|
+
* @private
|
|
188
|
+
*/
|
|
189
|
+
parseJudgment(response) {
|
|
190
|
+
try {
|
|
191
|
+
// Try to extract JSON from response
|
|
192
|
+
const jsonMatch = response.match(/\{[\s\S]*\}/);
|
|
193
|
+
if (!jsonMatch) {
|
|
194
|
+
throw new Error('No JSON found in LLM response');
|
|
195
|
+
}
|
|
196
|
+
const parsed = JSON.parse(jsonMatch[0]);
|
|
197
|
+
return {
|
|
198
|
+
criteriaScores: parsed.criteriaScores || [],
|
|
199
|
+
overallScore: parsed.overallScore || 0,
|
|
200
|
+
overallAssessment: parsed.overallAssessment || 'No assessment provided'
|
|
201
|
+
};
|
|
202
|
+
}
|
|
203
|
+
catch (error) {
|
|
204
|
+
// Fallback to simple parsing
|
|
205
|
+
return {
|
|
206
|
+
criteriaScores: [],
|
|
207
|
+
overallScore: 0,
|
|
208
|
+
overallAssessment: `Failed to parse LLM response: ${response.substring(0, 200)}`
|
|
209
|
+
};
|
|
210
|
+
}
|
|
211
|
+
}
|
|
212
|
+
}
|
|
213
|
+
exports.LLMJudgeOracle = LLMJudgeOracle;
|
|
214
|
+
//# sourceMappingURL=LLMJudgeOracle.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"LLMJudgeOracle.js","sourceRoot":"","sources":["../../src/oracles/LLMJudgeOracle.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,78 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* @fileoverview SQL validation oracle implementation
|
|
3
|
+
* @module @memberjunction/testing-engine
|
|
4
|
+
*/
|
|
5
|
+
import { IOracle } from './IOracle';
|
|
6
|
+
import { OracleInput, OracleConfig, OracleResult } from '../types';
|
|
7
|
+
/**
|
|
8
|
+
* SQL Validator Oracle.
|
|
9
|
+
*
|
|
10
|
+
* Validates database state by executing SQL queries and comparing results.
|
|
11
|
+
* Useful for testing that agent actions had the expected database effects.
|
|
12
|
+
*
|
|
13
|
+
* Configuration:
|
|
14
|
+
* - queries: Array of SQL validation queries
|
|
15
|
+
* - requireAll: Whether all queries must pass (default: true)
|
|
16
|
+
*
|
|
17
|
+
* Each query object contains:
|
|
18
|
+
* - sql: The SQL query to execute
|
|
19
|
+
* - expectedResult: Expected result (can be value, row count, or boolean)
|
|
20
|
+
* - description: Human-readable description of what the query validates
|
|
21
|
+
*
|
|
22
|
+
* @example
|
|
23
|
+
* ```typescript
|
|
24
|
+
* const oracle = new SQLValidatorOracle();
|
|
25
|
+
* const result = await oracle.evaluate({
|
|
26
|
+
* expectedOutput: {
|
|
27
|
+
* sqlValidations: [
|
|
28
|
+
* {
|
|
29
|
+
* sql: "SELECT COUNT(*) FROM Reports WHERE Name LIKE '%Sales%'",
|
|
30
|
+
* expectedResult: { count: 1 },
|
|
31
|
+
* description: "Sales report was created"
|
|
32
|
+
* },
|
|
33
|
+
* {
|
|
34
|
+
* sql: "SELECT Status FROM Reports WHERE ID = @ReportID",
|
|
35
|
+
* expectedResult: { status: 'Published' },
|
|
36
|
+
* description: "Report status is Published"
|
|
37
|
+
* }
|
|
38
|
+
* ]
|
|
39
|
+
* },
|
|
40
|
+
* actualOutput: {
|
|
41
|
+
* reportId: 'abc-123'
|
|
42
|
+
* },
|
|
43
|
+
* contextUser
|
|
44
|
+
* }, {});
|
|
45
|
+
* ```
|
|
46
|
+
*/
|
|
47
|
+
export declare class SQLValidatorOracle implements IOracle {
|
|
48
|
+
readonly type = "sql-validate";
|
|
49
|
+
/**
|
|
50
|
+
* Evaluate database state using SQL queries.
|
|
51
|
+
*
|
|
52
|
+
* @param input - Oracle input with SQL validations and actual output
|
|
53
|
+
* @param config - Oracle configuration
|
|
54
|
+
* @returns Oracle result with query validation details
|
|
55
|
+
*/
|
|
56
|
+
evaluate(input: OracleInput, config: OracleConfig): Promise<OracleResult>;
|
|
57
|
+
/**
|
|
58
|
+
* Execute a single validation query.
|
|
59
|
+
* @private
|
|
60
|
+
*/
|
|
61
|
+
private executeValidation;
|
|
62
|
+
/**
|
|
63
|
+
* Replace parameters in SQL query with actual values.
|
|
64
|
+
* @private
|
|
65
|
+
*/
|
|
66
|
+
private replaceParameters;
|
|
67
|
+
/**
|
|
68
|
+
* Extract result from query result set.
|
|
69
|
+
* @private
|
|
70
|
+
*/
|
|
71
|
+
private extractResult;
|
|
72
|
+
/**
|
|
73
|
+
* Compare expected and actual results.
|
|
74
|
+
* @private
|
|
75
|
+
*/
|
|
76
|
+
private compareResults;
|
|
77
|
+
}
|
|
78
|
+
//# sourceMappingURL=SQLValidatorOracle.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"SQLValidatorOracle.d.ts","sourceRoot":"","sources":["../../src/oracles/SQLValidatorOracle.ts"],"names":[],"mappings":"AAAA;;;GAGG;AAGH,OAAO,EAAE,OAAO,EAAE,MAAM,WAAW,CAAC;AACpC,OAAO,EAAE,WAAW,EAAE,YAAY,EAAE,YAAY,EAAE,MAAM,UAAU,CAAC;AAEnE;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GAuCG;AACH,qBAAa,kBAAmB,YAAW,OAAO;IAC9C,QAAQ,CAAC,IAAI,kBAAkB;IAE/B;;;;;;OAMG;IACG,QAAQ,CAAC,KAAK,EAAE,WAAW,EAAE,MAAM,EAAE,YAAY,GAAG,OAAO,CAAC,YAAY,CAAC;IAgE/E;;;OAGG;YACW,iBAAiB;IAqD/B;;;OAGG;IACH,OAAO,CAAC,iBAAiB;IA8BzB;;;OAGG;IACH,OAAO,CAAC,aAAa;IAqBrB;;;OAGG;IACH,OAAO,CAAC,cAAc;CA4BzB"}
|
|
@@ -0,0 +1,215 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
/**
|
|
3
|
+
* @fileoverview SQL validation oracle implementation
|
|
4
|
+
* @module @memberjunction/testing-engine
|
|
5
|
+
*/
|
|
6
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
7
|
+
exports.SQLValidatorOracle = void 0;
|
|
8
|
+
const core_1 = require("@memberjunction/core");
|
|
9
|
+
/**
|
|
10
|
+
* SQL Validator Oracle.
|
|
11
|
+
*
|
|
12
|
+
* Validates database state by executing SQL queries and comparing results.
|
|
13
|
+
* Useful for testing that agent actions had the expected database effects.
|
|
14
|
+
*
|
|
15
|
+
* Configuration:
|
|
16
|
+
* - queries: Array of SQL validation queries
|
|
17
|
+
* - requireAll: Whether all queries must pass (default: true)
|
|
18
|
+
*
|
|
19
|
+
* Each query object contains:
|
|
20
|
+
* - sql: The SQL query to execute
|
|
21
|
+
* - expectedResult: Expected result (can be value, row count, or boolean)
|
|
22
|
+
* - description: Human-readable description of what the query validates
|
|
23
|
+
*
|
|
24
|
+
* @example
|
|
25
|
+
* ```typescript
|
|
26
|
+
* const oracle = new SQLValidatorOracle();
|
|
27
|
+
* const result = await oracle.evaluate({
|
|
28
|
+
* expectedOutput: {
|
|
29
|
+
* sqlValidations: [
|
|
30
|
+
* {
|
|
31
|
+
* sql: "SELECT COUNT(*) FROM Reports WHERE Name LIKE '%Sales%'",
|
|
32
|
+
* expectedResult: { count: 1 },
|
|
33
|
+
* description: "Sales report was created"
|
|
34
|
+
* },
|
|
35
|
+
* {
|
|
36
|
+
* sql: "SELECT Status FROM Reports WHERE ID = @ReportID",
|
|
37
|
+
* expectedResult: { status: 'Published' },
|
|
38
|
+
* description: "Report status is Published"
|
|
39
|
+
* }
|
|
40
|
+
* ]
|
|
41
|
+
* },
|
|
42
|
+
* actualOutput: {
|
|
43
|
+
* reportId: 'abc-123'
|
|
44
|
+
* },
|
|
45
|
+
* contextUser
|
|
46
|
+
* }, {});
|
|
47
|
+
* ```
|
|
48
|
+
*/
|
|
49
|
+
class SQLValidatorOracle {
|
|
50
|
+
constructor() {
|
|
51
|
+
this.type = 'sql-validate';
|
|
52
|
+
}
|
|
53
|
+
/**
|
|
54
|
+
* Evaluate database state using SQL queries.
|
|
55
|
+
*
|
|
56
|
+
* @param input - Oracle input with SQL validations and actual output
|
|
57
|
+
* @param config - Oracle configuration
|
|
58
|
+
* @returns Oracle result with query validation details
|
|
59
|
+
*/
|
|
60
|
+
async evaluate(input, config) {
|
|
61
|
+
try {
|
|
62
|
+
// Get SQL validations from expected outcomes
|
|
63
|
+
const validations = input.expectedOutput?.sqlValidations || [];
|
|
64
|
+
if (validations.length === 0) {
|
|
65
|
+
return {
|
|
66
|
+
oracleType: this.type,
|
|
67
|
+
passed: false,
|
|
68
|
+
score: 0,
|
|
69
|
+
message: 'No SQL validations provided in ExpectedOutcomes.sqlValidations'
|
|
70
|
+
};
|
|
71
|
+
}
|
|
72
|
+
const requireAll = config.requireAll !== false; // Default true
|
|
73
|
+
const results = [];
|
|
74
|
+
// Execute each validation query
|
|
75
|
+
for (const validation of validations) {
|
|
76
|
+
const queryResult = await this.executeValidation(validation, input.actualOutput, input.contextUser);
|
|
77
|
+
results.push(queryResult);
|
|
78
|
+
}
|
|
79
|
+
// Calculate score and determine pass/fail
|
|
80
|
+
const passedCount = results.filter(r => r.passed).length;
|
|
81
|
+
const totalCount = results.length;
|
|
82
|
+
const score = totalCount > 0 ? passedCount / totalCount : 0;
|
|
83
|
+
const passed = requireAll ? passedCount === totalCount : passedCount > 0;
|
|
84
|
+
return {
|
|
85
|
+
oracleType: this.type,
|
|
86
|
+
passed,
|
|
87
|
+
score,
|
|
88
|
+
message: requireAll
|
|
89
|
+
? `${passedCount}/${totalCount} validation(s) passed`
|
|
90
|
+
: `At least one validation passed (${passedCount}/${totalCount})`,
|
|
91
|
+
details: { validations: results }
|
|
92
|
+
};
|
|
93
|
+
}
|
|
94
|
+
catch (error) {
|
|
95
|
+
return {
|
|
96
|
+
oracleType: this.type,
|
|
97
|
+
passed: false,
|
|
98
|
+
score: 0,
|
|
99
|
+
message: `SQL validation error: ${error.message}`
|
|
100
|
+
};
|
|
101
|
+
}
|
|
102
|
+
}
|
|
103
|
+
/**
|
|
104
|
+
* Execute a single validation query.
|
|
105
|
+
* @private
|
|
106
|
+
*/
|
|
107
|
+
async executeValidation(validation, actualOutput, contextUser) {
|
|
108
|
+
try {
|
|
109
|
+
// Replace parameters in SQL with values from actualOutput
|
|
110
|
+
const sql = this.replaceParameters(validation.sql, actualOutput);
|
|
111
|
+
// Get database provider from Metadata.Provider
|
|
112
|
+
const dbProvider = core_1.Metadata.Provider;
|
|
113
|
+
// Execute the SQL query
|
|
114
|
+
const queryResults = await dbProvider.ExecuteSQL(sql, undefined, // No parameters (already substituted in SQL string)
|
|
115
|
+
{ description: validation.description || 'SQL Validation' }, contextUser);
|
|
116
|
+
// Extract result (handle single value, single row, or multiple rows)
|
|
117
|
+
const actualResult = this.extractResult(queryResults);
|
|
118
|
+
// Compare with expected result
|
|
119
|
+
const passed = this.compareResults(validation.expectedResult, actualResult);
|
|
120
|
+
return {
|
|
121
|
+
description: validation.description || 'SQL validation',
|
|
122
|
+
sql: validation.sql,
|
|
123
|
+
passed,
|
|
124
|
+
expected: validation.expectedResult,
|
|
125
|
+
actual: actualResult
|
|
126
|
+
};
|
|
127
|
+
}
|
|
128
|
+
catch (error) {
|
|
129
|
+
return {
|
|
130
|
+
description: validation.description || 'SQL validation',
|
|
131
|
+
sql: validation.sql,
|
|
132
|
+
passed: false,
|
|
133
|
+
expected: validation.expectedResult,
|
|
134
|
+
actual: null,
|
|
135
|
+
error: error.message
|
|
136
|
+
};
|
|
137
|
+
}
|
|
138
|
+
}
|
|
139
|
+
/**
|
|
140
|
+
* Replace parameters in SQL query with actual values.
|
|
141
|
+
* @private
|
|
142
|
+
*/
|
|
143
|
+
replaceParameters(sql, actualOutput) {
|
|
144
|
+
if (!actualOutput || typeof actualOutput !== 'object') {
|
|
145
|
+
return sql;
|
|
146
|
+
}
|
|
147
|
+
let result = sql;
|
|
148
|
+
const outputObj = actualOutput;
|
|
149
|
+
// Replace @ParameterName with values from actualOutput
|
|
150
|
+
const paramMatches = sql.matchAll(/@(\w+)/g);
|
|
151
|
+
for (const match of paramMatches) {
|
|
152
|
+
const paramName = match[1];
|
|
153
|
+
const camelCaseParam = paramName.charAt(0).toLowerCase() + paramName.slice(1);
|
|
154
|
+
// Try both original and camelCase versions
|
|
155
|
+
const value = outputObj[paramName] || outputObj[camelCaseParam];
|
|
156
|
+
if (value !== undefined) {
|
|
157
|
+
// Properly escape and quote the value
|
|
158
|
+
const escapedValue = typeof value === 'string'
|
|
159
|
+
? `'${value.replace(/'/g, "''")}'`
|
|
160
|
+
: String(value);
|
|
161
|
+
result = result.replace(new RegExp(`@${paramName}`, 'g'), escapedValue);
|
|
162
|
+
}
|
|
163
|
+
}
|
|
164
|
+
return result;
|
|
165
|
+
}
|
|
166
|
+
/**
|
|
167
|
+
* Extract result from query result set.
|
|
168
|
+
* @private
|
|
169
|
+
*/
|
|
170
|
+
extractResult(results) {
|
|
171
|
+
if (!results || results.length === 0) {
|
|
172
|
+
return null;
|
|
173
|
+
}
|
|
174
|
+
// If single row, single column, return the value
|
|
175
|
+
if (results.length === 1) {
|
|
176
|
+
const row = results[0];
|
|
177
|
+
const keys = Object.keys(row);
|
|
178
|
+
if (keys.length === 1) {
|
|
179
|
+
return row[keys[0]];
|
|
180
|
+
}
|
|
181
|
+
return row;
|
|
182
|
+
}
|
|
183
|
+
// Multiple rows
|
|
184
|
+
return results;
|
|
185
|
+
}
|
|
186
|
+
/**
|
|
187
|
+
* Compare expected and actual results.
|
|
188
|
+
* @private
|
|
189
|
+
*/
|
|
190
|
+
compareResults(expected, actual) {
|
|
191
|
+
// Handle null/undefined
|
|
192
|
+
if (expected === null || expected === undefined) {
|
|
193
|
+
return actual === null || actual === undefined;
|
|
194
|
+
}
|
|
195
|
+
// Handle boolean
|
|
196
|
+
if (typeof expected === 'boolean') {
|
|
197
|
+
return Boolean(actual) === expected;
|
|
198
|
+
}
|
|
199
|
+
// Handle number
|
|
200
|
+
if (typeof expected === 'number') {
|
|
201
|
+
return Number(actual) === expected;
|
|
202
|
+
}
|
|
203
|
+
// Handle string
|
|
204
|
+
if (typeof expected === 'string') {
|
|
205
|
+
return String(actual) === expected;
|
|
206
|
+
}
|
|
207
|
+
// Handle object/array
|
|
208
|
+
if (typeof expected === 'object') {
|
|
209
|
+
return JSON.stringify(expected) === JSON.stringify(actual);
|
|
210
|
+
}
|
|
211
|
+
return false;
|
|
212
|
+
}
|
|
213
|
+
}
|
|
214
|
+
exports.SQLValidatorOracle = SQLValidatorOracle;
|
|
215
|
+
//# sourceMappingURL=SQLValidatorOracle.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"SQLValidatorOracle.js","sourceRoot":"","sources":["../../src/oracles/SQLValidatorOracle.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,61 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* @fileoverview Schema validation oracle implementation
|
|
3
|
+
* @module @memberjunction/testing-engine
|
|
4
|
+
*/
|
|
5
|
+
import { IOracle } from './IOracle';
|
|
6
|
+
import { OracleInput, OracleConfig, OracleResult } from '../types';
|
|
7
|
+
/**
|
|
8
|
+
* Schema Validator Oracle.
|
|
9
|
+
*
|
|
10
|
+
* Validates that actual output conforms to an expected JSON schema.
|
|
11
|
+
* Uses JSON Schema draft-07 specification for validation.
|
|
12
|
+
*
|
|
13
|
+
* Configuration:
|
|
14
|
+
* - schema: JSON Schema object defining expected structure
|
|
15
|
+
* - strict: Whether to fail on additional properties (default: false)
|
|
16
|
+
*
|
|
17
|
+
* @example
|
|
18
|
+
* ```typescript
|
|
19
|
+
* const oracle = new SchemaValidatorOracle();
|
|
20
|
+
* const result = await oracle.evaluate({
|
|
21
|
+
* actualOutput: { name: 'John', age: 30 },
|
|
22
|
+
* expectedOutput: {
|
|
23
|
+
* responseSchema: {
|
|
24
|
+
* type: 'object',
|
|
25
|
+
* required: ['name', 'age'],
|
|
26
|
+
* properties: {
|
|
27
|
+
* name: { type: 'string' },
|
|
28
|
+
* age: { type: 'number' }
|
|
29
|
+
* }
|
|
30
|
+
* }
|
|
31
|
+
* }
|
|
32
|
+
* }, {});
|
|
33
|
+
* ```
|
|
34
|
+
*/
|
|
35
|
+
export declare class SchemaValidatorOracle implements IOracle {
|
|
36
|
+
readonly type = "schema-validate";
|
|
37
|
+
/**
|
|
38
|
+
* Evaluate actual output against JSON schema.
|
|
39
|
+
*
|
|
40
|
+
* @param input - Oracle input with expected schema and actual output
|
|
41
|
+
* @param config - Oracle configuration
|
|
42
|
+
* @returns Oracle result with pass/fail and validation details
|
|
43
|
+
*/
|
|
44
|
+
evaluate(input: OracleInput, config: OracleConfig): Promise<OracleResult>;
|
|
45
|
+
/**
|
|
46
|
+
* Validate data against JSON schema.
|
|
47
|
+
* @private
|
|
48
|
+
*/
|
|
49
|
+
private validateAgainstSchema;
|
|
50
|
+
/**
|
|
51
|
+
* Validate a single value against schema.
|
|
52
|
+
* @private
|
|
53
|
+
*/
|
|
54
|
+
private validateValue;
|
|
55
|
+
/**
|
|
56
|
+
* Get JSON Schema type for a value.
|
|
57
|
+
* @private
|
|
58
|
+
*/
|
|
59
|
+
private getType;
|
|
60
|
+
}
|
|
61
|
+
//# sourceMappingURL=SchemaValidatorOracle.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"SchemaValidatorOracle.d.ts","sourceRoot":"","sources":["../../src/oracles/SchemaValidatorOracle.ts"],"names":[],"mappings":"AAAA;;;GAGG;AAEH,OAAO,EAAE,OAAO,EAAE,MAAM,WAAW,CAAC;AACpC,OAAO,EAAE,WAAW,EAAE,YAAY,EAAE,YAAY,EAAE,MAAM,UAAU,CAAC;AAEnE;;;;;;;;;;;;;;;;;;;;;;;;;;;GA2BG;AACH,qBAAa,qBAAsB,YAAW,OAAO;IACjD,QAAQ,CAAC,IAAI,qBAAqB;IAElC;;;;;;OAMG;IACG,QAAQ,CAAC,KAAK,EAAE,WAAW,EAAE,MAAM,EAAE,YAAY,GAAG,OAAO,CAAC,YAAY,CAAC;IA+C/E;;;OAGG;IACH,OAAO,CAAC,qBAAqB;IAc7B;;;OAGG;IACH,OAAO,CAAC,aAAa;IAiFrB;;;OAGG;IACH,OAAO,CAAC,OAAO;CA6BlB"}
|