Fix flaky quick_action_suggestions frame-guard spec
What does this MR do and why?
Fixes a flaky frontend spec that broke master:
spec/frontend/editor/quick_action_suggestions_spec.js →
"recordFrequentCommandUsage › guards against double increment in the same frame".
Root cause
The guard test set global.performance = { now: () => 100 } to make the
frame-bucket dedup deterministic. That assignment is a silent no-op: in the
jsdom test environment global === window, but performance is a getter-only
accessor property (no setter), so assigning to it is ignored.
As a result, the production code (app/assets/javascripts/editor/quick_action_suggestions.js)
kept reading the real, advancing window.performance.now(). The guard
de-duplicates writes that land in the same Math.floor(now / 16) (~60fps) frame
bucket. When two back-to-back calls happened to straddle a 16ms bucket boundary —
which occurs intermittently under CI contention — the guard key differed between
the two calls, dedup never fired, and saveStorageValue ran twice instead of
once. Hence the intermittent Expected: 1 / Received: 2.
Fix
Spy on performance.now (jest.spyOn(performance, 'now').mockReturnValue(100))
instead of reassigning the getter-only property. This pins the bucket to a
constant so the two calls can never straddle a boundary. This is a test-only
change; production timing behavior is unchanged. The manual save/restore of
originalPerformance is removed since jest.restoreAllMocks() handles the spy.
Steps to reproduce the failure (before this fix)
With the original (broken) mock left in place, force the real clock the production code reads to cross a 16ms bucket boundary between the two calls:
it('guards against double increment in the same frame', () => {
// floor(100/16)=6, floor(117/16)=7 -> different frame buckets
jest.spyOn(performance, 'now').mockReturnValueOnce(100).mockReturnValueOnce(117);
recordFrequentCommandUsage('alpha');
recordFrequentCommandUsage('alpha');
expect(LocalStorage.saveStorageValue).toHaveBeenCalledTimes(1);
});Running yarn jest spec/frontend/editor/quick_action_suggestions_spec.js then
fails deterministically with the exact master-broken signature:
✕ guards against double increment in the same frame
Expected number of calls: 1
Received number of calls: 2This proves (a) the original global.performance assignment does not prevent the
double write, and (b) crossing a frame bucket boundary reliably produces two
writes. With this MR's fix the bucket is constant, so the suite passes
deterministically (verified locally over repeated runs).
References
- Broken
masterincident: gitlab-org/quality/engineering-productivity/master-broken-incidents#26797
How to set up and validate locally
yarn jest spec/frontend/editor/quick_action_suggestions_spec.jsAll 5 tests pass.