Skip to content

Commit

Permalink
fix(#2029): callout add aria-live property
Browse files Browse the repository at this point in the history
  • Loading branch information
syedszeeshan authored and ArakTaiRoth committed Aug 27, 2024
1 parent 95ba940 commit 8822d39
Show file tree
Hide file tree
Showing 5 changed files with 194 additions and 41 deletions.
37 changes: 34 additions & 3 deletions libs/react-components/src/lib/callout/callout.spec.tsx
Original file line number Diff line number Diff line change
@@ -1,3 +1,4 @@
import React from "react";
import { render } from "@testing-library/react";
import GoACallout from "./callout";

Expand All @@ -13,10 +14,12 @@ describe("Callout", () => {
mr="m"
mb="l"
ml="xl"
ariaLive="polite"
testId="test-callout"
>
Information to the user goes in the content. Information can include
markup as desired.
</GoACallout>
Information to the user goes in the content. Information can include markup as
desired.
</GoACallout>,
);

const el = result.container.querySelector("goa-callout");
Expand All @@ -28,5 +31,33 @@ describe("Callout", () => {
expect(el?.getAttribute("mr")).toBe("m");
expect(el?.getAttribute("mb")).toBe("l");
expect(el?.getAttribute("ml")).toBe("xl");
expect(el?.getAttribute("arialive")).toBe("polite");
expect(el?.getAttribute("data-testid")).toBe("test-callout");
expect(el?.textContent).toContain("Information to the user goes");
});

test("Callout shall render with different ariaLive values", async () => {
const testCases = [
{ ariaLive: "assertive", expected: "assertive" },
{ ariaLive: "polite", expected: "polite" },
{ ariaLive: "off", expected: "off" },
{ ariaLive: undefined, expected: "off" },
{ ariaLive: "", expected: "" },
];

testCases.forEach(({ ariaLive, expected }) => {
const result = render(
<GoACallout
type="information"
heading="Callout Title"
ariaLive={ariaLive as "off" | "polite" | "assertive" | undefined}
>
Test content
</GoACallout>,
);

const el = result.container.querySelector("goa-callout");
expect(el?.getAttribute("arialive")).toBe(expected);
});
});
});
7 changes: 6 additions & 1 deletion libs/react-components/src/lib/callout/callout.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -8,12 +8,14 @@ export type GoACalloutType =
| "emergency";

export type GoACalloutSize = "medium" | "large";
export type GoACalloutAriaLive = "off" | "polite" | "assertive";

interface WCProps extends Margins {
heading?: string;
type?: GoACalloutType;
size?: GoACalloutSize;
maxwidth?: string;
arialive?: GoACalloutAriaLive;
}

declare global {
Expand All @@ -31,6 +33,7 @@ export interface GoACalloutProps extends Margins {
size?: GoACalloutSize;
maxWidth?: string;
testId?: string;
ariaLive?: GoACalloutAriaLive;
children?: React.ReactNode;
}

Expand All @@ -42,6 +45,7 @@ export const GoACallout = ({
size = "large",
maxWidth,
testId,
ariaLive = "off",
children,
mt,
mr,
Expand All @@ -54,6 +58,7 @@ export const GoACallout = ({
type={type}
size={size}
maxwidth={maxWidth}
arialive={ariaLive}
mt={mt}
mr={mr}
mb={mb}
Expand All @@ -63,6 +68,6 @@ export const GoACallout = ({
{children}
</goa-callout>
);
}
};

export default GoACallout;
19 changes: 17 additions & 2 deletions libs/web-components/src/components/callout/Callout.html-data.json
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,13 @@
{
"name": "type",
"description": "Define the context and colour of the callout.",
"values": [{ "name": "information" }, { "name": "important"}, { "name": "emergency"}, { "name": "success"}, { "name": "event"}]
"values": [
{ "name": "information" },
{ "name": "important" },
{ "name": "emergency" },
{ "name": "success" },
{ "name": "event" }
]
},
{
"name": "heading",
Expand All @@ -15,7 +21,7 @@
{
"name": "size",
"description": "Define the size of the callouts.",
"values": [{"name": "medium"}, {"name": "large"}]
"values": [{ "name": "medium" }, { "name": "large" }]
},
{
"name": "maxwidth",
Expand All @@ -41,6 +47,15 @@
"name": "ml",
"description": "Left margin",
"valueSet": "spacing"
},
{
"name": "arialive",
"description": "Sets the aria-live property",
"values": [
{ "name": "off" },
{ "name": "assertive" },
{ "name": "polite" }
]
}
],
"references": [
Expand Down
161 changes: 126 additions & 35 deletions libs/web-components/src/components/callout/Callout.spec.ts
Original file line number Diff line number Diff line change
@@ -1,90 +1,121 @@
import { render, waitFor } from '@testing-library/svelte';
import GoACallout from './Callout.svelte'
import GoACalloutWrapper from './CalloutWrapper.test.svelte'
import { render, waitFor } from "@testing-library/svelte";
import GoACallout from "./Callout.svelte";
import GoACalloutWrapper from "./CalloutWrapper.test.svelte";
import { it, describe } from "vitest";

describe('GoACalloutComponent', () => {
it('should render - emergency', async () => {
const baseElement = render(GoACallout, { testid: "callout-test", type: "emergency", heading: 'Complete' });
const callout = await baseElement.findByTestId('callout-test');
describe("GoACalloutComponent", () => {
it("should render - emergency", async () => {
const baseElement = render(GoACallout, {
testid: "callout-test",
type: "emergency",
heading: "Complete",
});
const callout = await baseElement.findByTestId("callout-test");
const span = callout.firstElementChild;
const icon = span.firstElementChild;

expect(callout).toBeTruthy();
expect(span).toBeTruthy();
expect(span).toHaveClass("emergency");
expect(icon).toHaveAttribute("type", "warning");
expect(callout).toContainHTML("Complete")
expect(callout).toContainHTML("Complete");
});

it('should render - important', async () => {
const baseElement = render(GoACallout, { testid: "callout-test", type: "important", heading: 'Complete' });
const callout = await baseElement.findByTestId('callout-test');
it("should render - important", async () => {
const baseElement = render(GoACallout, {
testid: "callout-test",
type: "important",
heading: "Complete",
});
const callout = await baseElement.findByTestId("callout-test");
const span = callout.firstElementChild;
const icon = span.firstElementChild;

expect(callout).toBeTruthy();
expect(span).toBeTruthy();
expect(span).toHaveClass("important");
expect(icon).toHaveAttribute("type", "alert-circle");
expect(callout).toContainHTML("Complete")
expect(callout).toContainHTML("Complete");
});

it('should render - information', async () => {
const baseElement = render(GoACallout, { testid: "callout-test", type: "information", heading: 'Complete' });
const callout = await baseElement.findByTestId('callout-test');
it("should render - information", async () => {
const baseElement = render(GoACallout, {
testid: "callout-test",
type: "information",
heading: "Complete",
});
const callout = await baseElement.findByTestId("callout-test");
const span = callout.firstElementChild;
const icon = span.firstElementChild;

expect(callout).toBeTruthy();
expect(span).toBeTruthy();
expect(span).toHaveClass("information");
expect(icon).toHaveAttribute("type", "information-circle");
expect(callout).toContainHTML("Complete")
expect(callout).toContainHTML("Complete");
});

it('should render - success', async () => {
const baseElement = render(GoACallout, { testid: "callout-test", type: "success", heading: 'Complete' });
const callout = await baseElement.findByTestId('callout-test');
it("should render - success", async () => {
const baseElement = render(GoACallout, {
testid: "callout-test",
type: "success",
heading: "Complete",
});
const callout = await baseElement.findByTestId("callout-test");
const span = callout.firstElementChild;
const icon = span.firstElementChild;

expect(callout).toBeTruthy();
expect(span).toBeTruthy();
expect(span).toHaveClass("success");
expect(icon).toHaveAttribute("type", "checkmark-circle");
expect(callout).toContainHTML("Complete")
expect(callout).toContainHTML("Complete");
});


it('should render - emergency', async () => {
const baseElement = render(GoACallout, { testid: "callout-test", type: "emergency", heading: 'Complete' });
const callout = await baseElement.findByTestId('callout-test');
it("should render - emergency", async () => {
const baseElement = render(GoACallout, {
testid: "callout-test",
type: "emergency",
heading: "Complete",
});
const callout = await baseElement.findByTestId("callout-test");
const span = callout.firstElementChild;
const icon = span.firstElementChild;

expect(callout).toBeTruthy();
expect(span).toBeTruthy();
expect(span).toHaveClass("emergency");
expect(icon).toHaveAttribute("type", "warning");
expect(callout).toContainHTML("Complete")
expect(callout).toContainHTML("Complete");
});

it('should render - the content', async () => {
const baseElement = render(GoACalloutWrapper, { type: "emergency", heading: 'Complete', content: 'This is the content' });
const callout = baseElement.container.querySelector('goa-callout');
expect(callout).toContainHTML("This is the content")
it("should render - the content", async () => {
const baseElement = render(GoACalloutWrapper, {
type: "emergency",
heading: "Complete",
content: "This is the content",
});
const callout = baseElement.container.querySelector("goa-callout");
expect(callout).toContainHTML("This is the content");
});

it('should render - without the heading', async () => {
const baseElement = render(GoACallout, { type: "emergency", testid: "testid" });
it("should render - without the heading", async () => {
const baseElement = render(GoACallout, {
type: "emergency",
testid: "testid",
});
const el = baseElement.queryByTestId("testid");
const heading = el.querySelector('h3');
const heading = el.querySelector("h3");
expect(heading).toBeNull();
});

it("should render - with size medium", async () => {
const baseElement = render(GoACallout, { type: "emergency", size: "medium", heading: "Heading", testid: "testid" });
const baseElement = render(GoACallout, {
type: "emergency",
size: "medium",
heading: "Heading",
testid: "testid",
});
const el = baseElement.queryByTestId("testid");

const heading = el.querySelector("h3.medium");
Expand All @@ -97,12 +128,15 @@ describe('GoACalloutComponent', () => {
});

it("should render - with max width", async () => {
const baseElement = render(GoACallout, { type: "emergency", maxwidth:"480px", testid: "testid" });
const baseElement = render(GoACallout, {
type: "emergency",
maxwidth: "480px",
testid: "testid",
});
const el = baseElement.queryByTestId("testid");
expect(el?.getAttribute("style")).toContain("max-width: 480px;");
});


describe("Margins", () => {
it(`should add the margin`, async () => {
const baseElement = render(GoACallout, {
Expand All @@ -122,4 +156,61 @@ describe('GoACalloutComponent', () => {
expect(callout).toHaveStyle("margin-left:var(--goa-space-xl)");
});
});

describe("live region", () => {
it("should have aria-live attribute set to off by default", async () => {
const baseElement = render(GoACallout, {
testid: "callout-test",
type: "information",
});
const callout = await baseElement.findByTestId("callout-test");

//expect(callout).not.toHaveAttribute("aria-live");
expect(callout).toHaveAttribute("aria-live", "off");
});

it("should set aria-live to off", async () => {
const baseElement = render(GoACallout, {
testid: "callout-test",
type: "important",
arialive: "off",
});
const callout = await baseElement.findByTestId("callout-test");

expect(callout).toHaveAttribute("aria-live", "off");
});

it("should set aria-live to polite", async () => {
const baseElement = render(GoACallout, {
testid: "callout-test",
type: "information",
arialive: "polite",
});
const callout = await baseElement.findByTestId("callout-test");

expect(callout).toHaveAttribute("aria-live", "polite");
});

it("should set aria-live to assertive", async () => {
const baseElement = render(GoACallout, {
testid: "callout-test",
type: "emergency",
arialive: "assertive",
});
const callout = await baseElement.findByTestId("callout-test");

expect(callout).toHaveAttribute("aria-live", "assertive");
});

it("should set aria-live attribute to empty when an empty string is provided", async () => {
const baseElement = render(GoACallout, {
testid: "callout-test",
type: "success",
arialive: "",
});
const callout = await baseElement.findByTestId("callout-test");

expect(callout).toHaveAttribute("aria-live", "");
});
});
});
Loading

0 comments on commit 8822d39

Please sign in to comment.