## Testplan – Stack link (`data-stack-link`) & z-index


### A. Regler (krav som testes)
- **SL1**: Hvert event har en gyldig `data-stack-link` JSON med felterne `{ prev, stackLevel }`.
- **SL2**: `stackLevel` ≥ 1 og heltal. Nederste event i en stack har `prev = null` og `stackLevel = 1`.
- **SL3**: `prev` refererer til **eksisterende** event-ID i **samme lane** (ingen cross-lane links).
- **SL4**: Kæden er **acyklisk** (ingen loops) og uden “dangling” referencer.
- **SL5**: For en given stack er levels **kontiguøse** (1..N uden huller).
- **SL6**: Ved **flyt/resize/slet** genberegnes stack-links deterministisk (samme input ⇒ samme output).
- **Z1**: z-index er en **strengt voksende funktion** af `stackLevel` (fx `zIndex = base + stackLevel`).
- **Z2**: For overlappende events i **samme lane** gælder: højere `stackLevel` **renderes visuelt ovenpå** lavere level (ingen tekst skjules af et lavere level).
- **Z3**: z-index må **ikke** afhænge af DOM-indsættelsesrækkefølge—kun af `stackLevel` (og evt. lane-offset).
- **Z4** (valgfrit): På tværs af lanes kan systemet enten bruge samme base eller lane-baseret offset (fx `zIndex = lane*100 + stackLevel`). Uanset valg må events i **samme lane** aldrig blive skjult af events i en **anden** lane, når de overlapper visuelt.


### B. Unit tests (logik for stack link)
1. **Basestack**
*Givet* en enkelt event A 10:00–11:00, *Når* stack beregnes, *Så* `A.prev=null` og `A.stackLevel=1` (SL2).
2. **Simpel overlap**
*Givet* A 10:00–13:00 og B 10:45–11:15 i samme lane, *Når* stack beregnes, *Så* `B.prev='A'` og `B.stackLevel=2` (SL1–SL3).
3. **Fler-leddet overlap**
*Givet* A 10–13, B 10:45–11:15, C 11:00–11:30, *Når* stack beregnes, *Så* `B.stackLevel=2`, `C.stackLevel≥2`, ingen huller i levels (SL5).
4. **Ingen overlap**
*Givet* A 10:00–11:00 og B 11:30–12:00 i samme lane, *Når* stack beregnes, *Så* `A.stackLevel=1`, `B.stackLevel=1`, `prev=null` for begge (SL2).
5. **Cross-lane isolation**
*Givet* A(lane1) 10–13 og B(lane2) 10:15–11:00, *Når* stack beregnes, *Så* `B.prev` **må ikke** pege på A (SL3).
6. **Acyklisk garanti**
*Givet* en vilkårlig mængde overlappende events, *Når* stack beregnes, *Så* kan traversal fra top → `prev` aldrig besøge samme ID to gange (SL4).
7. **Sletning i kæde**
*Givet* A→B→C (`prev`-kæde), *Når* B slettes, *Så* peger C.prev nu på A (eller `null` hvis A ikke findes), og levels reindekseres 1..N (SL5–SL6).
8. **Resize der fjerner overlap**
*Givet* A 10–13 og B 10:45–11:15 (stacked), *Når* B resizes til 13:00–13:30, *Så* `B.prev=null`, `B.stackLevel=1` (SL6).
9. **Determinisme**
*Givet* samme inputliste i samme sortering, *Når* stack beregnes to gange, *Så* er output (prev/stackLevel pr. event) identisk (SL6).


### C. Integration/DOM tests (z-index & rendering)
10. **Z-index mapping**
*Givet* mapping `zIndex = base + stackLevel`, *Når* tre overlappende events har levels 1,2,3, *Så* er `zIndex` hhv. stigende og uden lighed (Z1).
11. **Visuel prioritet**
*Givet* to overlappende events i samme lane med levels 1 (A) og 2 (B), *Når* kalenderen renderes, *Så* kan B’s titel læses fuldt ud, og A’s ikke dækker B (Z2).
12. **DOM-orden er irrelevant**
*Givet* to overlappende events, *Når* DOM-indsættelsesrækkefølgen byttes, *Så* er visuel orden uændret, styret af z-index (Z3).
13. **Lane-isolation**
*Givet* A(lane1, level 2) og B(lane2, level 1), *Når* de geometrisk overlapper (smal viewport), *Så* skjuler lane2 ikke lane1 i strid med reglen—afhængigt af valgt z-index strategi (Z4). Dokumentér valgt strategi.
14. **Tekst-visibility**
*Givet* N overlappende events, *Når* der renderes, *Så* er der ingen CSS-egenskaber (opacity/clip/overflow) der gør højere level mindre synlig end lavere (Z2).


### D. Scenarie-baserede tests (1–7)
15. **S1 – Overlap ovenpå**
Lunch `prev=Excursion`, `stackLevel=2`; `zIndex(Lunch) > zIndex(Excursion)`.
16. **S2 – Flere overlappende**
Lunch og Breakfast har `stackLevel≥2`; ingen huller 1..N; z-index følger levels.
17. **S3 – Side-by-side**
Overlappende events i samme lane har stigende `stackLevel`; venstre offset stiger med level; z-index følger levels.
18. **S4 – Sekvens**
For hvert overlap i sekvens: korrekt `prev` til nærmeste base; contiguøse levels; z-index stigende.
19. **S5 – <30 min ⇒ lane 2**
Lunch i lane 2; ingen `prev` der peger cross-lane; levels starter ved 1 i begge lanes; z-index valideres pr. lane.
20. **S6 – Stack + lane**
Lane 1: Excursion & Breakfast (levels 1..N). Lane 2: Lunch (level 1). Ingen cross-lane `prev`. Z-index korrekt i lane 1.
21. **S7 – Frivillig lane 2**
Events i lane 2 har egne levels startende på 1; z-index følger levels i hver lane.


### E. Edge cases
22. **Samme starttid**
To events med identisk start i samme lane fordeles deterministisk: det først behandlede bliver base (`level=1`), det næste `level=2`. Z-index følger.
23. **Mange levels**
*Givet* 6 overlappende events, *Når* der renderes, *Så* er levels 1..6 uden huller og z-index 6 er visuelt øverst.
24. **Ugyldigt JSON**
*Givet* en defekt `data-stack-link`, *Når* komponenten loader, *Så* logges fejl og stack genberegnes fra start/end (self-healing), hvorefter valid `data-stack-link` skrives (SL1, SL6).


### F. Implementationsnoter (hjælp til test)
- Z-index funktion bør være **enkel og auditérbar**, fx: `zIndex = 100 + stackLevel` (samme lane) eller `zIndex = lane*100 + stackLevel` (multi-lane isolation).
- Test for acykliskhed: lav traversal fra hver node: gentagen ID ⇒ fejl.
- Test for contiguity: hent alle `stackLevel` i en stack, sortér, forvent `[1..N]` uden huller.
- Test for cross-lane: sammenlign `event.dataset.lane` for `id` og dets `prev`—de skal være ens.