Rail sections (Outline/Blocks/Nodes) collapse via their headers like Experiments already did, so long pages stay navigable. Rail open state and section toggles persist in localStorage across reloads (the QA preview flow reloads constantly). The assistant panel shifts left while the dev panel is open instead of stacking exactly underneath it, and the rail/dev/assistant widths cap at the viewport on small screens. Tests: rail-sections harness (collapse, reload persistence, shifted assistant); harness boots with a fresh profile unless keepStorage is passed; in-memory localStorage shim for the origin-less jsdom. 🤖 Generated with Codebuff Co-Authored-By: Codebuff <noreply@codebuff.com>
75 lines
2.9 KiB
TypeScript
75 lines
2.9 KiB
TypeScript
import { afterEach, beforeEach, describe, expect, it } from 'vitest'
|
|
import { act } from 'react'
|
|
import { setup } from './harness'
|
|
import type { Harness } from './harness'
|
|
|
|
let h: Harness
|
|
beforeEach(() => localStorage.clear())
|
|
afterEach(() => {
|
|
h?.cleanup()
|
|
delete (navigator as any).gpu
|
|
})
|
|
|
|
const q = (sel: string) => h.shadow.querySelector<HTMLElement>(sel)!
|
|
const qa = (sel: string) => [...h.shadow.querySelectorAll<HTMLElement>(sel)]
|
|
|
|
describe('rail sections', () => {
|
|
it('outline, blocks and nodes collapse via their headers', async () => {
|
|
h = await setup()
|
|
await h.settle()
|
|
await h.press('Panel')
|
|
await h.settle()
|
|
await h.settle()
|
|
expect(qa('.cms-outline').length).toBeGreaterThan(0)
|
|
// collapse outline: the tree leaves the DOM, palette stays
|
|
// (NB: the section itself shares the aria-label, so target the toggle button)
|
|
await act(async () => void q('button[aria-label="Outline"]').click())
|
|
await h.settle()
|
|
expect(qa('.cms-outline').length).toBe(0)
|
|
expect(q('[aria-label="Search blocks"]')).not.toBeNull()
|
|
// collapse blocks too
|
|
await act(async () => void q('button[aria-label="Blocks"]').click())
|
|
await h.settle()
|
|
expect(h.shadow.querySelector('[aria-label="Search blocks"]')).toBeNull()
|
|
// and back open
|
|
await act(async () => void q('button[aria-label="Blocks"]').click())
|
|
await h.settle()
|
|
expect(q('[aria-label="Search blocks"]')).not.toBeNull()
|
|
await act(async () => void q('button[aria-label="Outline"]').click())
|
|
await h.settle()
|
|
expect(qa('.cms-outline').length).toBeGreaterThan(0)
|
|
})
|
|
|
|
it('rail open state and collapsed sections survive a reload', async () => {
|
|
h = await setup()
|
|
await h.settle()
|
|
await h.press('Panel')
|
|
await h.settle()
|
|
await act(async () => void q('button[aria-label="Blocks"]').click()) // collapse blocks
|
|
await h.settle()
|
|
expect(localStorage.getItem('cms-onpage.rail')).toBe('true')
|
|
expect(localStorage.getItem('cms-onpage.sec.blocks')).toBe('false')
|
|
// reload with the same profile: rail reopens, blocks stays collapsed
|
|
h.cleanup()
|
|
h = await setup({ keepStorage: true })
|
|
await h.settle()
|
|
await h.settle()
|
|
expect(q('.cms-rail')).not.toBeNull()
|
|
expect(h.shadow.querySelector('[aria-label="Search blocks"]')).toBeNull()
|
|
expect(qa('.cms-outline').length).toBeGreaterThan(0)
|
|
})
|
|
|
|
it('assistant sits beside the dev panel instead of stacking under it', async () => {
|
|
;(navigator as any).gpu = {} // aiSupported() checks for a WebGPU API
|
|
h = await setup()
|
|
await h.settle()
|
|
await act(async () => void h.editor.ctrl.store.set({ assistant: true, dev: true }))
|
|
await h.settle()
|
|
expect(q('.cms-dev')).not.toBeNull()
|
|
expect(q('.cms-assistant.cms-assistant--shifted')).not.toBeNull()
|
|
await act(async () => void h.editor.ctrl.store.set({ dev: false }))
|
|
await h.settle()
|
|
expect(h.shadow.querySelector('.cms-assistant--shifted')).toBeNull()
|
|
})
|
|
})
|