Make flaky Storybook stories deterministic for Argos (animations + lazy-load) (#21609)

Follow-up to #21594. A set of stories were still flagged flaky by Argos
after the data/image/date fixes. The remaining causes are **animation**
and **lazy-load timing**, not data. Argos's screenshot stabilization
waits for fonts and images and disables CSS animations at capture, but
it does **not** stop JS-driven animations (react-spring) or wait for
`React.lazy` chunks to load.

Two global, test-only changes in the Storybook Vitest setup, plus an
`optimizeDeps` entry:

**1. Disable JS animations (charts).** GraphWidgetLineChart (incl.
`--catalog`) and the pie chart draw via `@react-spring/web`
(`useAnimatedPath`/`useArcsTransition`, used by nivo), so they get
captured mid-draw.
- `Globals.assign({ skipAnimation: true })` from `@react-spring/web`
(single hoisted instance → covers nivo), mirroring the existing
`MotionGlobalConfig.skipAnimations`.
- A global CSS rule zeroing animation/transition durations
(belt-and-suspenders for the pre-capture window).
- `@react-spring/web` added to `optimizeDeps.include` (next to
`@nivo/*`) so importing it in the setup file doesn't trigger a mid-run
Vite re-optimization.

**2. Pre-warm lazy chunks.** RichTextFieldInput (BlockNote editor),
AiChatMessage (`react-markdown`/`remark-gfm`), and AppNavigationDrawer
(favorites/workspace section dispatchers) lazy-load behind `Suspense`;
the snapshot could capture the skeleton fallback instead of the loaded
content. Pre-warming the chunks at setup time (same pattern already used
for the workflow-step mock) caches them before stories render.

The settings object-about form was already covered by the
framer-motion/CSS animation disable.
This commit is contained in:
Raphaël Bosi
2026-06-15 15:54:28 +02:00
committed by GitHub
parent 87c878b101
commit 03f9ace0bc
2 changed files with 21 additions and 2 deletions
@@ -1,12 +1,30 @@
import { Globals } from '@react-spring/web';
import { setProjectAnnotations } from '@storybook/react-vite';
import { MotionGlobalConfig } from 'framer-motion';
import * as projectAnnotations from './preview';
MotionGlobalConfig.skipAnimations = true;
Globals.assign({ skipAnimation: true });
// Pre-warm the dynamic import used by WorkflowStepDecorator so the
// module is cached before any test runs (avoids flaky timeouts in CI).
const disableCssAnimationsStyle = document.createElement('style');
disableCssAnimationsStyle.innerHTML = `*, *::before, *::after {
animation-duration: 0s !important;
animation-delay: 0s !important;
transition-duration: 0s !important;
transition-delay: 0s !important;
}`;
document.head.appendChild(disableCssAnimationsStyle);
// Pre-warm the dynamic imports used by lazy() story components so the
// modules are cached before any test runs (avoids flaky timeouts and Argos
// screenshots that capture a Suspense skeleton instead of the loaded content).
import('~/testing/utils/getTestEnrichedObjectMetadataItemsMock');
import('react-markdown');
import('remark-gfm');
import('@/activities/components/ActivityRichTextEditor');
import('@/object-record/record-field/ui/meta-types/input/components/RichTextFieldEditor');
import('@/navigation-menu-item/display/sections/favorites/components/FavoritesSectionDispatcher');
import('@/navigation-menu-item/display/sections/workspace/components/WorkspaceSectionDispatcher');
// This is an important step to apply the right configuration when testing your stories.
// More info at: https://storybook.js.org/docs/api/portable-stories/portable-stories-vitest#setprojectannotations
+1
View File
@@ -154,6 +154,7 @@ export default defineConfig(({ mode }) => {
'@nivo/pie',
'@nivo/line',
'@nivo/arcs',
'@react-spring/web',
'd3-shape',
],
},