Wskaźnik offline: ramka zamiast belki + naprawa cyklicznego migania
Dwa zgłoszenia z kiosku (2026-07-31): 1. BELKA ZASŁANIAŁA DANE ALS. Pełnoekranowy pasek u góry zajmował pas ekranu i obcinał dane informacyjne w iframe. Zastąpiony cienką pulsującą RAMKĄ wokół całego ekranu (pointer-events: none, niczego nie zakrywa) plus małą plakietką w rogu. Z daleka widoczna równie dobrze. 2. WSKAŹNIK MIGAŁ zamiast świecić ciągle. disconnectedSince było resetowane przy KAŻDEJ nieudanej próbie reconnectu, nie tylko przy przejściu połączone->rozłączone — przy odstępie ponowień > 10 s (backoff dochodzi do 30 s) licznik ciszy zerował się co próbę i wskaźnik cyklicznie znikał i wracał. Teraz znacznik początku przerwy ustawiany wyłącznie przy przejściu ze stanu połączonego. Kontekst zgłoszenia: strona działa jeszcze przeciw STAREMU LuPortowi, który nie ma kanału zbiorczego ani uwierzytelniania WS — połączenie pada ciągle (oczekiwane do czasu wdrożenia; potem wstaje bez zmian), a błąd zamieniał tę ciągłą przerwę w miganie. Testy: scenariusz 7 próbkuje wskaźnik co 500 ms przez 90 s ciągłej awarii i wymaga 100% aktywnych próbek — z błędem aktywnych było 51/182 (72% czasu zgaszony; dokładnie zgłoszone "pojawia się i znika"). Fałszywy WebSocket odrzuca teraz połączenia jak przeglądarka (onclose po nieudanej próbie), więc długa przerwa z ponowieniami jest testowalna. 11/11 scenariuszy PASS, mutacja poprawki wywraca scenariusz 7. Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
This commit is contained in:
Binary file not shown.
+44
-17
@@ -40,8 +40,9 @@ function assert(nazwa, warunek) {
|
||||
}
|
||||
const alarmActive = () => document.getElementById("alarm-view").classList.contains("active");
|
||||
const cards = () => [...document.querySelectorAll(".card-machine-id")].map(e => e.textContent);
|
||||
const bannerActive = () => document.getElementById("offline-banner").classList.contains("active");
|
||||
const offline = () => document.getElementById("offline-indicator").classList.contains("active");
|
||||
const inst = () => FakeWebSocket.instances;
|
||||
const otwarty = () => inst().find(w => w.readyState === 1);
|
||||
|
||||
setTimeout(() => {
|
||||
assert("1. polaczenie nawiazane", inst().length === 1 && inst()[0].readyState === 1);
|
||||
@@ -67,46 +68,72 @@ setTimeout(() => {
|
||||
|
||||
setTimeout(() => {
|
||||
assert("5. maszyna spoza filtra ignorowana", !alarmActive());
|
||||
// serwer pada NA DLUGO: kazda kolejna proba polaczenia jest odrzucana
|
||||
FakeWebSocket.autoOpen = false;
|
||||
inst()[0]._serverClose();
|
||||
}, 250);
|
||||
|
||||
// KLUCZOWY test regresji: po zamknięciu MUSI powstać nowe połączenie.
|
||||
// KLUCZOWY test regresji starego bledu: po zamknieciu MUSI powstac nowa proba.
|
||||
setTimeout(() => {
|
||||
assert("6. reconnect zaplanowany i wykonany", inst().length >= 2);
|
||||
}, 5000);
|
||||
|
||||
// ANTY-MIGANIE (regresja 2026-07-31): przy DLUGIEJ przerwie wskaznik ma
|
||||
// swiecic CIAGLE. Blad resetowal disconnectedSince przy kazdej nieudanej
|
||||
// probie, wiec przy odstepie ponowien > 10 s wskaznik cyklicznie znikal.
|
||||
// Probkujemy co 500 ms przez 90 s ciaglej awarii — z bledem ~30% probek
|
||||
// bylo "zgaszonych", po poprawce wszystkie musza byc aktywne.
|
||||
window.__probki = { aktywne: 0, wszystkie: 0 };
|
||||
const probkowanie = setInterval(() => {
|
||||
window.__probki.wszystkie++;
|
||||
if (offline()) window.__probki.aktywne++;
|
||||
}, 500);
|
||||
setTimeout(() => { window.__probki.aktywne = 0; window.__probki.wszystkie = 0; }, 20000);
|
||||
setTimeout(() => {
|
||||
assert("7. baner offline widoczny po 10 s", bannerActive());
|
||||
clearInterval(probkowanie);
|
||||
const p = window.__probki;
|
||||
assert("7. wskaznik offline swieci CIAGLE przez cala przerwe (" +
|
||||
p.aktywne + "/" + p.wszystkie + " probek)", p.wszystkie > 100 && p.aktywne === p.wszystkie);
|
||||
// serwer wraca — najblizsza zaplanowana proba wstanie
|
||||
FakeWebSocket.autoOpen = true;
|
||||
inst()[inst().length-1]._open();
|
||||
inst()[inst().length-1]._message({type:"machine_data", machine:"4.09", data:{status:"Alarm - test"}});
|
||||
}, 16000);
|
||||
}, 111000);
|
||||
|
||||
setTimeout(() => {
|
||||
assert("8. po powrocie: baner znika, alarm 4.09", !bannerActive() && cards().join()==="4.09");
|
||||
}, 17000);
|
||||
|
||||
setTimeout(() => { window.__przedWatchdog = inst().length; }, 18000);
|
||||
setTimeout(() => {
|
||||
assert("9. watchdog: cisza 100s wymusza nowe polaczenie", inst().length > window.__przedWatchdog);
|
||||
}, 125000);
|
||||
assert("8. po powrocie serwera: polaczono, wskaznik zgaszony", !!otwarty() && !offline());
|
||||
otwarty() && otwarty()._message({type:"machine_data", machine:"4.09", data:{status:"Alarm - test"}});
|
||||
}, 155000);
|
||||
|
||||
setTimeout(() => {
|
||||
assert("10. przeterminowany alarm znika z ekranu", !alarmActive());
|
||||
assert("9. alarm po powrocie widoczny", alarmActive() && cards().join()==="4.09");
|
||||
window.__przedWatchdog = inst().length;
|
||||
}, 156000);
|
||||
|
||||
// cisza > 90 s -> watchdog ubija polaczenie, reconnect wstaje od reki
|
||||
setTimeout(() => {
|
||||
assert("10. watchdog: cisza wymusza nowe polaczenie", inst().length > window.__przedWatchdog);
|
||||
}, 270000);
|
||||
|
||||
// dane 4.09 z t=155 s bez odswiezenia -> po 5 min znikaja z ekranu
|
||||
setTimeout(() => {
|
||||
assert("11. przeterminowany alarm znika z ekranu", !alarmActive());
|
||||
document.getElementById("wynik").textContent += "\\nKONIEC";
|
||||
}, 340000);
|
||||
}, 470000);
|
||||
"""
|
||||
|
||||
FAKE_WS = """
|
||||
class FakeWebSocket {
|
||||
static instances = [];
|
||||
// true = polaczenie wstaje (serwer dziala)
|
||||
// false = polaczenie ODRZUCANE po chwili (serwer lezy / zly adres) —
|
||||
// przegladarka w tej sytuacji wola onclose, wiec fake tez musi,
|
||||
// inaczej nie da sie przetestowac dlugiej przerwy z ponowieniami.
|
||||
static autoOpen = true;
|
||||
constructor(url) {
|
||||
this.url = url;
|
||||
this.readyState = 0;
|
||||
FakeWebSocket.instances.push(this);
|
||||
if (FakeWebSocket.autoOpen) setTimeout(() => this._open(), 5);
|
||||
else setTimeout(() => this._serverClose(), 5);
|
||||
}
|
||||
_open() {
|
||||
if (this.readyState !== 0) return;
|
||||
@@ -141,7 +168,7 @@ def zbuduj_harness() -> str:
|
||||
markup = re.sub(r'src="http://[^"]*"', 'src="about:blank"', markup)
|
||||
return f"""<!doctype html><html><head><meta charset="utf-8"><style>
|
||||
#alarm-view{{display:none}} #alarm-view.active{{display:flex}}
|
||||
#offline-banner{{display:none}} #offline-banner.active{{display:block}}
|
||||
#offline-indicator{{display:none}} #offline-indicator.active{{display:block}}
|
||||
</style></head><body>
|
||||
{markup}
|
||||
<pre id="wynik"></pre>
|
||||
@@ -175,7 +202,7 @@ def main() -> int:
|
||||
"--headless",
|
||||
"--disable-gpu",
|
||||
"--no-sandbox",
|
||||
"--virtual-time-budget=350000",
|
||||
"--virtual-time-budget=480000",
|
||||
"--dump-dom",
|
||||
f"file://{harness}",
|
||||
],
|
||||
|
||||
Reference in New Issue
Block a user