Setzt Phase 2 aus Visualization.md um: Vanilla-SVG-Buero-Szene (Waende, 2 Tueren, 8 Schreibtische, Kanban-Board-Rahmen mit 7 Spalten, Monitor-Wand mit Event-/System-/ KPI-Monitor) ohne Animation, gespeist mit statischen Demo-Daten im Format der Phase-1-API-Responses. Board-Stapel-Logik (>5 Tickets, Done-Spalte als Dauerstapel) folgt Detailantworten.md F2/F3. Reine Layout-Logik (html/js/office-scene.js) ist ausgelagert und mit dem Node- Testrunner abgedeckt (100% Zeilenabdeckung, tests/frontend/), das DOM-Rendering (office-render.js) bleibt bewusst duenne Glue-Logik. Docker-Compose um web- (nginx, serviert html/) und frontend-Service (node, "npm test") erweitert, analog zum bestehenden api-Service und zum NC-Gantt-Vorbild: kein PHP/Node auf dem Host noetig. Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
91 lines
3.3 KiB
JavaScript
91 lines
3.3 KiB
JavaScript
import test from "node:test";
|
|
import assert from "node:assert/strict";
|
|
import {
|
|
BOARD_COLUMNS,
|
|
buildBoardColumnLayout,
|
|
buildDeskLayout,
|
|
buildSystemTiles,
|
|
buildEventLines,
|
|
MAX_SYSTEM_TILES,
|
|
MAX_EVENT_LINES,
|
|
DEFAULT_DESK_COUNT,
|
|
} from "../../html/js/office-scene.js";
|
|
|
|
test("buildBoardColumnLayout liefert alle Spalten in API.md-Reihenfolge", () => {
|
|
const layout = buildBoardColumnLayout({});
|
|
assert.deepEqual(
|
|
layout.map((c) => c.key),
|
|
BOARD_COLUMNS.map((c) => c.key)
|
|
);
|
|
});
|
|
|
|
test("buildBoardColumnLayout zeigt Tickets bis einschliesslich 5 einzeln an", () => {
|
|
const layout = buildBoardColumnLayout({ bereit: 5 });
|
|
const bereit = layout.find((c) => c.key === "bereit");
|
|
assert.equal(bereit.visibleNotes, 5);
|
|
assert.equal(bereit.stackCount, 0);
|
|
});
|
|
|
|
test("buildBoardColumnLayout stapelt ab dem 5. Ticket (F3): aelteste 4 einzeln + Rest als Stapel", () => {
|
|
const layout = buildBoardColumnLayout({ backlog: 8 });
|
|
const backlog = layout.find((c) => c.key === "backlog");
|
|
assert.equal(backlog.visibleNotes, 4);
|
|
assert.equal(backlog.stackCount, 4);
|
|
assert.equal(backlog.count, 8);
|
|
});
|
|
|
|
test("buildBoardColumnLayout stellt die Spalte done immer als Stapel dar (F2), unabhaengig von der Anzahl", () => {
|
|
const wenige = buildBoardColumnLayout({ done: 2 }).find((c) => c.key === "done");
|
|
assert.equal(wenige.visibleNotes, 0);
|
|
assert.equal(wenige.stackCount, 2);
|
|
|
|
const viele = buildBoardColumnLayout({ done: 42 }).find((c) => c.key === "done");
|
|
assert.equal(viele.visibleNotes, 0);
|
|
assert.equal(viele.stackCount, 42);
|
|
});
|
|
|
|
test("buildBoardColumnLayout behandelt fehlende/negative Zaehler als 0", () => {
|
|
const layout = buildBoardColumnLayout({ qa: -3 });
|
|
const qa = layout.find((c) => c.key === "qa");
|
|
assert.equal(qa.count, 0);
|
|
assert.equal(qa.visibleNotes, 0);
|
|
});
|
|
|
|
test("buildDeskLayout erzeugt genau DEFAULT_DESK_COUNT Schreibtische", () => {
|
|
const desks = buildDeskLayout([]);
|
|
assert.equal(desks.length, DEFAULT_DESK_COUNT);
|
|
assert.ok(desks.every((d) => d.agent === null));
|
|
});
|
|
|
|
test("buildDeskLayout ordnet Agenten der Reihe nach Schreibtischen zu und ignoriert Ueberschuss", () => {
|
|
const agents = Array.from({ length: DEFAULT_DESK_COUNT + 2 }, (_, i) => ({
|
|
name: `Agent${i}`,
|
|
role: "entwickler",
|
|
}));
|
|
const desks = buildDeskLayout(agents);
|
|
assert.equal(desks.length, DEFAULT_DESK_COUNT);
|
|
assert.equal(desks[0].agent.name, "Agent0");
|
|
assert.equal(desks[DEFAULT_DESK_COUNT - 1].agent.name, `Agent${DEFAULT_DESK_COUNT - 1}`);
|
|
});
|
|
|
|
test("buildDeskLayout ergaenzt fehlende pose auf idle", () => {
|
|
const desks = buildDeskLayout([{ name: "Alice", role: "entwickler" }], 1);
|
|
assert.equal(desks[0].agent.pose, "idle");
|
|
});
|
|
|
|
test("buildSystemTiles sortiert Fehler vor ok und kappt bei MAX_SYSTEM_TILES", () => {
|
|
const systems = Array.from({ length: MAX_SYSTEM_TILES + 3 }, (_, i) => ({
|
|
id: `s${i}`,
|
|
status: i === MAX_SYSTEM_TILES ? "error" : "ok",
|
|
}));
|
|
const tiles = buildSystemTiles(systems);
|
|
assert.equal(tiles.length, MAX_SYSTEM_TILES);
|
|
assert.equal(tiles[0].status, "error");
|
|
});
|
|
|
|
test("buildEventLines kappt bei MAX_EVENT_LINES und behaelt die Reihenfolge bei", () => {
|
|
const events = Array.from({ length: MAX_EVENT_LINES + 4 }, (_, i) => ({ id: i }));
|
|
const lines = buildEventLines(events);
|
|
assert.equal(lines.length, MAX_EVENT_LINES);
|
|
assert.equal(lines[0].id, 0);
|
|
});
|