Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
4 changes: 2 additions & 2 deletions packages/ui-react/tests/browser/diagrams-axis.layout.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -12,7 +12,7 @@ afterAll(async()=>{styles.remove();await commands.formViewport(previousViewport.
function setup(width=760){root=createBrainUiRoot({storage:null,request:async()=>Response.json({renderers:[],enabled:[]})});host=document.createElement("div");host.style.width=`${width}px`;document.body.append(host);render=createRoot(host);}
function mount(source:string,theme:"light"|"dark"|"print"){flushSync(()=>render.render(<BrainUiProvider root={root}><DiagramContent source={source} theme={theme} mode="chat"/></BrainUiProvider>));}
async function ready(){await expect.poll(()=>host.querySelector('figure>svg')).not.toBeNull();await document.fonts.ready;}
function inspect(svg:SVGSVGElement){const frame=svg.viewBox.baseVal;for(const label of svg.querySelectorAll("text")){const box=label.getBBox(),matrix=label.getScreenCTM()!,scale=Math.min(Math.hypot(matrix.a,matrix.b),Math.hypot(matrix.c,matrix.d));expect(parseFloat(getComputedStyle(label).fontSize)*scale,"AXIS_NORMAL_TEXT_FLOOR").toBeGreaterThanOrEqual(9);expect(box.x,"TEXT_LEFT_BOUND").toBeGreaterThanOrEqual(0);expect(box.x+box.width,"TEXT_RIGHT_BOUND").toBeLessThanOrEqual(frame.width);expect(box.y,"TEXT_TOP_BOUND").toBeGreaterThanOrEqual(0);expect(box.y+box.height,"TEXT_BOTTOM_BOUND").toBeLessThanOrEqual(frame.height);}}
function inspect(svg:SVGSVGElement){expect(svg.querySelectorAll("text").length,"EXPECTED_AXIS_TEXT_POPULATION").toBeGreaterThan(0);const frame=svg.viewBox.baseVal;for(const label of svg.querySelectorAll("text")){const box=label.getBBox(),matrix=label.getScreenCTM()!,scale=Math.min(Math.hypot(matrix.a,matrix.b),Math.hypot(matrix.c,matrix.d));expect(parseFloat(getComputedStyle(label).fontSize)*scale,"AXIS_NORMAL_TEXT_FLOOR").toBeGreaterThanOrEqual(9);expect(box.x,"TEXT_LEFT_BOUND").toBeGreaterThanOrEqual(0);expect(box.x+box.width,"TEXT_RIGHT_BOUND").toBeLessThanOrEqual(frame.width);expect(box.y,"TEXT_TOP_BOUND").toBeGreaterThanOrEqual(0);expect(box.y+box.height,"TEXT_BOTTOM_BOUND").toBeLessThanOrEqual(frame.height);}}
for(const [kind,spec] of Object.entries(axisExamples))test(`${kind} real light dark print baselines and static parity`,async()=>{
setup(kind==="swimlane"?1000:760);const source=JSON.stringify(spec);
for(const theme of ["light","dark","print"] as const){mount(source,theme);await ready();const svg=host.querySelector<SVGSVGElement>('figure>svg')!;inspect(svg);const parsed=new DOMParser().parseFromString(await toStatic(source,{theme}),"image/svg+xml");
Expand All @@ -22,7 +22,7 @@ for(const [kind,spec] of Object.entries(axisExamples))test(`${kind} real light d
});
test("sequence uses readable derived phone layout and unsafe content opens the full viewer",async()=>{
setup(320);mount(JSON.stringify(axisExamples.sequence),"dark");await ready();const svg=host.querySelector<SVGSVGElement>('figure>svg')!;expect(svg.viewBox.baseVal.width).toBe(320);inspect(svg);expect(host.scrollWidth).toBeLessThanOrEqual(320);await expect(page.elementLocator(host)).toMatchScreenshot("axis-sequence-320-dark");await commands.diagramCapture('[data-content-renderer="diagram"]',"axis-sequence-320-dark");
const unsafe=structuredClone(axisExamples.sequence);unsafe.nodes.push({id:"penelope",label:"Penelope"},{id:"athena",label:"Athena"});mount(JSON.stringify(unsafe),"light");await expect.poll(()=>host.querySelector('[data-diagram-summary]')).not.toBeNull();expect(host.querySelector('figure>svg')).toBeNull();const opener=[...host.querySelectorAll<HTMLElement>('[role="button"],button')].find(b=>b.textContent==="Open diagram")!;expect(opener.getBoundingClientRect().height).toBeGreaterThanOrEqual(44);await userEvent.click(opener);await expect.poll(()=>document.querySelector('[aria-label="Diagram viewer"] svg')).not.toBeNull();inspect(document.querySelector<SVGSVGElement>('[aria-label="Diagram viewer"] svg')!);await userEvent.keyboard("{Escape}");
const unsafe=structuredClone(axisExamples.sequence);unsafe.nodes.push({id:"penelope",label:"Penelope"},{id:"athena",label:"Athena"});mount(JSON.stringify(unsafe),"light");await expect.poll(()=>host.querySelector('[data-diagram-summary]')).not.toBeNull();expect(host.querySelector('figure>svg')).toBeNull();const opener=[...host.querySelectorAll<HTMLElement>('[role="button"],button')].find(b=>b.textContent==="Open diagram")!;expect(opener.getBoundingClientRect().height).toBeGreaterThanOrEqual(44);await userEvent.click(opener);await expect.poll(()=>document.querySelector('[aria-label="Diagram viewer"] svg.bk-diagram')).not.toBeNull();inspect(document.querySelector<SVGSVGElement>('[aria-label="Diagram viewer"] svg.bk-diagram')!);await userEvent.keyboard("{Escape}");
});

test("axis handoff masks clear every step and tips attach at the boundary",async()=>{
Expand Down
4 changes: 2 additions & 2 deletions packages/ui-react/tests/browser/diagrams-renderer.layout.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -18,7 +18,7 @@ function setup(width=1000){root=createBrainUiRoot({storage:null,request:async()=
function mount(element:React.ReactNode){flushSync(()=>render.render(<BrainUiProvider root={root}>{element}</BrainUiProvider>));}
function screenSvg(){return host.querySelector<SVGSVGElement>('figure > svg.bk-diagram');}
async function ready(){await expect.poll(()=>screenSvg()).not.toBeNull();await document.fonts.ready;}
function fontFloor(svg:SVGSVGElement){for(const text of svg.querySelectorAll("text")){const matrix=text.getScreenCTM()!;const scale=Math.min(Math.hypot(matrix.a,matrix.b),Math.hypot(matrix.c,matrix.d));expect(parseFloat(getComputedStyle(text).fontSize)*scale,"ACTUAL_DISPLAYED_TEXT_FLOOR").toBeGreaterThanOrEqual(9);}}
function fontFloor(svg:SVGSVGElement){expect(svg.querySelectorAll("text").length,"EXPECTED_DIAGRAM_TEXT_POPULATION").toBeGreaterThan(0);for(const text of svg.querySelectorAll("text")){const matrix=text.getScreenCTM()!;const scale=Math.min(Math.hypot(matrix.a,matrix.b),Math.hypot(matrix.c,matrix.d));expect(parseFloat(getComputedStyle(text).fontSize)*scale,"ACTUAL_DISPLAYED_TEXT_FLOOR").toBeGreaterThanOrEqual(9);}}
test("registered chat fence renders and follows live light/dark and actual print media",async()=>{
setup();defaultContentRendererRegistry.register(diagramsContentPack);document.documentElement.dataset.theme="light";root.stores.ui.setState({theme:"light"});
mount(<BrainMarkdown content={'```diagram\n'+source+'\n```'}/>);await ready();
Expand All @@ -34,7 +34,7 @@ test("actual constrained containers select authored layout or semantic fallback,
for(const width of [320,480,900]){host.style.width=`${width}px`;await expect.poll(()=>screenSvg()?.getBoundingClientRect().width).toBe(320);fontFloor(screenSvg()!);expect(host.scrollWidth).toBeLessThanOrEqual(width);}
const absent=structuredClone(rendererSpec);delete (absent as {layouts?:unknown}).layouts;host.style.width="320px";mount(<DiagramContent source={JSON.stringify(absent)} mode="chat" theme="dark"/>);await expect.poll(()=>screenSvg()).toBeNull();expect(host.querySelector("[data-diagram-summary]")?.textContent).toBe(rendererSpec.desc);
const opener=[...host.querySelectorAll<HTMLElement>("[role=button],button")].find(item=>item.textContent==="Open diagram")!;expect(opener.getBoundingClientRect().height).toBeGreaterThanOrEqual(44);await userEvent.click(opener);
await expect.poll(()=>document.querySelector('[aria-label="Diagram viewer"] svg')).not.toBeNull();const drawing=document.querySelector<SVGSVGElement>('[aria-label="Diagram viewer"] svg')!;fontFloor(drawing);await userEvent.keyboard("{Escape}");
await expect.poll(()=>document.querySelector('[aria-label="Diagram viewer"] svg.bk-diagram')).not.toBeNull();const drawing=document.querySelector<SVGSVGElement>('[aria-label="Diagram viewer"] svg.bk-diagram')!;expect([...drawing.querySelectorAll("[data-diagram-node] text")].map(text=>text.textContent),"EXPECTED_VIEWER_NODE_LABELS").toEqual(expect.arrayContaining(rendererSpec.nodes.map(node=>node.label)));fontFloor(drawing);await userEvent.keyboard("{Escape}");
});
test("keyboard nodes navigate like wiki links and incident edges and focus ring remain visible",async()=>{
setup();const paths:string[]=[];root.stores.file.setState({openFile:async(path)=>{paths.push(path);}});mount(<DiagramContent source={source} theme="light" mode="chat"/>);await ready();
Expand Down
6 changes: 4 additions & 2 deletions scripts/bound-browser-documents.ts
Original file line number Diff line number Diff line change
Expand Up @@ -31,19 +31,21 @@ const declarations:DocumentDeclaration[]=[{
},{
// Reviewed against #2295 and #2346: bounded capture tracing, split relay and
// callout cases keep the exact HTML/CSS sink, five callers and offline producers.
// #2241 re-audit: renderer/axis edits only strengthen viewer selection and
// font assertions; capture arguments, call counts and producer closure stay fixed.
"command": "diagramCapture",
"owner": "packages/ui-react/tests/browser/diagram-proof-command.ts",
"ownerHash": "d7280cf23ba24bd636f7737d8552801e37f8c03c1e773aee660c9e07ded524a9",
"caller": "packages/ui-react/tests/browser/diagrams-renderer.layout.tsx",
"callerHash": "dbac044e90a3b7b84e308a96cca8396874afb9b96d8cc23b2fddb4293d85706c",
"callerHash": "9d5e6b574bc22fb19f47c6d7d813f13bd444920539bf341732700e9d3413de4a",
"calls": 2,
"additionalCallers": {
"packages/ui-react/tests/browser/diagrams-callouts.layout.tsx": {
"hash": "64e5d794fe1a9f54386d712bb445d75d8e9fd50ac0e271b791de6ca4a0948b44",
"calls": 8
},
"packages/ui-react/tests/browser/diagrams-axis.layout.tsx": {
"hash": "6512cb4660834ef7b15a52258d51f694c4e34fd530754bdc51580137db22b75c",
"hash": "bd7c728af1ae5c250ddbef4e3423372590aabc65430661fe6afed97e3eb6e933",
"calls": 3
},
"packages/ui-react/tests/browser/diagrams-positional.layout.tsx": {
Expand Down
Loading