@@ -123,9 +123,11 @@ describe('agent test (agentforce-studio)', function () {
123123 writeFileSync ( join ( metaDir , `${ afsTestName } .aiTestingDefinition-meta.xml` ) , metaXml , 'utf8' ) ;
124124 console . log ( `Wrote AiTestingDefinition metadata to ${ metaDir } ` ) ;
125125
126- // Deploy the definition
126+ // Deploy the definition. Scope to just the file we authored — deploying the whole
127+ // aiTestingDefinitions dir would also sweep in static fixtures (e.g. ReturnsCheckoutSuite,
128+ // which targets a non-deployed multi-agent subject) and fail server-side validation.
127129 const cs = await ComponentSetBuilder . build ( {
128- sourcepath : [ metaDir ] ,
130+ sourcepath : [ join ( metaDir , ` ${ afsTestName } .aiTestingDefinition-meta.xml` ) ] ,
129131 } ) ;
130132 const deploy = await cs . deploy ( { usernameOrConnection : getUsername ( ) } ) ;
131133 const deployResult = await deploy . pollStatus ( { frequency : Duration . seconds ( 10 ) , timeout : Duration . minutes ( 10 ) } ) ;
@@ -139,8 +141,10 @@ describe('agent test (agentforce-studio)', function () {
139141 console . log ( `Deployed AiTestingDefinition '${ afsTestName } '` ) ;
140142 } ) ;
141143
142- // Set by the run test, consumed by the results tests (Mocha runs describes sequentially)
143- let completedRunId : string ;
144+ // Set by the run test, consumed by the results/resume tests (Mocha runs describes sequentially).
145+ // The AFS eval can outlast the client --wait window, so the run may still be IN_PROGRESS here.
146+ let sharedRunId : string ;
147+ let primaryRunCompleted = false ;
144148
145149 describe ( 'agent test list' , ( ) => {
146150 it ( 'should include the AFS test definition in list' , async ( ) => {
@@ -162,20 +166,26 @@ describe('agent test (agentforce-studio)', function () {
162166 { ensureExitCode : 0 }
163167 ) . jsonOutput ;
164168
165- expect ( output ?. result . status ) . to . equal ( 'COMPLETED' ) ;
166- expect ( output ?. result . runId . startsWith ( '3A2' ) ) . to . be . true ;
167169 const result = output ?. result as AgentTestRunResult & { testCases ?: unknown [ ] } ;
168- expect ( result ?. testCases ) . to . be . an ( 'array' ) ;
170+ // The AFS eval can take longer than the --wait window. A client-side timeout is a valid
171+ // outcome that now reports IN_PROGRESS (rather than masking as COMPLETED), so accept either
172+ // and assert only the run shape. testCases is only guaranteed once the run has COMPLETED.
173+ expect ( result ?. status ) . to . be . oneOf ( [ 'COMPLETED' , 'IN_PROGRESS' ] ) ;
174+ expect ( result ?. runId . startsWith ( '3A2' ) ) . to . be . true ;
169175 expect ( result ) . to . not . have . property ( 'subjectName' ) ;
176+ if ( result ?. status === 'COMPLETED' ) {
177+ expect ( result ?. testCases ) . to . be . an ( 'array' ) ;
178+ primaryRunCompleted = true ;
179+ }
170180
171- completedRunId = output ! . result . runId ;
181+ sharedRunId = output ! . result . runId ;
172182 } ) ;
173183 } ) ;
174184
175185 describe ( 'agent test results' , ( ) => {
176186 it ( 'should fetch AFS results by job ID (json)' , async ( ) => {
177187 const output = execCmd < AgentTestResultsResult > (
178- `agent test results --job-id ${ completedRunId } --target-org ${ getUsername ( ) } --json` ,
188+ `agent test results --job-id ${ sharedRunId } --target-org ${ getUsername ( ) } --json` ,
179189 { ensureExitCode : 0 }
180190 ) . jsonOutput ;
181191
@@ -187,15 +197,15 @@ describe('agent test (agentforce-studio)', function () {
187197
188198 it ( 'should support human result format' , ( ) => {
189199 const output = execCmd (
190- `agent test results --job-id ${ completedRunId } --result-format human --target-org ${ getUsername ( ) } ` ,
200+ `agent test results --job-id ${ sharedRunId } --result-format human --target-org ${ getUsername ( ) } ` ,
191201 { ensureExitCode : 0 }
192202 ) ;
193203 expect ( output . shellOutput . stdout ) . to . be . a ( 'string' ) . with . length . greaterThan ( 0 ) ;
194204 } ) ;
195205
196206 it ( 'should support junit result format' , ( ) => {
197207 const output = execCmd (
198- `agent test results --job-id ${ completedRunId } --result-format junit --target-org ${ getUsername ( ) } ` ,
208+ `agent test results --job-id ${ sharedRunId } --result-format junit --target-org ${ getUsername ( ) } ` ,
199209 { ensureExitCode : 0 }
200210 ) ;
201211 expect ( output . shellOutput . stdout ) . to . include ( '<?xml' ) ;
@@ -204,44 +214,59 @@ describe('agent test (agentforce-studio)', function () {
204214
205215 it ( 'should support tap result format' , ( ) => {
206216 const output = execCmd (
207- `agent test results --job-id ${ completedRunId } --result-format tap --target-org ${ getUsername ( ) } ` ,
217+ `agent test results --job-id ${ sharedRunId } --result-format tap --target-org ${ getUsername ( ) } ` ,
208218 { ensureExitCode : 0 }
209219 ) ;
210220 expect ( output . shellOutput . stdout ) . to . include ( 'TAP version 13' ) ;
211221 } ) ;
212222 } ) ;
213223
214224 describe ( 'agent test resume' , ( ) => {
215- it ( 'should start async then resume by job ID, and support --use-most-recent' , async ( ) => {
216- // Clear any stale entries before the run
217- const cacheBefore = await AgentTestCache . create ( ) ;
218- cacheBefore . clear ( ) ;
219- await cacheBefore . write ( ) ;
225+ it ( 'should resume the in-flight run (or a fresh async run) and honor the cache' , async function ( ) {
226+ this . timeout ( 30 * 60 * 1000 ) ;
220227
221- // One async start covers both resume paths
222- const runResult = execCmd < AgentTestRunResult > (
223- `agent test run --api-name ${ afsTestName } --target-org ${ getUsername ( ) } --json` ,
224- { ensureExitCode : 0 }
225- ) . jsonOutput ;
228+ if ( primaryRunCompleted ) {
229+ // The primary --wait run already finished, so its cache entry was removed and no run is
230+ // in flight. Start a fresh async run to exercise NEW + cache-write, then resume by job-id.
231+ const cacheBefore = await AgentTestCache . create ( ) ;
232+ cacheBefore . clear ( ) ;
233+ await cacheBefore . write ( ) ;
226234
227- expect ( runResult ?. result . runId . startsWith ( '3A2' ) ) . to . be . true ;
228- expect ( runResult ?. result . status ) . to . equal ( 'NEW' ) ;
235+ const runResult = execCmd < AgentTestRunResult > (
236+ `agent test run --api-name ${ afsTestName } --target-org ${ getUsername ( ) } --json` ,
237+ { ensureExitCode : 0 }
238+ ) . jsonOutput ;
229239
230- // Re-read from disk — the run command wrote the cache entry in a subprocess
231- const cache = await AgentTestCache . create ( ) ;
232- expect ( cache . resolveFromCache ( ) . runnerType ) . to . equal ( 'agentforce-studio' ) ;
240+ expect ( runResult ?. result . runId . startsWith ( '3A2' ) ) . to . be . true ;
241+ expect ( runResult ?. result . status ) . to . equal ( 'NEW' ) ;
233242
234- const output = execCmd < AgentTestRunResult > (
235- `agent test resume --job-id ${ runResult ?. result . runId } --target-org ${ getUsername ( ) } --json` ,
236- { ensureExitCode : 0 }
237- ) . jsonOutput ;
243+ // Re-read from disk — the run command wrote the cache entry in a subprocess
244+ const cache = await AgentTestCache . create ( ) ;
245+ expect ( cache . resolveFromCache ( ) . runnerType ) . to . equal ( 'agentforce-studio' ) ;
246+
247+ const output = execCmd < AgentTestRunResult > (
248+ `agent test resume --job-id ${ runResult ?. result . runId } --target-org ${ getUsername ( ) } --json` ,
249+ { ensureExitCode : 0 }
250+ ) . jsonOutput ;
251+
252+ // Resume may itself time out (the eval can outlast the poll window); both are valid.
253+ expect ( output ?. result . status ) . to . be . oneOf ( [ 'COMPLETED' , 'IN_PROGRESS' ] ) ;
254+ expect ( output ?. result . runId . startsWith ( '3A2' ) ) . to . be . true ;
255+ } else {
256+ // The primary --wait run timed out client-side and is still running server-side. Our fix
257+ // preserves the cache entry on a timeout, so resume --use-most-recent picks it up. Starting
258+ // a NEW run here would collide — AFS allows only one run per definition at a time.
259+ const cache = await AgentTestCache . create ( ) ;
260+ expect ( cache . resolveFromCache ( ) . runnerType ) . to . equal ( 'agentforce-studio' ) ;
238261
239- expect ( output ?. result . status ) . to . equal ( 'COMPLETED' ) ;
240- expect ( output ?. result . runId . startsWith ( '3A2' ) ) . to . be . true ;
262+ const output = execCmd < AgentTestRunResult > (
263+ `agent test resume --use-most-recent --target-org ${ getUsername ( ) } --json` ,
264+ { ensureExitCode : 0 }
265+ ) . jsonOutput ;
241266
242- // Re-read from disk — resume removes the entry in a subprocess
243- const cacheAfter = await AgentTestCache . create ( ) ;
244- expect ( ( ) => cacheAfter . resolveFromCache ( ) ) . to . throw ( 'Could not find a runId to resume' ) ;
267+ expect ( output ?. result . status ) . to . be . oneOf ( [ 'COMPLETED' , 'IN_PROGRESS' ] ) ;
268+ expect ( output ?. result . runId ) . to . equal ( sharedRunId ) ;
269+ }
245270 } ) ;
246271 } ) ;
247272
0 commit comments