from decimal import Decimal import pytest from app.engine.pie import UEBRIGE, pie_slices D = Decimal def test_leer_und_nullwerte(): assert pie_slices([]) == [] assert pie_slices([("A", D("0")), ("B", D("-5"))]) == [] def test_segmente_lueckenlos_und_anteile(): sl = pie_slices([("C", D("20")), ("A", D("50")), ("B", D("30"))]) assert [s.label for s in sl] == ["A", "B", "C"] assert [s.color for s in sl] == ["s1", "s2", "s3"] assert [s.share for s in sl] == [D("50.0"), D("30.0"), D("20.0")] assert sl[0].start == 0.0 and sl[-1].end == pytest.approx(1.0) for a, b in zip(sl, sl[1:]): assert a.end == pytest.approx(b.start) assert sl[0].path.startswith("M 0 0 L 0.0000 -1.0000 A 1 1 0 0 1 ") def test_large_arc_flag(): a, b = pie_slices([("A", D("70")), ("B", D("30"))]) assert " A 1 1 0 1 1 " in a.path assert " A 1 1 0 0 1 " in b.path def test_einzelsegment_ist_vollkreis(): (s,) = pie_slices([("A", D("12.34"))]) assert s.path is None and s.share == D("100.0") and s.color == "s1" def test_kleine_werte_zu_uebrige(): sl = pie_slices([("A", D("95")), ("B", D("2")), ("C", D("2")), ("D", D("1"))]) assert [s.label for s in sl] == ["A", UEBRIGE] u = sl[1] assert (u.value, u.color, u.merged, u.members) == (D("5"), "uebrige", True, ("B", "C", "D")) def test_einzelner_kleiner_wert_behaelt_namen(): sl = pie_slices([("A", D("98")), ("B", D("2"))]) assert [(s.label, s.color, s.merged) for s in sl] == [("A", "s1", False), ("B", "uebrige", False)] def test_hoechstens_acht_benannte_segmente(): sl = pie_slices([(f"K{i}", D("10")) for i in range(10)], rest=D("5"), rest_label="Frei verfügbar") assert [s.color for s in sl] == ["s1", "s2", "s3", "s4", "s5", "s6", "s7", "s8", "uebrige", "frei"] assert sl[-2].merged and sl[-2].members == ("K8", "K9") def test_acht_kategorien_ohne_uebrige(): sl = pie_slices([(f"K{i}", D("10")) for i in range(8)]) assert [s.color for s in sl] == [f"s{i}" for i in range(1, 9)] assert not any(s.merged for s in sl) def test_rest_wird_nie_zusammengefasst(): sl = pie_slices([("A", D("99.5"))], rest=D("0.5"), rest_label="Frei verfügbar") assert [(s.label, s.color, s.merged) for s in sl] == [("A", "s1", False), ("Frei verfügbar", "frei", False)] assert sl[1].share == D("0.5") def test_nur_rest_ist_vollkreis(): (s,) = pie_slices([], rest=D("100"), rest_label="Frei verfügbar") assert (s.label, s.color, s.path) == ("Frei verfügbar", "frei", None) def test_rest_none_oder_null_ignoriert(): assert len(pie_slices([("A", D("1"))], rest=None)) == 1 assert len(pie_slices([("A", D("1"))], rest=D("0"), rest_label="X")) == 1