mirror of
https://github.com/CherryHQ/cherry-studio.git
synced 2026-07-04 05:00:00 +08:00
145 lines
3.7 KiB
TypeScript
145 lines
3.7 KiB
TypeScript
import { vi } from 'vitest'
|
|
|
|
/**
|
|
* Mock DbService for main process testing
|
|
* Simulates the complete main process DbService functionality
|
|
*/
|
|
|
|
/**
|
|
* A chainable mock drizzle query builder. Every chain method returns the same
|
|
* builder; the synchronous terminals mirror better-sqlite3's drizzle dialect:
|
|
* `.run()` → RunResult-shaped, `.all()` → `[]`, `.get()` → `undefined`. Tests that
|
|
* need specific results override these via `vi.spyOn`/`mockReturnValue`.
|
|
*/
|
|
function makeQueryBuilderMock(): Record<string, ReturnType<typeof vi.fn>> {
|
|
const builder: Record<string, ReturnType<typeof vi.fn>> = {}
|
|
const chainMethods = [
|
|
'from',
|
|
'where',
|
|
'set',
|
|
'values',
|
|
'limit',
|
|
'offset',
|
|
'orderBy',
|
|
'groupBy',
|
|
'having',
|
|
'returning',
|
|
'onConflictDoUpdate',
|
|
'onConflictDoNothing',
|
|
'leftJoin',
|
|
'innerJoin',
|
|
'rightJoin'
|
|
]
|
|
for (const method of chainMethods) {
|
|
builder[method] = vi.fn(() => builder)
|
|
}
|
|
builder.run = vi.fn(() => ({ changes: 0, lastInsertRowid: 0 }))
|
|
builder.all = vi.fn(() => [])
|
|
builder.get = vi.fn(() => undefined)
|
|
return builder
|
|
}
|
|
|
|
// Default mock database with chainable, synchronous (better-sqlite3-shaped) stubs.
|
|
const defaultMockDb = {
|
|
select: vi.fn(() => makeQueryBuilderMock()),
|
|
insert: vi.fn(() => makeQueryBuilderMock()),
|
|
update: vi.fn(() => makeQueryBuilderMock()),
|
|
delete: vi.fn(() => makeQueryBuilderMock()),
|
|
run: vi.fn(() => ({ changes: 0, lastInsertRowid: 0 })),
|
|
transaction: vi.fn((fn: (tx: unknown) => unknown) => fn(defaultMockDb))
|
|
}
|
|
|
|
/**
|
|
* Mock DbService class
|
|
*/
|
|
export class MockMainDbService {
|
|
private static instance: MockMainDbService
|
|
private db: unknown = defaultMockDb
|
|
private _isReady = true
|
|
|
|
private constructor() {}
|
|
|
|
public static getInstance(): MockMainDbService {
|
|
if (!MockMainDbService.instance) {
|
|
MockMainDbService.instance = new MockMainDbService()
|
|
}
|
|
return MockMainDbService.instance
|
|
}
|
|
|
|
public getDb = vi.fn(() => this.db)
|
|
|
|
/**
|
|
* Write transaction mock. Mirrors `DbService.withWriteTx`: synchronously passes
|
|
* the current db (or whatever was set via `setDb`) to the synchronous `fn` so
|
|
* tests exercising the write path do not need a real transaction. Tests can
|
|
* replace this mock with `vi.spyOn(...)` to assert call order, etc.
|
|
*/
|
|
public withWriteTx = vi.fn(<T>(fn: (tx: unknown) => T): T => fn(this.db))
|
|
|
|
public get isReady() {
|
|
return this._isReady
|
|
}
|
|
}
|
|
|
|
// Mock singleton instance
|
|
const mockInstance = MockMainDbService.getInstance()
|
|
|
|
/**
|
|
* Export mock service
|
|
*/
|
|
export const MockMainDbServiceExport = {
|
|
DbService: MockMainDbService,
|
|
dbService: mockInstance
|
|
}
|
|
|
|
/**
|
|
* Utility functions for testing
|
|
*/
|
|
export const MockMainDbServiceUtils = {
|
|
/**
|
|
* Reset all mock call counts and state
|
|
*/
|
|
resetMocks: () => {
|
|
mockInstance.getDb.mockClear()
|
|
mockInstance.withWriteTx.mockClear()
|
|
|
|
// Reset default db mocks
|
|
Object.values(defaultMockDb).forEach((method) => {
|
|
if (vi.isMockFunction(method)) {
|
|
method.mockClear()
|
|
}
|
|
})
|
|
|
|
// Restore default db
|
|
mockInstance['db'] = defaultMockDb
|
|
mockInstance['_isReady'] = true
|
|
},
|
|
|
|
/**
|
|
* Replace the db instance with a custom mock
|
|
*/
|
|
setDb: (customDb: unknown) => {
|
|
mockInstance['db'] = customDb
|
|
},
|
|
|
|
/**
|
|
* Get the default mock db for reuse or extension
|
|
*/
|
|
getDefaultMockDb: () => defaultMockDb,
|
|
|
|
/**
|
|
* Set ready state for testing
|
|
*/
|
|
setIsReady: (ready: boolean) => {
|
|
mockInstance['_isReady'] = ready
|
|
},
|
|
|
|
/**
|
|
* Get mock call counts for debugging
|
|
*/
|
|
getMockCallCounts: () => ({
|
|
getDb: mockInstance.getDb.mock.calls.length,
|
|
withWriteTx: mockInstance.withWriteTx.mock.calls.length
|
|
})
|
|
}
|