velocious 1.0.644 → 1.0.646

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 (259) hide show
  1. package/README.md +11 -9
  2. package/build/authorization/ability.js +36 -13
  3. package/build/background-jobs/adapter.js +9 -0
  4. package/build/background-jobs/main.js +35 -10
  5. package/build/background-jobs/store.js +217 -38
  6. package/build/background-jobs/types.js +15 -0
  7. package/build/configuration-types.js +1 -1
  8. package/build/configuration.js +45 -9
  9. package/build/database/drivers/base-column.js +8 -0
  10. package/build/database/drivers/mssql/sql/update.js +1 -3
  11. package/build/database/drivers/mysql/sql/update.js +1 -3
  12. package/build/database/drivers/pgsql/column.js +22 -0
  13. package/build/database/drivers/pgsql/sql/update.js +1 -3
  14. package/build/database/drivers/sqlite/sql/alter-table.js +11 -1
  15. package/build/database/drivers/sqlite/sql/update.js +1 -3
  16. package/build/database/query/index.js +2 -2
  17. package/build/database/query/model-class-query.js +26 -10
  18. package/build/database/query/preloader/has-many.js +4 -1
  19. package/build/database/query/query-data.js +2 -1
  20. package/build/database/query/update-base.js +14 -0
  21. package/build/database/query/with-count.js +3 -1
  22. package/build/database/record/acts-as-list.js +37 -13
  23. package/build/database/record/attachments/store.js +336 -26
  24. package/build/database/record/auditing.js +6 -3
  25. package/build/database/record/index.js +197 -42
  26. package/build/database/record/instance-relationships/belongs-to.js +2 -1
  27. package/build/database/record/validators/uniqueness.js +8 -5
  28. package/build/environment-handlers/node/cli/commands/generate/frontend-models.js +24 -8
  29. package/build/frontend-model-controller.js +136 -53
  30. package/build/frontend-model-resource/base-resource.js +87 -37
  31. package/build/frontend-model-resource/velocious-attachment-resource.js +98 -31
  32. package/build/frontend-models/base.js +307 -59
  33. package/build/frontend-models/preloader.js +6 -3
  34. package/build/frontend-models/query.js +15 -6
  35. package/build/frontend-models/resource-definition.js +21 -2
  36. package/build/frontend-models/use-destroyed-event.js +1 -1
  37. package/build/frontend-models/use-model-class-event.js +2 -2
  38. package/build/frontend-models/use-updated-event.js +1 -1
  39. package/build/frontend-models/websocket-channel.js +256 -93
  40. package/build/frontend-models/websocket-publishers.js +218 -18
  41. package/build/http-server/client/websocket-session.js +13 -1
  42. package/build/http-server/websocket-channel.js +15 -2
  43. package/build/src/authorization/ability.d.ts +9 -3
  44. package/build/src/authorization/ability.d.ts.map +1 -1
  45. package/build/src/authorization/ability.js +33 -14
  46. package/build/src/background-jobs/adapter.d.ts +6 -0
  47. package/build/src/background-jobs/adapter.d.ts.map +1 -1
  48. package/build/src/background-jobs/adapter.js +9 -1
  49. package/build/src/background-jobs/main.d.ts +6 -0
  50. package/build/src/background-jobs/main.d.ts.map +1 -1
  51. package/build/src/background-jobs/main.js +34 -11
  52. package/build/src/background-jobs/store.d.ts +66 -12
  53. package/build/src/background-jobs/store.d.ts.map +1 -1
  54. package/build/src/background-jobs/store.js +191 -35
  55. package/build/src/background-jobs/types.d.ts +55 -0
  56. package/build/src/background-jobs/types.d.ts.map +1 -1
  57. package/build/src/background-jobs/types.js +16 -1
  58. package/build/src/configuration-types.d.ts +3 -3
  59. package/build/src/configuration-types.d.ts.map +1 -1
  60. package/build/src/configuration-types.js +2 -2
  61. package/build/src/configuration.d.ts +18 -8
  62. package/build/src/configuration.d.ts.map +1 -1
  63. package/build/src/configuration.js +38 -7
  64. package/build/src/database/drivers/base-column.d.ts +5 -0
  65. package/build/src/database/drivers/base-column.d.ts.map +1 -1
  66. package/build/src/database/drivers/base-column.js +8 -1
  67. package/build/src/database/drivers/mssql/sql/update.d.ts.map +1 -1
  68. package/build/src/database/drivers/mssql/sql/update.js +2 -4
  69. package/build/src/database/drivers/mysql/sql/update.d.ts.map +1 -1
  70. package/build/src/database/drivers/mysql/sql/update.js +2 -4
  71. package/build/src/database/drivers/pgsql/column.d.ts +5 -0
  72. package/build/src/database/drivers/pgsql/column.d.ts.map +1 -1
  73. package/build/src/database/drivers/pgsql/column.js +19 -1
  74. package/build/src/database/drivers/pgsql/sql/update.d.ts.map +1 -1
  75. package/build/src/database/drivers/pgsql/sql/update.js +2 -4
  76. package/build/src/database/drivers/sqlite/sql/alter-table.d.ts.map +1 -1
  77. package/build/src/database/drivers/sqlite/sql/alter-table.js +6 -2
  78. package/build/src/database/drivers/sqlite/sql/update.d.ts.map +1 -1
  79. package/build/src/database/drivers/sqlite/sql/update.js +2 -4
  80. package/build/src/database/query/index.d.ts +4 -4
  81. package/build/src/database/query/index.d.ts.map +1 -1
  82. package/build/src/database/query/index.js +3 -3
  83. package/build/src/database/query/model-class-query.d.ts +8 -2
  84. package/build/src/database/query/model-class-query.d.ts.map +1 -1
  85. package/build/src/database/query/model-class-query.js +25 -11
  86. package/build/src/database/query/preloader/has-many.d.ts.map +1 -1
  87. package/build/src/database/query/preloader/has-many.js +4 -2
  88. package/build/src/database/query/query-data.d.ts.map +1 -1
  89. package/build/src/database/query/query-data.js +3 -2
  90. package/build/src/database/query/update-base.d.ts +7 -0
  91. package/build/src/database/query/update-base.d.ts.map +1 -1
  92. package/build/src/database/query/update-base.js +13 -1
  93. package/build/src/database/query/with-count.d.ts.map +1 -1
  94. package/build/src/database/query/with-count.js +3 -2
  95. package/build/src/database/record/acts-as-list.d.ts.map +1 -1
  96. package/build/src/database/record/acts-as-list.js +35 -14
  97. package/build/src/database/record/attachments/store.d.ts +67 -0
  98. package/build/src/database/record/attachments/store.d.ts.map +1 -1
  99. package/build/src/database/record/attachments/store.js +301 -25
  100. package/build/src/database/record/auditing.d.ts.map +1 -1
  101. package/build/src/database/record/auditing.js +7 -4
  102. package/build/src/database/record/index.d.ts +78 -26
  103. package/build/src/database/record/index.d.ts.map +1 -1
  104. package/build/src/database/record/index.js +171 -42
  105. package/build/src/database/record/instance-relationships/belongs-to.d.ts.map +1 -1
  106. package/build/src/database/record/instance-relationships/belongs-to.js +3 -2
  107. package/build/src/database/record/validators/uniqueness.d.ts.map +1 -1
  108. package/build/src/database/record/validators/uniqueness.js +8 -6
  109. package/build/src/environment-handlers/node/cli/commands/generate/frontend-models.d.ts +4 -4
  110. package/build/src/environment-handlers/node/cli/commands/generate/frontend-models.d.ts.map +1 -1
  111. package/build/src/environment-handlers/node/cli/commands/generate/frontend-models.js +24 -12
  112. package/build/src/frontend-model-controller.d.ts +29 -8
  113. package/build/src/frontend-model-controller.d.ts.map +1 -1
  114. package/build/src/frontend-model-controller.js +122 -51
  115. package/build/src/frontend-model-resource/base-resource.d.ts +51 -24
  116. package/build/src/frontend-model-resource/base-resource.d.ts.map +1 -1
  117. package/build/src/frontend-model-resource/base-resource.js +83 -37
  118. package/build/src/frontend-model-resource/velocious-attachment-resource.d.ts +45 -26
  119. package/build/src/frontend-model-resource/velocious-attachment-resource.d.ts.map +1 -1
  120. package/build/src/frontend-model-resource/velocious-attachment-resource.js +89 -31
  121. package/build/src/frontend-models/base.d.ts +53 -20
  122. package/build/src/frontend-models/base.d.ts.map +1 -1
  123. package/build/src/frontend-models/base.js +275 -59
  124. package/build/src/frontend-models/preloader.d.ts.map +1 -1
  125. package/build/src/frontend-models/preloader.js +6 -4
  126. package/build/src/frontend-models/query.d.ts +2 -2
  127. package/build/src/frontend-models/query.d.ts.map +1 -1
  128. package/build/src/frontend-models/query.js +14 -7
  129. package/build/src/frontend-models/resource-definition.d.ts.map +1 -1
  130. package/build/src/frontend-models/resource-definition.js +20 -3
  131. package/build/src/frontend-models/use-destroyed-event.d.ts +1 -1
  132. package/build/src/frontend-models/use-destroyed-event.d.ts.map +1 -1
  133. package/build/src/frontend-models/use-destroyed-event.js +2 -2
  134. package/build/src/frontend-models/use-model-class-event.d.ts +2 -2
  135. package/build/src/frontend-models/use-model-class-event.d.ts.map +1 -1
  136. package/build/src/frontend-models/use-model-class-event.js +3 -3
  137. package/build/src/frontend-models/use-updated-event.d.ts +1 -1
  138. package/build/src/frontend-models/use-updated-event.d.ts.map +1 -1
  139. package/build/src/frontend-models/use-updated-event.js +2 -2
  140. package/build/src/frontend-models/websocket-channel.d.ts +60 -41
  141. package/build/src/frontend-models/websocket-channel.d.ts.map +1 -1
  142. package/build/src/frontend-models/websocket-channel.js +225 -85
  143. package/build/src/frontend-models/websocket-publishers.d.ts +9 -0
  144. package/build/src/frontend-models/websocket-publishers.d.ts.map +1 -1
  145. package/build/src/frontend-models/websocket-publishers.js +190 -19
  146. package/build/src/http-server/client/websocket-session.d.ts.map +1 -1
  147. package/build/src/http-server/client/websocket-session.js +11 -2
  148. package/build/src/http-server/websocket-channel.d.ts +20 -8
  149. package/build/src/http-server/websocket-channel.d.ts.map +1 -1
  150. package/build/src/http-server/websocket-channel.js +15 -3
  151. package/build/src/sync/sync-api-client.d.ts.map +1 -1
  152. package/build/src/sync/sync-api-client.js +4 -3
  153. package/build/src/sync/sync-client.d.ts.map +1 -1
  154. package/build/src/sync/sync-client.js +3 -2
  155. package/build/src/sync/sync-envelope-replay-service.d.ts.map +1 -1
  156. package/build/src/sync/sync-envelope-replay-service.js +6 -5
  157. package/build/src/sync/sync-publisher.d.ts.map +1 -1
  158. package/build/src/sync/sync-publisher.js +4 -3
  159. package/build/src/testing/browser-frontend-model-event-hook-scenarios.d.ts +2 -2
  160. package/build/src/testing/browser-frontend-model-event-hook-scenarios.d.ts.map +1 -1
  161. package/build/src/testing/browser-frontend-model-event-hook-scenarios.js +3 -3
  162. package/build/src/testing/test-profiler.d.ts +4 -4
  163. package/build/src/testing/test-profiler.d.ts.map +1 -1
  164. package/build/src/testing/test-profiler.js +3 -3
  165. package/build/src/testing/test-runner.d.ts +271 -117
  166. package/build/src/testing/test-runner.d.ts.map +1 -1
  167. package/build/src/testing/test-runner.js +496 -427
  168. package/build/src/testing/test.d.ts +11 -72
  169. package/build/src/testing/test.d.ts.map +1 -1
  170. package/build/src/testing/test.js +131 -284
  171. package/build/src/testing/velocious-attempt-executor.d.ts +14 -29
  172. package/build/src/testing/velocious-attempt-executor.d.ts.map +1 -1
  173. package/build/src/testing/velocious-attempt-executor.js +52 -46
  174. package/build/src/testing/velocious-runner-reporter.d.ts +29 -34
  175. package/build/src/testing/velocious-runner-reporter.d.ts.map +1 -1
  176. package/build/src/testing/velocious-runner-reporter.js +145 -57
  177. package/build/src/testing/velocious-suite-hook-executor.d.ts +5 -23
  178. package/build/src/testing/velocious-suite-hook-executor.d.ts.map +1 -1
  179. package/build/src/testing/velocious-suite-hook-executor.js +22 -47
  180. package/build/src/testing/velocious-test-arguments.d.ts +11 -6
  181. package/build/src/testing/velocious-test-arguments.d.ts.map +1 -1
  182. package/build/src/testing/velocious-test-arguments.js +18 -10
  183. package/build/src/utils/model-primary-key.d.ts +73 -0
  184. package/build/src/utils/model-primary-key.d.ts.map +1 -0
  185. package/build/src/utils/model-primary-key.js +144 -0
  186. package/build/sync/sync-api-client.js +3 -2
  187. package/build/sync/sync-client.js +2 -1
  188. package/build/sync/sync-envelope-replay-service.js +5 -4
  189. package/build/sync/sync-publisher.js +3 -2
  190. package/build/testing/browser-frontend-model-event-hook-scenarios.js +2 -2
  191. package/build/testing/test-profiler.js +2 -2
  192. package/build/testing/test-runner.js +493 -449
  193. package/build/testing/test.js +164 -306
  194. package/build/testing/velocious-attempt-executor.js +55 -45
  195. package/build/testing/velocious-runner-reporter.js +156 -58
  196. package/build/testing/velocious-suite-hook-executor.js +22 -50
  197. package/build/testing/velocious-test-arguments.js +19 -10
  198. package/build/utils/model-primary-key.js +171 -0
  199. package/package.json +6 -5
  200. package/src/authorization/ability.js +36 -13
  201. package/src/background-jobs/adapter.js +9 -0
  202. package/src/background-jobs/main.js +35 -10
  203. package/src/background-jobs/store.js +217 -38
  204. package/src/background-jobs/types.js +15 -0
  205. package/src/configuration-types.js +1 -1
  206. package/src/configuration.js +45 -9
  207. package/src/database/drivers/base-column.js +8 -0
  208. package/src/database/drivers/mssql/sql/update.js +1 -3
  209. package/src/database/drivers/mysql/sql/update.js +1 -3
  210. package/src/database/drivers/pgsql/column.js +22 -0
  211. package/src/database/drivers/pgsql/sql/update.js +1 -3
  212. package/src/database/drivers/sqlite/sql/alter-table.js +11 -1
  213. package/src/database/drivers/sqlite/sql/update.js +1 -3
  214. package/src/database/query/index.js +2 -2
  215. package/src/database/query/model-class-query.js +26 -10
  216. package/src/database/query/preloader/has-many.js +4 -1
  217. package/src/database/query/query-data.js +2 -1
  218. package/src/database/query/update-base.js +14 -0
  219. package/src/database/query/with-count.js +3 -1
  220. package/src/database/record/acts-as-list.js +37 -13
  221. package/src/database/record/attachments/store.js +336 -26
  222. package/src/database/record/auditing.js +6 -3
  223. package/src/database/record/index.js +197 -42
  224. package/src/database/record/instance-relationships/belongs-to.js +2 -1
  225. package/src/database/record/validators/uniqueness.js +8 -5
  226. package/src/environment-handlers/node/cli/commands/generate/frontend-models.js +24 -8
  227. package/src/frontend-model-controller.js +136 -53
  228. package/src/frontend-model-resource/base-resource.js +87 -37
  229. package/src/frontend-model-resource/velocious-attachment-resource.js +98 -31
  230. package/src/frontend-models/base.js +307 -59
  231. package/src/frontend-models/preloader.js +6 -3
  232. package/src/frontend-models/query.js +15 -6
  233. package/src/frontend-models/resource-definition.js +21 -2
  234. package/src/frontend-models/use-destroyed-event.js +1 -1
  235. package/src/frontend-models/use-model-class-event.js +2 -2
  236. package/src/frontend-models/use-updated-event.js +1 -1
  237. package/src/frontend-models/websocket-channel.js +256 -93
  238. package/src/frontend-models/websocket-publishers.js +218 -18
  239. package/src/http-server/client/websocket-session.js +13 -1
  240. package/src/http-server/websocket-channel.js +15 -2
  241. package/src/sync/sync-api-client.js +3 -2
  242. package/src/sync/sync-client.js +2 -1
  243. package/src/sync/sync-envelope-replay-service.js +5 -4
  244. package/src/sync/sync-publisher.js +3 -2
  245. package/src/testing/browser-frontend-model-event-hook-scenarios.js +2 -2
  246. package/src/testing/test-profiler.js +2 -2
  247. package/src/testing/test-runner.js +493 -449
  248. package/src/testing/test.js +164 -306
  249. package/src/testing/velocious-attempt-executor.js +55 -45
  250. package/src/testing/velocious-runner-reporter.js +156 -58
  251. package/src/testing/velocious-suite-hook-executor.js +22 -50
  252. package/src/testing/velocious-test-arguments.js +19 -10
  253. package/src/utils/model-primary-key.js +171 -0
  254. package/build/src/testing/testing-package-adapter.d.ts +0 -9
  255. package/build/src/testing/testing-package-adapter.d.ts.map +0 -1
  256. package/build/src/testing/testing-package-adapter.js +0 -69
  257. package/build/testing/testing-package-adapter.js +0 -76
  258. package/build/tsconfig.tsbuildinfo +0 -1
  259. package/src/testing/testing-package-adapter.js +0 -76
@@ -3,7 +3,9 @@
3
3
  import { TestDatabaseAccessRevokedError } from "../environment-handlers/base.js"
4
4
  import { clearDeliveries } from "../mailer.js"
5
5
  import restArgsError from "../utils/rest-args-error.js"
6
- import { testConfig } from "./test.js"
6
+ import {clearTimeout as realClearTimeout, setTimeout as realSetTimeout} from "node:timers"
7
+
8
+ /** @typedef {import("@velocious/testing/runner").AttemptExecutorInput["beforeEach"][number]} PackageHookDeclaration */
7
9
 
8
10
  /**
9
11
  * Marks one whole-lifecycle timeout while its underlying promise keeps running.
@@ -24,13 +26,13 @@ function runWithTimeout(promise, timeoutMs, testDescription) {
24
26
  timeoutError.velociousTestTimeout = true
25
27
 
26
28
  return new Promise((resolve, reject) => {
27
- const timeout = setTimeout(() => reject(timeoutError), timeoutMs)
29
+ const timeout = realSetTimeout(() => reject(timeoutError), timeoutMs)
28
30
 
29
31
  Promise.resolve(promise).then((result) => {
30
- clearTimeout(timeout)
32
+ realClearTimeout(timeout)
31
33
  resolve(result)
32
34
  }).catch((error) => {
33
- clearTimeout(timeout)
35
+ realClearTimeout(timeout)
34
36
  reject(error)
35
37
  })
36
38
  })
@@ -45,7 +47,7 @@ function runWithTimeout(promise, timeoutMs, testDescription) {
45
47
  function awaitSettledOrGrace(lifecycle, graceMs) {
46
48
  return new Promise((resolve) => {
47
49
  let settled = false
48
- const graceTimer = setTimeout(() => {
50
+ const graceTimer = realSetTimeout(() => {
49
51
  if (settled) return
50
52
 
51
53
  settled = true
@@ -57,14 +59,14 @@ function awaitSettledOrGrace(lifecycle, graceMs) {
57
59
  if (settled) return
58
60
 
59
61
  settled = true
60
- clearTimeout(graceTimer)
62
+ realClearTimeout(graceTimer)
61
63
  resolve({settled: true, status: "fulfilled"})
62
64
  },
63
65
  (reason) => {
64
66
  if (settled) return
65
67
 
66
68
  settled = true
67
- clearTimeout(graceTimer)
69
+ realClearTimeout(graceTimer)
68
70
  resolve({settled: true, status: "rejected", reason})
69
71
  }
70
72
  )
@@ -96,22 +98,31 @@ export default class VelociousAttemptExecutor {
96
98
  this.testRunner = testRunner
97
99
  }
98
100
 
101
+ /**
102
+ * Normalizes the legacy timeout contract at the framework adapter boundary.
103
+ * @param {number | undefined} timeoutMs - Declared package timeout.
104
+ * @returns {number | undefined} - Positive finite timeout, or no timeout.
105
+ */
106
+ normalizeTimeoutMs(timeoutMs) {
107
+ return typeof timeoutMs === "number" && Number.isFinite(timeoutMs) && timeoutMs > 0 ? timeoutMs : undefined
108
+ }
109
+
99
110
  /**
100
111
  * Executes exactly one complete Velocious-owned test attempt.
101
- * @param {object} args - Attempt arguments.
102
- * @param {import("./test-runner.js").AfterBeforeEachCallbackObjectType[]} args.afterEaches - Cleanup hooks.
103
- * @param {number} args.attemptNumber - One-based attempt number.
104
- * @param {import("./test-runner.js").AfterBeforeEachCallbackObjectType[]} args.beforeEaches - Setup hooks.
105
- * @param {string[]} args.descriptions - Parent descriptions.
106
- * @param {import("./velocious-test-arguments.js").TestArgs} args.testArgs - Stable test arguments.
107
- * @param {import("./velocious-test-arguments.js").TestData} args.testData - Test registration.
108
- * @param {string} args.testDescription - Test description.
109
- * @param {number} [args.timeoutMs] - Whole-lifecycle timeout.
110
- * @returns {Promise<{abortRemainingTests: boolean, consoleOutput: string, error: ReturnType<typeof JSON.parse>, failed: boolean}>} - Attempt outcome.
112
+ * @param {import("@velocious/testing/runner").AttemptExecutorInput} input - Package attempt.
113
+ * @returns {Promise<void>} - Resolves after one complete framework attempt.
111
114
  */
112
- async execute({afterEaches, attemptNumber, beforeEaches, descriptions, testArgs, testData, testDescription, timeoutMs, ...restArgs}) {
115
+ async execute({afterEach, args, attemptNumber, beforeEach, context, defaultExecute, fullName, suite, test, timeoutMs, ...restArgs}) {
113
116
  restArgsError(restArgs)
117
+ void context
118
+ void defaultExecute
119
+ void suite
114
120
  const testRunner = this.testRunner
121
+ const effectiveTimeoutMs = this.normalizeTimeoutMs(timeoutMs)
122
+ const compatibility = await testRunner.testCompatibility(test)
123
+ const {testArgs, testData} = compatibility
124
+ const metadata = testRunner.testMetadata(test)
125
+ const {descriptions, testDescription} = metadata
115
126
  /** @type {ReturnType<typeof JSON.parse>} */
116
127
  let caughtError
117
128
  let failed = false
@@ -133,14 +144,9 @@ export default class VelociousAttemptExecutor {
133
144
  const recordedTimeoutCleanupErrors = new Set()
134
145
  let abortRemainingTests = false
135
146
  let attemptTimedOut = false
136
- /** @type {string} */
137
- let consoleOutput
138
147
  testArgs.registerTransactionalTenant = async (args) => {
139
148
  await testRunner.registerTransactionalTenant(args, transactionalTenantRegistrations)
140
149
  }
141
- const stopConsoleCapture = testRunner.startConsoleCapture({
142
- passthrough: testConfig.consoleOutput === "live"
143
- })
144
150
  const profiler = testRunner._profiler
145
151
  const profileAttempt = profiler?.startAttempt({
146
152
  descriptions,
@@ -171,7 +177,7 @@ export default class VelociousAttemptExecutor {
171
177
  runCleanupHooks = true
172
178
 
173
179
  clearDeliveries()
174
- await this.runBeforeEaches({beforeEaches, testArgs, testData})
180
+ await this.runBeforeEaches({beforeEaches: beforeEach, testArgs, testData})
175
181
 
176
182
  if (useSharedTestConnections) {
177
183
  const activeConnections = testRunner.sharedTransactionConnections({transactionsOnly: true})
@@ -190,12 +196,12 @@ export default class VelociousAttemptExecutor {
190
196
  }
191
197
 
192
198
  testRunner._lastTestContext = {
193
- fullDescription: testRunner.buildFullDescription(descriptions, testDescription),
199
+ fullDescription: fullName,
194
200
  filePath: testData.filePath ?? "<unknown>",
195
201
  line: testData.line ?? 0
196
202
  }
197
203
  await testRunner.runProfileSpan({phase: "test body", filePath: testData.ownerFilePath ?? testData.filePath}, async () => {
198
- await testData.function(testArgs)
204
+ await test.callback(...args)
199
205
  })
200
206
  } catch (error) {
201
207
  lifecycleErrors.push(error)
@@ -227,7 +233,7 @@ export default class VelociousAttemptExecutor {
227
233
  }
228
234
 
229
235
  try {
230
- await this.runAfterEaches({afterEaches, testArgs, testData})
236
+ await this.runAfterEaches({afterEaches: [...afterEach].reverse(), testArgs, testData})
231
237
  } catch (error) {
232
238
  lifecycleErrors.push(error)
233
239
  }
@@ -265,8 +271,8 @@ export default class VelociousAttemptExecutor {
265
271
  ? profiler.runAttempt(profileAttempt, lifecycleCallback)
266
272
  : lifecycleCallback()
267
273
 
268
- if (timeoutMs !== undefined) {
269
- await runWithTimeout(testLifecycle, timeoutMs, testDescription)
274
+ if (effectiveTimeoutMs !== undefined) {
275
+ await runWithTimeout(testLifecycle, effectiveTimeoutMs, testDescription)
270
276
  } else {
271
277
  await testLifecycle
272
278
  }
@@ -280,7 +286,7 @@ export default class VelociousAttemptExecutor {
280
286
  const emergencyCleanupErrors = []
281
287
 
282
288
  if (profileAttempt && profiler) profiler.finishAttempt(profileAttempt, "timed-out")
283
- const lifecycleOutcome = await awaitSettledOrGrace(testLifecycle, timeoutMs ?? 60000)
289
+ const lifecycleOutcome = await awaitSettledOrGrace(testLifecycle, effectiveTimeoutMs ?? 60000)
284
290
 
285
291
  if (lifecycleOutcome.settled && lifecycleOutcome.status === "rejected") {
286
292
  emergencyCleanupErrors.push(lifecycleOutcome.reason)
@@ -293,7 +299,7 @@ export default class VelociousAttemptExecutor {
293
299
  testRunner.recordTimeoutCleanupFailure(cleanupError, "test lifecycle", recordedTimeoutCleanupErrors)
294
300
  })
295
301
  const quarantine = testRunner.quarantineBrowserDummyConnections(browserDummyConnectionRegistrations)
296
- const quarantineOutcome = await awaitSettledOrGrace(quarantine, timeoutMs ?? 60000)
302
+ const quarantineOutcome = await awaitSettledOrGrace(quarantine, effectiveTimeoutMs ?? 60000)
297
303
  const usesBrowserTransactions = testArgs.databaseCleaning?.transaction === true
298
304
  const usesBrowserTruncation = testArgs.databaseCleaning?.truncate ?? !usesBrowserTransactions
299
305
 
@@ -321,7 +327,7 @@ export default class VelociousAttemptExecutor {
321
327
  }
322
328
 
323
329
  const brokerCleanup = testRunner.stopSharedTransactionBroker(sharedTransactionBrokerRegistration || sharedTransactionBrokerPreparation)
324
- const brokerCleanupOutcome = await awaitSettledOrGrace(brokerCleanup, timeoutMs ?? 60000)
330
+ const brokerCleanupOutcome = await awaitSettledOrGrace(brokerCleanup, effectiveTimeoutMs ?? 60000)
325
331
 
326
332
  if (brokerCleanupOutcome.settled && brokerCleanupOutcome.status === "rejected") {
327
333
  emergencyCleanupErrors.push(brokerCleanupOutcome.reason)
@@ -333,7 +339,7 @@ export default class VelociousAttemptExecutor {
333
339
  sharedTransactionBrokerRegistration = undefined
334
340
  sharedTransactionBrokerPreparation = undefined
335
341
  const emergencyCleanup = testRunner.cleanupTransactionalTenants(transactionalTenantRegistrations, {discard: true})
336
- const emergencyCleanupOutcome = await awaitSettledOrGrace(emergencyCleanup, timeoutMs ?? 60000)
342
+ const emergencyCleanupOutcome = await awaitSettledOrGrace(emergencyCleanup, effectiveTimeoutMs ?? 60000)
337
343
 
338
344
  if (emergencyCleanupOutcome.settled && emergencyCleanupOutcome.status === "rejected") {
339
345
  emergencyCleanupErrors.push(emergencyCleanupOutcome.reason)
@@ -358,7 +364,6 @@ export default class VelociousAttemptExecutor {
358
364
  }
359
365
  } finally {
360
366
  testDatabaseAccessScope.revoked = true
361
- consoleOutput = stopConsoleCapture()
362
367
 
363
368
  if (profileAttempt && profiler) {
364
369
  profiler.finishAttempt(profileAttempt, failed
@@ -367,29 +372,32 @@ export default class VelociousAttemptExecutor {
367
372
  }
368
373
  }
369
374
 
370
- return {
375
+ testRunner.recordAttemptOutcome(test, attemptNumber, {
371
376
  abortRemainingTests,
372
- consoleOutput,
373
377
  error: caughtError,
374
378
  failed
375
- }
379
+ })
380
+
381
+ if (failed) throw caughtError
376
382
  }
377
383
 
378
384
  /**
379
385
  * Runs before-each hooks in inherited declaration order.
380
386
  * @param {object} args - Hook arguments.
381
- * @param {import("./test-runner.js").AfterBeforeEachCallbackObjectType[]} args.beforeEaches - Setup hooks.
387
+ * @param {PackageHookDeclaration[]} args.beforeEaches - Setup hooks.
382
388
  * @param {import("./velocious-test-arguments.js").TestArgs} args.testArgs - Stable test arguments.
383
389
  * @param {import("./velocious-test-arguments.js").TestData} args.testData - Test registration.
384
390
  * @returns {Promise<void>} - Resolves after all setup hooks complete.
385
391
  */
386
392
  async runBeforeEaches({beforeEaches, testArgs, testData}) {
387
393
  for (const hook of beforeEaches) {
394
+ const metadata = this.testRunner.hookMetadata(hook)
395
+
388
396
  await this.testRunner.runProfileSpan({
389
397
  phase: "beforeEach",
390
- declarationIndex: hook.declarationIndex,
391
- declarationScopeId: hook.declarationScopeId,
392
- filePath: hook.ownerFilePath
398
+ declarationIndex: metadata.declarationIndex,
399
+ declarationScopeId: metadata.declarationScopeId,
400
+ filePath: metadata.ownerFilePath
393
401
  }, async () => {
394
402
  await hook.callback({configuration: this.testRunner.getConfiguration(), testArgs, testData})
395
403
  })
@@ -399,7 +407,7 @@ export default class VelociousAttemptExecutor {
399
407
  /**
400
408
  * Runs every after-each hook while preserving all failures.
401
409
  * @param {object} args - Hook arguments.
402
- * @param {import("./test-runner.js").AfterBeforeEachCallbackObjectType[]} args.afterEaches - Cleanup hooks.
410
+ * @param {PackageHookDeclaration[]} args.afterEaches - Cleanup hooks.
403
411
  * @param {import("./velocious-test-arguments.js").TestArgs} args.testArgs - Stable test arguments.
404
412
  * @param {import("./velocious-test-arguments.js").TestData} args.testData - Test registration.
405
413
  * @returns {Promise<void>} - Resolves after every cleanup hook settles.
@@ -409,12 +417,14 @@ export default class VelociousAttemptExecutor {
409
417
  const errors = []
410
418
 
411
419
  for (const hook of afterEaches) {
420
+ const metadata = this.testRunner.hookMetadata(hook)
421
+
412
422
  try {
413
423
  await this.testRunner.runProfileSpan({
414
424
  phase: "afterEach",
415
- declarationIndex: hook.declarationIndex,
416
- declarationScopeId: hook.declarationScopeId,
417
- filePath: hook.ownerFilePath
425
+ declarationIndex: metadata.declarationIndex,
426
+ declarationScopeId: metadata.declarationScopeId,
427
+ filePath: metadata.ownerFilePath
418
428
  }, async () => {
419
429
  await hook.callback({configuration: this.testRunner.getConfiguration(), testArgs, testData})
420
430
  })
@@ -6,6 +6,11 @@ import picocolors from "picocolors"
6
6
  import restArgsError from "../utils/rest-args-error.js"
7
7
  import { testEvents } from "./test.js"
8
8
 
9
+ /** @typedef {import("@velocious/testing/runner").TestDeclaration} PackageTestDeclaration */
10
+
11
+ /** Stops package traversal after framework-owned connection quarantine. */
12
+ export class AbortRemainingTestsError extends Error {}
13
+
9
14
  export default class VelociousRunnerReporter {
10
15
  /**
11
16
  * Creates the legacy event and result projection adapter.
@@ -15,83 +20,189 @@ export default class VelociousRunnerReporter {
15
20
  constructor({testRunner, ...restArgs}) {
16
21
  restArgsError(restArgs)
17
22
  this.testRunner = testRunner
23
+ /** @type {WeakMap<PackageTestDeclaration, import("./test-runner.js").AttemptConsoleOutput[]>} */
24
+ this.attemptConsoleOutputs = new WeakMap()
25
+ /** @type {PackageTestDeclaration | undefined} */
26
+ this.activeTest = undefined
18
27
  }
19
28
 
20
29
  /**
21
- * Projects one completed attempt into legacy events and final result accounting.
22
- * Retry eligibility is decided by the caller before this method runs.
23
- * @param {object} args - Completed attempt and retry metadata.
24
- * @param {import("./test-runner.js").AttemptConsoleOutput[]} args.attemptConsoleOutputs - Captured output across attempts.
25
- * @param {number} args.attemptNumber - Current one-based attempt.
26
- * @param {string[]} args.descriptions - Parent description stack.
27
- * @param {ReturnType<typeof JSON.parse>} args.error - Raw thrown or rejected value.
28
- * @param {boolean} args.failed - Whether the attempt failed, independently of error truthiness.
29
- * @param {string} args.leftPadding - Console indentation.
30
- * @param {number} args.retriesUsed - Retry count consumed after this attempt.
31
- * @param {number} args.retryCount - Configured retry limit.
32
- * @param {import("./velocious-test-arguments.js").TestArgs} args.testArgs - Stable test arguments.
33
- * @param {import("./velocious-test-arguments.js").TestData} args.testData - Test registration.
34
- * @param {string} args.testDescription - Test description.
35
- * @param {boolean} args.willRetry - Whether the legacy loop will run another attempt.
36
- * @returns {Promise<void>} - Resolves after all legacy listeners complete.
30
+ * Translates one awaited package runner event into the legacy contract.
31
+ * @param {import("@velocious/testing/runner").RunnerEvent} event - Structured package event.
32
+ * @returns {Promise<void>} - Resolves after legacy listeners finish.
37
33
  */
38
- async reportAttempt({attemptConsoleOutputs, attemptNumber, descriptions, error, failed, leftPadding, retriesUsed, retryCount, testArgs, testData, testDescription, willRetry, ...restArgs}) {
39
- restArgsError(restArgs)
40
- const testRunner = this.testRunner
34
+ async onEvent(event) {
35
+ if (event.type === "test:start") {
36
+ this.activeTest = this.testRunner.findTestDeclaration(event.fullName)
37
+ if (this.activeTest) {
38
+ const metadata = this.testRunner.testMetadata(this.activeTest)
39
+ console.log(`${" ".repeat(metadata.descriptions.length * 2)}it ${metadata.testDescription}`)
40
+ }
41
+ return
42
+ }
43
+
44
+ if (event.type === "attempt:finish") {
45
+ await this.reportAttemptEvent(event)
46
+ return
47
+ }
41
48
 
42
- if (!failed) testRunner._successfulTests++
49
+ if (event.type === "test:finish") {
50
+ await this.reportTestEvent(event)
51
+ return
52
+ }
53
+
54
+ if (event.type === "run:finish") this.testRunner.recordPackageResult(event.result)
55
+ }
56
+
57
+ /**
58
+ * Projects attempt failure/retry events while retaining the raw thrown value.
59
+ * @param {import("@velocious/testing/runner").RunnerEvent} event - Attempt event.
60
+ * @returns {Promise<void>} - Resolves after listeners finish.
61
+ */
62
+ async reportAttemptEvent(event) {
63
+ const test = this.activeTest || this.testRunner.findTestDeclaration(event.fullName)
64
+
65
+ if (!test) throw new Error(`Package runner attempt did not match a declaration: ${event.fullName}`)
66
+
67
+ // Narrows the structured event payload for this event discriminator.
68
+ const attempt = /** @type {import("@velocious/testing/runner").TestAttemptResult} */ (event.attempt)
69
+ const outcome = this.testRunner.attemptOutcome(test, attempt.attemptNumber)
70
+ const attemptConsoleOutputs = this.attemptConsoleOutputs.get(test) || []
71
+
72
+ if (attempt.consoleOutput) {
73
+ attemptConsoleOutputs.push({attemptNumber: attempt.attemptNumber, output: attempt.consoleOutput.trimEnd()})
74
+ this.attemptConsoleOutputs.set(test, attemptConsoleOutputs)
75
+ }
76
+
77
+ const retryCount = this.testRunner.retryCount(test)
78
+ const failed = outcome?.failed ?? Boolean(attempt.error)
79
+ const error = outcome?.error
80
+ const retriesUsed = Math.min(attempt.attemptNumber, retryCount)
81
+ const willRetry = failed && !outcome?.abortRemainingTests && attempt.attemptNumber <= retryCount
82
+ const {descriptions, testDescription} = this.testRunner.testMetadata(test)
83
+ const compatibility = this.testRunner.testData(test)
43
84
 
44
85
  if (failed) {
45
86
  await this.emitEvent("testAttemptFailed", {
46
- configuration: testRunner.getConfiguration(),
87
+ configuration: this.testRunner.getConfiguration(),
47
88
  descriptions,
48
89
  error,
49
- attemptNumber,
50
- nextAttempt: willRetry ? attemptNumber + 1 : undefined,
90
+ attemptNumber: attempt.attemptNumber,
91
+ nextAttempt: willRetry ? attempt.attemptNumber + 1 : undefined,
51
92
  retriesUsed,
52
93
  retryCount,
53
- testArgs,
54
- testData,
94
+ testArgs: compatibility.testArgs,
95
+ testData: compatibility.testData,
55
96
  testDescription,
56
- testRunner,
97
+ testRunner: this.testRunner,
57
98
  willRetry
58
99
  })
59
100
  }
60
101
 
61
102
  if (willRetry) {
62
- console.warn(picocolors.red(`${leftPadding} Retrying (${retriesUsed}/${retryCount}) after error: ${error instanceof Error ? error.message : String(error)}`))
103
+ console.warn(picocolors.red(`${" ".repeat(descriptions.length * 2)} Retrying (${retriesUsed}/${retryCount}) after error: ${error instanceof Error ? error.message : String(error)}`))
63
104
  await this.emitEvent("testRetrying", {
64
- configuration: testRunner.getConfiguration(),
105
+ configuration: this.testRunner.getConfiguration(),
65
106
  descriptions,
66
107
  error,
67
- nextAttempt: attemptNumber + 1,
108
+ nextAttempt: attempt.attemptNumber + 1,
68
109
  retriesUsed,
69
110
  retryCount,
70
- testArgs,
71
- testData,
111
+ testArgs: compatibility.testArgs,
112
+ testData: compatibility.testData,
72
113
  testDescription,
73
- testRunner
114
+ testRunner: this.testRunner
74
115
  })
75
116
  }
76
117
 
77
- if (attemptNumber > 1) {
118
+ if (attempt.attemptNumber > 1) {
78
119
  await this.emitEvent("testRetried", {
79
- configuration: testRunner.getConfiguration(),
120
+ configuration: this.testRunner.getConfiguration(),
80
121
  descriptions,
81
122
  error,
82
- attemptNumber,
123
+ attemptNumber: attempt.attemptNumber,
83
124
  retriesUsed,
84
125
  retryCount,
85
- testArgs,
86
- testData,
126
+ testArgs: compatibility.testArgs,
127
+ testData: compatibility.testData,
87
128
  testDescription,
88
- testRunner
129
+ testRunner: this.testRunner
130
+ })
131
+ }
132
+
133
+ if (outcome?.abortRemainingTests) {
134
+ const metadata = this.testRunner.testMetadata(test)
135
+
136
+ this.testRunner.recordTestDuration({
137
+ durationMs: attempt.durationMs,
138
+ filePath: compatibility.testData.filePath ?? "<unknown>",
139
+ fullDescription: metadata.fullDescription,
140
+ line: compatibility.testData.line ?? 0
141
+ })
142
+ await this.reportFailedTest({
143
+ attemptConsoleOutputs,
144
+ descriptions,
145
+ error,
146
+ leftPadding: " ".repeat(descriptions.length * 2),
147
+ testArgs: compatibility.testArgs,
148
+ testData: compatibility.testData,
149
+ testDescription
150
+ })
151
+ this.testRunner.completeTestDeclaration(test)
152
+ this.activeTest = undefined
153
+ throw new AbortRemainingTestsError("Velocious quarantined an attempt-owned database connection")
154
+ }
155
+ }
156
+
157
+ /**
158
+ * Projects final package result accounting and failures.
159
+ * @param {import("@velocious/testing/runner").RunnerEvent} event - Test result event.
160
+ * @returns {Promise<void>} - Resolves after listeners finish.
161
+ */
162
+ async reportTestEvent(event) {
163
+ // Narrows the structured event payload for this event discriminator.
164
+ const packageTestResult = /** @type {import("@velocious/testing/runner").TestResult} */ (event.test)
165
+ const test = this.activeTest || this.testRunner.findTestDeclaration(packageTestResult.fullName)
166
+
167
+ if (!test) throw new Error(`Package runner result did not match a declaration: ${packageTestResult.fullName}`)
168
+
169
+ const metadata = this.testRunner.testMetadata(test)
170
+ const compatibility = this.testRunner.testData(test)
171
+ const durationMs = packageTestResult.attempts.reduce((total, attempt) => total + attempt.durationMs, 0)
172
+
173
+ if (packageTestResult.attempts.length > 0) {
174
+ this.testRunner.recordTestDuration({
175
+ durationMs,
176
+ filePath: compatibility.testData.filePath ?? "<unknown>",
177
+ fullDescription: metadata.fullDescription,
178
+ line: compatibility.testData.line ?? 0
89
179
  })
90
180
  }
91
181
 
92
- if (failed && !willRetry) {
93
- await this.reportFailedTest({attemptConsoleOutputs, descriptions, error, leftPadding, testArgs, testData, testDescription})
182
+ if (packageTestResult.status === "passed") {
183
+ this.testRunner.recordSuccessfulTest()
184
+ } else {
185
+ const finalAttempt = packageTestResult.attempts.at(-1)
186
+ const outcome = finalAttempt
187
+ ? this.testRunner.attemptOutcome(test, finalAttempt.attemptNumber)
188
+ : undefined
189
+ const error = outcome?.failed
190
+ ? outcome.error
191
+ : this.testRunner.setupFailureFor(test)
192
+
193
+ await this.reportFailedTest({
194
+ attemptConsoleOutputs: this.attemptConsoleOutputs.get(test) || [],
195
+ descriptions: metadata.descriptions,
196
+ error,
197
+ leftPadding: " ".repeat(metadata.descriptions.length * 2),
198
+ testArgs: compatibility.testArgs,
199
+ testData: compatibility.testData,
200
+ testDescription: metadata.testDescription
201
+ })
94
202
  }
203
+
204
+ this.testRunner.completeTestDeclaration(test)
205
+ this.activeTest = undefined
95
206
  }
96
207
 
97
208
  /**
@@ -101,8 +212,8 @@ export default class VelociousRunnerReporter {
101
212
  * @param {string[]} args.descriptions - Parent description stack.
102
213
  * @param {ReturnType<typeof JSON.parse>} args.error - Raw final failure.
103
214
  * @param {string} args.leftPadding - Console indentation.
104
- * @param {import("./velocious-test-arguments.js").TestArgs} args.testArgs - Stable test arguments.
105
- * @param {import("./velocious-test-arguments.js").TestData} args.testData - Test registration.
215
+ * @param {import("./test-runner.js").TestArgs} args.testArgs - Stable test arguments.
216
+ * @param {import("./test-runner.js").TestData} args.testData - Test registration.
106
217
  * @param {string} args.testDescription - Test description.
107
218
  * @returns {Promise<void>} - Resolves after the final-failure listener completes.
108
219
  */
@@ -119,23 +230,14 @@ export default class VelociousRunnerReporter {
119
230
  const stackLines = cleanedStack?.split("\n")
120
231
 
121
232
  if (stackLines) {
122
- for (const stackLine of stackLines) {
123
- console.error(picocolors.red(`${leftPadding} ${stackLine}`))
124
- }
233
+ for (const stackLine of stackLines) console.error(picocolors.red(`${leftPadding} ${stackLine}`))
125
234
  }
126
235
  } else {
127
236
  console.error(picocolors.red(`${leftPadding} Test failed with a ${typeof error}: ${String(error)}`))
128
237
  }
129
238
 
130
239
  testRunner.printFailedConsoleOutput({consoleOutput, leftPadding})
131
- testRunner._failedTests++
132
- testRunner._failedTestDetails.push({
133
- fullDescription: testRunner.buildFullDescription(descriptions, testDescription),
134
- filePath: testData.filePath,
135
- line: testData.line,
136
- error,
137
- consoleOutput: consoleOutput || undefined
138
- })
240
+ testRunner.recordFailedTest({descriptions, error, consoleOutput, testData, testDescription})
139
241
 
140
242
  await this.emitEvent("testFailed", {
141
243
  configuration: testRunner.getConfiguration(),
@@ -157,10 +259,6 @@ export default class VelociousRunnerReporter {
157
259
  * @returns {Promise<void>} - Resolves when all listeners complete.
158
260
  */
159
261
  async emitEvent(eventName, payload) {
160
- const listeners = testEvents.listeners(eventName)
161
-
162
- for (const listener of listeners) {
163
- await listener(payload)
164
- }
262
+ for (const listener of testEvents.listeners(eventName)) await listener(payload)
165
263
  }
166
264
  }
@@ -14,58 +14,30 @@ export default class VelociousSuiteHookExecutor {
14
14
  }
15
15
 
16
16
  /**
17
- * Runs suite setup hooks in declaration order.
18
- * @param {object} args - Hook execution arguments.
19
- * @param {import("./test-runner.js").BeforeAfterAllCallbackObjectType[]} args.hooks - Profiled setup hooks.
20
- * @returns {Promise<void>} - Resolves after every setup hook completes.
17
+ * Supplies the framework configuration while package traversal owns ordering,
18
+ * timeout enforcement, aggregation, and active-scope cleanup.
19
+ * @param {import("@velocious/testing/runner").SuiteHookExecutorInput} input - Package hook input.
20
+ * @returns {Promise<void>} - Resolves after the hook completes.
21
21
  */
22
- async runBeforeAlls({hooks, ...restArgs}) {
22
+ async execute({context, defaultExecute, fullName, hook, phase, suite, timeoutMs, ...restArgs}) {
23
23
  restArgsError(restArgs)
24
-
25
- for (const hook of hooks) {
26
- await this.runHook(hook, "beforeAll")
27
- }
28
- }
29
-
30
- /**
31
- * Runs every suite teardown hook in reverse declaration order.
32
- * @param {object} args - Hook execution arguments.
33
- * @param {import("./test-runner.js").BeforeAfterAllCallbackObjectType[]} args.hooks - Profiled teardown hooks.
34
- * @returns {Promise<void>} - Resolves after every teardown hook settles.
35
- */
36
- async runAfterAlls({hooks, ...restArgs}) {
37
- restArgsError(restArgs)
38
- /** @type {ReturnType<typeof JSON.parse>[]} */
39
- const errors = []
40
-
41
- for (const hook of [...hooks].reverse()) {
42
- try {
43
- await this.runHook(hook, "afterAll")
44
- } catch (error) {
45
- errors.push(error)
46
- }
47
- }
48
-
49
- if (errors.length == 1) throw errors[0]
50
- if (errors.length > 1) {
51
- throw new AggregateError(errors, "Multiple afterAll hooks failed", {cause: errors[0]})
24
+ void context
25
+ void fullName
26
+ void timeoutMs
27
+ const metadata = this.testRunner.hookMetadata(hook)
28
+
29
+ try {
30
+ await this.testRunner.runProfileSpan({
31
+ phase,
32
+ declarationIndex: metadata.declarationIndex,
33
+ declarationScopeId: metadata.declarationScopeId,
34
+ filePath: metadata.ownerFilePath
35
+ }, async () => {
36
+ await defaultExecute([{configuration: this.testRunner.getConfiguration()}])
37
+ })
38
+ } catch (error) {
39
+ this.testRunner.recordSuiteHookFailure({suite, phase, error})
40
+ throw error
52
41
  }
53
42
  }
54
-
55
- /**
56
- * Runs one suite hook with its Velocious profiler attribution.
57
- * @param {import("./test-runner.js").BeforeAfterAllCallbackObjectType} hook - Hook registration.
58
- * @param {"beforeAll" | "afterAll"} phase - Profiler phase.
59
- * @returns {Promise<void>} - Resolves when the hook completes.
60
- */
61
- async runHook(hook, phase) {
62
- await this.testRunner.runProfileSpan({
63
- phase,
64
- declarationIndex: hook.declarationIndex,
65
- declarationScopeId: hook.declarationScopeId,
66
- filePath: hook.ownerFilePath
67
- }, async () => {
68
- await hook.callback({configuration: this.testRunner.getConfiguration()})
69
- })
70
- }
71
43
  }