WCAG 2.2 AA: wyłączalny skrót / oraz nawigacja po grafie bez przeciągania (2.1.4, 2.5.7, 2.1.1) - #763
Open
mpasternak wants to merge 21 commits into
Open
WCAG 2.2 AA: wyłączalny skrót / oraz nawigacja po grafie bez przeciągania (2.1.4, 2.5.7, 2.1.1)#763mpasternak wants to merge 21 commits into
mpasternak wants to merge 21 commits into
Conversation
Domyka dwa kryteria odroczone w iteracji z 2026-08-06 (2.1.4 skrot `/`, 2.5.7 przeciaganie grafu) plus 2.1.1 przy okazji, bo obsluga klawiatura kosztuje niewiele gdy funkcje nawigacyjne i tak powstaja dla przyciskow. Rozstrzygniecia: - 2.1.4 → mechanizm wylaczania w localStorage. Wzorce branzowe (GitHub: ustawienie konta; Gmail: dialog pod `?`) zakladaja zalogowanego uzytkownika z profilem, a audytowany zakres BPP to czesc publiczna, anonimowa — localStorage jest funkcjonalnym odpowiednikiem. Przelacznik w stopce, NIE na stronie deklaracji dostepnosci: ta jest konfigurowalna per uczelnia (pokazuj_deklaracje_dostepnosci 1/2/brak) i na czesci wdrozen nie istnieje albo prowadzi na serwer uczelni. - 2.5.7 → siedem przyciskow nawigacji (kierunki, zoom, dopasuj) nad wspolnym modulem czystych funkcji. Istniejaca wyszukiwarka wezlow NIE jest alternatywa: podswietla trafienia, ale nie przesuwa widoku. - 2.1.1 → te same funkcje pod strzalkami/+/-/Home przy focusie na kontenerze grafu. Klawisze +/- sa znakami drukowalnymi, wiec podlegaja 2.1.4 — spelniaja je trzecim wariantem (aktywne tylko przy focusie), wiec nie wymagaja przelacznika z czesci A. Nowe przyciski musza spelniac 2.5.8 (cel >=24x24 px) — naprawiajac 2.5.7 nie wolno zlamac sasiedniego kryterium. Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01E8RjSZWMR6L7fuRDJJZW4L
Recenzja zwrocila NIE z jednym znaleziskiem blokujacym; wszystkie zweryfikowane w kodzie i przyjete. BLOKUJACE — skrot `/` obslugiwany jest w CZTERECH miejscach, nie jednym. Spec latal wylacznie base.html:42, podczas gdy global_search_modal.html:1048 (wlaczany z top_bar.html:511, czyli obecny na tej samej stronie) wiaze wlasny, niezalezny handler, a browse/uczelnia.html:134 reaguje na `/` zamykajac baner. Wylaczenie preferencji nie dalo by nic — modal otwieralby wyszukiwarke mimo wszystko, a kryterium 2.1.4 pozostaloby niespelnione. Dodano inwentaryzacje wszystkich handlerow i objeto warunkiem wszystkie publiczne. Przy okazji: oba handlery w base.html i modalu odpalaja sie dzis rownolegle, wiec openGlobalSearch wola sie DWA razy na jedno nacisniecie — duplikat likwidujemy, zostaje handler w modalu. ISTOTNE — nakladka nawigacji nie moze isc w lewy dolny rog: zajmuje go #graf-notka (graf.html:191), pokazywana gdy siec jest przycieta, czyli dokladnie przy duzych grafach gdzie nawigacja jest najpotrzebniejsza. Lewy gorny to #graf-panel, prawy gorny #graf-legenda. Jedyny wolny rog to prawy dolny. Pozostale korekty: wlascicielem logiki przelacznika jest modul (bppPodepnijPrzelacznikSkrotow), nie kod inline w stopce; guard `typeof` przed wywolaniem bppSkrotyWlaczone (wzorem istniejacego guardu dla openGlobalSearch); test Playwright na ZACHOWANIE skrotu, bez ktorego usuniecie warunku z handlera nie wywalilo by niczego; baner reklamujacy skrot ukrywany przy wylaczonych skrotach; rozroznienie testu `<script src>` (sensowny dla skroty-klawiszowe.js, bezsensowny dla nawigacja.js, ktory idzie w bundle esbuild); vitest wymaga jsdom dla modulu window-globalnego; limity zoomu odczytywane z instancji (cy.js:99-100), nie zaszyte; czy_pokazywac_siec_powiazan to metoda Autora, per-autor nadpisuje per-uczelnia; zasieg stopki uscislony (bare.html jej nie wlacza, ale tam tez nie ma skrotu). Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01E8RjSZWMR6L7fuRDJJZW4L
Osiem zadan: modul preferencji skrotow → podpiecie do WSZYSTKICH trzech publicznych handlerow / z likwidacja duplikatu → modul nawigacji po grafie → przyciski → klawiatura → testy Playwright → wykaz odroczonych i newsfragment → weryfikacja koncowa. Testy Playwright dostaly osobne zadanie, bo bez nich usuniecie warunku bppSkrotyWlaczone() z handlera albo preventDefault z obslugi klawiatury nie wywalilo by zadnego testu — szablonowe dowodza tylko, ze kod jest w pliku. Wzorzec testu przegladarkowego wziety z test_siec3d_bez_webgl.py:44-57 (channels_live_server + page: Page + transactional_db, baker.make(Autor)). Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01E8RjSZWMR6L7fuRDJJZW4L
…ra (2.1.4) Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
Handler klawiatury w grafie powiazan (Task 5) przechwytywal takze Ctrl/Cmd+Plus/Minus (zoom przegladarki, WCAG 1.4.4), Ctrl+Home (przewijanie na gore) i Alt+strzalka (nawigacja wstecz). Naprawiajac 2.1.1 lamalismy funkcje wazniejsza dla tej samej grupy uzytkownikow. Logike mapowania klawisza na akcje wydzielono z controls.js do nawigacja.js jako obsluzKlawisz(cy, e) — wczesne wyjscie na ctrlKey/metaKey/altKey (shiftKey celowo pominiety, bo + czesto wymaga Shift), zwraca true tylko dla obsluzonych klawiszy. controls.js redukuje sie do wywolania i warunkowego preventDefault. Dodano tests/js/graf-klawiatura.test.js (18 testow, atrapa cy z nawigacja-grafu.test.js) pokrywajacy strzalki, +/-/=/_, Home, klawisze nieobslugiwane (Tab/Escape/Enter/litera) oraz skroty z modyfikatorami. Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
Testy szablonowe z zadan 1-5 dowodza tylko, ze kod jest w plikach -- usuniecie warunku bppSkrotyWlaczone() z handlera skrotu / albo preventDefault z obslugi klawiatury grafu nie wywalaloby zadnego testu. Ten plik dowodzi zachowania w prawdziwej przegladarce (Playwright + channels_live_server). 10 testow: - 5x WCAG 2.1.4 (skrot / i jego wylacznik w stopce): domyslne otwarcie wyszukiwarki, wylaczenie dziala, ponowne wlaczenie przywraca skrot, aria-pressed sie aktualizuje, preferencja przezywa przeladowanie (localStorage). - 5x WCAG 2.5.7/2.1.1 (nawigacja po grafie powiazan): przyciski widoczne + kontener fokusowalny, klik zoom-in realnie zmienia cy.zoom(), klik kierunkowy realnie zmienia cy.pan(), strzalka z klawiatury realnie zmienia cy.pan(), Tab nie jest zlapany w pulapke klawiaturowa (2.1.2). Testy zoom/pan czytaja stan z container._cyreg.cy (wewnetrzny rejestr Cytoscape.js) PRZED i PO interakcji, zeby padaly gdy handler klikniecia zniknie -- sama widocznosc przycisku o tym nie swiadczy. Self-review (potwierdzone recznie, patrz raport): usuniecie warunku bppSkrotyWlaczone(), wylaczenie obsluzKlawisz() oraz odpiecie handlerow klikniec przyciskow kierunkowych/zoom kazde osobno wywalaly odpowiednie testy na czerwono. Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
…oom) Dwie przyczyny, obie ujawnione dopiero przy powtarzanych przebiegach. 1. `_url_grafu` tworzyl autora BEZ wspolautorow, wiec BFS zwracal siec jednowezlowa, a `renderujSiec()` (graph.js:172-178) asynchronicznie chowal `#cytoscape-container`. Klawisz albo klik trafial czasem w juz ukryty kontener — 20-30% awaryjnosci na niezmienionym, poprawnym kodzie. Autor testowy dostaje teraz wspolautora (jeden wiersz AuthorConnection wystarczy: `_kandydaci_frontu` czyta relacje dwukierunkowo), wiec ta galaz nie moze wystapic. 2. `_czekaj_na_graf` czekalo na `_cyreg.cy`, ktore powstaje synchronicznie w `utworzCy()` — ZANIM fetch `siec.json` wystartuje. Bylo to czekanie na nic. Teraz czekamy na sygnal pozytywny: `cy.nodes().length > 0`, ktory zapelnia dopiero `renderujSiec()` po odpowiedzi serwera. Warunek "kontener nie jest ukryty" bylby tu bezuzyteczny — szablon nie nadaje `display`, wiec spelnialby sie przed renderem. Naprawa (1) obnazyla druga usterke: przy dwuwezlowej sieci `cy.fit()` dobija do `maxZoom` (4), wiec `zoomuj()` przycina wynik i przyblizanie jest poprawnie operacja pusta — asercja "zoom wzrosl" padala mimo sprawnego handlera. Wczesniej test przechodzil z niewlasciwego powodu: przy jednym wezle kontener byl chowany, a `fit()` na pustym grafie zostawial zoom 1. Test ustawia teraz punkt startowy jawnie (`_ustaw_zoom_z_zapasem`) zamiast liczyc na geometrie ukladu. Przy okazji: `page.wait_for_timeout(500)` w tescie wylacznika zastapiony asercja warunkowa (handler "/" jest synchroniczny), `ruff format`. Weryfikacja: 150/150 (15 x caly plik). Wartosc testow potwierdzona mutacjami — wygaszenie handlera zoom-in i warunku `obsluzKlawisz` zapala odpowiednio test przyblizania i test strzalki. Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
Wykazy odroczonych niezgodnosci w obu specyfikacjach (08-05 i 08-06) twierdzily, ze 2.1.4 i 2.5.7 sa "niezgodne, swiadomie odroczone" — nadal prawdziwe w chwili pisania, nieprawdziwe od wczoraj. Oba wpisy zastapione jednym akapitem o domknieciu, z odsylaczem do specyfikacji 08-07. Poza wykazami dokument 08-05 twierdzil to samo w pieciu innych miejscach, kazde z wlasna korekta z 2026-08-06: tabela zrodel werdyktu, naglowek sekcji "Naruszenia stwierdzone", obie podsekcje kryteriow, kolejnosc prac (krok 3) i sekcja otwartych decyzji. Kazde dostalo `Korekta (2026-08-07)` zgodnie z konwencja dokumentu — bez kasowania oryginalu, zeby dalo sie odtworzyc, co i kiedy uznano za niezgodnosc. Sekcja otwartych decyzji jest tu najciekawsza: rekomendacja (zawezenie skrotu do focusa) nadal NIE zostala przyjeta, ale kryterium naprawiono inaczej — zalozenie, ze wylaczalnosc wymaga profilu uzytkownika, bylo zbyt ostrozne. Sprawdzone i pozostawione bez zmian: naglowek "Blok 5" (2.5.7 nadal jest przedmiotem audytu, teraz jako weryfikacja naprawy), wiersz 2.5.1 (osobne kryterium, gesty wielopunktowe — nietkniete), listy wykrywalnosci automatem (fakt o axe, niezalezny od stanu naprawy), opisy zakresu wymieniajace graf powiazan (nadal w probce). Wiekszosc trafien grepu z briefu to falszywe alarmy: "bibliograficzny" zawiera "graf". Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
Task 4 zalozyl `src/powiazania_autorow/tests/__init__.py` obok istniejacego
`src/powiazania_autorow/tests.py` (17 KB, 18 testow). Python rozwiazuje
`powiazania_autorow.tests` na PAKIET, wiec modul zostal przesloniety, a
pytest odmawial kolekcji `tests.py` ("import file mismatch"). Skutek gorszy
niz czerwona suita: te 18 testow po cichu przestalo sie wykonywac, a caly
przebieg konczyl sie bledem.
Recenzja Taska 4 tego nie zlapala, bo uruchamiala tylko 4 nowe testy —
kolizja nazw ujawnia sie dopiero przy kolekcji calego drzewa.
Konwencja tej aplikacji to moduly testowe w korzeniu pakietu
(`test_views.py`, `test_pbn_root_per_uczelnia.py`, `tests.py`) — to
katalog `tests/` byl odstepstwem. Plik wraca wiec o poziom wyzej, pakiet
znika.
Przy okazji `SZABLON` przestaje liczyc `parents[n]` od `__file__`, a
kotwiczy sie na katalogu pakietu: poprzedni wariant psul sie przy kazdym
przeniesieniu pliku (co wlasnie zaszlo).
Weryfikacja: `pytest src/powiazania_autorow/` 63 passed (bylo 56 + 7
niezbieranych).
Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
… z triazu Cztery pozycje z listy odlozonych drobiazgow w ledgerze. 1. Guardy w `browse/uczelnia.html` (oba miejsca) nie mialy zadnego testu — strona uczelni ma WLASNY, inline'owy skrypt: baner reklamujacy skrot `/` oraz handler zamykajacy ten baner. Zaden test Pythona jej nie renderowal, Playwright jej nie odwiedza, wiec usuniecie ktoregokolwiek guardu przechodzilo CI. To byla jedyna pozycja z triazu, przy ktorej regresja przeszlaby niezauwazona. Trzy nowe testy, kazdy zweryfikowany mutacja: usuniecie guardu banera, guardu handlera i guardu `typeof` zapala dokladnie po jednym, wlasciwym tescie. 2. Martwy kod w `catch` w `bppSkrotyWlaczone`: warunek na wejsciu zwraca juz `stanAwaryjny`, gdy ten jest ustawiony, wiec w `catch` jest on ZAWSZE `null`, a ternary zawsze dawal `true`. Zostaje `return true` z komentarzem, czemu tak. 3. `.footer__link-button` przeniesiony do bloku `.footer` jako `&__link-button` — konwencja BEM reszty pliku. Skompilowany CSS jest bajt-w-bajt taki sam (sprawdzone w app-blue.css), to zmiana czysto redakcyjna. 4. Test skalowania kroku sprawdzal tylko os X. Dopisany blizniaczy dla osi Y: podmiana `cy.height()` na `cy.width()` w `przesun` NIE wywalala starego testu (tam wysokosc jest stala), a wywala nowy — zweryfikowane mutacja. Weryfikacja: pytest 89 (test_wcag + powiazania_autorow), vitest 152/152, grunt build. Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
Wiedza o tym, co w temacie WCAG zostalo do zrobienia, zyla dotad wylacznie w `.superpowers/` — katalogu wykluczonym przez .gitignore (linia 229), a wiec znikajacym razem z worktree. Po scaleniu fazy 2 i usunieciu `bpp-wcag-faza2` przepadlby zarowno ledger, jak i HANDOFF: lista otwartych decyzji, powod rebase'u, hipotezy do zbadania i pulapki hosta. Dokument zbiera to w jednym, wersjonowanym miejscu: mape czterech dokumentow WCAG, stan obu faz, sciezke do scalenia z komenda rebase'u i uzasadnieniem, triaz otwartych decyzji projektowych oraz pozostale kroki programu (skan szeroki, baseline freeze, bramka axe-core, audyt WCAG-EM, raport zgodnosci) wraz z hipotezami i zgodnosciami warunkowymi. `docs/superpowers/` jest wykluczone z mkdocs przez `exclude_docs`, wiec plik nie trafia na strone dokumentacji i nie rusza gejtu `mkdocs build --strict`. HANDOFF.md w .superpowers zostaje jako skrot operacyjny i wskazuje na ten dokument. Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
…a mobile
Dwie decyzje z triazu, obie z dowodem wizualnym ze zrzutow.
1. Siedem przyciskow ukladalo sie w gridzie 3-kolumnowym jako
`↑ ← ⤢` / `→ ↓ +` / `−`, czyli w KOLEJNOSCI CZYTANIA, nie przestrzennie:
"w gore" sasiadowalo poziomo z "w lewo". Dla pomocy nawigacyjnej afordans
jest istotny — uzytkownik ma trafiac w przycisk bez czytania etykiet.
Teraz krzyz kierunkowy, zoom w osobnej kolumnie obok. Uklad robi
`grid-template-areas`, wiec KOLEJNOSC W DOM zostaje nietknieta — Tab
nadal idzie gora, lewo, dopasuj, prawo, dol, zoom+, zoom-.
2. Przy 390 px legenda (260 px) zaslaniala wiekszosc obszaru rysowania,
a notka (320 px) stykala sie z nawigacja — graf byl na telefonie
praktycznie bezuzyteczny. Nakladek nie da sie przestawic z arkusza,
bo `max-width` i `bottom` siedza w `style=""` w graf.html i styl inline
wygrywa. Zamiast rozsiewac `!important` — na malych ekranach nawigacja
przestaje byc pozycjonowana absolutnie i lezy POD grafem. Jednym ruchem
znika kolizja ze wszystkimi czterema naroznikami, a cele dotykowe sa
latwiejsze do trafienia. Legenda, ktora opisuje interakcje myszy
("Najedz na wezel…"), na ekranie dotykowym jest chowana.
Dwa testy Playwright pilnuja obu stron media query: przy 390 px nawigacja
musi lezec ponizej plotna i legenda ma byc schowana, przy 1440 px odwrotnie.
Kontrola jest konieczna, bo bez niej "naprawa" mobile mogla by po cichu
zjechac przyciski pod graf na wszystkich rozdzielczosciach. Usuniecie media
query zapala test waski i zostawia szeroki zielony — zweryfikowane mutacja.
Weryfikacja: Playwright 12/12 w tym pliku, vitest 152/152, pytest 89
(test_wcag + powiazania_autorow), grunt build.
Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
Recenzja calego diffu fazy 2 wylapala, ze `src/django_bpp/templates/admin/base_site.html:127` wiaze skrot `/` na `$(document)` z `preventDefault()` — ten sam wzorzec 2.1.4, ktory faza 2 naprawila po stronie publicznej, tylko nietkniety. Poza zadeklarowanym zakresem audytu (czesc publiczna dla anonima), wiec NIE wciagam tego do tej galezi. Ale kryterium obowiazuje per strona, a naprawa nie jest jednolinijkowa: panel administracyjny nie dziedziczy po `base.html`, wiec nie laduje `skroty-klawiszowe.js` — potrzebny jest i skrypt, i guard. Zapisane, zeby nie przepadlo do czasu, gdy raport zgodnosci obejmie panel. Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
…artwa
nawigacja, tresc chowana na mobile, cel dotykowy
Recenzja mutacyjna przepuscila 14 mutacji przez wszystkie trzy warstwy
testow. DWANASCIE przeszlo na zielono. To commit zamykajacy najpowazniejsze
z nich plus trzy znaleziska recenzji kodu.
**Spoiwo DOM -> akcja bylo nietestowane w ogole.** `controls.js` nie mial
zadnego testu jednostkowego, wiec przechodzily: zamiana "gora" z "dol",
wszystkie cztery strzalki robiace to samo, odpiety zoom-out albo "dopasuj",
usuniety `preventDefault` i — najgorsze — `document` zamiast kontenera jako
cel handlera keydown. Ta ostatnia zamienia `+` i `-` w GLOBALNE skroty
jednoznakowe, czyli lamie dokladnie to 2.1.4, ktore ta galaz naprawia,
przy calej suicie na zielono.
Spoiwo przeniesione do `nawigacja.js` jako `podepnijNawigacje(cy, dok)` —
zgodnie z zasada, ktora komentarz w `controls.js` juz formulowal dla
`obsluzKlawisz`, ale ktorej samo spoiwo nie dotrzymywalo. Funkcja zwraca
element, do ktorego podpieto keydown, zeby dalo sie na to asertowac.
13 testow w `tests/js/podepnij-nawigacje.test.js`; wszystkie cztery mutacje
sprawdzone i lapane.
**Guardy `uczelnia.html` byly testowane regexem po zrodle**, wiec odwrocenie
logiki (`|| !bppSkrotyWlaczone()`) przechodzilo: guard nadal tam jest, nadal
ma `typeof`, nadal nazywa sie `skrotyWl` — a baner reklamuje skrot dokladnie
wtedy, gdy uzytkownik go WYLACZYL. Doszedl test Playwright na realnej
stronie uczelni. Zweryfikowane: na tej mutacji nowy test pada, a wszystkie
26 testow szablonowych przechodzi.
**Martwa nawigacja nad pustym grafem.** Gdy siec ma <=1 wezel,
`renderujSiec()` chowa plotno, ale nie nakladke. `#graf-wrapper` zapada sie
do wysokosci akapitu, a panel wychodzi ~70 px PONAD niego i nachodzi na
komunikat "Brak powiazan". Przyciski sa przy tym martwe (`cy.width()` == 0)
i zostaja w kolejnosci Taba. Autor bez policzonych powiazan to nie egzotyka:
AuthorConnection liczy sie raz na dobe, wiec kazdy swiezo dodany autor
trafia tu zawsze.
**Media query chowala TRESC, nie dekoracje.** Legenda niosla jedyne w calym
szablonie wyjasnienie kodowania wizualnego ("wielkosc kola odpowiada
metryce, grubosc linii — liczbie publikacji"), a moj wlasny test to
zabetonowal asercja `not_to_be_visible`. Zdanie przenioslem do `<small>`
nad grafem, widocznego zawsze; w nakladce zostaly wylacznie podpowiedzi
o najechaniu kursorem, ktorych na dotyku nie ma.
**Cel dotykowy przelacznika.** `.footer__content` ma `font-size: 70%`, wiec
przycisk mial 134x15 px przy progu 24x24 z 2.5.8 — a to jedyny sposob
skorzystania z naprawy 2.1.4, adresowanej do osob ze sterowaniem glosem
i zaburzeniami motoryki. Sam padding, bez ruszania `font-size`.
Dolozone tez asercje na rozmiar celu przyciskow grafu i na pierscien focusa
kontenera (2.4.7) — oba byly deklarowane w komentarzach SCSS jako spelnione
i oba byly niechronione: zejscie do 10px albo skasowanie `:focus-visible`
przechodzilo cala suite.
Weryfikacja: Playwright 17/17 w tym pliku, vitest 170/170, pytest 106
(test_wcag + powiazania_autorow + integration).
Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
CI wywalilo `fallback: gdy setItem rzuca...` na `expected '0' to be null`,
choc lokalnie caly plik przechodzil. Przyczyna nie byla srodowiskowa —
technika stubowania byla zla, a roznica wersji jsdom tylko ja obnazyla.
`window.localStorage.setItem = () => { throw ... }` NIE przeslania metody.
`Storage` w jsdom to legacy platform object: przypisanie nieznanej
wlasciwosci ZAPISUJE POZYCJE o kluczu "setItem". Prawdziwy `setItem`
wykonywal sie wiec dalej i zapisywal "0", a asercja o pustym localStorage
padala.
Gorsze jest to, czego CI nie pokazalo: przy nieskutecznym stubie pozostale
trzy testy uzywajace tej techniki przechodzily NIEZALEZNIE od tego, czy
stub zadzialal — sprawdzaly `not.toThrow()` albo wartosc domyslna, czyli
to samo, co bez stubu. Nie pilnowaly niczego. Padl tylko ten jeden, ktory
faktycznie potrzebowal dzialajacego stubu.
Zamiast lepic metody na obiekcie Storage podmieniamy caly `localStorage`
przez `Object.defineProperty` (atrapa delegujaca do oryginalu plus
nadpisania) i przywracamy go w `finally`, zeby wyjatek w tescie nie
zostawial zepsutego globala kolejnym testom.
Wartosc mutacyjna sprawdzona: usuniecie `stanAwaryjny = !!wlaczone` z
`catch` w `bppUstawSkroty` zapala teraz DWA testy. Wczesniej stub bywal
ignorowany, wiec nie zapalalo nic.
vitest: 170/170.
Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Druga faza napraw WCAG 2.2 AA. Pierwsza to #732 (już zmergowana) — ta gałąź jest na niej odbita i przebazowana na
dev, więc diff zawiera wyłącznie fazę 2.Co domyka
2.1.4 Character Key Shortcuts — skrót
/otwierający wyszukiwarkę wisiał nadocumenti nie dawał się wyłączyć. Z trzech dopuszczonych przez kryterium wyjść wybrane zostało pierwsze: wyłączalność. Preferencja siedzi wlocalStorage(część publiczna nie ma kont, więc profil odpada), przełącznik jest w stopce, a wszystkie trzy publiczne handlery/pytają o nią przed otwarciem. Przy okazji zlikwidowany zdublowany handler —base.htmli modal otwierały wyszukiwarkę niezależnie, więc jedno naciśnięcie wołałoopenGlobalSearchdwa razy.2.5.7 Dragging Movements oraz 2.1.1 Keyboard — graf powiązań autorów dało się dotąd nawigować wyłącznie przeciąganiem. Doszło siedem przycisków (cztery kierunki w układzie kompasowym, przybliż, oddal, dopasuj) oraz obsługa klawiaturą: strzałki,
+/-,Home.Dwa sąsiednie kryteria pilnowane przy okazji, żeby naprawa jednego nie złamała drugiego:
preventDefaultleci wyłącznie dla obsłużonych klawiszy, więc Tab nadal wyprowadza focus (2.1.2), a kombinacje z Ctrl/Cmd/Alt są przepuszczane, żeby nie przechwycić zoomu przeglądarki (1.4.4).shiftKeyświadomie nie wchodzi do tego warunku — na wielu układach klawiatury+wymaga Shifta.Uwagi do przeglądu
Kolejność w DOM przycisków nawigacji jest celowo inna niż ich układ wizualny: kompas rozstawia
grid-template-areas, a DOM zostaje w kolejności dającej sensowny Tab.Poniżej 640 px nawigacja przestaje być nakładką i ląduje pod grafem. Nakładek nie da się przestawić z arkusza, bo
max-widthibottomsiedzą wstyle=""wgraf.html— zamiast rozsiewać!important, wyprowadzamy nawigację spod nich. Legenda jest tam chowana, ale zdanie wyjaśniające kodowanie wizualne (wielkość koła, grubość linii) zostało z niej przeniesione nad graf, gdzie jest widoczne zawsze — chowanie treści na małym ekranie to strata informacji, nie dekoracji.Testy
Nowe: 13 testów vitest na spoiwo DOM→akcja, 17 Playwright, plus asercje szablonowe. Warstwa Playwright nie jest ozdobą — łapie rzeczy, których dwie pozostałe nie łapią, i to jest zmierzone, nie zadeklarowane.
Gałąź przeszła przegląd mutacyjny (14 mutacji przez wszystkie trzy warstwy). Pierwsze podejście przepuszczało dwanaście z nich; najgroźniejsza podmieniała cel handlera
keydownnadocument, co zamieniało+/-w globalne skróty jednoznakowe i łamało dokładnie to 2.1.4, które ta gałąź naprawia — przy całej suicie na zielono. Spoiwo zostało wyniesione zcontrols.jsdonawigacja.jsjakopodepnijNawigacje()i jest teraz testowane; wszystkie te mutacje są łapane.Weryfikacja lokalna
Na świeżym kontenerze (reuse daje niewiarygodne wyniki przy testach zależnych od stanu bazy):
Dwa testy
src/django_bpp/tests/test_auth_server.pypadają — to defekt zastany nadev, nie regresja tej gałęzi. Odtworzone na czystymdevw trybie detached: baseline to te same 2 failed / 9391 passed. Objaw toTemplateDoesNotExistdlaauth_server/login.html, czyli rozstrzyganie szablonu, niezależne od stanu bazy. Do osobnego zgłoszenia.Znalezione przy okazji, celowo poza zakresem
src/django_bpp/templates/admin/base_site.html:127wiąże/na$(document)bez guardu — ten sam wzorzec 2.1.4, tylko w panelu administracyjnym, czyli poza zadeklarowanym zakresem audytu. Naprawa nie jest jednolinijkowa, bo admin nie dziedziczy pobase.htmli nie ładuje modułu. Zapisane wdocs/superpowers/specs/2026-08-13-wcag-stan-i-pozostale-prace.mdrazem z resztą pozostałych prac WCAG.🤖 Generated with Claude Code