vitest
vitest copied to clipboard
Adding custom watch commands
Clear and concise description of the problem
We use testcontainers to run our integration tests with a live PostgreSQL database, in 5 parallel workers
All these DBs must be migrated using Prisma before starting vitest --watch, we do this in our global setup:
import { PostgreSqlContainer } from "@testcontainers/postgresql";
import { exec as execCb } from "child_process";
import { promisify } from "util";
import type { GlobalSetupContext } from "vitest/node";
const exec = promisify(execCb);
export default async function setup({ provide, config }: GlobalSetupContext) {
const stopsFunctions: (() => Promise<void>)[] = [];
const postgresUrls: Record<number, string> = {};
await prismaGenerate();
await Promise.all(
[...Array(config.maxWorkers).keys()].map(async (index) => {
const postgres = await buildPostgresContainer();
postgresUrls[index + 1] = postgres.url;
stopsFunctions.push(postgres.stop);
}),
);
provide("postgresUrls", postgresUrls);
return async () => {
await Promise.all(
stopsFunctions.map(async (stop) => {
await stop();
}),
);
};
}
const prismaGenerate = async () => {
console.log("[Prisma] Generating...");
await exec(`npx prisma generate`);
console.log("[Prisma] Generated successfully!");
};
const buildPostgresContainer = async () => {
console.log("[Postgres] Starting...");
const postgres = await new PostgreSqlContainer("postgres:16")
.withTmpFs({ "/dev/shm/postgres": "rw,noexec,nosuid,size=65536k" })
// https://www.postgresql.org/docs/current/non-durability.html
.withCommand([
"postgres",
"-c",
"fsync=off",
"-c",
"synchronous_commit=off",
"-c",
"full_page_writes=off",
"-c",
"autovacuum=off",
])
.start();
const url = postgres.getConnectionUri();
console.log("[Postgres] Migrating...");
await exec(`DB_URL=${url} npx prisma migrate deploy`);
console.log("[Postgres] Migrated successfully!");
return {
url,
stop: async () => {
await postgres.stop();
},
};
};
// Type safe access to `provide/inject` methods:
declare module "vitest" {
export interface ProvidedContext {
postgresUrls: Record<number, string>;
}
}
If I write a new migration, it is not applied to my live test databases, I must end the Vitest process and start again (in this case, this takes ~30s because of all the containers)
Suggested solution
Would be nice if we could add a new quick command to the watch menu, such as m for triggering migrations inside the databases
Alternative
We could setup a parallel watching process which runs the migrations every time the migrations folder changes, but that seems flaky
Perhaps related to https://github.com/vitest-dev/vitest/issues/842
Additional context
No response
Validations
- [X] Follow our Code of Conduct
- [X] Read the Contributing Guidelines.
- [X] Read the docs.
- [X] Check that there isn't already an issue that request the same feature to avoid creating a duplicate.
I personally don't like extending the watch commands API. If you want to do something custom, you can always create your own script and run it in the terminal. But for this specific use case, maybe we can add something like onWatcherRerun to the globalSetup:
export default ({ onWatcherRerun }) => {
onWatcherRerun(async () => {
// do this before running tests
})
}