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
JavaScript
/**
* 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