Files
rose-ash/tests/playwright/stepper.spec.js
giles 9a64f13dc6 Fix stepper default: show full "the joy of sx" on load
Root cause: default step-idx was 9, but the expression has 16 steps.
At step 9, only "the joy" + empty emerald span renders. Changed default
to 16 so all four words display after hydration.

Reverted mutable-list changes — (list) already creates ListRef in the
OCaml kernel, so append! works correctly with plain (list).

Added spec/tests/test-stepper.sx (7 tests) proving the split-tag +
steps-to-preview pipeline works correctly at each step boundary.

Updated Playwright stepper.spec.js with four tests:
- no raw SX visible after hydration
- default view shows all four words
- all spans inside h1
- stepping forward renders styled text

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
2026-04-02 13:55:40 +00:00

82 lines
2.6 KiB
JavaScript

const { test, expect } = require('playwright/test');
const { loadPage, trackErrors } = require('./helpers');
test('stepper: no raw SX component calls visible after hydration', async ({ page }) => {
const t = trackErrors(page);
await loadPage(page, '');
const stepper = page.locator('[data-sx-island="home/stepper"]');
await expect(stepper).toBeVisible({ timeout: 10000 });
const lake = stepper.locator('[data-sx-lake]');
await expect(lake).toBeVisible({ timeout: 5000 });
const lakeText = await lake.textContent();
expect(lakeText).not.toContain('~cssx/tw');
expect(lakeText).not.toContain('~tw');
expect(lakeText).not.toContain(':tokens');
expect(t.errors()).toEqual([]);
});
test('stepper: default view shows all four words', async ({ page }) => {
// Clear stepper cookie
await page.context().clearCookies();
await loadPage(page, '');
const lake = page.locator('[data-sx-lake="home-preview"]');
await expect(lake).toBeVisible({ timeout: 10000 });
// Wait for hydration
await page.waitForTimeout(2000);
const text = await lake.textContent();
// All four words should be present after hydration
expect(text).toContain('the');
expect(text).toContain('joy');
expect(text).toContain('of');
expect(text).toContain('sx');
});
test('stepper: all spans inside h1 with correct structure', async ({ page }) => {
await page.context().clearCookies();
await loadPage(page, '');
await page.waitForTimeout(3000);
const lake = page.locator('[data-sx-lake="home-preview"]');
const h1 = lake.locator('h1');
await expect(h1).toBeVisible({ timeout: 5000 });
// All colored spans should be inside the h1
const spans = h1.locator('span');
const count = await spans.count();
expect(count).toBeGreaterThanOrEqual(4);
});
test('stepper: stepping forward renders styled text', async ({ page }) => {
// Start from step 0
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 10 times to get through "of"
for (let i = 0; i < 10; i++) {
await fwdBtn.click();
await page.waitForTimeout(300);
}
const lake = page.locator('[data-sx-lake="home-preview"]');
const text = await lake.textContent();
expect(text).toContain('of');
// The "of" text should be in a styled span (with sx- or data-tw class)
const styledSpan = lake.locator('span[data-tw]').filter({ hasText: 'of' });
const count = await styledSpan.count();
expect(count).toBeGreaterThan(0);
});