UNPKG

ai-debug-local-mcp

Version:

🎯 ENHANCED AI GUIDANCE v4.1.2: Dramatically improved tool descriptions help AI users choose the right tools instead of 'close enough' options. Ultra-fast keyboard automation (10x speed), universal recording, multi-ecosystem debugging support, and compreh

339 lines • 12.5 kB
/** * Flutter Test Mode Detector * Detects Flutter test environment and provides test-specific debugging capabilities * Based on Cycle 22 user feedback for TDD enhancements */ export class FlutterTestModeDetector { static instance; static getInstance() { if (!FlutterTestModeDetector.instance) { FlutterTestModeDetector.instance = new FlutterTestModeDetector(); } return FlutterTestModeDetector.instance; } /** * Detect if we're in a Flutter test environment */ async detectTestEnvironment(sessionId, page) { const environment = { isTestMode: false, testFramework: 'unknown', hasTestRunner: false, testType: 'unknown', authenticationMocks: { detected: false, providers: [], gaps: [] }, expectedWidgets: { keys: [], patterns: [], missing: [] } }; try { // Check for test environment indicators environment.isTestMode = await this.isFlutterTestMode(page); if (environment.isTestMode) { environment.testFramework = await this.detectTestFramework(page); environment.testType = await this.detectTestType(page); environment.mockingFramework = await this.detectMockingFramework(page); environment.hasTestRunner = await this.hasActiveTestRunner(page); // Analyze authentication mocks environment.authenticationMocks = await this.analyzeAuthenticationMocks(page); // Detect expected widgets from test code environment.expectedWidgets = await this.detectExpectedWidgets(page); } } catch (error) { console.warn('Error detecting Flutter test environment:', error); } return environment; } /** * Check if current environment is Flutter test mode */ async isFlutterTestMode(page) { if (!page) return false; try { // Check for Flutter test indicators in the page const indicators = await page.evaluate(() => { return { hasFlutterTestBinding: typeof window.flutter !== 'undefined' && typeof window.flutter.testMode !== 'undefined', hasTestWidgets: document.querySelector('[data-test-key]') !== null, hasDebugPaint: document.querySelector('.debug-paint') !== null, isFlutterWeb: typeof window.flutter !== 'undefined', hasWidgetTester: typeof window.widgetTester !== 'undefined', userAgent: navigator.userAgent, location: window.location.href }; }); // Multiple indicators for test mode return indicators.hasFlutterTestBinding || indicators.hasTestWidgets || indicators.hasWidgetTester || indicators.location.includes('test') || indicators.userAgent.includes('Flutter-Test'); } catch (error) { // Fallback: check URL and other environment indicators return this.detectTestModeFromEnvironment(); } } /** * Detect test mode from environment without page access */ detectTestModeFromEnvironment() { // Check process environment variables const envIndicators = [ process.env.FLUTTER_TEST === 'true', process.env.NODE_ENV === 'test', process.argv.some(arg => arg.includes('test')), typeof global !== 'undefined' && global.isFlutterTest ]; return envIndicators.some(indicator => indicator); } /** * Detect the specific test framework being used */ async detectTestFramework(page) { if (!page) return 'unknown'; try { const framework = await page.evaluate(() => { // Check for Flutter test framework indicators if (typeof window.flutter?.integrationTest !== 'undefined') { return 'integration_test'; } if (typeof window.flutter?.widgetTest !== 'undefined') { return 'widget_test'; } if (typeof window.flutter?.testBinding !== 'undefined') { return 'flutter_test'; } if (typeof window.flutter?.unitTest !== 'undefined') { return 'unit_test'; } return 'unknown'; }); return framework; } catch (error) { return 'unknown'; } } /** * Detect the type of test being run */ async detectTestType(page) { if (!page) return 'unknown'; try { const testType = await page.evaluate(() => { // Check for test type indicators const hasWidgets = document.querySelectorAll('[data-test-key]').length > 0; const hasIntegrationMarkers = document.querySelector('[data-integration-test]') !== null; const hasGoldenMarkers = document.querySelector('[data-golden-test]') !== null; if (hasGoldenMarkers) return 'golden'; if (hasIntegrationMarkers) return 'integration'; if (hasWidgets) return 'widget'; // Check for unit test indicators (no DOM widgets) return document.body.children.length === 0 ? 'unit' : 'unknown'; }); return testType; } catch (error) { return 'unknown'; } } /** * Detect mocking framework in use */ async detectMockingFramework(page) { if (!page) return 'none'; try { const mockingFramework = await page.evaluate(() => { // Check for mocking framework indicators if (typeof window.mockito !== 'undefined') return 'mockito'; if (typeof window.mocktail !== 'undefined') return 'mocktail'; if (typeof window.flutter?.mocks !== 'undefined') return 'built_in'; return 'none'; }); return mockingFramework; } catch (error) { return 'none'; } } /** * Check if there's an active test runner */ async hasActiveTestRunner(page) { if (!page) return false; try { return await page.evaluate(() => { return typeof window.flutter?.testRunner !== 'undefined' && window.flutter.testRunner.isActive === true; }); } catch (error) { return false; } } /** * Analyze authentication mocks in the test environment */ async analyzeAuthenticationMocks(page) { const result = { detected: false, providers: [], gaps: [] }; if (!page) return result; try { const authAnalysis = await page.evaluate(() => { const mocks = { providers: [], detected: false }; // Check for common authentication provider mocks const authProviders = [ 'unifiedAuthNotifierProvider', 'currentUserProvider', 'unifiedFamilyMembersProvider', 'primaryHouseholdNameProvider', 'dashboardLayoutConfigProvider', 'authStateProvider', 'userSessionProvider' ]; authProviders.forEach(provider => { // Check if provider is mocked in Flutter test environment if (typeof window.flutter?.mocks?.[provider] !== 'undefined') { mocks.providers.push(provider); mocks.detected = true; } }); return mocks; }); result.detected = authAnalysis.detected; result.providers = authAnalysis.providers; // Identify common gaps based on Cycle 22 feedback const commonProviders = [ 'unifiedAuthNotifierProvider', 'currentUserProvider', 'unifiedFamilyMembersProvider', 'primaryHouseholdNameProvider' ]; result.gaps = commonProviders.filter(provider => !result.providers.includes(provider)); } catch (error) { console.warn('Error analyzing authentication mocks:', error); } return result; } /** * Detect expected widgets from test code */ async detectExpectedWidgets(page) { const result = { keys: [], patterns: [], missing: [] }; if (!page) return result; try { const widgetAnalysis = await page.evaluate(() => { const analysis = { keys: [], patterns: [], rendered: [] }; // Common widget keys from Cycle 22 success pattern const expectedKeys = [ 'family_overview_section', 'family_member_status_card_', 'add_family_event_quick_action', 'add_family_chore_quick_action', 'family_wellbeing_indicator', 'family_calendar_sync_status' ]; expectedKeys.forEach((key) => { if (key.endsWith('_')) { analysis.patterns.push(key); // Check for pattern matches const elements = document.querySelectorAll(`[data-test-key^="${key}"]`); if (elements.length > 0) { Array.from(elements).forEach(el => { analysis.rendered.push(el.getAttribute('data-test-key') || ''); }); } } else { analysis.keys.push(key); // Check if exact key exists const element = document.querySelector(`[data-test-key="${key}"]`); if (element) { analysis.rendered.push(key); } } }); return analysis; }); result.keys = widgetAnalysis.keys; result.patterns = widgetAnalysis.patterns; // Identify missing widgets result.missing = [ ...widgetAnalysis.keys.filter((key) => !widgetAnalysis.rendered.includes(key)), ...widgetAnalysis.patterns.filter((pattern) => !widgetAnalysis.rendered.some((rendered) => rendered.startsWith(pattern))) ]; } catch (error) { console.warn('Error detecting expected widgets:', error); } return result; } /** * Configure test mode settings */ configureTestMode(config) { // Store configuration for use by other TDD tools const testConfig = { ...config, timestamp: Date.now() }; // Store in global state for access by other utilities if (typeof global !== 'undefined') { global.flutterTestConfig = testConfig; } } /** * Get current test mode configuration */ getTestModeConfiguration() { if (typeof global !== 'undefined' && global.flutterTestConfig) { return global.flutterTestConfig; } return null; } /** * Reset test mode detection */ reset() { if (typeof global !== 'undefined') { delete global.flutterTestConfig; } } } //# sourceMappingURL=flutter-test-mode-detector.js.map