// Mock @prisma/client for E2E tests. // PrismaService extends PrismaClient → this must be a plain class. // Model access (prisma.user.findMany()) is supported via prototype delegates. function modelMethods(): Record { return { findUnique: () => Promise.resolve(null), findFirst: () => Promise.resolve(null), findMany: () => Promise.resolve([]), findRaw: () => Promise.resolve([]), create: (args: any) => Promise.resolve({ id: 1, ...args?.data }), update: (args: any) => Promise.resolve({ id: 1, ...args?.data }), delete: () => Promise.resolve({ id: 1 }), upsert: (args: any) => Promise.resolve({ id: 1, ...args?.create }), count: () => Promise.resolve(0), aggregate: () => Promise.resolve({}), groupBy: () => Promise.resolve([]), createMany: () => Promise.resolve({ count: 1 }), deleteMany: () => Promise.resolve({ count: 0 }), updateMany: () => Promise.resolve({ count: 0 }), aggregateRaw: () => Promise.resolve([]), } } function createModelDelegate(): any { const methods = modelMethods() return new Proxy(methods, { get(target: any, prop: string) { if (prop === 'then') return undefined if (prop in target) return target[prop] return () => Promise.resolve(undefined) }, }) } // admin user fixture so login tests can get a real JWT const ADMIN_USER = { id: 'admin-test-001', email: 'admin@zhixi.app', displayName: 'Test Admin', passwordHash: '$2b$10$mp8kF.PwWBjb0fp/5d0nZ.VNofYcVm7jhJYtswxLfGU/EJW5K8qCm', // bcrypt hash of "admin123" role: 'SUPER_ADMIN', status: 'ACTIVE', twoFactorEnabled: false, failedLoginCount: 0, lockedUntil: null, deletedAt: null, lastLoginAt: null, lastLoginIp: null, createdAt: new Date(), updatedAt: new Date(), } const ADMIN_SESSION = { id: 1, adminUserId: 'admin-test-001', refreshTokenHash: 'test-hash', ip: null, userAgent: null, revokedAt: null, expiresAt: new Date(Date.now() + 7 * 86400000), createdAt: new Date(), } export class PrismaClient { $connect() { return Promise.resolve() } $disconnect() { return Promise.resolve() } $on() {} $transaction(fn: any) { const delegate = createModelDelegate() return typeof fn === 'function' ? fn(delegate) : Promise.resolve([]) } $executeRaw() { return Promise.resolve(0) } $queryRaw() { return Promise.resolve([]) } $runCommandRaw() { return Promise.resolve({}) } } const modelNames = [ 'user', 'authAccount', 'refreshToken', 'userProfile', 'userPreference', 'userConsent', 'knowledgeBase', 'knowledgeItem', 'knowledgeItemRelation', 'tag', 'knowledgeItemTag', 'uploadedFile', 'documentImport', 'learningSession', 'learningRecord', 'activeRecallQuestion', 'activeRecallAnswer', 'aiAnalysisJob', 'aiAnalysisResult', 'focusItem', 'reviewCard', 'reviewLog', 'reviewPlan', 'dailyLearningActivity', 'notification', 'feedback', 'aiUsageLog', 'waitlistEntry', 'appChangelog', 'knowledgeSource', 'knowledgeChunk', 'importCandidate', 'backupJob', 'adminUser', 'adminSession', 'adminAuditLog', 'membershipPlan', 'adminConversation', 'adminMessage', 'adminCostItem', 'appConfig', 'featureFlag', 'configChangeLog', 'securityEvent', 'sensitiveWord', 'contentSafetyCheck', 'contentReport', 'apiMetric', 'taskLog', 'userMembership', 'quotaUsage', 'costDailySummary', 'secretRecord', 'secretAccessLog', 'modelRoute', 'providerConfig', 'fallbackEvent', 'violationRecord', 'contentReport', 'userDevice', 'accountDeletionRequest', 'workspace', 'knowledgeFolder', ] for (const name of modelNames) { ;(PrismaClient.prototype as any)[name] = createModelDelegate() } // Patch adminUser.findUnique so login tests can succeed const origAdminUser = (PrismaClient.prototype as any).adminUser ;(PrismaClient.prototype as any).adminUser = new Proxy(origAdminUser, { get(target: any, prop: string) { if (prop === 'findUnique') { return (args: any) => { if (args?.where?.email === ADMIN_USER.email) return Promise.resolve(ADMIN_USER) if (args?.where?.id === ADMIN_USER.id) return Promise.resolve(ADMIN_USER) return target.findUnique(args) } } if (prop === 'findFirst') { return (args: any) => { if (args?.where?.email === ADMIN_USER.email) return Promise.resolve(ADMIN_USER) return target.findFirst(args) } } return target[prop] }, }) // Patch adminSession so admin auth guard doesn't reject const origAdminSession = (PrismaClient.prototype as any).adminSession ;(PrismaClient.prototype as any).adminSession = new Proxy(origAdminSession, { get(target: any, prop: string) { if (prop === 'findUnique' || prop === 'findFirst') { return (_args?: any) => Promise.resolve(ADMIN_SESSION) } return target[prop] }, }) export const Prisma = { ModelName: {}, PrismaClientKnownRequestError: class extends Error { code: string constructor(message: string, opts: { code: string; clientVersion: string }) { super(message) this.code = opts.code } }, PrismaClientValidationError: class extends Error {}, PrismaClientInitializationError: class extends Error {}, }