fluentui icon indicating copy to clipboard operation
fluentui copied to clipboard

[Bug]: Dialog sometimes remains hidden in jest+RTL tests

Open alice-ep opened this issue 9 months ago • 8 comments
trafficstars

Component

Dialog

Package version

9.59.0

React version

17.0.2 (though reproduced with 18+ as well)

Environment

System:
    OS: Windows 11 10.0.26100
    CPU: (12) x64 Intel(R) Xeon(R) W-11855M CPU @ 3.20GHz
    Memory: 32.08 GB / 63.71 GB
  Browsers:
    Edge: Chromium (130.0.2849.46)
    Internet Explorer: 11.0.26100.1882

Current Behavior

Tests of components that use a dialog intermittently fail in our CI pipelines and locally. Local runs are easy to reproduce by running the test multiple times. It seems like the dialog sometimes stays hidden after being triggered and thus RTL can't find it with get/findByRole

This started happening after we upgraded to the latest react-components packages, as well as in a separate branch that tried to install the calendar compat package which caused an upgrade to fluent's latest tabster package (9.24) - which I suspect might be guilty of the regression

Expected Behavior

Not fail :)

Reproduction

https://codesandbox.io/p/devbox/romantic-wiles-forked-f4h4zl

Steps to reproduce

Run the test (note that it repeats 10 times) - at least one of the 10 runs will fail with it being unable to find either the dialog or the input inside it

Are you reporting an Accessibility issue?

None

Suggested severity

High - No workaround

Products/sites affected

Internal Microsoft product

Are you willing to submit a PR to fix?

no

Validations

  • [x] Check that there isn't already an issue that reports the same bug to avoid creating a duplicate.
  • [x] The provided reproduction is a minimal reproducible example of the bug.

alice-ep avatar Feb 25 '25 07:02 alice-ep

The workaround technically is to stay with a lower version of Fluent, but obviously that's not a long term solution :) We'll rollback the update for now so our CI pipelines aren't constantly.

alice-ep avatar Feb 25 '25 07:02 alice-ep

I can confirm this for version 9.60.0 and a vitest setup. Tests including the Dialog failed randomly. Have to pin version 9.58.2 which works for me.

Wezea avatar Feb 28 '25 12:02 Wezea

Hiya, any updates about this?

alice-ep avatar Mar 04 '25 07:03 alice-ep

Bumping this again to check if there's any news :)

alice-ep avatar Apr 17 '25 08:04 alice-ep

I am also facing the same issue, I have the same setup React + VITE (Jest RTL). Sometime test gets passed and sometime test get failed. I suspect it fails when we have nested dialogs.

kumawat24 avatar May 13 '25 08:05 kumawat24

@mshoho any chance to get any update about this issue?

alice-ep avatar May 15 '25 13:05 alice-ep

An update on this would be great, this is still blocking us from updating to the latest version.

Wezea avatar May 29 '25 15:05 Wezea

I found a workaround to this issue which worked for us. TL;DR: Setting the modalType to "non-modal" resolves this issue.

More details: We narrowed the issue down to the useModalAttributes hook in @fluentui/react-tabster (code snippet immediately below). If trapFocus is false, or isAlwaysAccessible is true, then the issue doesn't occur. The only way to control this from a FluentUI <Dialog> component is to set the the modalType to "non-modal".

  const modalAttributes = useTabsterAttributes({
    restorer: { type: RestorerTypes.Source },
    ...(trapFocus && {
      modalizer: {
        id,
        isOthersAccessible: !trapFocus,
        isAlwaysAccessible: alwaysFocusable,
        isTrapped: legacyTrapFocus && trapFocus,
      },
    }),
  });

The downside of setting it to non-modal is that it removes the opaque backdrop behind the dialog. For <Dialog> components, you can provide JSX for the backdrop, and it works similarly, but for the <OverlayDrawer> component it doesn't apply the backdrop even if it's provided when the modalType is "non-modal". The main downside to this is that clicking outside of the modal doesn't close the modal. For <Dialog> components, where we can add a backdrop, that should be fine since we can put an onClick handler on it to do this. For <OverlayDrawer> components, we don't have that option.

DKirwan avatar Jun 09 '25 13:06 DKirwan

Hi there,

Is there any chance to get this fixed? The suggestion by @DKirwan works, but I don't like workarounds like this.

Also here, to satisfy any bot who might thought this could be closed :)

Wezea avatar Aug 12 '25 08:08 Wezea

I had an offline discussion with @mshoho regarding this issue. Tabster depends on DOM APIs to function correctly, while Jest relies on JSDOM, which provides only a simulated (and often inaccurate) subset of DOM events. This is particularly problematic for focus-related scenarios such as tabbing.

Our general recommendation is to use a browser-based testing environment, such as Playwright or Cypress. This is also the approach we follow on the Fluent side.

layershifter avatar Aug 19 '25 15:08 layershifter