|
| 1 | +import { describe, expect, it } from "vitest" |
| 2 | +import { getMarkerHalfHeight } from "@/components/svgs/edges" |
| 3 | +import { MARKER_CONFIGS } from "@/constants" |
| 4 | + |
| 5 | +// The aggregation/composition diamond and the inheritance triangle sit side by |
| 6 | +// side in a class diagram, so what a reader perceives is their proportions, not |
| 7 | +// their absolute sizes. These pin the relationships that set the diamond's size. |
| 8 | + |
| 9 | +// Both shapes are inscribed in their bounding box, so width * height / 2 is |
| 10 | +// their exact area — a proxy for visual weight. |
| 11 | +const inkArea = (id: keyof typeof MARKER_CONFIGS) => { |
| 12 | + const { size, widthFactor, heightFactor } = MARKER_CONFIGS[id] |
| 13 | + return (size * widthFactor * (size * heightFactor)) / 2 |
| 14 | +} |
| 15 | + |
| 16 | +const height = (id: keyof typeof MARKER_CONFIGS) => getMarkerHalfHeight(id) * 2 |
| 17 | + |
| 18 | +describe("class diagram marker geometry", () => { |
| 19 | + it("draws both diamonds identically apart from the fill", () => { |
| 20 | + const { filled: _b, ...black } = MARKER_CONFIGS["black-rhombus"] |
| 21 | + const { filled: _w, ...white } = MARKER_CONFIGS["white-rhombus"] |
| 22 | + expect(black).toEqual(white) |
| 23 | + expect(MARKER_CONFIGS["black-rhombus"].filled).toBe(true) |
| 24 | + expect(MARKER_CONFIGS["white-rhombus"].filled).toBe(false) |
| 25 | + }) |
| 26 | + |
| 27 | + it("gives the diamond at least the inheritance triangle's visual weight", () => { |
| 28 | + // draw.io puts the diamond at ~1.32x the triangle's area, Mermaid at 1.0x. |
| 29 | + expect(inkArea("black-rhombus")).toBeGreaterThanOrEqual( |
| 30 | + inkArea("white-triangle") |
| 31 | + ) |
| 32 | + }) |
| 33 | + |
| 34 | + it("keeps the diamond no taller than the inheritance triangle", () => { |
| 35 | + // Height is the extent perpendicular to the edge: how far a marker overhangs |
| 36 | + // the node border it points at. |
| 37 | + expect(height("black-rhombus")).toBeLessThanOrEqual( |
| 38 | + height("white-triangle") |
| 39 | + ) |
| 40 | + }) |
| 41 | + |
| 42 | + it("keeps the diamond's thickness in the band used by reference tools", () => { |
| 43 | + // draw.io 0.588 (diamondThin), PlantUML 0.667, Mermaid 0.706. |
| 44 | + const { widthFactor, heightFactor } = MARKER_CONFIGS["black-rhombus"] |
| 45 | + const aspect = heightFactor / widthFactor |
| 46 | + expect(aspect).toBeGreaterThanOrEqual(0.588) |
| 47 | + expect(aspect).toBeLessThanOrEqual(0.706) |
| 48 | + }) |
| 49 | + |
| 50 | + it("keeps the diamond small enough to render unscaled in the edge-type dropdown", () => { |
| 51 | + // EdgeTypePreviewIcon shrinks markers whose half-height exceeds 11; only the |
| 52 | + // node-scale interface socket should need that. |
| 53 | + expect(getMarkerHalfHeight("black-rhombus")).toBeLessThanOrEqual(11) |
| 54 | + }) |
| 55 | +}) |
0 commit comments