import { test, expect } from '@playwright/test' test('HomePage - Full DOM & Visual Analysis', async ({ page }) => { // Navigate to home await page.goto('/', { waitUntil: 'networkidle' }) // Take screenshot await page.screenshot({ path: 'D:\\Temp\\homepage-full.png', fullPage: true }) console.log('✅ Screenshot saved: D:\\Temp\\homepage-full.png') // DOM Analysis const domData = await page.evaluate(() => { const totalElements = document.querySelectorAll('*').length const visibleElements = Array.from(document.querySelectorAll('*')).filter(el => { const style = window.getComputedStyle(el) return style.display !== 'none' && style.visibility !== 'hidden' && style.opacity !== '0' }).length const headings = document.querySelectorAll('h1, h2, h3, h4, h5, h6') const buttons = document.querySelectorAll('button') const links = document.querySelectorAll('a') const images = document.querySelectorAll('img') const cards = document.querySelectorAll('[class*="card"], [class*="Card"]') // Text content const textContent = document.body.innerText const wordCount = textContent.split(/\s+/).filter(w => w.length > 0).length // Extract heading texts const headingTexts = Array.from(headings).map(h => ({ tag: h.tagName, text: h.textContent?.trim().substring(0, 50), })) // Extract button texts const buttonTexts = Array.from(buttons).map(b => ({ text: b.textContent?.trim(), type: b.getAttribute('type') || 'button', })) // Extract link texts const linkTexts = Array.from(links).map(l => ({ text: l.textContent?.trim().substring(0, 30), href: l.getAttribute('href'), })) return { totalElements, visibleElements, headingCount: headings.length, headingTexts, buttonCount: buttons.length, buttonTexts, linkCount: links.length, linkTexts: linkTexts.slice(0, 10), imageCount: images.length, cardCount: cards.length, wordCount, } }) console.log('\n=== HomePage DOM Analysis ===') console.log(`Total Elements: ${domData.totalElements}`) console.log(`Visible Elements: ${domData.visibleElements}`) console.log(`Headings: ${domData.headingCount}`) console.log( 'Heading Texts:', domData.headingTexts.map(h => `${h.tag}: "${h.text}"`).join(' | ') ) console.log(`\nButtons: ${domData.buttonCount}`) domData.buttonTexts.forEach((b, i) => { console.log(` ${i + 1}. "${b.text}" (type: ${b.type})`) }) console.log(`\nLinks: ${domData.linkCount}`) domData.linkTexts.forEach((l, i) => { console.log(` ${i + 1}. "${l.text}" → ${l.href}`) }) console.log(`\nImages: ${domData.imageCount}`) console.log(`Cards/Components: ${domData.cardCount}`) console.log(`Word Count: ${domData.wordCount}`) // Accessibility Check const a11yData = await page.evaluate(() => { const elementsWithAria = document.querySelectorAll('[aria-label], [aria-describedby], [role]') const imagesWithAlt = document.querySelectorAll('img[alt]') const buttonsWithAriaOrText = Array.from(document.querySelectorAll('button')).filter( b => b.getAttribute('aria-label') || b.textContent?.trim().length > 0 ) const linksWithAriaOrText = Array.from(document.querySelectorAll('a')).filter( l => l.getAttribute('aria-label') || l.textContent?.trim().length > 0 ) const hasLandmarks = !!document.querySelector('main, nav[aria-label], aside[aria-label]') const skipLink = document.querySelector('a.ks-skip') return { ariaElements: elementsWithAria.length, imagesWithAlt: imagesWithAlt.length, totalImages: document.querySelectorAll('img').length, accessibleButtons: buttonsWithAriaOrText.length, totalButtons: document.querySelectorAll('button').length, accessibleLinks: linksWithAriaOrText.length, totalLinks: document.querySelectorAll('a').length, hasLandmarks, hasSkipLink: !!skipLink, } }) console.log('\n=== Accessibility Assessment ===') console.log(`ARIA/Role Elements: ${a11yData.ariaElements}`) console.log(`Images with Alt Text: ${a11yData.imagesWithAlt}/${a11yData.totalImages}`) console.log(`Accessible Buttons: ${a11yData.accessibleButtons}/${a11yData.totalButtons}`) console.log(`Accessible Links: ${a11yData.accessibleLinks}/${a11yData.totalLinks}`) console.log(`Has Landmarks: ${a11yData.hasLandmarks}`) console.log(`Has Skip Link: ${a11yData.hasSkipLink}`) // Color & Typography Check const styleData = await page.evaluate(() => { const h1 = document.querySelector('h1') const buttons = document.querySelectorAll('button') const cards = document.querySelectorAll('[class*="card"], [class*="Card"]') const h1Style = h1 ? { fontSize: window.getComputedStyle(h1).fontSize, fontWeight: window.getComputedStyle(h1).fontWeight, color: window.getComputedStyle(h1).color, } : null const buttonStyles = Array.from(buttons) .slice(0, 3) .map(b => ({ text: b.textContent?.trim().substring(0, 20), backgroundColor: window.getComputedStyle(b).backgroundColor, color: window.getComputedStyle(b).color, padding: window.getComputedStyle(b).padding, minHeight: window.getComputedStyle(b).minHeight, })) return { h1Style, buttonStyles, cardCount: cards.length, } }) console.log('\n=== Typography & Styling ===') console.log('H1:', styleData.h1Style) console.log('Button Samples:') styleData.buttonStyles.forEach((b, i) => { console.log(` ${i + 1}. "${b.text}" | bg: ${b.backgroundColor} | color: ${b.color} | padding: ${b.padding}`) }) // Completeness Score Calculation const completenessScore = (() => { let score = 0 // DOM structure (max 25) score += Math.min((domData.visibleElements / 150) * 25, 25) // Content (max 20) score += Math.min((domData.wordCount / 300) * 20, 20) // Interactivity (max 20) score += Math.min(((domData.buttonCount + domData.linkCount) / 15) * 20, 20) // Accessibility (max 20) const a11yScore = (a11yData.imagesWithAlt / Math.max(a11yData.totalImages, 1)) * 5 + (a11yData.accessibleButtons / Math.max(a11yData.totalButtons, 1)) * 5 + (a11yData.accessibleLinks / Math.max(a11yData.totalLinks, 1)) * 5 + (a11yData.hasLandmarks ? 3 : 0) + (a11yData.hasSkipLink ? 2 : 0) score += Math.min(a11yScore, 20) // Visual hierarchy (max 15) score += styleData.h1Style ? 8 : 0 score += styleData.cardCount > 0 ? 7 : 0 return Math.min(score, 100) })() console.log(`\n=== Completeness Score ===`) console.log(`Overall: ${completenessScore.toFixed(1)}%`) console.log( `Status: ${completenessScore >= 90 ? '✅ COMMERCIAL-GRADE' : completenessScore >= 80 ? '⚠️ GOOD' : '❌ NEEDS WORK'}` ) // Expectations expect(domData.visibleElements).toBeGreaterThan(80) expect(domData.headingCount).toBeGreaterThan(0) expect(domData.buttonCount).toBeGreaterThan(0) expect(a11yData.hasLandmarks).toBe(true) })