Dark mode, kliensoldali hibakovetes es Playwright e2e - #79
Merged
Conversation
Az oldal csak vilagos temat tudott: a prefers-color-scheme nulla talalat volt a repoban, a base.css :root blokkja egyetlen fix palettat definialt. Rendszerszintu dark mode mellett ez kiugro, es a latogatok egy resze szamara kellemetlen. A szinek mar tokenekben voltak, de a tokenek mellett 59 fix szin allt a komponensek scoped style blokkjaiban - tulnyomo reszt "background: #fff" es "color: #fff". Ezek nem tudnak temat kovetni, es mivel minden style blokk scoped (nincs :deep sem :global az egesz repoban), a tokenek oroklodese az EGYETLEN csatorna a komponensek fele. Ezert a munka nagyobb resze nem uj paletta, hanem a fix szinek visszavezetese tokenre. - base.css: a vilagos paletta 17 tokenje 40-re bovult, es megkapta a parjat. Uj tokenek arra, aminek eddig nem volt: --on-accent / --on-ink / --on-danger (elotersznin egy kitoltott felszinen), --surface-alpha, --nav-bg, --overlay, --shadow-sm, --scrollbar-thumb, --hatch(-strong), --border-4, --accent-bg-strong, --danger-bg / --danger-border, --warn-bg / --warn-ink, --code-*-rgb, --viz-1..8 / --viz-other. - A sotet blokk ket szelektor alatt all: @media (prefers-color-scheme: dark) :root:not([data-theme='light']) a rendszer-preferencia, es [data-theme='dark'] a kezi valasztas. A media blokk azert van :not()-tal szukitve, hogy a kifejezett "vilagos" nyerjen egy sotetre allitott gepen is. A duplikacio szandekos: egy szabaly nem lehet egyszerre a media queryn belul es kivul, a light-dark() pedig egy regebbi bongeszon az OSSZES tokent egyszerre ervenytelenne teszi - az nem vilagos oldal, hanem csupasz. - A sotet paletta nem a vilagos invertalasa, minden token a SZEREPET tartja. A gray skala ezert fordul meg (a --gray-700 a legerosebb masodlagos szoveg mindket temaban, tehat sotet hatteren a legvilagosabb), a felszinek viszont a vilagos paletta SORRENDJET tartjak: --surface > --bg > --surface-3 > --surface-2 vilagossag szerint, tehat egy kartya tovabbra is kiemelkedik a lapbol, egy halk kitoltes (hover sor, progress sav, toggle vajata) tovabbra is besuvad. Az invertalas minden kiemelt chipet bemelyedesse forditott volna. - Kontraszt (WCAG AA) a sotet paletta minden szoveg-tokenjere merve, a szamok a base.css kommentjeben. A --danger ket tokenre valt szet: szoveghez eleg vilagos voros nem tud feher feliratot vinni, ezert a szolid destruktiv gomb --danger-solid(-hover)-t hasznal. - Uj shared composable: useTheme (pf_theme kulcs, useLang mintajara). Harom allapot, nem ketto - a "system" onallo valasztas, es egy ket-allasu kapcsolo az elso kattintassal csendben lepinnelne a temat. System modban a data-theme attributum NINCS kiirva: igy a media query dont, es a rendszerbeallitas menet kozbeni valtasa JavaScript nelkul is atszinezi az oldalt (a composable csak a theme-color metat koveti). - public/theme.js mindket appban: a tarolt temat a stylesheet elott irja ki, tehat a kifejezett valasztas nem villantja fel a masik palettat. Kulon fajl es nem inline script, mert a CSP script-src 'self' nonce nelkul - ugyanaz az indok, mint az /error.js-nel. A <head>-ben blokkolva, a Vite altal beszurt stylesheet elott. - ThemeToggle a publikus nav-ba a LangToggle melle, es a DetailNav-ba (ott a showLang-tol fuggetlenul: a nyelv egynyelvu lapon elrejtozik, a tema oldalszintu preferencia). Az adminban a sidebar lababa, oszlopba igazitva. A cimkek a uiCommon-ban, mert mindket app hasznalja. - Turnstile: a widget temaja eddig hard-kodolt "light" volt, a komment szerint "the site has no dark mode". Most a feloldott temara van kotve - nem 'auto'-ra, mert az a rendszert koveti, ami epp akkor rossz valasz, amikor a latogato felulirta. Temavaltasra a widget ujrarendelodik (a Turnstile-nak nincs API-ja elo widget atszinezesere), tehat a kihivas ujra kiadodik. - SkillsDonut: a nyolcas kategorikus paletta a base.css-be kerult temankent, es a szeletek :style-on kapjak a szint, nem a stroke attributumon - SVG presentation attributumban a var() nem behelyettesitodik, stroke="var(--viz-1)" semmit nem rajzolna. - CodeBackdrop: a nyolc kulonbozo alfa miatt a ket arnyalat csatorna- harmaskent jon a tokenbol, rgb(var(--code-ink-rgb) / 3%) formaban. A maszkban levo #000 marad: a maszk luminanciat olvas, nem szint. - error.html: sajat, bundle nelkuli paletta-masolata megkapta a sotet parjat, es betolti a /theme.js-t. Ez az az oldal, ahova a latogato akkor kerul, amikor mar valami baj van - vilagos villanas nelkul. - Ket szandekos kivetel maradt fix szinnek, kommenttel: a JPEG lapositas feher alapja az imageEdit.ts-ben (a tarolt kepbe sul bele, nem kovetheti a szerkeszto temajat) es a CodeBackdrop maszkja. - A site.webmanifest theme_color/background_color valtozatlan: a manifest nem tud temara reagalni, telepitett PWA-nal a splash igy vilagos marad. - A ThemeToggle harom glyphje utan U+FE0E (text presentation selector) all: egyik sincs a betoltott fontsource latin subsetekben, tehat platform-fallback fontbol jonnek, es a U+2600-nak van emoji formaja is - enelkul a monokrom pill egyik gombja Androidon szines nap lenne. Closes #50
Szerveroldalon volt hibakovetes (Serilog, UseSerilogRequestLogging, hibaoldal ErrorId-vel), kliensoldalon semmi: egy JavaScript kivetel, egy torott chunk-betoltes vagy egy hibas API-valasz-kezeles a latogato bongeszojeben tortent, es soha nem tudtunk rola. A content store elkapta az API-hibat es a HomeView megjelenitette a panelt, de hogy ez hanyszor fordult elo es miert, arrol nem volt adat. Az issue elso celja a self-hosted GlitchTip volt; ez a minimal valtozat lett. Indok: a jelentesek a mar meglevo Serilog-folyamba mennek, tehat nincs uj szolgaltatas a 2 GB-os VPS-en, nincs uj memorialimit, nincs uj uzemeltetesi felulet - es a `connect-src 'self'` mar fedi az endpointot, tehat a CSP-t sem kell nyitni. - Uj shared modul: utils/errorReporter.ts. Bekoti a window.onerror-t es az unhandledrejection-t, ad egy vueErrorHandler-t az app.config.errorHandler-hez, es egy reportCaughtError-t a router.onError-hoz. Mind a negy kell: a Vue elkapja a komponens hibakat, tehat azok nem jutnak el a window.onerror-ig, a lazy view chunkja pedig navigacio kozben hasal el, nem komponensben. - Szandekosan NEM az api/http.ts-en keresztul kuld. Az a wrapper eppen az egyik bejelentett dolog, es egy reporter, ami dob (vagy ujraprobal, vagy spinnerbe idozit tul), rosszabb, mint a semmi: minden kuldes fire-and-forget, elnyelt hibaval, mint a latogatas-beacon. - Uj endpoint: POST /api/activity/error. A Core-ban van es nem a Serverben, tehat MINDKET host kiszolgalja, es mindket app a sajat originjara jelent. Ha az admin a publikus hostra kuldene, ahhoz CORS kellene ott es szelesebb connect-src az admin CSP-ben - semmiert: egy admin oldali kivetel ma pont annyira lathatatlan, mint egy publikus. Az "activity" prefix ugyanazert van, mint a beaconnal: az adblocker szurolistak a telemetriara hasonlito URL-eket blokkoljak. - A jelentes Warning szinten megy a logba, nem Error szinten: kliensoldali hiba valodi defekt, de nem ez a process hasal el, es az Error az, amire egy riasztas kotne. A traceId a szovegben is szerepel, nem csak propertykent: a `grep <id>` a szerveroldali sort es ezt is megtalalja. - traceId osszekotes: a http.ts az 5xx-et a ProblemDetails traceId-jevel jelenti be, tehat a kliensoldali tunet es a szerveroldali ok egy grep-pel osszerakhato. A 4xx szandekosan nem megy be - egy 400, 404, 409 vagy 429 a szerver helyes valasza es a UI megjelenitett hibaja, nem defekt, es bejelentve elnyomna az igaziakat. A status 0 (a keres el sem ert a szerverig) viszont bemegy: az a fajta, amirol szerveroldalon definicio szerint nincs semmi. - Adatvedelem: nem megy be query string, hash es beirt urlap-tartalom, a POST Referer fejlece pedig `referrerPolicy: 'origin'` miatt csak az origint viszi (same-origin keresnel a strict-origin-when-cross-origin a teljes URL-t adna). Ami strukturalisan nem szurheto: egy kivetel SZOVEGE idezhet felhasznaloi bemenetet - ezt a 300 karakteres korlat hatarolja, nem szunteti meg. A kommentek ezt kimondjak. - Zajszures: a kliens eldobja a cross-origin "Script error."-t (a bongeszo mindent visszatart, nincs mire ranezni), a ResizeObserver loop ertesitest es a bovitmeny-eredetu hibakat; a szerver eldobja a bot user agentet (ugyanaz a BotDetection, mint a beaconnal). Azonos jelentes egyszer megy el, oldalbetoltesenkent legfeljebb ot, es az endpointnak sajat rate limit policyja van, kliensenkent tiz percenkent. A policy a RateLimitPolicies-ben van es MINDKET host regisztralja: egy olyan policy, amit a host nem regisztralt, keres kozben dob, nem indulaskor. - A chunk-hibakat a reporter atsorolja `chunk` fajtara. Ez nem kodhiba: a ful betoltese ota volt egy deploy, es a kert hash-elt chunk mar nincs az originen - mas a teendo, tehat mas fajta. - Log-injection: minden mezo tamado-kontrollalt szoveg, es egy sortores a kozepen egy hamisitott masodik log sor. A Clamp " | "-re valtja a sortoreseket (ez tartja el egymastol a stack frameket is) es kicsereli a tobbi kontroll karaktert. - A DTO minden mezoje nullable es egyik sem visel validacios attributumot, a RecordViewRequest-tel ellentetben: a jelentes olyan uton erkezik, ami soha nem olvassa a valaszt, tehat egy 400 nem javit semmit - csak elveszti a jelentest, mikozben eppen a mar hibasan mukodo klienstol erkezo jelentes a legerdekesebb. Az endpoint maga validal es klampol, es minden esetben 204-et ad, a kiszurt jelentesekre is: a hivo nem tud mit tenni egy verdikttel, es egy megkulonboztetheto elutasitas megmondana egy probolgatonak, mik a szurok. - Source map: `build.sourcemap: 'hidden'` mindket appban - a mapok elkeszulnek, de sourceMappingURL komment nem kerul a bundle-be. Az image buildbol a .map fajlok torlodnek a wwwroot-bol a publish elott (a map maga a forraskod, azt a publikus origin nem szolgalhatja ki), visszafejteshez ugyanazon a commiton kell ujraepiteni - a stackben levo fajlnev hash-e mondja meg, melyik build volt. A menete a RUNBOOK 12. szekciojaban. - CLIENT_ERRORS_ENABLED kapcsolo mindket hostra. Nem meretezes: a jelentes egyenesen a logba megy, tehat nincs mit meretezni - ez arra van, hogy egy zajos vagy visszaelesszeru bejelentest image build nelkul el lehessen hallgattatni. A log kontenerenkent 3 x 10 MB-ra rotal, tehat egy minden oldalbetoltesnel elsulo hiba elnyomhatja a tobbit. - Az uptime figyeles nem keszult el: az issue maga is kulon tetelnek nevezi. A /health mindket hoston megvan, csak nincs, ami kivulrol nezze - ez a RUNBOOK 12. szekciojanak vegen rogzitve van. - A deploy minden alkalommal ujrairja a VPS .env-jet a repository secretekbol, tehat a CLIENT_ERRORS_ENABLED-nek at kell menni a deploy.yml-en is - kulonben a kikapcsolas az elso master pushnal csendben visszaallna. A RUNBOOK ezt kimondja: a .env szerkesztese azonnali elhallgattatas, a tartos beallitas a secret. Closes #61
Xentinus
added a commit
that referenced
this pull request
Aug 22, 2026
Nem volt end-to-end teszt. A CI backend unit/API tesztet, frontend tipusellenorzest, lintet es Vitest komponens-tesztet futtatott, image buildet es Trivy szkennelest - de senki nem nyitott meg egy bongeszot az osszeallitott stacken, es a deploy utani smoke HTTP statuszkodot ellenoriz, nem mukodest. Ez pont azoknal a hibaknal dragit, ahol a retegek egymasra hatnak, es amelyek egyik meglevo teszttipussal sem erhetok el - a specek ezt a listat kovetik: - pages.spec.ts: statuszkod es a mogotte megjelenitett oldal EGYUTT. Az SPA nem tud statuszkodot allitani, tehat a szerver dont a sajat utvonal-tablajabol (PublicRoutes), a bongeszo pedig arrol, mit rajzol - es a hiba akkor all elo, ha a ketto nem egyezik. Valodi 404 a nem letezo slugra, csupasz 404 a pontot tartalmazo utvonalra (scanner-probe), /api alatti nem letezo endpoint 404 es nem index.html, es hogy az admin iro endpointok nem 401-et, hanem 404-et adnak a publikus hoston: nem letezenek ott. - head.spec.ts: a szerveroldali head-iras (SpaShell) es a kliensoldali useDocumentMeta egyutt. A kiszolgalt HTML-ben ott van az oldal sajat title-je es canonicalja (a beepitett fallback szandekosan egyiket sem tartalmazza, tehat a jelenletuk bizonyitja a templatelest), es mount utan a kliens ugyanazt a title-t tartja meg. A hiba itt nemakent all elo: minden megosztott link "Portfolio"-kent bomlik ki, kozben a bongeszo fule helyesnek latszik. - contact.spec.ts: a kapcsolati urlap teljes kore a Turnstile mindig-atmeno teszt kulcsaival. Amitol megfoghato: a submit gomb addig disabled, amig a captchanak nincs tokenje - tehat az engedelyezese MAGA a jelzes, hogy a kihivas megvalaszolodott. Plusz az ures submit: harom field error es nulla POST. - language.spec.ts: nyelvvaltas, es hogy megmarad kliensoldali navigacio ES teljes ujratoltes utan is (az elso a reaktivitas, a masodik a localStorage + module scope). A kulcsot maga is ellenorzi: az /error.js a pf_lang-ot olvassa, azt az oldalt viszont 429 provokalasa nelkul nem lehet elerni. - theme.spec.ts: a #50-ben bekerult temavalasztas. Nem az issue listajanak tetele, de ugyanebben a branchben landolt, es harom olyan resze van, ami csak bongeszoben talalkozik: a media query, a /theme.js altal irt attributum es a composable. Rendszer-preferencia attributum nelkul, kifejezett vilagos valasztas sotet rendszerbeallitas ellen, es a valasztas ujratoltes utan. - analytics.spec.ts: a ?notrack=1 kizaras. Nincs mit unit tesztelni benne - a mechanizmus MAGA a bongeszo-tarolo plusz a navigacio, es a hiba az, hogy a tulajdonos csendben latogatokent szamol a sajat statisztikajaban. - cache-outage.spec.ts: a ContentCache fail-open aga a gyakorlatban. Redis nelkul is 200 a fooldal, az API az adatbazisbol valaszol, es a PublicRouteIndex is fail-open - ha az fail-closed lenne, egy cache-kimaradas alatt az oldal MINDEN lapja 404-et adna. A CI job: - Sajat, cache-bol epulo web image (`cache-from: type=gha,scope=web`, iras nelkul: ket job ugyanabba a scope-ba irva egymast fejelne le), es a tag a compose WEB_IMAGE defaultja, tehat a compose nem buildel ujra. - `docker compose up -d --wait --wait-timeout 180 web`: csak a web (es a depends_on miatt a db + redis). Az `--wait` a healthcheckre var, tehat az `up -d` semmit nem bizonyito visszaterese helyett itt hasal el egy nem indulo host. Az admin nem indul - ahhoz Cloudflare Access assertion kellene -, de a `:?` valtozoi akkor is kellenek, mert a compose a fajl egeszet interpolalja. - SEED_MODE=dev, tehat a tesztek ismert slugokra allhatnak. A slugok egy helyen vannak (tests/seed.ts), nem hat specben. - Trace es kepernyokep artifact feltoltese hibanal: enelkul a CI-ban elhasalt e2e nem debuggolhato. - A cache-kimaradas tesztjei kulon futasban (@needs-outage tag), a Redis leallitva - egy spec ezt nem teheti meg magaval anelkul, hogy a suite tobbi reszet eltorne. A Redis egy `if: always()` lepesben indul vissza. - Commitolt package-lock.json, tehat a job `npm ci`-vel megy. A lepes ettol fuggetlenul lock nelkul is mukodik (`npm install` fallback), es a setup-node cache-e is csak lock mellett kapcsol be - igy egy jovobeli lock-torles nem buktatja a jobot, csak lassabb lesz. - Kulon type-check lepes az e2e-re, a stack felhuzasa elott: a Playwright esbuilddel forditja a specekt es egyaltalan nem tipusellenoriz, tehat egy spec lehet tipus-ertelmetlen es megis lefut. A tsc az egyetlen, ami ezt megfogja. Egyeb dontesek: - workers: 1 es fullyParallel: false. Ez nem figyelmetlenseg: minden keres egy kliens IP-rol jon, a host pedig kliensenkent limital (240/perc osszesen, 60/perc utvonalankent) - egy parhuzamos suite 429-eket kapna, es a hiba barminek latszana, csak rate limitnek nem. Ugyanezert kell a suite-nak kicsinek maradnia; ez a komment a configban van, mert a kovetkezo teszt irojanak szol. - Csak chromium: a suite az illesztesekre valo, nem bongeszo-kulonbsegekre. - A deploy/smoke-test.sh valtozatlan marad: az e2e a PR-t vedi, a smoke a kiadast. Az e2e a deploy utjan is lefut (a ci.yml ott is meghivodik), csak a sajat image-evel. - Az axe-core es a Lighthouse meres kimaradt: az issue szerint ugyanebben a jobban futtathato, de a Playwright bevezetese onmagaban is megall - es egy kulon tetelt nem erdemes ide csomagolni. - Az e2e a .dockerignore-ba kerult: semmi nem kerul belole image-be, a .NET stage viszont `COPY . .`-t csinal, tehat enelkul minden spec-valtoztatas invalidalna azt a layert. - Dependabot kulon npm bejegyzes az /e2e-re, nem a harom frontend csoportjaba: nem kerul belole semmi egyik appba sem, tehat a check-dep-sync.mjs sem nezi, es nincs ok hozzakotni a leptetesuket. A CI elso futasa (PR #79) 19 zold, 3 hasalt, 1 flaky - a harom kovetkezmenye itt van: - contact.spec: a captcha-varas a Turnstile iframe-jere vart, azt viszont a mindig-atmeno teszt kulcs NEM hoz letre - a token a cf-turnstile-response hidden inputba kerul (a trace szerint "XXXX.DUMMY.TOKEN.XXXX"). A varas most arra megy: attached, majd nem ures ertek, majd engedelyezett gomb. Mindharom egyiranyu, tehat nincs kozteslapot, amin a poller atszaladhat. - analytics.spec: a waitForLoadState('networkidle') elhasalt, mert a kapcsolati urlapon levo Turnstile widget nem hagyja elcsendesedni az oldalt. A negativ allitasnak felso korlat kell arra, hogy a beacon MAR elsult volna, ha egyaltalan elsul - ez a tartalom megjelenese, mert a trackView a router.afterEach-ben fut, meg az API-hivasok elott. - theme.spec flake: a trace szerint a /assets/HomeView-*.js 429-et kapott, tehat a SPA nem toltodott be es nem volt mire kattintani. A rate limit a statikus asseteket is szamolja: elesben ez ritkan harap, mert a Cloudflare cache-eli a hash-elt asseteket, itt viszont nincs CDN, tehat minden teszt friss context-tel a teljes asset-keszletet lekeri, es a 240/perc egy ablakon belul elfogy. Ezert lett a ket keres-budget konfigbol felulirhato (RateLimitOptions, RateLimit__PerClientPermitLimit / __PerPathPermitLimit). A default 0 = a hostba epitett ertek, tehat eles viselkedes nem valtozik, es a .env.example kimondja, hogy elesben 0-n kell maradnia. Az e2e job viszi feljebb. Egy rate limit amugy is olyan ertek, aminek jo, ha kornyezetenkent hangolhato. Kisebb keres-csokkentes is: ket teszt, aminek csak a statuszkod vagy egy statikus fajl kell, a request fixture-t hasznalja page.goto helyett - egy keres a tizenot helyett. Closes #60
Xentinus
force-pushed
the
feat/td-50-61-60-darkmode-hibakovetes-e2e
branch
from
August 22, 2026 18:56
dfc7241 to
7061a44
Compare
Nem volt end-to-end teszt. A CI backend unit/API tesztet, frontend tipusellenorzest, lintet es Vitest komponens-tesztet futtatott, image buildet es Trivy szkennelest - de senki nem nyitott meg egy bongeszot az osszeallitott stacken, es a deploy utani smoke HTTP statuszkodot ellenoriz, nem mukodest. Ez pont azoknal a hibaknal dragit, ahol a retegek egymasra hatnak, es amelyek egyik meglevo teszttipussal sem erhetok el - a specek ezt a listat kovetik: - pages.spec.ts: statuszkod es a mogotte megjelenitett oldal EGYUTT. Az SPA nem tud statuszkodot allitani, tehat a szerver dont a sajat utvonal-tablajabol (PublicRoutes), a bongeszo pedig arrol, mit rajzol - es a hiba akkor all elo, ha a ketto nem egyezik. Valodi 404 a nem letezo slugra, csupasz 404 a pontot tartalmazo utvonalra (scanner-probe), /api alatti nem letezo endpoint 404 es nem index.html, es hogy az admin iro endpointok nem 401-et, hanem 404-et adnak a publikus hoston: nem letezenek ott. - head.spec.ts: a szerveroldali head-iras (SpaShell) es a kliensoldali useDocumentMeta egyutt. A kiszolgalt HTML-ben ott van az oldal sajat title-je es canonicalja (a beepitett fallback szandekosan egyiket sem tartalmazza, tehat a jelenletuk bizonyitja a templatelest), es mount utan a kliens ugyanazt a title-t tartja meg. A hiba itt nemakent all elo: minden megosztott link "Portfolio"-kent bomlik ki, kozben a bongeszo fule helyesnek latszik. - contact.spec.ts: a kapcsolati urlap teljes kore a Turnstile mindig-atmeno teszt kulcsaival. Amitol megfoghato: a submit gomb addig disabled, amig a captchanak nincs tokenje - tehat az engedelyezese MAGA a jelzes, hogy a kihivas megvalaszolodott. Plusz az ures submit: harom field error es nulla POST. - language.spec.ts: nyelvvaltas, es hogy megmarad kliensoldali navigacio ES teljes ujratoltes utan is (az elso a reaktivitas, a masodik a localStorage + module scope). A kulcsot maga is ellenorzi: az /error.js a pf_lang-ot olvassa, azt az oldalt viszont 429 provokalasa nelkul nem lehet elerni. - theme.spec.ts: a #50-ben bekerult temavalasztas. Nem az issue listajanak tetele, de ugyanebben a branchben landolt, es harom olyan resze van, ami csak bongeszoben talalkozik: a media query, a /theme.js altal irt attributum es a composable. Rendszer-preferencia attributum nelkul, kifejezett vilagos valasztas sotet rendszerbeallitas ellen, es a valasztas ujratoltes utan. - analytics.spec.ts: a ?notrack=1 kizaras. Nincs mit unit tesztelni benne - a mechanizmus MAGA a bongeszo-tarolo plusz a navigacio, es a hiba az, hogy a tulajdonos csendben latogatokent szamol a sajat statisztikajaban. - cache-outage.spec.ts: a ContentCache fail-open aga a gyakorlatban. Redis nelkul is 200 a fooldal, az API az adatbazisbol valaszol, es a PublicRouteIndex is fail-open - ha az fail-closed lenne, egy cache-kimaradas alatt az oldal MINDEN lapja 404-et adna. A CI job: - Sajat, cache-bol epulo web image (`cache-from: type=gha,scope=web`, iras nelkul: ket job ugyanabba a scope-ba irva egymast fejelne le), es a tag a compose WEB_IMAGE defaultja, tehat a compose nem buildel ujra. - `docker compose up -d --wait --wait-timeout 180 web`: csak a web (es a depends_on miatt a db + redis). Az `--wait` a healthcheckre var, tehat az `up -d` semmit nem bizonyito visszaterese helyett itt hasal el egy nem indulo host. Az admin nem indul - ahhoz Cloudflare Access assertion kellene -, de a `:?` valtozoi akkor is kellenek, mert a compose a fajl egeszet interpolalja. - SEED_MODE=dev, tehat a tesztek ismert slugokra allhatnak. A slugok egy helyen vannak (tests/seed.ts), nem hat specben. - Trace es kepernyokep artifact feltoltese hibanal: enelkul a CI-ban elhasalt e2e nem debuggolhato. - A cache-kimaradas tesztjei kulon futasban (@needs-outage tag), a Redis leallitva - egy spec ezt nem teheti meg magaval anelkul, hogy a suite tobbi reszet eltorne. A Redis egy `if: always()` lepesben indul vissza. - Commitolt package-lock.json, tehat a job `npm ci`-vel megy. A lepes ettol fuggetlenul lock nelkul is mukodik (`npm install` fallback), es a setup-node cache-e is csak lock mellett kapcsol be - igy egy jovobeli lock-torles nem buktatja a jobot, csak lassabb lesz. - Kulon type-check lepes az e2e-re, a stack felhuzasa elott: a Playwright esbuilddel forditja a specekt es egyaltalan nem tipusellenoriz, tehat egy spec lehet tipus-ertelmetlen es megis lefut. A tsc az egyetlen, ami ezt megfogja. Egyeb dontesek: - workers: 1 es fullyParallel: false. Ez nem figyelmetlenseg: minden keres egy kliens IP-rol jon, a host pedig kliensenkent limital (240/perc osszesen, 60/perc utvonalankent) - egy parhuzamos suite 429-eket kapna, es a hiba barminek latszana, csak rate limitnek nem. Ugyanezert kell a suite-nak kicsinek maradnia; ez a komment a configban van, mert a kovetkezo teszt irojanak szol. - Csak chromium: a suite az illesztesekre valo, nem bongeszo-kulonbsegekre. - A deploy/smoke-test.sh valtozatlan marad: az e2e a PR-t vedi, a smoke a kiadast. Az e2e a deploy utjan is lefut (a ci.yml ott is meghivodik), csak a sajat image-evel. - Az axe-core es a Lighthouse meres kimaradt: az issue szerint ugyanebben a jobban futtathato, de a Playwright bevezetese onmagaban is megall - es egy kulon tetelt nem erdemes ide csomagolni. - Az e2e a .dockerignore-ba kerult: semmi nem kerul belole image-be, a .NET stage viszont `COPY . .`-t csinal, tehat enelkul minden spec-valtoztatas invalidalna azt a layert. - Dependabot kulon npm bejegyzes az /e2e-re, nem a harom frontend csoportjaba: nem kerul belole semmi egyik appba sem, tehat a check-dep-sync.mjs sem nezi, es nincs ok hozzakotni a leptetesuket. A CI elso futasa (PR #79) 19 zold, 3 hasalt, 1 flaky - a harom kovetkezmenye itt van: - contact.spec: a captcha-varas a Turnstile iframe-jere vart, azt viszont a mindig-atmeno teszt kulcs NEM hoz letre - a token a cf-turnstile-response hidden inputba kerul (a trace szerint "XXXX.DUMMY.TOKEN.XXXX"). A varas most arra megy: attached, majd nem ures ertek, majd engedelyezett gomb. Mindharom egyiranyu, tehat nincs kozteslapot, amin a poller atszaladhat. - analytics.spec: a waitForLoadState('networkidle') elhasalt, mert a kapcsolati urlapon levo Turnstile widget nem hagyja elcsendesedni az oldalt. A negativ allitasnak felso korlat kell arra, hogy a beacon MAR elsult volna, ha egyaltalan elsul - ez a tartalom megjelenese, mert a trackView a router.afterEach-ben fut, meg az API-hivasok elott. - theme.spec flake: a trace szerint a /assets/HomeView-*.js 429-et kapott, tehat a SPA nem toltodott be es nem volt mire kattintani. A rate limit a statikus asseteket is szamolja: elesben ez ritkan harap, mert a Cloudflare cache-eli a hash-elt asseteket, itt viszont nincs CDN, tehat minden teszt friss context-tel a teljes asset-keszletet lekeri, es a 240/perc egy ablakon belul elfogy. Ezert lett a ket keres-budget konfigbol felulirhato (RateLimitOptions, RateLimit__PerClientPermitLimit / __PerPathPermitLimit). A default 0 = a hostba epitett ertek, tehat eles viselkedes nem valtozik, es a .env.example kimondja, hogy elesben 0-n kell maradnia. Az e2e job viszi feljebb. Egy rate limit amugy is olyan ertek, aminek jo, ha kornyezetenkent hangolhato. Kisebb keres-csokkentes is: ket teszt, aminek csak a statuszkod vagy egy statikus fajl kell, a request fixture-t hasznalja page.goto helyett - egy keres a tizenot helyett. A masodik futas mar zold fo suite-ot adott; a cache-kimaradas lepese viszont elhasalt, es a trace megmutatta, miert: a bongeszo negy tartalmi endpointjat meg SEM kapta meg a szerver - a keresek ott vartak, amig a Redis-kliens eszrevette, hogy nincs kapcsolat. Ugyanezert volt gyors a kozvetlenul utana futo egy-hivasos API teszt. A fajl ezert most egyszer, elore "felmelegiti" a felismerest egy worker-scope keresben, es a tesztek utana a mar beallt allapotot merik - a kerdes az, hogy KIMARADAS ALATT mukodik-e az oldal, nem az, hogy a kimaradas pillanataban is azonnal gyors-e. A latencia maga a fail-open alku lenyege, ezert kaptak ezek a tesztek nagyobb idokorlatot is. Closes #60
Xentinus
force-pushed
the
feat/td-50-61-60-darkmode-hibakovetes-e2e
branch
from
August 22, 2026 19:03
7061a44 to
bf965b6
Compare
️✅ There are no secrets present in this pull request anymore.If these secrets were true positive and are still valid, we highly recommend you to revoke them. 🦉 GitGuardian detects secrets in your source code to help developers and security teams secure the modern development process. You are seeing this because you or someone else with access to this repository has authorized GitGuardian to scan your pull request. |
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.
Három issue, három commit. Egymásra épülnek: a dark mode hozza a témaválasztást, a hibakövetés
használja a shared modul-mintát, az e2e pedig mindkettőt megnézi böngészőben.
Dark mode a publikus oldalon és az adminban — closes #50
A 17 token 40-re bővült, és megkapta a sötét párját két szelektor alatt:
@media (prefers-color-scheme: dark) :root:not([data-theme='light'])a rendszer-preferencia,[data-theme='dark']a kézi választás. A:not()azért kell, hogy a kifejezett „világos" nyerjenegy sötétre állított gépen is.
A munka nagyobb része viszont nem a paletta volt: 59 fix szín állt a komponensek
scopedstyleblokkjaiban (túlnyomó részt
background: #ffféscolor: #fff), és mivel:deep/:globalnincsaz egész repóban, a tokenek öröklődése az egyetlen csatorna a komponensek felé.
fordul meg, a felszínek viszont a világos paletta sorrendjét tartják
(
--surface>--bg>--surface-3>--surface-2), tehát egy kártya továbbra is kiemelkedik,egy halk kitöltés továbbra is besüpped. Invertálva minden kiemelt chip bemélyedéssé fordult volna.
base.csskommentjében. A--dangerkét tokenre vált szét: szöveghez elég világos vörös nem tud fehér feliratot vinni.
useTheme(pf_theme, auseLangmintájára). Három állapot, nem kettő— a „system" önálló választás, és egy két-állású kapcsoló az első kattintással csendben lepinnelné
a témát. System módban a
data-themeattribútum nincs kiírva, tehát a rendszerbeállítás menetközbeni váltása JavaScript nélkül is átszínezi az oldalt.
public/theme.jsmindkét appban: a tárolt témát a stylesheet előtt írja ki. Külön fájl és neminline script, mert a CSP
script-src 'self'nonce nélkül — ugyanaz az indok, mint az/error.js-nél."light"volt („the site has no dark mode"); most afeloldott témára van kötve. Nem
'auto'-ra: az a rendszert követi, ami épp akkor rossz válasz,amikor a látogató felülírta.
error.htmlsaját, bundle nélküli paletta-másolata is megkapta a sötét párját. Ez az az oldal,ahova a látogató akkor kerül, amikor már valami baj van.
Kliensoldali hibakövetés a két frontendben — closes #61
Szerveroldalon volt hibakövetés (Serilog,
ErrorId), kliensoldalon semmi: egy JavaScript kivétel,egy törött chunk-betöltés vagy egy hibás API-válasz-kezelés a látogató böngészőjében történt, és
soha nem tudtunk róla.
Az issue első célja a self-hosted GlitchTip volt; ez a minimál változat. Indok: a jelentések a
már meglévő Serilog-folyamba mennek, tehát nincs új szolgáltatás a 2 GB-os VPS-en, nincs új
memórialimit, nincs új üzemeltetési felület — és a
connect-src 'self'már fedi az endpointot,tehát a CSP-t sem kell nyitni.
utils/errorReporter.ts.window.onerror+unhandledrejection+app.config.errorHandler+router.onError. Mind a négy kell: a Vue elkapja a komponenshibákat, tehát azok nem jutnak el a
window.onerror-ig, a lazy view chunkja pedig navigációközben hasal el, nem komponensben.
http.ts-en keresztül küld: az a wrapper éppen az egyik bejelentett dolog,és egy reporter, ami dob vagy újrapróbál, rosszabb, mint a semmi.
POST /api/activity/error) a Core-ban van és nem a Serverben, tehát mindkét hostkiszolgálja, és mindkét app a saját originjára jelent. Ha az admin a publikus hostra küldene,
ahhoz CORS kellene ott és szélesebb
connect-srcaz admin CSP-ben — semmiért.traceIdösszekötés: az 5xx a ProblemDetails traceId-jével megy be, tehát a kliensoldali tünet ésa szerveroldali ok egy
grep-pel összerakható. A 4xx szándékosan nem — az a szerver helyesválasza, nem defekt. A status 0 viszont igen: arról szerveroldalon definíció szerint nincs semmi.
RefererfejlécereferrerPolicy: 'origin'miatt csak az origint viszi. Amit strukturálisan nem lehet szűrni: egykivétel szövege idézhet felhasználói bemenetet — ezt a 300 karakteres korlát határolja.
log sor. A
Clamp" | "-re váltja a sortöréseket (ez tartja el a stack frameket is).build.sourcemap: 'hidden'— a mapok elkészülnek, desourceMappingURLkomment nemkerül a bundle-be, és a
.mapfájlok törlődnek a wwwrootból a publish előtt. A visszafejtésmenete a RUNBOOK 12. szekciójában.
CLIENT_ERRORS_ENABLEDkapcsoló mindkét hostra, adeploy.yml-en is átvezetve — a deploy mindenalkalommal újraírja a VPS
.env-jét, tehát nélküle a kikapcsolás az első master pushnál csendbenvisszaállt volna.
Ami kimaradt: az uptime figyelés. Az issue maga is külön tételnek nevezi; a
/healthmindkéthoston megvan, csak nincs, ami kívülről nézze — ez a RUNBOOK 12. szekciójának végén rögzítve van.
Playwright e2e smoke a teljes stackre — closes #60
Eddig senki nem nyitott meg egy böngészőt az összeállított stacken, a deploy utáni smoke pedig
státuszkódot ellenőriz, nem működést. Hét spec az issue listája szerint:
pages.spec.tshead.spec.tsSpaShell) és a kliensoldaliuseDocumentMetaegyütt. A hiba itt némán áll elő: minden megosztott link „Portfólió"-ként bomlik ki, közben a böngésző füle helyesnek látszikcontact.spec.tslanguage.spec.tstheme.spec.tsanalytics.spec.ts?notrack=1kizárás — a mechanizmus maga a böngésző-tároló plusz a navigációcache-outage.spec.tsContentCachefail-open ága leállított Redisszel, külön futásban--wait-tel. Az admin nem indul: ahhozCloudflare Access assertion kellene, az kimarad az első körből.
workers: 1ésfullyParallel: false. Ez nem figyelmetlenség: minden kérés egy kliens IP-rőljön, a host pedig kliensenként limitál (240/perc, 60/perc útvonalanként) — egy párhuzamos suite
429-eket kapna, és a hiba bárminek látszana, csak rate limitnek nem. Ugyanezért kell a suite-nak
kicsinek maradnia; a komment a configban van, mert a következő teszt írójának szól.
deploy/smoke-test.shváltozatlan: az e2e a PR-t védi, a smoke a kiadást.Ami kimaradt: az
axe-coreés a Lighthouse mérés. Az issue szerint ugyanebben a jobbanfuttatható, de a Playwright bevezetése önmagában is megáll, és egy külön tételt nem érdemes ide
csomagolni.
Amit az első e2e futás hozott felszínre
A suite első CI futása 19 zöldet, 3 hibát és 1 flaky-t adott — mindhárom hiba a saját specjeimben
volt, a flaky viszont nem:
/assets/HomeView-*.js429-et kapott, ezért nem töltődött be a SPA. A ratelimit a statikus asseteket is számolja (240 kérés/perc/kliens), és egy friss böngésző-contextből
induló oldalbetöltés ~14 kérés. Élesben ez ritkán harap, mert a Cloudflare cache-eli a hash-elt
asseteket — CDN nélkül viszont minden oldalbetöltés a teljes asset-készletbe kerül az originnél.
RateLimitOptions). A default 0 = a hostbaépített érték, tehát éles viselkedés nem változik, és a
.env.examplekimondja, hogy élesben0-n kell maradnia. Az e2e job viszi feljebb, és a
deploy.ymlszándékosan nem írja a VPS.env-jébe: ez környezet-alakra szóló felülírás, nem üzemeltetési kapcsoló.tartalmi endpointját a szerver meg sem kapta — a kérések ott vártak, amíg a Redis-kliens
észrevette, hogy nincs kapcsolat. A fájl ezért egyszer, előre „felmelegíti" a felismerést, és a
tesztek utána a beállt állapotot mérik: a kérdés az, hogy kimaradás alatt működik-e az oldal,
nem az, hogy a kimaradás pillanatában is azonnal gyors-e.
A javítások után a fő suite 23/23 zöld 13,7 másodperc alatt, a kimaradás-készlet 3/3.