import { describe, expect, it } from 'vitest'; import { erlaubteRechner, istErlaubt } from '../../electron/karte'; import { KARTENDIENSTE, baueKachelplan, dienstMit, herkunftstext, rechnernamen, } from '@/services/kartendienste'; /** * Kartendienste. * * Zwei Dinge muessen hier stimmen, und beide waeren im Betrieb nur schwer zu * bemerken: * * 1. Die Freigabeliste des Hauptprozesses muss alle eingetragenen Dienste * enthalten. Fehlt einer, laesst sich der Dienst zwar auswaehlen, der Abruf * scheitert aber mit einer Meldung, die wie ein Netzfehler aussieht. * * 2. Die Adressen, die das Programm tatsaechlich baut, muessen zu dieser Liste * passen. Eine Adresse, die der Hauptprozess abweist, sieht fuer den * Anwender wie ein Netzfehler aus. * * Der Zuschnitt des Ausschnitts steht in kachelplan.test.ts - dort wird gegen * ausschnittUm() geprueft, also gegen Mittelpunkt UND Kantenlaenge. */ const KNOTEN = { breite: 50.9412784, laenge: 6.9582814 }; describe('Freigabeliste', () => { it('enthaelt jeden eingetragenen Kartendienst', () => { const freigegeben = erlaubteRechner(); for (const name of rechnernamen()) { expect(freigegeben, `Rechner ${name} fehlt in electron/karte.ts`).toContain(name); } }); it('laesst jede erzeugte Abrufadresse zu - auch jede einzelne Kachel', () => { // Geprueft wird der Weg, den das Programm wirklich geht: Der Luftbilddialog // ruft ausschliesslich baueKachelplan. Eine Kantenlaenge, die aufteilt, // damit nicht nur die erste Adresse geprueft wird. for (const dienst of KARTENDIENSTE) { const plan = baueKachelplan({ dienst, mitte: KNOTEN, kantenlaenge: 600 }); expect(plan.kacheln.length, `${dienst.id} ohne Kacheln`).toBeGreaterThan(0); for (const kachel of plan.kacheln) { expect( istErlaubt(kachel.url), `${dienst.id}, Kachel ${kachel.spalte}/${kachel.zeile} nicht freigegeben`, ).toBe(true); } } }); it('weist fremde Rechner, unverschluesselte Verbindungen und Unsinn ab', () => { expect(istErlaubt('https://beispiel.example/wms?REQUEST=GetMap')).toBe(false); expect(istErlaubt('http://www.wms.nrw.de/geobasis/wms_nw_dop')).toBe(false); expect(istErlaubt('file:///C:/Windows/win.ini')).toBe(false); expect(istErlaubt('')).toBe(false); // Der Rechnername steht am Ende der Autoritaet, nicht irgendwo darin. expect(istErlaubt('https://www.wms.nrw.de.angreifer.example/x')).toBe(false); expect(istErlaubt('https://angreifer.example/?x=www.wms.nrw.de')).toBe(false); }); }); describe('Bildanforderung', () => { /* * Bildgroesse, Achsfolge, Massstab und Zuschnitt stehen in * kachelplan.test.ts - dort am Weg, den das Programm geht. Hier bleibt, was * dort fehlt: die Wahl der UTM-Zone. Der Kachelplan-Test prueft nur Zone 32, * weil alle seine Kacheln in derselben Zone liegen muessen. */ const dienst = dienstMit('nw-dop'); it('waehlt die UTM-Zone nach der geografischen Laenge', () => { // Aachen liegt in Zone 32, Goerlitz in Zone 33. Die falsche Zone // verschiebt den Ausschnitt um Hunderte Kilometer - der Dienst liefert // dann ein leeres Bild. const zoneVon = (laenge: number, breite: number): string | null => { const plan = baueKachelplan({ dienst, mitte: { breite, laenge }, kantenlaenge: 200 }); return new URL(plan.kacheln[0]!.url).searchParams.get('CRS'); }; expect(zoneVon(6.0839, 50.7753)).toBe('EPSG:25832'); expect(zoneVon(14.9873, 51.1524)).toBe('EPSG:25833'); }); }); describe('Quellenangabe', () => { it('nennt Herausgeber, Mittelpunkt und Kantenlaenge', () => { const text = herkunftstext(dienstMit('nw-dop'), KNOTEN, 200); expect(text).toContain('Geobasis NRW'); expect(text).toContain('50.941278'); // Sechs Nachkommastellen sind rund elf Zentimeter - genauer muss ein // Ausschnittsmittelpunkt nicht sein. Die letzte Stelle haengt an der // Binaerdarstellung, deshalb wird sie hier nicht mitgeprueft. expect(text).toContain('6.95828'); expect(text).toContain('200 m'); }); it('fuehrt den vorgeschriebenen Vermerk mit, wo einer verlangt ist', () => { for (const dienst of KARTENDIENSTE) { if (dienst.namensnennung === null) continue; expect(herkunftstext(dienst, KNOTEN, 200)).toContain(dienst.namensnennung); } }); }); describe('Eintraege', () => { it('haben eindeutige Kennungen und https-Adressen', () => { const kennungen = KARTENDIENSTE.map((d) => d.id); expect(new Set(kennungen).size).toBe(kennungen.length); for (const dienst of KARTENDIENSTE) { expect(dienst.basisUrl.startsWith('https://'), dienst.id).toBe(true); expect(dienst.aufloesung).toBeGreaterThan(0); expect(dienst.nutzungsrecht.length).toBeGreaterThan(10); } }); });