@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
@@ -0,0 +1,193 @@
1
+ import { getDebug } from "@midscene/shared/logger";
2
+ import { uuid } from "@midscene/shared/utils";
3
+ import { NodeScopeTeardownError, WorkflowLifecycleError } from "../errors.mjs";
4
+ import { executeStep } from "./execute-step.mjs";
5
+ import { WorkflowExecutionFailure, asExecutionError } from "./execution-failure.mjs";
6
+ import { ResourceCleanupDeferredError, cleanupScopeResources, createResourceScope } from "./resource-operations.mjs";
7
+ import { reportPathsFromTeardown } from "./scope-teardown.mjs";
8
+ async function runCollectedCase(collectedCase, options) {
9
+ const phases = {
10
+ beforeEach: options.beforeEach ?? [],
11
+ steps: collectedCase.definition.steps,
12
+ afterEach: options.afterEach ?? []
13
+ };
14
+ const nodes = {
15
+ beforeEach: phases.beforeEach.map((step)=>options.resolveNode(step.node)),
16
+ steps: phases.steps.map((step)=>options.resolveNode(step.node)),
17
+ afterEach: phases.afterEach.map((step)=>options.resolveNode(step.node))
18
+ };
19
+ const resourceScope = createResourceScope(options.signal);
20
+ const scopeSignal = resourceScope.signal;
21
+ const runId = options.createRunId?.() ?? uuid();
22
+ const startedAt = new Date();
23
+ const beforeEach = [];
24
+ const steps = [];
25
+ const afterEach = [];
26
+ const teardownStack = [];
27
+ let acceptingTeardowns = true;
28
+ const onTeardown = (node, teardown)=>{
29
+ if (!acceptingTeardowns) throw new WorkflowLifecycleError('Node teardown can only be registered while a case attempt is running.', {
30
+ runId,
31
+ node
32
+ });
33
+ if ('function' != typeof teardown) throw new WorkflowLifecycleError('Node onTeardown() requires a teardown function.', {
34
+ runId,
35
+ node
36
+ });
37
+ teardownStack.push({
38
+ registrationIndex: teardownStack.length,
39
+ node,
40
+ teardown
41
+ });
42
+ };
43
+ const runPhase = async (phase, results, signal = scopeSignal)=>{
44
+ for (const [stepIndex, step] of phases[phase].entries()){
45
+ const caseContext = {
46
+ caseId: collectedCase.caseId,
47
+ runId,
48
+ projectName: options.projectName ?? collectedCase.projectId,
49
+ attemptIndex: options.attemptIndex ?? 0,
50
+ name: collectedCase.definition.name,
51
+ sourcePath: collectedCase.sourcePath,
52
+ caseIndex: collectedCase.caseIndex,
53
+ phase,
54
+ stepIndex
55
+ };
56
+ const stepInfo = {
57
+ scope: 'case',
58
+ node: step.node,
59
+ stepCount: phases[phase].length,
60
+ case: caseContext
61
+ };
62
+ await options.onStepStart?.(stepInfo);
63
+ const result = await executeStep(step, nodes[phase][stepIndex], {
64
+ scope: 'case',
65
+ case: caseContext
66
+ }, options.context, {
67
+ signal,
68
+ defaultTimeoutMs: options.defaultTimeoutMs,
69
+ onTeardown
70
+ });
71
+ results.push(result);
72
+ await options.onStepResult?.(stepInfo, result);
73
+ if ('failed' === result.status && !result.continuedAfterError) break;
74
+ }
75
+ };
76
+ const executionErrors = [];
77
+ try {
78
+ await runPhase('beforeEach', beforeEach);
79
+ if (!beforeEach.some((step)=>'failed' === step.status)) await runPhase('steps', steps);
80
+ } catch (error) {
81
+ executionErrors.push(error);
82
+ }
83
+ const teardownErrors = [];
84
+ const reportPaths = new Set();
85
+ const reportSources = [];
86
+ const cleanupExecutionErrors = [];
87
+ let deferredCleanup = false;
88
+ const cleanup = async ()=>{
89
+ const priorTeardownErrors = teardownErrors.length;
90
+ acceptingTeardowns = false;
91
+ for (const { registrationIndex, node, teardown } of teardownStack.reverse())try {
92
+ const released = await teardown();
93
+ reportSources.push(...released?.reportSources ?? []);
94
+ for (const path of reportPathsFromTeardown(released))reportPaths.add(path);
95
+ } catch (error) {
96
+ teardownErrors.push(new NodeScopeTeardownError(error, {
97
+ scope: 'case',
98
+ scopeId: runId,
99
+ node,
100
+ registrationIndex
101
+ }));
102
+ }
103
+ if (deferredCleanup) {
104
+ const errors = [
105
+ ...cleanupExecutionErrors,
106
+ ...teardownErrors.slice(priorTeardownErrors)
107
+ ];
108
+ if (errors.length) throw new AggregateError(errors, 'Deferred Case cleanup failed');
109
+ }
110
+ };
111
+ try {
112
+ if (phases.afterEach.length || teardownStack.length) await cleanupScopeResources(scopeSignal, cleanup, {
113
+ beforeCleanup: async (cleanupSignal)=>{
114
+ try {
115
+ await runPhase('afterEach', afterEach, cleanupSignal);
116
+ } catch (error) {
117
+ executionErrors.push(error);
118
+ cleanupExecutionErrors.push(error);
119
+ }
120
+ },
121
+ onDeferredError: (error)=>getDebug('runner:cleanup', {
122
+ console: true
123
+ })(`Deferred Case cleanup failed: ${String(error)}`)
124
+ });
125
+ else acceptingTeardowns = false;
126
+ } catch (error) {
127
+ deferredCleanup = error instanceof ResourceCleanupDeferredError;
128
+ if (!deferredCleanup) acceptingTeardowns = false;
129
+ teardownErrors.push(new NodeScopeTeardownError(error, {
130
+ scope: 'case',
131
+ scopeId: runId,
132
+ node: 'resource-drain',
133
+ registrationIndex: -1
134
+ }));
135
+ }
136
+ const endedAt = new Date();
137
+ const result = {
138
+ caseId: collectedCase.caseId,
139
+ runId,
140
+ projectName: options.projectName ?? collectedCase.projectId,
141
+ attemptIndex: options.attemptIndex ?? 0,
142
+ name: collectedCase.definition.name,
143
+ sourcePath: collectedCase.sourcePath,
144
+ caseIndex: collectedCase.caseIndex,
145
+ status: executionErrors.length > 0 || beforeEach.some((step)=>'failed' === step.status) || steps.some((step)=>'failed' === step.status) || afterEach.some((step)=>'failed' === step.status) || teardownErrors.length > 0 ? 'failed' : 'success',
146
+ beforeEach: [
147
+ ...beforeEach
148
+ ],
149
+ steps: [
150
+ ...steps
151
+ ],
152
+ afterEach: [
153
+ ...afterEach
154
+ ],
155
+ ...executionErrors.length ? {
156
+ executionErrors: executionErrors.map(asExecutionError)
157
+ } : {},
158
+ ...teardownErrors.length > 0 ? {
159
+ teardownErrors: [
160
+ ...teardownErrors
161
+ ]
162
+ } : {},
163
+ ...reportPaths.size > 0 ? {
164
+ reportPaths: [
165
+ ...reportPaths
166
+ ]
167
+ } : {},
168
+ ...reportSources.length ? {
169
+ reportSources: [
170
+ ...reportSources
171
+ ]
172
+ } : {},
173
+ ...options.reportScopeId ? {
174
+ reportScopeId: options.reportScopeId
175
+ } : {},
176
+ startedAt: startedAt.toISOString(),
177
+ endedAt: endedAt.toISOString(),
178
+ durationMs: Math.max(0, endedAt.getTime() - startedAt.getTime())
179
+ };
180
+ try {
181
+ await options.onResult?.(result);
182
+ } catch (error) {
183
+ executionErrors.push(error);
184
+ result.status = 'failed';
185
+ result.executionErrors = executionErrors.map(asExecutionError);
186
+ }
187
+ resourceScope.dispose();
188
+ if (executionErrors.length) throw new WorkflowExecutionFailure(result, executionErrors);
189
+ return result;
190
+ }
191
+ export { runCollectedCase };
192
+
193
+ //# sourceMappingURL=run-collected-case.mjs.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"test-runner/engine/run-collected-case.mjs","sources":["../../../../src/test-runner/engine/run-collected-case.ts"],"sourcesContent":["import { getDebug } from '@midscene/shared/logger';\nimport { uuid as randomUUID } from '@midscene/shared/utils';\nimport { NodeScopeTeardownError, WorkflowLifecycleError } from '../errors';\nimport type { CollectedCase, NormalizedStep } from '../parser/types';\nimport { executeStep } from './execute-step';\nimport {\n WorkflowExecutionFailure,\n asExecutionError,\n} from './execution-failure';\nimport {\n ResourceCleanupDeferredError,\n cleanupScopeResources,\n createResourceScope,\n} from './resource-operations';\nimport { reportPathsFromTeardown } from './scope-teardown';\nimport type {\n CaseNodePhase,\n CaseRunResult,\n NodeCaseContext,\n NodeScopeTeardown,\n RunCollectedCaseOptions,\n StepRunResult,\n} from './types';\n\nexport async function runCollectedCase<TContext = undefined>(\n collectedCase: CollectedCase,\n options: RunCollectedCaseOptions<TContext>,\n): Promise<CaseRunResult> {\n const phases: Record<CaseNodePhase, readonly NormalizedStep[]> = {\n beforeEach: options.beforeEach ?? [],\n steps: collectedCase.definition.steps,\n afterEach: options.afterEach ?? [],\n };\n const nodes = {\n beforeEach: phases.beforeEach.map((step) => options.resolveNode(step.node)),\n steps: phases.steps.map((step) => options.resolveNode(step.node)),\n afterEach: phases.afterEach.map((step) => options.resolveNode(step.node)),\n };\n const resourceScope = createResourceScope(options.signal);\n const scopeSignal = resourceScope.signal;\n const runId = options.createRunId?.() ?? randomUUID();\n const startedAt = new Date();\n const beforeEach: StepRunResult[] = [];\n const steps: StepRunResult[] = [];\n const afterEach: StepRunResult[] = [];\n const teardownStack: Array<{\n registrationIndex: number;\n node: string;\n teardown: NodeScopeTeardown;\n }> = [];\n let acceptingTeardowns = true;\n\n const onTeardown = (node: string, teardown: NodeScopeTeardown): void => {\n if (!acceptingTeardowns) {\n throw new WorkflowLifecycleError(\n 'Node teardown can only be registered while a case attempt is running.',\n { runId, node },\n );\n }\n if (typeof teardown !== 'function') {\n throw new WorkflowLifecycleError(\n 'Node onTeardown() requires a teardown function.',\n { runId, node },\n );\n }\n teardownStack.push({\n registrationIndex: teardownStack.length,\n node,\n teardown,\n });\n };\n\n const runPhase = async (\n phase: CaseNodePhase,\n results: StepRunResult[],\n signal = scopeSignal,\n ): Promise<void> => {\n for (const [stepIndex, step] of phases[phase].entries()) {\n const caseContext: NodeCaseContext = {\n caseId: collectedCase.caseId,\n runId,\n projectName: options.projectName ?? collectedCase.projectId,\n attemptIndex: options.attemptIndex ?? 0,\n name: collectedCase.definition.name,\n sourcePath: collectedCase.sourcePath,\n caseIndex: collectedCase.caseIndex,\n phase,\n stepIndex,\n };\n const stepInfo = {\n scope: 'case' as const,\n node: step.node,\n stepCount: phases[phase].length,\n case: caseContext,\n };\n await options.onStepStart?.(stepInfo);\n const result = await executeStep(\n step,\n nodes[phase][stepIndex],\n { scope: 'case', case: caseContext },\n options.context as TContext,\n {\n signal,\n defaultTimeoutMs: options.defaultTimeoutMs,\n onTeardown,\n },\n );\n results.push(result);\n await options.onStepResult?.(stepInfo, result);\n if (result.status === 'failed' && !result.continuedAfterError) break;\n }\n };\n\n const executionErrors: unknown[] = [];\n try {\n await runPhase('beforeEach', beforeEach);\n if (!beforeEach.some((step) => step.status === 'failed')) {\n await runPhase('steps', steps);\n }\n } catch (error) {\n executionErrors.push(error);\n }\n const teardownErrors: NodeScopeTeardownError[] = [];\n const reportPaths = new Set<string>();\n const reportSources: import('./types').WorkflowReportSource[] = [];\n const cleanupExecutionErrors: unknown[] = [];\n let deferredCleanup = false;\n const cleanup = async () => {\n const priorTeardownErrors = teardownErrors.length;\n acceptingTeardowns = false;\n for (const {\n registrationIndex,\n node,\n teardown,\n } of teardownStack.reverse()) {\n try {\n const released = await teardown();\n reportSources.push(...(released?.reportSources ?? []));\n for (const path of reportPathsFromTeardown(released)) {\n reportPaths.add(path);\n }\n } catch (error) {\n teardownErrors.push(\n new NodeScopeTeardownError(error, {\n scope: 'case',\n scopeId: runId,\n node,\n registrationIndex,\n }),\n );\n }\n }\n if (deferredCleanup) {\n const errors = [\n ...cleanupExecutionErrors,\n ...teardownErrors.slice(priorTeardownErrors),\n ];\n if (errors.length)\n throw new AggregateError(errors, 'Deferred Case cleanup failed');\n }\n };\n try {\n if (phases.afterEach.length || teardownStack.length)\n await cleanupScopeResources(scopeSignal, cleanup, {\n beforeCleanup: async (cleanupSignal) => {\n try {\n await runPhase('afterEach', afterEach, cleanupSignal);\n } catch (error) {\n executionErrors.push(error);\n cleanupExecutionErrors.push(error);\n }\n },\n onDeferredError: (error) =>\n getDebug('runner:cleanup', { console: true })(\n `Deferred Case cleanup failed: ${String(error)}`,\n ),\n });\n else acceptingTeardowns = false;\n } catch (error) {\n deferredCleanup = error instanceof ResourceCleanupDeferredError;\n if (!deferredCleanup) acceptingTeardowns = false;\n teardownErrors.push(\n new NodeScopeTeardownError(error, {\n scope: 'case',\n scopeId: runId,\n node: 'resource-drain',\n registrationIndex: -1,\n }),\n );\n }\n const endedAt = new Date();\n const result: CaseRunResult = {\n caseId: collectedCase.caseId,\n runId,\n projectName: options.projectName ?? collectedCase.projectId,\n attemptIndex: options.attemptIndex ?? 0,\n name: collectedCase.definition.name,\n sourcePath: collectedCase.sourcePath,\n caseIndex: collectedCase.caseIndex,\n status:\n executionErrors.length > 0 ||\n beforeEach.some((step) => step.status === 'failed') ||\n steps.some((step) => step.status === 'failed') ||\n afterEach.some((step) => step.status === 'failed') ||\n teardownErrors.length > 0\n ? 'failed'\n : 'success',\n beforeEach: [...beforeEach],\n steps: [...steps],\n afterEach: [...afterEach],\n ...(executionErrors.length\n ? { executionErrors: executionErrors.map(asExecutionError) }\n : {}),\n ...(teardownErrors.length > 0\n ? { teardownErrors: [...teardownErrors] }\n : {}),\n ...(reportPaths.size > 0 ? { reportPaths: [...reportPaths] } : {}),\n ...(reportSources.length ? { reportSources: [...reportSources] } : {}),\n ...(options.reportScopeId ? { reportScopeId: options.reportScopeId } : {}),\n startedAt: startedAt.toISOString(),\n endedAt: endedAt.toISOString(),\n durationMs: Math.max(0, endedAt.getTime() - startedAt.getTime()),\n };\n\n try {\n await options.onResult?.(result);\n } catch (error) {\n executionErrors.push(error);\n result.status = 'failed';\n result.executionErrors = executionErrors.map(asExecutionError);\n }\n resourceScope.dispose();\n if (executionErrors.length)\n throw new WorkflowExecutionFailure(result, executionErrors);\n return result;\n}\n"],"names":["runCollectedCase","collectedCase","options","phases","nodes","step","resourceScope","createResourceScope","scopeSignal","runId","randomUUID","startedAt","Date","beforeEach","steps","afterEach","teardownStack","acceptingTeardowns","onTeardown","node","teardown","WorkflowLifecycleError","runPhase","phase","results","signal","stepIndex","caseContext","stepInfo","result","executeStep","executionErrors","error","teardownErrors","reportPaths","Set","reportSources","cleanupExecutionErrors","deferredCleanup","cleanup","priorTeardownErrors","registrationIndex","released","path","reportPathsFromTeardown","NodeScopeTeardownError","errors","AggregateError","cleanupScopeResources","cleanupSignal","getDebug","String","ResourceCleanupDeferredError","endedAt","asExecutionError","Math","WorkflowExecutionFailure"],"mappings":"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"}
@@ -0,0 +1,155 @@
1
+ import { createDocumentRuntime } from "./document-runtime.mjs";
2
+ import { WorkflowExecutionFailure, asExecutionError } from "./execution-failure.mjs";
3
+ import { runCollectedCase } from "./run-collected-case.mjs";
4
+ const asNotRun = (collectedCase, projectName, reason)=>({
5
+ caseId: collectedCase.caseId,
6
+ projectName,
7
+ name: collectedCase.definition.name,
8
+ sourcePath: collectedCase.sourcePath,
9
+ caseIndex: collectedCase.caseIndex,
10
+ ...collectedCase.definition.onFailure ? {
11
+ onFailure: collectedCase.definition.onFailure
12
+ } : {},
13
+ status: 'not-run',
14
+ notRunReason: reason
15
+ });
16
+ async function runWorkflowDocument(document, options) {
17
+ const signal = options.signal ?? new AbortController().signal;
18
+ const createDocumentRunId = options.createDocumentRunId;
19
+ const createCaseRunId = options.createCaseRunId;
20
+ const projectName = options.project?.name ?? document.projectId;
21
+ const retry = options.retry ?? options.project?.retry ?? 0;
22
+ if (!Number.isInteger(retry) || retry < 0) throw new TypeError('Workflow document retry must be a non-negative integer.');
23
+ const runtime = createDocumentRuntime(document, {
24
+ documentSetup: options.documentSetup,
25
+ documentAttemptIndex: options.documentAttemptIndex,
26
+ resolveNode: options.resolveNode,
27
+ project: options.project,
28
+ projectContext: options.projectContext,
29
+ signal,
30
+ defaultTimeoutMs: options.defaultTimeoutMs,
31
+ onStepStart: options.onStepStart,
32
+ onStepResult: options.onStepResult,
33
+ onResult: async (result)=>{
34
+ await options.documentSetup?.onDocumentResult?.(result, runtime.context);
35
+ await options.onDocumentResult?.(result);
36
+ },
37
+ createDocumentRunId: createDocumentRunId ? ()=>createDocumentRunId(document) : void 0
38
+ });
39
+ const cases = [];
40
+ let runtimeStarted = false;
41
+ let documentResult;
42
+ const executionErrors = [];
43
+ let fatalError = false;
44
+ let stoppedByCase = false;
45
+ try {
46
+ runtimeStarted = true;
47
+ const startedDocument = await runtime.start();
48
+ if (runtime.canRunCases) for (const collectedCase of document.cases){
49
+ if (stoppedByCase || fatalError || signal.aborted || options.shouldStop?.()) {
50
+ const outcome = asNotRun(collectedCase, projectName, signal.aborted ? options.stopReason?.() ?? 'interrupted' : fatalError ? 'fatal-error' : stoppedByCase ? 'bail' : options.stopReason?.() ?? 'interrupted');
51
+ cases.push(outcome);
52
+ await options.onCaseOutcome?.(outcome);
53
+ continue;
54
+ }
55
+ await options.onCaseStart?.(collectedCase);
56
+ const attempts = [];
57
+ for(let attemptIndex = 0; attemptIndex <= retry; attemptIndex += 1){
58
+ let attemptFailure;
59
+ const run = await runCollectedCase(collectedCase, {
60
+ resolveNode: options.resolveNode,
61
+ beforeEach: document.lifecycle.beforeEach,
62
+ afterEach: document.lifecycle.afterEach,
63
+ context: runtime.context,
64
+ projectName,
65
+ attemptIndex,
66
+ signal: runtime.signal,
67
+ defaultTimeoutMs: options.defaultTimeoutMs,
68
+ onStepStart: options.onStepStart,
69
+ onStepResult: options.onStepResult,
70
+ onResult: options.onCaseResult,
71
+ reportScopeId: options.resolveCaseReportScopeId?.(collectedCase, attemptIndex, startedDocument.documentRunId),
72
+ createRunId: createCaseRunId ? ()=>createCaseRunId(collectedCase, attemptIndex) : void 0
73
+ }).catch((error)=>{
74
+ if (!(error instanceof WorkflowExecutionFailure)) throw error;
75
+ attemptFailure = error;
76
+ return attemptFailure.result;
77
+ });
78
+ attempts.push(run);
79
+ if (attemptFailure) {
80
+ cases.push({
81
+ caseId: collectedCase.caseId,
82
+ projectName,
83
+ name: collectedCase.definition.name,
84
+ sourcePath: collectedCase.sourcePath,
85
+ caseIndex: collectedCase.caseIndex,
86
+ ...collectedCase.definition.onFailure ? {
87
+ onFailure: collectedCase.definition.onFailure
88
+ } : {},
89
+ status: 'failed',
90
+ run,
91
+ attempts
92
+ });
93
+ throw attemptFailure;
94
+ }
95
+ fatalError = options.isFatalError?.(run) ?? false;
96
+ if ('success' === run.status || !!run.teardownErrors?.length || fatalError || signal.aborted || options.shouldStop?.()) break;
97
+ }
98
+ const run = attempts.at(-1);
99
+ const outcome = {
100
+ caseId: collectedCase.caseId,
101
+ projectName,
102
+ name: collectedCase.definition.name,
103
+ sourcePath: collectedCase.sourcePath,
104
+ caseIndex: collectedCase.caseIndex,
105
+ ...collectedCase.definition.onFailure ? {
106
+ onFailure: collectedCase.definition.onFailure
107
+ } : {},
108
+ status: run.status,
109
+ run,
110
+ attempts
111
+ };
112
+ cases.push(outcome);
113
+ stoppedByCase = 'failed' === outcome.status && 'stop-document' === collectedCase.definition.onFailure;
114
+ await options.onCaseOutcome?.(outcome);
115
+ }
116
+ else {
117
+ const reason = signal.aborted ? options.stopReason?.() ?? 'interrupted' : 'document-start-failed';
118
+ cases.push(...document.cases.map((collectedCase)=>asNotRun(collectedCase, projectName, reason)));
119
+ }
120
+ } catch (error) {
121
+ executionErrors.push(...error instanceof WorkflowExecutionFailure ? error.errors : [
122
+ error
123
+ ]);
124
+ } finally{
125
+ if (runtimeStarted) try {
126
+ documentResult = await runtime.finish();
127
+ } catch (error) {
128
+ if (error instanceof WorkflowExecutionFailure) {
129
+ documentResult = error.result;
130
+ for (const failure of error.errors)if (!executionErrors.includes(failure)) executionErrors.push(failure);
131
+ } else executionErrors.push(error);
132
+ }
133
+ }
134
+ if (!documentResult) {
135
+ if (executionErrors.length) throw new AggregateError(executionErrors, 'Workflow execution did not produce a document result.');
136
+ throw new Error(`Workflow document "${document.sourcePath}" did not produce a result.`);
137
+ }
138
+ if (executionErrors.length) {
139
+ const completed = new Set(cases.map((outcome)=>outcome.caseId));
140
+ cases.push(...document.cases.filter((item)=>!completed.has(item.caseId)).map((item)=>asNotRun(item, projectName, 'interrupted')));
141
+ documentResult.status = 'failed';
142
+ documentResult.executionErrors = executionErrors.map(asExecutionError);
143
+ throw new WorkflowExecutionFailure({
144
+ document: documentResult,
145
+ cases
146
+ }, executionErrors);
147
+ }
148
+ return {
149
+ document: documentResult,
150
+ cases
151
+ };
152
+ }
153
+ export { runWorkflowDocument };
154
+
155
+ //# sourceMappingURL=run-workflow-document.mjs.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"test-runner/engine/run-workflow-document.mjs","sources":["../../../../src/test-runner/engine/run-workflow-document.ts"],"sourcesContent":["import type { CollectedCase, CollectedWorkflowDocument } from '../parser/types';\nimport { createDocumentRuntime } from './document-runtime';\nimport {\n WorkflowExecutionFailure,\n asExecutionError,\n} from './execution-failure';\nimport { runCollectedCase } from './run-collected-case';\nimport type {\n CaseRunOutcome,\n CaseRunResult,\n RunWorkflowDocumentOptions,\n WorkflowDocumentExecutionResult,\n WorkflowDocumentRunResult,\n} from './types';\n\nconst asNotRun = (\n collectedCase: CollectedCase,\n projectName: string,\n reason: NonNullable<CaseRunOutcome['notRunReason']>,\n): CaseRunOutcome => ({\n caseId: collectedCase.caseId,\n projectName,\n name: collectedCase.definition.name,\n sourcePath: collectedCase.sourcePath,\n caseIndex: collectedCase.caseIndex,\n ...(collectedCase.definition.onFailure\n ? { onFailure: collectedCase.definition.onFailure }\n : {}),\n status: 'not-run',\n notRunReason: reason,\n});\n\nexport async function runWorkflowDocument<TContext = undefined>(\n document: CollectedWorkflowDocument,\n options: RunWorkflowDocumentOptions<TContext>,\n): Promise<WorkflowDocumentExecutionResult> {\n const signal = options.signal ?? new AbortController().signal;\n const createDocumentRunId = options.createDocumentRunId;\n const createCaseRunId = options.createCaseRunId;\n const projectName = options.project?.name ?? document.projectId;\n const retry = options.retry ?? options.project?.retry ?? 0;\n if (!Number.isInteger(retry) || retry < 0) {\n throw new TypeError(\n 'Workflow document retry must be a non-negative integer.',\n );\n }\n const runtime = createDocumentRuntime(document, {\n documentSetup: options.documentSetup,\n documentAttemptIndex: options.documentAttemptIndex,\n resolveNode: options.resolveNode,\n project: options.project,\n projectContext: options.projectContext,\n signal,\n defaultTimeoutMs: options.defaultTimeoutMs,\n onStepStart: options.onStepStart,\n onStepResult: options.onStepResult,\n onResult: async (result) => {\n await options.documentSetup?.onDocumentResult?.(result, runtime.context);\n await options.onDocumentResult?.(result);\n },\n createDocumentRunId: createDocumentRunId\n ? () => createDocumentRunId(document)\n : undefined,\n });\n const cases: CaseRunOutcome[] = [];\n let runtimeStarted = false;\n let documentResult: WorkflowDocumentRunResult | undefined;\n const executionErrors: unknown[] = [];\n let fatalError = false;\n let stoppedByCase = false;\n\n try {\n runtimeStarted = true;\n const startedDocument = await runtime.start();\n\n if (!runtime.canRunCases) {\n const reason = signal.aborted\n ? (options.stopReason?.() ?? 'interrupted')\n : 'document-start-failed';\n cases.push(\n ...document.cases.map((collectedCase) =>\n asNotRun(collectedCase, projectName, reason),\n ),\n );\n } else {\n for (const collectedCase of document.cases) {\n if (\n stoppedByCase ||\n fatalError ||\n signal.aborted ||\n options.shouldStop?.()\n ) {\n const outcome = asNotRun(\n collectedCase,\n projectName,\n signal.aborted\n ? (options.stopReason?.() ?? 'interrupted')\n : fatalError\n ? 'fatal-error'\n : stoppedByCase\n ? 'bail'\n : (options.stopReason?.() ?? 'interrupted'),\n );\n cases.push(outcome);\n await options.onCaseOutcome?.(outcome);\n continue;\n }\n\n await options.onCaseStart?.(collectedCase);\n const attempts = [];\n for (let attemptIndex = 0; attemptIndex <= retry; attemptIndex += 1) {\n let attemptFailure:\n | WorkflowExecutionFailure<CaseRunResult>\n | undefined;\n const run = await runCollectedCase(collectedCase, {\n resolveNode: options.resolveNode,\n beforeEach: document.lifecycle.beforeEach,\n afterEach: document.lifecycle.afterEach,\n context: runtime.context,\n projectName,\n attemptIndex,\n signal: runtime.signal,\n defaultTimeoutMs: options.defaultTimeoutMs,\n onStepStart: options.onStepStart,\n onStepResult: options.onStepResult,\n onResult: options.onCaseResult,\n reportScopeId: options.resolveCaseReportScopeId?.(\n collectedCase,\n attemptIndex,\n startedDocument.documentRunId,\n ),\n createRunId: createCaseRunId\n ? () => createCaseRunId(collectedCase, attemptIndex)\n : undefined,\n }).catch((error: unknown) => {\n if (!(error instanceof WorkflowExecutionFailure)) throw error;\n attemptFailure = error as WorkflowExecutionFailure<CaseRunResult>;\n return attemptFailure.result;\n });\n attempts.push(run);\n if (attemptFailure) {\n cases.push({\n caseId: collectedCase.caseId,\n projectName,\n name: collectedCase.definition.name,\n sourcePath: collectedCase.sourcePath,\n caseIndex: collectedCase.caseIndex,\n ...(collectedCase.definition.onFailure\n ? { onFailure: collectedCase.definition.onFailure }\n : {}),\n status: 'failed',\n run,\n attempts,\n });\n throw attemptFailure;\n }\n fatalError = options.isFatalError?.(run) ?? false;\n if (\n run.status === 'success' ||\n // Retrying cannot repair cleanup/report publication and would\n // replay actions that may already have completed successfully.\n !!run.teardownErrors?.length ||\n fatalError ||\n signal.aborted ||\n options.shouldStop?.()\n )\n break;\n }\n const run = attempts.at(-1)!;\n const outcome: CaseRunOutcome = {\n caseId: collectedCase.caseId,\n projectName,\n name: collectedCase.definition.name,\n sourcePath: collectedCase.sourcePath,\n caseIndex: collectedCase.caseIndex,\n ...(collectedCase.definition.onFailure\n ? { onFailure: collectedCase.definition.onFailure }\n : {}),\n status: run.status,\n run,\n attempts,\n };\n cases.push(outcome);\n stoppedByCase =\n outcome.status === 'failed' &&\n collectedCase.definition.onFailure === 'stop-document';\n await options.onCaseOutcome?.(outcome);\n }\n }\n } catch (error) {\n executionErrors.push(\n ...(error instanceof WorkflowExecutionFailure ? error.errors : [error]),\n );\n } finally {\n if (runtimeStarted) {\n try {\n documentResult = await runtime.finish();\n } catch (error) {\n if (error instanceof WorkflowExecutionFailure) {\n documentResult = error.result as WorkflowDocumentRunResult;\n for (const failure of error.errors)\n if (!executionErrors.includes(failure))\n executionErrors.push(failure);\n } else executionErrors.push(error);\n }\n }\n }\n\n if (!documentResult) {\n if (executionErrors.length)\n throw new AggregateError(\n executionErrors,\n 'Workflow execution did not produce a document result.',\n );\n throw new Error(\n `Workflow document \"${document.sourcePath}\" did not produce a result.`,\n );\n }\n if (executionErrors.length) {\n const completed = new Set(cases.map((outcome) => outcome.caseId));\n cases.push(\n ...document.cases\n .filter((item) => !completed.has(item.caseId))\n .map((item) => asNotRun(item, projectName, 'interrupted')),\n );\n documentResult.status = 'failed';\n documentResult.executionErrors = executionErrors.map(asExecutionError);\n throw new WorkflowExecutionFailure(\n { document: documentResult, cases },\n executionErrors,\n );\n }\n return { document: documentResult, cases };\n}\n"],"names":["asNotRun","collectedCase","projectName","reason","runWorkflowDocument","document","options","signal","AbortController","createDocumentRunId","createCaseRunId","retry","Number","TypeError","runtime","createDocumentRuntime","result","undefined","cases","runtimeStarted","documentResult","executionErrors","fatalError","stoppedByCase","startedDocument","outcome","attempts","attemptIndex","attemptFailure","run","runCollectedCase","error","WorkflowExecutionFailure","failure","AggregateError","Error","completed","Set","item","asExecutionError"],"mappings":"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"}
@@ -0,0 +1,27 @@
1
+ async function runDocumentAttempts(options, run) {
2
+ for(let attemptIndex = 0; attemptIndex <= options.retry; attemptIndex++){
3
+ if (options.signal.aborted || options.shouldStop()) return;
4
+ const status = await run(attemptIndex);
5
+ if ('failed' !== status) return;
6
+ }
7
+ }
8
+ async function runConcurrentJobs(items, options, run) {
9
+ let next = 0;
10
+ const worker = async ()=>{
11
+ while(next < items.length && !options.shouldStop()){
12
+ const index = next++;
13
+ await run(items[index], index);
14
+ }
15
+ };
16
+ const workers = await Promise.allSettled(Array.from({
17
+ length: Math.min(options.concurrency, items.length)
18
+ }, worker));
19
+ const errors = workers.flatMap((result)=>'rejected' === result.status ? [
20
+ result.reason
21
+ ] : []);
22
+ if (1 === errors.length) throw errors[0];
23
+ if (errors.length) throw new AggregateError(errors, 'Document scheduling failed');
24
+ }
25
+ export { runConcurrentJobs, runDocumentAttempts };
26
+
27
+ //# sourceMappingURL=scheduler.mjs.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"test-runner/engine/scheduler.mjs","sources":["../../../../src/test-runner/engine/scheduler.ts"],"sourcesContent":["/** A rejected attempt is an infrastructure failure and is never replayed. */\nexport async function runDocumentAttempts(\n options: { retry: number; signal: AbortSignal; shouldStop(): boolean },\n run: (attemptIndex: number) => Promise<'success' | 'failed' | undefined>,\n): Promise<void> {\n for (let attemptIndex = 0; attemptIndex <= options.retry; attemptIndex++) {\n if (options.signal.aborted || options.shouldStop()) return;\n const status = await run(attemptIndex);\n if (status !== 'failed') return;\n }\n}\n\n/** Ordered admission, bounded concurrency, results in invocation order. */\nexport async function runConcurrentJobs<T>(\n items: readonly T[],\n options: { concurrency: number; shouldStop(): boolean },\n run: (item: T, index: number) => Promise<void>,\n): Promise<void> {\n let next = 0;\n const worker = async () => {\n while (next < items.length && !options.shouldStop()) {\n const index = next++;\n await run(items[index], index);\n }\n };\n const workers = await Promise.allSettled(\n Array.from({ length: Math.min(options.concurrency, items.length) }, worker),\n );\n const errors = workers.flatMap((result) =>\n result.status === 'rejected' ? [result.reason] : [],\n );\n if (errors.length === 1) throw errors[0];\n if (errors.length)\n throw new AggregateError(errors, 'Document scheduling failed');\n}\n"],"names":["runDocumentAttempts","options","run","attemptIndex","status","runConcurrentJobs","items","next","worker","index","workers","Promise","Array","Math","errors","result","AggregateError"],"mappings":"AACO,eAAeA,oBACpBC,OAAsE,EACtEC,GAAwE;IAExE,IAAK,IAAIC,eAAe,GAAGA,gBAAgBF,QAAQ,KAAK,EAAEE,eAAgB;QACxE,IAAIF,QAAQ,MAAM,CAAC,OAAO,IAAIA,QAAQ,UAAU,IAAI;QACpD,MAAMG,SAAS,MAAMF,IAAIC;QACzB,IAAIC,AAAW,aAAXA,QAAqB;IAC3B;AACF;AAGO,eAAeC,kBACpBC,KAAmB,EACnBL,OAAuD,EACvDC,GAA8C;IAE9C,IAAIK,OAAO;IACX,MAAMC,SAAS;QACb,MAAOD,OAAOD,MAAM,MAAM,IAAI,CAACL,QAAQ,UAAU,GAAI;YACnD,MAAMQ,QAAQF;YACd,MAAML,IAAII,KAAK,CAACG,MAAM,EAAEA;QAC1B;IACF;IACA,MAAMC,UAAU,MAAMC,QAAQ,UAAU,CACtCC,MAAM,IAAI,CAAC;QAAE,QAAQC,KAAK,GAAG,CAACZ,QAAQ,WAAW,EAAEK,MAAM,MAAM;IAAE,GAAGE;IAEtE,MAAMM,SAASJ,QAAQ,OAAO,CAAC,CAACK,SAC9BA,AAAkB,eAAlBA,OAAO,MAAM,GAAkB;YAACA,OAAO,MAAM;SAAC,GAAG,EAAE;IAErD,IAAID,AAAkB,MAAlBA,OAAO,MAAM,EAAQ,MAAMA,MAAM,CAAC,EAAE;IACxC,IAAIA,OAAO,MAAM,EACf,MAAM,IAAIE,eAAeF,QAAQ;AACrC"}
@@ -0,0 +1,16 @@
1
+ import { isAbsolute } from "node:path";
2
+ const reportPathsFromTeardown = (result)=>{
3
+ if (void 0 === result) return [];
4
+ if ('object' != typeof result || null === result || Array.isArray(result)) throw new TypeError('Node teardown result must be an object or undefined.');
5
+ const paths = result.reportPaths;
6
+ if (void 0 === paths) return [];
7
+ if (!Array.isArray(paths)) throw new TypeError('Node teardown reportPaths must be an array.');
8
+ return paths.map((path, index)=>{
9
+ if ('string' != typeof path || 0 === path.trim().length) throw new TypeError(`Node teardown reportPaths[${index}] must be a non-empty string.`);
10
+ if (!isAbsolute(path)) throw new TypeError(`Node teardown reportPaths[${index}] must be an absolute path.`);
11
+ return path;
12
+ });
13
+ };
14
+ export { reportPathsFromTeardown };
15
+
16
+ //# sourceMappingURL=scope-teardown.mjs.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"test-runner/engine/scope-teardown.mjs","sources":["../../../../src/test-runner/engine/scope-teardown.ts"],"sourcesContent":["import { isAbsolute } from 'node:path';\nimport type { NodeScopeTeardownResult } from './types';\n\nexport const reportPathsFromTeardown = (\n // biome-ignore lint/suspicious/noConfusingVoidType: this consumes the intentional void teardown return.\n result: NodeScopeTeardownResult | void,\n): readonly string[] => {\n if (result === undefined) return [];\n if (typeof result !== 'object' || result === null || Array.isArray(result)) {\n throw new TypeError('Node teardown result must be an object or undefined.');\n }\n const paths = result.reportPaths;\n if (paths === undefined) return [];\n if (!Array.isArray(paths)) {\n throw new TypeError('Node teardown reportPaths must be an array.');\n }\n return paths.map((path, index) => {\n if (typeof path !== 'string' || path.trim().length === 0) {\n throw new TypeError(\n `Node teardown reportPaths[${index}] must be a non-empty string.`,\n );\n }\n if (!isAbsolute(path)) {\n throw new TypeError(\n `Node teardown reportPaths[${index}] must be an absolute path.`,\n );\n }\n return path;\n });\n};\n"],"names":["reportPathsFromTeardown","result","undefined","Array","TypeError","paths","path","index","isAbsolute"],"mappings":";AAGO,MAAMA,0BAA0B,CAErCC;IAEA,IAAIA,AAAWC,WAAXD,QAAsB,OAAO,EAAE;IACnC,IAAI,AAAkB,YAAlB,OAAOA,UAAuBA,AAAW,SAAXA,UAAmBE,MAAM,OAAO,CAACF,SACjE,MAAM,IAAIG,UAAU;IAEtB,MAAMC,QAAQJ,OAAO,WAAW;IAChC,IAAII,AAAUH,WAAVG,OAAqB,OAAO,EAAE;IAClC,IAAI,CAACF,MAAM,OAAO,CAACE,QACjB,MAAM,IAAID,UAAU;IAEtB,OAAOC,MAAM,GAAG,CAAC,CAACC,MAAMC;QACtB,IAAI,AAAgB,YAAhB,OAAOD,QAAqBA,AAAuB,MAAvBA,KAAK,IAAI,GAAG,MAAM,EAChD,MAAM,IAAIF,UACR,CAAC,0BAA0B,EAAEG,MAAM,6BAA6B,CAAC;QAGrE,IAAI,CAACC,WAAWF,OACd,MAAM,IAAIF,UACR,CAAC,0BAA0B,EAAEG,MAAM,2BAA2B,CAAC;QAGnE,OAAOD;IACT;AACF"}
File without changes