promptfoo 0.95.0 → 0.96.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 +2 -1
- package/dist/package.json +13 -11
- package/dist/src/app/assets/{index-zXzgAsKj.js → index-Dwt7E2K_.js} +178 -178
- package/dist/src/app/assets/{index.es-Jztl1qad.js → index.es-CooNf3HB.js} +1 -1
- package/dist/src/app/assets/{sync-BJBBGzPI.js → sync-Bj1WJrHQ.js} +1 -1
- package/dist/src/app/index.html +1 -1
- package/dist/src/assertions/bleu.d.ts +33 -0
- package/dist/src/assertions/bleu.d.ts.map +1 -0
- package/dist/src/assertions/bleu.js +116 -0
- package/dist/src/assertions/bleu.js.map +1 -0
- package/dist/src/assertions/index.d.ts +1 -12
- package/dist/src/assertions/index.d.ts.map +1 -1
- package/dist/src/assertions/index.js +20 -250
- package/dist/src/assertions/index.js.map +1 -1
- package/dist/src/assertions/json.d.ts +8 -0
- package/dist/src/assertions/json.d.ts.map +1 -0
- package/dist/src/assertions/json.js +121 -0
- package/dist/src/assertions/json.js.map +1 -0
- package/dist/src/assertions/perplexity.d.ts +4 -0
- package/dist/src/assertions/perplexity.d.ts.map +1 -0
- package/dist/src/assertions/perplexity.js +40 -0
- package/dist/src/assertions/perplexity.js.map +1 -0
- package/dist/src/assertions/sql.d.ts +4 -0
- package/dist/src/assertions/sql.d.ts.map +1 -0
- package/dist/src/assertions/sql.js +87 -0
- package/dist/src/assertions/sql.js.map +1 -0
- package/dist/src/assertions/xml.d.ts +9 -0
- package/dist/src/assertions/xml.d.ts.map +1 -0
- package/dist/src/assertions/xml.js +57 -0
- package/dist/src/assertions/xml.js.map +1 -0
- package/dist/src/commands/eval/filterTests.d.ts +1 -0
- package/dist/src/commands/eval/filterTests.d.ts.map +1 -1
- package/dist/src/commands/eval/filterTests.js +14 -1
- package/dist/src/commands/eval/filterTests.js.map +1 -1
- package/dist/src/commands/eval.d.ts.map +1 -1
- package/dist/src/commands/eval.js +14 -3
- package/dist/src/commands/eval.js.map +1 -1
- package/dist/src/commands/import.d.ts.map +1 -1
- package/dist/src/commands/import.js +1 -0
- package/dist/src/commands/import.js.map +1 -1
- package/dist/src/commands/list.d.ts.map +1 -1
- package/dist/src/commands/list.js +15 -0
- package/dist/src/commands/list.js.map +1 -1
- package/dist/src/csv.d.ts.map +1 -1
- package/dist/src/csv.js +9 -4
- package/dist/src/csv.js.map +1 -1
- package/dist/src/database/tables.d.ts +189 -1
- package/dist/src/database/tables.d.ts.map +1 -1
- package/dist/src/envars.d.ts +9 -0
- package/dist/src/envars.d.ts.map +1 -1
- package/dist/src/envars.js.map +1 -1
- package/dist/src/evaluator.js +2 -2
- package/dist/src/evaluator.js.map +1 -1
- package/dist/src/evaluatorHelpers.d.ts.map +1 -1
- package/dist/src/evaluatorHelpers.js +4 -0
- package/dist/src/evaluatorHelpers.js.map +1 -1
- package/dist/src/globalConfig/accounts.d.ts +1 -0
- package/dist/src/globalConfig/accounts.d.ts.map +1 -1
- package/dist/src/globalConfig/accounts.js +24 -0
- package/dist/src/globalConfig/accounts.js.map +1 -1
- package/dist/src/index.d.ts +74 -68
- package/dist/src/index.d.ts.map +1 -1
- package/dist/src/onboarding.js +8 -8
- package/dist/src/onboarding.js.map +1 -1
- package/dist/src/providers/adaline.gateway.d.ts.map +1 -1
- package/dist/src/providers/adaline.gateway.js +4 -4
- package/dist/src/providers/adaline.gateway.js.map +1 -1
- package/dist/src/providers/anthropic.d.ts.map +1 -1
- package/dist/src/providers/anthropic.js +21 -0
- package/dist/src/providers/anthropic.js.map +1 -1
- package/dist/src/providers/{azureopenai.d.ts → azure.d.ts} +13 -13
- package/dist/src/providers/azure.d.ts.map +1 -0
- package/dist/src/providers/{azureopenai.js → azure.js} +64 -42
- package/dist/src/providers/azure.js.map +1 -0
- package/dist/src/providers/{azureopenaiUtil.d.ts → azureUtil.d.ts} +1 -1
- package/dist/src/providers/azureUtil.d.ts.map +1 -0
- package/dist/src/providers/{azureopenaiUtil.js → azureUtil.js} +3 -3
- package/dist/src/providers/azureUtil.js.map +1 -0
- package/dist/src/providers/bedrock.d.ts +5 -3
- package/dist/src/providers/bedrock.d.ts.map +1 -1
- package/dist/src/providers/bedrock.js +37 -8
- package/dist/src/providers/bedrock.js.map +1 -1
- package/dist/src/providers/defaults.d.ts.map +1 -1
- package/dist/src/providers/defaults.js +36 -0
- package/dist/src/providers/defaults.js.map +1 -1
- package/dist/src/providers/portkey.d.ts +3 -2
- package/dist/src/providers/portkey.d.ts.map +1 -1
- package/dist/src/providers/portkey.js +17 -10
- package/dist/src/providers/portkey.js.map +1 -1
- package/dist/src/providers/promptfoo.js +2 -2
- package/dist/src/providers/promptfoo.js.map +1 -1
- package/dist/src/providers.d.ts +9 -5
- package/dist/src/providers.d.ts.map +1 -1
- package/dist/src/providers.js +16 -11
- package/dist/src/providers.js.map +1 -1
- package/dist/src/redteam/commands/generate.d.ts.map +1 -1
- package/dist/src/redteam/commands/generate.js +5 -1
- package/dist/src/redteam/commands/generate.js.map +1 -1
- package/dist/src/redteam/commands/init.d.ts +11 -0
- package/dist/src/redteam/commands/init.d.ts.map +1 -1
- package/dist/src/redteam/commands/init.js +47 -12
- package/dist/src/redteam/commands/init.js.map +1 -1
- package/dist/src/redteam/commands/poison.d.ts +3 -0
- package/dist/src/redteam/commands/poison.d.ts.map +1 -0
- package/dist/src/redteam/commands/poison.js +165 -0
- package/dist/src/redteam/commands/poison.js.map +1 -0
- package/dist/src/redteam/commands/run.d.ts.map +1 -1
- package/dist/src/redteam/commands/run.js +2 -0
- package/dist/src/redteam/commands/run.js.map +1 -1
- package/dist/src/redteam/constants.d.ts +2 -2
- package/dist/src/redteam/constants.d.ts.map +1 -1
- package/dist/src/redteam/constants.js +13 -4
- package/dist/src/redteam/constants.js.map +1 -1
- package/dist/src/redteam/extraction/util.js +1 -1
- package/dist/src/redteam/extraction/util.js.map +1 -1
- package/dist/src/redteam/graders.d.ts +34 -32
- package/dist/src/redteam/graders.d.ts.map +1 -1
- package/dist/src/redteam/graders.js +34 -33
- package/dist/src/redteam/graders.js.map +1 -1
- package/dist/src/redteam/index.d.ts.map +1 -1
- package/dist/src/redteam/index.js +9 -2
- package/dist/src/redteam/index.js.map +1 -1
- package/dist/src/redteam/plugins/bfla.d.ts.map +1 -1
- package/dist/src/redteam/plugins/bfla.js +5 -3
- package/dist/src/redteam/plugins/bfla.js.map +1 -1
- package/dist/src/redteam/plugins/bola.js +3 -3
- package/dist/src/redteam/plugins/index.d.ts.map +1 -1
- package/dist/src/redteam/plugins/index.js +3 -2
- package/dist/src/redteam/plugins/index.js.map +1 -1
- package/dist/src/redteam/plugins/intent.d.ts +22 -0
- package/dist/src/redteam/plugins/intent.d.ts.map +1 -0
- package/dist/src/redteam/plugins/intent.js +100 -0
- package/dist/src/redteam/plugins/intent.js.map +1 -0
- package/dist/src/redteam/plugins/pii.d.ts.map +1 -1
- package/dist/src/redteam/plugins/pii.js +21 -14
- package/dist/src/redteam/plugins/pii.js.map +1 -1
- package/dist/src/redteam/plugins/rbac.d.ts.map +1 -1
- package/dist/src/redteam/plugins/rbac.js +5 -4
- package/dist/src/redteam/plugins/rbac.js.map +1 -1
- package/dist/src/redteam/plugins/sqlInjection.d.ts.map +1 -1
- package/dist/src/redteam/plugins/sqlInjection.js +13 -4
- package/dist/src/redteam/plugins/sqlInjection.js.map +1 -1
- package/dist/src/redteam/providers/crescendo/index.d.ts.map +1 -1
- package/dist/src/redteam/providers/crescendo/index.js +6 -4
- package/dist/src/redteam/providers/crescendo/index.js.map +1 -1
- package/dist/src/redteam/providers/goat.js +1 -1
- package/dist/src/redteam/providers/goat.js.map +1 -1
- package/dist/src/redteam/providers/iterative.d.ts.map +1 -1
- package/dist/src/redteam/providers/iterative.js +4 -2
- package/dist/src/redteam/providers/iterative.js.map +1 -1
- package/dist/src/redteam/providers/iterativeImage.d.ts.map +1 -1
- package/dist/src/redteam/providers/iterativeImage.js +4 -2
- package/dist/src/redteam/providers/iterativeImage.js.map +1 -1
- package/dist/src/redteam/providers/iterativeTree.d.ts +3 -1
- package/dist/src/redteam/providers/iterativeTree.d.ts.map +1 -1
- package/dist/src/redteam/providers/iterativeTree.js +5 -3
- package/dist/src/redteam/providers/iterativeTree.js.map +1 -1
- package/dist/src/redteam/providers/shared.d.ts +2 -2
- package/dist/src/redteam/providers/shared.d.ts.map +1 -1
- package/dist/src/redteam/providers/shared.js +2 -2
- package/dist/src/redteam/providers/shared.js.map +1 -1
- package/dist/src/redteam/strategies/mathPrompt.js +1 -1
- package/dist/src/redteam/strategies/mathPrompt.js.map +1 -1
- package/dist/src/redteam/strategies/multilingual.js +1 -1
- package/dist/src/redteam/strategies/multilingual.js.map +1 -1
- package/dist/src/redteam/types.d.ts +1 -0
- package/dist/src/redteam/types.d.ts.map +1 -1
- package/dist/src/remoteGrading.js +1 -1
- package/dist/src/remoteGrading.js.map +1 -1
- package/dist/src/telemetry.d.ts +2 -2
- package/dist/src/types/index.d.ts +4630 -11
- package/dist/src/types/index.d.ts.map +1 -1
- package/dist/src/types/index.js +2 -0
- package/dist/src/types/index.js.map +1 -1
- package/dist/src/types/providers.d.ts +12 -0
- package/dist/src/types/providers.d.ts.map +1 -1
- package/dist/src/types/providers.js.map +1 -1
- package/dist/src/util/config/load.d.ts +1 -1
- package/dist/src/util/config/load.d.ts.map +1 -1
- package/dist/src/util/config/load.js +14 -2
- package/dist/src/util/config/load.js.map +1 -1
- package/dist/src/util/index.d.ts +34 -0
- package/dist/src/util/index.d.ts.map +1 -1
- package/dist/src/validators/providers.d.ts +391 -0
- package/dist/src/validators/providers.d.ts.map +1 -1
- package/dist/src/validators/providers.js +18 -0
- package/dist/src/validators/providers.js.map +1 -1
- package/dist/src/validators/redteam.d.ts +136 -0
- package/dist/src/validators/redteam.d.ts.map +1 -1
- package/dist/test/assertions/bleu.test.d.ts +2 -0
- package/dist/test/assertions/bleu.test.d.ts.map +1 -0
- package/dist/test/assertions/bleu.test.js +137 -0
- package/dist/test/assertions/bleu.test.js.map +1 -0
- package/dist/test/assertions/index.test.js +276 -297
- package/dist/test/assertions/index.test.js.map +1 -1
- package/dist/test/assertions/json.test.d.ts +2 -0
- package/dist/test/assertions/json.test.d.ts.map +1 -0
- package/dist/test/assertions/json.test.js +36 -0
- package/dist/test/assertions/json.test.js.map +1 -0
- package/dist/test/assertions/sql.test.d.ts +2 -0
- package/dist/test/assertions/sql.test.d.ts.map +1 -0
- package/dist/test/{is-sql-tests/node-sql-parser.test.js → assertions/sql.test.js} +13 -13
- package/dist/test/assertions/sql.test.js.map +1 -0
- package/dist/test/commands/eval/filterTests.test.js +30 -0
- package/dist/test/commands/eval/filterTests.test.js.map +1 -1
- package/dist/test/factories/evalFactory.d.ts +155 -1
- package/dist/test/factories/evalFactory.d.ts.map +1 -1
- package/dist/test/onboarding.test.js +126 -1
- package/dist/test/onboarding.test.js.map +1 -1
- package/dist/test/providers/anthropic.test.js +81 -0
- package/dist/test/providers/anthropic.test.js.map +1 -1
- package/dist/test/providers/azure.test.js +22 -25
- package/dist/test/providers/azure.test.js.map +1 -1
- package/dist/test/providers/bedrock.test.js +178 -55
- package/dist/test/providers/bedrock.test.js.map +1 -1
- package/dist/test/providers/index.test.js +7 -7
- package/dist/test/providers/index.test.js.map +1 -1
- package/dist/test/providers/portkey.test.d.ts +2 -0
- package/dist/test/providers/portkey.test.d.ts.map +1 -0
- package/dist/test/providers/portkey.test.js +46 -0
- package/dist/test/providers/portkey.test.js.map +1 -0
- package/dist/test/redteam/commands/init.test.d.ts +2 -0
- package/dist/test/redteam/commands/init.test.d.ts.map +1 -0
- package/dist/test/redteam/commands/init.test.js +109 -0
- package/dist/test/redteam/commands/init.test.js.map +1 -0
- package/dist/test/redteam/plugins/pluginDocumentation.test.js +4 -1
- package/dist/test/redteam/plugins/pluginDocumentation.test.js.map +1 -1
- package/dist/test/redteam/providers/goat.test.js +1 -1
- package/dist/test/redteam/providers/goat.test.js.map +1 -1
- package/dist/test/redteam/providers/iterativeTree.test.js +8 -3
- package/dist/test/redteam/providers/iterativeTree.test.js.map +1 -1
- package/dist/tsconfig.tsbuildinfo +1 -1
- package/package.json +13 -11
- package/dist/src/providers/azureopenai.d.ts.map +0 -1
- package/dist/src/providers/azureopenai.js.map +0 -1
- package/dist/src/providers/azureopenaiUtil.d.ts.map +0 -1
- package/dist/src/providers/azureopenaiUtil.js.map +0 -1
- package/dist/test/is-sql-tests/node-sql-parser.test.d.ts +0 -2
- package/dist/test/is-sql-tests/node-sql-parser.test.d.ts.map +0 -1
- package/dist/test/is-sql-tests/node-sql-parser.test.js.map +0 -1
|
@@ -31,6 +31,7 @@ const fs = __importStar(require("fs"));
|
|
|
31
31
|
const node_module_1 = require("node:module");
|
|
32
32
|
const path = __importStar(require("path"));
|
|
33
33
|
const assertions_1 = require("../../src/assertions");
|
|
34
|
+
const xml_1 = require("../../src/assertions/xml");
|
|
34
35
|
const fetch_1 = require("../../src/fetch");
|
|
35
36
|
const openai_1 = require("../../src/providers/openai");
|
|
36
37
|
const replicate_1 = require("../../src/providers/replicate");
|
|
@@ -103,30 +104,6 @@ jest.mock('../../src/matchers', () => {
|
|
|
103
104
|
};
|
|
104
105
|
});
|
|
105
106
|
const Grader = new utils_1.TestGrader();
|
|
106
|
-
describe('createAjv', () => {
|
|
107
|
-
beforeAll(() => {
|
|
108
|
-
delete process.env.PROMPTFOO_DISABLE_AJV_STRICT_MODE;
|
|
109
|
-
jest.resetModules();
|
|
110
|
-
});
|
|
111
|
-
afterAll(() => {
|
|
112
|
-
delete process.env.PROMPTFOO_DISABLE_AJV_STRICT_MODE;
|
|
113
|
-
});
|
|
114
|
-
it('should create an Ajv instance with default options', () => {
|
|
115
|
-
const ajv = (0, assertions_1.createAjv)();
|
|
116
|
-
expect(ajv).toBeDefined();
|
|
117
|
-
expect(ajv.opts.strictSchema).toBe(true);
|
|
118
|
-
});
|
|
119
|
-
it('should disable strict mode when PROMPTFOO_DISABLE_AJV_STRICT_MODE is set', () => {
|
|
120
|
-
process.env.PROMPTFOO_DISABLE_AJV_STRICT_MODE = 'true';
|
|
121
|
-
const ajv = (0, assertions_1.createAjv)();
|
|
122
|
-
expect(ajv.opts.strictSchema).toBe(false);
|
|
123
|
-
});
|
|
124
|
-
it('should add formats to the Ajv instance', () => {
|
|
125
|
-
const ajv = (0, assertions_1.createAjv)();
|
|
126
|
-
expect(ajv.formats).toBeDefined();
|
|
127
|
-
expect(Object.keys(ajv.formats)).not.toHaveLength(0);
|
|
128
|
-
});
|
|
129
|
-
});
|
|
130
107
|
describe('runAssertions', () => {
|
|
131
108
|
const test = {
|
|
132
109
|
assert: [
|
|
@@ -955,278 +932,280 @@ describe('runAssertion', () => {
|
|
|
955
932
|
reason: 'JSON does not conform to the provided schema. Errors: data/latitude must be number',
|
|
956
933
|
});
|
|
957
934
|
});
|
|
958
|
-
|
|
959
|
-
|
|
960
|
-
|
|
961
|
-
|
|
962
|
-
|
|
963
|
-
|
|
964
|
-
|
|
965
|
-
|
|
966
|
-
|
|
967
|
-
|
|
968
|
-
|
|
969
|
-
|
|
970
|
-
|
|
971
|
-
|
|
972
|
-
it('should fail when the is-sql assertion fails', async () => {
|
|
973
|
-
const output = 'SELECT * FROM orders ORDERY BY order_date';
|
|
974
|
-
const result = await (0, assertions_1.runAssertion)({
|
|
975
|
-
prompt: 'Some prompt',
|
|
976
|
-
provider: new openai_1.OpenAiChatCompletionProvider('gpt-4o-mini'),
|
|
977
|
-
assertion: isSqlAssertion,
|
|
978
|
-
test: {},
|
|
979
|
-
providerResponse: { output },
|
|
980
|
-
});
|
|
981
|
-
expect(result).toMatchObject({
|
|
982
|
-
pass: false,
|
|
983
|
-
reason: 'SQL statement does not conform to the provided MySQL database syntax.',
|
|
984
|
-
});
|
|
985
|
-
});
|
|
986
|
-
it('should pass when the not-is-sql assertion passes', async () => {
|
|
987
|
-
const output = 'SELECT * FROM orders ORDERY BY order_date';
|
|
988
|
-
const result = await (0, assertions_1.runAssertion)({
|
|
989
|
-
prompt: 'Some prompt',
|
|
990
|
-
provider: new openai_1.OpenAiChatCompletionProvider('gpt-4o-mini'),
|
|
991
|
-
assertion: notIsSqlAssertion,
|
|
992
|
-
test: {},
|
|
993
|
-
providerResponse: { output },
|
|
994
|
-
});
|
|
995
|
-
expect(result).toMatchObject({
|
|
996
|
-
pass: true,
|
|
997
|
-
reason: 'Assertion passed',
|
|
998
|
-
});
|
|
999
|
-
});
|
|
1000
|
-
it('should fail when the not-is-sql assertion fails', async () => {
|
|
1001
|
-
const output = 'SELECT id, name FROM users';
|
|
1002
|
-
const result = await (0, assertions_1.runAssertion)({
|
|
1003
|
-
prompt: 'Some prompt',
|
|
1004
|
-
provider: new openai_1.OpenAiChatCompletionProvider('gpt-4o-mini'),
|
|
1005
|
-
assertion: notIsSqlAssertion,
|
|
1006
|
-
test: {},
|
|
1007
|
-
providerResponse: { output },
|
|
1008
|
-
});
|
|
1009
|
-
expect(result).toMatchObject({
|
|
1010
|
-
pass: false,
|
|
1011
|
-
reason: 'The output SQL statement is valid',
|
|
1012
|
-
});
|
|
1013
|
-
});
|
|
1014
|
-
it('should pass when the is-sql assertion passes given MySQL Database syntax', async () => {
|
|
1015
|
-
const output = 'SELECT id, name FROM users';
|
|
1016
|
-
const result = await (0, assertions_1.runAssertion)({
|
|
1017
|
-
prompt: 'Some prompt',
|
|
1018
|
-
provider: new openai_1.OpenAiChatCompletionProvider('gpt-4o-mini'),
|
|
1019
|
-
assertion: isSqlAssertionWithDatabase,
|
|
1020
|
-
test: {},
|
|
1021
|
-
providerResponse: { output },
|
|
1022
|
-
});
|
|
1023
|
-
expect(result).toMatchObject({
|
|
1024
|
-
pass: true,
|
|
1025
|
-
reason: 'Assertion passed',
|
|
1026
|
-
});
|
|
1027
|
-
});
|
|
1028
|
-
it('should fail when the is-sql assertion fails given MySQL Database syntax', async () => {
|
|
1029
|
-
const output = `SELECT first_name, last_name FROM employees WHERE first_name ILIKE 'john%'`;
|
|
1030
|
-
const result = await (0, assertions_1.runAssertion)({
|
|
1031
|
-
prompt: 'Some prompt',
|
|
1032
|
-
provider: new openai_1.OpenAiChatCompletionProvider('gpt-4o-mini'),
|
|
1033
|
-
assertion: isSqlAssertionWithDatabase,
|
|
1034
|
-
test: {},
|
|
1035
|
-
providerResponse: { output },
|
|
1036
|
-
});
|
|
1037
|
-
expect(result).toMatchObject({
|
|
1038
|
-
pass: false,
|
|
1039
|
-
reason: 'SQL statement does not conform to the provided MySQL database syntax.',
|
|
1040
|
-
});
|
|
1041
|
-
});
|
|
1042
|
-
it('should pass when the is-sql assertion passes given MySQL Database syntax and allowedTables', async () => {
|
|
1043
|
-
const output = 'SELECT * FROM departments WHERE department_id = 1';
|
|
1044
|
-
const result = await (0, assertions_1.runAssertion)({
|
|
1045
|
-
prompt: 'Some prompt',
|
|
1046
|
-
provider: new openai_1.OpenAiChatCompletionProvider('gpt-4o-mini'),
|
|
1047
|
-
assertion: isSqlAssertionWithDatabaseAndWhiteTableList,
|
|
1048
|
-
test: {},
|
|
1049
|
-
providerResponse: { output },
|
|
1050
|
-
});
|
|
1051
|
-
expect(result).toMatchObject({
|
|
1052
|
-
pass: true,
|
|
1053
|
-
reason: 'Assertion passed',
|
|
1054
|
-
});
|
|
1055
|
-
});
|
|
1056
|
-
it('should fail when the is-sql assertion fails given MySQL Database syntax and allowedTables', async () => {
|
|
1057
|
-
const output = 'UPDATE employees SET department_id = 2 WHERE employee_id = 1';
|
|
1058
|
-
const result = await (0, assertions_1.runAssertion)({
|
|
1059
|
-
prompt: 'Some prompt',
|
|
1060
|
-
provider: new openai_1.OpenAiChatCompletionProvider('gpt-4o-mini'),
|
|
1061
|
-
assertion: isSqlAssertionWithDatabaseAndWhiteTableList,
|
|
1062
|
-
test: {},
|
|
1063
|
-
providerResponse: { output },
|
|
1064
|
-
});
|
|
1065
|
-
expect(result).toMatchObject({
|
|
1066
|
-
pass: false,
|
|
1067
|
-
reason: `SQL validation failed: authority = 'update::null::employees' is required in table whiteList to execute SQL = 'UPDATE employees SET department_id = 2 WHERE employee_id = 1'.`,
|
|
1068
|
-
});
|
|
1069
|
-
});
|
|
1070
|
-
it('should pass when the is-sql assertion passes given MySQL Database syntax and allowedColumns', async () => {
|
|
1071
|
-
const output = 'SELECT name FROM t';
|
|
1072
|
-
const result = await (0, assertions_1.runAssertion)({
|
|
1073
|
-
prompt: 'Some prompt',
|
|
1074
|
-
provider: new openai_1.OpenAiChatCompletionProvider('gpt-4o-mini'),
|
|
1075
|
-
assertion: isSqlAssertionWithDatabaseAndWhiteColumnList,
|
|
1076
|
-
test: {},
|
|
1077
|
-
providerResponse: { output },
|
|
1078
|
-
});
|
|
1079
|
-
expect(result).toMatchObject({
|
|
1080
|
-
pass: true,
|
|
1081
|
-
reason: 'Assertion passed',
|
|
1082
|
-
});
|
|
1083
|
-
});
|
|
1084
|
-
it('should fail when the is-sql assertion fails given MySQL Database syntax and allowedColumns', async () => {
|
|
1085
|
-
const output = 'SELECT age FROM a WHERE id = 1';
|
|
1086
|
-
const result = await (0, assertions_1.runAssertion)({
|
|
1087
|
-
prompt: 'Some prompt',
|
|
1088
|
-
provider: new openai_1.OpenAiChatCompletionProvider('gpt-4o-mini'),
|
|
1089
|
-
assertion: isSqlAssertionWithDatabaseAndWhiteColumnList,
|
|
1090
|
-
test: {},
|
|
1091
|
-
providerResponse: { output },
|
|
1092
|
-
});
|
|
1093
|
-
expect(result).toMatchObject({
|
|
1094
|
-
pass: false,
|
|
1095
|
-
reason: `SQL validation failed: authority = 'select::null::age' is required in column whiteList to execute SQL = 'SELECT age FROM a WHERE id = 1'.`,
|
|
935
|
+
describe('SQL assertions', () => {
|
|
936
|
+
it('should pass when the is-sql assertion passes', async () => {
|
|
937
|
+
const output = 'SELECT id, name FROM users';
|
|
938
|
+
const result = await (0, assertions_1.runAssertion)({
|
|
939
|
+
prompt: 'Some prompt',
|
|
940
|
+
provider: new openai_1.OpenAiChatCompletionProvider('gpt-4o-mini'),
|
|
941
|
+
assertion: isSqlAssertion,
|
|
942
|
+
test: {},
|
|
943
|
+
providerResponse: { output },
|
|
944
|
+
});
|
|
945
|
+
expect(result).toMatchObject({
|
|
946
|
+
pass: true,
|
|
947
|
+
reason: 'Assertion passed',
|
|
948
|
+
});
|
|
1096
949
|
});
|
|
1097
|
-
|
|
1098
|
-
|
|
1099
|
-
|
|
1100
|
-
|
|
1101
|
-
|
|
1102
|
-
|
|
1103
|
-
|
|
1104
|
-
|
|
1105
|
-
|
|
950
|
+
it('should fail when the is-sql assertion fails', async () => {
|
|
951
|
+
const output = 'SELECT * FROM orders ORDERY BY order_date';
|
|
952
|
+
const result = await (0, assertions_1.runAssertion)({
|
|
953
|
+
prompt: 'Some prompt',
|
|
954
|
+
provider: new openai_1.OpenAiChatCompletionProvider('gpt-4o-mini'),
|
|
955
|
+
assertion: isSqlAssertion,
|
|
956
|
+
test: {},
|
|
957
|
+
providerResponse: { output },
|
|
958
|
+
});
|
|
959
|
+
expect(result).toMatchObject({
|
|
960
|
+
pass: false,
|
|
961
|
+
reason: 'SQL statement does not conform to the provided MySQL database syntax.',
|
|
962
|
+
});
|
|
1106
963
|
});
|
|
1107
|
-
|
|
1108
|
-
|
|
1109
|
-
|
|
964
|
+
it('should pass when the not-is-sql assertion passes', async () => {
|
|
965
|
+
const output = 'SELECT * FROM orders ORDERY BY order_date';
|
|
966
|
+
const result = await (0, assertions_1.runAssertion)({
|
|
967
|
+
prompt: 'Some prompt',
|
|
968
|
+
provider: new openai_1.OpenAiChatCompletionProvider('gpt-4o-mini'),
|
|
969
|
+
assertion: notIsSqlAssertion,
|
|
970
|
+
test: {},
|
|
971
|
+
providerResponse: { output },
|
|
972
|
+
});
|
|
973
|
+
expect(result).toMatchObject({
|
|
974
|
+
pass: true,
|
|
975
|
+
reason: 'Assertion passed',
|
|
976
|
+
});
|
|
1110
977
|
});
|
|
1111
|
-
|
|
1112
|
-
|
|
1113
|
-
|
|
1114
|
-
|
|
1115
|
-
|
|
1116
|
-
|
|
1117
|
-
|
|
1118
|
-
|
|
1119
|
-
|
|
978
|
+
it('should fail when the not-is-sql assertion fails', async () => {
|
|
979
|
+
const output = 'SELECT id, name FROM users';
|
|
980
|
+
const result = await (0, assertions_1.runAssertion)({
|
|
981
|
+
prompt: 'Some prompt',
|
|
982
|
+
provider: new openai_1.OpenAiChatCompletionProvider('gpt-4o-mini'),
|
|
983
|
+
assertion: notIsSqlAssertion,
|
|
984
|
+
test: {},
|
|
985
|
+
providerResponse: { output },
|
|
986
|
+
});
|
|
987
|
+
expect(result).toMatchObject({
|
|
988
|
+
pass: false,
|
|
989
|
+
reason: 'The output SQL statement is valid',
|
|
990
|
+
});
|
|
1120
991
|
});
|
|
1121
|
-
|
|
1122
|
-
|
|
1123
|
-
|
|
992
|
+
it('should pass when the is-sql assertion passes given MySQL Database syntax', async () => {
|
|
993
|
+
const output = 'SELECT id, name FROM users';
|
|
994
|
+
const result = await (0, assertions_1.runAssertion)({
|
|
995
|
+
prompt: 'Some prompt',
|
|
996
|
+
provider: new openai_1.OpenAiChatCompletionProvider('gpt-4o-mini'),
|
|
997
|
+
assertion: isSqlAssertionWithDatabase,
|
|
998
|
+
test: {},
|
|
999
|
+
providerResponse: { output },
|
|
1000
|
+
});
|
|
1001
|
+
expect(result).toMatchObject({
|
|
1002
|
+
pass: true,
|
|
1003
|
+
reason: 'Assertion passed',
|
|
1004
|
+
});
|
|
1124
1005
|
});
|
|
1125
|
-
|
|
1126
|
-
|
|
1127
|
-
|
|
1128
|
-
|
|
1129
|
-
|
|
1130
|
-
|
|
1131
|
-
|
|
1132
|
-
|
|
1133
|
-
|
|
1006
|
+
it('should fail when the is-sql assertion fails given MySQL Database syntax', async () => {
|
|
1007
|
+
const output = `SELECT first_name, last_name FROM employees WHERE first_name ILIKE 'john%'`;
|
|
1008
|
+
const result = await (0, assertions_1.runAssertion)({
|
|
1009
|
+
prompt: 'Some prompt',
|
|
1010
|
+
provider: new openai_1.OpenAiChatCompletionProvider('gpt-4o-mini'),
|
|
1011
|
+
assertion: isSqlAssertionWithDatabase,
|
|
1012
|
+
test: {},
|
|
1013
|
+
providerResponse: { output },
|
|
1014
|
+
});
|
|
1015
|
+
expect(result).toMatchObject({
|
|
1016
|
+
pass: false,
|
|
1017
|
+
reason: 'SQL statement does not conform to the provided MySQL database syntax.',
|
|
1018
|
+
});
|
|
1134
1019
|
});
|
|
1135
|
-
|
|
1136
|
-
|
|
1137
|
-
|
|
1020
|
+
it('should pass when the is-sql assertion passes given MySQL Database syntax and allowedTables', async () => {
|
|
1021
|
+
const output = 'SELECT * FROM departments WHERE department_id = 1';
|
|
1022
|
+
const result = await (0, assertions_1.runAssertion)({
|
|
1023
|
+
prompt: 'Some prompt',
|
|
1024
|
+
provider: new openai_1.OpenAiChatCompletionProvider('gpt-4o-mini'),
|
|
1025
|
+
assertion: isSqlAssertionWithDatabaseAndWhiteTableList,
|
|
1026
|
+
test: {},
|
|
1027
|
+
providerResponse: { output },
|
|
1028
|
+
});
|
|
1029
|
+
expect(result).toMatchObject({
|
|
1030
|
+
pass: true,
|
|
1031
|
+
reason: 'Assertion passed',
|
|
1032
|
+
});
|
|
1138
1033
|
});
|
|
1139
|
-
|
|
1140
|
-
|
|
1141
|
-
|
|
1142
|
-
|
|
1143
|
-
|
|
1144
|
-
|
|
1145
|
-
|
|
1146
|
-
|
|
1147
|
-
|
|
1034
|
+
it('should fail when the is-sql assertion fails given MySQL Database syntax and allowedTables', async () => {
|
|
1035
|
+
const output = 'UPDATE employees SET department_id = 2 WHERE employee_id = 1';
|
|
1036
|
+
const result = await (0, assertions_1.runAssertion)({
|
|
1037
|
+
prompt: 'Some prompt',
|
|
1038
|
+
provider: new openai_1.OpenAiChatCompletionProvider('gpt-4o-mini'),
|
|
1039
|
+
assertion: isSqlAssertionWithDatabaseAndWhiteTableList,
|
|
1040
|
+
test: {},
|
|
1041
|
+
providerResponse: { output },
|
|
1042
|
+
});
|
|
1043
|
+
expect(result).toMatchObject({
|
|
1044
|
+
pass: false,
|
|
1045
|
+
reason: `SQL validation failed: authority = 'update::null::employees' is required in table whiteList to execute SQL = 'UPDATE employees SET department_id = 2 WHERE employee_id = 1'.`,
|
|
1046
|
+
});
|
|
1148
1047
|
});
|
|
1149
|
-
|
|
1150
|
-
|
|
1151
|
-
|
|
1048
|
+
it('should pass when the is-sql assertion passes given MySQL Database syntax and allowedColumns', async () => {
|
|
1049
|
+
const output = 'SELECT name FROM t';
|
|
1050
|
+
const result = await (0, assertions_1.runAssertion)({
|
|
1051
|
+
prompt: 'Some prompt',
|
|
1052
|
+
provider: new openai_1.OpenAiChatCompletionProvider('gpt-4o-mini'),
|
|
1053
|
+
assertion: isSqlAssertionWithDatabaseAndWhiteColumnList,
|
|
1054
|
+
test: {},
|
|
1055
|
+
providerResponse: { output },
|
|
1056
|
+
});
|
|
1057
|
+
expect(result).toMatchObject({
|
|
1058
|
+
pass: true,
|
|
1059
|
+
reason: 'Assertion passed',
|
|
1060
|
+
});
|
|
1152
1061
|
});
|
|
1153
|
-
|
|
1154
|
-
|
|
1155
|
-
|
|
1156
|
-
|
|
1157
|
-
|
|
1158
|
-
|
|
1159
|
-
|
|
1160
|
-
|
|
1161
|
-
}
|
|
1162
|
-
|
|
1163
|
-
|
|
1062
|
+
it('should fail when the is-sql assertion fails given MySQL Database syntax and allowedColumns', async () => {
|
|
1063
|
+
const output = 'SELECT age FROM a WHERE id = 1';
|
|
1064
|
+
const result = await (0, assertions_1.runAssertion)({
|
|
1065
|
+
prompt: 'Some prompt',
|
|
1066
|
+
provider: new openai_1.OpenAiChatCompletionProvider('gpt-4o-mini'),
|
|
1067
|
+
assertion: isSqlAssertionWithDatabaseAndWhiteColumnList,
|
|
1068
|
+
test: {},
|
|
1069
|
+
providerResponse: { output },
|
|
1070
|
+
});
|
|
1071
|
+
expect(result).toMatchObject({
|
|
1072
|
+
pass: false,
|
|
1073
|
+
reason: `SQL validation failed: authority = 'select::null::age' is required in column whiteList to execute SQL = 'SELECT age FROM a WHERE id = 1'.`,
|
|
1074
|
+
});
|
|
1164
1075
|
});
|
|
1165
|
-
|
|
1166
|
-
|
|
1167
|
-
|
|
1076
|
+
it('should pass when the is-sql assertion passes given MySQL Database syntax, allowedTables, and allowedColumns', async () => {
|
|
1077
|
+
const output = 'SELECT name FROM departments';
|
|
1078
|
+
const result = await (0, assertions_1.runAssertion)({
|
|
1079
|
+
prompt: 'Some prompt',
|
|
1080
|
+
provider: new openai_1.OpenAiChatCompletionProvider('gpt-4o-mini'),
|
|
1081
|
+
assertion: isSqlAssertionWithDatabaseAndBothList,
|
|
1082
|
+
test: {},
|
|
1083
|
+
providerResponse: { output },
|
|
1084
|
+
});
|
|
1085
|
+
expect(result).toMatchObject({
|
|
1086
|
+
pass: true,
|
|
1087
|
+
reason: 'Assertion passed',
|
|
1088
|
+
});
|
|
1168
1089
|
});
|
|
1169
|
-
|
|
1170
|
-
|
|
1171
|
-
|
|
1172
|
-
|
|
1173
|
-
|
|
1174
|
-
|
|
1175
|
-
|
|
1176
|
-
|
|
1177
|
-
}
|
|
1178
|
-
|
|
1179
|
-
|
|
1090
|
+
it('should fail when the is-sql assertion fails given MySQL Database syntax, allowedTables, and allowedColumns', async () => {
|
|
1091
|
+
const output = `INSERT INTO departments (name) VALUES ('HR')`;
|
|
1092
|
+
const result = await (0, assertions_1.runAssertion)({
|
|
1093
|
+
prompt: 'Some prompt',
|
|
1094
|
+
provider: new openai_1.OpenAiChatCompletionProvider('gpt-4o-mini'),
|
|
1095
|
+
assertion: isSqlAssertionWithDatabaseAndBothList,
|
|
1096
|
+
test: {},
|
|
1097
|
+
providerResponse: { output },
|
|
1098
|
+
});
|
|
1099
|
+
expect(result).toMatchObject({
|
|
1100
|
+
pass: false,
|
|
1101
|
+
reason: `SQL validation failed: authority = 'insert::departments::name' is required in column whiteList to execute SQL = 'INSERT INTO departments (name) VALUES ('HR')'.`,
|
|
1102
|
+
});
|
|
1180
1103
|
});
|
|
1181
|
-
|
|
1182
|
-
|
|
1183
|
-
|
|
1104
|
+
it('should fail when the is-sql assertion fails due to missing table authority for MySQL Database syntax', async () => {
|
|
1105
|
+
const output = 'UPDATE a SET id = 1';
|
|
1106
|
+
const result = await (0, assertions_1.runAssertion)({
|
|
1107
|
+
prompt: 'Some prompt',
|
|
1108
|
+
provider: new openai_1.OpenAiChatCompletionProvider('gpt-4o-mini'),
|
|
1109
|
+
assertion: isSqlAssertionWithDatabaseAndBothList,
|
|
1110
|
+
test: {},
|
|
1111
|
+
providerResponse: { output },
|
|
1112
|
+
});
|
|
1113
|
+
expect(result).toMatchObject({
|
|
1114
|
+
pass: false,
|
|
1115
|
+
reason: `SQL validation failed: authority = 'update::null::a' is required in table whiteList to execute SQL = 'UPDATE a SET id = 1'.`,
|
|
1116
|
+
});
|
|
1184
1117
|
});
|
|
1185
|
-
|
|
1186
|
-
|
|
1187
|
-
|
|
1188
|
-
|
|
1189
|
-
|
|
1190
|
-
|
|
1191
|
-
|
|
1192
|
-
|
|
1193
|
-
}
|
|
1194
|
-
|
|
1195
|
-
|
|
1118
|
+
it('should fail when the is-sql assertion fails due to missing authorities for DELETE statement in MySQL Database syntax', async () => {
|
|
1119
|
+
const output = `DELETE FROM employees;`;
|
|
1120
|
+
const result = await (0, assertions_1.runAssertion)({
|
|
1121
|
+
prompt: 'Some prompt',
|
|
1122
|
+
provider: new openai_1.OpenAiChatCompletionProvider('gpt-4o-mini'),
|
|
1123
|
+
assertion: isSqlAssertionWithDatabaseAndBothList,
|
|
1124
|
+
test: {},
|
|
1125
|
+
providerResponse: { output },
|
|
1126
|
+
});
|
|
1127
|
+
expect(result).toMatchObject({
|
|
1128
|
+
pass: false,
|
|
1129
|
+
reason: `SQL validation failed: authority = 'delete::null::employees' is required in table whiteList to execute SQL = 'DELETE FROM employees;'. SQL validation failed: authority = 'delete::employees::(.*)' is required in column whiteList to execute SQL = 'DELETE FROM employees;'.`,
|
|
1130
|
+
});
|
|
1196
1131
|
});
|
|
1197
|
-
|
|
1198
|
-
|
|
1199
|
-
|
|
1132
|
+
it('should pass when the contains-sql assertion passes', async () => {
|
|
1133
|
+
const output = 'wassup\n```\nSELECT id, name FROM users\n```\nyolo';
|
|
1134
|
+
const result = await (0, assertions_1.runAssertion)({
|
|
1135
|
+
prompt: 'Some prompt',
|
|
1136
|
+
provider: new openai_1.OpenAiChatCompletionProvider('gpt-4o-mini'),
|
|
1137
|
+
assertion: {
|
|
1138
|
+
type: 'contains-sql',
|
|
1139
|
+
},
|
|
1140
|
+
test: {},
|
|
1141
|
+
providerResponse: { output },
|
|
1142
|
+
});
|
|
1143
|
+
expect(result).toMatchObject({
|
|
1144
|
+
pass: true,
|
|
1145
|
+
reason: 'Assertion passed',
|
|
1146
|
+
});
|
|
1200
1147
|
});
|
|
1201
|
-
|
|
1202
|
-
|
|
1203
|
-
|
|
1204
|
-
|
|
1205
|
-
|
|
1206
|
-
|
|
1207
|
-
|
|
1208
|
-
|
|
1209
|
-
|
|
1210
|
-
|
|
1211
|
-
|
|
1148
|
+
it('should pass when the contains-sql assertion sees `sql` in code block', async () => {
|
|
1149
|
+
const output = 'wassup\n```sql\nSELECT id, name FROM users\n```\nyolo';
|
|
1150
|
+
const result = await (0, assertions_1.runAssertion)({
|
|
1151
|
+
prompt: 'Some prompt',
|
|
1152
|
+
provider: new openai_1.OpenAiChatCompletionProvider('gpt-4o-mini'),
|
|
1153
|
+
assertion: {
|
|
1154
|
+
type: 'contains-sql',
|
|
1155
|
+
},
|
|
1156
|
+
test: {},
|
|
1157
|
+
providerResponse: { output },
|
|
1158
|
+
});
|
|
1159
|
+
expect(result).toMatchObject({
|
|
1160
|
+
pass: true,
|
|
1161
|
+
reason: 'Assertion passed',
|
|
1162
|
+
});
|
|
1212
1163
|
});
|
|
1213
|
-
|
|
1214
|
-
|
|
1164
|
+
it('should pass when the contains-sql assertion sees sql without code block', async () => {
|
|
1165
|
+
const output = 'SELECT id, name FROM users';
|
|
1166
|
+
const result = await (0, assertions_1.runAssertion)({
|
|
1167
|
+
prompt: 'Some prompt',
|
|
1168
|
+
provider: new openai_1.OpenAiChatCompletionProvider('gpt-4o-mini'),
|
|
1169
|
+
assertion: {
|
|
1170
|
+
type: 'contains-sql',
|
|
1171
|
+
},
|
|
1172
|
+
test: {},
|
|
1173
|
+
providerResponse: { output },
|
|
1174
|
+
});
|
|
1175
|
+
expect(result).toMatchObject({
|
|
1176
|
+
pass: true,
|
|
1177
|
+
reason: 'Assertion passed',
|
|
1178
|
+
});
|
|
1215
1179
|
});
|
|
1216
|
-
|
|
1217
|
-
|
|
1218
|
-
|
|
1219
|
-
|
|
1220
|
-
|
|
1221
|
-
|
|
1222
|
-
|
|
1223
|
-
|
|
1224
|
-
|
|
1225
|
-
|
|
1226
|
-
|
|
1180
|
+
it('should fail when the contains-sql does not contain code block', async () => {
|
|
1181
|
+
const output = 'nothin';
|
|
1182
|
+
const result = await (0, assertions_1.runAssertion)({
|
|
1183
|
+
prompt: 'Some prompt',
|
|
1184
|
+
provider: new openai_1.OpenAiChatCompletionProvider('gpt-4o-mini'),
|
|
1185
|
+
assertion: {
|
|
1186
|
+
type: 'contains-sql',
|
|
1187
|
+
},
|
|
1188
|
+
test: {},
|
|
1189
|
+
providerResponse: { output },
|
|
1190
|
+
});
|
|
1191
|
+
expect(result).toMatchObject({
|
|
1192
|
+
pass: false,
|
|
1193
|
+
});
|
|
1227
1194
|
});
|
|
1228
|
-
|
|
1229
|
-
|
|
1195
|
+
it('should fail when the contains-sql does not contain sql in code block', async () => {
|
|
1196
|
+
const output = '```python\nprint("Hello, World!")\n```';
|
|
1197
|
+
const result = await (0, assertions_1.runAssertion)({
|
|
1198
|
+
prompt: 'Some prompt',
|
|
1199
|
+
provider: new openai_1.OpenAiChatCompletionProvider('gpt-4o-mini'),
|
|
1200
|
+
assertion: {
|
|
1201
|
+
type: 'contains-sql',
|
|
1202
|
+
},
|
|
1203
|
+
test: {},
|
|
1204
|
+
providerResponse: { output },
|
|
1205
|
+
});
|
|
1206
|
+
expect(result).toMatchObject({
|
|
1207
|
+
pass: false,
|
|
1208
|
+
});
|
|
1230
1209
|
});
|
|
1231
1210
|
});
|
|
1232
1211
|
it('should pass when the contains-json assertion passes', async () => {
|
|
@@ -3468,37 +3447,37 @@ describe('runAssertion', () => {
|
|
|
3468
3447
|
});
|
|
3469
3448
|
describe('validateXml', () => {
|
|
3470
3449
|
it('should validate a simple valid XML string', () => {
|
|
3471
|
-
expect((0,
|
|
3450
|
+
expect((0, xml_1.validateXml)('<root><child>Content</child></root>')).toEqual({
|
|
3472
3451
|
isValid: true,
|
|
3473
3452
|
reason: 'XML is valid and contains all required elements',
|
|
3474
3453
|
});
|
|
3475
3454
|
});
|
|
3476
3455
|
it('should invalidate a malformed XML string', () => {
|
|
3477
|
-
expect((0,
|
|
3456
|
+
expect((0, xml_1.validateXml)('<root><child>Content</child></root')).toEqual({
|
|
3478
3457
|
isValid: false,
|
|
3479
3458
|
reason: expect.stringContaining('XML parsing failed'),
|
|
3480
3459
|
});
|
|
3481
3460
|
});
|
|
3482
3461
|
it('should validate XML with attributes', () => {
|
|
3483
|
-
expect((0,
|
|
3462
|
+
expect((0, xml_1.validateXml)('<root><child id="1">Content</child></root>')).toEqual({
|
|
3484
3463
|
isValid: true,
|
|
3485
3464
|
reason: 'XML is valid and contains all required elements',
|
|
3486
3465
|
});
|
|
3487
3466
|
});
|
|
3488
3467
|
it('should validate XML with namespaces', () => {
|
|
3489
|
-
expect((0,
|
|
3468
|
+
expect((0, xml_1.validateXml)('<root xmlns:ns="http://example.com"><ns:child>Content</ns:child></root>')).toEqual({
|
|
3490
3469
|
isValid: true,
|
|
3491
3470
|
reason: 'XML is valid and contains all required elements',
|
|
3492
3471
|
});
|
|
3493
3472
|
});
|
|
3494
3473
|
it('should validate when all required elements are present', () => {
|
|
3495
|
-
expect((0,
|
|
3474
|
+
expect((0, xml_1.validateXml)('<analysis><classification>T-shirt</classification><color>Red</color></analysis>', ['analysis.classification', 'analysis.color'])).toEqual({
|
|
3496
3475
|
isValid: true,
|
|
3497
3476
|
reason: 'XML is valid and contains all required elements',
|
|
3498
3477
|
});
|
|
3499
3478
|
});
|
|
3500
3479
|
it('should invalidate when a required element is missing', () => {
|
|
3501
|
-
expect((0,
|
|
3480
|
+
expect((0, xml_1.validateXml)('<analysis><classification>T-shirt</classification></analysis>', [
|
|
3502
3481
|
'analysis.classification',
|
|
3503
3482
|
'analysis.color',
|
|
3504
3483
|
])).toEqual({
|
|
@@ -3507,7 +3486,7 @@ describe('validateXml', () => {
|
|
|
3507
3486
|
});
|
|
3508
3487
|
});
|
|
3509
3488
|
it('should validate nested elements correctly', () => {
|
|
3510
|
-
expect((0,
|
|
3489
|
+
expect((0, xml_1.validateXml)('<root><parent><child><grandchild>Content</grandchild></child></parent></root>', [
|
|
3511
3490
|
'root.parent.child.grandchild',
|
|
3512
3491
|
])).toEqual({
|
|
3513
3492
|
isValid: true,
|
|
@@ -3515,7 +3494,7 @@ describe('validateXml', () => {
|
|
|
3515
3494
|
});
|
|
3516
3495
|
});
|
|
3517
3496
|
it('should invalidate when a nested required element is missing', () => {
|
|
3518
|
-
expect((0,
|
|
3497
|
+
expect((0, xml_1.validateXml)('<root><parent><child></child></parent></root>', [
|
|
3519
3498
|
'root.parent.child.grandchild',
|
|
3520
3499
|
])).toEqual({
|
|
3521
3500
|
isValid: false,
|
|
@@ -3523,7 +3502,7 @@ describe('validateXml', () => {
|
|
|
3523
3502
|
});
|
|
3524
3503
|
});
|
|
3525
3504
|
it('should handle empty elements correctly', () => {
|
|
3526
|
-
expect((0,
|
|
3505
|
+
expect((0, xml_1.validateXml)('<root><emptyChild></emptyChild><nonEmptyChild>Content</nonEmptyChild></root>', [
|
|
3527
3506
|
'root.emptyChild',
|
|
3528
3507
|
'root.nonEmptyChild',
|
|
3529
3508
|
])).toEqual({
|
|
@@ -3532,13 +3511,13 @@ describe('validateXml', () => {
|
|
|
3532
3511
|
});
|
|
3533
3512
|
});
|
|
3534
3513
|
it('should validate XML with multiple siblings', () => {
|
|
3535
|
-
expect((0,
|
|
3514
|
+
expect((0, xml_1.validateXml)('<root><child>Content1</child><child>Content2</child></root>', ['root.child'])).toEqual({
|
|
3536
3515
|
isValid: true,
|
|
3537
3516
|
reason: 'XML is valid and contains all required elements',
|
|
3538
3517
|
});
|
|
3539
3518
|
});
|
|
3540
3519
|
it('should handle XML with CDATA sections', () => {
|
|
3541
|
-
expect((0,
|
|
3520
|
+
expect((0, xml_1.validateXml)('<root><child><![CDATA[<p>This is CDATA content</p>]]></child></root>', [
|
|
3542
3521
|
'root.child',
|
|
3543
3522
|
])).toEqual({
|
|
3544
3523
|
isValid: true,
|
|
@@ -3547,13 +3526,13 @@ describe('validateXml', () => {
|
|
|
3547
3526
|
});
|
|
3548
3527
|
it('should validate XML with processing instructions', () => {
|
|
3549
3528
|
const xml = '<?xml version="1.0" encoding="UTF-8"?><?xml-stylesheet type="text/xsl" href="style.xsl"?><root><child>Content</child></root>';
|
|
3550
|
-
expect((0,
|
|
3529
|
+
expect((0, xml_1.validateXml)(xml, ['root.child'])).toEqual({
|
|
3551
3530
|
isValid: true,
|
|
3552
3531
|
reason: 'XML is valid and contains all required elements',
|
|
3553
3532
|
});
|
|
3554
3533
|
});
|
|
3555
3534
|
it('should handle XML with comments', () => {
|
|
3556
|
-
expect((0,
|
|
3535
|
+
expect((0, xml_1.validateXml)('<root><!-- This is a comment --><child>Content</child></root>', ['root.child'])).toEqual({
|
|
3557
3536
|
isValid: true,
|
|
3558
3537
|
reason: 'XML is valid and contains all required elements',
|
|
3559
3538
|
});
|
|
@@ -3569,7 +3548,7 @@ describe('validateXml', () => {
|
|
|
3569
3548
|
<reasoning>The image clearly shows a short-sleeved garment with a round neckline, which is characteristic of a T-shirt. The large circular graphic on the front is distinctive and appears to be a stylized smiley face or emoji design, which is popular in contemporary casual fashion. The stark contrast between the white fabric and black print is very clear, leaving little room for misinterpretation. The style is unmistakably modern and aligned with current trends in graphic tees. My confidence is high (9) because all elements of the image are clear and consistent with a typical graphic T-shirt design.</reasoning>
|
|
3570
3549
|
</analysis>
|
|
3571
3550
|
`;
|
|
3572
|
-
expect((0,
|
|
3551
|
+
expect((0, xml_1.validateXml)(xml, [
|
|
3573
3552
|
'analysis.classification',
|
|
3574
3553
|
'analysis.color',
|
|
3575
3554
|
'analysis.features',
|
|
@@ -3585,31 +3564,31 @@ describe('validateXml', () => {
|
|
|
3585
3564
|
describe('containsXml', () => {
|
|
3586
3565
|
it('should return true when valid XML is present', () => {
|
|
3587
3566
|
const input = 'Some text <root><child>Content</child></root> more text';
|
|
3588
|
-
const result = (0,
|
|
3567
|
+
const result = (0, xml_1.containsXml)(input);
|
|
3589
3568
|
expect(result.isValid).toBe(true);
|
|
3590
3569
|
});
|
|
3591
3570
|
it('should return false when no XML is present', () => {
|
|
3592
3571
|
const input = 'This is just plain text';
|
|
3593
|
-
expect((0,
|
|
3572
|
+
expect((0, xml_1.containsXml)(input)).toEqual({
|
|
3594
3573
|
isValid: false,
|
|
3595
3574
|
reason: 'No XML content found in the output',
|
|
3596
3575
|
});
|
|
3597
3576
|
});
|
|
3598
3577
|
it('should validate required elements', () => {
|
|
3599
3578
|
const input = 'Text <root><child>Content</child></root> more';
|
|
3600
|
-
const result = (0,
|
|
3579
|
+
const result = (0, xml_1.containsXml)(input, ['root.child']);
|
|
3601
3580
|
expect(result.isValid).toBe(true);
|
|
3602
3581
|
});
|
|
3603
3582
|
it('should return false when required elements are missing', () => {
|
|
3604
3583
|
const input = 'Text <root><child>Content</child></root> more';
|
|
3605
|
-
expect((0,
|
|
3584
|
+
expect((0, xml_1.containsXml)(input, ['root.missing'])).toEqual({
|
|
3606
3585
|
isValid: false,
|
|
3607
3586
|
reason: 'No valid XML content found matching the requirements',
|
|
3608
3587
|
});
|
|
3609
3588
|
});
|
|
3610
3589
|
it('should handle multiple XML fragments', () => {
|
|
3611
3590
|
const input = '<root1>Content</root1> text <root2><child>More</child></root2>';
|
|
3612
|
-
const result = (0,
|
|
3591
|
+
const result = (0, xml_1.containsXml)(input, ['root2.child']);
|
|
3613
3592
|
expect(result.isValid).toBe(true);
|
|
3614
3593
|
});
|
|
3615
3594
|
});
|