netdiag-app/tools/pruefe-kette.mjs
Eduard Wisch 460b85d708 Internet-Kette: Anschluss, Gateway, Namensaufloesung und HTTPS in einem Lauf
Die haeufigste Aussage beim Kunden ist "Internet geht nicht". Bisher musste
der Techniker Ping, Traceroute und Browser einzeln bedienen und selbst
schlussfolgern, welches Glied hakt. Das Werkzeug misst alle vier Stufen in
einem Lauf und benennt das Fehlerglied.

Neue native Methoden: dnsResolve (System-Resolver; die Grenze - Server nicht
waehlbar, Cache dazwischen - steht im Code und im Ergebnis) und httpsCheck.
Bei httpsCheck ist instanceFollowRedirects=false keine Feinheit, sondern der
Kern: ein Gaeste-WLAN beantwortet jede Anfrage mit einer Umleitung auf sein
Portal. Wer ihr folgt, bekommt ein sauberes 200 und meldet "Internet in
Ordnung", obwohl ohne Anmeldung nichts geht. linkInfo liefert zusaetzlich
NET_CAPABILITY_VALIDATED und _CAPTIVE_PORTAL - Androids eigenes Urteil,
das uns keine einzige Messung kostet.

Drei Entscheidungen fuer die Ehrlichkeit der Aussage:
1. Die Kette bricht nicht ab. Sehr viele Router beantworten Ping
   grundsaetzlich nicht - ein Abbruch dort meldete "Gateway tot" bei
   voellig gesundem Internet.
2. Eine stille Stufe ist kein Fehler, wenn eine spaetere antwortet. Wer eine
   Antwort aus dem Internet bekommt, hat sein Gateway benutzt. Ergebnis:
   gruen mit Hinweis statt rot.
3. Anmeldeseite schlaegt Fehlerglied. Sonst stuende im Kundendokument "Kein
   Internet - HTTPS antwortet nicht", obwohl der Techniker nur auf "Anmelden"
   tippen muss. Beim Pruefen aufgefallen und korrigiert.

Die Bewertung liegt in kette-bewertung.ts ohne jeden Laufzeit-Import, damit
tools/pruefe-kette.mjs sie laden kann: elf konstruierte Faelle gegen von Hand
ermittelte Sollwerte, alle korrekt. Der Browser-Mock liefert fuer DNS und
HTTPS bewusst nur den Gutfall und beweist nichts - das steht dort auch so.

Dabei repariert: tools/pruefe-monitor.mjs importierte eine .mjs-Kopie aus
einem /tmp-Sitzungsverzeichnis und lief nach dessen Wegfall nicht mehr,
waehrend in der ROADMAP "alle Faelle korrekt" stand. Die Rechnung liegt jetzt
in monitor-auswertung.ts, beide Pruefer laden die TS-Datei direkt.

Neu in der Debug-Seite: "Internet-Kette pruefen (misst nur, speichert nichts)".
Beantwortet vor Ort die erste aller Fragen - kommt das Messgeraet selbst ins
Netz? - und ist der einzige Weg, die native Schicht im Emulator zu pruefen,
solange die Testinstanz nur HTTP spricht (der WebView blockiert aus der
Origin https://localhost jede HTTP-Anfrage, siehe ROADMAP).

Im Emulator geprueft: Gutfall (alle vier Stufen mit Messwerten, validated=ja)
und Flugmodus (Status "nicht messbar", Fehlerglied Anschluss, ausdruecklich
KEINE Aussage ueber das Kundennetz).

Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
2026-08-16 22:56:20 +02:00

119 lines
4.7 KiB
JavaScript

/**
* Prueft die Bewertung der Internet-Kette gegen konstruierte Faelle mit von
* Hand ermitteltem Sollwert.
*
* Warum ueberhaupt: der Browser-Mock liefert fuer DNS und HTTPS immer den
* guten Fall, dort ist die Kette also IMMER gruen. Genau die Faelle, wegen
* derer das Werkzeug gebaut wurde (Gateway still, DNS tot, Anmeldeseite),
* kommen im Mock nicht vor.
*
* Start: node tools/pruefe-kette.mjs
* (laedt die TS-Datei direkt — Node 22.6+ entfernt die Typannotationen selbst;
* deshalb darf kette-bewertung.ts keinen Laufzeit-Import enthalten)
*/
const { bewerteKette } = await import('../src/lib/tools/internet/kette-bewertung.ts');
const anschlussOk = { name: 'Anschluss', ok: true, detail: 'LAN (Kabel) eth0, IP 192.168.1.42/24' };
const gwOk = { name: 'Gateway', ok: true, detail: '192.168.1.1 antwortet in 2 ms', stillErlaubt: true };
const gwStill = { name: 'Gateway', ok: false, detail: 'antwortet auf keines von 4 Paketen', stillErlaubt: true };
const gwUnbekannt = { name: 'Gateway', ok: null, detail: 'kein Standard-Gateway gemeldet', stillErlaubt: true };
const dnsOk = { name: 'Namensauflösung', ok: true, detail: 'www.google.de → 142.250.185.67 (23 ms)' };
const dnsTot = { name: 'Namensauflösung', ok: false, detail: 'nicht auflösbar (UnknownHostException)' };
const httpsOk = { name: 'HTTPS-Abruf', ok: true, detail: 'HTTP 204 in 58 ms' };
const httpsTot = { name: 'HTTPS-Abruf', ok: false, detail: 'kein Verbindungsaufbau (timeout)' };
const faelle = [
{
name: 'Alles in Ordnung',
stufen: [anschlussOk, gwOk, dnsOk, httpsOk],
portal: false,
system: true,
soll: { status: 0, glied: '' },
},
{
name: 'Gateway antwortet nicht auf Ping, Internet geht -> GRUEN mit Hinweis',
stufen: [anschlussOk, gwStill, dnsOk, httpsOk],
portal: false,
system: true,
soll: { status: 0, glied: '', hinweisEnthaelt: 'Werkseinstellung' },
},
{
name: 'Gateway tot UND alles danach tot -> Fehlerglied Gateway',
stufen: [anschlussOk, gwStill, dnsTot, httpsTot],
portal: false,
system: false,
soll: { status: 2, glied: 'Gateway' },
},
{
name: 'Gateway ok, DNS tot -> Fehlerglied Namensaufloesung',
stufen: [anschlussOk, gwOk, dnsTot, httpsTot],
portal: false,
system: false,
soll: { status: 2, glied: 'Namensauflösung' },
},
{
name: 'DNS ok, HTTPS tot -> Fehlerglied HTTPS-Abruf',
stufen: [anschlussOk, gwOk, dnsOk, httpsTot],
portal: false,
system: false,
soll: { status: 2, glied: 'HTTPS-Abruf' },
},
{
name: 'Umleitung auf Anmeldeseite -> GELB "Anmeldeseite", NICHT rot "HTTPS tot"',
stufen: [anschlussOk, gwOk, dnsOk, { name: 'HTTPS-Abruf', ok: false, detail: 'HTTP 302 → Portal' }],
portal: true,
system: false,
soll: { status: 1, glied: 'Anmeldeseite', hinweisEnthaelt: 'Gäste-WLAN' },
},
{
name: 'Portal nur ueber das Systemflag erkannt -> GELB Anmeldeseite',
stufen: [anschlussOk, gwOk, dnsOk, httpsOk],
portal: true,
system: false,
soll: { status: 1, glied: 'Anmeldeseite' },
},
{
name: 'Alles ok, aber Android bestaetigt die Verbindung nicht -> GELB',
stufen: [anschlussOk, gwOk, dnsOk, httpsOk],
portal: false,
system: false,
soll: { status: 1, glied: '', hinweisEnthaelt: 'gefilterte' },
},
{
name: 'Kein Anschluss (keine IP) -> NICHT MESSBAR, keine Aussage ueber das Kundennetz',
stufen: [{ name: 'Anschluss', ok: null, detail: 'keine IP-Adresse' }],
portal: false,
system: undefined,
soll: { status: 3, glied: 'Anschluss' },
},
{
name: 'Kein Gateway gemeldet, Rest geht -> GRUEN mit Hinweis "nicht geprueft"',
stufen: [anschlussOk, gwUnbekannt, dnsOk, httpsOk],
portal: false,
system: true,
soll: { status: 0, glied: '', hinweisEnthaelt: 'nicht geprüft' },
},
{
name: 'Systemurteil unbekannt (aeltere Android-Version) -> GRUEN, kein Gelb aus Unwissen',
stufen: [anschlussOk, gwOk, dnsOk, httpsOk],
portal: false,
system: undefined,
soll: { status: 0, glied: '' },
},
];
let fehler = 0;
for (const f of faelle) {
const r = bewerteKette(f.stufen, f.portal, f.system);
let ok = r.status === f.soll.status && r.fehlerglied === f.soll.glied;
if (f.soll.hinweisEnthaelt && !(r.hinweis || '').includes(f.soll.hinweisEnthaelt)) ok = false;
if (!ok) fehler++;
console.log(`${ok ? 'OK ' : 'FEHL'} ${f.name}`);
console.log(` status=${r.status} (soll ${f.soll.status}) glied="${r.fehlerglied}" (soll "${f.soll.glied}")`);
console.log(` Label: ${r.label}`);
if (r.hinweis) console.log(` Hinweis: ${r.hinweis.slice(0, 120)}`);
console.log();
}
console.log(fehler === 0 ? 'ALLE FAELLE KORREKT' : `${fehler} FEHLER`);
process.exit(fehler === 0 ? 0 : 1);