Skip to content

Commit bae51a7

Browse files
authored
🤖 fix: make bulk review story ordering deterministic (#1052)
The `BulkReviewActions` story was unstable because `createReview()` used `Math.random()` for `createdAt` timestamps, causing reviews to appear in different orders on each render. **Fix:** Add optional `createdAt` parameter to `createReview()` and pass deterministic timestamps in the story. Also adds guidance to AGENTS.md: keep story data deterministic to avoid visual instability. _Generated with `mux`_
1 parent df8a180 commit bae51a7

File tree

3 files changed

+18
-8
lines changed

3 files changed

+18
-8
lines changed

docs/AGENTS.md

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -72,6 +72,7 @@ Avoid mock-heavy tests that verify implementation details rather than behavior.
7272

7373
- Prefer full-app stories (`App.stories.tsx`) to isolated component stories. This tests components in their real context with proper providers, state management, and styling.
7474
- Use play functions with `@storybook/test` utilities (`within`, `userEvent`, `waitFor`) to interact with the UI and set up the desired visual state. Do not add props to production components solely for storybook convenience.
75+
- Keep story data deterministic: avoid `Math.random()`, `Date.now()`, or other non-deterministic values in story setup. Pass explicit values when ordering or timing matters for visual stability.
7576

7677
### TDD Expectations
7778

src/browser/stories/App.reviews.stories.tsx

Lines changed: 14 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -168,50 +168,58 @@ export const BulkReviewActions: AppStory = {
168168
setup={() => {
169169
const workspaceId = "ws-bulk-reviews";
170170

171+
// Use deterministic timestamps so reviews render in stable order
172+
const baseTime = 1700000000000;
171173
setReviews(workspaceId, [
172174
// Attached reviews - shown in ChatInput with "Clear all" button
173175
createReview(
174176
"review-attached-1",
175177
"src/api/auth.ts",
176178
"42-48",
177179
"Consider using a constant for the token expiry",
178-
"attached"
180+
"attached",
181+
baseTime + 1
179182
),
180183
createReview(
181184
"review-attached-2",
182185
"src/utils/helpers.ts",
183186
"15-20",
184187
"This function could be simplified using reduce",
185-
"attached"
188+
"attached",
189+
baseTime + 2
186190
),
187191
createReview(
188192
"review-attached-3",
189193
"src/hooks/useAuth.ts",
190194
"30-35",
191195
"Missing error handling for network failures",
192-
"attached"
196+
"attached",
197+
baseTime + 3
193198
),
194199
// Pending reviews - shown in banner with "Attach all to chat" button
195200
createReview(
196201
"review-pending-1",
197202
"src/components/LoginForm.tsx",
198203
"55-60",
199204
"Add loading state while authenticating",
200-
"pending"
205+
"pending",
206+
baseTime + 4
201207
),
202208
createReview(
203209
"review-pending-2",
204210
"src/services/api.ts",
205211
"12-18",
206212
"Consider adding retry logic for failed requests",
207-
"pending"
213+
"pending",
214+
baseTime + 5
208215
),
209216
createReview(
210217
"review-pending-3",
211218
"src/types/user.ts",
212219
"5-10",
213220
"Make email field optional for guest users",
214-
"pending"
221+
"pending",
222+
baseTime + 6
215223
),
216224
]);
217225

src/browser/stories/storyHelpers.ts

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -76,7 +76,8 @@ export function createReview(
7676
filePath: string,
7777
lineRange: string,
7878
note: string,
79-
status: "pending" | "attached" | "checked" = "pending"
79+
status: "pending" | "attached" | "checked" = "pending",
80+
createdAt?: number
8081
): Review {
8182
return {
8283
id,
@@ -87,7 +88,7 @@ export function createReview(
8788
userNote: note,
8889
},
8990
status,
90-
createdAt: Date.now() - Math.random() * 3600000, // Random time in last hour
91+
createdAt: createdAt ?? Date.now(),
9192
statusChangedAt: status === "checked" ? Date.now() : undefined,
9293
};
9394
}

0 commit comments

Comments
 (0)