Add docs and further stress tests to the demo
This commit is contained in:
@@ -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()
|
||||
|
||||
Reference in New Issue
Block a user