diff --git a/packages/drivers/driver-sql/src/sql-driver-datetime-mysql-storage.test.ts b/packages/drivers/driver-sql/src/sql-driver-datetime-mysql-storage.test.ts index de43ef4148..62aaea1be4 100644 --- a/packages/drivers/driver-sql/src/sql-driver-datetime-mysql-storage.test.ts +++ b/packages/drivers/driver-sql/src/sql-driver-datetime-mysql-storage.test.ts @@ -61,13 +61,27 @@ describe.skipIf(!URL)('Field.datetime on MySQL (#3942)', () => { await probe.disconnect(); }); + // ── Why this beforeEach carries an explicit 60_000 budget (#14213) ── + // The driver argument here is `MYSQL_CELL.config()` — unconditionally LIVE, + // not a parametrised `cell.config()` that would be SQLite for the sqlite + // cell — so every test in this suite pays a fresh live connect, a + // `drop table` and `initObjects(...)` schema-sync DDL against the cell's + // MySQL server. A beforeEach is the heaviest shape in this class: the cost is + // paid PER TEST, not once. + // ⚠️ A hook inherits `hookTimeout`, NOT `testTimeout`. Measured in this + // package's config (which sets neither, so both are vitest's own defaults): + // an unbudgeted hook dies at 10000ms ("Hook timed out in 10000ms"), not at + // the 5000ms an unbudgeted it() gets. Ten seconds is still a ceiling nobody + // chose for live work, and the third argument does lift it (measured). + // ⛔ NOT a claim that this hook is known to time out: it was found by a + // per-site AST walk over the package, never by a measured red. beforeEach(async () => { driver = new SqlDriver(MYSQL_CELL.config()); await driver.execute(`drop table if exists ${TABLE}`); await driver.initObjects([ { name: TABLE, fields: { label: { type: 'string' }, at: { type: 'datetime' } } }, ]); - }); + }, 60_000); afterEach(async () => { await driver.execute(`drop table if exists ${TABLE}`).catch(() => {}); @@ -155,6 +169,12 @@ describe.skipIf(!URL)('MySQL TIMESTAMP → DATETIME(3) migration (#3942)', () => const GOOD = '2026-03-20T12:34:56.000Z'; let driver: SqlDriver; + // ── Why this beforeEach carries an explicit 60_000 budget (#14213) ── + // Same live-cell reasoning as the #3942 suite's beforeEach above, and this + // one is heavier: it opens a SECOND live connection (`rawDriver()`) to build + // the legacy fixture — raw DDL plus an insert — before constructing the + // driver under test, all per test. A hook inherits `hookTimeout` (measured + // 10000ms), not `testTimeout` (5000ms); the third argument lifts it. beforeEach(async () => { // Build the table the way a pre-#3942 build did: TIMESTAMP columns, rows in // it. The legacy connection is pinned to UTC so the fixture's instants are @@ -178,7 +198,7 @@ describe.skipIf(!URL)('MySQL TIMESTAMP → DATETIME(3) migration (#3942)', () => await legacy.disconnect(); driver = new SqlDriver(MYSQL_CELL.config()); - }); + }, 60_000); afterEach(async () => { await driver.execute(`drop table if exists ${LEGACY}`).catch(() => {}); @@ -234,6 +254,12 @@ describe.skipIf(!URL)('os migrate plan lists the MySQL widening (#3954)', () => const SHAPE = { name: LEGACY, fields: { label: { type: 'string' }, at: { type: 'datetime' } } }; let driver: SqlDriver; + // ── Why this beforeEach carries an explicit 60_000 budget (#14213) ── + // Same live-cell reasoning as the two beforeEach hooks above. Heaviest of the + // three: a second live connection builds the legacy fixture with raw DDL and + // FIVE inserts before the driver under test is constructed — per test. + // A hook inherits `hookTimeout` (measured 10000ms), not `testTimeout` + // (5000ms); the third argument lifts it. beforeEach(async () => { const legacy = rawDriver(); await legacy.execute(`drop table if exists ${LEGACY}`); @@ -254,7 +280,7 @@ describe.skipIf(!URL)('os migrate plan lists the MySQL widening (#3954)', () => } await legacy.disconnect(); driver = new SqlDriver(MYSQL_CELL.config()); - }); + }, 60_000); afterEach(async () => { await driver.execute(`drop table if exists ${LEGACY}`).catch(() => {}); diff --git a/packages/drivers/driver-sql/src/sql-driver-datetime-postgres-timezone.test.ts b/packages/drivers/driver-sql/src/sql-driver-datetime-postgres-timezone.test.ts index b44f7632c2..2103f00088 100644 --- a/packages/drivers/driver-sql/src/sql-driver-datetime-postgres-timezone.test.ts +++ b/packages/drivers/driver-sql/src/sql-driver-datetime-postgres-timezone.test.ts @@ -49,20 +49,36 @@ describe.skipIf(!URL)('Field.datetime on Postgres is timezone-independent (#3912 let driver: SqlDriver; let serverTimeZone = ''; + // ── Why this beforeAll carries an explicit 60_000 budget (#14213) ── + // The driver argument here is `PG_CELL.config()` — unconditionally LIVE, not + // a parametrised `cell.config()` that would be SQLite for the sqlite cell — + // so this hook pays a full connect cycle against the cell's Postgres server, + // a `current_setting('TimeZone')` round trip and a disconnect. + // ⚠️ A hook inherits `hookTimeout`, NOT `testTimeout`. Measured in this + // package's config (which sets neither, so both are vitest's own defaults): + // an unbudgeted hook dies at 10000ms ("Hook timed out in 10000ms"), not at + // the 5000ms an unbudgeted it() gets. Ten seconds is still a ceiling nobody + // chose for live work, and the third argument does lift it (measured). + // ⛔ NOT a claim that this hook is known to time out: it was found by a + // per-site AST walk over the package, never by a measured red. beforeAll(async () => { const probe = new SqlDriver(PG_CELL.config()); const res: any = await probe.execute(`select current_setting('TimeZone') as tz`); serverTimeZone = ((res?.rows ?? res)[0] as any).tz; await probe.disconnect(); - }); + }, 60_000); + // ── Why this beforeEach carries an explicit 60_000 budget (#14213) ── + // Same live-cell reasoning as the beforeAll above, except this one is paid + // PER TEST rather than once: a fresh live connect, a `drop table ... cascade` + // and `initObjects(...)` schema-sync DDL, for every it() in this suite. beforeEach(async () => { driver = new SqlDriver(PG_CELL.config()); await driver.execute(`drop table if exists "${TABLE}" cascade`); await driver.initObjects([ { name: TABLE, fields: { label: { type: 'string' }, at: { type: 'datetime' } } }, ]); - }); + }, 60_000); afterEach(async () => { await driver.execute(`drop table if exists "${TABLE}" cascade`).catch(() => {}); diff --git a/packages/drivers/driver-sql/src/sql-driver-json-binding-without-ddl.test.ts b/packages/drivers/driver-sql/src/sql-driver-json-binding-without-ddl.test.ts index 670b54dc10..d764212bed 100644 --- a/packages/drivers/driver-sql/src/sql-driver-json-binding-without-ddl.test.ts +++ b/packages/drivers/driver-sql/src/sql-driver-json-binding-without-ddl.test.ts @@ -98,6 +98,19 @@ describe.skipIf(!PG_URL)('#10995 — live Postgres, driver told about the object let driver: SqlDriver; const TABLE = 'os10995_pref'; + // ── Why this beforeAll carries an explicit 60_000 budget (#14213) ── + // §1–§3 deliberately reuse the connection this hook opens, so the live cost + // of the whole suite is concentrated HERE: a full connect cycle against the + // cell's Postgres server plus the out-of-band `create table` in + // `migrateOutOfBand(...)`. (The §3 it() below is budgeted separately under + // #14100 because it builds a SECOND driver inside its own body.) + // ⚠️ A hook inherits `hookTimeout`, NOT `testTimeout`. Measured in this + // package's config (which sets neither, so both are vitest's own defaults): + // an unbudgeted hook dies at 10000ms ("Hook timed out in 10000ms"), not at + // the 5000ms an unbudgeted it() gets — so the 5000ms figure in §3's note + // below is correct for that it() and would be wrong for this hook. + // ⛔ NOT a claim that this hook is known to time out: it was found by a + // per-site AST walk over the package, never by a measured red. beforeAll(async () => { driver = new SqlDriver(PG_CELL.config()); await migrateOutOfBand(driver, TABLE); @@ -105,7 +118,7 @@ describe.skipIf(!PG_URL)('#10995 — live Postgres, driver told about the object // CREATE TABLE, no ALTER TABLE and no round-trip — what a `skipSchemaSync` // boot now does in place of doing nothing. driver.registerObjectMetadata([prefObject(TABLE)]); - }); + }, 60_000); afterAll(async () => { await driver?.disconnect(); diff --git a/packages/drivers/driver-sql/src/sql-driver-time-live-dialects.test.ts b/packages/drivers/driver-sql/src/sql-driver-time-live-dialects.test.ts index 85f70ddb33..d72529fc26 100644 --- a/packages/drivers/driver-sql/src/sql-driver-time-live-dialects.test.ts +++ b/packages/drivers/driver-sql/src/sql-driver-time-live-dialects.test.ts @@ -151,6 +151,19 @@ describe.skipIf(!MY_URL)('MySQL TIME → TIME(3) widening (#3994)', () => { const LEGACY = 'os3994_legacy'; let driver: SqlDriver; + // ── Why this beforeEach carries an explicit 60_000 budget (#14213) ── + // Both driver arguments here are `MYSQL_CELL.config()` — unconditionally + // LIVE, not the parametrised `cell.config()` the dialect sweep above uses — + // so this hook opens TWO live connections per test: one to build the legacy + // fixture with raw DDL and an insert, then the driver under test. A + // beforeEach pays that PER TEST, not once. + // ⚠️ A hook inherits `hookTimeout`, NOT `testTimeout`. Measured in this + // package's config (which sets neither, so both are vitest's own defaults): + // an unbudgeted hook dies at 10000ms ("Hook timed out in 10000ms"), not at + // the 5000ms an unbudgeted it() gets. Ten seconds is still a ceiling nobody + // chose for live work, and the third argument does lift it (measured). + // ⛔ NOT a claim that this hook is known to time out: it was found by a + // per-site AST walk over the package, never by a measured red. beforeEach(async () => { // Build the table the way a pre-#3994 build did: a bare TIME column. const legacy = new SqlDriver(MYSQL_CELL.config()); @@ -168,7 +181,7 @@ describe.skipIf(!MY_URL)('MySQL TIME → TIME(3) widening (#3994)', () => { await legacy.disconnect(); driver = new SqlDriver(MYSQL_CELL.config()); - }); + }, 60_000); afterEach(async () => { await driver.execute(`drop table if exists ${LEGACY}`).catch(() => {});