mirror of
https://github.com/Matysh/houseplan-card
synced 2026-09-29 03:09:36 +00:00
65 lines
2.6 KiB
JavaScript
65 lines
2.6 KiB
JavaScript
// #101: View/editor navigation has one controller for toolbar height, stage
|
|
// geometry and camera. This smoke deliberately observes real animation frames;
|
|
// it never asserts an exact wall-clock millisecond.
|
|
import { launch, checkAll, finish } from './serve.mjs';
|
|
|
|
const { page, browser } = await launch({ width: 820, height: 760 });
|
|
const result = await page.evaluate(async () => {
|
|
const card = window.__card;
|
|
const root = () => card.shadowRoot || card.renderRoot;
|
|
const sleepFrame = () => new Promise((resolve) => requestAnimationFrame(resolve));
|
|
const sampleUntilSettled = async () => {
|
|
const samples = [];
|
|
const started = performance.now();
|
|
do {
|
|
await sleepFrame();
|
|
const stage = root().querySelector('.stage');
|
|
const svg = stage?.querySelector(':scope .zoomwrap > svg');
|
|
if (stage && svg) {
|
|
const vb = svg.viewBox.baseVal;
|
|
samples.push({
|
|
busy: card._modeTransitionBusy,
|
|
inert: stage.inert,
|
|
height: stage.getBoundingClientRect().height,
|
|
aspect: vb.width / vb.height,
|
|
stageAspect: stage.clientWidth / stage.clientHeight,
|
|
});
|
|
}
|
|
} while (card._modeTransitionBusy && performance.now() - started < 1000);
|
|
return samples;
|
|
};
|
|
|
|
await card.updateComplete;
|
|
card._setMode('view');
|
|
await card.updateComplete;
|
|
const viewHeight = root().querySelector('.stage').clientHeight;
|
|
|
|
card._setMode('plan');
|
|
const enter = await sampleUntilSettled();
|
|
const planHeight = root().querySelector('.stage').clientHeight;
|
|
const distinctEnterHeights = new Set(enter.map((sample) => Math.round(sample.height))).size;
|
|
|
|
card._setMode('devices');
|
|
const swap = await sampleUntilSettled();
|
|
const chromeInner = root().querySelector('.editorchrome-inner');
|
|
|
|
card._setMode('view');
|
|
const leave = await sampleUntilSettled();
|
|
const restoredHeight = root().querySelector('.stage').clientHeight;
|
|
const allFrames = [...enter, ...swap, ...leave];
|
|
return {
|
|
enterHadIntermediateGeometry: distinctEnterHeights >= 3,
|
|
editorConsumesViewportHeight: planHeight < viewHeight,
|
|
stageInertDuringMotion: allFrames.filter((sample) => sample.busy).every((sample) => sample.inert),
|
|
cameraMatchesEveryStageAspect: allFrames.every((sample) =>
|
|
Number.isFinite(sample.aspect) && Math.abs(sample.aspect - sample.stageAspect) < 0.02),
|
|
editorSwapUsesSharedTimeline: swap.some((sample) => sample.busy) && !!chromeInner,
|
|
viewHeightRestored: Math.abs(restoredHeight - viewHeight) <= 2,
|
|
controllerSettled: card._modeTransitionBusy === false
|
|
&& !root().querySelector('.stage').classList.contains('mode-transition'),
|
|
};
|
|
});
|
|
|
|
checkAll(result);
|
|
await finish(browser, result);
|