tests.ts•7.45 kB
import { faker } from '@faker-js/faker'
import { Providers } from '../_utils/providers'
import { NewPrismaClient } from '../_utils/types'
import testMatrix from './_matrix'
// @ts-ignore
import type { Prisma, PrismaClient } from './generated/prisma/client'
// @only-ts-generator
type LogPrismaClient = PrismaClient<'query'>
// @only-js-generator
type LogPrismaClient = PrismaClient<{ log: [{ emit: 'event'; level: 'query' }] }>
declare const newPrismaClient: NewPrismaClient<LogPrismaClient, typeof PrismaClient>
testMatrix.setupTestSuite(({ provider, driverAdapter, clientEngineExecutor }) => {
const isMongoDb = provider === Providers.MONGODB
const isSqlServer = provider === Providers.SQLSERVER
const usesJsDrivers = driverAdapter !== undefined || clientEngineExecutor === 'remote'
let client: LogPrismaClient
test('should log queries on a method call', async () => {
client = newPrismaClient({
log: [
{
emit: 'event',
level: 'query',
},
],
})
const queryLogPromise = new Promise<Prisma.QueryEvent>((resolve) => {
client.$on('query', (data) => {
if ('query' in data) {
resolve(data)
}
})
})
await client.user.findMany()
const queryLogEvents = await queryLogPromise
expect(queryLogEvents).toHaveProperty('query')
expect(queryLogEvents).toHaveProperty('duration')
expect(queryLogEvents).toHaveProperty('timestamp')
expect(queryLogEvents).toHaveProperty('params')
expect(queryLogEvents).toHaveProperty('target')
if (isMongoDb) {
expect(queryLogEvents.query).toContain('db.User.aggregate')
} else {
expect(queryLogEvents.query).toContain('SELECT')
}
})
// D1: iTx are not available.
skipTestIf(driverAdapter === 'js_d1')('should log queries inside a ITX', async () => {
client = newPrismaClient({
log: [
{
emit: 'event',
level: 'query',
},
],
})
const queryLogs = new Promise<Prisma.QueryEvent[]>((resolve) => {
const logs: Prisma.QueryEvent[] = []
client.$on('query', (data) => {
if ('query' in data) {
logs.push(data)
if (isMongoDb && logs.length === 3) {
resolve(logs)
}
if ((data.query as string).includes('COMMIT')) {
resolve(logs)
}
}
})
})
await client.$transaction(async (tx) => {
const id = isMongoDb ? faker.database.mongodbObjectId() : faker.string.numeric()
await tx.user.create({
data: {
id,
},
})
return tx.user.findMany({
where: {
id,
},
})
})
const logs = await queryLogs
if (isMongoDb) {
expect(logs).toHaveLength(3)
expect(logs[0].query).toContain('User.insertOne')
expect(logs[1].query).toContain('User.aggregate')
expect(logs[2].query).toContain('User.aggregate')
} else {
// - Since https://github.com/prisma/prisma-engines/pull/4041,
// we skip a read when possible, on CockroachDB and PostgreSQL.
// - Since https://github.com/prisma/prisma-engines/pull/4640,
// we also skip a read when possible, on SQLite.
if (isSqlServer && !usesJsDrivers) {
expect(logs.shift()?.query).toContain('SET TRANSACTION')
}
if (!usesJsDrivers) {
// Driver adapters do not issue BEGIN through the query engine.
expect(logs.shift()?.query).toContain('BEGIN')
}
if (['postgresql', 'cockroachdb', 'sqlite'].includes(provider)) {
expect(logs).toHaveLength(3)
expect(logs.shift()?.query).toContain('INSERT')
expect(logs.shift()?.query).toContain('SELECT')
expect(logs.shift()?.query).toContain('COMMIT')
} else {
expect(logs).toHaveLength(4)
expect(logs.shift()?.query).toContain('INSERT')
expect(logs.shift()?.query).toContain('SELECT')
expect(logs.shift()?.query).toContain('SELECT')
expect(logs.shift()?.query).toContain('COMMIT')
}
}
})
// D1: iTx are not available.
skipTestIf(driverAdapter === 'js_d1')('should log batched queries inside a ITX', async () => {
client = newPrismaClient({
log: [
{
emit: 'event',
level: 'query',
},
],
})
const queryLogs = new Promise<Prisma.QueryEvent[]>((resolve) => {
const logs: Prisma.QueryEvent[] = []
client.$on('query', (data) => {
if ('query' in data) {
logs.push(data)
if (isMongoDb && logs.length === 2) {
resolve(logs)
}
if ((data.query as string).includes('COMMIT')) {
resolve(logs)
}
}
})
})
await client.$transaction(async (tx) => {
const id = isMongoDb ? faker.database.mongodbObjectId() : faker.string.numeric()
await Promise.all([
tx.user.findMany({
where: {
id,
},
}),
tx.user.findMany({
where: {
id,
},
}),
])
})
const logs = await queryLogs
if (isMongoDb) {
expect(logs).toHaveLength(2)
expect(logs[0].query).toContain('User.aggregate')
expect(logs[0].query).toContain('User.aggregate')
} else {
if (isSqlServer && !usesJsDrivers) {
expect(logs.shift()?.query).toContain('SET TRANSACTION')
}
if (!usesJsDrivers) {
// Driver adapters do not issue BEGIN through the query engine.
expect(logs.shift()?.query).toContain('BEGIN')
}
expect(logs).toHaveLength(3)
expect(logs.shift()?.query).toContain('SELECT')
expect(logs.shift()?.query).toContain('SELECT')
expect(logs.shift()?.query).toContain('COMMIT')
}
})
test('should log transaction batched queries', async () => {
client = newPrismaClient({
log: [
{
emit: 'event',
level: 'query',
},
],
})
const queryLogs = new Promise<Prisma.QueryEvent[]>((resolve) => {
const logs: Prisma.QueryEvent[] = []
client.$on('query', (data) => {
if ('query' in data) {
logs.push(data)
if (isMongoDb && logs.length === 2) {
resolve(logs)
}
if ((data.query as string).includes('COMMIT')) {
resolve(logs)
}
}
})
})
const id = isMongoDb ? faker.database.mongodbObjectId() : faker.string.numeric()
const q1 = client.user.findMany({
where: {
id,
},
})
const q2 = client.user.findMany({
where: {
id,
},
})
await client.$transaction([q1, q2])
const logs = await queryLogs
if (isMongoDb) {
expect(logs).toHaveLength(2)
expect(logs[0].query).toContain('User.aggregate')
expect(logs[0].query).toContain('User.aggregate')
} else {
if (isSqlServer && !usesJsDrivers) {
expect(logs.shift()?.query).toContain('SET TRANSACTION')
}
if (!usesJsDrivers) {
// Driver adapters do not issue BEGIN through the query engine.
expect(logs.shift()?.query).toContain('BEGIN')
}
expect(logs).toHaveLength(3)
expect(logs.shift()?.query).toContain('SELECT')
expect(logs.shift()?.query).toContain('SELECT')
expect(logs.shift()?.query).toContain('COMMIT')
}
})
})