Repository: Sage/carbon (ts)

Issue:
Toast - cannot compute accessible name during entrance animation sequence
### Description

An axe warning is triggered during the entrance animation of the `Toast` component: **"All page content should be contained by landmarks"**.

The warning occurs because the outer `div[data-role='toast-wrapper']` attempts to compute its accessible name from the text of the referenced elements, which have not yet been rendered during the animation. This causes accessibility tools to flag the issue as the required content is missing on the page temporarily.

Example markup during the middle of the entrance animation sequence:

```html
<div
  data-role="toast-wrapper"
  role="region"
  <!--👇 these referenced elements don't exist yet  -->
  aria-labelledby="ecc926f3-6d0f-0e8d-6ea8-101f8963e781 a69e8c1c-72ba-11f5-8d06-a825876cff01" 
  class="sc-cBrjTV bQtboq"
>
  <div>
    <div class="sc-jGxEUC cYDZmN toast-enter" data-component="toast" id="toast-default">
        <!-- The referenced elements will be rendered here once entrance animation is finished -->
    </div>
  </div>
</div>
```

### Reproduction

https://carbon.sage.com/iframe.html?args=&id=toast--default&viewMode=story

### Steps to reproduce

1. Open linked `Toast` story
2. Toggle toast preview to be on
3. Run axe during the middle of entrance animation - observe warning

### JIRA ticket numbers (Sage only)

_No response_

### Suggested solution

Avoid setting `aria-labelledby` to the inner content when it isn't visible 

### Carbon version

142.5.0

### Design tokens version

_No response_

### Relevant browsers

Chrome

### Relevant OSs

MacOS

### Additional context

_No response_

### Confidentiality

- [X] I confirm there is no confidential or commercially sensitive information included.

Pull request:
fix(toast): ensure closed toasts do not trigger axe warnings
fix #6923

### Proposed behaviour

<!--
A clear and concise description of what changes this PR makes. If applicable, include any UI screenshots to help explain your request. If you are a Sage contributor, please DO NOT share any commercially sensitive information, such as UI screenshots or code from Sage products.
-->
Set "aria-hidden" on Toast region while its closed. 
Only define the "aria-labelledby" when the Toast is open. 

### Current behaviour

<!--
A clear and concise description of the behaviour before this change. If applicable, include any UI screenshots to help explain your request. If you are a Sage contributor, please DO NOT share any commercially sensitive information, such as UI screenshots or code from Sage products.
-->
When a Toast's content is only defined on open, its accessible name cannot be computed and is "empty" while closed. This causes an axe issue when more than one Toast is rendered on a page with undefined content as their accessible name is not "unique".

![image](https://github.com/user-attachments/assets/b6e84bad-1b01-41f4-a4e7-f876ecd927e5)

### Checklist

<!-- Each PR should include the following -->

- [x] Commits follow our style guide
- [x] Related issues linked in commit messages if required
- [ ] Screenshots are included in the PR if useful
- [ ] All themes are supported if required
- [x] Unit tests added or updated if required
- [x] Playwright automation tests added or updated if required
- [ ] Storybook added or updated if required
- [ ] Translations added or updated (including creating or amending translation keys table in storybook) if required
- [ ] Typescript `d.ts` file added or updated if required
- [ ] Related docs have been updated if required

#### QA

- [ ] Tested in provided StackBlitz sandbox/Storybook
- [ ] Add new Playwright test coverage if required
- [ ] Carbon implementation matches Design System/designs
- [ ] UI Tests GitHub check reviewed if required

### Additional context

<!-- Add any other context or links about the pull request here. -->

### Testing instructions

<!--
How can a reviewer test this PR?

If this PR addresses a pre-existing bug, please include a link to a sandbox that reproduces the original bug. A starter template has been provided to help you do this:
<https://stackblitz.com/fork/github/Parsium/carbon-starter>
-->

[Sandbox demonstrating issue](https://stackblitz.com/edit/parsium-carbon-starter-slnd56?file=src%2FApp.tsx)
- Run axe scan with both Toasts closed. 
- See issue shown in screenshot. 

Screen reader behaviour should not change with fix. 


Patch:
diff --git a/src/components/toast/toast.component.tsx b/src/components/toast/toast.component.tsx
index 93dcfa894..8afe9834e 100644
--- a/src/components/toast/toast.component.tsx
+++ b/src/components/toast/toast.component.tsx
@@ -111,6 +111,9 @@ export const Toast = React.forwardRef<HTMLDivElement, ToastProps>(
     const focusedElementBeforeOpening = useRef<HTMLElement | null>(null);
 
     const [tabIndex, setTabIndex] = useState<number | undefined>(0);
+    const ariaLabelledBy = `${!isNotice && toastIconId.current} ${
+      toastContentId.current
+    }`;
 
     let refToPass = toastRef;
     if (ref && typeof ref === "object" && "current" in ref) {
@@ -266,9 +269,8 @@ export const Toast = React.forwardRef<HTMLDivElement, ToastProps>(
           isNotice={isNotice}
           data-role="toast-wrapper"
           role="region"
-          aria-labelledby={`${!isNotice && toastIconId.current} ${
-            toastContentId.current
-          }`}
+          aria-hidden={!open}
+          aria-labelledby={open ? ariaLabelledBy : undefined}
         >
           <TransitionGroup>{renderToastContent()}</TransitionGroup>
         </ToastWrapper>
diff --git a/src/components/toast/toast.pw.tsx b/src/components/toast/toast.pw.tsx
index 1b66e81be..9c2f75ac5 100644
--- a/src/components/toast/toast.pw.tsx
+++ b/src/components/toast/toast.pw.tsx
@@ -5,6 +5,7 @@ import { ToastProps } from ".";
 import {
   ToastComponent,
   ToastWhenOtherModalRenders,
+  ToastWithConditionalContent,
   ToastAllAlign,
 } from "./components.test-pw";
 import {
@@ -320,4 +321,19 @@ test.describe("Accessibility tests for Toast component", () => {
 
     await checkAccessibility(page);
   });
+
+  test("passes accessibility checks when multiple Toasts only have content when opened", async ({
+    mount,
+    page,
+  }) => {
+    await mount(<ToastWithConditionalContent />);
+
+    // check accessibility when both toasts are closed and have undefined content
+    await checkAccessibility(page);
+
+    await button(page).nth(0).click();
+
+    // check accessibility when first toast is open and has defined content
+    await checkAccessibility(page, toastComponent(page));
+  });
 });


Test patch:
diff --git a/src/components/toast/components.test-pw.tsx b/src/components/toast/components.test-pw.tsx
index c7bde0458..78cf2b15f 100644
--- a/src/components/toast/components.test-pw.tsx
+++ b/src/components/toast/components.test-pw.tsx
@@ -53,6 +53,26 @@ export const ToastWhenOtherModalRenders = ({
   );
 };
 
+export const ToastWithConditionalContent = ({
+  ...props
+}: Partial<ToastProps>) => {
+  const [isOpen1, setIsOpen1] = useState(false);
+  const [isOpen2, setIsOpen2] = useState(false);
+  return (
+    <>
+      <Button onClick={() => setIsOpen1(!isOpen1)}>Open Toast 1</Button>
+      <Button onClick={() => setIsOpen2(!isOpen2)}>Open Toast 2</Button>
+
+      <Toast open={isOpen1} {...props}>
+        {isOpen1 && "Toast 1"}
+      </Toast>
+      <Toast open={isOpen2} {...props}>
+        {isOpen2 && "Toast 2"}
+      </Toast>
+    </>
+  );
+};
+
 export const ToastAllAlign = ({ ...props }: Partial<ToastProps>) => {
   return (
     <>
diff --git a/src/components/toast/toast-test.stories.tsx b/src/components/toast/toast-test.stories.tsx
index 482f03399..bb31d2966 100644
--- a/src/components/toast/toast-test.stories.tsx
+++ b/src/components/toast/toast-test.stories.tsx
@@ -8,7 +8,7 @@ import Dialog from "../dialog";
 
 export default {
   title: "Toast/Test",
-  includeStories: ["Default", "Visual", "ToastWhenOtherModalRenders"],
+  excludeStories: ["TopAndBottom"],
   parameters: {
     info: { disable: true },
     chromatic: {
@@ -368,3 +368,23 @@ export const ToastWhenOtherModalRenders = () => {
     </>
   );
 };
+
+export const ToastWithConditionalContent = ({
+  ...props
+}: Partial<ToastProps>) => {
+  const [isOpen1, setIsOpen1] = useState(false);
+  const [isOpen2, setIsOpen2] = useState(false);
+  return (
+    <>
+      <Button onClick={() => setIsOpen1(!isOpen1)}>Open Toast 1</Button>
+      <Button onClick={() => setIsOpen2(!isOpen2)}>Open Toast 2</Button>
+
+      <Toast open={isOpen1} {...props}>
+        {isOpen1 && "Toast 1"}
+      </Toast>
+      <Toast open={isOpen2} {...props}>
+        {isOpen2 && "Toast 2"}
+      </Toast>
+    </>
+  );
+};
diff --git a/src/components/toast/toast.test.tsx b/src/components/toast/toast.test.tsx
index 9794f6be2..6c9dfbaff 100644
--- a/src/components/toast/toast.test.tsx
+++ b/src/components/toast/toast.test.tsx
@@ -1,13 +1,9 @@
 import React from "react";
 import { render, screen } from "@testing-library/react";
 import userEvent from "@testing-library/user-event";
-
-import guid from "../../__internal__/utils/helpers/guid";
 import Toast, { ToastProps } from "./toast.component";
 import ModalManager from "../modal/__internal__/modal-manager";
 
-jest.mock("../../__internal__/utils/helpers/guid");
-
 const MockToast = ({
   open = false,
   onDismiss,
@@ -47,41 +43,39 @@ const MockToast = ({
   );
 };
 
-describe("Toast component", () => {
-  (guid as jest.MockedFunction<typeof guid>).mockImplementation(
-    () => "guid-12345"
-  );
+test("should be added to modal manager when it mounts", () => {
+  jest.spyOn(ModalManager, "addModal");
+  render(<Toast onDismiss={() => {}}>foobar</Toast>);
 
-  beforeEach(() => {
-    jest.useFakeTimers();
-  });
+  const toast = screen.getByTestId("toast-wrapper");
 
-  afterEach(() => {
-    jest.useRealTimers();
-  });
+  expect(ModalManager.addModal).toHaveBeenCalledWith(toast, undefined, true);
+});
 
-  it("should be added to modal manager when it mounts", () => {
-    jest.spyOn(ModalManager, "addModal");
-    render(<Toast onDismiss={() => {}}>foobar</Toast>);
+test("should be removed from modal manager when it unmounts", () => {
+  const removeModalSpy = jest.spyOn(ModalManager, "removeModal");
+  removeModalSpy.mockClear();
+  const { unmount } = render(<Toast onDismiss={() => {}}>foobar</Toast>);
 
-    const toast = screen.getByTestId("toast-wrapper");
-    expect(ModalManager.addModal).toHaveBeenCalledWith(toast, undefined, true);
-  });
+  const toast = screen.getByTestId("toast-wrapper");
+  unmount();
 
-  it("should be removed from modal manager when it unmounts", () => {
-    const removeModalSpy = jest.spyOn(ModalManager, "removeModal");
-    removeModalSpy.mockClear();
-    const { unmount } = render(<Toast onDismiss={() => {}}>foobar</Toast>);
+  expect(ModalManager.removeModal).toHaveBeenCalledWith(toast, true);
+});
 
-    const toast = screen.getByTestId("toast-wrapper");
-    unmount();
-    expect(ModalManager.removeModal).toHaveBeenCalledWith(toast, true);
-  });
+test("should not unmount the toast wrapper when the closed", () => {
+  render(<MockToast open={false} />);
+
+  expect(screen.getByTestId("toast-wrapper")).toBeInTheDocument();
+});
 
-  it("should not unmount the toast wrapper when the closed", () => {
-    render(<MockToast open={false} />);
+describe("Event tests", () => {
+  beforeEach(() => {
+    jest.useFakeTimers();
+  });
 
-    expect(screen.getByTestId("toast-wrapper")).toBeInTheDocument();
+  afterEach(() => {
+    jest.useRealTimers();
   });
 
   it("should not call `onDismiss` when 'Escape' key pressed and `open` prop is false", async () => {
@@ -89,7 +83,7 @@ describe("Toast component", () => {
     const onDismissMock = jest.fn();
     render(<MockToast open onDismiss={onDismissMock} />);
 
-    const button = await screen.findByRole("button", { name: "Show toast" });
+    const button = screen.getByRole("button", { name: "Show toast" });
     await user.click(button);
     await user.keyboard("{Escape}");
 
@@ -187,90 +181,6 @@ describe("Toast component", () => {
     expect(onDismissMock).not.toHaveBeenCalled();
   });
 
-  it("should not render close icon when no `onDismiss` prop is set", () => {
-    render(<Toast open>foobar</Toast>);
-
-    const closeButton = screen.queryByRole("button", { name: "Close" });
-
-    expect(closeButton).not.toBeInTheDocument();
-  });
-
-  it("should render close icon when `onDismiss` prop is set", () => {
-    render(
-      <Toast open onDismiss={() => {}}>
-        foobar
-      </Toast>
-    );
-
-    const closeButton = screen.getByRole("button", { name: "Close" });
-
-    expect(closeButton).toBeInTheDocument();
-  });
-
-  it("should render with any custom classes passed via the `className` prop", () => {
-    render(
-      <Toast open className="exampleClass" data-role="toast">
-        foobar
-      </Toast>
-    );
-
-    expect(screen.getByTestId("toast")).toHaveClass("exampleClass");
-  });
-
-  it("should render with correct custom ids passed via `id` prop", () => {
-    render(
-      <Toast open id="exampleId" data-role="toast">
-        foobar
-      </Toast>
-    );
-
-    expect(screen.getByTestId("toast")).toHaveAttribute("id", "exampleId");
-  });
-
-  it("should render any child content passed via the `children` prop", () => {
-    render(
-      <Toast open data-role="toast">
-        <span>foobar</span>
-      </Toast>
-    );
-
-    expect(screen.getByText("foobar")).toBeInTheDocument();
-  });
-
-  it("should render with correct `data-` attributes", () => {
-    render(
-      <Toast open data-element="toast-element" data-role="toast-role">
-        foobar
-      </Toast>
-    );
-
-    const toast = screen.getByTestId("toast-role");
-
-    expect(toast).toHaveAttribute("data-component", "toast");
-    expect(toast).toHaveAttribute("data-element", "toast-element");
-  });
-
-  it("should allow custom data props to be passed to close button to be passed via `closeButtonDataProps`", () => {
-    render(
-      <Toast
-        open
-        onDismiss={() => {}}
-        closeButtonDataProps={{
-          "data-element": "close-element",
-          "data-role": "close-role",
-        }}
-      >
-        foobar
-      </Toast>
-    );
-
-    const closeButton = screen.getByRole("button", { name: "Close" });
-
-    expect(closeButton).toHaveAttribute("data-component", "close");
-    expect(closeButton).toHaveAttribute("data-element", "close-element");
-    expect(closeButton).toHaveAttribute("data-role", "close-role");
-  });
-
   it("should auto focus the toast wrapper element when initially opened", () => {
     render(
       <Toast open data-role="toast">
@@ -286,17 +196,15 @@ describe("Toast component", () => {
 
   it("should not auto focus the toast wrapper element when initially opened if `disableAutoFocus` prop is set", () => {
     render(
-      <Toast open data-role="toast" disableAutoFocus>
+      <Toast open disableAutoFocus>
         foobar
       </Toast>
     );
 
-    const toast = screen.getByTestId("toast");
-
-    expect(toast).not.toHaveAttribute("tabIndex");
-
     jest.runAllTimers();
+    const toast = screen.getByRole("region");
 
+    expect(toast).not.toHaveAttribute("tabIndex");
     expect(toast).not.toHaveFocus();
   });
 
@@ -321,11 +229,12 @@ describe("Toast component", () => {
     const user = userEvent.setup({ advanceTimers: jest.advanceTimersByTime });
     render(<MockToast open={false} addInternalOnDismiss />);
 
-    const button = await screen.findByRole("button", { name: "Show toast" });
+    const button = screen.getByRole("button", { name: "Show toast" });
     await user.click(button);
     jest.runAllTimers();
+
     const toast = await screen.findByTestId("toast");
-    const closeButton = await screen.findByRole("button", { name: "Close" });
+    const closeButton = screen.getByRole("button", { name: "Close" });
 
     expect(toast).toHaveFocus();
 
@@ -339,12 +248,14 @@ describe("Toast component", () => {
     const user = userEvent.setup({ advanceTimers: jest.advanceTimersByTime });
     render(<MockToast open={false} addInternalOnDismiss />);
 
-    const button = await screen.findByRole("button", { name: "Show toast" });
+    const button = screen.getByRole("button", { name: "Show toast" });
     await user.click(button);
     jest.runAllTimers();
+
+    const toast = await screen.findByTestId("toast");
     const closeButton = screen.getByRole("button", { name: "Close" });
 
-    expect(await screen.findByTestId("toast")).toHaveFocus();
+    expect(toast).toHaveFocus();
 
     await user.click(closeButton);
     jest.runAllTimers();
@@ -361,292 +272,358 @@ describe("Toast component", () => {
     const user = userEvent.setup({ advanceTimers: jest.advanceTimersByTime });
     render(<MockToast open={false} addInternalOnDismiss disableAutoFocus />);
 
-    const button = await screen.findByRole("button", { name: "Show toast" });
+    const button = screen.getByRole("button", { name: "Show toast" });
     await user.click(button);
     jest.runAllTimers();
+
     const closeButton = await screen.findByRole("button", { name: "Close" });
     await user.click(closeButton);
     jest.runAllTimers();
 
     expect(button).not.toHaveFocus();
   });
+});
 
-  it("should render content container with correct expected styling when `maxWidth` is set", () => {
-    render(
-      <Toast maxWidth="200px" data-role="toast">
-        Child
-      </Toast>
-    );
+test("should not render close button when no `onDismiss` prop is set", () => {
+  render(<Toast open>foobar</Toast>);
 
-    expect(screen.getByTestId("toast")).toHaveStyle({ maxWidth: "200px" });
-  });
+  const closeButton = screen.queryByRole("button", { name: "Close" });
 
-  it("should render with correct styling when `variant` prop is set to 'notice' and no `onDismiss` prop set", () => {
-    render(
-      <Toast open variant="notice" data-role="toast">
-        foobar
-      </Toast>
-    );
+  expect(closeButton).not.toBeInTheDocument();
+});
 
-    const toast = screen.getByTestId("toast");
+test("should render close button when `onDismiss` prop is set", () => {
+  render(
+    <Toast open onDismiss={() => {}}>
+      foobar
+    </Toast>
+  );
 
-    expect(screen.getByTestId("toast-wrapper")).toHaveStyle({
-      display: "block",
-    });
-    expect(toast).toHaveStyle({
-      "background-color": "var(--colorsUtilityMajor400)",
-      border: "none",
-      color: "var(--colorsSemanticNeutralYang100)",
-      "margin-right": "0",
-      "max-width": "100%",
-    });
-    expect(screen.getByTestId("toast-content")).toHaveStyle({
-      display: "flex",
-      "align-items": "center",
-      padding: "11px 40px",
-    });
-    expect(screen.queryByTestId("toast-type-icon")).not.toBeInTheDocument();
-  });
-
-  it("should render with correct styling when `variant` prop is set to 'notice' and `onDismiss` prop set", () => {
-    render(
-      <Toast open variant="notice" data-role="toast" onDismiss={() => {}}>
-        foobar
-      </Toast>
-    );
+  const closeButton = screen.getByRole("button", { name: "Close" });
 
-    expect(screen.getByTestId("toast-content")).toHaveStyle({
-      display: "flex",
-      "align-items": "center",
-      padding: "11px 88px 11px 40px",
-    });
-    expect(screen.getByRole("button", { name: "Close" })).toHaveStyle(
-      "right: 55px"
-    );
-  });
+  expect(closeButton).toBeVisible();
+});
 
-  it("should render with correct styling when `variant` prop is set to 'notice' and `alignY` prop is set to 'top'", () => {
-    render(
-      <Toast
-        open
-        variant="notice"
-        alignY="top"
-        data-role="toast"
-        onDismiss={() => {}}
-      >
-        foobar
-      </Toast>
-    );
+test("should render with any custom classes passed via the `className` prop", () => {
+  render(
+    <Toast open data-role="toast" className="exampleClass">
+      foobar
+    </Toast>
+  );
 
-    const toast = screen.getByTestId("toast");
+  expect(screen.getByTestId("toast")).toHaveClass("exampleClass");
+});
 
-    expect(toast).toHaveStyle({
-      margin: "0px 0px 0px auto",
-    });
-  });
+test("should render with provided custom id passed via `id` prop", () => {
+  render(
+    <Toast open data-role="toast" id="exampleId">
+      foobar
+    </Toast>
+  );
 
-  it("should render with correct styling when `variant` prop is set to 'notice' and `alignY` prop is set to 'bottom'", () => {
-    render(
-      <Toast
-        open
-        variant="notice"
-        alignY="bottom"
-        data-role="toast"
-        onDismiss={() => {}}
-      >
-        foobar
-      </Toast>
-    );
+  expect(screen.getByTestId("toast")).toHaveAttribute("id", "exampleId");
+});
 
-    const toast = screen.getByTestId("toast");
+test("should render any child content passed via the `children` prop", () => {
+  render(
+    <Toast open>
+      <span>foobar</span>
+    </Toast>
+  );
 
-    expect(toast).toHaveStyle({
-      margin: "0px 0px 0px auto",
-    });
-  });
+  expect(screen.getByText("foobar")).toBeVisible();
+});
 
-  it("should render the expected icon when `variant` prop is set to 'neutral'", () => {
-    render(
-      <Toast open variant="neutral">
-        foobar
-      </Toast>
-    );
+test("should render with provided `data-` attributes", () => {
+  render(
+    <Toast open data-element="toast-element" data-role="toast-role">
+      foobar
+    </Toast>
+  );
 
-    expect(screen.getByTestId("icon")).toHaveAttribute("type", "info");
-  });
+  const toast = screen.getByTestId("toast-role");
+  expect(toast).toHaveAttribute("data-element", "toast-element");
+});
 
-  it("should render the expected icon when `variant` prop is set to 'success'", () => {
-    render(
-      <Toast open variant="success">
-        foobar
-      </Toast>
-    );
+test("should render with accessible name when Toast is open", () => {
+  render(<Toast open>foobar</Toast>);
 
-    expect(screen.getByTestId("icon")).toHaveAttribute("type", "tick_circle");
-  });
+  const toast = screen.getByRole("region");
 
-  it("should render the expected icon when `variant` prop is set to 'warning'", () => {
-    render(
-      <Toast open variant="warning">
-        foobar
-      </Toast>
-    );
+  expect(toast).toHaveAccessibleName("Success foobar");
+});
+
+test("should not render an accessible region when Toast is closed", () => {
+  render(<Toast open={false}>foobar</Toast>);
+
+  const toast = screen.queryByRole("region");
+
+  expect(toast).not.toBeInTheDocument();
+});
 
-    expect(screen.getByTestId("icon")).toHaveAttribute("type", "warning");
+test("should allow custom data props to be passed to close button to be passed via `closeButtonDataProps`", () => {
+  render(
+    <Toast
+      open
+      onDismiss={() => {}}
+      closeButtonDataProps={{
+        "data-element": "close-element",
+        "data-role": "close-role",
+      }}
+    >
+      foobar
+    </Toast>
+  );
+
+  const closeButton = screen.getByRole("button", { name: "Close" });
+
+  expect(closeButton).toHaveAttribute("data-element", "close-element");
+  expect(closeButton).toHaveAttribute("data-role", "close-role");
+});
+
+test("should render content container with correct expected styling when `maxWidth` is set", () => {
+  render(
+    <Toast maxWidth="200px" data-role="toast">
+      Child
+    </Toast>
+  );
+
+  expect(screen.getByTestId("toast")).toHaveStyle({ maxWidth: "200px" });
+});
+
+test("should render with correct styling when `variant` prop is set to 'notice' and `onDismiss` is not set", () => {
+  render(
+    <Toast open variant="notice" data-role="toast">
+      foobar
+    </Toast>
+  );
+
+  const toast = screen.getByTestId("toast");
+
+  expect(screen.getByTestId("toast-wrapper")).toHaveStyle({
+    display: "block",
   });
 
-  it("should render the expected icon when `variant` prop is set to 'error'", () => {
-    render(
-      <Toast open variant="error">
-        foobar
-      </Toast>
-    );
+  expect(toast).toHaveStyle({
+    border: "none",
+    marginRight: "0",
+    maxWidth: "100%",
+  });
+  expect(toast).toHaveStyleRule(
+    "background-color",
+    "var(--colorsUtilityMajor400)"
+  );
+  expect(toast).toHaveStyleRule("color", "var(--colorsSemanticNeutralYang100)");
 
-    expect(screen.getByTestId("icon")).toHaveAttribute("type", "error");
+  expect(screen.getByTestId("toast-content")).toHaveStyle({
+    display: "flex",
+    "align-items": "center",
+    padding: "11px 40px",
   });
 
-  it("should render the expected icon when `variant` prop is set to 'info'", () => {
-    render(
-      <Toast open variant="info">
-        foobar
-      </Toast>
-    );
+  expect(screen.queryByTestId("toast-type-icon")).not.toBeInTheDocument();
+});
 
-    expect(screen.getByTestId("icon")).toHaveAttribute("type", "info");
+test("should render with correct styling when `variant` prop is set to 'notice' and `onDismiss` is set", () => {
+  render(
+    <Toast open variant="notice" onDismiss={() => {}}>
+      foobar
+    </Toast>
+  );
+
+  expect(screen.getByTestId("toast-content")).toHaveStyle({
+    display: "flex",
+    alignItems: "center",
+    padding: "11px 88px 11px 40px",
   });
 
-  it("should render the expected icon when `variant` prop is set to 'notification'", () => {
-    render(
-      <Toast open variant="notification">
-        foobar
-      </Toast>
-    );
+  expect(screen.getByRole("button", { name: "Close" })).toHaveStyle({
+    right: "55px",
+  });
+});
+
+test("should render with correct styling when `variant` prop is set to 'notice' and `alignY` prop is set to 'top'", () => {
+  render(
+    <Toast
+      open
+      variant="notice"
+      alignY="top"
+      data-role="toast"
+      onDismiss={() => {}}
+    >
+      foobar
+    </Toast>
+  );
+
+  const toast = screen.getByTestId("toast");
 
-    expect(screen.getByTestId("icon")).toHaveAttribute("type", "alert");
+  expect(toast).toHaveStyle({
+    margin: "0px 0px 0px auto",
   });
+});
+
+test("should render with correct styling when `variant` prop is set to 'notice' and `alignY` prop is set to 'bottom'", () => {
+  render(
+    <Toast
+      open
+      variant="notice"
+      alignY="bottom"
+      data-role="toast"
+      onDismiss={() => {}}
+    >
+      foobar
+    </Toast>
+  );
+
+  const toast = screen.getByTestId("toast");
 
-  it("should not throw when ref is a function", () => {
-    expect(() => {
-      render(
-        <Toast onDismiss={() => {}} ref={(ref) => ref}>
-          foobar
-        </Toast>
-      );
-    }).not.toThrow();
+  expect(toast).toHaveStyle({
+    margin: "0px 0px 0px auto",
   });
+});
 
-  it("should pass ref to the wrapper element", () => {
-    const ref = { current: null };
+test.each<[ToastProps["variant"], string]>([
+  ["neutral", "info"],
+  ["success", "tick_circle"],
+  ["warning", "warning"],
+  ["error", "error"],
+  ["info", "info"],
+  ["notification", "alert"],
+])(
+  "should render the expected icon when `variant` prop is set to '%s'",
+  (variant, iconType) => {
     render(
-      <Toast onDismiss={() => {}} ref={ref}>
+      <Toast open variant={variant}>
         foobar
       </Toast>
     );
 
-    expect(ref.current).toBe(screen.getByTestId("toast-wrapper"));
-  });
+    expect(screen.getByTestId("icon")).toHaveAttribute("type", iconType);
+  }
+);
 
-  it("should render with expected styling when `align` prop is 'right'", () => {
+test("should not throw when ref is a function", () => {
+  expect(() => {
     render(
-      <Toast open align="right" data-role="toast">
+      <Toast onDismiss={() => {}} ref={(ref) => ref}>
         foobar
       </Toast>
     );
+  }).not.toThrow();
+});
+
+test("should pass ref to the wrapper element", () => {
+  const ref = { current: null };
+  render(
+    <Toast onDismiss={() => {}} ref={ref}>
+      foobar
+    </Toast>
+  );
+
+  expect(ref.current).toBe(screen.getByTestId("toast-wrapper"));
+});
 
-    expect(screen.getByTestId("toast-wrapper")).toHaveStyle({
-      "justify-content": "right",
-    });
-    expect(screen.getByTestId("toast")).toHaveStyle({
-      "margin-right": "auto",
-      "margin-left": "30px",
-    });
+test("should render with expected styling when `align` prop is 'right'", () => {
+  render(
+    <Toast open align="right" data-role="toast">
+      foobar
+    </Toast>
+  );
+
+  expect(screen.getByRole("region")).toHaveStyle({
+    "justify-content": "right",
   });
 
-  it("should render with expected styling when `align` prop is 'center'", () => {
-    render(
-      <Toast open align="center" data-role="toast">
-        foobar
-      </Toast>
-    );
+  expect(screen.getByTestId("toast")).toHaveStyle({
+    "margin-right": "auto",
+    "margin-left": "30px",
+  });
+});
 
-    expect(screen.getByTestId("toast-wrapper")).toHaveStyle({
-      "justify-content": "center",
-    });
-    expect(screen.getByTestId("toast")).toHaveStyle({
-      "margin-right": "auto",
-      "margin-left": "auto",
-    });
+test("should render with expected styling when `align` prop is 'center'", () => {
+  render(
+    <Toast open align="center" data-role="toast">
+      foobar
+    </Toast>
+  );
+
+  expect(screen.getByRole("region")).toHaveStyle({
+    "justify-content": "center",
   });
+  expect(screen.getByTestId("toast")).toHaveStyle({
+    "margin-right": "auto",
+    "margin-left": "auto",
+  });
+});
 
-  it("should render with expected styling when `align` prop is 'left'", () => {
-    render(
-      <Toast open align="left" data-role="toast">
-        foobar
-      </Toast>
-    );
+test("should render with expected styling when `align` prop is 'left'", () => {
+  render(
+    <Toast open align="left" data-role="toast">
+      foobar
+    </Toast>
+  );
 
-    expect(screen.getByTestId("toast-wrapper")).toHaveStyle({
-      "justify-content": "left",
-    });
-    expect(screen.getByTestId("toast")).toHaveStyle({
-      "margin-right": "30px",
-      "margin-left": "auto",
-    });
+  expect(screen.getByRole("region")).toHaveStyle({
+    "justify-content": "left",
   });
+  expect(screen.getByTestId("toast")).toHaveStyle({
+    "margin-right": "30px",
+    "margin-left": "auto",
+  });
+});
 
-  it("should render with expected styling when `alignY` prop is set to 'top'", () => {
-    render(
-      <Toast alignY="top" data-role="toast">
-        foobar
-      </Toast>
-    );
+test("should render with expected styling when `alignY` prop is set to 'top'", () => {
+  render(
+    <Toast alignY="top" data-role="toast">
+      foobar
+    </Toast>
+  );
 
-    const toast = screen.getByTestId("toast");
+  const toast = screen.getByTestId("toast");
 
-    expect(toast).toHaveStyle({
-      "margin-top": "30px",
-      "margin-bottom": "0",
-    });
+  expect(toast).toHaveStyle({
+    "margin-top": "30px",
+    "margin-bottom": "0",
   });
+});
 
-  it("should render with expected styling when `alignY` prop is set to 'bottom'", () => {
-    render(
-      <Toast alignY="bottom" data-role="toast">
-        foobar
-      </Toast>
-    );
+test("should render with expected styling when `alignY` prop is set to 'bottom'", () => {
+  render(
+    <Toast alignY="bottom" data-role="toast">
+      foobar
+    </Toast>
+  );
 
-    const toast = screen.getByTestId("toast");
+  const toast = screen.getByTestId("toast");
 
-    expect(toast).toHaveStyle({
-      "margin-top": "0",
-      "margin-bottom": "30px",
-    });
+  expect(toast).toHaveStyle({
+    "margin-top": "0",
+    "margin-bottom": "30px",
   });
+});
 
-  it("should render with expected styling when `alignY` prop is 'center' and `align` prop is 'left'", () => {
-    render(
-      <Toast alignY="center" align="left" data-role="toast">
-        foobar
-      </Toast>
-    );
+test("should render with expected styling when `alignY` prop is 'center' and `align` prop is 'left'", () => {
+  render(
+    <Toast alignY="center" align="left" data-role="toast">
+      foobar
+    </Toast>
+  );
 
-    expect(screen.getByTestId("carbon-portal-exit")).toHaveStyle({
-      top: "50%",
-      transform: "translate(50%,-50%)",
-    });
+  expect(screen.getByTestId("carbon-portal-exit")).toHaveStyle({
+    top: "50%",
+    transform: "translate(50%,-50%)",
   });
+});
 
-  it("should render with expected styling when `alignY` prop is 'center' and `align` prop is not 'left'", () => {
-    render(
-      <Toast alignY="center" data-role="toast">
-        foobar
-      </Toast>
-    );
+test("should render with expected styling when `alignY` prop is 'center' and `align` prop is not 'left'", () => {
+  render(
+    <Toast alignY="center" data-role="toast">
+      foobar
+    </Toast>
+  );
 
-    expect(screen.getByTestId("carbon-portal-exit")).toHaveStyle({
-      top: "50%",
-      transform: "translate(-50%,-50%)",
-    });
+  expect(screen.getByTestId("carbon-portal-exit")).toHaveStyle({
+    top: "50%",
+    transform: "translate(-50%,-50%)",
   });
 });