UNPKG

@notjustcoders/ioc-arise

Version:

Arise type-safe IoC containers from your code. Zero overhead, zero coupling.

116 lines 5.15 kB
"use strict"; Object.defineProperty(exports, "__esModule", { value: true }); exports.MockClassResolver = void 0; /** * Utility class for resolving mock classes based on configuration */ class MockClassResolver { /** * Resolves a mock class for the given target class if mock mode is enabled * @param targetClass The class name to find a mock for * @param availableClasses All available classes in the project * @param mockConfig Mock configuration from ioc.config.json * @returns Mock class name if found, null otherwise */ static resolveMockClass(targetClass, availableClasses, mockConfig) { if (!mockConfig?.enabled || !mockConfig?.mockMode) { return null; } // Priority 1: Explicit mock mappings if (mockConfig.explicitMocks?.[targetClass]) { const explicitMock = mockConfig.explicitMocks[targetClass]; // Verify the explicit mock class exists const mockExists = availableClasses.some(c => c.name === explicitMock); if (mockExists) { return explicitMock; } } // Priority 2: Find mock classes using glob patterns if (mockConfig.mockClassGlobs && mockConfig.mockClassGlobs.length > 0) { for (const globPattern of mockConfig.mockClassGlobs) { const mockCandidates = availableClasses.filter(classInfo => this.matchesGlobPattern(classInfo.name, globPattern) && this.isMockForTarget(classInfo.name, targetClass)); if (mockCandidates.length > 0) { return mockCandidates[0]?.name || null; // Return first match } } } return null; // No mock found, use original class } /** * Checks if a class name matches a glob pattern * @param className The class name to check * @param globPattern The glob pattern (e.g., "*Mock*", "Mock*") * @returns true if the class name matches the pattern */ static matchesGlobPattern(className, globPattern) { // Convert glob pattern to regex const regexPattern = globPattern .replace(/\*/g, '.*') .replace(/\?/g, '.'); const regex = new RegExp(`^${regexPattern}$`, 'i'); return regex.test(className); } /** * Determines if a mock class name is intended for the target class * @param mockClassName The potential mock class name * @param targetClassName The target class name * @returns true if the mock is for the target */ static isMockForTarget(mockClassName, targetClassName) { // Remove common mock prefixes/suffixes to get the core name const cleanMockName = mockClassName .replace(/^Mock/i, '') .replace(/Mock$/i, '') .replace(/^Test/i, '') .replace(/Test$/i, ''); // Check various matching strategies return (cleanMockName === targetClassName || targetClassName.includes(cleanMockName) || cleanMockName.includes(targetClassName) || this.fuzzyMatch(cleanMockName, targetClassName)); } /** * Performs fuzzy matching between mock and target class names * @param mockName Cleaned mock class name * @param targetName Target class name * @returns true if names are similar enough */ static fuzzyMatch(mockName, targetName) { // Simple fuzzy matching - check if they share significant common parts const mockParts = mockName.toLowerCase().split(/(?=[A-Z])/); const targetParts = targetName.toLowerCase().split(/(?=[A-Z])/); // If they share at least 50% of parts, consider it a match const commonParts = mockParts.filter(part => targetParts.some(targetPart => targetPart.includes(part) || part.includes(targetPart))); return commonParts.length >= Math.min(mockParts.length, targetParts.length) * 0.5; } /** * Gets all available mock classes based on configuration * @param availableClasses All available classes * @param mockConfig Mock configuration * @returns Array of mock class names */ static getAllMockClasses(availableClasses, mockConfig) { if (!mockConfig?.enabled || !mockConfig.mockClassGlobs) { return []; } const mockClasses = new Set(); // Add explicit mocks if (mockConfig.explicitMocks) { Object.values(mockConfig.explicitMocks).forEach(mockClass => { if (availableClasses.some(c => c.name === mockClass)) { mockClasses.add(mockClass); } }); } // Add classes matching glob patterns for (const globPattern of mockConfig.mockClassGlobs) { availableClasses .filter(classInfo => this.matchesGlobPattern(classInfo.name, globPattern)) .forEach(classInfo => mockClasses.add(classInfo.name)); } return Array.from(mockClasses); } } exports.MockClassResolver = MockClassResolver; //# sourceMappingURL=mock-class-resolver.js.map