Skip to content

Commit 8f8401d

Browse files
committed
🤖 Use stable timestamps and version for visual testing
- Replace Date.now() with stable timestamp in all story files - Mock VERSION in Storybook with stable values for Chromatic - Use Apple's iconic demo time: January 24, 2024, 9:41 AM PST - Ensures consistent visual snapshots across Chromatic runs
1 parent 7e7d5c7 commit 8f8401d

File tree

8 files changed

+76
-12
lines changed

8 files changed

+76
-12
lines changed

.storybook/main.ts

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -19,6 +19,8 @@ const config: StorybookConfig = {
1919
resolve: {
2020
alias: {
2121
"@": path.join(process.cwd(), "src"),
22+
// Mock version module for stable visual testing in Storybook
23+
"@/version": path.join(process.cwd(), ".storybook/mocks/version.ts"),
2224
},
2325
},
2426
});

.storybook/mocks/version.ts

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,9 @@
1+
// Mock version for Storybook visual testing
2+
// This ensures consistent snapshots in Chromatic
3+
// Apple's classic demo time: 9:41 AM on January 24, 2024
4+
export const VERSION = {
5+
git_commit: 'abc1234',
6+
git_describe: 'v1.0.0',
7+
buildTime: '2024-01-24T17:41:00Z', // 9:41 AM PST
8+
};
9+

src/App.stories.tsx

Lines changed: 11 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -5,6 +5,9 @@ import type { ProjectConfig } from "./config";
55
import type { FrontendWorkspaceMetadata } from "./types/workspace";
66
import type { IPCApi } from "./types/ipc";
77

8+
// Stable timestamp for visual testing (Apple demo time: Jan 24, 2024, 9:41 AM PST)
9+
const STABLE_TIMESTAMP = new Date('2024-01-24T09:41:00-08:00').getTime();
10+
811
// Mock window.api for App component
912
function setupMockAPI(options: {
1013
projects?: Map<string, ProjectConfig>;
@@ -374,7 +377,7 @@ export const ActiveWorkspaceWithChat: Story = {
374377
parts: [{ type: "text", text: "Add authentication to the user API endpoint" }],
375378
metadata: {
376379
historySequence: 1,
377-
timestamp: Date.now() - 300000,
380+
timestamp: STABLE_TIMESTAMP - 300000,
378381
},
379382
});
380383

@@ -402,7 +405,7 @@ export const ActiveWorkspaceWithChat: Story = {
402405
],
403406
metadata: {
404407
historySequence: 2,
405-
timestamp: Date.now() - 290000,
408+
timestamp: STABLE_TIMESTAMP - 290000,
406409
model: "claude-sonnet-4-20250514",
407410
usage: {
408411
inputTokens: 1250,
@@ -420,7 +423,7 @@ export const ActiveWorkspaceWithChat: Story = {
420423
parts: [{ type: "text", text: "Yes, add JWT token validation" }],
421424
metadata: {
422425
historySequence: 3,
423-
timestamp: Date.now() - 280000,
426+
timestamp: STABLE_TIMESTAMP - 280000,
424427
},
425428
});
426429

@@ -452,7 +455,7 @@ export const ActiveWorkspaceWithChat: Story = {
452455
],
453456
metadata: {
454457
historySequence: 4,
455-
timestamp: Date.now() - 270000,
458+
timestamp: STABLE_TIMESTAMP - 270000,
456459
model: "claude-sonnet-4-20250514",
457460
usage: {
458461
inputTokens: 2100,
@@ -470,7 +473,7 @@ export const ActiveWorkspaceWithChat: Story = {
470473
parts: [{ type: "text", text: "Can you run the tests to make sure it works?" }],
471474
metadata: {
472475
historySequence: 5,
473-
timestamp: Date.now() - 240000,
476+
timestamp: STABLE_TIMESTAMP - 240000,
474477
},
475478
});
476479

@@ -502,7 +505,7 @@ export const ActiveWorkspaceWithChat: Story = {
502505
],
503506
metadata: {
504507
historySequence: 6,
505-
timestamp: Date.now() - 230000,
508+
timestamp: STABLE_TIMESTAMP - 230000,
506509
model: "claude-sonnet-4-20250514",
507510
usage: {
508511
inputTokens: 2800,
@@ -525,7 +528,7 @@ export const ActiveWorkspaceWithChat: Story = {
525528
],
526529
metadata: {
527530
historySequence: 7,
528-
timestamp: Date.now() - 180000,
531+
timestamp: STABLE_TIMESTAMP - 180000,
529532
},
530533
});
531534

@@ -562,7 +565,7 @@ export const ActiveWorkspaceWithChat: Story = {
562565
],
563566
metadata: {
564567
historySequence: 8,
565-
timestamp: Date.now() - 170000,
568+
timestamp: STABLE_TIMESTAMP - 170000,
566569
model: "claude-sonnet-4-20250514",
567570
usage: {
568571
inputTokens: 3500,

src/components/Messages/AssistantMessage.stories.tsx

Lines changed: 4 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -3,6 +3,9 @@ import { AssistantMessage } from "./AssistantMessage";
33
import type { DisplayedMessage } from "@/types/message";
44
import { action } from "@storybook/addon-actions";
55

6+
// Stable timestamp for visual testing (Apple demo time: Jan 24, 2024, 9:41 AM PST)
7+
const STABLE_TIMESTAMP = new Date('2024-01-24T09:41:00-08:00').getTime();
8+
69
const clipboardWriteText = (data: string) => {
710
action("copy-text")(data);
811
return Promise.resolve();
@@ -52,7 +55,7 @@ const createAssistantMessage = (
5255
isStreaming: false,
5356
isPartial: false,
5457
isCompacted: false,
55-
timestamp: Date.now(),
58+
timestamp: STABLE_TIMESTAMP,
5659
model: "anthropic:claude-sonnet-4-5",
5760
...overrides,
5861
});

src/components/Messages/ReasoningMessage.stories.tsx

Lines changed: 4 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -2,6 +2,9 @@ import type { Meta, StoryObj } from "@storybook/react";
22
import { ReasoningMessage } from "./ReasoningMessage";
33
import type { DisplayedMessage } from "@/types/message";
44

5+
// Stable timestamp for visual testing (Apple demo time: Jan 24, 2024, 9:41 AM PST)
6+
const STABLE_TIMESTAMP = new Date('2024-01-24T09:41:00-08:00').getTime();
7+
58
const meta = {
69
title: "Messages/ReasoningMessage",
710
component: ReasoningMessage,
@@ -34,7 +37,7 @@ const createReasoningMessage = (
3437
historySequence: 1,
3538
isStreaming: false,
3639
isPartial: false,
37-
timestamp: Date.now(),
40+
timestamp: STABLE_TIMESTAMP,
3841
...overrides,
3942
});
4043

src/components/Messages/StreamErrorMessage.stories.tsx

Lines changed: 4 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -3,6 +3,9 @@ import { StreamErrorMessage } from "./StreamErrorMessage";
33
import type { DisplayedMessage } from "@/types/message";
44
import type { StreamErrorType } from "@/types/errors";
55

6+
// Stable timestamp for visual testing (Apple demo time: Jan 24, 2024, 9:41 AM PST)
7+
const STABLE_TIMESTAMP = new Date('2024-01-24T09:41:00-08:00').getTime();
8+
69
const meta = {
710
title: "Messages/StreamErrorMessage",
811
component: StreamErrorMessage,
@@ -35,7 +38,7 @@ const createStreamErrorMessage = (
3538
error,
3639
errorType,
3740
historySequence: 1,
38-
timestamp: Date.now(),
41+
timestamp: STABLE_TIMESTAMP,
3942
...overrides,
4043
});
4144

src/components/Messages/UserMessage.stories.tsx

Lines changed: 4 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -3,6 +3,9 @@ import { action } from "@storybook/addon-actions";
33
import { UserMessage } from "./UserMessage";
44
import type { DisplayedMessage } from "@/types/message";
55

6+
// Stable timestamp for visual testing (Apple demo time: Jan 24, 2024, 9:41 AM PST)
7+
const STABLE_TIMESTAMP = new Date('2024-01-24T09:41:00-08:00').getTime();
8+
69
const clipboardWriteText = (data: string) => {
710
action("copy-text")(data);
811
return Promise.resolve();
@@ -42,7 +45,7 @@ const createUserMessage = (
4245
historyId: "hist-1",
4346
content,
4447
historySequence: 1,
45-
timestamp: Date.now(),
48+
timestamp: STABLE_TIMESTAMP,
4649
...overrides,
4750
});
4851

Lines changed: 38 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,38 @@
1+
import type { Meta, StoryObj } from "@storybook/react";
2+
import { TitleBar } from "./TitleBar";
3+
4+
const meta = {
5+
title: "Components/TitleBar",
6+
component: TitleBar,
7+
parameters: {
8+
layout: "fullscreen",
9+
backgrounds: {
10+
default: "dark",
11+
values: [{ name: "dark", value: "#1e1e1e" }],
12+
},
13+
},
14+
tags: ["autodocs"],
15+
} satisfies Meta<typeof TitleBar>;
16+
17+
export default meta;
18+
type Story = StoryObj<typeof meta>;
19+
20+
/**
21+
* The TitleBar shows the cmux version and build date.
22+
*
23+
* Note: The version displayed is generated at build time from git information.
24+
* In Storybook, you'll see the current development version.
25+
*/
26+
export const Default: Story = {};
27+
28+
export const WithTelemetryDisabled: Story = {
29+
parameters: {
30+
docs: {
31+
description: {
32+
story:
33+
"When telemetry is disabled, the update indicator shows a disabled state (⊘) and hovering explains updates are disabled.",
34+
},
35+
},
36+
},
37+
};
38+

0 commit comments

Comments
 (0)