mirror of
https://github.com/Matysh/houseplan-card
synced 2026-09-29 03:09:36 +00:00
test: prove settings help at 200 percent zoom
Exercise the effective Chromium renderer contract for 200% browser zoom and assert that the trigger and tooltip stay visible, the dialog does not gain horizontal overflow, and opening help leaves stage geometry unchanged. Issue: #86 User-Visible: no
This commit is contained in:
@@ -381,6 +381,71 @@ res.party1ColdOnboardingHelpIsReadOnly = onboardingHelp.readOnly;
|
||||
res.party1ColdOnboardingKeepsEditorLazy = onboardingHelp.editorStillLazy;
|
||||
await onboarding.browser.close();
|
||||
|
||||
// Browser zoom at 200% on a 780 px-wide display exposes a 390 CSS px viewport
|
||||
// at DPR 2. Playwright cannot change Chromium's toolbar preference, so create
|
||||
// that exact renderer contract directly; unlike CSS `zoom`, this preserves the
|
||||
// coordinate space used by fixed/popover surfaces and catches real clipping.
|
||||
const zoomed = await launch({ width: 390, height: 900 }, 2);
|
||||
const zoomedLayout = await zoomed.page.evaluate(async () => {
|
||||
const card = window.__card;
|
||||
const root = card.renderRoot;
|
||||
const frame = () => new Promise((resolve) => requestAnimationFrame(resolve));
|
||||
card._openSettingsDialog();
|
||||
await card.updateComplete;
|
||||
await frame();
|
||||
|
||||
const help = root.querySelector('hp-help[data-help-key="gs.bg_mode.help"]');
|
||||
const trigger = help?.shadowRoot?.querySelector('.trigger');
|
||||
const stage = root.querySelector('.stage');
|
||||
const dialogBody = root.querySelector('hp-dialog .body');
|
||||
const stageRect = () => {
|
||||
const box = stage?.getBoundingClientRect();
|
||||
return box ? [box.left, box.top, box.width, box.height].map((value) => Math.round(value)) : null;
|
||||
};
|
||||
const settleStage = async () => {
|
||||
let previous = null;
|
||||
for (let attempt = 0; attempt < 8; attempt++) {
|
||||
await frame();
|
||||
const current = stageRect();
|
||||
if (JSON.stringify(current) === JSON.stringify(previous)) return current;
|
||||
previous = current;
|
||||
}
|
||||
return previous;
|
||||
};
|
||||
trigger?.scrollIntoView({ block: 'center', inline: 'nearest' });
|
||||
await frame();
|
||||
const before = await settleStage();
|
||||
trigger?.click();
|
||||
await help?.updateComplete;
|
||||
await new Promise((resolve) => requestAnimationFrame(() => requestAnimationFrame(resolve)));
|
||||
const triggerBox = trigger?.getBoundingClientRect();
|
||||
const surface = help?.shadowRoot?.querySelector('.tooltip')
|
||||
|| root.querySelector('hp-dialog')?.shadowRoot
|
||||
?.querySelector('[data-hp-overlay="help"]')?.shadowRoot?.querySelector('.tooltip');
|
||||
const surfaceBox = surface?.getBoundingClientRect();
|
||||
const viewport = window.visualViewport;
|
||||
const left = viewport?.offsetLeft || 0;
|
||||
const top = viewport?.offsetTop || 0;
|
||||
const right = left + (viewport?.width || innerWidth);
|
||||
const bottom = top + (viewport?.height || innerHeight);
|
||||
const inside = (box) => !!box && box.width > 0 && box.height > 0
|
||||
&& box.left >= left && box.top >= top && box.right <= right && box.bottom <= bottom;
|
||||
return {
|
||||
zoomApplied: devicePixelRatio === 2 && innerWidth === 390,
|
||||
triggerInside: inside(triggerBox),
|
||||
tooltipInside: inside(surfaceBox),
|
||||
noHorizontalDialogOverflow: !!dialogBody
|
||||
&& dialogBody.scrollWidth <= dialogBody.clientWidth + 1,
|
||||
stageStable: JSON.stringify(await settleStage()) === JSON.stringify(before),
|
||||
};
|
||||
});
|
||||
res.party1BrowserZoom200Applied = zoomedLayout.zoomApplied;
|
||||
res.party1BrowserZoom200TriggerInside = zoomedLayout.triggerInside;
|
||||
res.party1BrowserZoom200TooltipInside = zoomedLayout.tooltipInside;
|
||||
res.party1BrowserZoom200NoHorizontalOverflow = zoomedLayout.noHorizontalDialogOverflow;
|
||||
res.party1BrowserZoom200StageStable = zoomedLayout.stageStable;
|
||||
await zoomed.browser.close();
|
||||
|
||||
res.keyboardFocus = keyboardFocus;
|
||||
|
||||
checkAll(res);
|
||||
|
||||
@@ -202,6 +202,9 @@ save paths всех настроек остаются прежними. Мигр
|
||||
- отдельный cold-install запуск lazy onboarding runtime: все пять `space.*`
|
||||
placement присутствуют, editor runtime остаётся незагруженным, открытие
|
||||
подсказки не меняет draft;
|
||||
- отдельный Chromium layout-pass при 200% zoom: renderer-контракт 780 физических
|
||||
px представлен как 390 CSS px при DPR 2; trigger и tooltip остаются внутри
|
||||
viewport, у диалога нет горизонтального overflow, геометрия stage не меняется;
|
||||
- mouse hover, keyboard focus/Enter/Escape и touch toggle/outside close;
|
||||
- open help does not change setting/show-hidden action;
|
||||
- disabled group, native Popover and forced fallback;
|
||||
|
||||
Reference in New Issue
Block a user