@midscene/core 1.12.10-beta-20260920031616.0 → 1.13.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.
Files changed (319) hide show
  1. package/dist/es/agent/agent.mjs +103 -6
  2. package/dist/es/agent/agent.mjs.map +1 -1
  3. package/dist/es/agent/index.mjs +4 -3
  4. package/dist/es/agent/tasks.mjs +2 -2
  5. package/dist/es/agent/tasks.mjs.map +1 -1
  6. package/dist/es/agent/test-runner-nodes.mjs +291 -40
  7. package/dist/es/agent/test-runner-nodes.mjs.map +1 -1
  8. package/dist/es/agent/utils.mjs +1 -1
  9. package/dist/es/device/index.mjs +15 -2
  10. package/dist/es/device/index.mjs.map +1 -1
  11. package/dist/es/dump/html-utils.mjs +37 -4
  12. package/dist/es/dump/html-utils.mjs.map +1 -1
  13. package/dist/es/dump/screenshot-store.mjs +8 -1
  14. package/dist/es/dump/screenshot-store.mjs.map +1 -1
  15. package/dist/es/report-cli.mjs +9 -4
  16. package/dist/es/report-cli.mjs.map +1 -1
  17. package/dist/es/report-generator.mjs +117 -4
  18. package/dist/es/report-generator.mjs.map +1 -1
  19. package/dist/es/report-html-template.mjs +1 -1
  20. package/dist/es/report.mjs +190 -41
  21. package/dist/es/report.mjs.map +1 -1
  22. package/dist/es/test-run-report.mjs.map +1 -1
  23. package/dist/es/test-runner/engine/case-runner.mjs +52 -0
  24. package/dist/es/test-runner/engine/case-runner.mjs.map +1 -0
  25. package/dist/es/test-runner/engine/document-runtime.mjs +273 -0
  26. package/dist/es/test-runner/engine/document-runtime.mjs.map +1 -0
  27. package/dist/es/test-runner/engine/execute-step.mjs +177 -0
  28. package/dist/es/test-runner/engine/execute-step.mjs.map +1 -0
  29. package/dist/es/test-runner/engine/execution-failure.mjs +39 -0
  30. package/dist/es/test-runner/engine/execution-failure.mjs.map +1 -0
  31. package/dist/es/test-runner/engine/index.mjs +12 -0
  32. package/dist/es/test-runner/engine/project-runtime.mjs +142 -0
  33. package/dist/es/test-runner/engine/project-runtime.mjs.map +1 -0
  34. package/dist/es/test-runner/engine/registry.mjs +61 -0
  35. package/dist/es/test-runner/engine/registry.mjs.map +1 -0
  36. package/dist/es/test-runner/engine/resource-operations.mjs +211 -0
  37. package/dist/es/test-runner/engine/resource-operations.mjs.map +1 -0
  38. package/dist/es/test-runner/engine/run-collected-case.mjs +193 -0
  39. package/dist/es/test-runner/engine/run-collected-case.mjs.map +1 -0
  40. package/dist/es/test-runner/engine/run-workflow-document.mjs +155 -0
  41. package/dist/es/test-runner/engine/run-workflow-document.mjs.map +1 -0
  42. package/dist/es/test-runner/engine/scheduler.mjs +27 -0
  43. package/dist/es/test-runner/engine/scheduler.mjs.map +1 -0
  44. package/dist/es/test-runner/engine/scope-teardown.mjs +16 -0
  45. package/dist/es/test-runner/engine/scope-teardown.mjs.map +1 -0
  46. package/dist/es/test-runner/engine/types.mjs +0 -0
  47. package/dist/es/test-runner/errors.mjs +201 -0
  48. package/dist/es/test-runner/errors.mjs.map +1 -0
  49. package/dist/es/test-runner/execution-record.mjs +83 -0
  50. package/dist/es/test-runner/execution-record.mjs.map +1 -0
  51. package/dist/es/test-runner/index.mjs +12 -0
  52. package/dist/es/test-runner/node/define-node.mjs +44 -0
  53. package/dist/es/test-runner/node/define-node.mjs.map +1 -0
  54. package/dist/es/test-runner/node/index.mjs +2 -0
  55. package/dist/es/test-runner/node/types.mjs +0 -0
  56. package/dist/es/test-runner/parser/document-format.mjs +21 -0
  57. package/dist/es/test-runner/parser/document-format.mjs.map +1 -0
  58. package/dist/es/test-runner/parser/normalize.mjs +87 -0
  59. package/dist/es/test-runner/parser/normalize.mjs.map +1 -0
  60. package/dist/es/test-runner/parser/types.mjs +0 -0
  61. package/dist/es/test-runner/project.mjs +0 -0
  62. package/dist/es/test-runner/reporting/agent-report.mjs +23 -0
  63. package/dist/es/test-runner/reporting/agent-report.mjs.map +1 -0
  64. package/dist/es/test-runner/reporting/execution-record.mjs +73 -0
  65. package/dist/es/test-runner/reporting/execution-record.mjs.map +1 -0
  66. package/dist/es/test-runner/reporting/merge-report.mjs +231 -0
  67. package/dist/es/test-runner/reporting/merge-report.mjs.map +1 -0
  68. package/dist/es/test-runner/reporting/sanitize.mjs +162 -0
  69. package/dist/es/test-runner/reporting/sanitize.mjs.map +1 -0
  70. package/dist/es/test-runner/reporting/test-run-report.mjs +327 -0
  71. package/dist/es/test-runner/reporting/test-run-report.mjs.map +1 -0
  72. package/dist/es/test-runner/reporting/types.mjs +0 -0
  73. package/dist/es/utils.mjs +1 -1
  74. package/dist/es/yaml/execution-context.node.mjs +6 -0
  75. package/dist/es/yaml/execution-context.node.mjs.map +1 -0
  76. package/dist/es/yaml/execution-context.stub.mjs +8 -0
  77. package/dist/es/yaml/execution-context.stub.mjs.map +1 -0
  78. package/dist/es/yaml/execution-session.mjs +90 -0
  79. package/dist/es/yaml/execution-session.mjs.map +1 -0
  80. package/dist/es/yaml/index.mjs +2 -1
  81. package/dist/es/yaml/legacy-yaml-execution-record.mjs +47 -0
  82. package/dist/es/yaml/legacy-yaml-execution-record.mjs.map +1 -0
  83. package/dist/es/yaml/legacy-yaml-report.mjs +52 -0
  84. package/dist/es/yaml/legacy-yaml-report.mjs.map +1 -0
  85. package/dist/es/yaml/legacy-yaml-runtime.mjs +119 -0
  86. package/dist/es/yaml/legacy-yaml-runtime.mjs.map +1 -0
  87. package/dist/es/yaml/player-state.mjs +15 -0
  88. package/dist/es/yaml/player-state.mjs.map +1 -0
  89. package/dist/es/yaml/player.mjs +214 -348
  90. package/dist/es/yaml/player.mjs.map +1 -1
  91. package/dist/es/yaml/report-policy.mjs +7 -0
  92. package/dist/es/yaml/report-policy.mjs.map +1 -0
  93. package/dist/es/yaml/test-runner-compat.mjs +301 -0
  94. package/dist/es/yaml/test-runner-compat.mjs.map +1 -0
  95. package/dist/es/yaml/test-runner-nodes.mjs +147 -0
  96. package/dist/es/yaml/test-runner-nodes.mjs.map +1 -0
  97. package/dist/es/yaml/utils.mjs +12 -1
  98. package/dist/es/yaml/utils.mjs.map +1 -1
  99. package/dist/es/yaml-runtime.mjs +7 -0
  100. package/dist/es/yaml.mjs.map +1 -1
  101. package/dist/lib/agent/agent.js +103 -6
  102. package/dist/lib/agent/agent.js.map +1 -1
  103. package/dist/lib/agent/index.js +37 -3
  104. package/dist/lib/agent/tasks.js +2 -2
  105. package/dist/lib/agent/tasks.js.map +1 -1
  106. package/dist/lib/agent/test-runner-nodes.js +329 -45
  107. package/dist/lib/agent/test-runner-nodes.js.map +1 -1
  108. package/dist/lib/agent/utils.js +1 -1
  109. package/dist/lib/device/index.js +15 -2
  110. package/dist/lib/device/index.js.map +1 -1
  111. package/dist/lib/dump/html-utils.js +43 -4
  112. package/dist/lib/dump/html-utils.js.map +1 -1
  113. package/dist/lib/dump/screenshot-store.js +8 -1
  114. package/dist/lib/dump/screenshot-store.js.map +1 -1
  115. package/dist/lib/report-cli.js +8 -3
  116. package/dist/lib/report-cli.js.map +1 -1
  117. package/dist/lib/report-generator.js +114 -1
  118. package/dist/lib/report-generator.js.map +1 -1
  119. package/dist/lib/report-html-template.js +1 -1
  120. package/dist/lib/report.js +187 -38
  121. package/dist/lib/report.js.map +1 -1
  122. package/dist/lib/test-run-report.js.map +1 -1
  123. package/dist/lib/test-runner/engine/case-runner.js +89 -0
  124. package/dist/lib/test-runner/engine/case-runner.js.map +1 -0
  125. package/dist/lib/test-runner/engine/document-runtime.js +307 -0
  126. package/dist/lib/test-runner/engine/document-runtime.js.map +1 -0
  127. package/dist/lib/test-runner/engine/execute-step.js +211 -0
  128. package/dist/lib/test-runner/engine/execute-step.js.map +1 -0
  129. package/dist/lib/test-runner/engine/execution-failure.js +79 -0
  130. package/dist/lib/test-runner/engine/execution-failure.js.map +1 -0
  131. package/dist/lib/test-runner/engine/index.js +137 -0
  132. package/dist/lib/test-runner/engine/index.js.map +1 -0
  133. package/dist/lib/test-runner/engine/project-runtime.js +176 -0
  134. package/dist/lib/test-runner/engine/project-runtime.js.map +1 -0
  135. package/dist/lib/test-runner/engine/registry.js +95 -0
  136. package/dist/lib/test-runner/engine/registry.js.map +1 -0
  137. package/dist/lib/test-runner/engine/resource-operations.js +272 -0
  138. package/dist/lib/test-runner/engine/resource-operations.js.map +1 -0
  139. package/dist/lib/test-runner/engine/run-collected-case.js +227 -0
  140. package/dist/lib/test-runner/engine/run-collected-case.js.map +1 -0
  141. package/dist/lib/test-runner/engine/run-workflow-document.js +189 -0
  142. package/dist/lib/test-runner/engine/run-workflow-document.js.map +1 -0
  143. package/dist/lib/test-runner/engine/scheduler.js +64 -0
  144. package/dist/lib/test-runner/engine/scheduler.js.map +1 -0
  145. package/dist/lib/test-runner/engine/scope-teardown.js +50 -0
  146. package/dist/lib/test-runner/engine/scope-teardown.js.map +1 -0
  147. package/dist/lib/test-runner/engine/types.js +20 -0
  148. package/dist/lib/test-runner/engine/types.js.map +1 -0
  149. package/dist/lib/test-runner/errors.js +283 -0
  150. package/dist/lib/test-runner/errors.js.map +1 -0
  151. package/dist/lib/test-runner/execution-record.js +123 -0
  152. package/dist/lib/test-runner/execution-record.js.map +1 -0
  153. package/dist/lib/test-runner/index.js +137 -0
  154. package/dist/lib/test-runner/index.js.map +1 -0
  155. package/dist/lib/test-runner/node/define-node.js +78 -0
  156. package/dist/lib/test-runner/node/define-node.js.map +1 -0
  157. package/dist/lib/test-runner/node/index.js +67 -0
  158. package/dist/lib/test-runner/node/index.js.map +1 -0
  159. package/dist/lib/test-runner/node/types.js +20 -0
  160. package/dist/lib/test-runner/node/types.js.map +1 -0
  161. package/dist/lib/test-runner/parser/document-format.js +58 -0
  162. package/dist/lib/test-runner/parser/document-format.js.map +1 -0
  163. package/dist/lib/test-runner/parser/normalize.js +124 -0
  164. package/dist/lib/test-runner/parser/normalize.js.map +1 -0
  165. package/dist/lib/test-runner/parser/types.js +20 -0
  166. package/dist/lib/test-runner/parser/types.js.map +1 -0
  167. package/dist/lib/test-runner/project.js +20 -0
  168. package/dist/lib/test-runner/project.js.map +1 -0
  169. package/dist/lib/test-runner/reporting/agent-report.js +57 -0
  170. package/dist/lib/test-runner/reporting/agent-report.js.map +1 -0
  171. package/dist/lib/test-runner/reporting/execution-record.js +107 -0
  172. package/dist/lib/test-runner/reporting/execution-record.js.map +1 -0
  173. package/dist/lib/test-runner/reporting/merge-report.js +265 -0
  174. package/dist/lib/test-runner/reporting/merge-report.js.map +1 -0
  175. package/dist/lib/test-runner/reporting/sanitize.js +202 -0
  176. package/dist/lib/test-runner/reporting/sanitize.js.map +1 -0
  177. package/dist/lib/test-runner/reporting/test-run-report.js +364 -0
  178. package/dist/lib/test-runner/reporting/test-run-report.js.map +1 -0
  179. package/dist/lib/test-runner/reporting/types.js +20 -0
  180. package/dist/lib/test-runner/reporting/types.js.map +1 -0
  181. package/dist/lib/utils.js +1 -1
  182. package/dist/lib/yaml/execution-context.node.js +43 -0
  183. package/dist/lib/yaml/execution-context.node.js.map +1 -0
  184. package/dist/lib/yaml/execution-context.stub.js +45 -0
  185. package/dist/lib/yaml/execution-context.stub.js.map +1 -0
  186. package/dist/lib/yaml/execution-session.js +136 -0
  187. package/dist/lib/yaml/execution-session.js.map +1 -0
  188. package/dist/lib/yaml/index.js +49 -7
  189. package/dist/lib/yaml/legacy-yaml-execution-record.js +81 -0
  190. package/dist/lib/yaml/legacy-yaml-execution-record.js.map +1 -0
  191. package/dist/lib/yaml/legacy-yaml-report.js +86 -0
  192. package/dist/lib/yaml/legacy-yaml-report.js.map +1 -0
  193. package/dist/lib/yaml/legacy-yaml-runtime.js +156 -0
  194. package/dist/lib/yaml/legacy-yaml-runtime.js.map +1 -0
  195. package/dist/lib/yaml/player-state.js +52 -0
  196. package/dist/lib/yaml/player-state.js.map +1 -0
  197. package/dist/lib/yaml/player.js +213 -347
  198. package/dist/lib/yaml/player.js.map +1 -1
  199. package/dist/lib/yaml/report-policy.js +41 -0
  200. package/dist/lib/yaml/report-policy.js.map +1 -0
  201. package/dist/lib/yaml/test-runner-compat.js +344 -0
  202. package/dist/lib/yaml/test-runner-compat.js.map +1 -0
  203. package/dist/lib/yaml/test-runner-nodes.js +184 -0
  204. package/dist/lib/yaml/test-runner-nodes.js.map +1 -0
  205. package/dist/lib/yaml/utils.js +18 -1
  206. package/dist/lib/yaml/utils.js.map +1 -1
  207. package/dist/lib/yaml-runtime.js +67 -0
  208. package/dist/lib/yaml-runtime.js.map +1 -0
  209. package/dist/lib/yaml.js.map +1 -1
  210. package/dist/types/agent/agent.d.ts +14 -1
  211. package/dist/types/agent/agent.d.ts.map +1 -1
  212. package/dist/types/agent/index.d.ts +4 -3
  213. package/dist/types/agent/index.d.ts.map +1 -1
  214. package/dist/types/agent/tasks.d.ts +1 -1
  215. package/dist/types/agent/tasks.d.ts.map +1 -1
  216. package/dist/types/agent/test-runner-nodes.d.ts +226 -0
  217. package/dist/types/agent/test-runner-nodes.d.ts.map +1 -1
  218. package/dist/types/device/index.d.ts +1 -1
  219. package/dist/types/device/index.d.ts.map +1 -1
  220. package/dist/types/dump/html-utils.d.ts +4 -0
  221. package/dist/types/dump/html-utils.d.ts.map +1 -1
  222. package/dist/types/dump/screenshot-store.d.ts +2 -1
  223. package/dist/types/dump/screenshot-store.d.ts.map +1 -1
  224. package/dist/types/report-cli.d.ts.map +1 -1
  225. package/dist/types/report-generator.d.ts +10 -0
  226. package/dist/types/report-generator.d.ts.map +1 -1
  227. package/dist/types/report.d.ts +3 -1
  228. package/dist/types/report.d.ts.map +1 -1
  229. package/dist/types/test-run-report.d.ts +18 -2
  230. package/dist/types/test-run-report.d.ts.map +1 -1
  231. package/dist/types/test-runner/engine/case-runner.d.ts +13 -0
  232. package/dist/types/test-runner/engine/case-runner.d.ts.map +1 -0
  233. package/dist/types/test-runner/engine/document-runtime.d.ts +4 -0
  234. package/dist/types/test-runner/engine/document-runtime.d.ts.map +1 -0
  235. package/dist/types/test-runner/engine/execute-step.d.ts +17 -0
  236. package/dist/types/test-runner/engine/execute-step.d.ts.map +1 -0
  237. package/dist/types/test-runner/engine/execution-failure.d.ts +13 -0
  238. package/dist/types/test-runner/engine/execution-failure.d.ts.map +1 -0
  239. package/dist/types/test-runner/engine/index.d.ts +13 -0
  240. package/dist/types/test-runner/engine/index.d.ts.map +1 -0
  241. package/dist/types/test-runner/engine/project-runtime.d.ts +3 -0
  242. package/dist/types/test-runner/engine/project-runtime.d.ts.map +1 -0
  243. package/dist/types/test-runner/engine/registry.d.ts +12 -0
  244. package/dist/types/test-runner/engine/registry.d.ts.map +1 -0
  245. package/dist/types/test-runner/engine/resource-operations.d.ts +32 -0
  246. package/dist/types/test-runner/engine/resource-operations.d.ts.map +1 -0
  247. package/dist/types/test-runner/engine/run-collected-case.d.ts +4 -0
  248. package/dist/types/test-runner/engine/run-collected-case.d.ts.map +1 -0
  249. package/dist/types/test-runner/engine/run-workflow-document.d.ts +4 -0
  250. package/dist/types/test-runner/engine/run-workflow-document.d.ts.map +1 -0
  251. package/dist/types/test-runner/engine/scheduler.d.ts +12 -0
  252. package/dist/types/test-runner/engine/scheduler.d.ts.map +1 -0
  253. package/dist/types/test-runner/engine/scope-teardown.d.ts +3 -0
  254. package/dist/types/test-runner/engine/scope-teardown.d.ts.map +1 -0
  255. package/dist/types/test-runner/engine/types.d.ts +226 -0
  256. package/dist/types/test-runner/engine/types.d.ts.map +1 -0
  257. package/dist/types/test-runner/errors.d.ts +79 -0
  258. package/dist/types/test-runner/errors.d.ts.map +1 -0
  259. package/dist/types/test-runner/execution-record.d.ts +43 -0
  260. package/dist/types/test-runner/execution-record.d.ts.map +1 -0
  261. package/dist/types/test-runner/index.d.ts +20 -0
  262. package/dist/types/test-runner/index.d.ts.map +1 -0
  263. package/dist/types/test-runner/node/define-node.d.ts +4 -0
  264. package/dist/types/test-runner/node/define-node.d.ts.map +1 -0
  265. package/dist/types/test-runner/node/index.d.ts +3 -0
  266. package/dist/types/test-runner/node/index.d.ts.map +1 -0
  267. package/dist/types/test-runner/node/types.d.ts +66 -0
  268. package/dist/types/test-runner/node/types.d.ts.map +1 -0
  269. package/dist/types/test-runner/parser/document-format.d.ts +8 -0
  270. package/dist/types/test-runner/parser/document-format.d.ts.map +1 -0
  271. package/dist/types/test-runner/parser/normalize.d.ts +9 -0
  272. package/dist/types/test-runner/parser/normalize.d.ts.map +1 -0
  273. package/dist/types/test-runner/parser/types.d.ts +69 -0
  274. package/dist/types/test-runner/parser/types.d.ts.map +1 -0
  275. package/dist/types/test-runner/project.d.ts +75 -0
  276. package/dist/types/test-runner/project.d.ts.map +1 -0
  277. package/dist/types/test-runner/reporting/agent-report.d.ts +9 -0
  278. package/dist/types/test-runner/reporting/agent-report.d.ts.map +1 -0
  279. package/dist/types/test-runner/reporting/execution-record.d.ts +9 -0
  280. package/dist/types/test-runner/reporting/execution-record.d.ts.map +1 -0
  281. package/dist/types/test-runner/reporting/merge-report.d.ts +15 -0
  282. package/dist/types/test-runner/reporting/merge-report.d.ts.map +1 -0
  283. package/dist/types/test-runner/reporting/sanitize.d.ts +6 -0
  284. package/dist/types/test-runner/reporting/sanitize.d.ts.map +1 -0
  285. package/dist/types/test-runner/reporting/test-run-report.d.ts +5 -0
  286. package/dist/types/test-runner/reporting/test-run-report.d.ts.map +1 -0
  287. package/dist/types/test-runner/reporting/types.d.ts +34 -0
  288. package/dist/types/test-runner/reporting/types.d.ts.map +1 -0
  289. package/dist/types/yaml/execution-context.node.d.ts +4 -0
  290. package/dist/types/yaml/execution-context.node.d.ts.map +1 -0
  291. package/dist/types/yaml/execution-context.stub.d.ts +6 -0
  292. package/dist/types/yaml/execution-context.stub.d.ts.map +1 -0
  293. package/dist/types/yaml/execution-session.d.ts +17 -0
  294. package/dist/types/yaml/execution-session.d.ts.map +1 -0
  295. package/dist/types/yaml/index.d.ts +1 -1
  296. package/dist/types/yaml/index.d.ts.map +1 -1
  297. package/dist/types/yaml/legacy-yaml-execution-record.d.ts +24 -0
  298. package/dist/types/yaml/legacy-yaml-execution-record.d.ts.map +1 -0
  299. package/dist/types/yaml/legacy-yaml-report.d.ts +19 -0
  300. package/dist/types/yaml/legacy-yaml-report.d.ts.map +1 -0
  301. package/dist/types/yaml/legacy-yaml-runtime.d.ts +23 -0
  302. package/dist/types/yaml/legacy-yaml-runtime.d.ts.map +1 -0
  303. package/dist/types/yaml/player-state.d.ts +11 -0
  304. package/dist/types/yaml/player-state.d.ts.map +1 -0
  305. package/dist/types/yaml/player.d.ts +11 -3
  306. package/dist/types/yaml/player.d.ts.map +1 -1
  307. package/dist/types/yaml/report-policy.d.ts +4 -0
  308. package/dist/types/yaml/report-policy.d.ts.map +1 -0
  309. package/dist/types/yaml/test-runner-compat.d.ts +17 -0
  310. package/dist/types/yaml/test-runner-compat.d.ts.map +1 -0
  311. package/dist/types/yaml/test-runner-nodes.d.ts +6 -0
  312. package/dist/types/yaml/test-runner-nodes.d.ts.map +1 -0
  313. package/dist/types/yaml/utils.d.ts +9 -0
  314. package/dist/types/yaml/utils.d.ts.map +1 -1
  315. package/dist/types/yaml-runtime.d.ts +13 -0
  316. package/dist/types/yaml-runtime.d.ts.map +1 -0
  317. package/dist/types/yaml.d.ts +25 -7
  318. package/dist/types/yaml.d.ts.map +1 -1
  319. package/package.json +28 -2
@@ -1,13 +1,14 @@
1
- import { appendFileSync, copyFileSync, existsSync, mkdirSync, mkdtempSync, readdirSync, renameSync, rmSync, unlinkSync, writeFileSync } from "node:fs";
1
+ import { appendFileSync, copyFileSync, existsSync, mkdirSync, mkdtempSync, readFileSync, readdirSync, renameSync, rmSync, unlinkSync, writeFileSync } from "node:fs";
2
+ import { copyFile, cp, mkdir, mkdtemp, readFile, rename, rm, writeFile } from "node:fs/promises";
2
3
  import { basename, dirname, join, resolve } from "node:path";
3
4
  import { getMidsceneRunSubDir } from "@midscene/shared/common";
4
- import { antiEscapeScriptTag, escapeScriptTag, logMsg } from "@midscene/shared/utils";
5
+ import { antiEscapeScriptTag, logMsg, uuid } from "@midscene/shared/utils";
5
6
  import { getReportFileName } from "./agent/report-file-name.mjs";
6
- import { DATA_SCREENSHOT_MODE_ATTR, extractAllDumpScriptsSync, extractLastDumpScriptSync, generateAgentReportComment, getBaseUrlFixScript, streamDumpScriptsSync, streamImageScriptsToFile } from "./dump/html-utils.mjs";
7
+ import { DATA_SCREENSHOT_MODE_ATTR, extractAllDumpScriptsSync, extractLastDumpScriptSync, extractTestRunReportDumpSync, generateAgentReportComment, generateTestRunReportScriptTag, getBaseUrlFixScript, streamDumpScriptsSync, streamImageScriptsToFile } from "./dump/html-utils.mjs";
7
8
  import { imageRefFileExtension, normalizeStoredImageRef } from "./dump/image-reference.mjs";
8
9
  import { parseBase64ImageDataUrl, resolveImageSource } from "./dump/screenshot-store.mjs";
9
10
  import { collectReportSummary } from "./report-stats.mjs";
10
- import { TEST_RUN_REPORT_SCRIPT_TYPE } from "./test-run-report.mjs";
11
+ import { mergeTestRunReportDumps } from "./test-runner/reporting/merge-report.mjs";
11
12
  import { ReportActionDump } from "./types.mjs";
12
13
  import { getReportTpl, getVersion, reportHTMLContent } from "./utils.mjs";
13
14
  function _define_property(obj, key, value) {
@@ -88,7 +89,7 @@ function mergedAgentReportComment(reports) {
88
89
  groupDescription: 'Agent-readable summary for merged report HTML',
89
90
  modelBriefs: reports.flatMap((report)=>report.modelBriefs ?? []),
90
91
  deviceType: 1 === deviceTypes.length ? deviceTypes[0] : 'mixed',
91
- executions: reports.flatMap((report)=>report.executions ?? [])
92
+ executions: dedupeExecutionsKeepLatest(reports.flatMap((report)=>report.executions ?? []))
92
93
  });
93
94
  return generateAgentReportComment(mergedReport);
94
95
  }
@@ -138,6 +139,8 @@ class ReportMergingTool {
138
139
  logMsg('No reports to merge');
139
140
  return null;
140
141
  }
142
+ const runnerDumps = this.reportInfos.map((info)=>info.reportFilePath ? extractTestRunReportDumpSync(info.reportFilePath) : void 0);
143
+ const hasRunnerDump = runnerDumps.some(Boolean);
141
144
  const targetDir = outputDir ? resolve(outputDir) : getMidsceneRunSubDir('report');
142
145
  if (outputDir) mkdirSync(targetDir, {
143
146
  recursive: true
@@ -166,6 +169,7 @@ class ReportMergingTool {
166
169
  appendFileSync(outputFilePath, tplWithoutClose);
167
170
  if (hasDirectoryModeReport) appendFileSync(outputFilePath, getBaseUrlFixScript());
168
171
  const agentReports = [];
172
+ const runnerSources = [];
169
173
  const writtenInlineImageIds = new Set();
170
174
  for(let i = 0; i < this.reportInfos.length; i++){
171
175
  const reportInfo = this.reportInfos[i];
@@ -191,16 +195,26 @@ class ReportMergingTool {
191
195
  } else streamImageScriptsToFile(reportInfo.reportFilePath, outputFilePath, writtenInlineImageIds);
192
196
  const allDumps = extractAllDumpScriptsSync(reportInfo.reportFilePath).filter((d)=>d.openTag.includes('data-group-id'));
193
197
  const groupIdMatch = allDumps[0]?.openTag.match(/data-group-id="([^"]+)"/);
194
- if (groupIdMatch) mergedGroupId = decodeURIComponent(groupIdMatch[1]);
198
+ if (groupIdMatch && !hasRunnerDump) mergedGroupId = decodeURIComponent(groupIdMatch[1]);
195
199
  const extractedDumpString = allDumps.length > 0 ? this.mergeDumpScripts(allDumps.map((d)=>d.content)) : extractLastDumpScriptSync(reportInfo.reportFilePath);
196
200
  if (extractedDumpString) dumpString = extractedDumpString;
197
201
  }
198
202
  const agentReport = tryParseAgentReportDump(dumpString);
199
203
  if (agentReport) agentReports.push(agentReport);
204
+ if (hasRunnerDump) runnerSources.push({
205
+ reportId: mergedGroupId,
206
+ sourcePath: reportInfo.reportFilePath ?? '<skipped-agent-report>',
207
+ attributes: reportAttributes,
208
+ dump: runnerDumps[i],
209
+ timing: agentReport ? agentReportTiming(agentReport, reportAttributes.testDuration) : void 0
210
+ });
200
211
  const reportHtmlStr = `${reportHTMLContent({
201
212
  dumpString,
202
213
  attributes: {
203
214
  'data-group-id': mergedGroupId,
215
+ ...hasRunnerDump ? {
216
+ 'data-report-id': mergedGroupId
217
+ } : {},
204
218
  [DATA_SCREENSHOT_MODE_ATTR]: hasDirectoryModeReport ? 'directory' : 'inline',
205
219
  playwright_test_duration: reportAttributes.testDuration,
206
220
  playwright_test_status: reportAttributes.testStatus,
@@ -212,6 +226,16 @@ class ReportMergingTool {
212
226
  }, void 0, void 0, false)}\n`;
213
227
  appendFileSync(outputFilePath, reportHtmlStr);
214
228
  }
229
+ if (hasRunnerDump) {
230
+ const summary = collectReportSummary({
231
+ executions: dedupeExecutionsKeepLatest(agentReports.flatMap((report)=>report.executions))
232
+ });
233
+ appendFileSync(outputFilePath, generateTestRunReportScriptTag(mergeTestRunReportDumps(runnerSources, {
234
+ modelCallCount: summary.timing.modelCallCount,
235
+ modelTimeMs: summary.timing.modelCallTimeMs,
236
+ ...summary.tokens
237
+ }, uuid())));
238
+ }
215
239
  const agentComment = mergedAgentReportComment(agentReports);
216
240
  if (agentComment) appendFileSync(outputFilePath, agentComment);
217
241
  appendFileSync(outputFilePath, `${htmlEndTag}\n`);
@@ -240,28 +264,29 @@ class ReportMergingTool {
240
264
  _define_property(this, "reportInfos", []);
241
265
  }
242
266
  }
243
- const emptyTestRunReportMetrics = ()=>({
244
- modelCallCount: 0,
245
- modelTimeMs: 0,
246
- promptTokens: 0,
247
- cachedInputTokens: 0,
248
- completionTokens: 0,
249
- totalTokens: 0
250
- });
267
+ function agentReportTiming(report, durationMs) {
268
+ const timing = collectReportSummary(report).timing;
269
+ const executionTimes = report.executions.map((execution)=>execution.logTime).filter((value)=>'number' == typeof value && Number.isFinite(value));
270
+ const started = timing.wallTimeStart ?? (executionTimes.length ? Math.min(...executionTimes) : void 0);
271
+ if (void 0 === started) return;
272
+ const ended = timing.wallTimeEnd ?? Math.max(...executionTimes, started + (Number.isFinite(durationMs) ? Math.max(0, durationMs) : 0));
273
+ return {
274
+ startedAt: new Date(started).toISOString(),
275
+ endedAt: new Date(ended).toISOString(),
276
+ durationMs: Math.max(0, ended - started)
277
+ };
278
+ }
251
279
  const validateTestRunReportFileName = (fileName)=>{
252
280
  if (!fileName || '.' === fileName || '..' === fileName || basename(fileName) !== fileName || fileName.endsWith('.html')) throw new Error(`Midscene Test reportFileName must be one path segment without an extension: ${fileName}`);
253
281
  };
254
282
  const uniqueTestRunReportSources = (sources)=>{
255
283
  const unique = new Map();
256
- const scopeBySourcePath = new Map();
257
284
  for (const source of sources){
258
285
  const scopeId = source.scopeId.trim();
259
286
  const sourcePath = resolve(source.sourcePath);
260
287
  if (!scopeId) throw new Error('Midscene Test report source scopeId must not be empty.');
261
- const previousScope = scopeBySourcePath.get(sourcePath);
262
- if (previousScope && previousScope !== scopeId) throw new Error(`Agent report source is shared by multiple test scopes (${previousScope}, ${scopeId}): ${sourcePath}`);
263
- scopeBySourcePath.set(sourcePath, scopeId);
264
- unique.set(`${scopeId}\u0000${sourcePath}`, {
288
+ unique.set(`${scopeId}\u0000${source.dumpPath ?? sourcePath}`, {
289
+ ...source,
265
290
  scopeId,
266
291
  sourcePath
267
292
  });
@@ -270,20 +295,49 @@ const uniqueTestRunReportSources = (sources)=>{
270
295
  ...unique.values()
271
296
  ];
272
297
  };
273
- const prepareTestRunReportSources = (sources)=>{
298
+ const prepareTestRunReportSources = (sources, loadedDumps)=>{
274
299
  const prepared = [];
275
- const metrics = emptyTestRunReportMetrics();
276
300
  const ownerByScopedExecution = new Map();
301
+ const preparedByPath = new Map();
277
302
  for (const [sourceIndex, source] of uniqueTestRunReportSources(sources).entries()){
278
- if (!existsSync(source.sourcePath)) throw new Error(`Agent report does not exist: ${source.sourcePath}`);
279
- const sourceVersion = peekReportSdkVersion(source.sourcePath);
303
+ const sourceKey = source.sourcePath;
304
+ const shared = preparedByPath.get(sourceKey);
305
+ if (shared) {
306
+ if (source.dumpPath) {
307
+ const snapshot = ReportActionDump.fromSerializedString(loadedDumps?.get(source.dumpPath) ?? readFileSync(source.dumpPath, 'utf8'));
308
+ shared.dump.executions = dedupeExecutionsKeepLatest([
309
+ ...shared.dump.executions,
310
+ ...snapshot.executions
311
+ ]);
312
+ shared.executionIds.splice(0, shared.executionIds.length, ...shared.dump.executions.flatMap((execution)=>execution.id ? [
313
+ execution.id
314
+ ] : []));
315
+ }
316
+ for (const executionId of shared.executionIds){
317
+ const key = `${source.scopeId}\u0000${executionId}`;
318
+ const owner = ownerByScopedExecution.get(key);
319
+ if (owner && owner !== shared.reportId) throw new Error(`Agent execution ${executionId} is present in multiple reports for test scope ${source.scopeId}: ${owner}, ${shared.reportId}`);
320
+ ownerByScopedExecution.set(key, shared.reportId);
321
+ }
322
+ prepared.push({
323
+ ...shared,
324
+ scopeId: source.scopeId
325
+ });
326
+ continue;
327
+ }
328
+ if (!source.dumpPath && !existsSync(source.sourcePath)) throw new Error(`Agent report does not exist: ${source.sourcePath}`);
329
+ const sourceVersion = source.dumpPath ? void 0 : peekReportSdkVersion(source.sourcePath);
280
330
  const currentVersion = getVersion();
281
331
  if (sourceVersion && currentVersion && sourceVersion !== currentVersion && !warnedMismatchedVersions.has(sourceVersion)) {
282
332
  warnedMismatchedVersions.add(sourceVersion);
283
333
  logMsg(`[@midscene/core] TestRunReportAssembler version mismatch: source report was written by @midscene/core@${sourceVersion} but the assembler is @midscene/core@${currentVersion}. Align the workspace package versions before generating the Midscene Test report.`);
284
334
  }
285
335
  const reportId = `runner-report-${sourceIndex + 1}`;
286
- const { baseDump, executions } = collectDedupedExecutions(source.sourcePath);
336
+ const snapshot = source.dumpPath ? ReportActionDump.fromSerializedString(loadedDumps?.get(source.dumpPath) ?? readFileSync(source.dumpPath, 'utf8')) : void 0;
337
+ const { baseDump, executions } = snapshot ? {
338
+ baseDump: snapshot,
339
+ executions: snapshot.executions
340
+ } : collectDedupedExecutions(source.sourcePath);
287
341
  const executionIds = [];
288
342
  for (const execution of executions){
289
343
  if (!execution.id) continue;
@@ -301,32 +355,124 @@ const prepareTestRunReportSources = (sources)=>{
301
355
  deviceType: baseDump.deviceType,
302
356
  executions
303
357
  });
304
- const sourceMetrics = collectReportSummary(dump);
305
- metrics.modelCallCount += sourceMetrics.timing.modelCallCount;
306
- metrics.modelTimeMs += sourceMetrics.timing.modelCallTimeMs;
307
- metrics.promptTokens += sourceMetrics.tokens.promptTokens;
308
- metrics.cachedInputTokens += sourceMetrics.tokens.cachedInputTokens;
309
- metrics.completionTokens += sourceMetrics.tokens.completionTokens;
310
- metrics.totalTokens += sourceMetrics.tokens.totalTokens;
311
- prepared.push({
358
+ const preparedSource = {
312
359
  reportId,
313
360
  scopeId: source.scopeId,
314
361
  sourcePath: source.sourcePath,
315
362
  executionIds,
316
363
  dump,
317
- directoryMode: isDirectoryModeReport(source.sourcePath)
318
- });
364
+ directoryMode: !!source.dumpPath || isDirectoryModeReport(source.sourcePath),
365
+ ...source.dumpPath ? {
366
+ dumpPath: source.dumpPath
367
+ } : {}
368
+ };
369
+ prepared.push(preparedSource);
370
+ preparedByPath.set(sourceKey, preparedSource);
319
371
  }
372
+ const summary = collectReportSummary({
373
+ executions: dedupeExecutionsKeepLatest([
374
+ ...preparedByPath.values()
375
+ ].flatMap((source)=>source.dump.executions))
376
+ });
320
377
  return {
321
378
  sources: prepared,
322
- metrics
379
+ metrics: {
380
+ modelCallCount: summary.timing.modelCallCount,
381
+ modelTimeMs: summary.timing.modelCallTimeMs,
382
+ ...summary.tokens
383
+ }
323
384
  };
324
385
  };
325
- const runnerDumpScript = (dump)=>{
326
- const closeTag = "<\/script>";
327
- return '<script type="' + TEST_RUN_REPORT_SCRIPT_TYPE + '">\n' + escapeScriptTag(JSON.stringify(dump)) + '\n' + closeTag + '\n';
328
- };
329
386
  class TestRunReportAssembler {
387
+ async assembleAsync(options) {
388
+ validateTestRunReportFileName(options.reportFileName);
389
+ const loaded = new Map();
390
+ await Promise.all(options.sources.map(async (source)=>{
391
+ if (source.dumpPath) loaded.set(source.dumpPath, await readFile(source.dumpPath, 'utf8'));
392
+ }));
393
+ const prepared = prepareTestRunReportSources(options.sources, loaded);
394
+ const dump = options.buildRunnerDump({
395
+ sources: prepared.sources,
396
+ metrics: prepared.metrics
397
+ });
398
+ if ('test-runner' !== dump.kind || 1 !== dump.schemaVersion) throw new Error('Invalid Runner report dump');
399
+ const directoryMode = prepared.sources.some((source)=>source.directoryMode);
400
+ const outputDir = resolve(options.outputDir);
401
+ await mkdir(outputDir, {
402
+ recursive: true
403
+ });
404
+ const artifact = join(outputDir, options.reportFileName);
405
+ const finalPath = directoryMode ? join(artifact, 'index.html') : `${artifact}.html`;
406
+ if (!options.overwrite && (existsSync(artifact) || existsSync(`${artifact}.html`))) throw new Error(`Report artifact already exists: ${artifact}`);
407
+ const temporary = await mkdtemp(join(outputDir, '.test-run-report-'));
408
+ const htmlPath = join(temporary, 'index.html');
409
+ try {
410
+ const parts = [
411
+ getReportTpl(),
412
+ directoryMode ? getBaseUrlFixScript() : ''
413
+ ];
414
+ const imageIds = new Set();
415
+ const reports = [];
416
+ for (const source of new Map(prepared.sources.map((source)=>[
417
+ source.reportId,
418
+ source
419
+ ])).values()){
420
+ const serialized = source.dump.serialize();
421
+ if (source.dumpPath) {
422
+ const refs = new Map();
423
+ JSON.parse(serialized, (_key, value)=>{
424
+ const ref = normalizeStoredImageRef(value);
425
+ if (ref) refs.set(ref.id, ref);
426
+ return value;
427
+ });
428
+ if (refs.size) await mkdir(join(temporary, 'screenshots'), {
429
+ recursive: true
430
+ });
431
+ for (const ref of refs.values())if (!imageIds.has(ref.id)) {
432
+ if ('file' !== ref.storage || !ref.path) throw new Error(`Snapshot image ${ref.id} has no file source`);
433
+ await copyFile(resolve(dirname(source.dumpPath), ref.path), join(temporary, 'screenshots', `${ref.id}.${imageRefFileExtension(ref)}`));
434
+ imageIds.add(ref.id);
435
+ }
436
+ } else if (source.directoryMode) {
437
+ const images = join(dirname(source.sourcePath), 'screenshots');
438
+ if (existsSync(images)) await cp(images, join(temporary, 'screenshots'), {
439
+ recursive: true
440
+ });
441
+ } else {
442
+ const html = await readFile(source.sourcePath, 'utf8');
443
+ for (const match of html.matchAll(/<script\b([^>]*)>[\s\S]*?<\/script>/g))if (/(?:^|\s)type=["']midscene-image["']/.test(match[1])) parts.push(match[0]);
444
+ }
445
+ reports.push(source.dump);
446
+ parts.push(reportHTMLContent({
447
+ dumpString: serialized,
448
+ attributes: {
449
+ 'data-group-id': source.reportId,
450
+ 'data-report-id': source.reportId,
451
+ 'data-runner-scope-id': source.scopeId,
452
+ [DATA_SCREENSHOT_MODE_ATTR]: directoryMode ? 'directory' : 'inline'
453
+ }
454
+ }, void 0, void 0, false));
455
+ }
456
+ parts.push(generateTestRunReportScriptTag(dump), mergedAgentReportComment(reports));
457
+ await writeFile(htmlPath, parts.join('\n'));
458
+ if (options.overwrite) {
459
+ await rm(artifact, {
460
+ recursive: true,
461
+ force: true
462
+ });
463
+ await rm(`${artifact}.html`, {
464
+ force: true
465
+ });
466
+ }
467
+ await rename(directoryMode ? temporary : htmlPath, directoryMode ? artifact : finalPath);
468
+ return finalPath;
469
+ } finally{
470
+ await rm(temporary, {
471
+ recursive: true,
472
+ force: true
473
+ });
474
+ }
475
+ }
330
476
  assemble(options) {
331
477
  validateTestRunReportFileName(options.reportFileName);
332
478
  const outputDir = resolve(options.outputDir);
@@ -369,7 +515,10 @@ class TestRunReportAssembler {
369
515
  appendFileSync(temporaryReportPath, -1 === htmlEndIndex ? template : template.slice(0, htmlEndIndex));
370
516
  if (directoryMode) appendFileSync(temporaryReportPath, getBaseUrlFixScript());
371
517
  const agentReports = [];
372
- for (const source of prepared.sources){
518
+ for (const source of new Map(prepared.sources.map((source)=>[
519
+ source.reportId,
520
+ source
521
+ ])).values()){
373
522
  if (source.directoryMode) {
374
523
  const screenshotsDir = join(dirname(source.sourcePath), 'screenshots');
375
524
  if (existsSync(screenshotsDir)) {
@@ -391,7 +540,7 @@ class TestRunReportAssembler {
391
540
  }
392
541
  }, void 0, void 0, false)}\n`);
393
542
  }
394
- appendFileSync(temporaryReportPath, runnerDumpScript(runnerDump));
543
+ appendFileSync(temporaryReportPath, generateTestRunReportScriptTag(runnerDump));
395
544
  const agentComment = mergedAgentReportComment(agentReports);
396
545
  if (agentComment) appendFileSync(temporaryReportPath, agentComment);
397
546
  appendFileSync(temporaryReportPath, `${htmlEndTag}\n`);