#!/usr/bin/env bun /** * INTRO TEXT JUSTIFICATION TEST * ============================== * Tests the intro-text paragraph styling including: * - Full text justification (text-align: justify) * - Last line justification (text-align-last: justify) * - Hyphenation support (hyphens: auto) * - Cross-browser compatibility */ import { chromium } from 'playwright'; const URL = "http://localhost:1999"; async function testIntroTextJustification() { console.log('📝 INTRO TEXT JUSTIFICATION TEST\n'); console.log('='.repeat(70)); const browser = await chromium.launch({ headless: true }); const errors = []; const testResults = []; // ======================================================================== // TEST 1: Verify intro-text element exists // ======================================================================== console.log("\n1️⃣ Checking intro-text element exists..."); const page = await browser.newPage({ viewport: { width: 1076, height: 756 } }); page.on('console', msg => { if (msg.type() === 'error') { errors.push(msg.text()); console.log(`❌ ERROR: ${msg.text()}`); } }); await page.goto(URL); await page.waitForTimeout(1500); const elementExists = await page.evaluate(() => { const introText = document.querySelector('.intro-text'); return { exists: introText !== null, textLength: introText ? introText.textContent.length : 0 }; }); if (elementExists.exists) { console.log(` ✅ .intro-text element found (${elementExists.textLength} chars)`); testResults.push({ test: "intro-text exists", passed: true }); } else { console.log(" ❌ .intro-text element NOT found"); testResults.push({ test: "intro-text exists", passed: false }); } // ======================================================================== // TEST 2: Verify text-align: justify // ======================================================================== console.log("\n2️⃣ Checking text-align: justify..."); const textAlignTest = await page.evaluate(() => { const introText = document.querySelector('.intro-text'); if (!introText) return { passed: false, value: 'element not found' }; const computed = window.getComputedStyle(introText); const textAlign = computed.textAlign; return { passed: textAlign === 'justify', value: textAlign }; }); if (textAlignTest.passed) { console.log(` ✅ text-align: ${textAlignTest.value}`); testResults.push({ test: "text-align justify", passed: true }); } else { console.log(` ❌ text-align: ${textAlignTest.value} (expected: justify)`); testResults.push({ test: "text-align justify", passed: false }); } // ======================================================================== // TEST 3: Verify text-align-last: justify // ======================================================================== console.log("\n3️⃣ Checking text-align-last: justify..."); const textAlignLastTest = await page.evaluate(() => { const introText = document.querySelector('.intro-text'); if (!introText) return { passed: false, value: 'element not found' }; const computed = window.getComputedStyle(introText); const textAlignLast = computed.textAlignLast; return { passed: textAlignLast === 'justify', value: textAlignLast }; }); if (textAlignLastTest.passed) { console.log(` ✅ text-align-last: ${textAlignLastTest.value}`); testResults.push({ test: "text-align-last justify", passed: true }); } else { console.log(` ❌ text-align-last: ${textAlignLastTest.value} (expected: justify)`); testResults.push({ test: "text-align-last justify", passed: false }); } // ======================================================================== // TEST 4: Verify hyphens: auto // ======================================================================== console.log("\n4️⃣ Checking hyphens: auto..."); const hyphensTest = await page.evaluate(() => { const introText = document.querySelector('.intro-text'); if (!introText) return { passed: false, value: 'element not found' }; const computed = window.getComputedStyle(introText); // Note: Chromium returns 'auto' or 'manual' or 'none' const hyphens = computed.hyphens || computed.webkitHyphens; return { passed: hyphens === 'auto', value: hyphens }; }); if (hyphensTest.passed) { console.log(` ✅ hyphens: ${hyphensTest.value}`); testResults.push({ test: "hyphens auto", passed: true }); } else { console.log(` ❌ hyphens: ${hyphensTest.value} (expected: auto)`); testResults.push({ test: "hyphens auto", passed: false }); } // ======================================================================== // TEST 5: Verify word-spacing is set // ======================================================================== console.log("\n5️⃣ Checking word-spacing..."); const wordSpacingTest = await page.evaluate(() => { const introText = document.querySelector('.intro-text'); if (!introText) return { passed: false, value: 'element not found' }; const computed = window.getComputedStyle(introText); const wordSpacing = computed.wordSpacing; // We set word-spacing: -1px, but computed returns in px const value = parseFloat(wordSpacing); return { passed: value < 0, // Should be negative value: wordSpacing }; }); if (wordSpacingTest.passed) { console.log(` ✅ word-spacing: ${wordSpacingTest.value}`); testResults.push({ test: "word-spacing negative", passed: true }); } else { console.log(` ❌ word-spacing: ${wordSpacingTest.value} (expected: negative value)`); testResults.push({ test: "word-spacing negative", passed: false }); } // ======================================================================== // TEST 6: Verify overflow-wrap: break-word // ======================================================================== console.log("\n6️⃣ Checking overflow-wrap: break-word..."); const overflowWrapTest = await page.evaluate(() => { const introText = document.querySelector('.intro-text'); if (!introText) return { passed: false, value: 'element not found' }; const computed = window.getComputedStyle(introText); const overflowWrap = computed.overflowWrap || computed.wordWrap; return { passed: overflowWrap === 'break-word', value: overflowWrap }; }); if (overflowWrapTest.passed) { console.log(` ✅ overflow-wrap: ${overflowWrapTest.value}`); testResults.push({ test: "overflow-wrap break-word", passed: true }); } else { console.log(` ❌ overflow-wrap: ${overflowWrapTest.value} (expected: break-word)`); testResults.push({ test: "overflow-wrap break-word", passed: false }); } // ======================================================================== // TEST 7: Verify font-style: italic // ======================================================================== console.log("\n7️⃣ Checking font-style: italic..."); const fontStyleTest = await page.evaluate(() => { const introText = document.querySelector('.intro-text'); if (!introText) return { passed: false, value: 'element not found' }; const computed = window.getComputedStyle(introText); const fontStyle = computed.fontStyle; return { passed: fontStyle === 'italic', value: fontStyle }; }); if (fontStyleTest.passed) { console.log(` ✅ font-style: ${fontStyleTest.value}`); testResults.push({ test: "font-style italic", passed: true }); } else { console.log(` ❌ font-style: ${fontStyleTest.value} (expected: italic)`); testResults.push({ test: "font-style italic", passed: false }); } // ======================================================================== // TEST 8: Test on Spanish language (different hyphenation) // ======================================================================== console.log("\n8️⃣ Testing Spanish version..."); await page.goto(`${URL}/?lang=es`); await page.waitForTimeout(1500); const spanishTest = await page.evaluate(() => { const introText = document.querySelector('.intro-text'); const htmlLang = document.documentElement.lang; if (!introText) return { passed: false, lang: htmlLang, hasText: false }; const computed = window.getComputedStyle(introText); return { passed: htmlLang === 'es' && computed.textAlign === 'justify', lang: htmlLang, hasText: introText.textContent.length > 0, textAlign: computed.textAlign }; }); if (spanishTest.passed) { console.log(` ✅ Spanish version: lang="${spanishTest.lang}", text-align: ${spanishTest.textAlign}`); testResults.push({ test: "spanish justification", passed: true }); } else { console.log(` ❌ Spanish version failed - lang: ${spanishTest.lang}, text-align: ${spanishTest.textAlign}`); testResults.push({ test: "spanish justification", passed: false }); } // ======================================================================== // SUMMARY // ======================================================================== console.log('\n' + '='.repeat(70)); console.log('📊 TEST SUMMARY\n'); const passed = testResults.filter(t => t.passed).length; const total = testResults.length; const consoleErrors = errors.filter(e => !e.includes('favicon')); console.log(`Tests: ${passed}/${total} passed`); console.log(`Console errors: ${consoleErrors.length}`); if (consoleErrors.length > 0) { console.log('\nConsole errors:'); consoleErrors.forEach(e => console.log(` - ${e}`)); } console.log('\nDetailed results:'); testResults.forEach(t => { console.log(` ${t.passed ? '✅' : '❌'} ${t.test}`); }); await browser.close(); const success = passed === total && consoleErrors.length === 0; console.log(`\n${success ? '✅ ALL TESTS PASSED' : '❌ SOME TESTS FAILED'}\n`); process.exit(success ? 0 : 1); } testIntroTextJustification().catch(err => { console.error('Test failed:', err); process.exit(1); });