Resource Manager: Materialien-Tab mit PBR-Kugel-Vorschau, Suche und Kategorie-Chips
Geteilter Offscreen-three.js-Renderer (ein Kontext, serielle Queue, Cache per Map-Signatur) rendert 128px-Kugeln lazy via IntersectionObserver. Kategorie-Chips aus der Bibliothek abgeleitet, uneinheitliche Manifest- Schreibweisen normalisiert; Suche und Kategorie kombinierbar. Kachel-Klick markiert aktiv (gleiche Sprache wie MaterialPicker). Puppeteer-Probe scripts/probe-material-tiles.mjs prüft Grid, Lazy-Render und Filter.
This commit is contained in:
@@ -0,0 +1,109 @@
|
||||
// Probe (Materialien-Tab — PBR-Kugel-Vorschau + Filter): öffnet den Ressourcen-
|
||||
// Manager, wechselt in den neuen „Materialien"-Tab, prüft dass Kacheln
|
||||
// erscheinen, mindestens eine Kugel-Vorschau (Bild) gerendert wurde, und dass
|
||||
// Such-/Kategorie-Filter die Trefferzahl verändern.
|
||||
//
|
||||
// Aufruf: PROBE_URL=http://localhost:5187/ node scripts/probe-material-tiles.mjs
|
||||
import puppeteer from "puppeteer";
|
||||
|
||||
const URL = process.env.PROBE_URL || "http://localhost:5187/";
|
||||
const OUT = "scripts";
|
||||
|
||||
const browser = await puppeteer.launch({
|
||||
headless: "new",
|
||||
args: ["--no-sandbox", "--use-gl=swiftshader", "--enable-unsafe-swiftshader"],
|
||||
});
|
||||
const page = await browser.newPage();
|
||||
await page.setViewport({ width: 1360, height: 900, deviceScaleFactor: 2 });
|
||||
|
||||
const logs = [];
|
||||
page.on("console", (m) => logs.push(`[${m.type()}] ${m.text()}`));
|
||||
page.on("pageerror", (e) => logs.push(`[PAGEERROR] ${e.message}`));
|
||||
|
||||
const sleep = (ms) => new Promise((r) => setTimeout(r, ms));
|
||||
const shot = (n) => page.screenshot({ path: `${OUT}/${n}` });
|
||||
|
||||
async function clickByText(selector, text) {
|
||||
const handle = await page.evaluateHandle(
|
||||
(sel, t) =>
|
||||
[...document.querySelectorAll(sel)].find((el) => el.textContent.includes(t)),
|
||||
selector,
|
||||
text,
|
||||
);
|
||||
const el = handle.asElement();
|
||||
if (!el) throw new Error(`nicht gefunden: ${selector} ~ "${text}"`);
|
||||
await el.click();
|
||||
return el;
|
||||
}
|
||||
|
||||
await page.goto(URL, { waitUntil: "domcontentloaded", timeout: 20000 });
|
||||
await page.waitForSelector(".topbar", { timeout: 20000 });
|
||||
await sleep(600);
|
||||
|
||||
// 1) Ressourcen öffnen → in den Materialien-Tab wechseln.
|
||||
await page.waitForSelector('button[aria-label="Ressourcen"]', { timeout: 8000 });
|
||||
await page.click('button[aria-label="Ressourcen"]');
|
||||
await page.waitForSelector(".res-drawer", { timeout: 8000 });
|
||||
await clickByText(".res-tab-btn", "Materialien");
|
||||
await page.waitForSelector(".mat-lib-grid .mat-tile", { timeout: 8000 });
|
||||
|
||||
const tileCount = await page.$$eval(".mat-lib-grid .mat-tile", (els) => els.length);
|
||||
console.log("Material-Kacheln (ungefiltert):", tileCount);
|
||||
|
||||
// 2) Warten, bis mindestens eine Kugel-Vorschau gerendert ist (Bild im Tile).
|
||||
await page.waitForFunction(
|
||||
() => document.querySelectorAll(".mat-sphere img").length > 0,
|
||||
{ timeout: 10000 },
|
||||
);
|
||||
// Sichtbare Kacheln lazy nachladen lassen (Warteschlange rendert seriell).
|
||||
await sleep(2500);
|
||||
const renderedCount = await page.$$eval(".mat-sphere img", (els) => els.length);
|
||||
console.log("Gerenderte Kugel-Vorschauen (sichtbarer Bereich):", renderedCount);
|
||||
|
||||
// Erstes Vorschaubild darf kein leeres/transparentes 1x1-Pixelbild sein.
|
||||
const firstSrc = await page.$eval(".mat-sphere img", (img) => img.src);
|
||||
console.log("Erste Vorschau-DataURL-Länge:", firstSrc.length);
|
||||
|
||||
await shot("probe-material-tiles-1-grid.png");
|
||||
|
||||
// 3) Kategorie-Filter: erste konkrete Kategorie-Chip anklicken (nicht "Alle").
|
||||
const chipLabels = await page.$$eval(".mat-chip", (els) => els.map((e) => e.textContent));
|
||||
console.log("Kategorie-Chips:", chipLabels);
|
||||
const firstCategoryChip = chipLabels[1]; // Index 0 = "Alle".
|
||||
await clickByText(".mat-chip", firstCategoryChip);
|
||||
await sleep(300);
|
||||
const filteredByCategory = await page.$$eval(".mat-lib-grid .mat-tile", (els) => els.length);
|
||||
console.log(`Kacheln nach Kategorie-Filter ("${firstCategoryChip}"):`, filteredByCategory);
|
||||
await shot("probe-material-tiles-2-category.png");
|
||||
|
||||
// Filter zurücksetzen ("Alle").
|
||||
await clickByText(".mat-chip", "Alle");
|
||||
await sleep(200);
|
||||
|
||||
// 4) Textsuche: nach "Holz" suchen (mehrere Bibliotheks-Einträge betroffen).
|
||||
await page.type(".mat-search", "Holz");
|
||||
await sleep(400);
|
||||
const filteredByText = await page.$$eval(".mat-lib-grid .mat-tile", (els) => els.length);
|
||||
console.log('Kacheln nach Textsuche ("Holz"):', filteredByText);
|
||||
await shot("probe-material-tiles-3-search.png");
|
||||
|
||||
// 5) Kachel auswählen → aktiv-Zustand + Statuszeile prüfen.
|
||||
await page.click(".mat-lib-grid .mat-tile");
|
||||
await sleep(200);
|
||||
const hasActive = await page.$(".mat-lib-grid .mat-tile.active");
|
||||
const selectedLine = await page.$eval(".mat-lib-selected", (el) => el.textContent).catch(() => null);
|
||||
console.log("Aktive Kachel vorhanden:", !!hasActive, "| Auswahl-Zeile:", selectedLine);
|
||||
await shot("probe-material-tiles-4-selected.png");
|
||||
|
||||
console.log("--- console ---");
|
||||
for (const l of logs.slice(-30)) console.log(l);
|
||||
|
||||
if (tileCount === 0) throw new Error("Keine Material-Kacheln gefunden");
|
||||
if (renderedCount === 0) throw new Error("Keine Kugel-Vorschau gerendert");
|
||||
if (firstSrc.length < 200) throw new Error("Vorschau-DataURL wirkt leer");
|
||||
if (filteredByCategory >= tileCount) throw new Error("Kategorie-Filter hat nichts gefiltert");
|
||||
if (filteredByText >= tileCount) throw new Error("Textsuche hat nichts gefiltert");
|
||||
if (!hasActive) throw new Error("Kachel-Auswahl hat keinen aktiven Zustand gesetzt");
|
||||
|
||||
await browser.close();
|
||||
console.log("done");
|
||||
Reference in New Issue
Block a user