Skip to main content
Glama
dead-code-detection.test.ts11.6 kB
/** * Dead Code Detection Tests * * These tests systematically detect common dead code patterns using deterministic methods. * Based on findings from DEAD-CODE-ANALYSIS.md - ensures we catch these issues going forward. */ import { describe, it, expect } from 'vitest'; import { readFileSync, readdirSync, statSync, existsSync } from 'fs'; import { join, resolve } from 'path'; import { execSync } from 'child_process'; // Get project root dynamically const projectRoot = resolve(__dirname, '../../'); describe('Dead Code Detection - Deterministic Validation', () => { describe('Method Call Validation', () => { it('should not have calls to non-existent methods', async () => { // Test the specific pattern that caused our SharedTestClient bug const problematicPatterns = [ { pattern: /\.isInitialized\(\)/g, file: join(projectRoot, 'tests/factories/shared-client.ts'), description: 'isInitialized() calls on NavidromeClient (which lacks this method)' } ]; for (const { pattern, file, description } of problematicPatterns) { try { const content = readFileSync(file, 'utf-8'); const matches = content.match(pattern); if (matches) { // Check if this is a valid call by examining the class definition if (file.includes('shared-client.ts')) { // For SharedTestClient: isInitialized() should only be called on objects that have it const lines = content.split('\n'); const problematicLines = lines .map((line, index) => ({ line: line.trim(), number: index + 1 })) .filter(({ line }) => pattern.test(line)) .filter(({ line }) => // Flag calls on this.client (NavidromeClient) but not on this (SharedTestClient) line.includes('this.client.isInitialized()') && !line.includes('this.isInitialized()') ); expect(problematicLines).toEqual([]); } } } catch (error) { // File might not exist, which is fine continue; } } }); it('should validate all manager services have consistent isInitialized() patterns', () => { // Test that all manager services consistently implement isInitialized() const managerServices = [ join(projectRoot, 'src/services/library-manager.ts'), join(projectRoot, 'src/services/filter-cache-manager.ts'), join(projectRoot, 'src/client/navidrome-client.ts') ]; const servicesWithIsInitialized: string[] = []; const servicesWithoutIsInitialized: string[] = []; for (const serviceFile of managerServices) { try { const content = readFileSync(serviceFile, 'utf-8'); if (content.includes('isInitialized(')) { servicesWithIsInitialized.push(serviceFile); } else { servicesWithoutIsInitialized.push(serviceFile); } } catch (error) { // Service file doesn't exist continue; } } // If any service calls isInitialized() on another service, both should implement it const clientFile = join(projectRoot, 'src/client/navidrome-client.ts'); if (existsSync(clientFile)) { const clientContent = readFileSync(clientFile, 'utf-8'); if (clientContent.includes('libraryManager.isInitialized()')) { expect(servicesWithIsInitialized).toContain(join(projectRoot, 'src/services/library-manager.ts')); } } }); }); describe('Unused Export Detection', () => { it('should detect unused exports using ts-unused-exports', () => { try { execSync('pnpm run check:dead-code', { cwd: projectRoot, stdio: 'pipe', env: { ...process.env, PATH: process.env.PATH } }); // If ts-unused-exports passes without error, we're good expect(true).toBe(true); } catch (error) { const output = (error as any).stdout?.toString() || (error as any).stderr?.toString() || ''; // Check if this contains the expected pattern from our analysis if (output.includes('modules with unused exports')) { const lines = output.split('\n'); const unusedExportLines = lines.filter(line => line.includes('.ts:') && (line.includes('FilterCacheManager') || line.includes('LibraryManager') || line.includes('Cache') || line.includes('MessageManager')) ); // These are the critical service exports we identified // If any of these show up, fail the test with details if (unusedExportLines.length > 0) { console.log('Unused service exports detected:'); unusedExportLines.forEach(line => console.log(` ${line}`)); // This is informational for now - we document known unused exports // Note: Cache and MessageManager were removed since they're used in tests (fixed tsconfig.analysis.json) const knownUnusedExports = [ // Test factories with genuinely unused exports 'createLiveClient', 'resetSharedClient', 'isSharedClientInitialized', 'mockAlbum', 'mockArtist', 'isCI', 'hasNavidromeConfig', 'logTestEnvironment', 'itLive', 'getSharedLiveClientSafe', 'describeLiveOnly', 'itLiveOnly', 'beforeAllLive', 'describeMockOnly', 'itMockOnly' ]; const actualUnusedExports = unusedExportLines .flatMap(line => { const exportPart = line.split(':')[1]?.trim(); return exportPart ? exportPart.split(',').map(exp => exp.trim()) : []; }) .filter(Boolean); // Only fail if we have NEW unused exports beyond the known ones const unexpectedUnusedExports = actualUnusedExports.filter( exportName => !knownUnusedExports.includes(exportName) ); if (unexpectedUnusedExports.length > 0) { expect(unexpectedUnusedExports).toEqual([]); } } } else { // Different kind of error - re-throw throw error; } } }); }); describe('Singleton Pattern Validation', () => { it('should ensure singleton patterns have proper initialization checks', () => { const singletonFiles = [ join(projectRoot, 'tests/factories/shared-client.ts'), join(projectRoot, 'src/services/library-manager.ts'), join(projectRoot, 'src/services/filter-cache-manager.ts') ]; for (const file of singletonFiles) { try { const content = readFileSync(file, 'utf-8'); // Singleton patterns should have proper null checks if (content.includes('getInstance()') || content.includes('private static instance')) { // Should have null checks before using instance const lines = content.split('\n'); const instanceUsages = lines .map((line, index) => ({ line: line.trim(), number: index + 1 })) .filter(({ line }) => line.includes('this.') && (line.includes('.isInitialized()') || line.includes('.method()')) ); // Each instance usage should be properly guarded for (const { line, number } of instanceUsages) { // Look for null/undefined checks in preceding lines const precedingLines = lines.slice(Math.max(0, number - 5), number - 1); const hasNullCheck = precedingLines.some(precedingLine => precedingLine.includes('if (') && (precedingLine.includes('null') || precedingLine.includes('undefined')) ); if (!hasNullCheck && line.includes('this.client.')) { expect.soft(false).toBe(true); console.log(`Potentially unguarded instance usage at ${file}:${number}: ${line}`); } } } } catch (error) { // File doesn't exist, skip continue; } } }); }); describe('Test Coverage for Dead Code Paths', () => { it('should ensure critical singleton code paths are tested', async () => { // This test ensures that singleton patterns like SharedTestClient // have tests that actually exercise retry/error paths const sharedClientFile = join(projectRoot, 'tests/factories/shared-client.ts'); if (!existsSync(sharedClientFile)) { console.log('Info: SharedTestClient file not found, skipping test coverage analysis'); return; } const sharedClientContent = readFileSync(sharedClientFile, 'utf-8'); // If there are retry/error handling patterns if (sharedClientContent.includes('initializationError') || sharedClientContent.includes('RETRY_DELAY')) { // Check if there are tests for these patterns const testDir = join(projectRoot, 'tests/unit'); if (!existsSync(testDir)) { console.log('Info: Test directory not found, skipping retry test analysis'); return; } const testFiles = readdirSync(testDir) .filter(file => file.endsWith('.test.ts')) .map(file => join(testDir, file)); let hasRetryTests = false; for (const testFile of testFiles) { try { const testContent = readFileSync(testFile, 'utf-8'); if (testContent.includes('retry') || testContent.includes('error') || testContent.includes('SharedTestClient')) { hasRetryTests = true; break; } } catch { continue; } } // This is informational - complex singleton patterns should have dedicated tests if (!hasRetryTests) { console.log('Info: SharedTestClient has complex retry logic but no dedicated retry tests'); } } }); }); describe('Import/Export Consistency', () => { it('should have consistent import patterns for service classes', () => { // Test the pattern we discovered: services are used as singleton instances // but the classes are exported but never imported const servicePatterns = [ { serviceFile: join(projectRoot, 'src/services/library-manager.ts'), expectedUsage: 'libraryManager', exportedClass: 'LibraryManager' }, { serviceFile: join(projectRoot, 'src/services/filter-cache-manager.ts'), expectedUsage: 'filterCacheManager', exportedClass: 'FilterCacheManager' } ]; for (const { serviceFile, expectedUsage, exportedClass } of servicePatterns) { try { const content = readFileSync(serviceFile, 'utf-8'); // Should export the class const exportsClass = content.includes(`export { ${exportedClass} }`); // Should also export a singleton instance const exportsInstance = content.includes(`export { ${expectedUsage} }`); if (exportsClass && !exportsInstance) { // This might indicate the class export is unused (people use the instance) console.log(`Info: ${serviceFile} exports ${exportedClass} class but usage pattern suggests instance is preferred`); } } catch (error) { continue; } } }); }); });

Latest Blog Posts

MCP directory API

We provide all the information about MCP servers via our MCP API.

curl -X GET 'https://glama.ai/api/mcp/v1/servers/Blakeem/Navidrome-MCP'

If you have feedback or need assistance with the MCP directory API, please join our Discord server