Aufgefallen an einem Screenshot: Bei einer Kachel lag oben ein lila Streifen, bei den anderen fehlte jede Farbe. Die Ursache war meine eigene Aenderung von gerade eben. Der Glanzstreifen kam ins ::before -- dort wohnt aber schon die farbige Oberkante (.wd-karte--kappe), und zwar seit dem urspruenglichen Bau der Seite. Ein Element hat nur ZWEI Pseudoelemente, und beide waren belegt: ::after traegt den Lichtkegel, ::before die Kante. Der Glanz hat sich das ::before genommen und die Kante damit still ueberschrieben. Warum es nur teilweise auffiel: ".wd-karte--lila.wd-karte--kappe::before" hat zwei Klassen und damit mehr Gewicht als mein ".wd-karte::before" -- die lila Farbe blieb also stehen, die blaue verschwand. Deshalb sah es aus wie ein Zufall statt wie ein Fehler. DIE LOESUNG Glanzstreifen und Lichtkegel teilen sich jetzt das ::after -- als zwei Hintergrundebenen desselben Pseudoelements. Das ::before ist wieder frei fuer die Oberkante. Beides funktioniert unveraendert: Der Glanz wandert weiterhin mit der Neigung (er nimmt --wd-nx in seinen Winkel auf), der Lichtkegel weiterhin mit dem Zeiger. DIE PRUEFUNG DAZU Ein neuer Abschnitt in pruef-bewegung.mjs misst alle acht Kacheln mit Oberkante: 5 Punkte Hoehe, ganz oben sitzend, Farbe vorhanden -- und ausdruecklich BLAUE UND LILA zusammen. Haette der Test nur eine Sorte angesehen, waere genau dieser Fehler wieder durchgerutscht, denn die lila Fassung war ja nie kaputt. Dazu die Gegenprobe, dass der Glanz nicht einfach verlorengegangen ist: Das ::after muss beide Verlaeufe tragen. Geprueft: 296 Pruefungen gruen (Bewegung 32, Portfolio 19, Verwaltung 62, CRYONOVA 53, Blickfang 13, System 5, Abmelden 16, Abbruch 42, Angebot 54). Co-Authored-By: Claude Opus 5 <[email protected]>
199 lines
8.7 KiB
JavaScript
199 lines
8.7 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("\n2b. DIE FARBIGE OBERKANTE DARF NICHT VERSCHWINDEN");
|
|
const s3 = await browser.newPage({ viewport: { width: 1440, height: 900 } });
|
|
await s3.goto("http://127.0.0.1:4405/webdesign/index.html");
|
|
await s3.waitForTimeout(4500);
|
|
const kappen = await s3.evaluate(() =>
|
|
[...document.querySelectorAll(".wd-karte--kappe")].slice(0, 8).map((k) => {
|
|
const v = getComputedStyle(k, "::before");
|
|
return {
|
|
lila: k.classList.contains("wd-karte--lila"),
|
|
hoehe: parseFloat(v.height),
|
|
oben: parseFloat(v.top),
|
|
farbig: /gradient/.test(v.backgroundImage),
|
|
};
|
|
}));
|
|
pruefe("es gibt Kacheln mit Oberkante", kappen.length > 0, kappen.length + " Stueck");
|
|
|
|
/* Das ist der Kern: Ein Element hat nur ZWEI Pseudoelemente. Der
|
|
Glanzstreifen lag zuerst ebenfalls im ::before und hat die farbige
|
|
Oberkante stillschweigend geloescht -- sichtbar als "bei einer
|
|
Kachel Farbe oben, bei den anderen keine". Die Lila-Fassung hat
|
|
eine Klasse mehr und damit mehr Gewicht, ihre Farbe blieb; die
|
|
blaue verschwand. Deshalb wird hier ausdruecklich BEIDES geprueft. */
|
|
pruefe("jede davon hat eine 5 Punkte hohe Kante ganz oben",
|
|
kappen.every((k) => k.hoehe === 5 && k.oben === 0),
|
|
kappen.map((k) => k.hoehe + "px").join(" "));
|
|
pruefe("und jede traegt Farbe", kappen.every((k) => k.farbig),
|
|
kappen.filter((k) => k.farbig).length + " von " + kappen.length);
|
|
pruefe("blaue UND lila Kacheln sind dabei",
|
|
kappen.some((k) => k.lila) && kappen.some((k) => !k.lila),
|
|
kappen.filter((k) => k.lila).length + " lila, " +
|
|
kappen.filter((k) => !k.lila).length + " blau");
|
|
|
|
/* Der Glanz muss trotzdem noch da sein -- er ist jetzt die erste von
|
|
zwei Hintergrundebenen im ::after. */
|
|
const glanz = await s3.evaluate(() => {
|
|
const k = document.querySelector(".wd-karte");
|
|
return getComputedStyle(k, "::after").backgroundImage;
|
|
});
|
|
pruefe("der Glanzstreifen liegt jetzt beim Lichtkegel",
|
|
/linear-gradient/.test(glanz) && /radial-gradient/.test(glanz),
|
|
(glanz.match(/gradient/g) || []).length + " Verlaeufe");
|
|
await s3.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);
|
|
});
|