@danceroutine/tango-testing 1.11.0 → 1.11.2
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/dist/{aDBClient-CH-ZcOaP.js → aDBClient-fMkIdR7p.js} +16 -7
- package/dist/aDBClient-fMkIdR7p.js.map +1 -0
- package/dist/assertions/index.d.ts +2 -4
- package/dist/assertions/index.js +2 -3
- package/dist/assertions-lsAd7fhA.js +15 -0
- package/dist/assertions-lsAd7fhA.js.map +1 -0
- package/dist/chunk-D7D4PA-g.js +13 -0
- package/dist/express/index.d.ts +2 -3
- package/dist/express/index.js +2 -3
- package/dist/{express-Czpfz_Ay.js → express-CH6_GAyC.js} +23 -15
- package/dist/express-CH6_GAyC.js.map +1 -0
- package/dist/factories/index.d.ts +2 -4
- package/dist/factories/index.js +2 -3
- package/dist/{factories-Cl_CAzbj.js → factories-qAJouv1I.js} +10 -8
- package/dist/factories-qAJouv1I.js.map +1 -0
- package/dist/index-49XmDOxW.d.ts +40 -0
- package/dist/index-B4H3wYuR.d.ts +325 -0
- package/dist/index-BCWo7zAn.d.ts +41 -0
- package/dist/index-CKVKW5j_.d.ts +15 -0
- package/dist/index-CnUPgs3G.d.ts +208 -0
- package/dist/index.d.ts +7 -19
- package/dist/index.js +8 -9
- package/dist/integration/index.d.ts +2 -18
- package/dist/integration/index.js +2 -4
- package/dist/{integration-CaRF_lF_.js → integration-CLzkacon.js} +99 -84
- package/dist/integration-CLzkacon.js.map +1 -0
- package/dist/mocks/index.d.ts +2 -20
- package/dist/mocks/index.js +3 -4
- package/dist/{mocks-BL_0iuAI.js → mocks-JyZwO-W4.js} +77 -65
- package/dist/mocks-JyZwO-W4.js.map +1 -0
- package/dist/vitest/index.d.ts +60 -3
- package/dist/vitest/index.js +119 -4
- package/dist/vitest/index.js.map +1 -0
- package/package.json +8 -8
- package/dist/aDBClient-CH-ZcOaP.js.map +0 -1
- package/dist/assertions/assertions.d.ts +0 -7
- package/dist/assertions-CCFZ53Y-.js +0 -15
- package/dist/assertions-CCFZ53Y-.js.map +0 -1
- package/dist/chunk-BkvOhyD0.js +0 -12
- package/dist/express/anExpressRequest.d.ts +0 -24
- package/dist/express/anExpressResponse.d.ts +0 -9
- package/dist/express-Czpfz_Ay.js.map +0 -1
- package/dist/factories/ModelDataFactory.d.ts +0 -33
- package/dist/factories-Cl_CAzbj.js.map +0 -1
- package/dist/integration/HarnessStrategyRegistry.d.ts +0 -25
- package/dist/integration/TestHarness.d.ts +0 -38
- package/dist/integration/anIntegrationHarness.d.ts +0 -5
- package/dist/integration/config.d.ts +0 -11
- package/dist/integration/conformance/index.d.ts +0 -1
- package/dist/integration/conformance/runDialectConformanceSuite.d.ts +0 -11
- package/dist/integration/domain/Dialect.d.ts +0 -5
- package/dist/integration/domain/HarnessStrategy.d.ts +0 -17
- package/dist/integration/domain/IntegrationHarness.d.ts +0 -22
- package/dist/integration/domain/ResetMode.d.ts +0 -6
- package/dist/integration/domain/index.d.ts +0 -7
- package/dist/integration/migrations/ApplyAndVerifyMigrations.d.ts +0 -16
- package/dist/integration/migrations/AssertMigrationPlan.d.ts +0 -9
- package/dist/integration/migrations/IntrospectSchema.d.ts +0 -5
- package/dist/integration/migrations/index.d.ts +0 -6
- package/dist/integration/orm/createModelQuerySetFixture.d.ts +0 -10
- package/dist/integration/orm/createQuerySetFixture.d.ts +0 -10
- package/dist/integration/orm/expectQueryResult.d.ts +0 -4
- package/dist/integration/orm/index.d.ts +0 -7
- package/dist/integration/orm/seedTable.d.ts +0 -5
- package/dist/integration/runtime/aTangoConfig.d.ts +0 -9
- package/dist/integration/runtime/aTangoRuntime.d.ts +0 -6
- package/dist/integration/runtime/index.d.ts +0 -7
- package/dist/integration/runtime/setupTestTangoRuntime.d.ts +0 -6
- package/dist/integration/smoke/AppProcessHarness.d.ts +0 -83
- package/dist/integration/smoke/index.d.ts +0 -4
- package/dist/integration/strategies/PostgresHarnessStrategy.d.ts +0 -19
- package/dist/integration/strategies/SqliteHarnessStrategy.d.ts +0 -19
- package/dist/integration-CaRF_lF_.js.map +0 -1
- package/dist/mocks/DBClient.d.ts +0 -1
- package/dist/mocks/MockQuerySetResult.d.ts +0 -6
- package/dist/mocks/aDBClient.d.ts +0 -24
- package/dist/mocks/aManager.d.ts +0 -20
- package/dist/mocks/aManyToManyRelatedManager.d.ts +0 -52
- package/dist/mocks/aModelQuerySet.d.ts +0 -8
- package/dist/mocks/aQueryExecutor.d.ts +0 -16
- package/dist/mocks/aQueryResult.d.ts +0 -9
- package/dist/mocks/aQuerySet.d.ts +0 -5
- package/dist/mocks/aRelationMeta.d.ts +0 -20
- package/dist/mocks/aRequestContext.d.ts +0 -22
- package/dist/mocks/anAdapter.d.ts +0 -13
- package/dist/mocks-BL_0iuAI.js.map +0 -1
- package/dist/vitest/registerVitestTango.d.ts +0 -46
- package/dist/vitest/withGlobalTestApi.d.ts +0 -7
- package/dist/vitest-BqZmULOa.js +0 -111
- package/dist/vitest-BqZmULOa.js.map +0 -1
|
@@ -1,20 +1,18 @@
|
|
|
1
|
-
import {
|
|
2
|
-
import {
|
|
1
|
+
import { t as __exportAll } from "./chunk-D7D4PA-g.js";
|
|
2
|
+
import { n as anAdapter, t as aDBClient } from "./aDBClient-fMkIdR7p.js";
|
|
3
3
|
import { ModelQuerySet, TangoRuntime, initializeTangoRuntime, resetTangoRuntime } from "@danceroutine/tango-orm";
|
|
4
4
|
import { vi } from "vitest";
|
|
5
|
-
import { getLogger, quoteSqlIdentifier,
|
|
6
|
-
import { MigrationRunner,
|
|
7
|
-
import { defineConfig, loadConfig
|
|
5
|
+
import { getLogger, quoteSqlIdentifier, validateSqlIdentifier } from "@danceroutine/tango-core";
|
|
6
|
+
import { MigrationRunner, createDefaultIntrospectorStrategy } from "@danceroutine/tango-migrations";
|
|
7
|
+
import { defineConfig, loadConfig } from "@danceroutine/tango-config";
|
|
8
8
|
import { spawn } from "node:child_process";
|
|
9
|
-
import { PostgresAdapter, SqliteAdapter } from "@danceroutine/tango-orm/connection";
|
|
9
|
+
import { PostgresAdapter as PostgresAdapter$1, SqliteAdapter as SqliteAdapter$1 } from "@danceroutine/tango-orm/connection";
|
|
10
10
|
import { rm } from "node:fs/promises";
|
|
11
|
-
|
|
12
11
|
//#region src/integration/domain/Dialect.ts
|
|
13
12
|
const Dialect = {
|
|
14
13
|
Sqlite: "sqlite",
|
|
15
14
|
Postgres: "postgres"
|
|
16
15
|
};
|
|
17
|
-
|
|
18
16
|
//#endregion
|
|
19
17
|
//#region src/integration/domain/ResetMode.ts
|
|
20
18
|
const ResetMode = {
|
|
@@ -22,26 +20,27 @@ const ResetMode = {
|
|
|
22
20
|
Truncate: "truncate",
|
|
23
21
|
DropSchema: "drop-schema"
|
|
24
22
|
};
|
|
25
|
-
|
|
26
23
|
//#endregion
|
|
27
24
|
//#region src/integration/domain/index.ts
|
|
28
|
-
var domain_exports = {
|
|
29
|
-
__export(domain_exports, {
|
|
25
|
+
var domain_exports = /* @__PURE__ */ __exportAll({
|
|
30
26
|
Dialect: () => Dialect,
|
|
31
27
|
ResetMode: () => ResetMode
|
|
32
28
|
});
|
|
33
|
-
|
|
34
29
|
//#endregion
|
|
35
30
|
//#region src/integration/migrations/AssertMigrationPlan.ts
|
|
31
|
+
/**
|
|
32
|
+
* Generate a migration plan through a harness and assert that required SQL fragments appear.
|
|
33
|
+
*/
|
|
36
34
|
async function assertMigrationPlan(harness, options) {
|
|
37
|
-
const
|
|
38
|
-
const plan = await runner.plan();
|
|
35
|
+
const plan = await harness.migrationRunner(options.migrationsDir).plan();
|
|
39
36
|
for (const snippet of options.expectSqlContains ?? []) if (!plan.includes(snippet)) throw new Error(`Expected migration plan to contain: ${snippet}`);
|
|
40
37
|
return plan;
|
|
41
38
|
}
|
|
42
|
-
|
|
43
39
|
//#endregion
|
|
44
40
|
//#region src/integration/migrations/ApplyAndVerifyMigrations.ts
|
|
41
|
+
/**
|
|
42
|
+
* Apply migrations through a harness and optionally verify that specific ids were applied.
|
|
43
|
+
*/
|
|
45
44
|
async function applyAndVerifyMigrations(harness, options) {
|
|
46
45
|
const runner = harness.migrationRunner(options.migrationsDir);
|
|
47
46
|
await runner.apply(options.toId);
|
|
@@ -52,27 +51,32 @@ async function applyAndVerifyMigrations(harness, options) {
|
|
|
52
51
|
}
|
|
53
52
|
return { statuses };
|
|
54
53
|
}
|
|
55
|
-
|
|
56
54
|
//#endregion
|
|
57
55
|
//#region src/integration/migrations/IntrospectSchema.ts
|
|
58
56
|
const introspectorStrategy = createDefaultIntrospectorStrategy();
|
|
57
|
+
/**
|
|
58
|
+
* Introspect the schema visible to a harness using Tango's built-in introspectors.
|
|
59
|
+
*/
|
|
59
60
|
async function introspectSchema(harness) {
|
|
60
61
|
if (harness.dialect !== Dialect.Postgres && harness.dialect !== Dialect.Sqlite) throw new Error(`No introspector registered for dialect: ${String(harness.dialect)}`);
|
|
61
62
|
const dialect = harness.dialect === Dialect.Postgres ? "postgres" : "sqlite";
|
|
62
63
|
return introspectorStrategy.introspect(dialect, harness.dbClient);
|
|
63
64
|
}
|
|
64
|
-
|
|
65
65
|
//#endregion
|
|
66
66
|
//#region src/integration/migrations/index.ts
|
|
67
|
-
var migrations_exports = {
|
|
68
|
-
__export(migrations_exports, {
|
|
67
|
+
var migrations_exports = /* @__PURE__ */ __exportAll({
|
|
69
68
|
applyAndVerifyMigrations: () => applyAndVerifyMigrations,
|
|
70
69
|
assertMigrationPlan: () => assertMigrationPlan,
|
|
71
70
|
introspectSchema: () => introspectSchema
|
|
72
71
|
});
|
|
73
|
-
|
|
74
72
|
//#endregion
|
|
75
73
|
//#region src/integration/conformance/runDialectConformanceSuite.ts
|
|
74
|
+
/**
|
|
75
|
+
* Shared conformance checks every harness strategy must satisfy.
|
|
76
|
+
*
|
|
77
|
+
* This is intentionally framework-agnostic so first-party and third-party
|
|
78
|
+
* strategies can run the same lifecycle validation.
|
|
79
|
+
*/
|
|
76
80
|
async function runDialectConformanceSuite(strategy, options = {}) {
|
|
77
81
|
const harness = await strategy.create(options.createOptions);
|
|
78
82
|
if (harness.dialect !== strategy.dialect) throw new Error(`Conformance failed: harness dialect '${String(harness.dialect)}' does not match strategy dialect '${String(strategy.dialect)}'`);
|
|
@@ -96,14 +100,14 @@ async function runDialectConformanceSuite(strategy, options = {}) {
|
|
|
96
100
|
}
|
|
97
101
|
if (!dbClientAfterTeardownThrew) throw new Error("Conformance failed: dbClient getter must throw after teardown()");
|
|
98
102
|
}
|
|
99
|
-
|
|
100
103
|
//#endregion
|
|
101
104
|
//#region src/integration/conformance/index.ts
|
|
102
|
-
var conformance_exports = {};
|
|
103
|
-
__export(conformance_exports, { runDialectConformanceSuite: () => runDialectConformanceSuite });
|
|
104
|
-
|
|
105
|
+
var conformance_exports = /* @__PURE__ */ __exportAll({ runDialectConformanceSuite: () => runDialectConformanceSuite });
|
|
105
106
|
//#endregion
|
|
106
107
|
//#region src/integration/runtime/aTangoConfig.ts
|
|
108
|
+
/**
|
|
109
|
+
* Create a stable Tango config fixture for runtime-oriented tests.
|
|
110
|
+
*/
|
|
107
111
|
function aTangoConfig(options = {}) {
|
|
108
112
|
const adapter = options.adapter ?? "sqlite";
|
|
109
113
|
const sqliteFilename = options.sqliteFilename ?? ":memory:";
|
|
@@ -161,29 +165,30 @@ function aTangoConfig(options = {}) {
|
|
|
161
165
|
}
|
|
162
166
|
});
|
|
163
167
|
}
|
|
164
|
-
|
|
165
168
|
//#endregion
|
|
166
169
|
//#region src/integration/runtime/aTangoRuntime.ts
|
|
170
|
+
/**
|
|
171
|
+
* Create a standalone Tango runtime for tests without mutating the process-default runtime.
|
|
172
|
+
*/
|
|
167
173
|
function aTangoRuntime(options = {}) {
|
|
168
|
-
return new TangoRuntime(() => loadConfig
|
|
174
|
+
return new TangoRuntime(() => loadConfig(() => aTangoConfig(options)));
|
|
169
175
|
}
|
|
170
|
-
|
|
171
176
|
//#endregion
|
|
172
177
|
//#region src/integration/runtime/setupTestTangoRuntime.ts
|
|
178
|
+
/**
|
|
179
|
+
* Reset and initialize the process-default Tango runtime for tests.
|
|
180
|
+
*/
|
|
173
181
|
async function setupTestTangoRuntime(options = {}) {
|
|
174
182
|
await resetTangoRuntime();
|
|
175
183
|
return initializeTangoRuntime(() => aTangoConfig(options));
|
|
176
184
|
}
|
|
177
|
-
|
|
178
185
|
//#endregion
|
|
179
186
|
//#region src/integration/runtime/index.ts
|
|
180
|
-
var runtime_exports = {
|
|
181
|
-
__export(runtime_exports, {
|
|
187
|
+
var runtime_exports = /* @__PURE__ */ __exportAll({
|
|
182
188
|
aTangoConfig: () => aTangoConfig,
|
|
183
189
|
aTangoRuntime: () => aTangoRuntime,
|
|
184
190
|
setupTestTangoRuntime: () => setupTestTangoRuntime
|
|
185
191
|
});
|
|
186
|
-
|
|
187
192
|
//#endregion
|
|
188
193
|
//#region src/integration/smoke/AppProcessHarness.ts
|
|
189
194
|
const DEFAULT_READY_TIMEOUT_MS = 3e4;
|
|
@@ -197,6 +202,9 @@ const defaultDeps = {
|
|
|
197
202
|
setTimeout(resolve, ms);
|
|
198
203
|
})
|
|
199
204
|
};
|
|
205
|
+
/**
|
|
206
|
+
* Lightweight process harness for end-to-end smoke tests that need a real app process.
|
|
207
|
+
*/
|
|
200
208
|
var AppProcessHarness = class AppProcessHarness {
|
|
201
209
|
static BRAND = "tango.testing.app_process_harness";
|
|
202
210
|
__tangoBrand = AppProcessHarness.BRAND;
|
|
@@ -242,11 +250,10 @@ var AppProcessHarness = class AppProcessHarness {
|
|
|
242
250
|
* Spawn the target process and wait until its readiness endpoint responds successfully.
|
|
243
251
|
*/
|
|
244
252
|
static async start(options, deps = {}) {
|
|
245
|
-
const
|
|
253
|
+
const harness = new AppProcessHarness(options, {
|
|
246
254
|
...defaultDeps,
|
|
247
255
|
...deps
|
|
248
|
-
};
|
|
249
|
-
const harness = new AppProcessHarness(options, mergedDeps);
|
|
256
|
+
});
|
|
250
257
|
await harness.waitForReady();
|
|
251
258
|
return harness;
|
|
252
259
|
}
|
|
@@ -303,8 +310,7 @@ var AppProcessHarness = class AppProcessHarness {
|
|
|
303
310
|
this.stopped = true;
|
|
304
311
|
if (this.child.exitCode !== null || this.child.killed) return;
|
|
305
312
|
this.child.kill("SIGTERM");
|
|
306
|
-
|
|
307
|
-
if (!exited && !this.child.killed) {
|
|
313
|
+
if (!await this.waitForExit(this.stopTimeoutMs) && !this.child.killed) {
|
|
308
314
|
this.child.kill("SIGKILL");
|
|
309
315
|
await this.waitForExit(this.stopTimeoutMs);
|
|
310
316
|
}
|
|
@@ -314,8 +320,7 @@ var AppProcessHarness = class AppProcessHarness {
|
|
|
314
320
|
while (Date.now() < deadline) {
|
|
315
321
|
if (this.child.exitCode !== null) throw new Error(`Process exited before ready check succeeded (exitCode=${String(this.child.exitCode)}).\n${this.getCombinedLog()}`);
|
|
316
322
|
try {
|
|
317
|
-
|
|
318
|
-
if (response.ok) return;
|
|
323
|
+
if ((await this.deps.fetchImpl(this.readyUrl)).ok) return;
|
|
319
324
|
} catch {}
|
|
320
325
|
await this.deps.sleep(this.readyIntervalMs);
|
|
321
326
|
}
|
|
@@ -346,12 +351,9 @@ function normalizePath(path) {
|
|
|
346
351
|
if (!path) return "/";
|
|
347
352
|
return path.startsWith("/") ? path : `/${path}`;
|
|
348
353
|
}
|
|
349
|
-
|
|
350
354
|
//#endregion
|
|
351
355
|
//#region src/integration/smoke/index.ts
|
|
352
|
-
var smoke_exports = {};
|
|
353
|
-
__export(smoke_exports, { AppProcessHarness: () => AppProcessHarness });
|
|
354
|
-
|
|
356
|
+
var smoke_exports = /* @__PURE__ */ __exportAll({ AppProcessHarness: () => AppProcessHarness });
|
|
355
357
|
//#endregion
|
|
356
358
|
//#region src/integration/anIntegrationHarness.ts
|
|
357
359
|
const defaultCapabilities = {
|
|
@@ -361,6 +363,9 @@ const defaultCapabilities = {
|
|
|
361
363
|
supportsDeferredFkValidation: false,
|
|
362
364
|
supportsJsonb: false
|
|
363
365
|
};
|
|
366
|
+
/**
|
|
367
|
+
* Create an integration-harness fixture with optional overrides.
|
|
368
|
+
*/
|
|
364
369
|
function anIntegrationHarness(overrides = {}) {
|
|
365
370
|
return {
|
|
366
371
|
dialect: Dialect.Sqlite,
|
|
@@ -375,13 +380,15 @@ function anIntegrationHarness(overrides = {}) {
|
|
|
375
380
|
...overrides
|
|
376
381
|
};
|
|
377
382
|
}
|
|
378
|
-
|
|
379
383
|
//#endregion
|
|
380
384
|
//#region src/integration/HarnessStrategyRegistry.ts
|
|
385
|
+
/**
|
|
386
|
+
* Registry of test harness strategies keyed by dialect.
|
|
387
|
+
*/
|
|
381
388
|
var HarnessStrategyRegistry = class HarnessStrategyRegistry {
|
|
382
389
|
static BRAND = "tango.testing.harness_strategy_registry";
|
|
383
390
|
__tangoBrand = HarnessStrategyRegistry.BRAND;
|
|
384
|
-
strategies = new Map();
|
|
391
|
+
strategies = /* @__PURE__ */ new Map();
|
|
385
392
|
/**
|
|
386
393
|
* Narrow an unknown value to `HarnessStrategyRegistry`.
|
|
387
394
|
*/
|
|
@@ -410,19 +417,21 @@ var HarnessStrategyRegistry = class HarnessStrategyRegistry {
|
|
|
410
417
|
return [...this.strategies.values()];
|
|
411
418
|
}
|
|
412
419
|
};
|
|
413
|
-
|
|
414
420
|
//#endregion
|
|
415
421
|
//#region src/integration/config.ts
|
|
416
422
|
function readNumber(value) {
|
|
417
|
-
if (!value) return
|
|
423
|
+
if (!value) return void 0;
|
|
418
424
|
const parsed = Number(value);
|
|
419
|
-
return Number.isFinite(parsed) ? parsed :
|
|
425
|
+
return Number.isFinite(parsed) ? parsed : void 0;
|
|
420
426
|
}
|
|
427
|
+
/**
|
|
428
|
+
* Resolve adapter configuration for a test harness from explicit options,
|
|
429
|
+
* typed Tango config, and environment variables in that order.
|
|
430
|
+
*/
|
|
421
431
|
function resolveAdapterConfig(dialect, opts) {
|
|
422
432
|
const fromOptions = opts.config ?? {};
|
|
423
433
|
if (opts.tangoConfigLoader) {
|
|
424
|
-
const
|
|
425
|
-
const current = loaded.current.db;
|
|
434
|
+
const current = loadConfig(opts.tangoConfigLoader).current.db;
|
|
426
435
|
const merged = {
|
|
427
436
|
url: fromOptions.url ?? current.url,
|
|
428
437
|
host: fromOptions.host ?? current.host,
|
|
@@ -450,9 +459,11 @@ function resolveAdapterConfig(dialect, opts) {
|
|
|
450
459
|
maxConnections: fromOptions.maxConnections ?? 1
|
|
451
460
|
};
|
|
452
461
|
}
|
|
453
|
-
|
|
454
462
|
//#endregion
|
|
455
463
|
//#region src/integration/strategies/PostgresHarnessStrategy.ts
|
|
464
|
+
/**
|
|
465
|
+
* Harness strategy for PostgreSQL-backed integration tests.
|
|
466
|
+
*/
|
|
456
467
|
var PostgresHarnessStrategy = class PostgresHarnessStrategy {
|
|
457
468
|
static BRAND = "tango.testing.postgres_harness_strategy";
|
|
458
469
|
__tangoBrand = PostgresHarnessStrategy.BRAND;
|
|
@@ -483,24 +494,24 @@ var PostgresHarnessStrategy = class PostgresHarnessStrategy {
|
|
|
483
494
|
config: options.config,
|
|
484
495
|
tangoConfigLoader: options.tangoConfigLoader
|
|
485
496
|
});
|
|
486
|
-
const adapter = new PostgresAdapter();
|
|
497
|
+
const adapter = new PostgresAdapter$1();
|
|
487
498
|
const schemaName = PostgresHarnessStrategy.buildSchemaName(options.schema);
|
|
488
499
|
const resetMode = options.resetMode ?? ResetMode.DropSchema;
|
|
489
500
|
let client = null;
|
|
490
501
|
const ensureSearchPath = async () => {
|
|
491
502
|
const dbClient = client;
|
|
492
|
-
const schema = quoteSqlIdentifier
|
|
503
|
+
const schema = quoteSqlIdentifier(validateSqlIdentifier(schemaName, "schema"), "postgres");
|
|
493
504
|
await dbClient.query(`CREATE SCHEMA IF NOT EXISTS ${schema}`);
|
|
494
505
|
await dbClient.query(`SET search_path TO ${schema}`);
|
|
495
506
|
};
|
|
496
507
|
const recreateSchema = async () => {
|
|
497
508
|
const dbClient = client;
|
|
498
|
-
const schema = quoteSqlIdentifier
|
|
509
|
+
const schema = quoteSqlIdentifier(validateSqlIdentifier(schemaName, "schema"), "postgres");
|
|
499
510
|
await dbClient.query(`DROP SCHEMA IF EXISTS ${schema} CASCADE`);
|
|
500
511
|
await dbClient.query(`CREATE SCHEMA ${schema}`);
|
|
501
512
|
await dbClient.query(`SET search_path TO ${schema}`);
|
|
502
513
|
};
|
|
503
|
-
|
|
514
|
+
return {
|
|
504
515
|
dialect: Dialect.Postgres,
|
|
505
516
|
adapter,
|
|
506
517
|
capabilities: this.capabilities,
|
|
@@ -521,16 +532,16 @@ var PostgresHarnessStrategy = class PostgresHarnessStrategy {
|
|
|
521
532
|
}
|
|
522
533
|
const { rows } = await client.query(`SELECT table_name FROM information_schema.tables WHERE table_schema = $1 AND table_type = 'BASE TABLE'`, [schemaName]);
|
|
523
534
|
for (const row of rows) {
|
|
524
|
-
const schema = quoteSqlIdentifier
|
|
525
|
-
const table = quoteSqlIdentifier
|
|
535
|
+
const schema = quoteSqlIdentifier(validateSqlIdentifier(schemaName, "schema"), "postgres");
|
|
536
|
+
const table = quoteSqlIdentifier(validateSqlIdentifier(String(row.table_name), "table"), "postgres");
|
|
526
537
|
await client.query(`TRUNCATE TABLE ${schema}.${table} RESTART IDENTITY CASCADE`);
|
|
527
538
|
}
|
|
528
|
-
await client.query(`SET search_path TO ${quoteSqlIdentifier
|
|
539
|
+
await client.query(`SET search_path TO ${quoteSqlIdentifier(validateSqlIdentifier(schemaName, "schema"), "postgres")}`);
|
|
529
540
|
},
|
|
530
541
|
async teardown() {
|
|
531
542
|
if (!client) return;
|
|
532
543
|
try {
|
|
533
|
-
await client.query(`DROP SCHEMA IF EXISTS ${quoteSqlIdentifier
|
|
544
|
+
await client.query(`DROP SCHEMA IF EXISTS ${quoteSqlIdentifier(validateSqlIdentifier(schemaName, "schema"), "postgres")} CASCADE`);
|
|
534
545
|
} finally {
|
|
535
546
|
await client.close();
|
|
536
547
|
client = null;
|
|
@@ -538,15 +549,16 @@ var PostgresHarnessStrategy = class PostgresHarnessStrategy {
|
|
|
538
549
|
},
|
|
539
550
|
migrationRunner(migrationsDir) {
|
|
540
551
|
if (!client) throw new Error("Postgres harness not initialized. Call setup() first.");
|
|
541
|
-
return new MigrationRunner
|
|
552
|
+
return new MigrationRunner(client, "postgres", migrationsDir);
|
|
542
553
|
}
|
|
543
554
|
};
|
|
544
|
-
return harness;
|
|
545
555
|
}
|
|
546
556
|
};
|
|
547
|
-
|
|
548
557
|
//#endregion
|
|
549
558
|
//#region src/integration/strategies/SqliteHarnessStrategy.ts
|
|
559
|
+
/**
|
|
560
|
+
* Harness strategy for SQLite-backed integration tests.
|
|
561
|
+
*/
|
|
550
562
|
var SqliteHarnessStrategy = class SqliteHarnessStrategy {
|
|
551
563
|
static BRAND = "tango.testing.sqlite_harness_strategy";
|
|
552
564
|
__tangoBrand = SqliteHarnessStrategy.BRAND;
|
|
@@ -567,7 +579,7 @@ var SqliteHarnessStrategy = class SqliteHarnessStrategy {
|
|
|
567
579
|
static async dropAllTables(client) {
|
|
568
580
|
const { rows } = await client.query("SELECT name FROM sqlite_master WHERE type='table' AND name NOT LIKE 'sqlite_%'");
|
|
569
581
|
for (const row of rows) {
|
|
570
|
-
const table = quoteSqlIdentifier
|
|
582
|
+
const table = quoteSqlIdentifier(validateSqlIdentifier(String(row.name), "table"), "sqlite");
|
|
571
583
|
await client.query(`DROP TABLE IF EXISTS ${table}`);
|
|
572
584
|
}
|
|
573
585
|
}
|
|
@@ -580,14 +592,14 @@ var SqliteHarnessStrategy = class SqliteHarnessStrategy {
|
|
|
580
592
|
tangoConfigLoader: options.tangoConfigLoader,
|
|
581
593
|
sqliteFile: options.sqliteFile
|
|
582
594
|
});
|
|
583
|
-
const adapter = new SqliteAdapter();
|
|
595
|
+
const adapter = new SqliteAdapter$1();
|
|
584
596
|
const resetMode = options.resetMode ?? ResetMode.DropSchema;
|
|
585
597
|
let client = null;
|
|
586
598
|
const reconnect = async () => {
|
|
587
599
|
client = await adapter.connect(config);
|
|
588
600
|
return client;
|
|
589
601
|
};
|
|
590
|
-
|
|
602
|
+
return {
|
|
591
603
|
dialect: Dialect.Sqlite,
|
|
592
604
|
adapter,
|
|
593
605
|
capabilities: this.capabilities,
|
|
@@ -621,12 +633,13 @@ var SqliteHarnessStrategy = class SqliteHarnessStrategy {
|
|
|
621
633
|
return new MigrationRunner(client, "sqlite", migrationsDir);
|
|
622
634
|
}
|
|
623
635
|
};
|
|
624
|
-
return harness;
|
|
625
636
|
}
|
|
626
637
|
};
|
|
627
|
-
|
|
628
638
|
//#endregion
|
|
629
639
|
//#region src/integration/TestHarness.ts
|
|
640
|
+
/**
|
|
641
|
+
* Facade for creating integration test harnesses by dialect.
|
|
642
|
+
*/
|
|
630
643
|
var TestHarness = class TestHarness {
|
|
631
644
|
static BRAND = "tango.testing.test_harness";
|
|
632
645
|
static defaultRegistry = null;
|
|
@@ -653,9 +666,7 @@ var TestHarness = class TestHarness {
|
|
|
653
666
|
* Create a dialect-specific harness from the registry.
|
|
654
667
|
*/
|
|
655
668
|
static async forDialect(args, registry) {
|
|
656
|
-
|
|
657
|
-
const strategy = selectedRegistry.get(args.dialect);
|
|
658
|
-
return strategy.create(args.options);
|
|
669
|
+
return (registry ?? this.ensureRegistry()).get(args.dialect).create(args.options);
|
|
659
670
|
}
|
|
660
671
|
/**
|
|
661
672
|
* Convenience helper for a SQLite test harness.
|
|
@@ -684,9 +695,11 @@ var TestHarness = class TestHarness {
|
|
|
684
695
|
return registry;
|
|
685
696
|
}
|
|
686
697
|
};
|
|
687
|
-
|
|
688
698
|
//#endregion
|
|
689
699
|
//#region src/integration/orm/seedTable.ts
|
|
700
|
+
/**
|
|
701
|
+
* Seed rows directly into a table for integration tests that need known fixtures.
|
|
702
|
+
*/
|
|
690
703
|
async function seedTable(harness, table, rows) {
|
|
691
704
|
if (rows.length === 0) return;
|
|
692
705
|
const columns = Object.keys(rows[0] ?? {});
|
|
@@ -704,26 +717,28 @@ async function seedTable(harness, table, rows) {
|
|
|
704
717
|
await harness.dbClient.query(`INSERT INTO ${safeTable} (${safeColumns.join(", ")}) VALUES (${placeholders})`, values);
|
|
705
718
|
}
|
|
706
719
|
}
|
|
707
|
-
|
|
708
720
|
//#endregion
|
|
709
721
|
//#region src/integration/orm/createModelQuerySetFixture.ts
|
|
722
|
+
/**
|
|
723
|
+
* Create a `ModelQuerySet` fixture backed by a real integration harness and supplied table metadata.
|
|
724
|
+
*/
|
|
710
725
|
function createModelQuerySetFixture(input) {
|
|
711
|
-
|
|
726
|
+
return new ModelQuerySet({
|
|
712
727
|
meta: input.meta,
|
|
713
728
|
client: input.harness.dbClient,
|
|
714
729
|
adapter: input.harness.adapter,
|
|
715
730
|
run: async (compiled) => {
|
|
716
|
-
|
|
717
|
-
return result.rows;
|
|
731
|
+
return (await input.harness.dbClient.query(compiled.sql, compiled.params)).rows;
|
|
718
732
|
}
|
|
719
|
-
};
|
|
720
|
-
return new ModelQuerySet(executor);
|
|
733
|
+
});
|
|
721
734
|
}
|
|
722
|
-
|
|
723
735
|
//#endregion
|
|
724
736
|
//#region src/integration/orm/createQuerySetFixture.ts
|
|
725
737
|
const logger = getLogger("tango.testing.integration");
|
|
726
738
|
let hasWarned = false;
|
|
739
|
+
/**
|
|
740
|
+
* @deprecated Use `createModelQuerySetFixture(...)` instead.
|
|
741
|
+
*/
|
|
727
742
|
function createQuerySetFixture(input) {
|
|
728
743
|
if (!hasWarned) {
|
|
729
744
|
hasWarned = true;
|
|
@@ -731,20 +746,20 @@ function createQuerySetFixture(input) {
|
|
|
731
746
|
}
|
|
732
747
|
return createModelQuerySetFixture(input);
|
|
733
748
|
}
|
|
734
|
-
|
|
735
749
|
//#endregion
|
|
736
750
|
//#region src/integration/orm/expectQueryResult.ts
|
|
751
|
+
/**
|
|
752
|
+
* Assert that a query result matches an expected value using structural equality.
|
|
753
|
+
*/
|
|
737
754
|
async function expectQueryResult(actual, expected) {
|
|
738
755
|
const resolved = await actual;
|
|
739
756
|
const resolvedJson = JSON.stringify(resolved);
|
|
740
757
|
const expectedJson = JSON.stringify(expected);
|
|
741
758
|
if (resolvedJson !== expectedJson) throw new Error(`Expected query result ${expectedJson}, got ${resolvedJson}`);
|
|
742
759
|
}
|
|
743
|
-
|
|
744
760
|
//#endregion
|
|
745
761
|
//#region src/integration/index.ts
|
|
746
|
-
var integration_exports = {
|
|
747
|
-
__export(integration_exports, {
|
|
762
|
+
var integration_exports = /* @__PURE__ */ __exportAll({
|
|
748
763
|
AppProcessHarness: () => AppProcessHarness,
|
|
749
764
|
Dialect: () => Dialect,
|
|
750
765
|
HarnessStrategyRegistry: () => HarnessStrategyRegistry,
|
|
@@ -768,7 +783,7 @@ __export(integration_exports, {
|
|
|
768
783
|
setupTestTangoRuntime: () => setupTestTangoRuntime,
|
|
769
784
|
smoke: () => smoke_exports
|
|
770
785
|
});
|
|
771
|
-
|
|
772
786
|
//#endregion
|
|
773
|
-
export {
|
|
774
|
-
|
|
787
|
+
export { Dialect as C, ResetMode as S, migrations_exports as _, seedTable as a, assertMigrationPlan as b, anIntegrationHarness as c, runtime_exports as d, setupTestTangoRuntime as f, runDialectConformanceSuite as g, conformance_exports as h, createModelQuerySetFixture as i, smoke_exports as l, aTangoConfig as m, expectQueryResult as n, TestHarness as o, aTangoRuntime as p, createQuerySetFixture as r, HarnessStrategyRegistry as s, integration_exports as t, AppProcessHarness as u, introspectSchema as v, domain_exports as x, applyAndVerifyMigrations as y };
|
|
788
|
+
|
|
789
|
+
//# sourceMappingURL=integration-CLzkacon.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"integration-CLzkacon.js","names":["PostgresAdapter","SqliteAdapter"],"sources":["../src/integration/domain/Dialect.ts","../src/integration/domain/ResetMode.ts","../src/integration/domain/index.ts","../src/integration/migrations/AssertMigrationPlan.ts","../src/integration/migrations/ApplyAndVerifyMigrations.ts","../src/integration/migrations/IntrospectSchema.ts","../src/integration/migrations/index.ts","../src/integration/conformance/runDialectConformanceSuite.ts","../src/integration/conformance/index.ts","../src/integration/runtime/aTangoConfig.ts","../src/integration/runtime/aTangoRuntime.ts","../src/integration/runtime/setupTestTangoRuntime.ts","../src/integration/runtime/index.ts","../src/integration/smoke/AppProcessHarness.ts","../src/integration/smoke/index.ts","../src/integration/anIntegrationHarness.ts","../src/integration/HarnessStrategyRegistry.ts","../src/integration/config.ts","../src/integration/strategies/PostgresHarnessStrategy.ts","../src/integration/strategies/SqliteHarnessStrategy.ts","../src/integration/TestHarness.ts","../src/integration/orm/seedTable.ts","../src/integration/orm/createModelQuerySetFixture.ts","../src/integration/orm/createQuerySetFixture.ts","../src/integration/orm/expectQueryResult.ts","../src/integration/index.ts"],"sourcesContent":["export const Dialect = {\n Sqlite: 'sqlite',\n Postgres: 'postgres',\n} as const;\n\nexport type Dialect = (typeof Dialect)[keyof typeof Dialect];\n","export const ResetMode = {\n Transaction: 'transaction',\n Truncate: 'truncate',\n DropSchema: 'drop-schema',\n} as const;\n\nexport type ResetMode = (typeof ResetMode)[keyof typeof ResetMode];\n","/**\n * Domain boundary barrel: centralizes this subdomain's public contract.\n */\n\nexport { Dialect } from './Dialect';\nexport type { HarnessOptions, HarnessStrategy } from './HarnessStrategy';\nexport type { DialectTestCapabilities, IntegrationHarness } from './IntegrationHarness';\nexport { ResetMode } from './ResetMode';\n","import type { IntegrationHarness } from '../domain';\n\nexport type AssertMigrationPlanOptions = {\n migrationsDir: string;\n expectSqlContains?: string[];\n};\n\n/**\n * Generate a migration plan through a harness and assert that required SQL fragments appear.\n */\nexport async function assertMigrationPlan(\n harness: IntegrationHarness,\n options: AssertMigrationPlanOptions\n): Promise<string> {\n const runner = harness.migrationRunner(options.migrationsDir);\n const plan = await runner.plan();\n\n for (const snippet of options.expectSqlContains ?? []) {\n if (!plan.includes(snippet)) {\n throw new Error(`Expected migration plan to contain: ${snippet}`);\n }\n }\n\n return plan;\n}\n","import type { IntegrationHarness } from '../domain';\n\nexport type ApplyAndVerifyMigrationsOptions = {\n migrationsDir: string;\n toId?: string;\n expectedAppliedIds?: string[];\n};\n\nexport type MigrationStatus = { id: string; applied: boolean };\n\n/**\n * Apply migrations through a harness and optionally verify that specific ids were applied.\n */\nexport async function applyAndVerifyMigrations(\n harness: IntegrationHarness,\n options: ApplyAndVerifyMigrationsOptions\n): Promise<{ statuses: MigrationStatus[] }> {\n const runner = harness.migrationRunner(options.migrationsDir);\n await runner.apply(options.toId);\n const statuses = await runner.status();\n\n for (const id of options.expectedAppliedIds ?? []) {\n const row = statuses.find((status: MigrationStatus) => status.id === id);\n if (!row || !row.applied) {\n throw new Error(`Expected migration ${id} to be applied`);\n }\n }\n\n return { statuses };\n}\n","import { createDefaultIntrospectorStrategy } from '@danceroutine/tango-migrations';\nimport type { Dialect as MigrationDialect } from '@danceroutine/tango-migrations';\nimport { Dialect, type IntegrationHarness } from '../domain';\n\nconst introspectorStrategy = createDefaultIntrospectorStrategy();\n\n/**\n * Introspect the schema visible to a harness using Tango's built-in introspectors.\n */\nexport async function introspectSchema(harness: IntegrationHarness): Promise<unknown> {\n if (harness.dialect !== Dialect.Postgres && harness.dialect !== Dialect.Sqlite) {\n throw new Error(`No introspector registered for dialect: ${String(harness.dialect)}`);\n }\n const dialect = harness.dialect === Dialect.Postgres ? 'postgres' : 'sqlite';\n return introspectorStrategy.introspect(dialect as unknown as MigrationDialect, harness.dbClient);\n}\n","/**\n * Domain boundary barrel: centralizes this subdomain's public contract.\n */\n\nexport { assertMigrationPlan, type AssertMigrationPlanOptions } from './AssertMigrationPlan';\nexport {\n applyAndVerifyMigrations,\n type ApplyAndVerifyMigrationsOptions,\n type MigrationStatus,\n} from './ApplyAndVerifyMigrations';\nexport { introspectSchema } from './IntrospectSchema';\n","import type { HarnessOptions, HarnessStrategy } from '../domain';\n\n/**\n * Shared conformance checks every harness strategy must satisfy.\n *\n * This is intentionally framework-agnostic so first-party and third-party\n * strategies can run the same lifecycle validation.\n */\nexport async function runDialectConformanceSuite(\n strategy: HarnessStrategy,\n options: {\n createOptions?: HarnessOptions;\n migrationsDir?: string;\n } = {}\n): Promise<void> {\n const harness = await strategy.create(options.createOptions);\n\n if (harness.dialect !== strategy.dialect) {\n throw new Error(\n `Conformance failed: harness dialect '${String(harness.dialect)}' does not match strategy dialect '${String(strategy.dialect)}'`\n );\n }\n\n if (harness.capabilities !== strategy.capabilities) {\n throw new Error('Conformance failed: harness capabilities must be strategy capabilities reference');\n }\n\n let resetBeforeSetupThrew = false;\n try {\n await harness.reset();\n } catch {\n resetBeforeSetupThrew = true;\n }\n if (!resetBeforeSetupThrew) {\n throw new Error('Conformance failed: reset() must throw before setup()');\n }\n\n await harness.setup();\n await harness.reset();\n harness.migrationRunner(options.migrationsDir ?? '/tmp/migrations');\n await harness.teardown();\n\n let dbClientAfterTeardownThrew = false;\n try {\n // Access after teardown should fail to prevent stale client usage.\n\n // oxlint-disable-next-line no-unused-expressions\n harness.dbClient;\n } catch {\n dbClientAfterTeardownThrew = true;\n }\n if (!dbClientAfterTeardownThrew) {\n throw new Error('Conformance failed: dbClient getter must throw after teardown()');\n }\n}\n","export { runDialectConformanceSuite } from './runDialectConformanceSuite';\n","import { defineConfig, type TangoConfig } from '@danceroutine/tango-config';\n\nexport type TestTangoConfigOptions = {\n adapter?: 'sqlite' | 'postgres';\n sqliteFilename?: string;\n};\n\n/**\n * Create a stable Tango config fixture for runtime-oriented tests.\n */\nexport function aTangoConfig(options: TestTangoConfigOptions = {}): TangoConfig {\n const adapter = options.adapter ?? 'sqlite';\n const sqliteFilename = options.sqliteFilename ?? ':memory:';\n\n return defineConfig({\n current: 'test',\n environments: {\n development: {\n name: 'development',\n db:\n adapter === 'sqlite'\n ? { adapter: 'sqlite', filename: sqliteFilename, maxConnections: 1 }\n : {\n adapter: 'postgres',\n url: 'postgres://postgres:postgres@localhost:5432/tango',\n maxConnections: 1,\n },\n migrations: { dir: 'migrations', online: adapter === 'postgres' },\n },\n test: {\n name: 'test',\n db:\n adapter === 'sqlite'\n ? { adapter: 'sqlite', filename: sqliteFilename, maxConnections: 1 }\n : {\n adapter: 'postgres',\n url: 'postgres://postgres:postgres@localhost:5432/tango_test',\n maxConnections: 1,\n },\n migrations: { dir: 'migrations', online: adapter === 'postgres' },\n },\n production: {\n name: 'production',\n db:\n adapter === 'sqlite'\n ? { adapter: 'sqlite', filename: sqliteFilename, maxConnections: 1 }\n : {\n adapter: 'postgres',\n url: 'postgres://postgres:postgres@localhost:5432/tango',\n maxConnections: 1,\n },\n migrations: { dir: 'migrations', online: adapter === 'postgres' },\n },\n },\n });\n}\n","import { loadConfig } from '@danceroutine/tango-config';\nimport { TangoRuntime } from '@danceroutine/tango-orm';\nimport { aTangoConfig, type TestTangoConfigOptions } from './aTangoConfig';\n\n/**\n * Create a standalone Tango runtime for tests without mutating the process-default runtime.\n */\nexport function aTangoRuntime(options: TestTangoConfigOptions = {}): TangoRuntime {\n return new TangoRuntime(() => loadConfig(() => aTangoConfig(options)));\n}\n","import { initializeTangoRuntime, resetTangoRuntime, type TangoRuntime } from '@danceroutine/tango-orm';\nimport { aTangoConfig, type TestTangoConfigOptions } from './aTangoConfig';\n\n/**\n * Reset and initialize the process-default Tango runtime for tests.\n */\nexport async function setupTestTangoRuntime(options: TestTangoConfigOptions = {}): Promise<TangoRuntime> {\n await resetTangoRuntime();\n return initializeTangoRuntime(() => aTangoConfig(options));\n}\n","/**\n * Domain boundary barrel: centralizes runtime-oriented integration fixtures.\n */\n\nexport { aTangoConfig } from './aTangoConfig';\nexport type { TestTangoConfigOptions } from './aTangoConfig';\nexport { aTangoRuntime } from './aTangoRuntime';\nexport { setupTestTangoRuntime } from './setupTestTangoRuntime';\n","import { spawn } from 'node:child_process';\n\nexport interface AppProcessHarnessOptions {\n command: string;\n args?: string[];\n cwd?: string;\n env?: Record<string, string | undefined>;\n baseUrl: string;\n readyPath?: string;\n readyTimeoutMs?: number;\n readyIntervalMs?: number;\n stopTimeoutMs?: number;\n}\n\ntype FetchLike = typeof fetch;\ntype ProcessHarnessOutputStream = {\n on(eventName: 'data', listener: (chunk: unknown) => void): unknown;\n};\ntype ProcessHarnessChild = {\n exitCode: number | null;\n killed: boolean;\n kill(signal?: NodeJS.Signals): boolean;\n off(eventName: 'exit', listener: () => void): unknown;\n once(eventName: 'exit', listener: () => void): unknown;\n stdout?: ProcessHarnessOutputStream | null;\n stderr?: ProcessHarnessOutputStream | null;\n};\n\ninterface AppProcessHarnessDeps {\n spawnProcess: (\n command: string,\n args?: readonly string[],\n options?: Parameters<typeof spawn>[2]\n ) => ProcessHarnessChild;\n fetchImpl: FetchLike;\n sleep: (ms: number) => Promise<void>;\n}\n\nconst DEFAULT_READY_TIMEOUT_MS = 30_000;\nconst DEFAULT_READY_INTERVAL_MS = 250;\nconst DEFAULT_STOP_TIMEOUT_MS = 10_000;\nconst MAX_LOG_BUFFER_CHARS = 20_000;\n\nconst defaultDeps: AppProcessHarnessDeps = {\n spawnProcess: (command, args, options) => spawn(command, args as string[], options as Parameters<typeof spawn>[2]),\n fetchImpl: fetch,\n sleep: (ms: number) =>\n new Promise((resolve) => {\n setTimeout(resolve, ms);\n }),\n};\n\n/**\n * Lightweight process harness for end-to-end smoke tests that need a real app process.\n */\nexport class AppProcessHarness {\n static readonly BRAND = 'tango.testing.app_process_harness' as const;\n readonly __tangoBrand: typeof AppProcessHarness.BRAND = AppProcessHarness.BRAND;\n private readonly child: ProcessHarnessChild;\n private readonly baseUrl: string;\n private readonly readyUrl: string;\n private readonly readyTimeoutMs: number;\n private readonly readyIntervalMs: number;\n private readonly stopTimeoutMs: number;\n private readonly deps: AppProcessHarnessDeps;\n private stopped = false;\n private stdoutBuffer = '';\n private stderrBuffer = '';\n\n private constructor(options: AppProcessHarnessOptions, deps: AppProcessHarnessDeps) {\n this.baseUrl = options.baseUrl.replace(/\\/+$/, '');\n this.readyUrl = `${this.baseUrl}${normalizePath(options.readyPath ?? '/health')}`;\n this.readyTimeoutMs = options.readyTimeoutMs ?? DEFAULT_READY_TIMEOUT_MS;\n this.readyIntervalMs = options.readyIntervalMs ?? DEFAULT_READY_INTERVAL_MS;\n this.stopTimeoutMs = options.stopTimeoutMs ?? DEFAULT_STOP_TIMEOUT_MS;\n this.deps = deps;\n\n this.child = this.deps.spawnProcess(options.command, options.args ?? [], {\n cwd: options.cwd,\n env: { ...process.env, ...options.env },\n stdio: 'pipe',\n });\n this.child.stdout?.on('data', (chunk: unknown) => {\n this.stdoutBuffer = appendBuffer(this.stdoutBuffer, String(chunk));\n });\n this.child.stderr?.on('data', (chunk: unknown) => {\n this.stderrBuffer = appendBuffer(this.stderrBuffer, String(chunk));\n });\n }\n\n /**\n * Narrow an unknown value to the smoke-test harness that owns a child process.\n */\n static isAppProcessHarness(value: unknown): value is AppProcessHarness {\n return (\n typeof value === 'object' &&\n value !== null &&\n (value as { __tangoBrand?: unknown }).__tangoBrand === AppProcessHarness.BRAND\n );\n }\n\n /**\n * Spawn the target process and wait until its readiness endpoint responds successfully.\n */\n static async start(\n options: AppProcessHarnessOptions,\n deps: Partial<AppProcessHarnessDeps> = {}\n ): Promise<AppProcessHarness> {\n const mergedDeps: AppProcessHarnessDeps = {\n ...defaultDeps,\n ...deps,\n };\n const harness = new AppProcessHarness(options, mergedDeps);\n await harness.waitForReady();\n return harness;\n }\n\n /**\n * Return the buffered stdout log for recent process output.\n */\n getStdoutLog(): string {\n return this.stdoutBuffer;\n }\n\n /**\n * Return the buffered stderr log for recent process output.\n */\n getStderrLog(): string {\n return this.stderrBuffer;\n }\n\n /**\n * Return stdout and stderr in a single formatted string for debugging failures.\n */\n getCombinedLog(): string {\n const stdout = this.stdoutBuffer.trim();\n const stderr = this.stderrBuffer.trim();\n if (!stdout && !stderr) {\n return '';\n }\n return [`[stdout]\\n${stdout}`, `[stderr]\\n${stderr}`].join('\\n\\n').trim();\n }\n\n /**\n * Issue an HTTP request against the managed application process.\n */\n async request(path: string, init?: RequestInit): Promise<Response> {\n const target = path.startsWith('http') ? path : `${this.baseUrl}${normalizePath(path)}`;\n return this.deps.fetchImpl(target, init);\n }\n\n /**\n * Assert an HTTP response status and include process logs when it mismatches.\n */\n async assertResponseStatus(response: Response, expectedStatus: number, label: string): Promise<void> {\n if (response.status === expectedStatus) {\n return;\n }\n\n let bodyText: string;\n try {\n bodyText = await response.text();\n } catch (error) {\n bodyText = `failed to read response body: ${String(error)}`;\n }\n\n throw new Error(\n [\n `${label}. expected ${String(expectedStatus)} got ${String(response.status)}`,\n `response body: ${bodyText}`,\n `process logs:\\n${this.getCombinedLog()}`,\n ].join('\\n')\n );\n }\n\n /**\n * Stop the managed process, escalating from SIGTERM to SIGKILL when necessary.\n */\n async stop(): Promise<void> {\n if (this.stopped) {\n return;\n }\n this.stopped = true;\n\n if (this.child.exitCode !== null || this.child.killed) {\n return;\n }\n\n this.child.kill('SIGTERM');\n const exited = await this.waitForExit(this.stopTimeoutMs);\n if (!exited && !this.child.killed) {\n this.child.kill('SIGKILL');\n await this.waitForExit(this.stopTimeoutMs);\n }\n }\n\n private async waitForReady(): Promise<void> {\n const deadline = Date.now() + this.readyTimeoutMs;\n\n while (Date.now() < deadline) {\n if (this.child.exitCode !== null) {\n throw new Error(\n `Process exited before ready check succeeded (exitCode=${String(this.child.exitCode)}).\\n${this.getCombinedLog()}`\n );\n }\n try {\n const response = await this.deps.fetchImpl(this.readyUrl);\n if (response.ok) {\n return;\n }\n } catch {\n // Retry until timeout.\n }\n await this.deps.sleep(this.readyIntervalMs);\n }\n\n await this.stop();\n throw new Error(`Timed out waiting for readiness at ${this.readyUrl}.\\n${this.getCombinedLog()}`);\n }\n\n private async waitForExit(timeoutMs: number): Promise<boolean> {\n if (this.child.exitCode !== null) {\n return true;\n }\n\n return await new Promise<boolean>((resolve) => {\n const timer = setTimeout(() => {\n this.child.off('exit', onExit);\n resolve(false);\n }, timeoutMs);\n\n const onExit = () => {\n clearTimeout(timer);\n resolve(true);\n };\n\n this.child.once('exit', onExit);\n });\n }\n}\n\nfunction appendBuffer(current: string, chunk: string): string {\n const next = current + chunk;\n if (next.length <= MAX_LOG_BUFFER_CHARS) {\n return next;\n }\n return next.slice(next.length - MAX_LOG_BUFFER_CHARS);\n}\n\nfunction normalizePath(path: string): string {\n if (!path) {\n return '/';\n }\n return path.startsWith('/') ? path : `/${path}`;\n}\n","/**\n * Domain boundary barrel: centralizes this subdomain's public contract.\n */\n\nexport * from './AppProcessHarness';\n","import { vi } from 'vitest';\nimport { anAdapter } from '../mocks/anAdapter';\nimport { aDBClient } from '../mocks/aDBClient';\nimport { Dialect } from './domain/Dialect';\nimport { ResetMode } from './domain/ResetMode';\nimport type { DialectTestCapabilities, IntegrationHarness } from './domain/IntegrationHarness';\n\nconst defaultCapabilities: DialectTestCapabilities = {\n transactionalDDL: true,\n supportsSchemas: false,\n supportsConcurrentIndex: false,\n supportsDeferredFkValidation: false,\n supportsJsonb: false,\n};\n\n/**\n * Create an integration-harness fixture with optional overrides.\n */\nexport function anIntegrationHarness(overrides: Partial<IntegrationHarness> = {}): IntegrationHarness {\n return {\n dialect: Dialect.Sqlite,\n adapter: anAdapter({ dialect: 'sqlite' }),\n capabilities: defaultCapabilities,\n resetMode: ResetMode.DropSchema,\n dbClient: aDBClient(),\n setup: vi.fn(async () => {}),\n reset: vi.fn(async () => {}),\n teardown: vi.fn(async () => {}),\n migrationRunner: vi.fn(() => ({}) as never),\n ...overrides,\n };\n}\n","import type { Dialect, HarnessStrategy } from './domain';\n\n/**\n * Registry of test harness strategies keyed by dialect.\n */\nexport class HarnessStrategyRegistry {\n static readonly BRAND = 'tango.testing.harness_strategy_registry' as const;\n readonly __tangoBrand: typeof HarnessStrategyRegistry.BRAND = HarnessStrategyRegistry.BRAND;\n private readonly strategies = new Map<string, HarnessStrategy>();\n\n /**\n * Narrow an unknown value to `HarnessStrategyRegistry`.\n */\n static isHarnessStrategyRegistry(value: unknown): value is HarnessStrategyRegistry {\n return (\n typeof value === 'object' &&\n value !== null &&\n (value as { __tangoBrand?: unknown }).__tangoBrand === HarnessStrategyRegistry.BRAND\n );\n }\n\n /**\n * Register or replace a dialect strategy.\n */\n register(strategy: HarnessStrategy): this {\n this.strategies.set(String(strategy.dialect), strategy);\n return this;\n }\n\n /**\n * Resolve a strategy for a dialect, or throw if none is registered.\n */\n get(dialect: Dialect | string): HarnessStrategy {\n const strategy = this.strategies.get(String(dialect));\n if (!strategy) {\n throw new Error(`No harness strategy registered for dialect: ${String(dialect)}`);\n }\n return strategy;\n }\n\n /**\n * List all registered strategies.\n */\n list(): readonly HarnessStrategy[] {\n return [...this.strategies.values()];\n }\n}\n","import type { AdapterConfig } from '@danceroutine/tango-orm';\nimport { loadConfig } from '@danceroutine/tango-config';\nimport { Dialect } from './domain';\n\nfunction readNumber(value: string | undefined): number | undefined {\n if (!value) return undefined;\n const parsed = Number(value);\n return Number.isFinite(parsed) ? parsed : undefined;\n}\n\n/**\n * Resolve adapter configuration for a test harness from explicit options,\n * typed Tango config, and environment variables in that order.\n */\nexport function resolveAdapterConfig(\n dialect: Dialect,\n opts: {\n config?: Partial<AdapterConfig>;\n tangoConfigLoader?: () => unknown;\n sqliteFile?: string;\n }\n): AdapterConfig {\n const fromOptions = opts.config ?? {};\n\n if (opts.tangoConfigLoader) {\n const loaded = loadConfig(opts.tangoConfigLoader);\n const current = loaded.current.db;\n const merged: AdapterConfig = {\n url: fromOptions.url ?? current.url,\n host: fromOptions.host ?? current.host,\n port: fromOptions.port ?? current.port,\n database: fromOptions.database ?? current.database,\n user: fromOptions.user ?? current.user,\n password: fromOptions.password ?? current.password,\n filename: fromOptions.filename ?? current.filename,\n maxConnections: fromOptions.maxConnections ?? current.maxConnections,\n };\n if (dialect === Dialect.Sqlite) {\n merged.filename = opts.sqliteFile ?? merged.filename ?? ':memory:';\n }\n return merged;\n }\n\n if (dialect === Dialect.Postgres) {\n return {\n url: fromOptions.url ?? process.env.TANGO_DATABASE_URL ?? process.env.DATABASE_URL,\n host: fromOptions.host ?? process.env.TANGO_DB_HOST,\n port: fromOptions.port ?? readNumber(process.env.TANGO_DB_PORT),\n database: fromOptions.database ?? process.env.TANGO_DB_NAME,\n user: fromOptions.user ?? process.env.TANGO_DB_USER,\n password: fromOptions.password ?? process.env.TANGO_DB_PASSWORD,\n maxConnections: fromOptions.maxConnections ?? 10,\n };\n }\n\n return {\n filename: opts.sqliteFile ?? fromOptions.filename ?? process.env.TANGO_SQLITE_FILENAME ?? ':memory:',\n maxConnections: fromOptions.maxConnections ?? 1,\n };\n}\n","import { quoteSqlIdentifier, validateSqlIdentifier } from '@danceroutine/tango-core';\nimport { MigrationRunner } from '@danceroutine/tango-migrations';\nimport type { Dialect as MigrationDialect } from '@danceroutine/tango-migrations';\nimport { PostgresAdapter } from '@danceroutine/tango-orm/connection';\nimport type { DBClient } from '@danceroutine/tango-orm';\nimport { resolveAdapterConfig } from '../config';\nimport {\n Dialect,\n ResetMode,\n type DialectTestCapabilities,\n type HarnessOptions,\n type HarnessStrategy,\n type IntegrationHarness,\n} from '../domain';\n\n/**\n * Harness strategy for PostgreSQL-backed integration tests.\n */\nexport class PostgresHarnessStrategy implements HarnessStrategy {\n static readonly BRAND = 'tango.testing.postgres_harness_strategy' as const;\n readonly __tangoBrand: typeof PostgresHarnessStrategy.BRAND = PostgresHarnessStrategy.BRAND;\n readonly dialect: Dialect = Dialect.Postgres;\n readonly capabilities: DialectTestCapabilities = {\n transactionalDDL: true,\n supportsSchemas: true,\n supportsConcurrentIndex: true,\n supportsDeferredFkValidation: true,\n supportsJsonb: true,\n };\n\n /**\n * Narrow an unknown value to the PostgreSQL integration harness strategy.\n */\n static isPostgresHarnessStrategy(value: unknown): value is PostgresHarnessStrategy {\n return (\n typeof value === 'object' &&\n value !== null &&\n (value as { __tangoBrand?: unknown }).__tangoBrand === PostgresHarnessStrategy.BRAND\n );\n }\n\n private static buildSchemaName(explicitSchema?: string): string {\n if (explicitSchema) return explicitSchema;\n const random = Math.random().toString(36).slice(2, 8);\n return `tango_test_${Date.now()}_${random}`;\n }\n\n /**\n * Create a configured Postgres integration harness instance.\n */\n async create(options: HarnessOptions = {}): Promise<IntegrationHarness> {\n const config = resolveAdapterConfig(Dialect.Postgres, {\n config: options.config,\n tangoConfigLoader: options.tangoConfigLoader,\n });\n\n const adapter = new PostgresAdapter();\n const schemaName = PostgresHarnessStrategy.buildSchemaName(options.schema);\n const resetMode = options.resetMode ?? ResetMode.DropSchema;\n let client: DBClient | null = null;\n\n const ensureSearchPath = async (): Promise<void> => {\n const dbClient = client as DBClient;\n const schema = quoteSqlIdentifier(validateSqlIdentifier(schemaName, 'schema'), 'postgres');\n await dbClient.query(`CREATE SCHEMA IF NOT EXISTS ${schema}`);\n await dbClient.query(`SET search_path TO ${schema}`);\n };\n\n const recreateSchema = async (): Promise<void> => {\n const dbClient = client as DBClient;\n const schema = quoteSqlIdentifier(validateSqlIdentifier(schemaName, 'schema'), 'postgres');\n await dbClient.query(`DROP SCHEMA IF EXISTS ${schema} CASCADE`);\n await dbClient.query(`CREATE SCHEMA ${schema}`);\n await dbClient.query(`SET search_path TO ${schema}`);\n };\n\n const harness: IntegrationHarness = {\n dialect: Dialect.Postgres,\n adapter,\n capabilities: this.capabilities,\n resetMode,\n get dbClient(): DBClient {\n if (!client) {\n throw new Error('Postgres harness not initialized. Call setup() first.');\n }\n return client;\n },\n async setup(): Promise<void> {\n client = await adapter.connect(config);\n await ensureSearchPath();\n },\n async reset(): Promise<void> {\n if (!client) {\n throw new Error('Postgres harness not initialized. Call setup() first.');\n }\n if (resetMode === ResetMode.DropSchema || resetMode === ResetMode.Transaction) {\n await recreateSchema();\n return;\n }\n\n const { rows } = await client.query<{ table_name: string }>(\n `SELECT table_name FROM information_schema.tables WHERE table_schema = $1 AND table_type = 'BASE TABLE'`,\n [schemaName]\n );\n for (const row of rows) {\n const schema = quoteSqlIdentifier(validateSqlIdentifier(schemaName, 'schema'), 'postgres');\n const table = quoteSqlIdentifier(\n validateSqlIdentifier(String(row.table_name), 'table'),\n 'postgres'\n );\n await client.query(`TRUNCATE TABLE ${schema}.${table} RESTART IDENTITY CASCADE`);\n }\n await client.query(\n `SET search_path TO ${quoteSqlIdentifier(validateSqlIdentifier(schemaName, 'schema'), 'postgres')}`\n );\n },\n async teardown(): Promise<void> {\n if (!client) return;\n try {\n await client.query(\n `DROP SCHEMA IF EXISTS ${quoteSqlIdentifier(validateSqlIdentifier(schemaName, 'schema'), 'postgres')} CASCADE`\n );\n } finally {\n await client.close();\n client = null;\n }\n },\n migrationRunner(migrationsDir: string): MigrationRunner {\n if (!client) {\n throw new Error('Postgres harness not initialized. Call setup() first.');\n }\n return new MigrationRunner(client, 'postgres' as MigrationDialect, migrationsDir);\n },\n };\n\n return harness;\n }\n}\n","import { rm } from 'node:fs/promises';\nimport { quoteSqlIdentifier, validateSqlIdentifier } from '@danceroutine/tango-core';\nimport { MigrationRunner } from '@danceroutine/tango-migrations';\nimport type { Dialect as MigrationDialect } from '@danceroutine/tango-migrations';\nimport { SqliteAdapter } from '@danceroutine/tango-orm/connection';\nimport type { DBClient } from '@danceroutine/tango-orm';\nimport { resolveAdapterConfig } from '../config';\nimport {\n Dialect,\n ResetMode,\n type DialectTestCapabilities,\n type HarnessOptions,\n type HarnessStrategy,\n type IntegrationHarness,\n} from '../domain';\n\n/**\n * Harness strategy for SQLite-backed integration tests.\n */\nexport class SqliteHarnessStrategy implements HarnessStrategy {\n static readonly BRAND = 'tango.testing.sqlite_harness_strategy' as const;\n readonly __tangoBrand: typeof SqliteHarnessStrategy.BRAND = SqliteHarnessStrategy.BRAND;\n readonly dialect: Dialect = Dialect.Sqlite;\n readonly capabilities: DialectTestCapabilities = {\n transactionalDDL: true,\n supportsSchemas: false,\n supportsConcurrentIndex: false,\n supportsDeferredFkValidation: false,\n supportsJsonb: false,\n };\n\n /**\n * Narrow an unknown value to the SQLite integration harness strategy.\n */\n static isSqliteHarnessStrategy(value: unknown): value is SqliteHarnessStrategy {\n return (\n typeof value === 'object' &&\n value !== null &&\n (value as { __tangoBrand?: unknown }).__tangoBrand === SqliteHarnessStrategy.BRAND\n );\n }\n\n private static async dropAllTables(client: DBClient): Promise<void> {\n const { rows } = await client.query<{ name: string }>(\n \"SELECT name FROM sqlite_master WHERE type='table' AND name NOT LIKE 'sqlite_%'\"\n );\n for (const row of rows) {\n const table = quoteSqlIdentifier(validateSqlIdentifier(String(row.name), 'table'), 'sqlite');\n await client.query(`DROP TABLE IF EXISTS ${table}`);\n }\n }\n\n /**\n * Create a configured SQLite integration harness instance.\n */\n async create(options: HarnessOptions = {}): Promise<IntegrationHarness> {\n const config = resolveAdapterConfig(Dialect.Sqlite, {\n config: options.config,\n tangoConfigLoader: options.tangoConfigLoader,\n sqliteFile: options.sqliteFile,\n });\n\n const adapter = new SqliteAdapter();\n const resetMode = options.resetMode ?? ResetMode.DropSchema;\n let client: DBClient | null = null;\n\n const reconnect = async (): Promise<DBClient> => {\n client = await adapter.connect(config);\n return client;\n };\n\n const harness: IntegrationHarness = {\n dialect: Dialect.Sqlite,\n adapter,\n capabilities: this.capabilities,\n resetMode,\n get dbClient(): DBClient {\n if (!client) {\n throw new Error('Sqlite harness not initialized. Call setup() first.');\n }\n return client;\n },\n async setup(): Promise<void> {\n await reconnect();\n },\n async reset(): Promise<void> {\n if (!client) {\n throw new Error('Sqlite harness not initialized. Call setup() first.');\n }\n\n if (resetMode === ResetMode.DropSchema && config.filename && config.filename !== ':memory:') {\n await client.close();\n await rm(config.filename, { force: true });\n await reconnect();\n return;\n }\n\n await SqliteHarnessStrategy.dropAllTables(client);\n },\n async teardown(): Promise<void> {\n if (client) {\n await client.close();\n client = null;\n }\n if (config.filename && config.filename !== ':memory:') {\n await rm(config.filename, { force: true });\n }\n },\n migrationRunner(migrationsDir: string): MigrationRunner {\n if (!client) {\n throw new Error('Sqlite harness not initialized. Call setup() first.');\n }\n return new MigrationRunner(client, 'sqlite' as MigrationDialect, migrationsDir);\n },\n };\n\n return harness;\n }\n}\n","import { HarnessStrategyRegistry } from './HarnessStrategyRegistry';\nimport { Dialect, type HarnessOptions, type HarnessStrategy, type IntegrationHarness } from './domain';\nimport { PostgresHarnessStrategy } from './strategies/PostgresHarnessStrategy';\nimport { SqliteHarnessStrategy } from './strategies/SqliteHarnessStrategy';\n\n/**\n * Facade for creating integration test harnesses by dialect.\n */\nexport class TestHarness {\n static readonly BRAND = 'tango.testing.test_harness' as const;\n private static defaultRegistry: HarnessStrategyRegistry | null = null;\n readonly __tangoBrand: typeof TestHarness.BRAND = TestHarness.BRAND;\n\n /**\n * Narrow an unknown value to `TestHarness`.\n */\n static isTestHarness(value: unknown): value is TestHarness {\n return (\n typeof value === 'object' &&\n value !== null &&\n (value as { __tangoBrand?: unknown }).__tangoBrand === TestHarness.BRAND\n );\n }\n\n /**\n * Register a harness strategy on the shared default registry.\n */\n static registerStrategy(strategy: HarnessStrategy): void {\n this.ensureRegistry().register(strategy);\n }\n\n /**\n * Return the shared harness strategy registry.\n */\n static getRegistry(): HarnessStrategyRegistry {\n return this.ensureRegistry();\n }\n\n /**\n * Create a dialect-specific harness from the registry.\n */\n static async forDialect(\n args: { dialect: Dialect | string; options?: HarnessOptions },\n registry?: HarnessStrategyRegistry\n ): Promise<IntegrationHarness> {\n const selectedRegistry = registry ?? this.ensureRegistry();\n const strategy = selectedRegistry.get(args.dialect);\n return strategy.create(args.options);\n }\n\n /**\n * Convenience helper for a SQLite test harness.\n */\n static async sqlite(options?: HarnessOptions): Promise<IntegrationHarness> {\n return this.forDialect({ dialect: Dialect.Sqlite, options });\n }\n\n /**\n * Convenience helper for a Postgres test harness.\n */\n static async postgres(options?: HarnessOptions): Promise<IntegrationHarness> {\n return this.forDialect({ dialect: Dialect.Postgres, options });\n }\n\n private static ensureRegistry(): HarnessStrategyRegistry {\n if (this.defaultRegistry) return this.defaultRegistry;\n\n const registry = new HarnessStrategyRegistry();\n registry.register(new SqliteHarnessStrategy());\n registry.register(new PostgresHarnessStrategy());\n this.defaultRegistry = registry;\n return registry;\n }\n}\n","import { quoteSqlIdentifier, validateSqlIdentifier, type SqlDialect } from '@danceroutine/tango-core';\nimport { Dialect, type IntegrationHarness } from '../domain/index';\n\n/**\n * Seed rows directly into a table for integration tests that need known fixtures.\n */\nexport async function seedTable<T extends Record<string, unknown>>(\n harness: IntegrationHarness,\n table: string,\n rows: T[]\n): Promise<void> {\n if (rows.length === 0) {\n return;\n }\n\n const columns = Object.keys(rows[0] ?? {});\n if (columns.length === 0) {\n return;\n }\n\n const dialect = harness.dialect as SqlDialect;\n const safeTable = quoteSqlIdentifier(validateSqlIdentifier(table, 'table'), dialect);\n const safeColumns = columns.map((column) =>\n quoteSqlIdentifier(validateSqlIdentifier(column, 'column', columns), dialect)\n );\n\n for (const row of rows) {\n const values = columns.map((column) => {\n const value = row[column];\n if (harness.dialect === Dialect.Sqlite && typeof value === 'boolean') {\n return value ? 1 : 0;\n }\n return value;\n });\n const placeholders =\n harness.dialect === Dialect.Postgres\n ? columns.map((_, index) => `$${index + 1}`).join(', ')\n : columns.map(() => '?').join(', ');\n\n await harness.dbClient.query(\n `INSERT INTO ${safeTable} (${safeColumns.join(', ')}) VALUES (${placeholders})`,\n values as unknown[]\n );\n }\n}\n","import { ModelQuerySet, QuerySet, type QueryExecutor } from '@danceroutine/tango-orm';\nimport type { TableMeta } from '@danceroutine/tango-orm/query';\nimport type { IntegrationHarness } from '../domain/index';\n\n/**\n * Create a `ModelQuerySet` fixture backed by a real integration harness and supplied table metadata.\n */\nexport function createModelQuerySetFixture<TModel extends Record<string, unknown>>(input: {\n harness: IntegrationHarness;\n meta: TableMeta;\n}): QuerySet<TModel> {\n const executor: QueryExecutor<TModel> = {\n meta: input.meta,\n client: input.harness.dbClient,\n adapter: input.harness.adapter,\n run: async (compiled) => {\n const result = await input.harness.dbClient.query<TModel>(compiled.sql, compiled.params);\n return result.rows;\n },\n };\n\n return new ModelQuerySet<TModel>(executor);\n}\n","import { getLogger } from '@danceroutine/tango-core';\nimport type { QuerySet } from '@danceroutine/tango-orm';\nimport type { TableMeta } from '@danceroutine/tango-orm/query';\nimport type { IntegrationHarness } from '../domain/index';\nimport { createModelQuerySetFixture } from './createModelQuerySetFixture';\n\nconst logger = getLogger('tango.testing.integration');\nlet hasWarned = false;\n\n/**\n * @deprecated Use `createModelQuerySetFixture(...)` instead.\n */\nexport function createQuerySetFixture<TModel extends Record<string, unknown>>(input: {\n harness: IntegrationHarness;\n meta: TableMeta;\n}): QuerySet<TModel> {\n if (!hasWarned) {\n hasWarned = true;\n logger.warn('`createQuerySetFixture(...)` is deprecated. Use `createModelQuerySetFixture(...)` instead.');\n }\n\n return createModelQuerySetFixture(input);\n}\n","/**\n * Assert that a query result matches an expected value using structural equality.\n */\nexport async function expectQueryResult<T>(actual: Promise<T> | T, expected: T): Promise<void> {\n const resolved = await actual;\n\n const resolvedJson = JSON.stringify(resolved);\n const expectedJson = JSON.stringify(expected);\n\n if (resolvedJson !== expectedJson) {\n throw new Error(`Expected query result ${expectedJson}, got ${resolvedJson}`);\n }\n}\n","/**\n * Domain boundary barrel: exposes namespaced exports for Django-style drill-down\n * imports and curated flat exports for TS-native ergonomics.\n */\n\nexport * as domain from './domain/index';\nexport * as migrations from './migrations/index';\nexport * as conformance from './conformance/index';\nexport * as runtime from './runtime/index';\nexport * as smoke from './smoke/index';\n\nexport * from './domain/index';\nexport * from './anIntegrationHarness';\nexport * from './HarnessStrategyRegistry';\nexport * from './TestHarness';\nexport * from './migrations/index';\nexport * from './conformance/index';\nexport * from './orm/index';\nexport * from './runtime/index';\nexport * from './smoke/index';\n"],"mappings":"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"}
|
package/dist/mocks/index.d.ts
CHANGED
|
@@ -1,20 +1,2 @@
|
|
|
1
|
-
|
|
2
|
-
|
|
3
|
-
*/
|
|
4
|
-
export { anAdapter } from './anAdapter';
|
|
5
|
-
export { aDBClient } from './aDBClient';
|
|
6
|
-
export { aManager } from './aManager';
|
|
7
|
-
export { aManyToManyRelatedManager } from './aManyToManyRelatedManager';
|
|
8
|
-
export { aModelQuerySet } from './aModelQuerySet';
|
|
9
|
-
export { aQueryResult } from './aQueryResult';
|
|
10
|
-
export { aQuerySet } from './aQuerySet';
|
|
11
|
-
export { aRequestContext } from './aRequestContext';
|
|
12
|
-
export { aQueryExecutor } from './aQueryExecutor';
|
|
13
|
-
export { aRelationMeta } from './aRelationMeta';
|
|
14
|
-
export type { AdapterOverrides } from './anAdapter';
|
|
15
|
-
export type { QueryExecutorOverrides } from './aQueryExecutor';
|
|
16
|
-
export type { ManagerOverrides } from './aManager';
|
|
17
|
-
export type { ManyToManyRelatedManagerFixture, ManyToManyRelatedManagerFixtureOverrides, } from './aManyToManyRelatedManager';
|
|
18
|
-
export type { DBClient } from './DBClient';
|
|
19
|
-
export type { MockQuerySetResult } from './MockQuerySetResult';
|
|
20
|
-
export type { RequestContextFixtureOptions } from './aRequestContext';
|
|
1
|
+
import { _ as DBClient, a as aQueryExecutor, c as aQuerySet, d as ManyToManyRelatedManagerFixture, f as ManyToManyRelatedManagerFixtureOverrides, g as aDBClient, h as aManager, i as QueryExecutorOverrides, l as aQueryResult, m as ManagerOverrides, n as MockQuerySetResult, o as RequestContextFixtureOptions, p as aManyToManyRelatedManager, r as aRelationMeta, s as aRequestContext, u as aModelQuerySet, v as AdapterOverrides, y as anAdapter } from "../index-CnUPgs3G.js";
|
|
2
|
+
export { type AdapterOverrides, type DBClient, type ManagerOverrides, type ManyToManyRelatedManagerFixture, type ManyToManyRelatedManagerFixtureOverrides, type MockQuerySetResult, type QueryExecutorOverrides, type RequestContextFixtureOptions, aDBClient, aManager, aManyToManyRelatedManager, aModelQuerySet, aQueryExecutor, aQueryResult, aQuerySet, aRelationMeta, aRequestContext, anAdapter };
|
package/dist/mocks/index.js
CHANGED
|
@@ -1,4 +1,3 @@
|
|
|
1
|
-
import {
|
|
2
|
-
import {
|
|
3
|
-
|
|
4
|
-
export { aDBClient, aManager, aManyToManyRelatedManager, aModelQuerySet, aQueryExecutor, aQueryResult, aQuerySet, aRelationMeta, aRequestContext, anAdapter };
|
|
1
|
+
import { n as anAdapter, t as aDBClient } from "../aDBClient-fMkIdR7p.js";
|
|
2
|
+
import { a as aManyToManyRelatedManager, c as aQueryExecutor, i as aQuerySet, l as aQueryResult, n as aRelationMeta, o as aManager, r as aRequestContext, s as aModelQuerySet } from "../mocks-JyZwO-W4.js";
|
|
3
|
+
export { aDBClient, aManager, aManyToManyRelatedManager, aModelQuerySet, aQueryExecutor, aQueryResult, aQuerySet, aRelationMeta, aRequestContext, anAdapter };
|