Stricter isomorphic test: exact DOM structure + text comparison

Test 2 now compares JSON.stringify of the full DOM tree structure
(tags, ids, classes, island markers, lake markers) and exact text
content between JS-disabled and JS-enabled renders.

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
This commit is contained in:
2026-03-23 20:12:17 +00:00
parent 33a02c8fe1
commit 49b03b246d

View File

@@ -85,37 +85,29 @@ test.describe('Isomorphic SSR', () => {
await context.close(); await context.close();
}); });
test('page renders with JavaScript and matches SSR structure', async ({ browser }) => { test('JS and no-JS render the same DOM structure and styles', async ({ browser }) => {
// First: get SSR content (no JS) // Get SSR DOM (no JS)
const noJsContext = await browser.newContext({ javaScriptEnabled: false }); const noJsContext = await browser.newContext({ javaScriptEnabled: false });
const noJsPage = await noJsContext.newPage(); const noJsPage = await noJsContext.newPage();
await noJsPage.goto(BASE_URL + TEST_PAGE, { waitUntil: 'domcontentloaded' }); await noJsPage.goto(BASE_URL + TEST_PAGE, { waitUntil: 'domcontentloaded' });
const ssrText = await getSxRootText(noJsPage);
const ssrStructure = await getSxRootStructure(noJsPage); const ssrStructure = await getSxRootStructure(noJsPage);
const ssrText = await getSxRootText(noJsPage);
await noJsContext.close(); await noJsContext.close();
// Then: get client-rendered content (with JS) // Get client DOM (with JS)
const jsContext = await browser.newContext({ javaScriptEnabled: true }); const jsContext = await browser.newContext({ javaScriptEnabled: true });
const jsPage = await jsContext.newPage(); const jsPage = await jsContext.newPage();
await jsPage.goto(BASE_URL + TEST_PAGE, { waitUntil: 'networkidle' }); await jsPage.goto(BASE_URL + TEST_PAGE, { waitUntil: 'networkidle' });
// Wait for islands to hydrate await jsPage.waitForTimeout(2000); // wait for hydration
await jsPage.waitForSelector('[data-sx-island].sx-processed', { timeout: 10000 }).catch(() => {}); const clientStructure = await getSxRootStructure(jsPage);
await jsPage.waitForTimeout(500); // settle
const clientText = await getSxRootText(jsPage); const clientText = await getSxRootText(jsPage);
await jsContext.close(); await jsContext.close();
// Text content should be the same (article text, headings, etc) // Text content must match
expect(ssrText.length).toBeGreaterThan(100); expect(ssrText).toBe(clientText);
expect(clientText.length).toBeGreaterThan(100);
// The core content should match — both should have the article headings // Structure must match — same tags, ids, classes
expect(clientText).toContain('Language games'); expect(JSON.stringify(ssrStructure)).toBe(JSON.stringify(clientStructure));
expect(clientText).toContain('The limits of my language');
// SSR should also have these
expect(ssrText).toContain('Language games');
expect(ssrText).toContain('The limits of my language');
}); });
test('header island has CSSX styling without JavaScript', async ({ browser }) => { test('header island has CSSX styling without JavaScript', async ({ browser }) => {