diff --git a/package-lock.json b/package-lock.json
index 0baea115..0fd6b84b 100644
--- a/package-lock.json
+++ b/package-lock.json
@@ -10,7 +10,7 @@
"hasInstallScript": true,
"license": "Apache-2.0",
"dependencies": {
- "@salesforce/agents": "^1.2.0",
+ "@salesforce/agents": "^1.6.4",
"@salesforce/core": "^8.28.3",
"@salesforce/kit": "^3.2.6",
"@salesforce/types": "^1.7.1",
@@ -2255,27 +2255,27 @@
}
},
"node_modules/@salesforce/agents": {
- "version": "1.2.0",
- "resolved": "https://registry.npmjs.org/@salesforce/agents/-/agents-1.2.0.tgz",
- "integrity": "sha512-gyF1xzJcEp3MuS8Apf1eUGUvy41zq7HQqKPEhDIU6aUiowoewW/RI9LcPB0K7LPrGCIiARq4TYKlxf452HASqA==",
+ "version": "1.6.4",
+ "resolved": "https://registry.npmjs.org/@salesforce/agents/-/agents-1.6.4.tgz",
+ "integrity": "sha512-+E9Ljtr+LiDHEfgRnqpFV4crLsfd07bTmU4Gi6hVLQmLG4T/cBM15nNnkfsMMhMs5t50cY7hpAP/PWkutC8eQw==",
"license": "Apache-2.0",
"dependencies": {
- "@salesforce/core": "^8.28.3",
+ "@salesforce/core": "^8.29.1",
"@salesforce/kit": "^3.2.6",
- "@salesforce/source-deploy-retrieve": "^12.32.7",
+ "@salesforce/source-deploy-retrieve": "^12.35.8",
"@salesforce/types": "^1.7.1",
- "fast-xml-parser": "^5.6.0",
+ "fast-xml-parser": "^5.7.3",
"nock": "^13.5.6",
- "yaml": "^2.8.3"
+ "yaml": "^2.8.4"
},
"engines": {
"node": ">=18.0.0"
}
},
"node_modules/@salesforce/core": {
- "version": "8.28.3",
- "resolved": "https://registry.npmjs.org/@salesforce/core/-/core-8.28.3.tgz",
- "integrity": "sha512-DDAeHVwDO8wUlqEGwfp8Vuu7Vp7K+hpubKu6baWkHAXiO1u7ZbQkvwCbpPz9JiYEXVUBvP11JtBQ7zOUIPShlQ==",
+ "version": "8.29.1",
+ "resolved": "https://registry.npmjs.org/@salesforce/core/-/core-8.29.1.tgz",
+ "integrity": "sha512-Pdo9yjKU6Lgm3CJOVJPTM4PzUHhTVMX43K5XmClsBEt75fs8mHNFALniHZwnZbVf+TSMfGsUygYAyTX6ShnNQA==",
"license": "BSD-3-Clause",
"dependencies": {
"@jsforce/jsforce-node": "^3.10.13",
@@ -2312,17 +2312,17 @@
}
},
"node_modules/@salesforce/source-deploy-retrieve": {
- "version": "12.32.9",
- "resolved": "https://registry.npmjs.org/@salesforce/source-deploy-retrieve/-/source-deploy-retrieve-12.32.9.tgz",
- "integrity": "sha512-DRIiyt9dP+QzBs+Lonw7UeB+LvtHmEyrVbYibXvRtKkTAj/zuBGjvKHm06/ql1TymXFotwE54j6xLi1rxS5Zfw==",
+ "version": "12.35.9",
+ "resolved": "https://registry.npmjs.org/@salesforce/source-deploy-retrieve/-/source-deploy-retrieve-12.35.9.tgz",
+ "integrity": "sha512-Qud+1lHS0u+LM/AAHPN9Y/6W6hBZ8nvw6/TxJRzn/BuvRSz74YBwvmVhmn5pvpZdNrYmKRMPxsK47l2VmazSsw==",
"license": "Apache-2.0",
"dependencies": {
- "@salesforce/core": "^8.27.1",
+ "@salesforce/core": "^8.29.0",
"@salesforce/kit": "^3.2.4",
"@salesforce/ts-types": "^2.0.12",
"@salesforce/types": "^1.6.0",
"fast-levenshtein": "^3.0.0",
- "fast-xml-parser": "^5.5.11",
+ "fast-xml-parser": "^5.7.3",
"got": "^11.8.6",
"graceful-fs": "^4.2.11",
"ignore": "^5.3.2",
@@ -4071,9 +4071,9 @@
}
},
"node_modules/basic-ftp": {
- "version": "5.3.0",
- "resolved": "https://registry.npmjs.org/basic-ftp/-/basic-ftp-5.3.0.tgz",
- "integrity": "sha512-5K9eNNn7ywHPsYnFwjKgYH8Hf8B5emh7JKcPaVjjrMJFQQwGpwowEnZNEtHs7DfR7hCZsmaK3VA4HUK0YarT+w==",
+ "version": "5.3.1",
+ "resolved": "https://registry.npmjs.org/basic-ftp/-/basic-ftp-5.3.1.tgz",
+ "integrity": "sha512-bopVNp6ugyA150DDuZfPFdt1KZ5a94ZDiwX4hMgZDzF+GttD80lEy8kj98kbyhLXnPvhtIo93mdnLIjpCAeeOw==",
"license": "MIT",
"engines": {
"node": ">=10.0.0"
@@ -5633,9 +5633,9 @@
"license": "BSD-3-Clause"
},
"node_modules/fast-xml-builder": {
- "version": "1.1.5",
- "resolved": "https://registry.npmjs.org/fast-xml-builder/-/fast-xml-builder-1.1.5.tgz",
- "integrity": "sha512-4TJn/8FKLeslLAH3dnohXqE3QSoxkhvaMzepOIZytwJXZO69Bfz0HBdDHzOTOon6G59Zrk6VQ2bEiv1t61rfkA==",
+ "version": "1.2.0",
+ "resolved": "https://registry.npmjs.org/fast-xml-builder/-/fast-xml-builder-1.2.0.tgz",
+ "integrity": "sha512-00aAWieqff+ZJhsXA4g1g7M8k+7AYoMUUHF+/zFb5U6Uv/P0Vl4QZo84/IcufzYalLuEj9928bXN9PbbFzMF0Q==",
"funding": [
{
"type": "github",
@@ -5644,13 +5644,14 @@
],
"license": "MIT",
"dependencies": {
- "path-expression-matcher": "^1.1.3"
+ "path-expression-matcher": "^1.5.0",
+ "xml-naming": "^0.1.0"
}
},
"node_modules/fast-xml-parser": {
- "version": "5.7.1",
- "resolved": "https://registry.npmjs.org/fast-xml-parser/-/fast-xml-parser-5.7.1.tgz",
- "integrity": "sha512-8Cc3f8GUGUULg34pBch/KGyPLglS+OFs05deyOlY7fL2MTagYPKrVQNmR1fLF/yJ9PH5ZSTd3YDF6pnmeZU+zA==",
+ "version": "5.7.3",
+ "resolved": "https://registry.npmjs.org/fast-xml-parser/-/fast-xml-parser-5.7.3.tgz",
+ "integrity": "sha512-C0AaNuC+mscy6vrAQKAc/rMq+zAPHodfHGZu4sGVehvAQt/JLG1O5zEcYcXSY5zSqr4YVgxsB+pHXTq0i7eDlg==",
"funding": [
{
"type": "github",
@@ -5660,7 +5661,7 @@
"license": "MIT",
"dependencies": {
"@nodable/entities": "^2.1.0",
- "fast-xml-builder": "^1.1.5",
+ "fast-xml-builder": "^1.1.7",
"path-expression-matcher": "^1.5.0",
"strnum": "^2.2.3"
},
@@ -6532,9 +6533,9 @@
"optional": true
},
"node_modules/ip-address": {
- "version": "10.1.0",
- "resolved": "https://registry.npmjs.org/ip-address/-/ip-address-10.1.0.tgz",
- "integrity": "sha512-XXADHxXmvT9+CRxhXg56LJovE+bmWnEWB78LB83VZTprKTmaC5QfruXocxzTZ2Kl0DNwKuBdlIhjL8LeY8Sf8Q==",
+ "version": "10.2.0",
+ "resolved": "https://registry.npmjs.org/ip-address/-/ip-address-10.2.0.tgz",
+ "integrity": "sha512-/+S6j4E9AHvW9SWMSEY9Xfy66O5PWvVEJ08O0y5JGyEKQpojb0K0GKpz/v5HJ/G0vi3D2sjGK78119oXZeE0qA==",
"license": "MIT",
"engines": {
"node": ">= 12"
@@ -10797,12 +10798,12 @@
}
},
"node_modules/socks": {
- "version": "2.8.7",
- "resolved": "https://registry.npmjs.org/socks/-/socks-2.8.7.tgz",
- "integrity": "sha512-HLpt+uLy/pxB+bum/9DzAgiKS8CX1EvbWxI4zlmgGCExImLdiad2iCwXT5Z4c9c3Eq8rP2318mPW2c+QbtjK8A==",
+ "version": "2.8.9",
+ "resolved": "https://registry.npmjs.org/socks/-/socks-2.8.9.tgz",
+ "integrity": "sha512-LJhUYUvItdQ0LkJTmPeaEObWXAqFyfmP85x0tch/ez9cahmhlBBLbIqDFnvBnUJGagb0JbIQrkBs1wJ+yRYpEw==",
"license": "MIT",
"dependencies": {
- "ip-address": "^10.0.1",
+ "ip-address": "^10.1.1",
"smart-buffer": "^4.2.0"
},
"engines": {
@@ -12137,6 +12138,21 @@
"node": ">=18"
}
},
+ "node_modules/xml-naming": {
+ "version": "0.1.0",
+ "resolved": "https://registry.npmjs.org/xml-naming/-/xml-naming-0.1.0.tgz",
+ "integrity": "sha512-k8KO9hrMyNk6tUWqUfkTEZbezRRpONVOzUTnc97VnCvyj6Tf9lyUR9EDAIeiVLv56jsMcoXEwjW8Kv5yPY52lw==",
+ "funding": [
+ {
+ "type": "github",
+ "url": "https://github.com/sponsors/NaturalIntelligence"
+ }
+ ],
+ "license": "MIT",
+ "engines": {
+ "node": ">=16.0.0"
+ }
+ },
"node_modules/xml2js": {
"version": "0.6.2",
"resolved": "https://registry.npmjs.org/xml2js/-/xml2js-0.6.2.tgz",
@@ -12190,9 +12206,9 @@
"license": "ISC"
},
"node_modules/yaml": {
- "version": "2.8.3",
- "resolved": "https://registry.npmjs.org/yaml/-/yaml-2.8.3.tgz",
- "integrity": "sha512-AvbaCLOO2Otw/lW5bmh9d/WEdcDFdQp2Z2ZUH3pX9U2ihyUY0nvLv7J6TrWowklRGPYbB/IuIMfYgxaCPg5Bpg==",
+ "version": "2.8.4",
+ "resolved": "https://registry.npmjs.org/yaml/-/yaml-2.8.4.tgz",
+ "integrity": "sha512-ml/JPOj9fOQK8RNnWojA67GbZ0ApXAUlN2UQclwv2eVgTgn7O9gg9o7paZWKMp4g0H3nTLtS9LVzhkpOFIKzog==",
"license": "ISC",
"bin": {
"yaml": "bin.mjs"
diff --git a/package.json b/package.json
index 553c2639..663c4ea0 100644
--- a/package.json
+++ b/package.json
@@ -20,7 +20,7 @@
],
"main": "lib/src/extension.js",
"dependencies": {
- "@salesforce/agents": "^1.2.0",
+ "@salesforce/agents": "^1.6.4",
"@salesforce/core": "^8.28.3",
"@salesforce/kit": "^3.2.6",
"@salesforce/types": "^1.7.1",
diff --git a/src/types/MetadataDefinitions.ts b/src/types/MetadataDefinitions.ts
index bc4d37a1..7c0cb3e5 100644
--- a/src/types/MetadataDefinitions.ts
+++ b/src/types/MetadataDefinitions.ts
@@ -22,3 +22,21 @@ export type AgentTestCase = {
{ name: 'expectedOutcome'; expectedValue: string }
];
};
+
+// until @salesforce/types has AiTestingDefinition
+export type AgentforceStudioTestCaseMetadata = {
+ number: string;
+ inputs: { utterance: string };
+};
+
+// until @salesforce/types has AiTestingDefinition
+export type AiTestingDefinition = {
+ AiTestingDefinition: {
+ description: string;
+ name: string;
+ subjectType: 'AGENT';
+ subjectName: string;
+ subjectVersion: string;
+ testCase: AgentforceStudioTestCaseMetadata | AgentforceStudioTestCaseMetadata[];
+ };
+};
diff --git a/src/types/TestNodes.ts b/src/types/TestNodes.ts
index c014885c..e4b2792b 100644
--- a/src/types/TestNodes.ts
+++ b/src/types/TestNodes.ts
@@ -1,5 +1,5 @@
import * as vscode from 'vscode';
-import { TestStatus } from '@salesforce/agents';
+import { TestStatus, type TestRunnerType } from '@salesforce/agents';
import { getTestOutlineProvider } from '../views/testOutlineProvider';
/**
@@ -66,8 +66,13 @@ export abstract class TestNode extends vscode.TreeItem {
* has children AgentTestNode for individual test cases
*/
export class AgentTestGroupNode extends TestNode {
+ /** The actual metadata API name, which may differ from the display label when there's a naming conflict. */
+ public testDefinitionName: string;
+ public runnerType: TestRunnerType = 'testing-center';
+
constructor(label: string, location?: vscode.Location) {
super(label, vscode.TreeItemCollapsibleState.Expanded, location ?? null);
+ this.testDefinitionName = label;
}
public contextValue = 'agentTestGroup';
diff --git a/src/views/testOutlineProvider.ts b/src/views/testOutlineProvider.ts
index f8416cb8..9997ea1e 100644
--- a/src/views/testOutlineProvider.ts
+++ b/src/views/testOutlineProvider.ts
@@ -18,50 +18,107 @@ import { basename } from 'path';
import * as vscode from 'vscode';
import * as xml from 'fast-xml-parser';
import { Commands } from '../enums/commands';
-import { AgentTestGroupNode, AgentTestNode, AiEvaluationDefinition, TestNode } from '../types';
+import { AgentTestGroupNode, AgentTestNode, AiEvaluationDefinition, AiTestingDefinition, TestNode } from '../types';
+import type { TestRunnerType } from '@salesforce/agents';
const NO_TESTS_MESSAGE = 'no tests found';
const NO_TESTS_DESCRIPTION = 'no test description';
const AGENT_TESTS = 'AgentTests';
+
+const buildTestGroupNode = (
+ definitionUri: vscode.Uri,
+ definitionApiName: string,
+ label: string,
+ runnerType: TestRunnerType,
+ testCases: Array<{ number: string; inputs: { utterance: string } }>,
+ fileContent: string
+): AgentTestGroupNode => {
+ const testDefinitionNode = new AgentTestGroupNode(
+ label,
+ new vscode.Location(definitionUri, new vscode.Position(0, 0))
+ );
+ testDefinitionNode.testDefinitionName = definitionApiName;
+ testDefinitionNode.runnerType = runnerType;
+ const splitContent = fileContent.split(EOL);
+ testCases.forEach(test => {
+ const line = splitContent.findIndex(l => l.includes(`${test.number}`));
+ const testcaseNode = new AgentTestNode(
+ `#${test.number}`,
+ new vscode.Location(definitionUri, new vscode.Position(line < 0 ? 0 : line, 8))
+ );
+ testcaseNode.parentName = label;
+ testcaseNode.description = test.inputs.utterance;
+ testDefinitionNode.children.push(testcaseNode);
+ });
+ testDefinitionNode.children.sort((a, b) => a.name.localeCompare(b.name));
+ return testDefinitionNode;
+};
+
export const parseAgentTestsFromProject = async (): Promise