| ... | @@ -15,7 +15,7 @@ import { | ... | @@ -15,7 +15,7 @@ import { |
| 15 | import { RouterProvider, createMemoryHistory } from "@tanstack/react-router"; | 15 | import { RouterProvider, createMemoryHistory } from "@tanstack/react-router"; |
| 16 | import { HttpResponse, http, ws } from "msw"; | 16 | import { HttpResponse, http, ws } from "msw"; |
| 17 | import { setupWorker } from "msw/browser"; | 17 | import { setupWorker } from "msw/browser"; |
| 18 | import { afterAll, afterEach, beforeAll, beforeEach, describe, expect, it } from "vitest"; | 18 | import { afterAll, afterEach, beforeAll, beforeEach, describe, expect, it, vi } from "vitest"; |
| 19 | import { render } from "vitest-browser-react"; | 19 | import { render } from "vitest-browser-react"; |
| 20 | | 20 | |
| 21 | import { getRouter } from "../router"; | 21 | import { getRouter } from "../router"; |
| ... | @@ -301,13 +301,21 @@ async function waitForElement<T extends Element>( | ... | @@ -301,13 +301,21 @@ async function waitForElement<T extends Element>( |
| 301 | query: () => T | null, | 301 | query: () => T | null, |
| 302 | errorMessage: string, | 302 | errorMessage: string, |
| 303 | ): Promise<T> { | 303 | ): Promise<T> { |
| 304 | const timeoutAt = performance.now() + 8_000; | 304 | let element: T | null = null; |
| 305 | while (performance.now() < timeoutAt) { | 305 | await vi.waitFor( |
| 306 | const element = query(); | 306 | () => { |
| 307 | if (element) return element; | 307 | element = query(); |
| 308 | await nextFrame(); | 308 | expect(element, errorMessage).toBeTruthy(); |
| | 309 | }, |
| | 310 | { |
| | 311 | timeout: 8_000, |
| | 312 | interval: 16, |
| | 313 | }, |
| | 314 | ); |
| | 315 | if (!element) { |
| | 316 | throw new Error(errorMessage); |
| 309 | } | 317 | } |
| 310 | throw new Error(errorMessage); | 318 | return element; |
| 311 | } | 319 | } |
| 312 | | 320 | |
| 313 | async function waitForImagesToLoad(scope: ParentNode): Promise<void> { | 321 | async function waitForImagesToLoad(scope: ParentNode): Promise<void> { |
| ... | @@ -368,29 +376,29 @@ async function renderAndMeasureUserRow(options: { | ... | @@ -368,29 +376,29 @@ async function renderAndMeasureUserRow(options: { |
| 368 | ); | 376 | ); |
| 369 | | 377 | |
| 370 | let row: HTMLElement | null = null; | 378 | let row: HTMLElement | null = null; |
| 371 | const timeoutAt = performance.now() + 8_000; | 379 | await vi.waitFor( |
| 372 | while (performance.now() < timeoutAt) { | 380 | async () => { |
| 373 | scrollContainer.scrollTop = 0; | 381 | scrollContainer.scrollTop = 0; |
| 374 | scrollContainer.dispatchEvent(new Event("scroll")); | 382 | scrollContainer.dispatchEvent(new Event("scroll")); |
| 375 | await waitForLayout(); | 383 | await waitForLayout(); |
| 376 | row = host.querySelector<HTMLElement>( | 384 | row = host.querySelector<HTMLElement>( |
| 377 | `[data-message-id="${options.targetMessageId}"][data-message-role="user"]`, | 385 | `[data-message-id="${options.targetMessageId}"][data-message-role="user"]`, |
| 378 | ); | 386 | ); |
| 379 | if (row) { | 387 | expect(row, "Unable to locate targeted user message row.").toBeTruthy(); |
| 380 | break; | 388 | }, |
| 381 | } | 389 | { |
| 382 | } | 390 | timeout: 8_000, |
| 383 | if (!row) { | 391 | interval: 16, |
| 384 | throw new Error("Unable to locate targeted user message row."); | 392 | }, |
| 385 | } | 393 | ); |
| 386 | | 394 | |
| 387 | await waitForImagesToLoad(row); | 395 | await waitForImagesToLoad(row!); |
| 388 | scrollContainer.scrollTop = 0; | 396 | scrollContainer.scrollTop = 0; |
| 389 | scrollContainer.dispatchEvent(new Event("scroll")); | 397 | scrollContainer.dispatchEvent(new Event("scroll")); |
| 390 | await nextFrame(); | 398 | await nextFrame(); |
| 391 | | 399 | |
| 392 | const timelineRoot = | 400 | const timelineRoot = |
| 393 | row.closest<HTMLElement>('[data-timeline-root="true"]') ?? | 401 | row!.closest<HTMLElement>('[data-timeline-root="true"]') ?? |
| 394 | host.querySelector<HTMLElement>('[data-timeline-root="true"]'); | 402 | host.querySelector<HTMLElement>('[data-timeline-root="true"]'); |
| 395 | if (!(timelineRoot instanceof HTMLElement)) { | 403 | if (!(timelineRoot instanceof HTMLElement)) { |
| 396 | throw new Error("Unable to locate timeline root container."); | 404 | throw new Error("Unable to locate timeline root container."); |
| ... | @@ -400,24 +408,22 @@ async function renderAndMeasureUserRow(options: { | ... | @@ -400,24 +408,22 @@ async function renderAndMeasureUserRow(options: { |
| 400 | let measuredRowHeightPx = 0; | 408 | let measuredRowHeightPx = 0; |
| 401 | let renderedInVirtualizedRegion = false; | 409 | let renderedInVirtualizedRegion = false; |
| 402 | const rowSelector = `[data-message-id="${options.targetMessageId}"][data-message-role="user"]`; | 410 | const rowSelector = `[data-message-id="${options.targetMessageId}"][data-message-role="user"]`; |
| 403 | const measureTimeoutAt = performance.now() + 4_000; | 411 | await vi.waitFor( |
| 404 | while (performance.now() < measureTimeoutAt) { | 412 | async () => { |
| 405 | scrollContainer.scrollTop = 0; | 413 | scrollContainer.scrollTop = 0; |
| 406 | scrollContainer.dispatchEvent(new Event("scroll")); | 414 | scrollContainer.dispatchEvent(new Event("scroll")); |
| 407 | await nextFrame(); | 415 | await nextFrame(); |
| 408 | const measuredRow = host.querySelector<HTMLElement>(rowSelector); | 416 | const measuredRow = host.querySelector<HTMLElement>(rowSelector); |
| 409 | if (!measuredRow) { | 417 | expect(measuredRow, "Unable to measure targeted user row height.").toBeTruthy(); |
| 410 | continue; | 418 | measuredRowHeightPx = measuredRow!.getBoundingClientRect().height; |
| 411 | } | 419 | renderedInVirtualizedRegion = measuredRow!.closest("[data-index]") instanceof HTMLElement; |
| 412 | measuredRowHeightPx = measuredRow.getBoundingClientRect().height; | 420 | expect(measuredRowHeightPx, "Unable to measure targeted user row height.").toBeGreaterThan(0); |
| 413 | renderedInVirtualizedRegion = measuredRow.closest("[data-index]") instanceof HTMLElement; | 421 | }, |
| 414 | if (measuredRowHeightPx > 0) { | 422 | { |
| 415 | break; | 423 | timeout: 4_000, |
| 416 | } | 424 | interval: 16, |
| 417 | } | 425 | }, |
| 418 | if (measuredRowHeightPx <= 0) { | 426 | ); |
| 419 | throw new Error("Unable to measure targeted user row height."); | | |
| 420 | } | | |
| 421 | | 427 | |
| 422 | return { measuredRowHeightPx, timelineWidthMeasuredPx, renderedInVirtualizedRegion }; | 428 | return { measuredRowHeightPx, timelineWidthMeasuredPx, renderedInVirtualizedRegion }; |
| 423 | } finally { | 429 | } finally { |