test: add Wave 1 infrastructure (types, mocks, vitest config) + User/Order/Material factories
- tests/fixtures/types.ts: Test fixture type definitions - tests/fixtures/factory.ts: User/Order/Material factories - tests/mocks/types.ts: Mock type definitions (549 lines) - tests/mocks/index.ts: Mock factory functions - vitest.config.ts: Performance optimizations (isolate:false, pool:threads) - User/Order/Material factory tests (7 tests total) Performance: 7.65s → 4.94s (35% improvement)
This commit is contained in:
549
tests/mocks/types.ts
Normal file
549
tests/mocks/types.ts
Normal file
@@ -0,0 +1,549 @@
|
||||
/**
|
||||
* Mock Type Definitions for ERPAuto Unit Tests
|
||||
*
|
||||
* This module provides strongly-typed Mock interfaces and factory function signatures
|
||||
* for all core services that need to be mocked in unit tests.
|
||||
*
|
||||
* Design Principles:
|
||||
* - Zero any types - all mocks are fully typed
|
||||
* - Use vi.fn() mocks for all methods
|
||||
* - Factory functions accept Partial<T> overrides for customization
|
||||
* - JSDoc comments on all types and functions
|
||||
*
|
||||
* Usage:
|
||||
* - Import types from this file in test files
|
||||
* - Use vi.fn() to create mock implementations
|
||||
* - Factory functions provide sensible defaults
|
||||
*
|
||||
* Note: This file defines standalone mock types compatible with src/main interfaces.
|
||||
* Import actual Config/Logger/Erp types from src/main in test files when needed.
|
||||
*/
|
||||
|
||||
import { vi } from 'vitest'
|
||||
import type { Browser, BrowserContext, Page, Frame } from 'playwright'
|
||||
|
||||
// ============================================================================
|
||||
// Re-exported/Compatible Types from src/main (for mock compatibility)
|
||||
// ============================================================================
|
||||
|
||||
/**
|
||||
* Logging level type - must match src/main/services/logger/index.ts
|
||||
*/
|
||||
export type LogLevel = 'error' | 'warn' | 'info' | 'debug' | 'verbose'
|
||||
|
||||
/**
|
||||
* Database type enum - must match src/main/types/config.schema.ts
|
||||
*/
|
||||
export type DatabaseType = 'mysql' | 'sqlserver'
|
||||
|
||||
/**
|
||||
* MySQL configuration - compatible with src/main/types/config.schema.ts
|
||||
*/
|
||||
export interface MySqlConfig {
|
||||
host: string
|
||||
port: number
|
||||
database: string
|
||||
username: string
|
||||
password: string
|
||||
charset: string
|
||||
}
|
||||
|
||||
/**
|
||||
* SQL Server configuration - compatible with src/main/types/config.schema.ts
|
||||
*/
|
||||
export interface SqlServerConfig {
|
||||
server: string
|
||||
port: number
|
||||
database: string
|
||||
username: string
|
||||
password: string
|
||||
driver: string
|
||||
trustServerCertificate: boolean
|
||||
}
|
||||
|
||||
/**
|
||||
* Database configuration section - compatible with src/main/types/config.schema.ts
|
||||
*/
|
||||
export interface DatabaseConfig {
|
||||
activeType: DatabaseType
|
||||
mysql: MySqlConfig
|
||||
sqlserver: SqlServerConfig
|
||||
}
|
||||
|
||||
/**
|
||||
* ERP configuration - compatible with src/main/types/config.schema.ts
|
||||
*/
|
||||
export interface ErpConfig {
|
||||
url: string
|
||||
}
|
||||
|
||||
/**
|
||||
* Paths configuration - compatible with src/main/types/config.schema.ts
|
||||
*/
|
||||
export interface PathsConfig {
|
||||
dataDir: string
|
||||
defaultOutput: string
|
||||
validationOutput: string
|
||||
}
|
||||
|
||||
/**
|
||||
* Extraction configuration - compatible with src/main/types/config.schema.ts
|
||||
*/
|
||||
export interface ExtractionConfig {
|
||||
batchSize: number
|
||||
verbose: boolean
|
||||
autoConvert: boolean
|
||||
mergeBatches: boolean
|
||||
enableDbPersistence: boolean
|
||||
headless: boolean
|
||||
}
|
||||
|
||||
/**
|
||||
* Validation configuration - compatible with src/main/types/config.schema.ts
|
||||
*/
|
||||
export interface ValidationConfig {
|
||||
dataSource: string
|
||||
batchSize: number
|
||||
matchMode: string
|
||||
enableCrud: boolean
|
||||
defaultManager: string
|
||||
}
|
||||
|
||||
/**
|
||||
* Cleaner configuration - compatible with src/main/types/config.schema.ts
|
||||
*/
|
||||
export interface CleanerConfig {
|
||||
queryBatchSize: number
|
||||
processConcurrency: number
|
||||
}
|
||||
|
||||
/**
|
||||
* Order resolution configuration - compatible with src/main/types/config.schema.ts
|
||||
*/
|
||||
export interface OrderResolutionConfig {
|
||||
tableName: string
|
||||
productionIdField: string
|
||||
orderNumberField: string
|
||||
}
|
||||
|
||||
/**
|
||||
* Logging configuration - compatible with src/main/types/config.schema.ts
|
||||
*/
|
||||
export interface LoggingConfig {
|
||||
level: LogLevel
|
||||
auditRetention: number
|
||||
appRetention: number
|
||||
}
|
||||
|
||||
/**
|
||||
* Seq configuration - compatible with src/main/types/config.schema.ts
|
||||
*/
|
||||
export interface SeqConfig {
|
||||
enabled: boolean
|
||||
serverUrl: string
|
||||
apiKey: string
|
||||
batchPostingLimit: number
|
||||
period: number
|
||||
queueLimit: number
|
||||
maxRetries: number
|
||||
}
|
||||
|
||||
/**
|
||||
* RustFS configuration - compatible with src/main/types/config.schema.ts
|
||||
*/
|
||||
export interface RustFSConfig {
|
||||
enabled: boolean
|
||||
endpoint: string
|
||||
accessKey: string
|
||||
secretKey: string
|
||||
bucket: string
|
||||
region: string
|
||||
}
|
||||
|
||||
/**
|
||||
* Update configuration - compatible with src/main/types/config.schema.ts
|
||||
*/
|
||||
export interface UpdateConfig {
|
||||
enabled: boolean
|
||||
allowDevMode: boolean
|
||||
endpoint: string
|
||||
accessKey: string
|
||||
secretKey: string
|
||||
bucket: string
|
||||
region: string
|
||||
basePrefix: string
|
||||
checkIntervalMinutes: number
|
||||
maxAdminHistoryPerChannel: number
|
||||
}
|
||||
|
||||
/**
|
||||
* Full application configuration - compatible with src/main/types/config.schema.ts
|
||||
*/
|
||||
export interface FullConfig {
|
||||
erp: ErpConfig
|
||||
database: DatabaseConfig
|
||||
paths: PathsConfig
|
||||
extraction: ExtractionConfig
|
||||
validation: ValidationConfig
|
||||
cleaner: CleanerConfig
|
||||
orderResolution: OrderResolutionConfig
|
||||
logging: LoggingConfig
|
||||
seq: SeqConfig
|
||||
rustfs: RustFSConfig
|
||||
update: UpdateConfig
|
||||
}
|
||||
|
||||
// ============================================================================
|
||||
// Logger Mock Types
|
||||
// ============================================================================
|
||||
|
||||
/**
|
||||
* Mock Logger interface matching winston.Logger API
|
||||
* Used for testing services that depend on logging without writing to actual log files
|
||||
*/
|
||||
export interface MockLogger {
|
||||
/** Log at 'error' level with error serialization */
|
||||
error: (message: string, meta?: Record<string, unknown>) => void
|
||||
|
||||
/** Log at 'warn' level */
|
||||
warn: (message: string, meta?: Record<string, unknown>) => void
|
||||
|
||||
/** Log at 'info' level - most common for business logic */
|
||||
info: (message: string, meta?: Record<string, unknown>) => void
|
||||
|
||||
/** Log at 'debug' level for detailed diagnostic info */
|
||||
debug: (message: string, meta?: Record<string, unknown>) => void
|
||||
|
||||
/** Log at 'verbose' level - most detailed tracing */
|
||||
verbose: (message: string, meta?: Record<string, unknown>) => void
|
||||
|
||||
/** Create a child logger with specific context */
|
||||
child: (context: string) => MockLogger
|
||||
}
|
||||
|
||||
// ============================================================================
|
||||
// ConfigManager Mock Types
|
||||
// ============================================================================
|
||||
|
||||
/**
|
||||
* Mock ConfigManager interface matching the production ConfigManager class
|
||||
* Used for testing services that depend on configuration without file I/O
|
||||
*/
|
||||
export interface MockConfigManager {
|
||||
/** Get full configuration object */
|
||||
getConfig: () => FullConfig
|
||||
|
||||
/** Get currently active database config (MySQL or SQL Server) */
|
||||
getActiveDatabaseConfig: () => MySqlConfig | SqlServerConfig
|
||||
|
||||
/** Get database type enum */
|
||||
getDatabaseType: () => DatabaseType
|
||||
|
||||
/** Get logging configuration section */
|
||||
getLoggingConfig: () => LoggingConfig
|
||||
|
||||
/** Update configuration with deep merge */
|
||||
updateConfig: (updates: Partial<FullConfig>) => Promise<{ success: boolean; error?: string }>
|
||||
|
||||
/** Reset to default configuration */
|
||||
resetToDefaults: () => Promise<boolean>
|
||||
|
||||
/** Get default configuration template */
|
||||
getDefaultConfig: () => FullConfig
|
||||
|
||||
/** Export config as YAML string */
|
||||
exportToYaml: () => string
|
||||
}
|
||||
|
||||
// ============================================================================
|
||||
// ErpAuthService Mock Types
|
||||
// ============================================================================
|
||||
|
||||
/**
|
||||
* Mock ErpAuthService interface matching the production ERP authentication service
|
||||
* Used for testing services that interact with ERP without actual browser automation
|
||||
*
|
||||
* Key methods:
|
||||
* - login: Establish mock ERP session
|
||||
* - close: Cleanup mock session
|
||||
* - getSession: Return mock session (must be logged in)
|
||||
* - isActive: Check if mock session is active
|
||||
*/
|
||||
export interface MockErpAuthService {
|
||||
/** Login to ERP system and establish mock session */
|
||||
login: () => Promise<MockErpSession>
|
||||
|
||||
/** Close mock browser session and cleanup */
|
||||
close: () => Promise<void>
|
||||
|
||||
/** Get current mock session (throws if not logged in) */
|
||||
getSession: () => MockErpSession
|
||||
|
||||
/** Check if mock session is active */
|
||||
isActive: () => boolean
|
||||
}
|
||||
|
||||
/**
|
||||
* Mock ERP Session interface
|
||||
* Simplified version of ErpSession for testing - uses vi.fn() mocks for Playwright objects
|
||||
*/
|
||||
export interface MockErpSession {
|
||||
/** Mock Playwright Browser instance */
|
||||
browser: MockBrowser
|
||||
|
||||
/** Mock Playwright BrowserContext instance */
|
||||
context: MockBrowserContext
|
||||
|
||||
/** Mock Playwright Page instance */
|
||||
page: MockPage
|
||||
|
||||
/** Mock Playwright Frame instance (forwardFrame content) */
|
||||
mainFrame: MockFrame
|
||||
|
||||
/** Whether the session is logged in */
|
||||
isLoggedIn: boolean
|
||||
}
|
||||
|
||||
// ============================================================================
|
||||
// Playwright Mock Types
|
||||
// ============================================================================
|
||||
|
||||
/**
|
||||
* Mock Browser interface - simplified for unit testing
|
||||
* Focus on methods used in ERPAuto codebase
|
||||
*/
|
||||
export interface MockBrowser {
|
||||
/** Close the browser */
|
||||
close: () => Promise<void>
|
||||
|
||||
/** Check if browser is connected */
|
||||
isConnected: () => boolean
|
||||
}
|
||||
|
||||
/**
|
||||
* Mock BrowserContext interface - simplified for unit testing
|
||||
*/
|
||||
export interface MockBrowserContext {
|
||||
/** Close the context */
|
||||
close: () => Promise<void>
|
||||
|
||||
/** Create a new page in this context */
|
||||
newPage: () => Promise<MockPage>
|
||||
}
|
||||
|
||||
/**
|
||||
* Mock Page interface - simplified for unit testing
|
||||
* Includes commonly used Playwright Page methods
|
||||
*/
|
||||
export interface MockPage {
|
||||
/** Navigate to URL */
|
||||
goto: (url: string, options?: { waitUntil?: string }) => Promise<void>
|
||||
|
||||
/** Wait for selector */
|
||||
waitForSelector: (
|
||||
selector: string,
|
||||
options?: { state?: string; timeout?: number }
|
||||
) => Promise<void>
|
||||
|
||||
/** Wait for load state */
|
||||
waitForLoadState: (state: string, options?: { timeout?: number }) => Promise<void>
|
||||
|
||||
/** Take screenshot (mock - no actual file) */
|
||||
screenshot: (options?: { path?: string }) => Promise<Buffer>
|
||||
|
||||
/** Get page content */
|
||||
content: () => Promise<string>
|
||||
|
||||
/** Close the page */
|
||||
close: () => Promise<void>
|
||||
|
||||
/** Mock locator */
|
||||
locator: (selector: string) => MockLocator
|
||||
|
||||
/** Mock getByRole */
|
||||
getByRole: (role: string, options?: { name?: string }) => MockLocator
|
||||
}
|
||||
|
||||
/**
|
||||
* Mock Frame interface - simplified for unit testing
|
||||
*/
|
||||
export interface MockFrame {
|
||||
/** Get frame content */
|
||||
content: () => Promise<string>
|
||||
|
||||
/** Mock locator within frame */
|
||||
locator: (selector: string) => MockLocator
|
||||
|
||||
/** Mock getByRole within frame */
|
||||
getByRole: (role: string, options?: { name?: string }) => MockLocator
|
||||
|
||||
/** Wait for selector in frame */
|
||||
waitForSelector: (
|
||||
selector: string,
|
||||
options?: { state?: string; timeout?: number }
|
||||
) => Promise<void>
|
||||
}
|
||||
|
||||
/**
|
||||
* Mock Locator interface - simplified for unit testing
|
||||
*/
|
||||
export interface MockLocator {
|
||||
/** Fill input with value */
|
||||
fill: (value: string) => Promise<void>
|
||||
|
||||
/** Click the element */
|
||||
click: () => Promise<void>
|
||||
|
||||
/** Wait for element */
|
||||
waitFor: (options?: { state?: string; timeout?: number }) => Promise<void>
|
||||
|
||||
/** Check if element is visible */
|
||||
isVisible: () => Promise<boolean>
|
||||
|
||||
/** Get element text content */
|
||||
textContent: () => Promise<string | null>
|
||||
|
||||
/** Get element attribute */
|
||||
getAttribute: (name: string) => Promise<string | null>
|
||||
}
|
||||
|
||||
// ============================================================================
|
||||
// Electron Mock Types (from setup.ts)
|
||||
// ============================================================================
|
||||
|
||||
/**
|
||||
* Mock Electron app interface - matches existing setup.ts implementation
|
||||
*/
|
||||
export interface MockElectronApp {
|
||||
isPackaged: boolean
|
||||
isReady: () => boolean
|
||||
getPath: (name: string) => string
|
||||
getVersion: () => string
|
||||
getName: () => string
|
||||
getAppPath: () => string
|
||||
on: (event: string, listener: () => void) => void
|
||||
off: (event: string, listener: () => void) => void
|
||||
once: (event: string, listener: () => void) => void
|
||||
emit: (event: string, ...args: unknown[]) => void
|
||||
isDefaultProtocolClient: (protocol: string) => boolean
|
||||
quit: () => void
|
||||
relaunch: (options?: { args?: string[] }) => void
|
||||
exit: (code?: number) => void
|
||||
focus: () => void
|
||||
blur: () => void
|
||||
isQuitting: () => boolean
|
||||
isAccessibilityEnabled: () => boolean
|
||||
getApplicationNameForProtocol: (protocol: string) => string | null
|
||||
}
|
||||
|
||||
/**
|
||||
* Mock IPC Main interface - matches existing setup.ts implementation
|
||||
*/
|
||||
export interface MockIpcMain {
|
||||
handle: (channel: string, listener: (...args: unknown[]) => void | Promise<unknown>) => void
|
||||
on: (channel: string, listener: (...args: unknown[]) => void) => void
|
||||
once: (channel: string, listener: (...args: unknown[]) => void) => void
|
||||
removeHandler: (channel: string) => void
|
||||
removeListener: (channel: string, listener: (...args: unknown[]) => void) => void
|
||||
removeAllListeners: (channel: string) => void
|
||||
}
|
||||
|
||||
/**
|
||||
* Mock Electron Dialog interface - matches existing setup.ts implementation
|
||||
*/
|
||||
export interface MockDialog {
|
||||
showErrorBox: (title: string, content: string) => void
|
||||
showMessageBox: (options: unknown) => Promise<{ response: number }>
|
||||
showOpenDialog: (options: unknown) => Promise<{ canceled: boolean; filePaths?: string[] }>
|
||||
showSaveDialog: (options: unknown) => Promise<{ canceled: boolean; filePath?: string }>
|
||||
}
|
||||
|
||||
/**
|
||||
* Mock Electron Shell interface - matches existing setup.ts implementation
|
||||
*/
|
||||
export interface MockShell {
|
||||
openPath: (path: string) => Promise<string>
|
||||
openExternal: (url: string) => Promise<void>
|
||||
showItemInFolder: (fullPath: string) => void
|
||||
trashItem: (fullPath: string) => void
|
||||
}
|
||||
|
||||
/**
|
||||
* Mock Electron BrowserWindow interface - matches existing setup.ts implementation
|
||||
*/
|
||||
export interface MockBrowserWindowConstructor {
|
||||
getAllWindows: () => MockBrowserWindow[]
|
||||
fromWebContents: (webContents: unknown) => MockBrowserWindow | null
|
||||
fromId: (id: number) => MockBrowserWindow | null
|
||||
getFocusedWindow: () => MockBrowserWindow | null
|
||||
}
|
||||
|
||||
/**
|
||||
* Mock BrowserWindow instance interface
|
||||
*/
|
||||
export interface MockBrowserWindow {
|
||||
isDestroyed: () => boolean
|
||||
close: () => void
|
||||
destroy: () => void
|
||||
webContents: {
|
||||
send: (channel: string, ...args: unknown[]) => void
|
||||
isDestroyed: () => boolean
|
||||
}
|
||||
}
|
||||
|
||||
// ============================================================================
|
||||
// Factory Function Type Signatures
|
||||
// ============================================================================
|
||||
|
||||
/**
|
||||
* Options for creating a mock logger
|
||||
*/
|
||||
export interface MockLoggerOptions {
|
||||
/** Custom log level filters */
|
||||
level?: LogLevel
|
||||
/** Override specific methods */
|
||||
overrides?: Partial<MockLogger>
|
||||
}
|
||||
|
||||
/**
|
||||
* Options for creating a mock config manager
|
||||
*/
|
||||
export interface MockConfigManagerOptions {
|
||||
/** Initial config values to merge with defaults */
|
||||
config?: Partial<FullConfig>
|
||||
/** Override specific methods */
|
||||
overrides?: Partial<MockConfigManager>
|
||||
}
|
||||
|
||||
/**
|
||||
* Options for creating a mock ERP auth service
|
||||
*/
|
||||
export interface MockErpAuthOptions {
|
||||
/** Whether the session should start as logged in */
|
||||
isLoggedIn?: boolean
|
||||
/** ERP config to use */
|
||||
config?: Partial<ErpConfig>
|
||||
/** Override specific methods */
|
||||
overrides?: Partial<MockErpAuthService>
|
||||
}
|
||||
|
||||
/**
|
||||
* Create a mock logger instance
|
||||
* @param overrides - Optional overrides for specific methods or properties
|
||||
* @returns Mock logger matching winston.Logger API
|
||||
*/
|
||||
export type MockLoggerFactory = (overrides?: Partial<MockLogger>) => MockLogger
|
||||
|
||||
/**
|
||||
* Create a mock config manager instance
|
||||
* @param config - Optional partial config to use as initial state
|
||||
* @returns Mock config manager
|
||||
*/
|
||||
export type MockConfigManagerFactory = (config?: Partial<FullConfig>) => MockConfigManager
|
||||
|
||||
/**
|
||||
* Create a mock ERP auth service instance
|
||||
* @param options - Options including initial login state and config
|
||||
* @returns Mock ERP auth service
|
||||
*/
|
||||
export type MockErpAuthFactory = (options?: MockErpAuthOptions) => MockErpAuthService
|
||||
Reference in New Issue
Block a user