mirror of
https://github.com/Matysh/houseplan-card
synced 2026-07-31 16:38:31 +00:00
T1: demo/serve.mjs exports check/checkAll/finish — all 48 smokes now assert named facts and exit non-zero on a mismatch or an uncaught in-card exception (verified by breaking the kiosk guard on purpose). Informational values were frozen from a v1.43.1 run and cross-read against the source; timings assert budgets, not exact numbers. T2: new CI job 'smoke' gated on 'frontend', builds a FRESH bundle before running (the committed demo/srv/assets copy is a snapshot) and uploads per-file logs on failure. T3: [auto] now means 'a named failing check exists' and each line names it (43 lines); 72 aspirational markers honestly downgraded to [manual]. Fixed the 'ZERO edit buttons' contradiction (wrong since v1.30.1) and the opening-click line (true again since v1.43.1). Three smokes carried pre-v1.39.0/v1.25 expectations and were testing old behaviour: tap defaults for lights, card-wide tap action, label drag requiring plan mode. DEVELOPMENT.md documents the harness contract.
87 lines
4.1 KiB
JavaScript
87 lines
4.1 KiB
JavaScript
// UX modes shell (v1.25.0): view is display-only; plan/devices gate the tools.
|
||
import { launch, checkAll, finish } from './serve.mjs';
|
||
const { page, browser } = await launch();
|
||
const out = {};
|
||
const q = (sel) => page.evaluate((s) => (window.__card.shadowRoot || window.__card.renderRoot).querySelectorAll(s).length, sel);
|
||
const st = () => page.evaluate(() => {
|
||
const c = window.__card;
|
||
const sr = c.shadowRoot || c.renderRoot;
|
||
return {
|
||
mode: c._mode,
|
||
modeTabs: sr.querySelectorAll('.modetab').length,
|
||
active: sr.querySelector('.modetab.active')?.textContent.trim(),
|
||
editBtns: sr.querySelectorAll('.head .btn:not(.zb)').length,
|
||
gears: sr.querySelectorAll('.tabedit').length,
|
||
markupBar: !!sr.querySelector('.editbar'),
|
||
stageClass: sr.querySelector('.stage').className,
|
||
};
|
||
});
|
||
// 1) старт: view, чистая шапка
|
||
out.start = await st();
|
||
// 2) drag в view ничего не двигает и не мешает пану
|
||
await page.evaluate(() => {
|
||
const c = window.__card;
|
||
const d = c._devices.find((x) => x.space === 'f1');
|
||
const before = { ...c._pos(d) };
|
||
c._pointerDown({ preventDefault(){}, clientX: 10, clientY: 10, target: { setPointerCapture(){} }, pointerId: 1 }, d);
|
||
c._pointerMove({ clientX: 90, clientY: 60 }, d);
|
||
c._pointerUp({}, d);
|
||
const after = { ...c._pos(d) };
|
||
window.__viewDragMoved = Math.abs(after.x - before.x) + Math.abs(after.y - before.y) > 0.5;
|
||
clearTimeout(c._holdTimer);
|
||
});
|
||
out.viewDragMoved = await page.evaluate(() => window.__viewDragMoved);
|
||
// long-press в view открывает инфо
|
||
await page.evaluate(async () => {
|
||
const c = window.__card;
|
||
const d = c._devices.find((x) => x.space === 'f1');
|
||
c._pointerDown({ preventDefault(){}, clientX: 10, clientY: 10, target: { setPointerCapture(){} }, pointerId: 2 }, d);
|
||
await new Promise((r) => setTimeout(r, 700));
|
||
});
|
||
out.viewHoldInfo = await page.evaluate(() => { const r = !!window.__card._infoCard; window.__card._infoCard = null; window.__card._holdFired = false; return r; });
|
||
// 3) режим План
|
||
await page.evaluate(() => window.__card._setMode('plan'));
|
||
await page.waitForTimeout(200);
|
||
out.plan = await st();
|
||
out.planIconsHidden = await page.evaluate(() => {
|
||
const sr = window.__card.shadowRoot || window.__card.renderRoot;
|
||
const dev = sr.querySelector('.dev');
|
||
return dev ? getComputedStyle(dev).display === 'none' : 'no-dev';
|
||
});
|
||
// 4) режим Устройства: drag работает, клик открывает редактор
|
||
await page.evaluate(() => window.__card._setMode('devices'));
|
||
await page.waitForTimeout(200);
|
||
out.devices = await st();
|
||
out.devDragWorks = await page.evaluate(() => {
|
||
const c = window.__card;
|
||
const d = c._devices.find((x) => x.space === 'f1');
|
||
const before = { ...c._pos(d) };
|
||
c._pointerDown({ preventDefault(){}, clientX: 10, clientY: 10, target: { setPointerCapture(){} }, pointerId: 3 }, d);
|
||
c._pointerMove({ clientX: 100, clientY: 70 }, d);
|
||
c._pointerUp({}, d);
|
||
const after = { ...c._pos(d) };
|
||
return Math.abs(after.x - before.x) + Math.abs(after.y - before.y) > 0.5;
|
||
});
|
||
out.devClickOpensEditor = await page.evaluate(async () => {
|
||
const c = window.__card;
|
||
c._drag = null;
|
||
const d = c._devices.find((x) => x.space === 'f1');
|
||
c._clickDevice({ stopPropagation(){} }, d);
|
||
await c.updateComplete;
|
||
const r = !!c._markerDialog;
|
||
c._markerDialog = null;
|
||
return r;
|
||
});
|
||
// 5) назад в view
|
||
await page.evaluate(() => window.__card._setMode('view'));
|
||
out.backToView = (await st()).mode;
|
||
// значения зафиксированы прогоном на v1.43.1 и сверены с кодом (audit T1)
|
||
checkAll(out, {
|
||
"start": {"mode": "view", "modeTabs": 3, "editBtns": 1, "gears": 2, "markupBar": false, "stageClass": "stage mode-view"},
|
||
"viewDragMoved": false,
|
||
"plan": {"mode": "plan", "modeTabs": 3, "active": "Plan editor", "editBtns": 1, "gears": 2, "markupBar": true, "stageClass": "stage markup tool-draw mode-plan"},
|
||
"devices": {"mode": "devices", "modeTabs": 3, "active": "Device editor", "editBtns": 1, "gears": 2, "markupBar": true, "stageClass": "stage mode-devices"},
|
||
"backToView": "view",
|
||
});
|
||
await finish(browser, out);
|