Skip to content
Closed
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
26 changes: 23 additions & 3 deletions src/contest.test.ts
Original file line number Diff line number Diff line change
@@ -1,3 +1,5 @@
import { resolve } from 'node:path';
import { pathToFileURL } from 'node:url';
import { beforeEach, describe, expect, it, vi } from 'vitest';
import {
type PrismaClient as PrismaClientStub,
Expand All @@ -19,9 +21,9 @@ const makeContext = async (
| 'transactionPending'
| 'transactionStarted'
| 'transactionEnded' = 'transactionPending',
): Promise<[ReturnType<typeof createContext>, PrismaClientStub]> => {
const context = createContext({
clientPath: '../test/prisma-client-stub.js',
): Promise<[Awaited<ReturnType<typeof createContext>>, PrismaClientStub]> => {
const context = await createContext({
clientPath: './test/prisma-client-stub.js',
databaseUrl: 'postgres://fake',
log: ['query'],
transactionOptions: { timeout: 123 },
Expand Down Expand Up @@ -53,6 +55,24 @@ describe('createContext', () => {
await ctx.teardown();
});

it('accepts an absolute file:// URL as clientPath', async () => {
vi.stubEnv('DATABASE_URL', 'postgres://fake');
const fileUrl = pathToFileURL(resolve('./test/prisma-client-stub.js')).href;
const ctx = await createContext({
clientPath: fileUrl,
databaseUrl: 'postgres://fake',
log: ['query'],
transactionOptions: { timeout: 123 },
});
await ctx.setup();

expect(PrismaPgMock).toHaveBeenCalledWith({
connectionString: 'postgres://fake',
});

await ctx.teardown();
});

it('throws when client is accessed outside of a test transaction', async () => {
const [transactionPendingContext] = await makeContext('transactionPending');
const [transactionEndedContext] = await makeContext('transactionEnded');
Expand Down
19 changes: 14 additions & 5 deletions src/context.ts
Original file line number Diff line number Diff line change
@@ -1,20 +1,19 @@
import { createRequire } from 'node:module';
import { isAbsolute, resolve } from 'node:path';
import { pathToFileURL } from 'node:url';
import { PrismaPg } from '@prisma/adapter-pg';
import type {
PrismaClientLike,
PrismaPostgresEnvironmentOptions,
} from './dts/index.js';

const require = createRequire(import.meta.url);

/**
* Creates the test context used by the `prisma-postgres` Vitest environment.
*
* @param options PrismaPostgresEnvironmentOptions
* @returns The test context object used by both the Vitest environment and the
* user's Prisma client mock.
*/
export function createContext(options: PrismaPostgresEnvironmentOptions) {
export async function createContext(options: PrismaPostgresEnvironmentOptions) {
let savePointCounter = 0;

/**
Expand All @@ -31,7 +30,17 @@ export function createContext(options: PrismaPostgresEnvironmentOptions) {
*/
let internalEndTestTransaction: (() => void) | null = null;

const { PrismaClient } = require(options.clientPath);
// Normalize clientPath so relative/absolute filesystem paths resolve against
// the consuming project's CWD instead of this module's location. Leave bare
// module specifiers (e.g. '@prisma/client') and existing file:// URLs
// untouched so ESM resolution handles them as-is.
const isPathLike =
options.clientPath.startsWith('.') || isAbsolute(options.clientPath);
const clientImportPath = isPathLike
? pathToFileURL(resolve(options.clientPath)).href
: options.clientPath;

const { PrismaClient } = await import(clientImportPath);
const originalClient: PrismaClientLike = new PrismaClient({
adapter: new PrismaPg({ connectionString: process.env.DATABASE_URL }),
log: options.log,
Expand Down
2 changes: 1 addition & 1 deletion src/index.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -24,7 +24,7 @@ import environment from '../src/index.js';
describe('prisma-postgres environment', () => {
const global: any = {};
const options = {
clientPath: '../test/prisma-client-stub.js',
clientPath: './test/prisma-client-stub.js',
};

beforeEach(() => {
Expand Down
2 changes: 1 addition & 1 deletion src/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -17,7 +17,7 @@ const environment: Environment = {
throw new Error('no DATABASE_URL defined!');
}

const ctx = createContext(options);
const ctx = await createContext(options);
await ctx.setup();

// make context available globally for setupFiles.
Expand Down