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.
- package/README.md +11 -9
- package/build/authorization/ability.js +36 -13
- package/build/background-jobs/adapter.js +9 -0
- package/build/background-jobs/main.js +35 -10
- package/build/background-jobs/store.js +217 -38
- package/build/background-jobs/types.js +15 -0
- package/build/configuration-types.js +1 -1
- package/build/configuration.js +45 -9
- package/build/database/drivers/base-column.js +8 -0
- package/build/database/drivers/mssql/sql/update.js +1 -3
- package/build/database/drivers/mysql/sql/update.js +1 -3
- package/build/database/drivers/pgsql/column.js +22 -0
- package/build/database/drivers/pgsql/sql/update.js +1 -3
- package/build/database/drivers/sqlite/sql/alter-table.js +11 -1
- package/build/database/drivers/sqlite/sql/update.js +1 -3
- package/build/database/query/index.js +2 -2
- package/build/database/query/model-class-query.js +26 -10
- package/build/database/query/preloader/has-many.js +4 -1
- package/build/database/query/query-data.js +2 -1
- package/build/database/query/update-base.js +14 -0
- package/build/database/query/with-count.js +3 -1
- package/build/database/record/acts-as-list.js +37 -13
- package/build/database/record/attachments/store.js +336 -26
- package/build/database/record/auditing.js +6 -3
- package/build/database/record/index.js +197 -42
- package/build/database/record/instance-relationships/belongs-to.js +2 -1
- package/build/database/record/validators/uniqueness.js +8 -5
- package/build/environment-handlers/node/cli/commands/generate/frontend-models.js +24 -8
- package/build/frontend-model-controller.js +136 -53
- package/build/frontend-model-resource/base-resource.js +87 -37
- package/build/frontend-model-resource/velocious-attachment-resource.js +98 -31
- package/build/frontend-models/base.js +307 -59
- package/build/frontend-models/preloader.js +6 -3
- package/build/frontend-models/query.js +15 -6
- package/build/frontend-models/resource-definition.js +21 -2
- package/build/frontend-models/use-destroyed-event.js +1 -1
- package/build/frontend-models/use-model-class-event.js +2 -2
- package/build/frontend-models/use-updated-event.js +1 -1
- package/build/frontend-models/websocket-channel.js +256 -93
- package/build/frontend-models/websocket-publishers.js +218 -18
- package/build/http-server/client/websocket-session.js +13 -1
- package/build/http-server/websocket-channel.js +15 -2
- package/build/src/authorization/ability.d.ts +9 -3
- package/build/src/authorization/ability.d.ts.map +1 -1
- package/build/src/authorization/ability.js +33 -14
- package/build/src/background-jobs/adapter.d.ts +6 -0
- package/build/src/background-jobs/adapter.d.ts.map +1 -1
- package/build/src/background-jobs/adapter.js +9 -1
- package/build/src/background-jobs/main.d.ts +6 -0
- package/build/src/background-jobs/main.d.ts.map +1 -1
- package/build/src/background-jobs/main.js +34 -11
- package/build/src/background-jobs/store.d.ts +66 -12
- package/build/src/background-jobs/store.d.ts.map +1 -1
- package/build/src/background-jobs/store.js +191 -35
- package/build/src/background-jobs/types.d.ts +55 -0
- package/build/src/background-jobs/types.d.ts.map +1 -1
- package/build/src/background-jobs/types.js +16 -1
- package/build/src/configuration-types.d.ts +3 -3
- package/build/src/configuration-types.d.ts.map +1 -1
- package/build/src/configuration-types.js +2 -2
- package/build/src/configuration.d.ts +18 -8
- package/build/src/configuration.d.ts.map +1 -1
- package/build/src/configuration.js +38 -7
- package/build/src/database/drivers/base-column.d.ts +5 -0
- package/build/src/database/drivers/base-column.d.ts.map +1 -1
- package/build/src/database/drivers/base-column.js +8 -1
- package/build/src/database/drivers/mssql/sql/update.d.ts.map +1 -1
- package/build/src/database/drivers/mssql/sql/update.js +2 -4
- package/build/src/database/drivers/mysql/sql/update.d.ts.map +1 -1
- package/build/src/database/drivers/mysql/sql/update.js +2 -4
- package/build/src/database/drivers/pgsql/column.d.ts +5 -0
- package/build/src/database/drivers/pgsql/column.d.ts.map +1 -1
- package/build/src/database/drivers/pgsql/column.js +19 -1
- package/build/src/database/drivers/pgsql/sql/update.d.ts.map +1 -1
- package/build/src/database/drivers/pgsql/sql/update.js +2 -4
- package/build/src/database/drivers/sqlite/sql/alter-table.d.ts.map +1 -1
- package/build/src/database/drivers/sqlite/sql/alter-table.js +6 -2
- package/build/src/database/drivers/sqlite/sql/update.d.ts.map +1 -1
- package/build/src/database/drivers/sqlite/sql/update.js +2 -4
- package/build/src/database/query/index.d.ts +4 -4
- package/build/src/database/query/index.d.ts.map +1 -1
- package/build/src/database/query/index.js +3 -3
- package/build/src/database/query/model-class-query.d.ts +8 -2
- package/build/src/database/query/model-class-query.d.ts.map +1 -1
- package/build/src/database/query/model-class-query.js +25 -11
- package/build/src/database/query/preloader/has-many.d.ts.map +1 -1
- package/build/src/database/query/preloader/has-many.js +4 -2
- package/build/src/database/query/query-data.d.ts.map +1 -1
- package/build/src/database/query/query-data.js +3 -2
- package/build/src/database/query/update-base.d.ts +7 -0
- package/build/src/database/query/update-base.d.ts.map +1 -1
- package/build/src/database/query/update-base.js +13 -1
- package/build/src/database/query/with-count.d.ts.map +1 -1
- package/build/src/database/query/with-count.js +3 -2
- package/build/src/database/record/acts-as-list.d.ts.map +1 -1
- package/build/src/database/record/acts-as-list.js +35 -14
- package/build/src/database/record/attachments/store.d.ts +67 -0
- package/build/src/database/record/attachments/store.d.ts.map +1 -1
- package/build/src/database/record/attachments/store.js +301 -25
- package/build/src/database/record/auditing.d.ts.map +1 -1
- package/build/src/database/record/auditing.js +7 -4
- package/build/src/database/record/index.d.ts +78 -26
- package/build/src/database/record/index.d.ts.map +1 -1
- package/build/src/database/record/index.js +171 -42
- package/build/src/database/record/instance-relationships/belongs-to.d.ts.map +1 -1
- package/build/src/database/record/instance-relationships/belongs-to.js +3 -2
- package/build/src/database/record/validators/uniqueness.d.ts.map +1 -1
- package/build/src/database/record/validators/uniqueness.js +8 -6
- package/build/src/environment-handlers/node/cli/commands/generate/frontend-models.d.ts +4 -4
- package/build/src/environment-handlers/node/cli/commands/generate/frontend-models.d.ts.map +1 -1
- package/build/src/environment-handlers/node/cli/commands/generate/frontend-models.js +24 -12
- package/build/src/frontend-model-controller.d.ts +29 -8
- package/build/src/frontend-model-controller.d.ts.map +1 -1
- package/build/src/frontend-model-controller.js +122 -51
- package/build/src/frontend-model-resource/base-resource.d.ts +51 -24
- package/build/src/frontend-model-resource/base-resource.d.ts.map +1 -1
- package/build/src/frontend-model-resource/base-resource.js +83 -37
- package/build/src/frontend-model-resource/velocious-attachment-resource.d.ts +45 -26
- package/build/src/frontend-model-resource/velocious-attachment-resource.d.ts.map +1 -1
- package/build/src/frontend-model-resource/velocious-attachment-resource.js +89 -31
- package/build/src/frontend-models/base.d.ts +53 -20
- package/build/src/frontend-models/base.d.ts.map +1 -1
- package/build/src/frontend-models/base.js +275 -59
- package/build/src/frontend-models/preloader.d.ts.map +1 -1
- package/build/src/frontend-models/preloader.js +6 -4
- package/build/src/frontend-models/query.d.ts +2 -2
- package/build/src/frontend-models/query.d.ts.map +1 -1
- package/build/src/frontend-models/query.js +14 -7
- package/build/src/frontend-models/resource-definition.d.ts.map +1 -1
- package/build/src/frontend-models/resource-definition.js +20 -3
- package/build/src/frontend-models/use-destroyed-event.d.ts +1 -1
- package/build/src/frontend-models/use-destroyed-event.d.ts.map +1 -1
- package/build/src/frontend-models/use-destroyed-event.js +2 -2
- package/build/src/frontend-models/use-model-class-event.d.ts +2 -2
- package/build/src/frontend-models/use-model-class-event.d.ts.map +1 -1
- package/build/src/frontend-models/use-model-class-event.js +3 -3
- package/build/src/frontend-models/use-updated-event.d.ts +1 -1
- package/build/src/frontend-models/use-updated-event.d.ts.map +1 -1
- package/build/src/frontend-models/use-updated-event.js +2 -2
- package/build/src/frontend-models/websocket-channel.d.ts +60 -41
- package/build/src/frontend-models/websocket-channel.d.ts.map +1 -1
- package/build/src/frontend-models/websocket-channel.js +225 -85
- package/build/src/frontend-models/websocket-publishers.d.ts +9 -0
- package/build/src/frontend-models/websocket-publishers.d.ts.map +1 -1
- package/build/src/frontend-models/websocket-publishers.js +190 -19
- package/build/src/http-server/client/websocket-session.d.ts.map +1 -1
- package/build/src/http-server/client/websocket-session.js +11 -2
- package/build/src/http-server/websocket-channel.d.ts +20 -8
- package/build/src/http-server/websocket-channel.d.ts.map +1 -1
- package/build/src/http-server/websocket-channel.js +15 -3
- package/build/src/sync/sync-api-client.d.ts.map +1 -1
- package/build/src/sync/sync-api-client.js +4 -3
- package/build/src/sync/sync-client.d.ts.map +1 -1
- package/build/src/sync/sync-client.js +3 -2
- package/build/src/sync/sync-envelope-replay-service.d.ts.map +1 -1
- package/build/src/sync/sync-envelope-replay-service.js +6 -5
- package/build/src/sync/sync-publisher.d.ts.map +1 -1
- package/build/src/sync/sync-publisher.js +4 -3
- package/build/src/testing/browser-frontend-model-event-hook-scenarios.d.ts +2 -2
- package/build/src/testing/browser-frontend-model-event-hook-scenarios.d.ts.map +1 -1
- package/build/src/testing/browser-frontend-model-event-hook-scenarios.js +3 -3
- package/build/src/testing/test-profiler.d.ts +4 -4
- package/build/src/testing/test-profiler.d.ts.map +1 -1
- package/build/src/testing/test-profiler.js +3 -3
- package/build/src/testing/test-runner.d.ts +271 -117
- package/build/src/testing/test-runner.d.ts.map +1 -1
- package/build/src/testing/test-runner.js +496 -427
- package/build/src/testing/test.d.ts +11 -72
- package/build/src/testing/test.d.ts.map +1 -1
- package/build/src/testing/test.js +131 -284
- package/build/src/testing/velocious-attempt-executor.d.ts +14 -29
- package/build/src/testing/velocious-attempt-executor.d.ts.map +1 -1
- package/build/src/testing/velocious-attempt-executor.js +52 -46
- package/build/src/testing/velocious-runner-reporter.d.ts +29 -34
- package/build/src/testing/velocious-runner-reporter.d.ts.map +1 -1
- package/build/src/testing/velocious-runner-reporter.js +145 -57
- package/build/src/testing/velocious-suite-hook-executor.d.ts +5 -23
- package/build/src/testing/velocious-suite-hook-executor.d.ts.map +1 -1
- package/build/src/testing/velocious-suite-hook-executor.js +22 -47
- package/build/src/testing/velocious-test-arguments.d.ts +11 -6
- package/build/src/testing/velocious-test-arguments.d.ts.map +1 -1
- package/build/src/testing/velocious-test-arguments.js +18 -10
- package/build/src/utils/model-primary-key.d.ts +73 -0
- package/build/src/utils/model-primary-key.d.ts.map +1 -0
- package/build/src/utils/model-primary-key.js +144 -0
- package/build/sync/sync-api-client.js +3 -2
- package/build/sync/sync-client.js +2 -1
- package/build/sync/sync-envelope-replay-service.js +5 -4
- package/build/sync/sync-publisher.js +3 -2
- package/build/testing/browser-frontend-model-event-hook-scenarios.js +2 -2
- package/build/testing/test-profiler.js +2 -2
- package/build/testing/test-runner.js +493 -449
- package/build/testing/test.js +164 -306
- package/build/testing/velocious-attempt-executor.js +55 -45
- package/build/testing/velocious-runner-reporter.js +156 -58
- package/build/testing/velocious-suite-hook-executor.js +22 -50
- package/build/testing/velocious-test-arguments.js +19 -10
- package/build/utils/model-primary-key.js +171 -0
- package/package.json +6 -5
- package/src/authorization/ability.js +36 -13
- package/src/background-jobs/adapter.js +9 -0
- package/src/background-jobs/main.js +35 -10
- package/src/background-jobs/store.js +217 -38
- package/src/background-jobs/types.js +15 -0
- package/src/configuration-types.js +1 -1
- package/src/configuration.js +45 -9
- package/src/database/drivers/base-column.js +8 -0
- package/src/database/drivers/mssql/sql/update.js +1 -3
- package/src/database/drivers/mysql/sql/update.js +1 -3
- package/src/database/drivers/pgsql/column.js +22 -0
- package/src/database/drivers/pgsql/sql/update.js +1 -3
- package/src/database/drivers/sqlite/sql/alter-table.js +11 -1
- package/src/database/drivers/sqlite/sql/update.js +1 -3
- package/src/database/query/index.js +2 -2
- package/src/database/query/model-class-query.js +26 -10
- package/src/database/query/preloader/has-many.js +4 -1
- package/src/database/query/query-data.js +2 -1
- package/src/database/query/update-base.js +14 -0
- package/src/database/query/with-count.js +3 -1
- package/src/database/record/acts-as-list.js +37 -13
- package/src/database/record/attachments/store.js +336 -26
- package/src/database/record/auditing.js +6 -3
- package/src/database/record/index.js +197 -42
- package/src/database/record/instance-relationships/belongs-to.js +2 -1
- package/src/database/record/validators/uniqueness.js +8 -5
- package/src/environment-handlers/node/cli/commands/generate/frontend-models.js +24 -8
- package/src/frontend-model-controller.js +136 -53
- package/src/frontend-model-resource/base-resource.js +87 -37
- package/src/frontend-model-resource/velocious-attachment-resource.js +98 -31
- package/src/frontend-models/base.js +307 -59
- package/src/frontend-models/preloader.js +6 -3
- package/src/frontend-models/query.js +15 -6
- package/src/frontend-models/resource-definition.js +21 -2
- package/src/frontend-models/use-destroyed-event.js +1 -1
- package/src/frontend-models/use-model-class-event.js +2 -2
- package/src/frontend-models/use-updated-event.js +1 -1
- package/src/frontend-models/websocket-channel.js +256 -93
- package/src/frontend-models/websocket-publishers.js +218 -18
- package/src/http-server/client/websocket-session.js +13 -1
- package/src/http-server/websocket-channel.js +15 -2
- package/src/sync/sync-api-client.js +3 -2
- package/src/sync/sync-client.js +2 -1
- package/src/sync/sync-envelope-replay-service.js +5 -4
- package/src/sync/sync-publisher.js +3 -2
- package/src/testing/browser-frontend-model-event-hook-scenarios.js +2 -2
- package/src/testing/test-profiler.js +2 -2
- package/src/testing/test-runner.js +493 -449
- package/src/testing/test.js +164 -306
- package/src/testing/velocious-attempt-executor.js +55 -45
- package/src/testing/velocious-runner-reporter.js +156 -58
- package/src/testing/velocious-suite-hook-executor.js +22 -50
- package/src/testing/velocious-test-arguments.js +19 -10
- package/src/utils/model-primary-key.js +171 -0
- package/build/src/testing/testing-package-adapter.d.ts +0 -9
- package/build/src/testing/testing-package-adapter.d.ts.map +0 -1
- package/build/src/testing/testing-package-adapter.js +0 -69
- package/build/testing/testing-package-adapter.js +0 -76
- package/build/tsconfig.tsbuildinfo +0 -1
- 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 {
|
|
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 =
|
|
29
|
+
const timeout = realSetTimeout(() => reject(timeoutError), timeoutMs)
|
|
28
30
|
|
|
29
31
|
Promise.resolve(promise).then((result) => {
|
|
30
|
-
|
|
32
|
+
realClearTimeout(timeout)
|
|
31
33
|
resolve(result)
|
|
32
34
|
}).catch((error) => {
|
|
33
|
-
|
|
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 =
|
|
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
|
-
|
|
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
|
-
|
|
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 {
|
|
102
|
-
* @
|
|
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({
|
|
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:
|
|
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
|
|
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 (
|
|
269
|
-
await runWithTimeout(testLifecycle,
|
|
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,
|
|
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,
|
|
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,
|
|
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,
|
|
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
|
-
|
|
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 {
|
|
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:
|
|
391
|
-
declarationScopeId:
|
|
392
|
-
filePath:
|
|
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 {
|
|
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:
|
|
416
|
-
declarationScopeId:
|
|
417
|
-
filePath:
|
|
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
|
-
*
|
|
22
|
-
*
|
|
23
|
-
* @
|
|
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
|
|
39
|
-
|
|
40
|
-
|
|
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 (
|
|
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(`${
|
|
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 (
|
|
93
|
-
|
|
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("./
|
|
105
|
-
* @param {import("./
|
|
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.
|
|
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
|
|
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
|
-
*
|
|
18
|
-
*
|
|
19
|
-
* @param {import("
|
|
20
|
-
* @returns {Promise<void>} - Resolves after
|
|
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
|
|
22
|
+
async execute({context, defaultExecute, fullName, hook, phase, suite, timeoutMs, ...restArgs}) {
|
|
23
23
|
restArgsError(restArgs)
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
|
|
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
|
}
|