lsa-planer

LSA-Planer Professional – Planungssoftware für Lichtsignalanlagen nach RiLSA 2015 und § 45 StVO. EUPL-1.2.

/ tests services kartenantwortInhalt.test.ts

4,4 KB Rohdatei
tests/services/kartenantwortInhalt.test.ts — 117 Zeilen
1 import { afterEach, describe, expect, it, vi } from 'vitest';
2 import { holeKartenbild } from '../../electron/karte';
3
4 /**
5 * Was der Hauptprozess als Bild durchlaesst.
6 *
7 * Der Inhaltstyp allein faengt nur den Dienst ab, der ehrlich meldet, was er
8 * schickt. Ueberlastete MapProxy- und UMN-Installationen antworten mit Status
9 * 200, `content-type: image/jpeg` und LEEREM Koerper; ein vorgeschalteter Proxy
10 * schiebt seine HTML-Fehlerseite unter demselben Typ durch. Beides kam bisher
11 * mit `ok: true` an der Anzeige an - als Daten-URL ohne Nutzlast beziehungsweise
12 * als base64-kodierte Fehlerseite.
13 *
14 * Der Schaden steht nicht im Hauptprozess, sondern im Dialog: Eine Antwort mit
15 * `ok: true` beendet die Wiederholung je Kachel und wird zwischengespeichert.
16 * Erst beim Zusammensetzen faellt auf, dass daraus kein Bild wird.
17 *
18 * Geprueft wird deshalb, dass eine solche Antwort hier abgewiesen wird - und
19 * dass eine echte Kachel weiterhin durchkommt.
20 */
21
22 const echtesFetch = globalThis.fetch;
23
24 afterEach(() => {
25 globalThis.fetch = echtesFetch;
26 vi.restoreAllMocks();
27 });
28
29 const NRW = 'https://www.wms.nrw.de/geobasis/wms_nw_dop?SERVICE=WMS&REQUEST=GetMap';
30
31 /** Antwort mit Statuscode 200 und frei waehlbarem Koerper und Inhaltstyp. */
32 function antwortMit(koerper: BodyInit, typ: string): Response {
33 return new Response(koerper, { status: 200, headers: { 'content-type': typ } });
34 }
35
36 const JPEG = new Uint8Array([0xff, 0xd8, 0xff, 0xdb, 0x00, 0x43]);
37 const PNG = new Uint8Array([0x89, 0x50, 0x4e, 0x47, 0x0d, 0x0a, 0x1a, 0x0a]);
38
39 describe('Kartenantwort mit Bild-Inhaltstyp, aber ohne Bild', () => {
40 it('weist einen leeren Koerper ab, statt Erfolg zu melden', async () => {
41 globalThis.fetch = vi.fn(async () => antwortMit(new Uint8Array(0), 'image/jpeg'));
42
43 const antwort = await holeKartenbild({ url: NRW });
44
45 expect(antwort.ok).toBe(false);
46 expect(antwort.datenUrl).toBeNull();
47 // Der Anwender muss erfahren, dass der Fehler beim Dienst liegt - sonst
48 // sucht er ihn bei sich.
49 expect(antwort.fehler).toContain('Kartendienst');
50 // Und keine Daten-URL ohne Nutzlast: Genau daran scheitert erst das
51 // Zusammensetzen des Mosaiks, lange nach dem Abruf.
52 expect(antwort.fehler).not.toContain('base64,');
53 });
54
55 it('weist eine HTML-Fehlerseite unter Bild-Inhaltstyp ab', async () => {
56 globalThis.fetch = vi.fn(async () =>
57 antwortMit('<html><body>503 Service Unavailable</body></html>', 'image/jpeg'),
58 );
59
60 const antwort = await holeKartenbild({ url: NRW });
61
62 expect(antwort.ok).toBe(false);
63 expect(antwort.datenUrl).toBeNull();
64 });
65
66 it('weist ab, wenn Inhaltstyp und Bildanfang nicht zusammenpassen', async () => {
67 // Gemeldet wird PNG, geliefert ein JPEG. Was hier durchginge, traegt den
68 // falschen Kopf in der Daten-URL.
69 globalThis.fetch = vi.fn(async () => antwortMit(JPEG, 'image/png'));
70
71 const antwort = await holeKartenbild({ url: NRW });
72
73 expect(antwort.ok).toBe(false);
74 expect(antwort.datenUrl).toBeNull();
75 });
76
77 it('etikettiert ein GIF nicht als JPEG', async () => {
78 // Ein Dienst, der image/gif liefert, wurde bisher als JPEG ausgegeben -
79 // die Zuordnung kannte nur "png oder sonst jpeg".
80 const gif = new Uint8Array([0x47, 0x49, 0x46, 0x38, 0x39, 0x61]);
81 globalThis.fetch = vi.fn(async () => antwortMit(gif, 'image/gif'));
82
83 const antwort = await holeKartenbild({ url: NRW });
84
85 expect(antwort.ok).toBe(false);
86 expect(antwort.datenUrl).toBeNull();
87 });
88 });
89
90 describe('Echte Kacheln kommen weiterhin durch', () => {
91 it('gibt ein JPEG mit gueltiger Signatur zurueck', async () => {
92 globalThis.fetch = vi.fn(async () => antwortMit(JPEG, 'image/jpeg'));
93
94 const antwort = await holeKartenbild({ url: NRW });
95
96 expect(antwort.ok).toBe(true);
97 expect(antwort.fehler).toBeNull();
98 expect(antwort.datenUrl?.startsWith('data:image/jpeg;base64,')).toBe(true);
99 });
100
101 it('gibt ein PNG mit gueltiger Signatur zurueck', async () => {
102 globalThis.fetch = vi.fn(async () => antwortMit(PNG, 'image/png'));
103
104 const antwort = await holeKartenbild({ url: NRW });
105
106 expect(antwort.ok).toBe(true);
107 expect(antwort.datenUrl?.startsWith('data:image/png;base64,')).toBe(true);
108 });
109
110 it('nimmt einen Inhaltstyp mit Anhang wie "image/jpeg; charset=binary"', async () => {
111 globalThis.fetch = vi.fn(async () => antwortMit(JPEG, 'image/jpeg; charset=binary'));
112
113 const antwort = await holeKartenbild({ url: NRW });
114
115 expect(antwort.ok).toBe(true);
116 });
117 });