Calendar/.workbench/stacking-test-desc.txt

81 lines
5.7 KiB
Text
Raw Normal View History

## 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:0011:00, *Når* stack beregnes, *Så* `A.prev=null` og `A.stackLevel=1` (SL2).
2. **Simpel overlap**
*Givet* A 10:0013:00 og B 10:4511:15 i samme lane, *Når* stack beregnes, *Så* `B.prev='A'` og `B.stackLevel=2` (SL1SL3).
3. **Fler-leddet overlap**
*Givet* A 1013, B 10:4511:15, C 11:0011:30, *Når* stack beregnes, *Så* `B.stackLevel=2`, `C.stackLevel≥2`, ingen huller i levels (SL5).
4. **Ingen overlap**
*Givet* A 10:0011:00 og B 11:3012: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) 1013 og B(lane2) 10:1511: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 (SL5SL6).
8. **Resize der fjerner overlap**
*Givet* A 1013 og B 10:4511:15 (stacked), *Når* B resizes til 13:0013: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 Bs titel læses fuldt ud, og As 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 (17)
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.