Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

[Locked Figure Aria] Locked polygon aria labels (graph + editor) #1691

Merged
merged 17 commits into from
Sep 30, 2024
Merged
Show file tree
Hide file tree
Changes from 15 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
6 changes: 6 additions & 0 deletions .changeset/beige-worms-hope.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,6 @@
---
"@khanacademy/perseus": minor
"@khanacademy/perseus-editor": minor
---

[Locked Figure Aria] Locked function aria labels (graph + editor)
6 changes: 6 additions & 0 deletions .changeset/dirty-ducks-rescue.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,6 @@
---
"@khanacademy/perseus": minor
"@khanacademy/perseus-editor": minor
---

[Locked Figure Labels] Add/edit/delete locked polygon labels
6 changes: 6 additions & 0 deletions .changeset/fresh-sheep-invent.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,6 @@
---
"@khanacademy/perseus": minor
"@khanacademy/perseus-editor": minor
---

[Locked Figure Aria] Implement locked line aria label behavior on graph
6 changes: 6 additions & 0 deletions .changeset/honest-frogs-walk.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,6 @@
---
"@khanacademy/perseus": minor
"@khanacademy/perseus-editor": minor
---

[Locked Figure Aria] Locked polygon aria labels (graph + editor)
6 changes: 6 additions & 0 deletions .changeset/hot-geese-look.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,6 @@
---
"@khanacademy/perseus": minor
"@khanacademy/perseus-editor": minor
---

[Locked Figure Aria] Implement locked point aria label behavior on graph
6 changes: 6 additions & 0 deletions .changeset/itchy-pears-march.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,6 @@
---
"@khanacademy/perseus": minor
"@khanacademy/perseus-editor": minor
---

[Locked Figure Aria] Locked line aria label editor UI
6 changes: 6 additions & 0 deletions .changeset/red-garlics-divide.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,6 @@
---
"@khanacademy/perseus": minor
"@khanacademy/perseus-editor": minor
---

[Locked Figure Aria] Implement locked vector aria labels (graph + editor)
6 changes: 6 additions & 0 deletions .changeset/shiny-falcons-sparkle.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,6 @@
---
"@khanacademy/perseus": minor
"@khanacademy/perseus-editor": minor
---

[Locked Figure Labels] View locked polygon labels
6 changes: 6 additions & 0 deletions .changeset/strong-spoons-talk.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,6 @@
---
"@khanacademy/perseus": minor
"@khanacademy/perseus-editor": minor
---

[Locked Figure Aria] Locked point aria label editor UI
6 changes: 6 additions & 0 deletions .changeset/wild-cars-drop.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,6 @@
---
"@khanacademy/perseus": minor
"@khanacademy/perseus-editor": minor
---

[Locked Figure Aria] Implement locked ellipse aria labels (graph + editor)
Original file line number Diff line number Diff line change
Expand Up @@ -16,10 +16,12 @@ export const flags = {

// Locked figures flags
"interactive-graph-locked-features-labels": true,
"locked-figures-aria": true,
"locked-point-labels": true,
"locked-line-labels": true,
"locked-vector-labels": true,
"locked-ellipse-labels": true,
"locked-polygon-labels": true,
"locked-function-labels": true,
},
} satisfies APIOptions["flags"];
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -153,10 +153,12 @@ export const MafsWithLockedFiguresCurrent = (): React.ReactElement => {
mafs: {
...flags.mafs,
"interactive-graph-locked-features-labels": false,
"locked-figures-aria": false,
"locked-point-labels": false,
"locked-line-labels": false,
"locked-vector-labels": false,
"locked-ellipse-labels": false,
"locked-polygon-labels": false,
"locked-function-labels": false,
},
},
Expand Down Expand Up @@ -186,6 +188,7 @@ export const MafsWithLockedLabelsFlag = (): React.ReactElement => {
"locked-line-labels": false,
"locked-vector-labels": false,
"locked-ellipse-labels": false,
"locked-polygon-labels": false,
"locked-function-labels": false,
},
},
Expand All @@ -207,6 +210,7 @@ export const MafsWithLockedPointLabelsFlag = (): React.ReactElement => {
"locked-line-labels": false,
"locked-vector-labels": false,
"locked-ellipse-labels": false,
"locked-polygon-labels": false,
"locked-function-labels": false,
},
},
Expand All @@ -228,6 +232,7 @@ export const MafsWithLockedLineLabelsFlag = (): React.ReactElement => {
"locked-line-labels": true,
"locked-vector-labels": false,
"locked-ellipse-labels": false,
"locked-polygon-labels": false,
"locked-function-labels": false,
},
},
Expand All @@ -249,6 +254,7 @@ export const MafsWithLockedVectorLabelsFlag = (): React.ReactElement => {
"locked-line-labels": false,
"locked-vector-labels": true,
"locked-ellipse-labels": false,
"locked-polygon-labels": false,
"locked-function-labels": false,
},
},
Expand All @@ -270,6 +276,29 @@ export const MafsWithLockedEllipseLabelsFlag = (): React.ReactElement => {
"locked-line-labels": false,
"locked-vector-labels": false,
"locked-ellipse-labels": true,
"locked-polygon-labels": false,
"locked-function-labels": false,
},
},
}}
question={segmentWithLockedFigures}
/>
);
};

export const MafsWithLockedPolygonLabelsFlag = (): React.ReactElement => {
return (
<EditorPageWithStorybookPreview
apiOptions={{
flags: {
mafs: {
...flags.mafs,
"interactive-graph-locked-features-labels": true,
"locked-point-labels": false,
"locked-line-labels": false,
"locked-vector-labels": false,
"locked-ellipse-labels": false,
"locked-polygon-labels": true,
"locked-function-labels": false,
},
},
Expand All @@ -291,6 +320,7 @@ export const MafsWithLockedFunctionLabelsFlag = (): React.ReactElement => {
"locked-line-labels": false,
"locked-vector-labels": false,
"locked-ellipse-labels": false,
"locked-polygon-labels": false,
"locked-function-labels": true,
},
},
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -34,7 +34,7 @@ export default function InteractiveGraphDescription(props: Props) {
<LabelXSmall style={styles.caption}>
Use these fields to describe the graph as a whole. These
are used by screen readers to describe content to users
who are visually impaired.
who may be visually impaired.
</LabelXSmall>
<LabelLarge tag="label">
Title
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -317,4 +317,223 @@ describe("LockedEllipseSettings", () => {
});
});
});

describe("Aria label", () => {
test("Renders with aria label", () => {
// Arrange

// Act
render(
<LockedEllipseSettings
{...defaultProps}
ariaLabel="Ellipse at (x, y)"
/>,
{wrapper: RenderStateRoot},
);

const input = screen.getByRole("textbox", {name: "Aria label"});

// Assert
expect(input).toHaveValue("Ellipse at (x, y)");
});

test("calls onChangeProps when the aria label is updated", async () => {
// Arrange
const onChangeProps = jest.fn();
render(
<LockedEllipseSettings
{...defaultProps}
ariaLabel={undefined}
onChangeProps={onChangeProps}
/>,
{wrapper: RenderStateRoot},
);

// Act
const input = screen.getByRole("textbox", {name: "Aria label"});
await userEvent.clear(input);
await userEvent.type(input, "A");

// Assert
expect(onChangeProps).toHaveBeenCalledWith({
ariaLabel: "A",
});
});

test("aria label autogenerates saying circle when the radii are equal", async () => {
// Arrange
const onChangeProps = jest.fn();

// Act
render(
<LockedEllipseSettings
{...defaultProps}
radius={[2, 2]}
ariaLabel={undefined}
onChangeProps={onChangeProps}
/>,
{wrapper: RenderStateRoot},
);

const autoGenButton = screen.getByRole("button", {
name: "Auto-generate",
});
await userEvent.click(autoGenButton);

// Assert
expect(onChangeProps).toHaveBeenCalledWith({
ariaLabel: "Circle with radius 2, centered at (0, 0)",
});
});

test("aria label auto-generates without rotation when ellipse is a circle", async () => {
// Arrange
const onChangeProps = jest.fn();

// Act
render(
<LockedEllipseSettings
{...defaultProps}
radius={[2, 2]}
ariaLabel={undefined}
onChangeProps={onChangeProps}
angle={Math.PI}
/>,
{wrapper: RenderStateRoot},
);

const autoGenButton = screen.getByRole("button", {
name: "Auto-generate",
});
await userEvent.click(autoGenButton);

// Assert
expect(onChangeProps).toHaveBeenCalledWith({
ariaLabel: "Circle with radius 2, centered at (0, 0)",
});
});

test("aria label auto-generates saying ellipse when the radii are different", async () => {
// Arrange
const onChangeProps = jest.fn();

// Act
render(
<LockedEllipseSettings
{...defaultProps}
radius={[2, 3]}
ariaLabel={undefined}
onChangeProps={onChangeProps}
/>,
{wrapper: RenderStateRoot},
);

const autoGenButton = screen.getByRole("button", {
name: "Auto-generate",
});
await userEvent.click(autoGenButton);

// Assert
expect(onChangeProps).toHaveBeenCalledWith({
ariaLabel:
"Ellipse with x radius 2 and y radius 3, centered at (0, 0)",
});
});

test("aria label auto-generates with rotation when ellipse is rotated", async () => {
// Arrange
const onChangeProps = jest.fn();

// Act
render(
<LockedEllipseSettings
{...defaultProps}
radius={[2, 3]}
ariaLabel={undefined}
onChangeProps={onChangeProps}
angle={Math.PI / 2}
/>,
{wrapper: RenderStateRoot},
);

const autoGenButton = screen.getByRole("button", {
name: "Auto-generate",
});
await userEvent.click(autoGenButton);

// Assert
expect(onChangeProps).toHaveBeenCalledWith({
ariaLabel:
"Ellipse with x radius 2 and y radius 3, centered at (0, 0), rotated by 90 degrees",
});
});

test("aria label auto-generates with one label", async () => {
// Arrange
const onChangeProps = jest.fn();
render(
<LockedEllipseSettings
{...defaultProps}
radius={[2, 2]}
ariaLabel={undefined}
onChangeProps={onChangeProps}
labels={[
{
...defaultLabel,
text: "A",
},
]}
/>,
{wrapper: RenderStateRoot},
);

// Act
const autoGenButton = screen.getByRole("button", {
name: "Auto-generate",
});
await userEvent.click(autoGenButton);

// Assert
expect(onChangeProps).toHaveBeenCalledWith({
ariaLabel:
"Circle with radius 2, centered at (0, 0), with label A",
});
});

test("aria label auto-generates with multiple labels", async () => {
// Arrange
const onChangeProps = jest.fn();
render(
<LockedEllipseSettings
{...defaultProps}
radius={[2, 2]}
ariaLabel={undefined}
onChangeProps={onChangeProps}
labels={[
{
...defaultLabel,
text: "A",
},
{
...defaultLabel,
text: "B",
},
]}
/>,
{wrapper: RenderStateRoot},
);

// Act
const autoGenButton = screen.getByRole("button", {
name: "Auto-generate",
});
await userEvent.click(autoGenButton);

// Assert
expect(onChangeProps).toHaveBeenCalledWith({
ariaLabel:
"Circle with radius 2, centered at (0, 0), with labels A, B",
});
});
});
});
Loading