| ... | @@ -130,7 +130,9 @@ function matchMedia() { | ... | @@ -130,7 +130,9 @@ function matchMedia() { |
| 130 | }; | 130 | }; |
| 131 | } | 131 | } |
| 132 | | 132 | |
| 133 | beforeAll(() => { | 133 | let MessagesTimeline: typeof import("./MessagesTimeline").MessagesTimeline; |
| | 134 | |
| | 135 | beforeAll(async () => { |
| 134 | const classList = { | 136 | const classList = { |
| 135 | add: () => {}, | 137 | add: () => {}, |
| 136 | remove: () => {}, | 138 | remove: () => {}, |
| ... | @@ -161,7 +163,9 @@ beforeAll(() => { | ... | @@ -161,7 +163,9 @@ beforeAll(() => { |
| 161 | offsetHeight: 0, | 163 | offsetHeight: 0, |
| 162 | }, | 164 | }, |
| 163 | }); | 165 | }); |
| 164 | }); | 166 | |
| | 167 | ({ MessagesTimeline } = await import("./MessagesTimeline")); |
| | 168 | }, 30_000); |
| 165 | | 169 | |
| 166 | const ACTIVE_THREAD_ENVIRONMENT_ID = EnvironmentId.make("environment-local"); | 170 | const ACTIVE_THREAD_ENVIRONMENT_ID = EnvironmentId.make("environment-local"); |
| 167 | const MESSAGE_CREATED_AT = "2026-03-17T19:12:28.000Z"; | 171 | const MESSAGE_CREATED_AT = "2026-03-17T19:12:28.000Z"; |
| ... | @@ -219,8 +223,7 @@ function buildUserTimelineEntry(text: string) { | ... | @@ -219,8 +223,7 @@ function buildUserTimelineEntry(text: string) { |
| 219 | } | 223 | } |
| 220 | | 224 | |
| 221 | describe("MessagesTimeline", () => { | 225 | describe("MessagesTimeline", () => { |
| 222 | it("uses the larger leading inset only when the top fade is enabled", async () => { | 226 | it("uses the larger leading inset only when the top fade is enabled", () => { |
| 223 | const { MessagesTimeline } = await import("./MessagesTimeline"); | | |
| 224 | const timelineEntries = [buildUserTimelineEntry("Hello")]; | 227 | const timelineEntries = [buildUserTimelineEntry("Hello")]; |
| 225 | | 228 | |
| 226 | const compactMarkup = renderToStaticMarkup( | 229 | const compactMarkup = renderToStaticMarkup( |
| ... | @@ -236,8 +239,7 @@ describe("MessagesTimeline", () => { | ... | @@ -236,8 +239,7 @@ describe("MessagesTimeline", () => { |
| 236 | expect(fadedMarkup).toContain("chat-timeline-scroll-fade"); | 239 | expect(fadedMarkup).toContain("chat-timeline-scroll-fade"); |
| 237 | }); | 240 | }); |
| 238 | | 241 | |
| 239 | it("keeps assistant changed-files headers sticky below the thread header", async () => { | 242 | it("keeps assistant changed-files headers sticky below the thread header", () => { |
| 240 | const { MessagesTimeline } = await import("./MessagesTimeline"); | | |
| 241 | const assistantMessageId = MessageId.make("message-assistant-with-files"); | 243 | const assistantMessageId = MessageId.make("message-assistant-with-files"); |
| 242 | const turnId = TurnId.make("turn-with-files"); | 244 | const turnId = TurnId.make("turn-with-files"); |
| 243 | const markup = renderToStaticMarkup( | 245 | const markup = renderToStaticMarkup( |
| ... | @@ -349,8 +351,7 @@ describe("MessagesTimeline", () => { | ... | @@ -349,8 +351,7 @@ describe("MessagesTimeline", () => { |
| 349 | expect(resolveTimelineMinimapInteractiveWidth(40, true)).toBe("22rem"); | 351 | expect(resolveTimelineMinimapInteractiveWidth(40, true)).toBe("22rem"); |
| 350 | }); | 352 | }); |
| 351 | | 353 | |
| 352 | it("anchors a sent attachment message using its measured height", async () => { | 354 | it("anchors a sent attachment message using its measured height", () => { |
| 353 | const { MessagesTimeline } = await import("./MessagesTimeline"); | | |
| 354 | const onAnchorReady = vi.fn(); | 355 | const onAnchorReady = vi.fn(); |
| 355 | const onAnchorSizeChanged = vi.fn(); | 356 | const onAnchorSizeChanged = vi.fn(); |
| 356 | const firstEntry = buildUserTimelineEntry("First prompt."); | 357 | const firstEntry = buildUserTimelineEntry("First prompt."); |
| ... | @@ -398,8 +399,7 @@ describe("MessagesTimeline", () => { | ... | @@ -398,8 +399,7 @@ describe("MessagesTimeline", () => { |
| 398 | expect(onAnchorSizeChanged).toHaveBeenCalledWith(secondEntry.message.id, 240); | 399 | expect(onAnchorSizeChanged).toHaveBeenCalledWith(secondEntry.message.id, 240); |
| 399 | }); | 400 | }); |
| 400 | | 401 | |
| 401 | it("renders collapse controls for long user messages", async () => { | 402 | it("renders collapse controls for long user messages", () => { |
| 402 | const { MessagesTimeline } = await import("./MessagesTimeline"); | | |
| 403 | const markup = renderToStaticMarkup( | 403 | const markup = renderToStaticMarkup( |
| 404 | <MessagesTimeline | 404 | <MessagesTimeline |
| 405 | {...buildProps()} | 405 | {...buildProps()} |
| ... | @@ -418,8 +418,7 @@ describe("MessagesTimeline", () => { | ... | @@ -418,8 +418,7 @@ describe("MessagesTimeline", () => { |
| 418 | expect(markup).toContain('data-user-message-footer="true"'); | 418 | expect(markup).toContain('data-user-message-footer="true"'); |
| 419 | }); | 419 | }); |
| 420 | | 420 | |
| 421 | it("does not render collapse controls for short user messages", async () => { | 421 | it("does not render collapse controls for short user messages", () => { |
| 422 | const { MessagesTimeline } = await import("./MessagesTimeline"); | | |
| 423 | const markup = renderToStaticMarkup( | 422 | const markup = renderToStaticMarkup( |
| 424 | <MessagesTimeline | 423 | <MessagesTimeline |
| 425 | {...buildProps()} | 424 | {...buildProps()} |
| ... | @@ -431,8 +430,7 @@ describe("MessagesTimeline", () => { | ... | @@ -431,8 +430,7 @@ describe("MessagesTimeline", () => { |
| 431 | expect(markup).toContain('data-user-message-collapsible="false"'); | 430 | expect(markup).toContain('data-user-message-collapsible="false"'); |
| 432 | }); | 431 | }); |
| 433 | | 432 | |
| 434 | it("renders inline terminal labels with the composer chip UI", async () => { | 433 | it("renders inline terminal labels with the composer chip UI", () => { |
| 435 | const { MessagesTimeline } = await import("./MessagesTimeline"); | | |
| 436 | const markup = renderToStaticMarkup( | 434 | const markup = renderToStaticMarkup( |
| 437 | <MessagesTimeline | 435 | <MessagesTimeline |
| 438 | {...buildProps()} | 436 | {...buildProps()} |
| ... | @@ -459,8 +457,7 @@ describe("MessagesTimeline", () => { | ... | @@ -459,8 +457,7 @@ describe("MessagesTimeline", () => { |
| 459 | expect(markup).toContain("Show full message"); | 457 | expect(markup).toContain("Show full message"); |
| 460 | }, 20_000); | 458 | }, 20_000); |
| 461 | | 459 | |
| 462 | it("renders chips for standalone element-pick context messages", async () => { | 460 | it("renders chips for standalone element-pick context messages", () => { |
| 463 | const { MessagesTimeline } = await import("./MessagesTimeline"); | | |
| 464 | const markup = renderToStaticMarkup( | 461 | const markup = renderToStaticMarkup( |
| 465 | <MessagesTimeline | 462 | <MessagesTimeline |
| 466 | {...buildProps()} | 463 | {...buildProps()} |
| ... | @@ -486,8 +483,7 @@ describe("MessagesTimeline", () => { | ... | @@ -486,8 +483,7 @@ describe("MessagesTimeline", () => { |
| 486 | expect(markup).not.toContain("<element_context"); | 483 | expect(markup).not.toContain("<element_context"); |
| 487 | }); | 484 | }); |
| 488 | | 485 | |
| 489 | it("keeps the copy button for collapsed long user messages", async () => { | 486 | it("keeps the copy button for collapsed long user messages", () => { |
| 490 | const { MessagesTimeline } = await import("./MessagesTimeline"); | | |
| 491 | const markup = renderToStaticMarkup( | 487 | const markup = renderToStaticMarkup( |
| 492 | <MessagesTimeline | 488 | <MessagesTimeline |
| 493 | {...buildProps()} | 489 | {...buildProps()} |
| ... | @@ -500,8 +496,7 @@ describe("MessagesTimeline", () => { | ... | @@ -500,8 +496,7 @@ describe("MessagesTimeline", () => { |
| 500 | expect(markup).toContain('data-user-message-footer="true"'); | 496 | expect(markup).toContain('data-user-message-footer="true"'); |
| 501 | }); | 497 | }); |
| 502 | | 498 | |
| 503 | it("renders context compaction entries in the normal work log", async () => { | 499 | it("renders context compaction entries in the normal work log", () => { |
| 504 | const { MessagesTimeline } = await import("./MessagesTimeline"); | | |
| 505 | const markup = renderToStaticMarkup( | 500 | const markup = renderToStaticMarkup( |
| 506 | <MessagesTimeline | 501 | <MessagesTimeline |
| 507 | {...buildProps()} | 502 | {...buildProps()} |
| ... | @@ -525,8 +520,7 @@ describe("MessagesTimeline", () => { | ... | @@ -525,8 +520,7 @@ describe("MessagesTimeline", () => { |
| 525 | expect(markup).toContain("Work Log"); | 520 | expect(markup).toContain("Work Log"); |
| 526 | }); | 521 | }); |
| 527 | | 522 | |
| 528 | it("formats changed file paths from the workspace root", async () => { | 523 | it("formats changed file paths from the workspace root", () => { |
| 529 | const { MessagesTimeline } = await import("./MessagesTimeline"); | | |
| 530 | const markup = renderToStaticMarkup( | 524 | const markup = renderToStaticMarkup( |
| 531 | <MessagesTimeline | 525 | <MessagesTimeline |
| 532 | {...buildProps()} | 526 | {...buildProps()} |
| ... | @@ -552,8 +546,7 @@ describe("MessagesTimeline", () => { | ... | @@ -552,8 +546,7 @@ describe("MessagesTimeline", () => { |
| 552 | expect(markup).not.toContain("C:/Users/mike/dev-stuff/t3code/apps/web/src/session-logic.ts"); | 546 | expect(markup).not.toContain("C:/Users/mike/dev-stuff/t3code/apps/web/src/session-logic.ts"); |
| 553 | }); | 547 | }); |
| 554 | | 548 | |
| 555 | it("renders review comment contexts as structured cards instead of raw tags", async () => { | 549 | it("renders review comment contexts as structured cards instead of raw tags", () => { |
| 556 | const { MessagesTimeline } = await import("./MessagesTimeline"); | | |
| 557 | const markup = renderToStaticMarkup( | 550 | const markup = renderToStaticMarkup( |
| 558 | <MessagesTimeline | 551 | <MessagesTimeline |
| 559 | {...buildProps()} | 552 | {...buildProps()} |
| ... | @@ -593,8 +586,7 @@ describe("MessagesTimeline", () => { | ... | @@ -593,8 +586,7 @@ describe("MessagesTimeline", () => { |
| 593 | expect(markup).not.toContain("&lt;/review_comment&gt;"); | 586 | expect(markup).not.toContain("&lt;/review_comment&gt;"); |
| 594 | }); | 587 | }); |
| 595 | | 588 | |
| 596 | it("renders file review comments as source code instead of diffs", async () => { | 589 | it("renders file review comments as source code instead of diffs", () => { |
| 597 | const { MessagesTimeline } = await import("./MessagesTimeline"); | | |
| 598 | const markup = renderToStaticMarkup( | 590 | const markup = renderToStaticMarkup( |
| 599 | <MessagesTimeline | 591 | <MessagesTimeline |
| 600 | {...buildProps()} | 592 | {...buildProps()} |
| ... | @@ -631,8 +623,7 @@ describe("MessagesTimeline", () => { | ... | @@ -631,8 +623,7 @@ describe("MessagesTimeline", () => { |
| 631 | expect(markup).not.toContain('data-testid="file-diff"'); | 623 | expect(markup).not.toContain('data-testid="file-diff"'); |
| 632 | }); | 624 | }); |
| 633 | | 625 | |
| 634 | it("renders a failure marker for failed tool lifecycle entries", async () => { | 626 | it("renders a failure marker for failed tool lifecycle entries", () => { |
| 635 | const { MessagesTimeline } = await import("./MessagesTimeline"); | | |
| 636 | const markup = renderToStaticMarkup( | 627 | const markup = renderToStaticMarkup( |
| 637 | <MessagesTimeline | 628 | <MessagesTimeline |
| 638 | {...buildProps()} | 629 | {...buildProps()} |