26fbd11b73
- Treppe referenz links/mitte/rechts (Stair.referenz, Default mitte): Perp-Versatz referenzMidShift auf start/center, Lauflinie/Pfeil bleiben visuell zentriert. - Fenster Fluegel-Mittelpfosten (Opening.wingCount 1-4, Default 1): wingCount-1 Querlinien im Rahmen (window-mullion), nur mittel/fein. - Tuer-Typ wandoeffnung (Opening.doorType, Default normal): ueberspringt Tuerblatt + Schwenkbogen, Laibung/Sturz bleiben. - Alle Modellfelder optional/rueckwaertskompatibel. 17 neue Tests. vitest 292/292, tsc sauber.
150 lines
5.2 KiB
TypeScript
150 lines
5.2 KiB
TypeScript
/**
|
|
* Unit-Tests für die Öffnungs-Symbole im Grundriss (generatePlan):
|
|
* • Item 5 — Fenster Flügel-Mittelpfosten: bei wingCount=3 werden genau 2
|
|
* Pfosten-Linien (Querlinien) erzeugt; wingCount=1/undefined ⇒ keine.
|
|
* • Item 6 — Tür-Typ „wandoeffnung": kein Türblatt, kein Schwenkbogen (arc);
|
|
* „normal" (Default) zeichnet Blatt + Bogen wie bisher.
|
|
*/
|
|
|
|
import { describe, it, expect } from "vitest";
|
|
import { generatePlan } from "./generatePlan";
|
|
import type { Opening, Project, Wall } from "../model/types";
|
|
|
|
/** Minimalprojekt mit einer Wand + einer Öffnung, konfigurierbar. */
|
|
function projectWithOpening(opening: Opening): Project {
|
|
const wall: Wall = {
|
|
id: "W1",
|
|
type: "wall",
|
|
floorId: "eg",
|
|
categoryCode: "20",
|
|
start: { x: 0, y: 0 },
|
|
end: { x: 4, y: 0 },
|
|
wallTypeId: "aw",
|
|
height: 2.6,
|
|
};
|
|
return {
|
|
id: "t",
|
|
name: "T",
|
|
lineStyles: [{ id: "thin", name: "d", weight: 0.13, color: "#111", dash: null }],
|
|
hatches: [{ id: "none", name: "Ohne", pattern: "none", scale: 1, angle: 0, color: "#111" }],
|
|
components: [{ id: "a", name: "A", color: "#d8d2c7", hatchId: "none", joinPriority: 10 }],
|
|
wallTypes: [{ id: "aw", name: "AW", layers: [{ componentId: "a", thickness: 0.3 }] }],
|
|
drawingLevels: [
|
|
{ id: "eg", name: "EG", kind: "floor", visible: true, locked: false, floorHeight: 2.6, cutHeight: 1.0, baseElevation: 0 },
|
|
],
|
|
layers: [
|
|
{ code: "20", name: "Wände", color: "#0a0a0a", lw: 0.5, visible: true, locked: false },
|
|
{ code: "21", name: "Öffnungen", color: "#0a0a0a", lw: 0.3, visible: true, locked: false },
|
|
],
|
|
walls: [wall],
|
|
doors: [],
|
|
openings: [opening],
|
|
ceilings: [],
|
|
stairs: [],
|
|
rooms: [],
|
|
drawings2d: [],
|
|
context: [],
|
|
};
|
|
}
|
|
|
|
const visible = new Set(["20", "21"]);
|
|
|
|
/** Basis-Fenster (Brüstung 0, damit keine Sill-Linie mitzählt). */
|
|
const baseWindow: Opening = {
|
|
id: "F1",
|
|
type: "opening",
|
|
hostWallId: "W1",
|
|
categoryCode: "21",
|
|
kind: "window",
|
|
position: 1.0,
|
|
width: 1.6,
|
|
height: 1.2,
|
|
sillHeight: 0,
|
|
};
|
|
|
|
/** Basis-Tür. */
|
|
const baseDoor: Opening = {
|
|
id: "T1",
|
|
type: "opening",
|
|
hostWallId: "W1",
|
|
categoryCode: "21",
|
|
kind: "door",
|
|
position: 1.0,
|
|
width: 0.9,
|
|
height: 2.0,
|
|
sillHeight: 0,
|
|
swing: "left",
|
|
hinge: "start",
|
|
};
|
|
|
|
/** Zählt Mittelpfosten-Linien (cls "window-mullion") im Plan. */
|
|
const mullionCount = (p: Project) =>
|
|
generatePlan(p, "eg", visible, undefined, "mittel").primitives.filter(
|
|
(pr) => pr.kind === "line" && pr.cls === "window-mullion",
|
|
).length;
|
|
|
|
describe("generatePlan — Fenster Flügel-Mittelpfosten (Item 5)", () => {
|
|
it("wingCount=3 erzeugt genau 2 Pfosten-Linien", () => {
|
|
expect(mullionCount(projectWithOpening({ ...baseWindow, wingCount: 3 }))).toBe(2);
|
|
});
|
|
|
|
it("wingCount=1 erzeugt keine Pfosten", () => {
|
|
expect(mullionCount(projectWithOpening({ ...baseWindow, wingCount: 1 }))).toBe(0);
|
|
});
|
|
|
|
it("ohne wingCount (Default) keine Pfosten — rückwärtskompatibel", () => {
|
|
expect(mullionCount(projectWithOpening({ ...baseWindow }))).toBe(0);
|
|
});
|
|
|
|
it("wingCount=4 erzeugt 3 Pfosten", () => {
|
|
expect(mullionCount(projectWithOpening({ ...baseWindow, wingCount: 4 }))).toBe(3);
|
|
});
|
|
|
|
it("Pfosten sind reine Linien ohne Strichmuster (kein dash)", () => {
|
|
const plan = generatePlan(projectWithOpening({ ...baseWindow, wingCount: 3 }), "eg", visible, undefined, "mittel");
|
|
const mullions = plan.primitives.filter(
|
|
(pr) => pr.kind === "line" && pr.cls === "window-mullion",
|
|
);
|
|
for (const m of mullions) {
|
|
expect((m as { dash?: number[] | null }).dash ?? null).toBeNull();
|
|
}
|
|
});
|
|
|
|
it("bei grob keine Pfosten (nur mittel/fein)", () => {
|
|
const plan = generatePlan(projectWithOpening({ ...baseWindow, wingCount: 3 }), "eg", visible, undefined, "grob");
|
|
const n = plan.primitives.filter((pr) => pr.kind === "line" && pr.cls === "window-mullion").length;
|
|
expect(n).toBe(0);
|
|
});
|
|
});
|
|
|
|
describe("generatePlan — Tür-Typ wandoeffnung (Item 6)", () => {
|
|
/** Zählt Bögen (arc-Primitive) im Plan. */
|
|
const arcCount = (p: Project, detail: "grob" | "mittel" | "fein" = "mittel") =>
|
|
generatePlan(p, "eg", visible, undefined, detail).primitives.filter((pr) => pr.kind === "arc").length;
|
|
/** Zählt Türblatt-Linien (cls "door-leaf"). */
|
|
const leafCount = (p: Project) =>
|
|
generatePlan(p, "eg", visible, undefined, "mittel").primitives.filter(
|
|
(pr) => pr.kind === "line" && pr.cls === "door-leaf",
|
|
).length;
|
|
|
|
it("wandoeffnung erzeugt KEINE Bögen (arc)", () => {
|
|
expect(arcCount(projectWithOpening({ ...baseDoor, doorType: "wandoeffnung" }))).toBe(0);
|
|
});
|
|
|
|
it("wandoeffnung erzeugt KEIN Türblatt", () => {
|
|
expect(leafCount(projectWithOpening({ ...baseDoor, doorType: "wandoeffnung" }))).toBe(0);
|
|
});
|
|
|
|
it("normal (Default) erzeugt Türblatt + Schwenkbogen", () => {
|
|
const normal = projectWithOpening({ ...baseDoor, doorType: "normal" });
|
|
expect(leafCount(normal)).toBe(1);
|
|
expect(arcCount(normal)).toBe(1);
|
|
});
|
|
|
|
it("ohne doorType (Default) verhält sich wie normal — rückwärtskompatibel", () => {
|
|
const def = projectWithOpening({ ...baseDoor });
|
|
expect(leafCount(def)).toBe(1);
|
|
expect(arcCount(def)).toBe(1);
|
|
});
|
|
});
|