playwright-ai-auto-debug
Version:
Automatic Playwright test debugging with AI assistance + UI Test Coverage Analysis
278 lines (232 loc) • 11.4 kB
JavaScript
import { test } from '../lib/simpleFixture.js';
import { expect } from '@playwright/test';
import { UICoverageAnalyzer } from '../lib/uiCoverageAnalyzer.js';
import fs from 'fs';
test.describe('🎯 UI Coverage Analysis with MCP', () => {
let analyzer;
test.beforeEach(async () => {
// Инициализация анализатора с критичными элементами
analyzer = new UICoverageAnalyzer({
criticalElements: [
{ type: 'button', name: 'Get started', selector: 'text=Get started' },
{ type: 'button', name: 'Search', selector: 'button:has-text("Search")' },
{ type: 'link', name: 'Docs', selector: 'text=Docs' },
{ type: 'navigation', name: 'Main', selector: 'navigation' },
{ type: 'button', name: 'Node.js', selector: 'button:has-text("Node.js")' }
]
});
});
test('🌳 1. Анализ дерева доступности главной страницы', async ({ page }) => {
await test.step('Переход на главную страницу', async () => {
await page.goto('/');
await page.waitForLoadState('networkidle');
});
await test.step('Получение DOM snapshot через MCP', async () => {
// Имитируем получение snapshot от MCP
// В реальной реализации это будет вызов MCP API
const mockSnapshot = await getMockSnapshot(page);
// Парсинг accessibility tree
const accessibilityTree = analyzer.parseAccessibilityTree(mockSnapshot);
console.log('🌳 Accessibility Tree Analysis:');
console.log(`Total elements: ${accessibilityTree.totalCount}`);
console.log('Elements by type:', accessibilityTree.byType);
// Проверки
expect(accessibilityTree.totalCount).toBeGreaterThan(0);
expect(accessibilityTree.byType.button).toBeDefined();
expect(accessibilityTree.byType.link).toBeDefined();
});
});
test('✅ 2. Подсчет элементов и проверка свойств', async ({ page }) => {
await test.step('Навигация и анализ элементов', async () => {
await page.goto('/');
await page.waitForLoadState('networkidle');
const mockSnapshot = await getMockSnapshot(page);
const accessibilityTree = analyzer.parseAccessibilityTree(mockSnapshot);
// Анализ покрытия элементов
const elementStats = analyzer.analyzeElementCoverage(accessibilityTree);
console.log('📊 Element Coverage Analysis:');
console.log('Summary:', elementStats.summary);
// Создание отчета
const report = {
accessibilityTree,
elementStats
};
const coverageReport = analyzer.generateCoverageReport(report, 'playwright-homepage');
// Сохранение отчета
await analyzer.saveReport(coverageReport, `ui-coverage-${Date.now()}.md`);
// Проверки
expect(elementStats.summary.totalElements).toBeGreaterThan(10);
expect(elementStats.summary.buttons).toBeGreaterThan(0);
expect(elementStats.summary.links).toBeGreaterThan(0);
expect(elementStats.summary.interactive).toBeGreaterThan(0);
});
});
test('🔄 3. Проверка критичных элементов', async ({ page }) => {
await test.step('Анализ критичных элементов страницы', async () => {
await page.goto('/');
await page.waitForLoadState('networkidle');
const mockSnapshot = await getMockSnapshot(page);
const accessibilityTree = analyzer.parseAccessibilityTree(mockSnapshot);
// Проверка критичных элементов
const criticalCheck = analyzer.checkCriticalElements(
accessibilityTree,
analyzer.config.criticalElements
);
console.log('🔍 Critical Elements Check:');
console.log(`Found critical: ${criticalCheck.foundCritical.length}`);
console.log(`Missing critical: ${criticalCheck.missingCritical.length}`);
console.log('Recommendations:', criticalCheck.recommendations);
// Создание полного отчета
const fullReport = {
accessibilityTree,
elementStats: analyzer.analyzeElementCoverage(accessibilityTree),
criticalCheck
};
const coverageReport = analyzer.generateCoverageReport(fullReport, 'critical-elements-check');
await analyzer.saveReport(coverageReport, `critical-check-${Date.now()}.md`);
// Проверки
expect(criticalCheck.foundCritical.length).toBeGreaterThan(0);
// Логирование для демонстрации
if (criticalCheck.missingCritical.length > 0) {
console.log('⚠️ Missing critical elements detected!');
criticalCheck.missingCritical.forEach(missing => {
console.log(`❌ ${missing.name} (${missing.type})`);
});
}
});
});
test('📊 4. Сравнение с золотой версией', async ({ page }) => {
await test.step('Создание и сравнение с эталонным snapshot', async () => {
await page.goto('/');
await page.waitForLoadState('networkidle');
const currentSnapshot = await getMockSnapshot(page);
const currentTree = analyzer.parseAccessibilityTree(currentSnapshot);
// Создание "золотой" версии (для демонстрации)
const goldenSnapshot = await createGoldenSnapshot();
const goldenTree = analyzer.parseAccessibilityTree(goldenSnapshot);
// Сравнение с эталоном
const goldenComparison = analyzer.compareWithGolden(currentTree, goldenTree);
console.log('🔗 Golden Comparison:');
console.log(`Identical: ${goldenComparison.identical}`);
console.log(`New elements: ${goldenComparison.newElements.length}`);
console.log(`Removed elements: ${goldenComparison.removedElements.length}`);
console.log('Differences:', goldenComparison.differences);
// Создание итогового отчета
const fullAnalysis = {
accessibilityTree: currentTree,
elementStats: analyzer.analyzeElementCoverage(currentTree),
criticalCheck: analyzer.checkCriticalElements(currentTree, analyzer.config.criticalElements),
goldenComparison
};
const finalReport = analyzer.generateCoverageReport(fullAnalysis, 'golden-comparison');
await analyzer.saveReport(finalReport, `golden-comparison-${Date.now()}.md`);
// Проверки
expect(goldenComparison).toBeDefined();
expect(Array.isArray(goldenComparison.differences)).toBe(true);
});
});
test('⚙️ 5. Интеграция в CI/CD pipeline', async ({ page }) => {
await test.step('Полный цикл анализа для CI/CD', async () => {
await page.goto('/');
await page.waitForLoadState('networkidle');
// Полный анализ страницы
const snapshot = await getMockSnapshot(page);
const accessibilityTree = analyzer.parseAccessibilityTree(snapshot);
const elementStats = analyzer.analyzeElementCoverage(accessibilityTree);
const criticalCheck = analyzer.checkCriticalElements(accessibilityTree, analyzer.config.criticalElements);
// Создание CI/CD отчета
const ciReport = {
accessibilityTree,
elementStats,
criticalCheck,
// goldenComparison можно добавить при наличии эталона
};
const coverageReport = analyzer.generateCoverageReport(ciReport, 'ci-cd-pipeline');
const reportPath = await analyzer.saveReport(coverageReport, `ci-report-${Date.now()}.md`);
// Проверки для CI/CD
console.log('🚀 CI/CD Integration Results:');
console.log(`Report saved to: ${reportPath}`);
console.log(`Coverage: ${coverageReport.summary.coveragePercentage}%`);
console.log(`Accessibility Score: ${coverageReport.summary.accessibilityScore}%`);
// Условия прохождения для CI/CD
expect(coverageReport.summary.totalElements).toBeGreaterThan(5);
expect(coverageReport.summary.interactiveElements).toBeGreaterThan(2);
// Проверка критичных элементов
if (!criticalCheck.allCriticalPresent) {
console.warn('⚠️ Some critical elements are missing!');
// В реальном CI/CD можно настроить fail теста
}
// Логирование рекомендаций
console.log('📋 Recommendations:');
coverageReport.recommendations.forEach(rec => console.log(` ${rec}`));
});
});
});
// Вспомогательные функции
/**
* Получение mock snapshot (имитация MCP)
*/
async function getMockSnapshot(page) {
// В реальной реализации здесь будет вызов MCP API
// Пока используем имитацию на основе реального DOM
const snapshot = `# Page snapshot
- region "Skip to main content":
- link "Skip to main content":
- /url: "#__docusaurus_skipToContent_fallback"
- navigation "Main":
- link "Playwright logo Playwright":
- /url: /
- img "Playwright logo"
- text: Playwright
- link "Docs":
- /url: /docs/intro
- link "API":
- /url: /docs/api/class-playwright
- button "Node.js"
- link "Community":
- /url: /community/welcome
- link "GitHub repository":
- /url: https://github.com/microsoft/playwright
- button "Switch between dark and light mode"
- button "Search (Command+K)": Search ⌘ K
- banner:
- heading "Playwright enables reliable end-to-end testing" [level=1]
- link "Get started":
- /url: /docs/intro
- link "Star microsoft/playwright on GitHub":
- /url: https://github.com/microsoft/playwright
- main:
- img "Browsers (Chromium, Firefox, WebKit)"
- heading "Any browser • Any platform • One API" [level=3]
- paragraph: Cross-browser. Playwright supports all modern rendering engines
- link "TypeScript":
- /url: https://playwright.dev/docs/intro
- link "JavaScript":
- /url: https://playwright.dev/docs/intro`;
return snapshot;
}
/**
* Создание эталонного snapshot для сравнения
*/
async function createGoldenSnapshot() {
// Имитация "золотой" версии с небольшими отличиями
return `# Page snapshot
- region "Skip to main content":
- link "Skip to main content":
- /url: "#__docusaurus_skipToContent_fallback"
- navigation "Main":
- link "Playwright logo Playwright":
- /url: /
- link "Docs":
- /url: /docs/intro
- button "Node.js"
- link "Community":
- /url: /community/welcome
- button "Search (Command+K)": Search ⌘ K
- banner:
- heading "Playwright enables reliable end-to-end testing" [level=1]
- link "Get started":
- /url: /docs/intro
- main:
- heading "Any browser • Any platform • One API" [level=3]`;
}