From 6849b096b430b150b133216ccab84243f288af07 Mon Sep 17 00:00:00 2001 From: Oliver Eyton-Williams Date: Mon, 19 Feb 2024 06:24:14 +0100 Subject: [PATCH] test: only use test dbs in testing (#53770) --- api/jest.utils.ts | 44 ++++++++++++++++++++++++++++++++++++++++++++ api/src/db/prisma.ts | 44 ++++++++------------------------------------ 2 files changed, 52 insertions(+), 36 deletions(-) diff --git a/api/jest.utils.ts b/api/jest.utils.ts index 21a41140467..25aeee4b1db 100644 --- a/api/jest.utils.ts +++ b/api/jest.utils.ts @@ -1,8 +1,28 @@ +import { execSync } from 'child_process'; + import request from 'supertest'; import { build } from './src/app'; import { createUserInput } from './src/utils/create-user'; import { examJson } from './__mocks__/exam'; +import { MONGOHQ_URL } from './src/utils/env'; + +jest.mock('./src/utils/env', () => { + const createTestConnectionURL = (url: string, dbId: string) => + url.replace(/(.*)(\?.*)/, `$1${dbId}$2`); + // There are other properties, and this type is too narrow, but we're only + // interested in MONGOHQ_URL here. + const actual: { + MONGOHQ_URL: string; + } = jest.requireActual('./src/utils/env'); + return { + ...actual, + MONGOHQ_URL: createTestConnectionURL( + actual.MONGOHQ_URL, + process.env.JEST_WORKER_ID! + ) + }; +}); type FastifyTestInstance = Awaited>; @@ -71,11 +91,35 @@ export function setupServer(): void { fastify = await build(); await fastify.ready(); + // Prisma does not support TTL indexes in the schema yet, so, to avoid + // conflicts with the TTL index in the sessions collection, we need to + // create it manually (before interacting with the db in any way) + await fastify.prisma.$runCommandRaw({ + createIndexes: 'sessions', + indexes: [ + { + key: { expires: 1 }, + name: 'expires_1', + background: true, + expireAfterSeconds: 0 + } + ] + }); + // push the schema to the test db to setup indexes, unique constraints, etc + execSync('pnpm prisma db push -- --skip-generate', { + env: { + ...process.env, + MONGOHQ_URL + } + }); + global.fastifyTestInstance = fastify; // allow a little time to setup the db }, 10000); afterAll(async () => { + await fastifyTestInstance.prisma.$runCommandRaw({ dropDatabase: 1 }); + // Due to a prisma bug, this is not enough, we need to --force-exit jest: // https://github.com/prisma/prisma/issues/18146 await fastifyTestInstance.close(); diff --git a/api/src/db/prisma.ts b/api/src/db/prisma.ts index 56bbe8483f0..f3f54d8629a 100644 --- a/api/src/db/prisma.ts +++ b/api/src/db/prisma.ts @@ -1,9 +1,9 @@ -import { execSync } from 'node:child_process'; import fp from 'fastify-plugin'; import { FastifyPluginAsync } from 'fastify'; import { PrismaClient } from '@prisma/client'; -import { FREECODECAMP_NODE_ENV, MONGOHQ_URL } from '../utils/env'; +// importing MONGOHQ_URL so we can mock it in testing. +import { MONGOHQ_URL } from '../utils/env'; declare module 'fastify' { interface FastifyInstance { @@ -11,48 +11,20 @@ declare module 'fastify' { } } -// Appends the dbId to the existing database name -const createTestConnectionURL = (url: string, dbId: string) => - url.replace(/(.*)(\?.*)/, `$1${dbId}$2`); - -const isTest = (workerId: string | undefined): workerId is string => - !!workerId && FREECODECAMP_NODE_ENV === 'development'; - const prismaPlugin: FastifyPluginAsync = fp(async (server, _options) => { - if (isTest(process.env.JEST_WORKER_ID)) { - // push the schema to the test db to setup indexes, unique constraints, etc - execSync('pnpm prisma db push -- --skip-generate', { - env: { - ...process.env, - MONGOHQ_URL: createTestConnectionURL( - MONGOHQ_URL, - process.env.JEST_WORKER_ID - ) + const prisma = new PrismaClient({ + datasources: { + db: { + url: MONGOHQ_URL } - }); - } - - const prisma = isTest(process.env.JEST_WORKER_ID) - ? new PrismaClient({ - datasources: { - db: { - url: createTestConnectionURL( - MONGOHQ_URL, - process.env.JEST_WORKER_ID - ) - } - } - }) - : new PrismaClient(); + } + }); await prisma.$connect(); server.decorate('prisma', prisma); server.addHook('onClose', async server => { - if (isTest(process.env.JEST_WORKER_ID)) { - await server.prisma.$runCommandRaw({ dropDatabase: 1 }); - } await server.prisma.$disconnect(); }); });