Files
orca/tests/tools/benchmarks/spinner-rendering/verify-rendering.mjs
aeddfa463d perf(renderer): avoid per-second spinner animation events (#19407)
* perf(renderer): avoid per-second spinner animation events

* fix(bench): ensure the Electron runtime before bench:spinners

The script launches Electron via Playwright but skipped ensure:electron-runtime,
which every other Electron-launching bench script runs first.

* docs(renderer): scope spinner pixel-tolerance claim to paused-animation checks

---------

Co-authored-by: m4air <m4air@m4airs-MacBook-Air.local>
Co-authored-by: pullfrog[bot] <226033991+pullfrog[bot]@users.noreply.github.com>
2026-09-07 19:29:53 -07:00

115 lines
3.8 KiB
JavaScript

import assert from 'node:assert/strict'
import { verifyPixels } from './verify-pixels.mjs'
async function waitForPhase(page) {
await page
.waitForFunction(() =>
[...document.querySelectorAll('[data-agent-spinner]')].every((element) => {
const animations = element.getAnimations({ subtree: true })
return (
animations.length === 1 &&
animations[0].startTime === 0 &&
animations[0].playState === 'running'
)
})
)
.catch(async (error) => {
console.log(
await page.evaluate(() =>
[...document.querySelectorAll('[data-agent-spinner]')].slice(0, 3).map((element) => ({
html: element.outerHTML,
width: getComputedStyle(element).width,
state: document.visibilityState,
animations: element.getAnimations({ subtree: true }).map((animation) => ({
name: animation.animationName,
start: animation.startTime,
time: animation.currentTime
}))
}))
)
)
throw error
})
}
export async function verifyRendering(app, page, outputDir) {
await page.emulateMedia({ reducedMotion: 'no-preference' })
await page.evaluate(() => window.spinnerBenchmark.render({ count: 4, paired: true }))
await waitForPhase(page)
const pixelComparisons = await verifyPixels(app, page, outputDir, waitForPhase)
await app.evaluate(({ BrowserWindow }) =>
BrowserWindow.getAllWindows()[0].webContents.setZoomFactor(1)
)
await page.emulateMedia({ reducedMotion: 'reduce' })
await page.waitForFunction(() =>
[...document.querySelectorAll('[data-agent-spinner]')].every((element) => {
const ring = getComputedStyle(element)
return (
element.getAnimations({ subtree: true }).length === 0 &&
ring.borderTopColor === ring.borderLeftColor
)
})
)
await page.emulateMedia({ reducedMotion: 'no-preference' })
await waitForPhase(page)
await page.evaluate(() => window.spinnerBenchmark.render({ count: 200, offset: 5000 }))
await waitForPhase(page)
await page.evaluate(() => {
document.querySelector('#scroller').scrollTop = 5000
})
await waitForPhase(page)
await page.evaluate(() => {
document.querySelector('#scroller').scrollTop = 0
})
await waitForPhase(page)
await page.evaluate(() => {
document.querySelector('#scroller').scrollTop = 5000
})
await waitForPhase(page)
await page.evaluate(() => {
document.querySelector('#grid').style.display = 'none'
})
await page.waitForFunction(
() => document.querySelector('#grid').getBoundingClientRect().height === 0
)
await page.evaluate(() => {
document.querySelector('#grid').style.display = 'grid'
})
await waitForPhase(page)
const iterationEvents = await page.evaluate(async () => {
window.spinnerBenchmark.render({ count: 4, paired: true })
const events = { baseline: 0, candidate: 0 }
const count = (event) => {
if (event.animationName === 'spinner-benchmark-spin') {
events.baseline++
}
if (event.animationName === 'agent-spinner-rotate') {
events.candidate++
}
}
document.addEventListener('animationiteration', count, true)
try {
await new Promise((resolve) => setTimeout(resolve, 1250))
} finally {
document.removeEventListener('animationiteration', count, true)
}
return events
})
assert.ok(iterationEvents.baseline >= 2)
assert.equal(iterationEvents.candidate, 0)
assert.ok(
await app.evaluate(({ BrowserWindow }) =>
BrowserWindow.getAllWindows().every((window) => !window.isVisible() && !window.isFocused())
)
)
return {
pixelComparisons,
iterationEvents,
phases: true,
reducedMotion: true,
scrollReveal: true,
displayReveal: true,
hiddenWindow: true
}
}