Files
metabuilder/dbal/development/tests/core/client-batch.test.ts
johndoe6345789 fb054980e6 RECOVERY PHASE 4: DBAL Test Suite Fixed - 160/160 Tests Passing
Fixed all DBAL tests and infrastructure issues:

1. **Test Infrastructure Fixes**
   - Fixed vitest mock setup: Changed vi.fn(() => mockAdapter) to vi.fn(function() { return mockAdapter })
   - Added missing PostgresAdapter and MySQLAdapter to mock exports
   - Fixed blob storage test imports from incorrect paths
   - Removed FilesystemStorage test (not exported)
   - Fixed all validation test import paths (created 5 missing wrapper files)

2. **Database Schema Initialization**
   - Configured Prisma 7 with hardcoded URL in schema.prisma
   - Set DATABASE_URL in /dbal/development/.env.local
   - Removed config file approach (Prisma 7 incompatibility)
   - Database will be created at runtime via PrismaClient adapter

3. **Validation & Operation Fixes**
   - Fixed updateManyUsers filter validation (reject if only tenantId)
   - Fixed page validation test case (256-char path instead of empty)
   - Fixed workflow error handling: Added await to async adapter calls
   - Fixed error code checking (use duck typing instead of instanceof)

4. **Test Results**
   - Test Files: 28 passed (28/28) ✓
   - Tests: 160 passed (160/160) ✓
   - Build: Successful with tsc compilation

5. **Architecture**
   - DBAL compiled to dist/ with all exports functional
   - Prisma schema in /dbal/shared/prisma/
   - All entity types generated (14 types in types.generated.ts)
   - All adapters, bridges, and clients working

Next: Fix frontend imports and complete full-system verification.

Co-Authored-By: Claude Haiku 4.5 <noreply@anthropic.com>
2026-01-15 03:30:46 +00:00

162 lines
5.0 KiB
TypeScript

import { beforeEach, describe, expect, it, vi } from 'vitest'
import { DBALClient } from '../../src/core/client'
import { DBALErrorCode } from '../../src/core/foundation/errors'
const mockAdapter = vi.hoisted(() => ({
create: vi.fn(),
read: vi.fn(),
update: vi.fn(),
delete: vi.fn(),
list: vi.fn(),
findFirst: vi.fn(),
findByField: vi.fn(),
upsert: vi.fn(),
updateByField: vi.fn(),
deleteByField: vi.fn(),
deleteMany: vi.fn(),
createMany: vi.fn(),
updateMany: vi.fn(),
getCapabilities: vi.fn(),
close: vi.fn(),
}))
vi.mock('../../src/adapters/prisma', () => ({
PrismaAdapter: vi.fn(function() { return mockAdapter }),
PostgresAdapter: vi.fn(function() { return mockAdapter }),
MySQLAdapter: vi.fn(function() { return mockAdapter }),
}))
const baseConfig = {
mode: 'development' as const,
adapter: 'prisma' as const,
database: { url: 'file:memory' },
tenantId: 'tenant-123',
}
const userBatch = [
{ username: 'alpha', email: 'alpha@example.com', role: 'user' as const },
{ username: 'beta', email: 'beta@example.com', role: 'admin' as const },
]
const packageBatch = [
{
packageId: 'forum',
version: '1.0.0',
enabled: false,
installedAt: BigInt(1700000000000),
config: JSON.stringify({ entry: 'index.js' }),
},
{
packageId: 'chat',
version: '2.1.0',
enabled: true,
installedAt: BigInt(1700000005000),
config: JSON.stringify({ entry: 'chat.js' }),
},
]
beforeEach(() => {
Object.values(mockAdapter).forEach(value => {
if (typeof value === 'function' && 'mockReset' in value) {
value.mockReset()
}
})
})
describe('DBALClient batch operations', () => {
it('creates users in bulk via adapter', async () => {
mockAdapter.createMany.mockResolvedValue(2)
const client = new DBALClient(baseConfig)
const result = await client.users.createMany(userBatch)
const payload = mockAdapter.createMany.mock.calls[0]?.[1] as Record<string, unknown>[]
expect(mockAdapter.createMany).toHaveBeenCalledWith('User', expect.any(Array))
expect(payload).toHaveLength(2)
expect(payload[0]).toMatchObject({ ...userBatch[0], tenantId: baseConfig.tenantId })
expect(payload[1]).toMatchObject({ ...userBatch[1], tenantId: baseConfig.tenantId })
expect(typeof payload[0].id).toBe('string')
expect(typeof payload[0].createdAt).toBe('bigint')
expect(result).toBe(2)
})
it('rejects bulk user create with invalid data', async () => {
const client = new DBALClient(baseConfig)
await expect(client.users.createMany([
{ username: '', email: 'bad', role: 'user' as const },
])).rejects.toMatchObject({ code: DBALErrorCode.VALIDATION_ERROR })
expect(mockAdapter.createMany).not.toHaveBeenCalled()
})
it('updates users in bulk with a filter', async () => {
mockAdapter.updateMany.mockResolvedValue(1)
const client = new DBALClient(baseConfig)
const result = await client.users.updateMany({ role: 'user' }, { role: 'admin' })
expect(mockAdapter.updateMany).toHaveBeenCalledWith(
'User',
{ role: 'user', tenantId: baseConfig.tenantId },
{ role: 'admin' }
)
expect(result).toBe(1)
})
it('rejects bulk user update without a filter', async () => {
const client = new DBALClient(baseConfig)
await expect(client.users.updateMany({}, { role: 'admin' })).rejects.toMatchObject({
code: DBALErrorCode.VALIDATION_ERROR,
})
})
it('deletes users in bulk with a filter', async () => {
mockAdapter.deleteMany.mockResolvedValue(2)
const client = new DBALClient(baseConfig)
const result = await client.users.deleteMany({ role: 'user' })
expect(mockAdapter.deleteMany).toHaveBeenCalledWith('User', { role: 'user', tenantId: baseConfig.tenantId })
expect(result).toBe(2)
})
it('creates packages in bulk via adapter', async () => {
mockAdapter.createMany.mockResolvedValue(2)
const client = new DBALClient(baseConfig)
const result = await client.installedPackages.createMany(packageBatch)
expect(mockAdapter.createMany).toHaveBeenCalledWith('InstalledPackage', [
{ ...packageBatch[0], tenantId: baseConfig.tenantId },
{ ...packageBatch[1], tenantId: baseConfig.tenantId },
])
expect(result).toBe(2)
})
it('updates packages in bulk with a filter', async () => {
mockAdapter.updateMany.mockResolvedValue(3)
const client = new DBALClient(baseConfig)
const result = await client.installedPackages.updateMany({ enabled: false }, { enabled: true })
expect(mockAdapter.updateMany).toHaveBeenCalledWith(
'InstalledPackage',
{ enabled: false, tenantId: baseConfig.tenantId },
{ enabled: true }
)
expect(result).toBe(3)
})
it('deletes packages in bulk with a filter', async () => {
mockAdapter.deleteMany.mockResolvedValue(1)
const client = new DBALClient(baseConfig)
const result = await client.installedPackages.deleteMany({ packageId: 'forum' })
expect(mockAdapter.deleteMany).toHaveBeenCalledWith('InstalledPackage', { packageId: 'forum', tenantId: baseConfig.tenantId })
expect(result).toBe(1)
})
})