oracle-browser.spec.ts 2.7 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475
  1. import { expect, test } from "@playwright/test"
  2. import {
  3. analyzeVisualObservations,
  4. defineVisualRegions,
  5. startVisualProbe,
  6. stopVisualProbe,
  7. visualPlan,
  8. } from "../../utils/visual-stability"
  9. import { assistantMessage, setupTimeline, textPart, userMessage } from "./fixture"
  10. test("detects blanking caused by ancestor opacity", async ({ page }) => {
  11. const partID = "prt_oracle_ancestor_opacity"
  12. await setupTimeline(page, { messages: [userMessage(), assistantMessage([textPart(partID, "Visible content")])] })
  13. const row = page.locator(`[data-timeline-part-id="${partID}"]`).first()
  14. const regions = defineVisualRegions({
  15. content: { selector: `[data-timeline-part-id="${partID}"]` },
  16. })
  17. await startVisualProbe(page, regions)
  18. await row.evaluate((element) => {
  19. element.parentElement!.style.opacity = "0"
  20. })
  21. await page.waitForTimeout(50)
  22. await row.evaluate((element) => {
  23. element.parentElement!.style.opacity = "1"
  24. })
  25. await page.waitForTimeout(50)
  26. const trace = await stopVisualProbe<keyof typeof regions>(page)
  27. const issues = analyzeVisualObservations(
  28. trace.samples,
  29. visualPlan(regions, [
  30. { type: "opacity", regions: "all" },
  31. { type: "continuity", regions: "all" },
  32. { type: "motion", regions: "all" },
  33. { type: "label-stability", regions: "all" },
  34. ]),
  35. )
  36. expect(issues.some((issue) => issue.includes("blanked between visible frames"))).toBe(true)
  37. })
  38. test("detects root opacity when probing descendant opacity", async ({ page }) => {
  39. const partID = "prt_oracle_descendant_opacity"
  40. await setupTimeline(page, { messages: [userMessage(), assistantMessage([textPart(partID, "Visible content")])] })
  41. const row = page.locator(`[data-timeline-part-id="${partID}"]`).first()
  42. await row.evaluate((element) => {
  43. element.innerHTML = '<span data-probe-opacity="true">Visible content</span>'
  44. })
  45. const regions = defineVisualRegions({
  46. content: {
  47. selector: `[data-timeline-part-id="${partID}"]`,
  48. opacitySelectors: ['[data-probe-opacity="true"]'],
  49. },
  50. })
  51. await startVisualProbe(page, regions)
  52. await row.evaluate((element) => {
  53. ;(element as HTMLElement).style.opacity = "0"
  54. })
  55. await page.waitForTimeout(50)
  56. await row.evaluate((element) => {
  57. ;(element as HTMLElement).style.opacity = "1"
  58. })
  59. await page.waitForTimeout(50)
  60. const trace = await stopVisualProbe<keyof typeof regions>(page)
  61. const issues = analyzeVisualObservations(
  62. trace.samples,
  63. visualPlan(regions, [
  64. { type: "opacity", regions: "all" },
  65. { type: "continuity", regions: "all" },
  66. { type: "motion", regions: "all" },
  67. { type: "label-stability", regions: "all" },
  68. ]),
  69. )
  70. expect(issues.some((issue) => issue.includes("blanked between visible frames"))).toBe(true)
  71. })