bench-test-suite
4
总安装量
4
周安装量
#47754
全站排名
安装命令
npx skills add https://github.com/itsjavi/vani --skill bench-test-suite
Agent 安装分布
claude-code
3
windsurf
2
trae
2
opencode
2
antigravity
2
Skill 文档
Bench Test Suite
When to Use
- Adding a new benchmark view/test suite (like
datatableorpokeboxes) - Extending the Playwright runner with new view operations
- Making UI test results show up in the snapshot UI
Workflow
-
Define the view id and ready selector
- Pick a lowercase
viewid (used in?view=). - Decide the first stable selector that signals the view is ready.
- Pick a lowercase
-
Add the blueprint markup
- Create
bench/frameworks/blueprint-<view>.html. - The initial DOM must match every frameworkâs initial render (preflight compares against it).
- Reuse the view toggle markup and IDs used by existing blueprints.
- Create
-
Update the benchmark runner
- Add the view id to
OperationView,AVAILABLE_VIEWS, andBLUEPRINTS. - Add a
resolveViewReadySelectorbranch for the new view. - Add new
Operationentries that setview: '<view>'andreadySelector.
- Add the view id to
-
Add shared operations/data helpers
- Add new helpers in
bench/frameworks/shared.js. - Add matching types and exports in
bench/frameworks/shared.d.ts.
- Add new helpers in
-
Update framework implementations
- Each framework must render the same initial markup as the blueprint for the new view.
- Parse
?view=and render the correct view. - Add view toggle buttons and ensure they link to the correct
viewquery param. - Use design system classes from
bench/src/design-system.css(max 3 classes per element).
-
Expose the suite in results UI
- Add human-friendly labels for new operations in
bench/snapshot/index.ts. - Add the new view to
suiteOrderandsuiteTitles.
- Add human-friendly labels for new operations in
-
Run UI tests and generate results
- Run the runner with preflight to validate markup and measure timings.
- Open the snapshot UI to verify the new suite is visible.
Templates
bench/runner.ts additions
// 1) View type + constants
type OperationView = 'datatable' | 'pokeboxes' | '<view>'
const BLUEPRINTS = {
datatable: path.join(import.meta.dirname, 'frameworks/blueprint-datatable.html'),
pokeboxes: path.join(import.meta.dirname, 'frameworks/blueprint-pokeboxes.html'),
<view>: path.join(import.meta.dirname, 'frameworks/blueprint-<view>.html'),
}
const AVAILABLE_VIEWS: OperationView[] = ['datatable', 'pokeboxes', '<view>']
function resolveViewReadySelector(view: OperationView): string {
if (view === 'pokeboxes') return '#append40'
if (view === '<view>') return '#<ready-id>'
return '#run'
}
// 2) New operations
const operations: Operation[] = [
// ...
{
name: '<operationName>',
view: '<view>',
readySelector: '#<ready-id>',
setup: (page) => /* optional */,
action: (page) => clickAndMeasure(page, '#<action-id>', '<operationName>'),
teardown: (page) => /* optional */,
},
]
bench/frameworks/blueprint-<view>.html
<!-- Match initial DOM for *all* frameworks -->
<div class="bench-view-toggle" id="view-toggle">
<!-- include one button per view (datatable/pokeboxes/<view>) -->
</div>
<!-- New view DOM should be here with stable IDs -->
bench/frameworks/shared.js + bench/frameworks/shared.d.ts
// shared.js (helpers used by all frameworks)
export function build<Thing>(/* params */) {
// deterministic data helpers for the new view
}
export function <operationHelper>(/* params */) {
// pure data operation (no DOM)
}
// shared.d.ts (types + function declarations)
export type <Thing> = {
// ...
}
export declare function build<Thing>(/* params */): <Thing>[]
export declare function <operationHelper>(/* params */): <Thing>[]
Framework view routing (each bench/frameworks/*/index.ts[x]|index.js)
const resolveView = () => {
const params = new URLSearchParams(window.location.search)
return params.get('view') === '<view>' ? '<view>' : 'datatable'
}
const navigateToView = (view: string) => {
const url = new URL(window.location.href)
url.searchParams.set('view', view)
window.location.href = url.toString()
}
// Render toggle buttons + new view
bench/snapshot/index.ts updates
const OPERATION_LABELS = {
// ...
<operationName>: {
title: '<human title>',
description: '<what it measures>',
},
}
let suiteOrder = ['datatable', 'pokeboxes', '<view>']
let suiteTitles: Record<string, string> = {
datatable: 'Data Table',
pokeboxes: 'Pokeboxes',
<view>: '<View Title>',
}
Commands
- Run the full benchmark suite:
pnpm --filter benchmarks bench(orpnpm run benchfrombench/)
- Run only the new view:
pnpm --filter benchmarks bench -- --view <view>
- Validate markup only (preflight):
pnpm --filter benchmarks bench -- --preflight-only --view <view>
- View results UI:
pnpm --filter benchmarks devâ openhttp://localhost:4555/snapshot
Notes
- Preflight DOM checks compare each framework against the blueprint for every view.
- If you add new helpers or data shapes, update
bench/frameworks/shared.jsandbench/frameworks/shared.d.ts. - Keep button IDs and aria attributes aligned across all frameworks and blueprints.