Tests require Docker for PostgreSQL and MySQL. SQLite and DuckDB use in-memory databases and don’t need Docker.
Terminal window
npmruntest:setup# Starts test PostgreSQL (port 54333) and MySQL (port 33077) via Docker
npmtest# Run all tests (default: PostgreSQL)
npmruntest:teardown# Stop and remove test database containers
[!TIP]
The dev server and test databases use completely separate Docker containers and ports, so you can run npm run dev and npm test at the same time. This is useful for observing your changes in the browser while verifying they pass tests.
No Docker available? If you’re working in a container, a sandbox, or any environment where you can’t start Docker, run the DB-free suites instead of npm test — npm run test:sqlite, npm run test:client, npm run test:cli, plus npm run lint and npm run typecheck. test:sqlite runs the same server suite against in-process SQLite, so it’s a real verification signal rather than a subset. See CLAUDE.md → Testing in a constrained environment.
We have specific rules on how commit messages should be structured.
It’s important to make sure your commit messages are clear, concise, and informative to make it easier for others to understand the changes you are making.
All commit messages should follow the pattern below:
<subject>
<BLANK LINE>
<body>
Example:
Add PostgreSQL array support to measures
Enables aggregation functions on PostgreSQL array columns
for more flexible analytics queries
[!WARNING]
All commits should be signed before submitting a PR. Please check the documentation on how to sign commits.
Drizzle Cube has integration tests that run against real databases with different queries and responses. Tests use Docker containers for PostgreSQL and MySQL, and in-memory databases for SQLite and DuckDB.
If you have added additional logic to the core library, make sure that all tests complete without any failures.
[!IMPORTANT]
Not every test needs a database.vitest.config.ts defines a DB-free cli project
(alongside server and client). Logic that never opens a connection or builds SQL — CLI
commands, manifest/artifact parsers, code generators, naming and type mapping — goes in
tests/cli/, runs with in-memory fixtures, needs no Docker and no globalSetup, and
finishes in milliseconds:
Reserve the server / engine projects for code that actually issues SQL. Decide by the
subject under test, not by where its source file lives — see tests/CLAUDE.md and the live
project definitions in vitest.config.ts.
[!NOTE]
If you have added data types, query features, or new functionality, you need to create additional test cases using the new API to ensure it works properly.
Setup test databases via Docker:
Terminal window
npmruntest:setup# Starts PostgreSQL (port 54333) and MySQL (port 33077)
Run server tests (semantic layer, executors, query planning):
Terminal window
# PostgreSQL (default)
npmruntest:postgres
# MySQL
npmruntest:mysql
# SQLite (no Docker needed)
npmruntest:sqlite
# DuckDB (no Docker needed)
npmruntest:duckdb
# All databases sequentially
npmruntest:all
Run client tests (React components, hooks, stores):
Terminal window
npmruntest:client
Run all tests (server + client):
Terminal window
npmtest
Watch mode:
Terminal window
npmruntest:watch# All tests
npmruntest:server:watch# Server tests only
npmruntest:client:watch# Client tests only
Coverage reports:
Terminal window
npmruntest:coverage# Server coverage (default DB)
npmruntest:client:coverage# Client coverage
npmruntest:coverage:all# Server coverage across all databases
npmruntest:coverage:complete# Full coverage (all server DBs + client)
Teardown test databases:
Terminal window
npmruntest:teardown# Stop and remove Docker containers
Environment variables:
Variable
Default
Description
TEST_DB_TYPE
postgres
Database to test against (postgres, mysql, sqlite, duckdb)
Drizzle-First Design: This project is built around Drizzle ORM as the core:
All SQL generation must use Drizzle query builder
Never use string concatenation for SQL
All database operations go through Drizzle
Type safety is enforced through Drizzle schema definitions
Security: SQL injection prevention is paramount:
Use parameterized queries only
Leverage Drizzle’s type safety
Include security context in all cube definitions
Test multi-tenant isolation
Adding a New Chart Type: Chart types are used inside the AnalysisBuilder component. When adding a new chart type, verify it works end-to-end within the AnalysisBuilder — select it from the chart type picker, configure axes via the chart config panel, and confirm it renders correctly with real query results. See src/client/CLAUDE.md for the full registration steps (chart config, lazy loading, ChartLoader).