Files
dogfather-universe/pruef-bewegung.mjs
T
DogFatherGitandClaude Opus 5 e4216a2c7a Kachel-Effekte gelten jetzt auf der ganzen Seite, nicht nur intern
Neigung, Glanzstreifen und Lichtkante lagen bisher nur im
Verwaltungsbereich. Sie stehen jetzt im Grundsystem und gelten damit
ueberall: Startseite, Leistungen, Ablauf, Portfolio, "Ueber mich",
Kundenportal.

Die Farbe kommt aus --wd-lumen. Jede Kachel bringt die ohnehin mit
(Token-Regel 02), der Verwaltungsbereich ueberschreibt sie mit der Farbe
des jeweiligen Bereichs. Dadurch braucht es keine einzige Sonderregel.

DREI FEHLER, DIE DIE REGRESSION GEFUNDEN HAT

1. Die Einblendung hat die Neigung geloescht.

   ".wd-bereit .wd-auf.wd-sichtbar" setzt "transform: none" und hat mit
   drei Klassen die hoehere Gewichtung. Sichtbar war das nur auf Seiten,
   deren Kacheln eine Einblendung tragen: Auf "ablauf" kippte die
   Kachel, auf "leistungen" nicht -- und der Wert kam in beiden Faellen
   korrekt an. Die Einblendung nutzt jetzt "translate".

   Das ist zum dritten Mal dieselbe Falle nach Buehne und Kacheln im
   Verwaltungsbereich. Merksatz: Wer "transform" animiert oder
   zuruecksetzt, blockiert es fuer alles andere.

2. Die Perspektive hat die Buehne zerlegt.

   "perspective" auf dem Abschnitt macht diesen zum Bezugsrahmen fuer
   position:fixed in seinem Inneren -- genau wie "transform" oder
   "filter". Die bildschirmfuellende Buehne im Verwaltungsbereich lag
   danach nicht mehr am Fenster, sondern am Abschnitt: gemessen 472
   statt 900 Punkte Hoehe.

   Die Perspektive steckt jetzt als Funktion im transform der Kachel
   selbst. Der gemeinsame Fluchtpunkt benachbarter Kacheln entfaellt
   damit, was bei hoechstens fuenf Grad niemand sieht.

3. Kachel-Neigung und Bild-Parallaxe haben sich aufgeschaukelt.

   Die kippende Kachel schiebt das Bild unter dem Zeiger weg, der landet
   dadurch auf einem Nachbarelement, das Bild springt zurueck auf null --
   und beim naechsten Zucken von vorne. Messbar war das als "an einer
   Ecke sauber, an der anderen dauerhaft 0".

   Klare Arbeitsteilung: Ein Bild INNERHALB einer Kachel bekommt nur den
   Zoom, die Kachel kippt darum herum. Freistehende Bilder behalten ihre
   eigene Gegenbewegung.

NEUER DURCHLAUF ueber alle Seiten (pruef-bewegung.mjs)

Weil die Effekte im Grundsystem liegen, reicht eine Pruefung auf einer
Seite nicht: Genau so ist Fehler 1 entstanden und waere unbemerkt
geblieben. Der Durchlauf geht sechs Seiten ab und prueft je Seite
Neigung, Winkel unter neun Grad, Zuruecksetzen beim Verlassen und
Skriptfehler.

Zwei Stolpersteine stecken darin dokumentiert: Die Startseite legt beim
Laden einen Vorhang ueber alles (wer zu frueh misst, trifft den Vorhang
statt der Kachel), und eine Portfolio-Kachel ist ueber 1400 Punkte hoch
-- ein fester Anteil ihrer Hoehe landet ausserhalb des Bildschirms.

Geprueft: 291 Pruefungen gruen (Bewegung 27, Portfolio 19, Verwaltung 62,
CRYONOVA 53, Blickfang 13, System 5, Abmelden 16, Abbruch 42,
Angebot 54).

Co-Authored-By: Claude Opus 5 <[email protected]>
2026-08-25 12:12:31 +02:00

156 lines
6.6 KiB
JavaScript

/* =====================================================================
Prueft, dass Kacheln und Bilder auf ALLEN Seiten auf den Zeiger
reagieren -- nicht nur im Verwaltungsbereich.
Warum als eigener Durchlauf: Die Effekte liegen im Grundsystem
(webdesign.css und wd-core.js) und gelten damit fuer jede Seite. Eine
Pruefung, die nur eine Seite ansieht, wuerde nicht auffallen lassen,
wenn eine andere Seite den Effekt still ueberschreibt. Genau das ist
passiert: ".wd-bereit .wd-auf.wd-sichtbar" setzt "transform: none"
und hat mit hoeherer Spezifitaet die Neigung geloescht -- sichtbar
nur auf Seiten, deren Kacheln eine Einblendung tragen.
===================================================================== */
import { chromium } from "playwright";
import http from "http";
import fs from "fs";
import path from "path";
const TYP = {
".html": "text/html", ".css": "text/css", ".js": "text/javascript",
".png": "image/png", ".svg": "image/svg+xml", ".webp": "image/webp",
".json": "application/json", ".ico": "image/x-icon", ".jpg": "image/jpeg",
};
const srv = http.createServer((q, r) => {
const p = path.join(process.cwd(), decodeURIComponent(q.url.split("?")[0]));
if (fs.existsSync(p) && !p.endsWith("/")) {
r.writeHead(200, { "content-type": TYP[path.extname(p)] || "text/plain" });
return r.end(fs.readFileSync(p));
}
r.writeHead(404);
r.end("");
});
let ok = 0, fehl = 0;
const pruefe = (name, gut, info) => {
if (gut) { ok++; console.log(" ok " + name + (info ? " -> " + info : "")); }
else { fehl++; console.log(" FEHL " + name + (info ? " -> " + info : "")); }
};
const SEITEN = ["index", "leistungen", "ablauf", "portfolio", "ueber", "portal"];
srv.listen(4405, async () => {
const browser = await chromium.launch();
console.log("1. NEIGEN SICH DIE KACHELN AUF JEDER SEITE?");
for (const name of SEITEN) {
const seite = await browser.newPage({ viewport: { width: 1440, height: 900 } });
const skriptfehler = [];
seite.on("pageerror", (e) => skriptfehler.push(String(e).slice(0, 110)));
await seite.goto(`http://127.0.0.1:4405/webdesign/${name}.html`);
/* Die Startseite legt beim Laden einen Vorhang ueber alles. Wer zu
frueh misst, trifft den Vorhang statt der Kachel. */
await seite.waitForTimeout(4500);
const karte = seite.locator(".wd-karte").first();
if (await karte.count() === 0) {
pruefe(`${name}: Kachel vorhanden`, false, "keine .wd-karte");
await seite.close();
continue;
}
await karte.scrollIntoViewIfNeeded();
await seite.waitForTimeout(700);
/* Einen Punkt suchen, der WIRKLICH auf der Kachel liegt und im
Fenster sichtbar ist. Eine Portfolio-Kachel ist ueber 1400 Punkte
hoch -- ein fester Anteil ihrer Hoehe landet ausserhalb des
Bildschirms, und dann misst der Test das Nichts. */
const ziel = await seite.evaluate(() => {
const k = document.querySelector(".wd-karte");
const r = k.getBoundingClientRect();
const x = Math.round(r.left + Math.min(r.width * 0.25, 200));
const y = Math.round(Math.max(80, Math.min(r.top + 60, window.innerHeight - 80)));
const e = document.elementFromPoint(x, y);
return { x, y, trifft: !!(e && e.closest(".wd-karte")) };
});
if (!ziel.trifft) {
pruefe(`${name}: Messpunkt liegt auf der Kachel`, false, JSON.stringify(ziel));
await seite.close();
continue;
}
/* Mit steps bewegen, sonst entsteht kein pointermove. */
await seite.mouse.move(ziel.x + 80, ziel.y + 30, { steps: 8 });
await seite.mouse.move(ziel.x, ziel.y, { steps: 14 });
await seite.waitForTimeout(600);
const d = await karte.evaluate((e) => ({
nx: parseFloat(e.style.getPropertyValue("--wd-nx")),
matrix: getComputedStyle(e).transform,
lumen: getComputedStyle(e).getPropertyValue("--wd-lumen").trim(),
}));
pruefe(`${name}: die Kachel neigt sich`,
d.matrix.startsWith("matrix3d") && !Number.isNaN(d.nx),
`nx ${d.nx}`);
/* Klein halten: Alles ueber neun Grad verzerrt die Schrift. */
if (d.matrix.startsWith("matrix3d")) {
const zahlen = d.matrix.slice(d.matrix.indexOf("(") + 1, -1).split(",").map(Number);
const winkel = Math.abs(Math.asin(Math.max(-1, Math.min(1, zahlen[2]))) * 180 / Math.PI);
pruefe(`${name}: und bleibt flach genug`, winkel <= 9, winkel.toFixed(1) + " Grad");
}
/* Beim Verlassen zuruecksetzen. */
await seite.mouse.move(5, 5, { steps: 12 });
await seite.waitForTimeout(600);
const zurueck = await karte.evaluate((e) => e.style.getPropertyValue("--wd-nx"));
pruefe(`${name}: stellt sich beim Verlassen zurueck`, zurueck === "0", zurueck);
pruefe(`${name}: kein Skriptfehler`, skriptfehler.length === 0, skriptfehler[0] || "");
await seite.close();
}
console.log("\n2. DIE EINBLENDUNG DARF DIE NEIGUNG NICHT LOESCHEN");
const s2 = await browser.newPage({ viewport: { width: 1440, height: 900 } });
await s2.goto("http://127.0.0.1:4405/webdesign/leistungen.html");
await s2.waitForTimeout(2500);
const einblendung = await s2.evaluate(() => {
const k = document.querySelector(".wd-auf.wd-sichtbar") ||
document.querySelector(".wd-auf");
if (!k) return null;
const st = getComputedStyle(k);
return { translate: st.translate, transform: st.transform };
});
/* Der Kern: Die Einblendung muss ueber "translate" laufen. Nutzt sie
"transform", loescht ihr hoeher gewichtetes "transform: none" die
Neigung -- und zwar still, ohne Fehlermeldung. */
pruefe("die Einblendung nutzt translate, nicht transform",
einblendung && einblendung.translate !== undefined,
einblendung ? `translate: ${einblendung.translate}` : "kein .wd-auf gefunden");
await s2.close();
console.log("\n3. BEI REDUZIERTER BEWEGUNG IST ALLES AUS");
const ruhig = await browser.newPage({
viewport: { width: 1440, height: 900 }, reducedMotion: "reduce" });
await ruhig.goto("http://127.0.0.1:4405/webdesign/leistungen.html");
await ruhig.waitForTimeout(2000);
const still = await ruhig.evaluate(() => {
const k = document.querySelector(".wd-karte");
return {
transform: getComputedStyle(k).transform,
sichtbar: getComputedStyle(k).opacity,
};
});
pruefe("keine Neigung", still.transform === "none", still.transform);
/* Abschalten heisst NICHT verschwinden: Die Kachel muss sichtbar
bleiben, auch wenn die Einblendung nicht laeuft. */
pruefe("die Kachel ist trotzdem sichtbar", parseFloat(still.sichtbar) > 0.9,
still.sichtbar);
await ruhig.close();
console.log(`\n===== ${ok} bestanden, ${fehl} fehlgeschlagen =====`);
await browser.close();
srv.close();
process.exit(fehl ? 1 : 0);
});