home-tab-navigation-benchmark.spec.ts 4.5 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114
  1. import { benchmark, expect } from "../benchmark"
  2. import { expectSessionTitle } from "../../utils/waits"
  3. import { measureNavigationMilestones } from "./navigation-milestones"
  4. import { fixture } from "./session-timeline-stress.fixture"
  5. import {
  6. installStressSessionTabs,
  7. installTimelineSettings,
  8. mockStressTimeline,
  9. stressSessionHref,
  10. } from "./timeline-test-helpers"
  11. import { waitForStableTimeline } from "./session-tab-switch-probe"
  12. const homeRow = '[data-component="home-session-row"]'
  13. const homeShell = '[data-component="home-session-search"]'
  14. benchmark.describe("performance: home and tab navigation", () => {
  15. benchmark("opens a home session and paints its titlebar tab", async ({ page, report }) => {
  16. await setup(page, [])
  17. await page.goto("/")
  18. const row = page.locator(homeRow).filter({ hasText: fixture.expected.targetTitle }).first()
  19. await expect(row).toBeVisible()
  20. const href = stressSessionHref(fixture.targetID)
  21. const result = await measureNavigationMilestones(page, {
  22. triggerSelector: homeRow,
  23. milestones: {
  24. content: { selector: messageSelector(fixture.expected.targetMessageIDs.at(-1)!) },
  25. tab: { selector: `[data-slot="titlebar-tabs"] a[href="${href}"]` },
  26. },
  27. navigate: async () => {
  28. await row.click()
  29. await expectSessionTitle(page, fixture.expected.targetTitle)
  30. },
  31. })
  32. report(result)
  33. await expect(page.locator(`[data-slot="titlebar-tabs"] a[href="${href}"]`)).toContainText(
  34. fixture.expected.targetTitle,
  35. )
  36. })
  37. benchmark("stages the review body after cold session content", async ({ page, report }) => {
  38. await setup(page, [])
  39. await page.goto("/")
  40. const row = page.locator(homeRow).filter({ hasText: fixture.expected.targetTitle }).first()
  41. await expect(row).toBeVisible()
  42. const result = await page.evaluate(
  43. ({ rowSelector, title, contentSelector }) =>
  44. new Promise<{ contentBeforeReview: boolean; samples: number }>((resolve) => {
  45. let samples = 0
  46. const sample = () => {
  47. samples++
  48. const content = !!document.querySelector(contentSelector)
  49. const review = !!document.querySelector('[data-component="session-review"]')
  50. if (content && !review) {
  51. resolve({ contentBeforeReview: true, samples })
  52. return
  53. }
  54. if (content && review) {
  55. resolve({ contentBeforeReview: false, samples })
  56. return
  57. }
  58. requestAnimationFrame(sample)
  59. }
  60. const target = [...document.querySelectorAll<HTMLElement>(rowSelector)].find((item) =>
  61. item.textContent?.includes(title),
  62. )
  63. if (!target) throw new Error(`Home session row not found: ${title}`)
  64. target.click()
  65. requestAnimationFrame(sample)
  66. }),
  67. {
  68. rowSelector: homeRow,
  69. title: fixture.expected.targetTitle,
  70. contentSelector: messageSelector(fixture.expected.targetMessageIDs.at(-1)!),
  71. },
  72. )
  73. report(result)
  74. expect(result.contentBeforeReview).toBe(true)
  75. await expect(page.locator('[data-component="session-review"]')).toBeVisible()
  76. })
  77. benchmark("closes the only session tab and paints home", async ({ page, report }) => {
  78. await setup(page, [fixture.sourceID])
  79. const href = stressSessionHref(fixture.sourceID)
  80. await page.goto(href)
  81. await expectSessionTitle(page, fixture.expected.sourceTitle)
  82. await waitForStableTimeline(page, fixture.expected.sourceMessageIDs.at(-1)!)
  83. const tab = page.locator(`[data-slot="titlebar-tabs"] a[href="${href}"]`).first()
  84. const close = tab.locator("..").locator('[data-component="icon-button-v2"]')
  85. await expect(close).toBeVisible()
  86. const result = await measureNavigationMilestones(page, {
  87. triggerSelector: '[data-slot="titlebar-tabs"] [data-component="icon-button-v2"]',
  88. milestones: {
  89. home: { selector: homeShell },
  90. row: { selector: homeRow },
  91. tabRemoved: { selector: `[data-slot="titlebar-tabs"] a[href="${href}"]`, visible: false },
  92. },
  93. navigate: async () => {
  94. await close.click()
  95. await expect(page).toHaveURL("/")
  96. },
  97. })
  98. report(result)
  99. })
  100. })
  101. async function setup(page: Parameters<typeof mockStressTimeline>[0], sessionIDs: string[]) {
  102. await mockStressTimeline(page)
  103. await installTimelineSettings(page)
  104. await installStressSessionTabs(page, { sessionIDs })
  105. }
  106. function messageSelector(id: string) {
  107. return `[data-message-id="${id}"]`
  108. }