This commit is contained in:
Abhay Singh 2026-09-26 20:20:51 +00:00 • committed by GitHub
commit 03a8da0333
No known key found for this signature in database
GPG key ID: B5690EEEBB952194
4 changed files with 107 additions and 4 deletions

View file

@ -0,0 +1,95 @@
/**
* Mounted-render accessibility checks for the graph control surfaces:
* accessible names on icon-only zoom buttons, disclosure state on the legend,
* and a live region on the loading indicator.
*/
// @vitest-environment happy-dom
import { cleanup, fireEvent, render } from "@testing-library/react"
import { afterEach, describe, expect, it } from "vitest"
afterEach(cleanup)
import { Legend } from "../components/legend"
import { LoadingIndicator } from "../components/loading-indicator"
import { NavigationControls } from "../components/navigation-controls"
import { DEFAULT_COLORS, DEFAULT_LABELS } from "../constants"
import type { GraphNode } from "../types"
const node: GraphNode = {
id: "doc-1",
type: "document",
x: 0,
y: 0,
data: {
id: "doc-1",
title: "Doc",
summary: null,
type: "text",
createdAt: "2026-01-01",
updatedAt: "2026-01-01",
memories: [],
},
size: 40,
borderColor: "#fff",
isHovered: false,
isDragging: false,
}
const noop = () => {}
describe("NavigationControls accessibility", () => {
it("gives the icon-only zoom buttons accessible names", () => {
const { getByLabelText } = render(
<NavigationControls
onCenter={noop}
onZoomIn={noop}
onZoomOut={noop}
onAutoFit={noop}
nodes={[node]}
zoomLevel={100}
colors={DEFAULT_COLORS}
/>,
)
expect(getByLabelText("Zoom in")).toBeTruthy()
expect(getByLabelText("Zoom out")).toBeTruthy()
})
})
describe("Legend accessibility", () => {
it("exposes disclosure state via aria-expanded and toggles it", () => {
const { getByRole } = render(
<Legend
nodes={[node]}
edges={[]}
colors={DEFAULT_COLORS}
labels={DEFAULT_LABELS}
/>,
)
const toggle = getByRole("button", { name: "Legend" })
expect(toggle.getAttribute("aria-expanded")).toBe("false")
fireEvent.click(toggle)
expect(toggle.getAttribute("aria-expanded")).toBe("true")
})
})
describe("LoadingIndicator accessibility", () => {
it("announces loading through a status live region", () => {
const { getByRole } = render(
<LoadingIndicator
isLoading
isLoadingMore={false}
totalLoaded={0}
colors={DEFAULT_COLORS}
labels={DEFAULT_LABELS}
/>,
)
const status = getByRole("status")
expect(status.getAttribute("aria-live")).toBe("polite")
})
})

View file

@ -244,6 +244,7 @@ function StatRow({
onClick={expandable ? onToggle : undefined}
style={buttonStyle}
type="button"
aria-expanded={expandable ? expanded : undefined}
>
<div style={leftStyle}>
{icon}
@ -430,6 +431,7 @@ export const Legend = memo(function Legend({
onClick={() => setIsExpanded(!isExpanded)}
style={headerBtnStyle}
type="button"
aria-expanded={isExpanded}
>
{isExpanded ? (
<ChevronDownIcon color={colors.textPrimary} />

View file

@ -76,7 +76,7 @@ export const LoadingIndicator = memo<
}
return (
<div style={containerStyle}>
<output style={containerStyle} aria-live="polite">
<div style={flexStyle}>
<svg
aria-hidden="true"
@ -96,7 +96,7 @@ export const LoadingIndicator = memo<
: labels.loadingMoreDocuments(totalLoaded)}
</span>
</div>
</div>
</output>
)
},
)

View file

@ -169,6 +169,7 @@ export const NavigationControls = memo<NavigationControlsProps>(
onClick={onZoomOut}
style={zoomBtnStyle}
type="button"
aria-label="Zoom out"
onMouseEnter={(e) => {
e.currentTarget.style.opacity = "0.8"
}}
@ -176,13 +177,16 @@ export const NavigationControls = memo<NavigationControlsProps>(
e.currentTarget.style.opacity = "1"
}}
>
<span style={{ fontSize: 12 }}>−</span>
<span aria-hidden="true" style={{ fontSize: 12 }}>
−
</span>
</button>
<button
aria-label="Zoom in"
onClick={onZoomIn}
style={zoomBtnStyle}
type="button"
aria-label="Zoom in"
onMouseEnter={(e) => {
e.currentTarget.style.opacity = "0.8"
}}
@ -190,7 +194,9 @@ export const NavigationControls = memo<NavigationControlsProps>(
e.currentTarget.style.opacity = "1"
}}
>
<span style={{ fontSize: 12 }}>+</span>
<span aria-hidden="true" style={{ fontSize: 12 }}>
+
</span>
</button>
</div>
</div>