chakra-ui icon indicating copy to clipboard operation
chakra-ui copied to clipboard

Toasts trolling me in tests

Open timkindberg opened this issue 4 years ago • 24 comments

🐛 Bug report

Toasts cause headaches during testing.

  1. There is no easy way to clear all toasts without any exit animation. They always linger around, messing with dom element selection. You have to wait 401ms for all toasts to be gone. Is there a way to disable the animation in tests?

  2. Toast renders two alerts, one visible one in the toast manager, another hidden one meant for accessibility rendered into a role=status element. This makes selection difficult because it's hard to select by role of 'alert', or by the text contents, because there is always two elements found.

  3. Toast Manager renders persistent dom elements into every test and adds to cognitive overload while reviewing snapshots or screen.debug output.

<div id="chakra-toast-portal"><ul id="chakra-toast-manager-top" style="position: fixed; z-index: 5500; pointer-events: none; display: flex; flex-direction: column; margin: 0px auto; top: 0px; right: 0px; left: 0px;"></ul><ul id="chakra-toast-manager-top-left" style="position: fixed; z-index: 5500; pointer-events: none; display: flex; flex-direction: column; top: 0px; left: 0px;"></ul><ul id="chakra-toast-manager-top-right" style="position: fixed; z-index: 5500; pointer-events: none; display: flex; flex-direction: column; top: 0px; right: 0px;"></ul><ul id="chakra-toast-manager-bottom-left" style="position: fixed; z-index: 5500; pointer-events: none; display: flex; flex-direction: column; bottom: 0px; left: 0px;"></ul><ul id="chakra-toast-manager-bottom" style="position: fixed; z-index: 5500; pointer-events: none; display: flex; flex-direction: column; margin: 0px auto; bottom: 0px; right: 0px; left: 0px;"></ul><ul id="chakra-toast-manager-bottom-right" style="position: fixed; z-index: 5500; pointer-events: none; display: flex; flex-direction: column; bottom: 0px; right: 0px;"></ul></div>

💥 Steps to reproduce

Install Chakra and react-testing-library.

  1. Show a toast.
  2. Now try to select alert via RTL

💻 Link to reproduction

This shows the double alert causing selection issues. https://codesandbox.io/s/chakra-toast-renders-two-alerts-mlhyr

🧭 Possible Solution

  1. Add an option to remove all toasts outside of a component (for example in an afterEach) and disable animations while doing so. I know there is removeAll, is this callable outside of the useToast hook?
  2. Somehow hide one of the alerts from the accessibility tree? Maybe we can hide the visible alert, since the "hidden" one is really the one meant to be seen by screenreaders.
  3. Do not render the Toast Manager divs unless a toast is present.

🌍 System information

Software Version(s)
Chakra UI 1.0.3
Browser Chrome
Operating System Mac

timkindberg avatar Jan 07 '21 02:01 timkindberg

I can confirm all of that, its really annoying T_T

cloud-walker avatar Jan 18 '21 09:01 cloud-walker

Hi! This issue hasn't seen any activity recently. We close inactive issues after 35 days to manage the volume of issues we receive. If we missed this issue or you want to keep it open, please reply here. That will reset the timer and allow more time for this issue to be addressed before it is closed.

stale[bot] avatar Feb 21 '21 23:02 stale[bot]

Please keep this open. It’s still an issue.

It would be great to have some testing guidance in the documentation if nothing else.

avaragado avatar Feb 22 '21 07:02 avaragado

Anytime I render any component using the jest + react testing library, the toast manager is also included in that render. Is there any workaround for this problem?
For example, when I render a ChakraButton, I receive -

<body>
      <div
        id="chakra-toast-portal"
      >
        <ul
          id="chakra-toast-manager-top"
          style="position: fixed; z-index: 5500; pointer-events: none; display: flex; flex-direction: column; margin: 0px auto; top: 0px; right: 0px; left: 0px;"
        />
        <ul
          id="chakra-toast-manager-top-left"
          style="position: fixed; z-index: 5500; pointer-events: none; display: flex; flex-direction: column; top: 0px; left: 0px;"
        />
        <ul
          id="chakra-toast-manager-top-right"
          style="position: fixed; z-index: 5500; pointer-events: none; display: flex; flex-direction: column; top: 0px; right: 0px;"
        />
        <ul
          id="chakra-toast-manager-bottom-left"
          style="position: fixed; z-index: 5500; pointer-events: none; display: flex; flex-direction: column; bottom: 0px; left: 0px;"
        />
        <ul
          id="chakra-toast-manager-bottom"
          style="position: fixed; z-index: 5500; pointer-events: none; display: flex; flex-direction: column; margin: 0px auto; bottom: 0px; right: 0px; left: 0px;"
        />
        <ul
          id="chakra-toast-manager-bottom-right"
          style="position: fixed; z-index: 5500; pointer-events: none; display: flex; flex-direction: column; bottom: 0px; right: 0px;"
        />
      </div>
      <div>
        <button
          class="chakra-button css-113xcha"
          type="button"
        />
      </div>
    </body>

dca123 avatar Mar 14 '21 02:03 dca123

I am having this same issue. Have been trying to render literally anything to test using getByText, getByID - everything fails because screen.debug() only shows me toasts and margins instead of the HTML code for the whole page and its actual components.

sbaileys avatar Mar 27 '21 17:03 sbaileys

I am having this same issue. Have been trying to render literally anything to test using getByText, getByID - everything fails because screen.debug() only shows me toasts and margins instead of the HTML code for the whole page and its actual components.

You can increase the output size of screen.debug() by passing DEBUG_PRINT_LIMIT, eg, (DEBUG_PRINT_LIMIT=100000 jest --watch).

lee-reinhardt avatar Mar 27 '21 20:03 lee-reinhardt

Anytime I render any component using the jest + react testing library, the toast manager is also included in that render. Is there any workaround for this problem?

This is the problem I'm having as well. I'm not rendering a <Toast> anywhere in my app so I'm confused about what's adding these elements. They are visible in the snapshot from react-testing-library, in baseElement, just like what you posted in your snippet.

All I can think of is I'm rendering a <ChakraProvider>, but even that is only in one component, yet I'm seeing this artifact across all of my snapshot tests.

edit: I was able to workaround this by adding to my Jest setup file:

beforeEach(() => {
  document.getElementById("chakra-toast-portal")?.remove();
});

kodell avatar May 18 '21 13:05 kodell

We discussed this today in our team meeting and we think it's something we need to rethink. The Toast system just isn't built to handle this issue well. It's something we'll get to eventually, but not for now unfortunately.

with-heart avatar May 20 '21 16:05 with-heart

Hi! This issue hasn't seen any activity recently. We close inactive issues after 35 days to manage the volume of issues we receive. If we missed this issue or you want to keep it open, please reply here. That will reset the timer and allow more time for this issue to be addressed before it is closed.

stale[bot] avatar Jun 20 '21 11:06 stale[bot]

keepalive packet

avaragado avatar Jun 20 '21 12:06 avaragado

Facing same issues here

matheusmb avatar Jul 05 '21 20:07 matheusmb

I've had this problem too you should remove height:100vh from all tags this fixed it for me

tamaskani avatar Aug 03 '21 09:08 tamaskani

@tamaskani I don't understand how adding some css would fix any of the three issues listed in the original post? Which issue are you saying the height: 100vh would fix?

timkindberg avatar Aug 03 '21 13:08 timkindberg

Hi! This issue has been automatically marked as stale because lack of recent activity. It will be closed if no further activity occurs within 5 days. Thank you for your contributions.

stale[bot] avatar Nov 09 '21 20:11 stale[bot]

I got pretty far using @kodell's suggestion, but tests involving toasts were randomly failing in some rare cases.

Closing all toasts programmatically, as seen in the Chakra tests, seems to work more reliably in the end: https://github.com/chakra-ui/chakra-ui/blob/3f0b369e34e7336df2d51d9978d6334cc073e541/packages/toast/test/use-toast.test.tsx#L9-L16

dlindenkreuz avatar Nov 26 '21 11:11 dlindenkreuz

Hi! This issue has been automatically marked as stale because lack of recent activity. It will be closed if no further activity occurs within 5 days. Thank you for your contributions.

stale[bot] avatar Apr 16 '22 09:04 stale[bot]

keepalive packet

dlindenkreuz avatar Apr 20 '22 08:04 dlindenkreuz

keepalive packet

wildeyes avatar Apr 27 '22 19:04 wildeyes

up

valenciaHQ avatar May 10 '22 16:05 valenciaHQ

up

alexonaci20robots avatar May 11 '22 15:05 alexonaci20robots

This is still annoying as hell, and after updating to chakra 2.x, the above workarounds no longer work.

hevans90 avatar Jun 09 '22 20:06 hevans90

After 2.x, the globally added HTML changes significantly:

image

And my attempts to interrogate the DOM in a setup preset (as before), just return empty collections...

image image

hevans90 avatar Jun 11 '22 14:06 hevans90

Having the same issues pretty annoying 🥲

0ubbe avatar Jul 27 '22 11:07 0ubbe

Same issues

rafaelaprado avatar Sep 15 '22 04:09 rafaelaprado

Facing this issue. No idea how to clear the toasts.

Ninfa-Jeon avatar Jan 11 '23 09:01 Ninfa-Jeon

Subscribing to here, current beforeEach that Chakra UI uses internally does work for me on Chakra UI 1.6

beforeEach(async () => { await waitFor( () => { expect( screen.queryAllByText("successToastHeading").length ).toBe(0); }, { timeout: 50000 } );

Though they run extremely slow, I assume that's because I have a duration of 4000 on them, though would like to see a solution that can close them all up immediately before each test.

bojackhorseman0309 avatar Mar 08 '23 23:03 bojackhorseman0309

I'm using Chakra UI for the first time and integrated it with my vite + react + ts scaffold. The only chakra import I've done so far is the ChakraProvider in my main.tsx file.

Without importing any other chakra component, my existing application's styles become wonky and upon inspecting the HTML I see a ton of "portal" & "toast" elements injected in my HTML.

Why is this happening?

1NF053C avatar Mar 16 '23 00:03 1NF053C

@1NF053C that's unrelated to this issue. ChakraProvider uses a global css reset that can be disabled by setting resetCSS={false} (but doing so will mess with how your Chakra components look).

Portal and toast elements are used for exactly what their name suggests: rendering portals and toasts

with-heart avatar Mar 16 '23 02:03 with-heart

Subscribing to here, current beforeEach that Chakra UI uses internally does work for me on Chakra UI 1.6

beforeEach(async () => { await waitFor( () => { expect( screen.queryAllByText("successToastHeading").length ).toBe(0); }, { timeout: 50000 } );

Though they run extremely slow, I assume that's because I have a duration of 4000 on them, though would like to see a solution that can close them all up immediately before each test.

@bojackhorseman0309 Try this:

import {
  waitForElementToBeRemoved,
} from '@testing-library/react';
import { act } from 'react-dom/test-utils';

jest.useFakeTimers();

it('test', async () => {
  await act(async () => {
    jest.runAllTimers();
  });

  await waitForElementToBeRemoved(() =>
    screen.queryAllByText('successToastHeading')
  );

  expect(screen.queryAllByText('successToastHeading').length).toBe(0);
});

luisspassos avatar May 20 '23 17:05 luisspassos

Any idea why toasts (I find it happens the same with modals) take so long to render in Jest with JSDOM? Is it because of fade-in animations or something?

0ubbe avatar Jun 01 '23 13:06 0ubbe