Add docs and further stress tests to the demo

This commit is contained in:
2026-07-21 17:56:58 +10:00
parent 9af84760fa
commit 92c61abcfe
15 changed files with 752 additions and 14 deletions

View File

@@ -32,14 +32,19 @@ async function waitForTransition(page: Page) {
await expect(page.locator('.nvr-router-view')).not.toHaveClass(/nvr-router-view--interactive/)
}
async function flickToNextTab(page: Page) {
async function flickToNextTab(page: Page, leaveSlowSpring = false) {
// Start on the route header, outside conversation-owned drag targets.
const frame = await page.locator('[data-native-role="active"] .app-header, [data-native-role="to"] .app-header').last().boundingBox()
if (!frame) throw new Error('Active route header did not render')
const y = frame.y + frame.height * 0.5
await page.mouse.move(frame.x + frame.width * 0.68, y)
const surface = await page.locator('.nvr-router-view').boundingBox()
const header = await page.locator('[data-native-role="active"] .app-header, [data-native-role="to"] .app-header').last().boundingBox()
if (!surface || !header) throw new Error('Active route header did not render')
const y = header.y + header.height * 0.5
await page.mouse.move(surface.x + surface.width * 0.72, y)
await page.mouse.down()
await page.mouse.move(frame.x + frame.width * 0.48, y)
if (leaveSlowSpring) {
await page.mouse.move(surface.x + surface.width * 0.3, y, { steps: 10 })
await page.waitForTimeout(90)
}
await page.mouse.move(surface.x + surface.width * 0.27, y)
await page.mouse.up()
}
@@ -146,7 +151,9 @@ test('accepts a second fast tab flick while the first spring is still settling',
await page.goto('/inbox')
const routerView = page.locator('.nvr-router-view')
await flickToNextTab(page)
// Commit by distance with a deliberately slow final sample, leaving enough
// baseline spring for the second fast gesture to interrupt deterministically.
await flickToNextTab(page, true)
await expect(page).toHaveURL(/\/stories$/)
await expect(routerView).toHaveClass(/nvr-router-view--interactive/)
@@ -162,6 +169,61 @@ test('accepts a second fast tab flick while the first spring is still settling',
await expect(routerView).not.toHaveAttribute('data-native-transaction')
})
test('renders a suspended deep sibling and keeps its pushed history entry', async ({ page }) => {
await page.goto('/profile')
await page.getByRole('link', { name: /Runtime stress lab/ }).click()
await expect(page.getByTestId('async-data-loading')).toBeVisible()
await expect(page).toHaveURL(/\/profile\/runtime-lab$/)
await expect(page.getByRole('navigation', { name: 'Primary navigation' })).toBeVisible()
await expect(page.getByRole('link', { name: /You/ })).toHaveAttribute('aria-current', 'page')
await expect(page.getByTestId('async-data-ready')).toBeVisible({ timeout: 2_000 })
const counter = page.locator('[data-native-route="/profile/runtime-lab"] [data-testid="mounted-seconds"]')
const before = Number(await counter.getAttribute('data-seconds'))
await page.getByRole('button', { name: 'Back' }).click()
await expect(page).toHaveURL(/\/profile$/)
await waitForTransition(page)
// The route is out of view but still mounted, so its local interval advances.
await expect.poll(async () => Number(await counter.getAttribute('data-seconds')), { timeout: 2_500 }).toBeGreaterThan(before)
// browser forward exists only because this sibling opted into push history.
await page.evaluate(() => history.forward())
await expect(page).toHaveURL(/\/profile\/runtime-lab$/)
await expect(page.getByTestId('async-data-ready')).toBeVisible()
})
test('a dynamic guard rejects an already-cached route without destroying it', async ({ page }) => {
await page.goto('/profile')
await page.getByRole('link', { name: /Runtime stress lab/ }).click()
await expect(page).toHaveURL(/\/profile\/runtime-lab$/)
await expect(page.getByTestId('async-data-ready')).toBeVisible({ timeout: 2_000 })
await page.getByRole('button', { name: 'Back' }).click()
await expect(page).toHaveURL(/\/profile$/)
await waitForTransition(page)
const cachedLab = page.locator('[data-native-route="/profile/runtime-lab"]')
const counter = cachedLab.getByTestId('mounted-seconds')
const beforeBlockedAttempt = Number(await counter.getAttribute('data-seconds'))
await page.getByRole('button', { name: 'Block Runtime Lab re-entry' }).click()
await expect(page.getByRole('button', { name: 'Block Runtime Lab re-entry' })).toHaveAttribute('aria-pressed', 'true')
await page.getByRole('link', { name: /Runtime stress lab/ }).click()
await expect(cachedLab.getByTestId('lab-guard-status')).toHaveText('blocked')
await waitForTransition(page)
await expect(page).toHaveURL(/\/profile$/)
await expect(page.getByRole('heading', { name: 'You' })).toBeVisible()
await expect(cachedLab).toHaveCount(1)
await expect.poll(async () => Number(await counter.getAttribute('data-seconds')), { timeout: 2_500 }).toBeGreaterThan(beforeBlockedAttempt)
await page.getByRole('button', { name: 'Block Runtime Lab re-entry' }).click()
await page.getByRole('link', { name: /Runtime stress lab/ }).click()
await expect(page).toHaveURL(/\/profile\/runtime-lab$/)
await expect(page.getByTestId('async-data-ready')).toBeVisible()
await expect(page.getByTestId('mounted-seconds')).toHaveAttribute('data-seconds', /[2-9]|[1-9]\d+/)
})
test('opens and dismisses the compose sheet', async ({ page }) => {
await page.goto('/inbox')
await page.getByRole('button', { name: 'Compose' }).click()

View File

@@ -88,4 +88,5 @@ test('precaches lazily split routes for offline navigation', async ({ page }) =>
})
expect(cachedUrls.some((url) => /StoriesView-.*\.js$/.test(url))).toBe(true)
expect(cachedUrls.some((url) => /ProfileView-.*\.js$/.test(url))).toBe(true)
expect(cachedUrls.some((url) => /RuntimeLabView-.*\.js$/.test(url))).toBe(true)
})