[docs] Use specific date to avoid daily Argos diffs#4337
Conversation
commit: |
Bundle size report
Check out the code infra dashboard for more information about this PR. |
✅ Deploy Preview for base-ui ready!
To edit notification comments on pull requests, go to your Netlify project configuration. |
|
I think using today will cause issue with hydration on the doc, not just with Argos. |
Yes, there will still be hydration mismatches, especially for today (current day). Do you prefer a safe approach, avoiding all hydration/flashing problems altogether? |
What behavior do they have exactly? |
Spectrum shows the current month and hydrates the today (i.e., getting back to a stale tab). |
|
OK so same thing as us right now? |
Yup. The basic idea is the same. |
|
If Spectrum is doing that way, I'm fine doing the same at least for now 👍 |
Code Review by Claude CodeOverviewThe PR overrides Notes
Looks good to merge with or without the nits. |
|
The approach suggested by @Janpot works just as well.
|
|
The docs-components-calendar-demos-validation-css-modules demo still looks date-dependent. The min/max dates use the actual current day. |
@michaldudak All the demos use the current day, but with this change it would be mocked to be the same for each regression test run (screenshots and Argos diff comparison). Or are you suggesting changing the validation demo to use specific dates to have the demo more stable in the docs? |
Sorry, my bad, I missed this. 🙈 |
| import { ChevronLeft, ChevronRight } from 'lucide-react'; | ||
| import styles from './calendar.module.css'; | ||
|
|
||
| const today = new Date(); |
There was a problem hiding this comment.
Surprises me that this doesn't work, we're importing the demos after mocking the date. Have you checked what's going on? Is this something that was broken in prod or dev or both?
edit: tried it and it seems to work for me 🤔
There was a problem hiding this comment.
In short - bundlers don't seem to guarantee module evaluation order.
P.S. It's reproducible in dev mode as well.
And just to clarify, change here is just for consistency; the main relevant change is in the demos, not experiments.
Here is the full Claude response:
This is a classic module evaluation order issue.
When Vite (or any bundler) processes the import.meta.glob(..., { eager: true }) calls in main.tsx, it eagerly imports all matching demo files. Each module's top-level code executes once, at import time, as part of the module's static evaluation.
Here's the sequence:
import './fakeDateSetup'runs first — it patchesglobalThis.DatewithFakeDate.- The
import.meta.globcalls pull in all demo.tsxfiles. Each module is evaluated (its top-level scope runs). - Inside a demo,
const today = new Date()at the module top level executes during step 2 — after the fake is installed — so it should get the faked date.
But that's the happy path. The real problem is that bundlers don't guarantee the evaluation order of eagerly-globbed modules relative to explicit imports in all scenarios. Specifically:
- With Vite's dev server (ESM),
import.meta.glob({ eager: true })resolves modules that may have already been loaded by the browser as part of the module graph (e.g., via HMR or another import chain). If another entry point or a transitive dependency caused a demo module to load beforefakeDateSetupran, thennew Date()at the top level of that module captured the realDateconstructor. - In production builds, code-splitting and chunk ordering can similarly cause modules to evaluate before
fakeDateSetupif they end up in a different chunk or are shared across entry points.
Why moving it inside the component fixes it:
// Module top-level — runs once at import/evaluation time
const today = new Date(); // Captures Date at module eval time (might be real Date)
function MyDemo() {
// Runs at render time — always after all imports have settled
const today = new Date(); // Always uses the patched FakeDate
}There was a problem hiding this comment.
P.S. It's reproducible in dev mode as well.
How do you reproduce it?
There was a problem hiding this comment.
Revert the change in the demo file, run regressions app locally with pnpm test:regression:dev, navigate to http://localhost:5173/docs-components-calendar-demos-validation-css-modules/index.tsx and observe the min and max dates are using actual today instead of mocked.
There was a problem hiding this comment.
That's what I did, but it's showing the mocked date for me. I even tried changing the mocked date, and it just follows. Both in prod and in dev.
There was a problem hiding this comment.
I just double-checked.
Merged with the latest master.
Retried the local build - same.
Tried pnpm test:regressions:build && pnpm test:regressions:server - same.
In both instances, it works exactly the same.
If I move the date initialization outside of the component scope - date faking is not applied.
Anyone else interested in trying?
In any case, CI also confirms this behavior, so I'm not sure if there is a point in keeping this PR open and Argos broken. 🤔
The previous inline `Date` override was hand-rolled and I incorrectly described it as mirroring mui-x (mui-x uses sinon `useFakeTimers`; this bundle does not). Replace the shim with the reviewed approach from mui/base-ui#4337: `Reflect.construct` preserves the native `Date.prototype` (timezone-aware date libraries enumerate its own methods) and forwards `new.target`. Also pin `timezoneId: 'UTC'` on the playwright page — without it the frozen instant would render in the CI machine's local timezone and still churn the baseline. This was missing before. Kept as an inline classic <script> (rather than base-ui's module + fixture-extraction in mui#4370): a classic script runs synchronously before the deferred module bundle, so it beats the eager-glob import hoisting that mui#4370 worked around — without refactoring the glob loading that drives the entire VRT suite. Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>

This is to avoid the Argos diff everyday shifting the
todayin each demo and causing diffs.It's a modified version of what is used in X Pickers e2e tests, because working with
TZDaterequired a more elaborate overriding.