const { test, expect } = require('playwright/test'); const { loadPage, trackErrors } = require('./helpers'); test('stepper: lake never shows raw SX source during hydration', async ({ page }) => { // Monitor the lake content during page load to catch flashes const lakeStates = []; await page.context().clearCookies(); // Set up mutation observer before navigation await page.addInitScript(() => { window.__lakeStates = []; const observer = new MutationObserver(() => { const lake = document.querySelector('[data-sx-lake="home-preview"]'); if (lake) { const text = lake.textContent; if (text && text.length > 0) { window.__lakeStates.push(text.slice(0, 100)); } } }); // Start observing once DOM is ready if (document.body) { observer.observe(document.body, { childList: true, subtree: true, characterData: true }); } else { document.addEventListener('DOMContentLoaded', () => { observer.observe(document.body, { childList: true, subtree: true, characterData: true }); }); } }); await page.goto('http://localhost:8013/', { waitUntil: 'networkidle' }); await page.waitForTimeout(3000); const states = await page.evaluate(() => window.__lakeStates); // No state should contain raw SX component calls for (const state of states) { expect(state).not.toContain('~tw'); expect(state).not.toContain('~cssx'); expect(state).not.toContain(':tokens'); } }); test('stepper: default view shows all four words after hydration', async ({ page }) => { await page.context().clearCookies(); await loadPage(page, ''); const lake = page.locator('[data-sx-lake="home-preview"]'); await expect(lake).toBeVisible({ timeout: 10000 }); await page.waitForTimeout(3000); const text = await lake.textContent(); expect(text).toContain('the'); expect(text).toContain('joy'); expect(text).toContain('of'); expect(text).toContain('sx'); }); test('stepper: stepped spans have colored text', async ({ page }) => { await page.context().addCookies([{ name: 'sx-home-stepper', value: '0', url: 'http://localhost:8013' }]); await loadPage(page, ''); await page.waitForTimeout(3000); const fwdBtn = page.locator('button:has-text("▶")'); await expect(fwdBtn).toBeVisible({ timeout: 5000 }); // Step forward 16 times to complete the expression for (let i = 0; i < 16; i++) { await fwdBtn.click(); await page.waitForTimeout(200); } const lake = page.locator('[data-sx-lake="home-preview"]'); // Check each span has a non-black computed color const colors = await lake.evaluate(el => { const spans = el.querySelectorAll('span'); return Array.from(spans).map(s => ({ text: s.textContent, color: getComputedStyle(s).color, hasClass: s.className.length > 0 })); }); expect(colors.length).toBeGreaterThanOrEqual(4); for (const span of colors) { // Each span should have a class applied expect(span.hasClass).toBe(true); // Color should not be default black (rgb(0, 0, 0)) expect(span.color).not.toBe('rgb(0, 0, 0)'); } });