Relevant source files
The following files were used as context for generating this wiki page:
- integration-tests/vitest.config.ts
- integration-tests/package.json
- drizzle-kit/src/cli/connections.ts
- drizzle-orm/type-tests/singlestore/tables.ts
- drizzle-seed/vitest.config.ts
- drizzle-kit/src/api.ts
- drizzle-kit/vitest.config.ts
- integration-tests/vitest-ci.config.ts
- integration-tests/sst.config.ts
- drizzle-arktype/vitest.config.ts
- drizzle-orm/type-tests/sqlite/db.ts
- drizzle-orm/src/singlestore/session.ts
- drizzle-valibot/vitest.config.ts
- drizzle-orm/vitest.config.ts
- eslint-plugin-drizzle/vitest.config.ts
- drizzle-typebox/vitest.config.ts
- drizzle-kit/src/serializer/studio.ts
- drizzle-zod/vitest.config.ts
- drizzle-kit/src/sqlgenerator.ts
- drizzle-orm/src/pglite/driver.ts
- drizzle-orm/src/singlestore/driver.ts
- drizzle-seed/type-tests/pg.ts
- drizzle-orm/type-tests/singlestore/db.ts
- drizzle-seed/type-tests/sqlite.ts
- integration-tests/drizzle2/sqlite/meta/_journal.json
- integration-tests/drizzle2/pg/meta/_journal.json
- integration-tests/sst-env.d.ts
- integration-tests/drizzle2/singlestore/meta/_journal.json
- integration-tests/drizzle2/pg-proxy/first/meta/_journal.json
- drizzle-orm/type-tests/singlestore/select.ts
Overview
The integration test harness coordinates multi-dialect validation suites across local environments and continuous integration pipelines, verifying database driver behavior, schema migrations, and query execution semantics. By combining Vitest runner configurations, AWS SST infrastructure fixtures, and multi-dialect snapshot journals, the suite validates database interactions across SQLite, PostgreSQL, MySQL, SingleStore, and Gel.
Sources: integration-tests/vitest.config.ts:6-24, integration-tests/package.json:74-74, integration-tests/drizzle2/sqlite/meta/_journal.json:1-13
Vitest runner configuration across environments
Local and CI configuration structures
The integration test suite utilizes distinct Vitest runner configurations for local execution and continuous integration environments. Local runs are governed by integration-tests/vitest.config.ts, which loads environment variables via dotenv/config and resolves TypeScript path mappings through vite-tsconfig-paths. The local configuration explicitly defines inclusion globs covering relational tests, dialect-specific test suites, driver initializations, and vector or spatial extensions.
test: {
include: [
'tests/seeder/**/*.test.ts',
'tests/extensions/postgis/**/*',
'tests/relational/**/*.test.ts',
'tests/pg/**/*.test.ts',
'tests/mysql/**/*.test.ts',
'tests/singlestore/**/*.test.ts',
'tests/sqlite/**/*.test.ts',
'tests/replicas/**/*',
'tests/imports/**/*',
'tests/extensions/vectors/**/*',
'tests/version.test.ts',
'tests/pg/node-postgres.test.ts',
'tests/utils/is-config.test.ts',
'js-tests/driver-init/commonjs/*.test.cjs',
'js-tests/driver-init/module/*.test.mjs',
'tests/gel/**/*.test.ts',
],Sources: integration-tests/vitest.config.ts:6-24
Note
When SKIP_EXTERNAL_DB_TESTS is active in the environment, local execution automatically filters out tests requiring remote or external database services such as PlanetScale, Neon, TiDB, LibSQL, and Vercel.
Continuous integration runs are directed by integration-tests/vitest-ci.config.ts, which omits the verbose include and exclude pattern arrays to streamline execution while retaining core test timeouts, single-thread pool options, and type checking constraints.
export default defineConfig({
test: {
typecheck: {
tsconfig: 'tsconfig.json',
},
testTimeout: 100000,
hookTimeout: 200000,
isolate: true,
poolOptions: {
threads: {
singleThread: true,
},
},
maxWorkers: 1,
fileParallelism: false,
},Sources: integration-tests/vitest-ci.config.ts:5-20
Execution parameter matrix
Both local and CI runner configurations enforce strict concurrency controls and execution boundaries to prevent race conditions against shared or local database instances. The parameter configuration defines explicit timeouts, worker limits, and isolation rules.
| Parameter | Configuration Key | Value | Purpose |
|---|---|---|---|
| Test Timeout | testTimeout | 100000 | Maximum execution time in milliseconds allotted to an individual test case. |
| Hook Timeout | hookTimeout | 200000 | Maximum execution time in milliseconds allotted to setup and teardown hooks. |
| Test Isolation | isolate | true | Ensures test files run in isolated environments to avoid state leakage. |
| Single Thread | poolOptions.threads.singleThread | true | Forces test execution onto a single thread within the pool. |
| Max Workers | maxWorkers | 1 | Restricts parallel worker processes to prevent database connection contention. |
| File Parallelism | fileParallelism | false | Disables concurrent test file execution across workers. |
Sources: integration-tests/vitest.config.ts:70-83, integration-tests/vitest-ci.config.ts:7-19
Infrastructure provisioning with SST fixtures
Cloud stack orchestration and AWS Postgres configuration
The integration test suite utilizes SST (Serverless Stack) to orchestrate cloud infrastructure stacks for serverless database validation. The configuration file integration-tests/sst.config.ts includes a triple-slash reference to ./.sst/platform/config.d.ts for type safety and is exported via the $config function block.
// eslint-disable-next-line @typescript-eslint/triple-slash-reference
/// <reference path="./.sst/platform/config.d.ts" />
export default $config({
app(_input) {
return {
name: 'awsdataapi',
removal: 'remove',
home: 'aws',
};
},
async run() {
new sst.aws.Postgres('Postgres', {
scaling: {
min: '0.5 ACU',
max: '1 ACU',
},
});
},Sources: integration-tests/sst.config.ts:1-19
| Configuration Property | Target Value / Setting | Context |
|---|---|---|
| App Name | awsdataapi | Defined within the app hook callback. |
| Removal Policy | remove | Specifies stack teardown behavior upon destruction. |
| Home Provider | aws | Designates AWS as the infrastructure provider. |
| Postgres Resource ID | Postgres | Instantiated via new sst.aws.Postgres('Postgres', ...). |
| Minimum ACU | 0.5 ACU | Serverless scaling lower bound for the Postgres instance. |
| Maximum ACU | 1 ACU | Serverless scaling upper bound for the Postgres instance. |
Sources: integration-tests/sst.config.ts:4-19
Note
The serverless PostgreSQL resource scales dynamically between 0.5 and 1 Aurora Capacity Units (ACU) to accommodate AWS Data API integration tests without maintaining idle compute overhead.
Generated environment bindings
Environment binding synchronization for the SST stack is managed through generated type definition files. The file integration-tests/sst-env.d.ts establishes type references for runtime resource bindings generated during stack deployment.
// eslint-disable-next-line @typescript-eslint/triple-slash-reference
/// <reference path="./.sst/types.generated.ts" />Sources: integration-tests/sst-env.d.ts:1-2
Warning
Manual modifications to sst-env.d.ts will be overwritten when SST generates new environment type definitions from the active stack state.
Cross dialect migration journal fixtures
Migration journal schema and dialect variants
Integration tests validate schema change tracking and snapshot generation by utilizing multi-dialect migration journal fixtures. Each migration journal is defined inside a meta/_journal.json configuration file, specifying the schema metadata version, target SQL dialect, and sequential entries detailing individual migration steps. The journal format records metadata such as transaction timestamps, unique tags, and breakpoint configurations.
{
"version": "5",
"dialect": "sqlite",
"entries": [
{
"idx": 0,
"version": "5",
"when": 1680202256473,
"tag": "0000_fancy_bug",
"breakpoints": true
}
]Sources: integration-tests/drizzle2/sqlite/meta/_journal.json:1-12
The migration journals capture differences across database engines. For example, PostgreSQL journal configurations accommodate single and multi-step migration histories, whereas SQLite and SingleStore maintain target-specific format versions.
{
"version": "5",
"dialect": "pg",
"entries": [
{
"idx": 0,
"version": "5",
"when": 1680271923328,
"tag": "0000_puzzling_flatman",
"breakpoints": true
},
{
"idx": 1,
"version": "5",
"when": 1680271923329,
"tag": "0001_test",
"breakpoints": true
}
]Sources: integration-tests/drizzle2/pg/meta/_journal.json:1-19
| Dialect | Journal File Path | Version | Entry Count | Dialect Identifier |
|---|---|---|---|---|
| SQLite | integration-tests/drizzle2/sqlite/meta/_journal.json | 5 | 1 | sqlite |
| PostgreSQL | integration-tests/drizzle2/pg/meta/_journal.json | 5 | 2 | pg |
| SingleStore | integration-tests/drizzle2/singlestore/meta/_journal.json | 1 | 1 | singlestore |
| PostgreSQL Proxy | integration-tests/drizzle2/pg-proxy/first/meta/_journal.json | 5 | 1 | pg |
Sources: integration-tests/drizzle2/sqlite/meta/_journal.json:1-12, integration-tests/drizzle2/pg/meta/_journal.json:1-19, integration-tests/drizzle2/singlestore/meta/_journal.json:1-13, integration-tests/drizzle2/pg-proxy/first/meta/_journal.json:1-13
Proxy configurations and isolated entrysets
Proxy integration tests use specialized journal directories such as pg-proxy/first/meta/_journal.json to validate driver-agnostic query and migration proxy layers. These proxy setups mirror standard PostgreSQL version schemas while restricting entrysets to initial baseline migrations.
{
"version": "5",
"dialect": "pg",
"entries": [
{
"idx": 0,
"version": "5",
"when": 1680271923328,
"tag": "0000_puzzling_flatman",
"breakpoints": true
}
]
}Sources: integration-tests/drizzle2/pg-proxy/first/meta/_journal.json:1-13
Note
SingleStore migration journals specify format version 1 and dialect identifier singlestore, differing from the version 5 format utilized across PostgreSQL and SQLite fixtures.
Caution
Altering migration entry indices (idx) or timestamp values (when) within active journal fixtures causes migration parser validation checks to fail during test harness startup.
In memory SQLite and embedded PostgreSQL execution
SQLite driver instantiation across runtimes
SQLite test harnesses instantiate local in-memory databases by invoking engine-specific constructors, such as Database from better-sqlite3 or Database from bun:sqlite, paired with the ':memory:' connection string. These client instances are passed directly to dialect-specific initialization helpers like drizzleBetterSqlite3, drizzleBun, drizzleD1, and durableSqlite to construct fully typed database instances for test execution and seeding utilities.
import Database from 'better-sqlite3';
import { Database as BunDatabase } from 'bun:sqlite';
import { drizzle as drizzleBetterSqlite3 } from '~/better-sqlite3/index.ts';
import { drizzle as drizzleBun } from '~/bun-sqlite/index.ts';
import { drizzle as drizzleD1 } from '~/d1/index.ts';
import { drizzle as durableSqlite } from '~/durable-sqlite/index.ts';
const client = new Database(':memory:');
const bunClient = new BunDatabase(':memory:');
declare const d1: D1Database;
declare const durableSql: DurableObjectStorage;
export const db = drizzleBetterSqlite3(client);
export const bunDb = drizzleBun(bunClient);
export const d1Db = drizzleD1(d1);
export const durableSqliteDb = durableSqlite(durableSql);Sources: drizzle-orm/type-tests/sqlite/db.ts:1-16
Tip
SQLite seeding utilities support both standard table definitions and foreign key relational references using in-memory connections, allowing rapid fixture resets via reset and seed function calls.
Sources: drizzle-seed/type-tests/sqlite.ts:1-17
Embedded PGlite driver and session configuration
Embedded PostgreSQL execution relies on the PgliteDriver class and the @electric-sql/pglite package to spin up zero-dependency PostgreSQL instances within test environments. The drizzle entry point handles multiple parameter overload signatures, accepting either an existing PGlite client instance, a connection string, a data directory path with options, or a configuration object containing logger and cache parameters.
export function drizzle<
TSchema extends Record<string, unknown> = Record<string, never>,
TClient extends PGlite = PGlite,
>(
...params:
| []
| [
TClient | string,
]
| [
TClient | string,
DrizzleConfig<TSchema>,
]
| [
(
& DrizzleConfig<TSchema>
& ({
connection?: (PGliteOptions & { dataDir?: string }) | string;
} | {
client: TClient;
})
),
]
): PgliteDatabase<TSchema> & {
$client: TClient;
} {
if (params[0] === undefined || typeof params[0] === 'string') {
const instance = new PGlite(params[0]);
return construct(instance, params[1]) as any;
}
if (isConfig(params[0])) {
const { connection, client, ...drizzleConfig } = params[0] as {
connection?: PGliteOptions & { dataDir: string };
client?: TClient;
} & DrizzleConfig<TSchema>;
if (client) return construct(client, drizzleConfig) as any;
if (typeof connection === 'object') {
const { dataDir, ...options } = connection;
const instance = new PGlite(dataDir, options);
return construct(instance, drizzleConfig) as any;
}
const instance = new PGlite(connection);
return construct(instance, drizzleConfig) as any;
}
return construct(params[0] as TClient, params[1] as DrizzleConfig<TSchema> | undefined) as any;
}Sources: drizzle-orm/src/pglite/driver.ts:98-151
The internal construct function initializes the PostgreSQL dialect with optional casing configurations, parses user-provided loggers and schema definitions using extractTablesRelationalConfig, and attaches client reference properties $client and $cache to the resulting PgliteDatabase instance.
function construct<TSchema extends Record<string, unknown> = Record<string, never>>(
client: PgliteClient,
config: DrizzleConfig<TSchema> = {},
): PgliteDatabase<TSchema> & {
$client: PgliteClient;
} {
const dialect = new PgDialect({ casing: config.casing });
let logger;
if (config.logger === true) {
logger = new DefaultLogger();
} else if (config.logger !== false) {
logger = config.logger;
}
let schema: RelationalSchemaConfig<TablesRelationalConfig> | undefined;
if (config.schema) {
const tablesConfig = extractTablesRelationalConfig(
config.schema,
createTableRelationsHelpers,
);
schema = {
fullSchema: config.schema,
schema: tablesConfig.tables,
tableNamesMap: tablesConfig.tableNamesMap,
};
}
const driver = new PgliteDriver(client, dialect, { logger, cache: config.cache });
const session = driver.createSession(schema);
const db = new PgliteDatabase(dialect, session, schema as any) as PgliteDatabase<TSchema>;
(<any> db).$client = client;
(<any> db).$cache = config.cache;
if ((<any> db).$cache) {
(<any> db).$cache['invalidate'] = config.cache?.onMutate;
}
// (<any> db).$cache = { invalidate: (<any> config).cache?.onMutate };
// if (config.cache) {
// for (
// const key of Object.getOwnPropertyNames(Object.getPrototypeOf(config.cache)).filter((key) =>
// key !== 'constructor'
// )
// ) {
// (<any> db).$cache[key as keyof typeof config.cache] = (<any> config).cache[key];
// }
// }
return db as any;
}Sources: drizzle-orm/src/pglite/driver.ts:49-96
| Overload Signature | Primary Parameter Type | Description |
|---|---|---|
| Client or String | TClient | string | undefined | Instantiates a new PGlite with an optional connection string or data path. |
| Configuration Object | DrizzleConfig & (connection | client) | Configures PGlite using explicit connection options or a passed client instance. |
| Mock Instance | DrizzleConfig via drizzle.mock() | Returns a mock database instance where $client is marked as unavailable. |
Sources: drizzle-orm/src/pglite/driver.ts:98-160
Warning
Calling drizzle.mock() provides a database instance without an active client connection, returning the string literal '\\$client is not available on drizzle.mock()' for any access to the $client property.
SingleStore connection pooling and query execution
Connection pool instantiation and session setup
SingleStore integration tests establish database connections and connection pools by utilizing the mysql2/promise package. The test harness creates a connection pool through the createPool function and passes the resulting pool object into the drizzle factory function to construct a typed SingleStore database instance for query execution.
import { createPool } from 'mysql2/promise';
import { drizzle } from '~/singlestore/index.ts';
const pool = createPool({});
export const db = drizzle(pool);
Sources: drizzle-orm/type-tests/singlestore/db.ts:1-7
The drizzle function accepts various configuration combinations, including passing the pool directly, providing a schema object alongside the pool, or supplying empty options configurations during initialization.
{
drizzle(pool);
drizzle(pool, { schema: {} });
drizzle(pool, { schema: {} });
drizzle(pool, {});
}Sources: drizzle-orm/type-tests/singlestore/db.ts:8-13
Note
SingleStore database instances support optional schema definitions passed via the initialization configuration object to bind tables directly to targeted named schemas.
Dialect query lifecycle and locking modifiers
Query execution test suites validate complex join operations, subqueries, and table aliasing across the SingleStore dialect. Queries support explicit locking clauses such as .for('update') and .for('share'), with configuration options including noWait and skipLocked flags.
await db.select().from(users).for('update');
await db.select().from(users).for('share', { skipLocked: true });
await db.select().from(users).for('update', { noWait: true });Sources: drizzle-orm/type-tests/singlestore/select.ts:615-617
| Locking Clause | Modifier Option | Description |
|---|---|---|
for('update') | None | Locks selected rows for update operations. |
for('share') | { skipLocked: true } | Shares selected rows while skipping locked records. |
for('update') | { noWait: true } | Attempts to lock rows for update without waiting for locks to release. |
Sources: drizzle-orm/type-tests/singlestore/select.ts:615-617
Caution
Combining both noWait and skipLocked within the same locking modifier options object triggers a type-level compilation error to prevent conflicting locking behaviors.
/* await db
.select()
.from(users)
// @ts-expect-error - can't use both skipLocked and noWait
.for('share', { noWait: true, skipLocked: true });Sources: drizzle-orm/type-tests/singlestore/select.ts:619-623
Ecosystem package test harnesses
Schema validation and seeding test parameters
Test configuration parity across ecosystem packages is maintained through dedicated Vitest runner settings in drizzle-zod, drizzle-typebox, drizzle-valibot, drizzle-arktype, and drizzle-seed. Schema validator packages exclude runtime bun-specific test folders (tests/bun/**/*) while configuring test timeouts to 100000 milliseconds, hook timeouts to 100000 milliseconds, and running tests with isolate: false and singleThread: true via thread pool options.
test: {
include: [
'tests/**/*.test.ts',
],
exclude: [
'tests/bun/**/*',
],
typecheck: {
tsconfig: 'tsconfig.json',
},
testTimeout: 100000,
hookTimeout: 100000,
isolate: false,
poolOptions: {
threads: {
singleThread: true,
},
},
},Sources: drizzle-zod/vitest.config.ts:5-23
| Package Configuration | Test Isolation (isolate) | Thread Mode (singleThread) | Test Timeout (ms) | Excluded Patterns |
|---|---|---|---|---|
drizzle-zod | false | true | 100000 | tests/bun/**/* |
drizzle-typebox | false | true | 100000 | tests/bun/**/* |
drizzle-valibot | false | true | 100000 | tests/bun/**/* |
drizzle-arktype | false | true | 100000 | tests/bun/**/* |
drizzle-seed | true | true | 100000 | None |
Sources: drizzle-seed/vitest.config.ts:4-24, drizzle-arktype/vitest.config.ts:5-23, drizzle-valibot/vitest.config.ts:5-23, drizzle-typebox/vitest.config.ts:5-23, drizzle-zod/vitest.config.ts:5-23
Note
drizzle-seed enforces strict test isolation (isolate: true) across postgres, mysql, and sqlite test directories while explicitly setting maxWorkers: 1 and fileParallelism: false.
Linting tool verification and path resolution
The eslint-plugin-drizzle test suite relies on a simplified Vitest setup enabling global test APIs and excluding **/dist/** build output paths. Meanwhile, parser configurations across drizzle-kit, drizzle-arktype, drizzle-valibot, drizzle-typebox, and drizzle-zod utilize vite-tsconfig-paths plugins to map internal path aliases directly against local tsconfig.json definitions.
import { defineConfig } from 'vitest/config';
export default defineConfig({
test: {
globals: true,
exclude: ['**/dist/**'],
},Sources: eslint-plugin-drizzle/vitest.config.ts:1-7
Warning
Omitting vite-tsconfig-paths plugin registration in ecosystem package test files causes module resolution failures when test suites import internal workspace dependencies using path aliases.
Related
On This Page
OverviewVitest runner configuration across environmentsLocal and CI configuration structuresExecution parameter matrixInfrastructure provisioning with SST fixturesCloud stack orchestration and AWS Postgres configurationGenerated environment bindingsCross dialect migration journal fixturesMigration journal schema and dialect variantsProxy configurations and isolated entrysetsIn memory SQLite and embedded PostgreSQL executionSQLite driver instantiation across runtimesEmbedded PGlite driver and session configurationSingleStore connection pooling and query executionConnection pool instantiation and session setupDialect query lifecycle and locking modifiersEcosystem package test harnessesSchema validation and seeding test parametersLinting tool verification and path resolutionRelated