11import type { OpenClawConfig } from "openclaw/plugin-sdk/config-runtime" ;
22import { afterEach , describe , expect , it , vi } from "vitest" ;
3+ import { renderQaMarkdownReport } from "../../report.js" ;
34import { __testing as liveTesting } from "./runtime.js" ;
45
56afterEach ( ( ) => {
@@ -228,6 +229,18 @@ describe("matrix live qa runtime", () => {
228229 scenarios : [ ] ,
229230 startedAt : "2026-04-10T10:00:00.000Z" ,
230231 sutAccountId : "sut" ,
232+ timings : {
233+ artifactWriteMs : 5 ,
234+ canaryMs : 40 ,
235+ harnessBootMs : 100 ,
236+ initialGatewayBootMs : 200 ,
237+ provisioningMs : 300 ,
238+ scenarioGatewayBootMs : 50 ,
239+ scenarioRestartGatewayMs : 60 ,
240+ scenarioTransportInterruptMs : 70 ,
241+ scenarios : [ ] ,
242+ totalMs : 825 ,
243+ } ,
231244 userIds : {
232245 driver : "@driver:matrix-qa.test" ,
233246 observer : "@observer:matrix-qa.test" ,
@@ -300,6 +313,27 @@ describe("matrix live qa runtime", () => {
300313 ] ,
301314 startedAt : "2026-04-10T10:00:00.000Z" ,
302315 sutAccountId : "sut" ,
316+ timings : {
317+ artifactWriteMs : 5 ,
318+ canaryMs : 40 ,
319+ harnessBootMs : 100 ,
320+ initialGatewayBootMs : 200 ,
321+ provisioningMs : 300 ,
322+ scenarioGatewayBootMs : 50 ,
323+ scenarioRestartGatewayMs : 60 ,
324+ scenarioTransportInterruptMs : 70 ,
325+ scenarios : [
326+ {
327+ durationMs : 80 ,
328+ gatewayBootMs : 0 ,
329+ gatewayRestartMs : 0 ,
330+ id : "matrix-mention-gating" ,
331+ title : "Matrix room message without mention does not trigger" ,
332+ transportInterruptMs : 0 ,
333+ } ,
334+ ] ,
335+ totalMs : 905 ,
336+ } ,
303337 userIds : {
304338 driver : "@driver:matrix-qa.test" ,
305339 observer : "@observer:matrix-qa.test" ,
@@ -322,9 +356,128 @@ describe("matrix live qa runtime", () => {
322356 } ,
323357 } ,
324358 ] ,
359+ timings : {
360+ totalMs : 905 ,
361+ } ,
325362 } ) ;
326363 } ) ;
327364
365+ it ( "keeps failing Matrix scenario details and timings complete in summary + report output" , ( ) => {
366+ const summary = liveTesting . buildMatrixQaSummary ( {
367+ artifactPaths : {
368+ observedEvents : "/tmp/observed.json" ,
369+ report : "/tmp/report.md" ,
370+ summary : "/tmp/summary.json" ,
371+ } ,
372+ checks : [ { name : "Matrix harness ready" , status : "pass" } ] ,
373+ config : {
374+ default : liveTesting . buildMatrixQaConfigSnapshot ( {
375+ driverUserId : "@driver:matrix-qa.test" ,
376+ observerUserId : "@observer:matrix-qa.test" ,
377+ sutUserId : "@sut:matrix-qa.test" ,
378+ topology : {
379+ defaultRoomId : "!room:matrix-qa.test" ,
380+ defaultRoomKey : "main" ,
381+ rooms : [ ] ,
382+ } ,
383+ } ) ,
384+ scenarios : [ ] ,
385+ } ,
386+ finishedAt : "2026-04-10T10:05:00.000Z" ,
387+ harness : {
388+ baseUrl : "http://127.0.0.1:28008/" ,
389+ composeFile : "/tmp/docker-compose.yml" ,
390+ dmRoomIds : [ ] ,
391+ image : "ghcr.io/matrix-construct/tuwunel:v1.5.1" ,
392+ roomId : "!room:matrix-qa.test" ,
393+ roomIds : [ "!room:matrix-qa.test" ] ,
394+ serverName : "matrix-qa.test" ,
395+ } ,
396+ observedEventCount : 6 ,
397+ scenarios : [
398+ {
399+ id : "matrix-reaction-not-a-reply" ,
400+ title : "Matrix reactions do not trigger a fresh bot reply" ,
401+ status : "fail" ,
402+ details : [
403+ "unexpected SUT reply after reaction from @driver:matrix-qa.test" ,
404+ "reaction event: $reaction" ,
405+ "unexpected reply event: $reply" ,
406+ ] . join ( "\n" ) ,
407+ } ,
408+ ] ,
409+ startedAt : "2026-04-10T10:00:00.000Z" ,
410+ sutAccountId : "sut" ,
411+ timings : {
412+ artifactWriteMs : 5 ,
413+ canaryMs : 40 ,
414+ harnessBootMs : 100 ,
415+ initialGatewayBootMs : 200 ,
416+ provisioningMs : 300 ,
417+ scenarioGatewayBootMs : 50 ,
418+ scenarioRestartGatewayMs : 60 ,
419+ scenarioTransportInterruptMs : 70 ,
420+ scenarios : [
421+ {
422+ durationMs : 8_000 ,
423+ gatewayBootMs : 0 ,
424+ gatewayRestartMs : 0 ,
425+ id : "matrix-reaction-not-a-reply" ,
426+ title : "Matrix reactions do not trigger a fresh bot reply" ,
427+ transportInterruptMs : 0 ,
428+ } ,
429+ ] ,
430+ totalMs : 825 ,
431+ } ,
432+ userIds : {
433+ driver : "@driver:matrix-qa.test" ,
434+ observer : "@observer:matrix-qa.test" ,
435+ sut : "@sut:matrix-qa.test" ,
436+ } ,
437+ } ) ;
438+
439+ expect ( summary ) . toMatchObject ( {
440+ counts : {
441+ total : 2 ,
442+ passed : 1 ,
443+ failed : 1 ,
444+ } ,
445+ scenarios : [
446+ {
447+ id : "matrix-reaction-not-a-reply" ,
448+ status : "fail" ,
449+ details : expect . stringContaining ( "reaction event: $reaction" ) ,
450+ } ,
451+ ] ,
452+ timings : {
453+ scenarios : [
454+ {
455+ id : "matrix-reaction-not-a-reply" ,
456+ durationMs : 8_000 ,
457+ } ,
458+ ] ,
459+ } ,
460+ } ) ;
461+
462+ const report = renderQaMarkdownReport ( {
463+ title : "Matrix QA Report" ,
464+ startedAt : new Date ( summary . startedAt ) ,
465+ finishedAt : new Date ( summary . finishedAt ) ,
466+ checks : summary . checks ,
467+ scenarios : summary . scenarios . map ( ( scenario ) => ( {
468+ details : scenario . details ,
469+ name : scenario . title ,
470+ status : scenario . status ,
471+ } ) ) ,
472+ notes : [ `observed events: ${ summary . observedEventsPath } ` ] ,
473+ } ) ;
474+
475+ expect ( report ) . toContain ( "### Matrix reactions do not trigger a fresh bot reply" ) ;
476+ expect ( report ) . toContain ( "unexpected SUT reply after reaction from @driver:matrix-qa.test" ) ;
477+ expect ( report ) . toContain ( "reaction event: $reaction" ) ;
478+ expect ( report ) . toContain ( "observed events: /tmp/observed.json" ) ;
479+ } ) ;
480+
328481 it ( "batches Matrix scenarios by config key while preserving stable in-group order" , ( ) => {
329482 const scenarios = liveTesting . findMatrixQaScenarios ( [
330483 "matrix-top-level-reply-shape" ,
0 commit comments