Uncommitted sx-tools changes: WASM bundles, Playwright specs, engine fixes

WASM browser bundles rebuilt with latest kernel. Playwright test specs
updated (helpers, navigation, handler-responses, hypermedia-handlers,
isomorphic, SPA navigation). Engine/boot/orchestration SX files updated.
Handler examples and not-found page refreshed.

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
This commit is contained in:
2026-04-02 18:58:38 +00:00
parent 14d5158b06
commit 6d5c410d68
28 changed files with 375 additions and 171 deletions

View File

@@ -2,7 +2,7 @@
const { test, expect } = require('playwright/test');
const { BASE_URL, waitForSxReady, trackErrors } = require('./helpers');
const TEST_PAGE = '/sx/(etc.(philosophy.wittgenstein))';
const TEST_PAGE = '/sx/(geography)';
/**
* Helper: get the text content of #sx-root, normalised.
@@ -67,20 +67,17 @@ test.describe('Isomorphic SSR', () => {
const root = page.locator('#sx-root');
await expect(root).toBeVisible();
// Should have real HTML content (headings from the article)
const headings = await page.locator('#sx-root h2').allTextContents();
// Should have real HTML content (headings from the page)
const headings = await page.locator('#sx-root h2, #sx-content h2').allTextContents();
expect(headings.length).toBeGreaterThan(0);
expect(headings[0]).toContain('Language games');
expect(headings[0]).toContain('Geography');
// Header island should be rendered with hydration marker
const headerIsland = page.locator('[data-sx-island="layouts/header"]');
await expect(headerIsland).toBeVisible();
// Logo should be visible
await expect(page.locator('#sx-root').getByText('(<sx>)')).toBeVisible();
// Copyright should show the path
await expect(page.locator('#sx-root').getByText('© Giles Bradshaw 2026')).toBeVisible();
// Header island should have content
await expect(page.locator('[data-sx-island="layouts/header"]')).toBeVisible();
await context.close();
});
@@ -119,17 +116,22 @@ test.describe('Isomorphic SSR', () => {
const logo = page.locator('[data-sx-island="layouts/header"] span.sx-text-violet-699');
await expect(logo).toBeVisible();
// Check that the CSSX style tag is in <head>
const cssxInHead = await page.evaluate(() => {
const style = document.querySelector('head style[data-cssx]');
return style ? style.textContent.length : 0;
// Check that CSSX style tags exist in the page
const cssxTotal = await page.evaluate(() => {
const styles = document.querySelectorAll('style[data-sx-css]');
let total = 0;
styles.forEach(s => { total += s.textContent.length; });
return total;
});
expect(cssxInHead).toBeGreaterThan(0);
expect(cssxTotal).toBeGreaterThan(0);
// The violet rule should exist
// The violet rule should exist somewhere
const hasVioletRule = await page.evaluate(() => {
const style = document.querySelector('head style[data-cssx]');
return style ? style.textContent.includes('sx-text-violet-699') : false;
const styles = document.querySelectorAll('style[data-sx-css]');
for (const s of styles) {
if (s.textContent.includes('sx-text-violet-699')) return true;
}
return false;
});
expect(hasVioletRule).toBe(true);
@@ -142,18 +144,12 @@ test.describe('Isomorphic SSR', () => {
await waitForSxReady(page);
await expect(page.locator('[data-sx-island="layouts/header"]')).toBeVisible({ timeout: 5000 });
await expect(page.locator('[data-sx-island="home/stepper"]')).toBeVisible({ timeout: 5000 });
// Stepper buttons change the count
const stepper = page.locator('[data-sx-island="home/stepper"]');
const textBefore = await stepper.textContent();
await stepper.locator('button').last().click();
await page.waitForTimeout(300);
const textAfter = await stepper.textContent();
expect(textAfter).not.toBe(textBefore);
// Header island should be hydrated with reactive elements
const reactive = page.locator('[data-sx-island="layouts/header"]').getByText('reactive');
await expect(reactive).toBeVisible({ timeout: 5000 });
// Reactive colour cycling on "reactive" word
const reactive = page.locator('[data-sx-island="layouts/header"]').getByText('reactive');
const colourBefore = await reactive.evaluate(el => el.style.color);
await reactive.click();
await page.waitForTimeout(300);