/** * Test Application Utilities * * Provides utilities for creating and managing test applications * in Titan framework tests. */ import { Application } from '@omnitron-dev/titan/application'; import type { IApplicationOptions } from '@omnitron-dev/titan/application'; import { Container } from '@omnitron-dev/titan/nexus'; import { Errors } from '@omnitron-dev/titan/errors'; /** * Test application builder with simplified API */ export class TestApplication { private app: Application | null = null; private container: Container; private cleanupFns: (() => Promise | void)[] = []; constructor(private options: Partial = {}) { this.container = new Container(); } /** * Create test application with modules */ static async create(rootModule: any, options: Partial = {}): Promise { const testApp = new TestApplication(options); await testApp.bootstrap(rootModule); return testApp; } /** * Bootstrap the application */ async bootstrap(rootModule: any): Promise { // Create application with test defaults this.app = await Application.create({ ...this.options, modules: [rootModule], logger: (this.options as any)['logger'] ?? false, // Disable logging by default in tests gracefulShutdown: false, disableCoreModules: !(this.options as any)['registerCoreModules'], }); // Store container reference - use public getter this.container = this.app.container; } /** * Get service instance from container */ get(token: any): T { if (!this.container) { throw Errors.internal('Application not initialized'); } return this.container.resolve(token); } /** * Check if service exists in container */ has(token: any): boolean { if (!this.container) { return false; } return this.container.has(token); } /** * Get the application instance */ getApplication(): Application { if (!this.app) { throw Errors.internal('Application not initialized'); } return this.app; } /** * Get the container instance */ getContainer(): Container { return this.container; } /** * Register cleanup function */ addCleanup(fn: () => Promise | void): void { this.cleanupFns.push(fn); } /** * Close application and cleanup */ async close(): Promise { // Run custom cleanup functions for (const fn of this.cleanupFns.reverse()) { await fn(); } // Close application if (this.app) { await this.app.stop(); this.app = null; } } /** * Create spy for service method */ spyOn(service: T, method: keyof T): any { const spy = vi.spyOn(service as any, method as any); this.addCleanup(() => spy.mockRestore()); return spy; } /** * Mock service in container */ mock(token: any, mockImplementation: Partial): void { const original = this.container.resolve(token); Object.assign(original as any, mockImplementation); this.addCleanup(() => { // Restore original implementation for (const key in mockImplementation) { delete (original as any)[key]; } }); } /** * Override provider in container */ override(token: any, value: T): void { const originalBinding = (this.container as any).bindings.get(token); (this.container as any).bindings.set(token, { token, useValue: value, scope: 'singleton', }); this.addCleanup(() => { if (originalBinding) { (this.container as any).bindings.set(token, originalBinding); } else { (this.container as any).bindings.delete(token); } }); } }