fix(v5): MakeMKV-Installer aus dem Internet Archive nur nach Rückfrage, mit Größe und SHA-256
WAS: makemkvInstallerHolen fragt vor der Archiv-Quelle über eine Freigabe-Funktion; ohne Freigabe wird das Archiv übersprungen und im Bericht genannt. Der Kern stellt die Frage ans Fenster (beschaffung-status mit `frage`), die MakeMKV-Karte zeigt sie mit „Archiv-Kopie laden" / „Lieber nicht" (beschaffung-antwort); ohne Antwort in zehn Minuten gilt Nein. Die geladene Datei wird mit Größe und SHA-256 gemeldet. WARUM: Durchsicht 12.09.2026, Fund F16 (Commander-Entscheid: Archiv nur nach Rückfrage) — eine unsignierte EXE von fremder Hand, die mit Adminrechten läuft, entscheidet der Nutzer, nicht Rippy. Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
This commit is contained in:
co-authored by
Claude Opus 5
parent
3dacd7cb4f
commit
ae82d8c0fd
@@ -22,6 +22,7 @@ import {
|
|||||||
} from '../bausteine'
|
} from '../bausteine'
|
||||||
import {
|
import {
|
||||||
benachrichtigungTesten,
|
benachrichtigungTesten,
|
||||||
|
beschaffungAntworten,
|
||||||
einstellungSetzen,
|
einstellungSetzen,
|
||||||
fremdenOrdnerLoeschen,
|
fremdenOrdnerLoeschen,
|
||||||
kompressionAbbrechen,
|
kompressionAbbrechen,
|
||||||
@@ -480,6 +481,19 @@ export function MakemkvKarte({ verbindung }: { verbindung: Verbindung }) {
|
|||||||
{b !== null && (
|
{b !== null && (
|
||||||
<div className="rounded-lg border border-tinte/10 bg-buehne/70 p-2.5">
|
<div className="rounded-lg border border-tinte/10 bg-buehne/70 p-2.5">
|
||||||
<p className={`font-mono text-[11px] leading-5 ${b.fehler ? 'text-rot' : b.laeuft ? 'text-gold-hell' : 'text-gruen'}`}>{b.text}</p>
|
<p className={`font-mono text-[11px] leading-5 ${b.fehler ? 'text-rot' : b.laeuft ? 'text-gold-hell' : 'text-gruen'}`}>{b.text}</p>
|
||||||
|
{b.frage !== undefined && b.frage.length > 0 && (
|
||||||
|
<div className="mt-2 rounded-lg border border-warn/45 bg-warn/10 p-2.5">
|
||||||
|
<p className="text-xs leading-5 text-dunst">{b.frage}</p>
|
||||||
|
<div className="mt-2 flex flex-wrap gap-2">
|
||||||
|
<button onClick={() => beschaffungAntworten(true)} className="rounded-lg border border-warn/50 bg-warn/15 px-3 py-1 text-[11px] font-semibold text-warn hover:bg-warn/25">
|
||||||
|
Archiv-Kopie laden
|
||||||
|
</button>
|
||||||
|
<button onClick={() => beschaffungAntworten(false)} className={KNOPF_LEISE}>
|
||||||
|
Lieber nicht
|
||||||
|
</button>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
)}
|
||||||
{b.laeuft && b.anteil !== null && (
|
{b.laeuft && b.anteil !== null && (
|
||||||
<div className="mt-1.5 h-1.5 overflow-hidden rounded-full bg-tinte/8">
|
<div className="mt-1.5 h-1.5 overflow-hidden rounded-full bg-tinte/8">
|
||||||
<div className="h-full rounded-full bg-gradient-to-r from-gold-tief to-gold-hell transition-all" style={{ width: `${Math.round(b.anteil * 100)}%` }} />
|
<div className="h-full rounded-full bg-gradient-to-r from-gold-tief to-gold-hell transition-all" style={{ width: `${Math.round(b.anteil * 100)}%` }} />
|
||||||
|
|||||||
@@ -381,6 +381,11 @@ export function schluesselPruefen(): void {
|
|||||||
senden({ art: 'schluessel-pruefen' })
|
senden({ art: 'schluessel-pruefen' })
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/** 5.7.0 (F16): Ja/Nein auf eine Frage der MakeMKV-Beschaffung. */
|
||||||
|
export function beschaffungAntworten(ja: boolean): void {
|
||||||
|
anKern({ art: 'beschaffung-antwort', ja }, 'Antwort an die Beschaffung')
|
||||||
|
}
|
||||||
|
|
||||||
export function einstellungSetzen(schluessel: string, wert: string): void {
|
export function einstellungSetzen(schluessel: string, wert: string): void {
|
||||||
anKern({ art: 'einstellung-setzen', schluessel, wert }, `Einstellung ${schluessel}`)
|
anKern({ art: 'einstellung-setzen', schluessel, wert }, `Einstellung ${schluessel}`)
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -257,6 +257,9 @@ export interface BeschaffungStand {
|
|||||||
/** 0–1 während des Downloads; null wenn gerade nicht bezifferbar. */
|
/** 0–1 während des Downloads; null wenn gerade nicht bezifferbar. */
|
||||||
anteil: number | null
|
anteil: number | null
|
||||||
fehler: boolean
|
fehler: boolean
|
||||||
|
/** 5.7.0 (F16): Rippy wartet auf ein Ja/Nein — z. B. „Archiv-Kopie laden?".
|
||||||
|
* Fehlt: keine Frage offen. */
|
||||||
|
frage?: string
|
||||||
}
|
}
|
||||||
|
|
||||||
// ── Vorgänge und Kompressions-Warteschlange (5.4.0) ─────────────────────
|
// ── Vorgänge und Kompressions-Warteschlange (5.4.0) ─────────────────────
|
||||||
@@ -450,6 +453,8 @@ export type FensterNachricht =
|
|||||||
| { art: 'makemkv-update' }
|
| { art: 'makemkv-update' }
|
||||||
/** Schlüsselkette sofort neu laufen lassen (z. B. nach einer Installation). */
|
/** Schlüsselkette sofort neu laufen lassen (z. B. nach einer Installation). */
|
||||||
| { art: 'schluessel-pruefen' }
|
| { art: 'schluessel-pruefen' }
|
||||||
|
/** 5.7.0 (F16): Antwort auf eine Frage der MakeMKV-Beschaffung. */
|
||||||
|
| { art: 'beschaffung-antwort'; ja: boolean }
|
||||||
// ── 5.4.0: Vorgänge, Roh-Dateien, Warteschlange, Laufwerks-Gesundheit ──
|
// ── 5.4.0: Vorgänge, Roh-Dateien, Warteschlange, Laufwerks-Gesundheit ──
|
||||||
| { art: 'vorgaenge-laden' }
|
| { art: 'vorgaenge-laden' }
|
||||||
/** Den Roh-Ordner EINES Vorgangs jetzt löschen (von Hand). */
|
/** Den Roh-Ordner EINES Vorgangs jetzt löschen (von Hand). */
|
||||||
@@ -712,6 +717,9 @@ export function istFensterNachricht(wert: unknown): wert is FensterNachricht {
|
|||||||
if (wert.art === 'kompression-pause') {
|
if (wert.art === 'kompression-pause') {
|
||||||
return typeof wert.an === 'boolean'
|
return typeof wert.an === 'boolean'
|
||||||
}
|
}
|
||||||
|
if (wert.art === 'beschaffung-antwort') {
|
||||||
|
return typeof wert.ja === 'boolean'
|
||||||
|
}
|
||||||
if (wert.art === 'einstellung-setzen') {
|
if (wert.art === 'einstellung-setzen') {
|
||||||
return istKennung(wert.schluessel) && typeof wert.wert === 'string'
|
return istKennung(wert.schluessel) && typeof wert.wert === 'string'
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -15,6 +15,9 @@ export class WerkzeugDienst {
|
|||||||
schluesselStand: SchluesselStand | null = null
|
schluesselStand: SchluesselStand | null = null
|
||||||
private beschaffungLaeuft = false
|
private beschaffungLaeuft = false
|
||||||
private installerAntwort: ((fehler: string | null) => void) | null = null
|
private installerAntwort: ((fehler: string | null) => void) | null = null
|
||||||
|
/** 5.7.0 (F16): Die offene Ja/Nein-Frage der Beschaffung — null, wenn keine. */
|
||||||
|
private frageAntwort: ((ja: boolean) => void) | null = null
|
||||||
|
private letzterBeschaffungsText = ''
|
||||||
|
|
||||||
constructor(
|
constructor(
|
||||||
private readonly kontext: KernKontext,
|
private readonly kontext: KernKontext,
|
||||||
@@ -115,9 +118,40 @@ export class WerkzeugDienst {
|
|||||||
this.installerAntwort = null
|
this.installerAntwort = null
|
||||||
}
|
}
|
||||||
|
|
||||||
private beschaffungMelden(text: string, anteil: number | null, laeuft: boolean, fehler = false): void {
|
private beschaffungMelden(text: string, anteil: number | null, laeuft: boolean, fehler = false, frage?: string): void {
|
||||||
this.kontext.anFenster({ art: 'beschaffung-status', stand: { werkzeug: 'makemkv', laeuft, text, anteil, fehler } })
|
this.letzterBeschaffungsText = text
|
||||||
this.kontext.protokoll.schreiben(`MakeMKV-Update: ${text}`)
|
this.kontext.anFenster({ art: 'beschaffung-status', stand: { werkzeug: 'makemkv', laeuft, text, anteil, fehler, ...(frage !== undefined ? { frage } : {}) } })
|
||||||
|
this.kontext.protokoll.schreiben(`MakeMKV-Update: ${text}${frage !== undefined ? ` — FRAGE: ${frage}` : ''}`)
|
||||||
|
}
|
||||||
|
|
||||||
|
/** Antwort des Fensters auf eine offene Frage (beschaffung-antwort). */
|
||||||
|
beschaffungAntwort(ja: boolean): void {
|
||||||
|
const antwort = this.frageAntwort
|
||||||
|
this.frageAntwort = null
|
||||||
|
if (antwort === null) {
|
||||||
|
this.kontext.hinweis('Es ist keine Frage der MakeMKV-Beschaffung offen.')
|
||||||
|
return
|
||||||
|
}
|
||||||
|
antwort(ja)
|
||||||
|
}
|
||||||
|
|
||||||
|
/** Eine Ja/Nein-Frage ans Fenster; ohne Antwort in zehn Minuten gilt Nein. */
|
||||||
|
private frage(text: string): Promise<boolean> {
|
||||||
|
return new Promise((fertig) => {
|
||||||
|
this.frageAntwort = (ja) => {
|
||||||
|
clearTimeout(zeiger)
|
||||||
|
this.beschaffungMelden(ja ? 'Freigegeben — die Archiv-Kopie wird geladen.' : 'Nicht freigegeben.', null, true)
|
||||||
|
fertig(ja)
|
||||||
|
}
|
||||||
|
const zeiger = setTimeout(() => {
|
||||||
|
if (this.frageAntwort === null) return
|
||||||
|
this.frageAntwort = null
|
||||||
|
this.beschaffungMelden('Keine Antwort — die Archiv-Kopie wird nicht geladen.', null, true)
|
||||||
|
fertig(false)
|
||||||
|
}, 10 * 60_000)
|
||||||
|
zeiger.unref()
|
||||||
|
this.beschaffungMelden(this.letzterBeschaffungsText, null, true, false, text)
|
||||||
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
// ── MakeMKV-Update (§ 9): holen, prüfen, installieren lassen ────────────
|
// ── MakeMKV-Update (§ 9): holen, prüfen, installieren lassen ────────────
|
||||||
@@ -168,8 +202,25 @@ export class WerkzeugDienst {
|
|||||||
const alteExe = this.makemkvcon()
|
const alteExe = this.makemkvcon()
|
||||||
const alteVersion = alteExe.length > 0 ? versionsangaben(alteExe).version : ''
|
const alteVersion = alteExe.length > 0 ? versionsangaben(alteExe).version : ''
|
||||||
|
|
||||||
const ergebnis = await makemkvInstallerHolen(neueste, (text, anteil) => this.beschaffungMelden(text, anteil, true))
|
const ergebnis = await makemkvInstallerHolen(
|
||||||
this.beschaffungMelden(`Geprüft (Quelle: ${ergebnis.quelle}) — der Installer wird gestartet …`, null, true)
|
neueste,
|
||||||
|
(text, anteil) => this.beschaffungMelden(text, anteil, true),
|
||||||
|
'',
|
||||||
|
undefined,
|
||||||
|
undefined,
|
||||||
|
undefined,
|
||||||
|
// F16: Das Archiv liefert eine unsignierte EXE, die gleich mit
|
||||||
|
// Adminrechten läuft — das entscheidet der Nutzer, nicht Rippy.
|
||||||
|
(quelle) =>
|
||||||
|
this.frage(
|
||||||
|
`makemkv.com antwortet nicht. Soll Rippy den MakeMKV-Installer ${neueste} aus dem ${quelle} laden? Das ist eine Kopie von fremder Hand, geprüft wird nur, dass sie ein MakeMKV-Programm ist — er läuft danach mit Adminrechten. Wer sicher gehen will, lädt später selbst von makemkv.com.`,
|
||||||
|
),
|
||||||
|
)
|
||||||
|
this.beschaffungMelden(
|
||||||
|
`Geprüft (Quelle: ${ergebnis.quelle}, ${(ergebnis.bytes / 1024 ** 2).toFixed(1)} MB, SHA-256 ${ergebnis.sha256}) — der Installer wird gestartet …`,
|
||||||
|
null,
|
||||||
|
true,
|
||||||
|
)
|
||||||
|
|
||||||
const startFehler = await new Promise<string | null>((fertig) => {
|
const startFehler = await new Promise<string | null>((fertig) => {
|
||||||
this.installerAntwort = fertig
|
this.installerAntwort = fertig
|
||||||
|
|||||||
@@ -288,6 +288,9 @@ function fensterNachricht(frage: unknown): void {
|
|||||||
case 'schluessel-pruefen':
|
case 'schluessel-pruefen':
|
||||||
void werkzeuge.schluesselLauf().then(() => werkzeuge.senden())
|
void werkzeuge.schluesselLauf().then(() => werkzeuge.senden())
|
||||||
return
|
return
|
||||||
|
case 'beschaffung-antwort':
|
||||||
|
werkzeuge.beschaffungAntwort(frage.ja)
|
||||||
|
return
|
||||||
case 'vorgaenge-laden':
|
case 'vorgaenge-laden':
|
||||||
vorgaenge.neuMessen()
|
vorgaenge.neuMessen()
|
||||||
return
|
return
|
||||||
|
|||||||
@@ -22,7 +22,8 @@
|
|||||||
// 3. NIE eine gute Datei durch eine halbe ersetzen: Geladen wird in
|
// 3. NIE eine gute Datei durch eine halbe ersetzen: Geladen wird in
|
||||||
// `.neu`, geprüft, erst dann getauscht.
|
// `.neu`, geprüft, erst dann getauscht.
|
||||||
import { spawnSync } from 'node:child_process'
|
import { spawnSync } from 'node:child_process'
|
||||||
import { createWriteStream, openSync, readSync, closeSync, mkdirSync, renameSync, rmSync, statSync } from 'node:fs'
|
import { createHash } from 'node:crypto'
|
||||||
|
import { createWriteStream, openSync, readFileSync, readSync, closeSync, mkdirSync, renameSync, rmSync, statSync } from 'node:fs'
|
||||||
import { win32 as pfad } from 'node:path'
|
import { win32 as pfad } from 'node:path'
|
||||||
import { werkzeugOrdner } from './katalog'
|
import { werkzeugOrdner } from './katalog'
|
||||||
|
|
||||||
@@ -285,6 +286,22 @@ export interface BeschaffungErgebnis {
|
|||||||
pfad: string
|
pfad: string
|
||||||
quelle: string
|
quelle: string
|
||||||
version: string
|
version: string
|
||||||
|
/** 5.7.0 (F16): Größe und SHA-256 der geladenen Datei — damit man sie
|
||||||
|
* gegen die Herstellerangabe halten kann, sobald die Seite wieder da ist. */
|
||||||
|
bytes: number
|
||||||
|
sha256: string
|
||||||
|
}
|
||||||
|
|
||||||
|
/** SHA-256 einer Datei als Hex — für die Anzeige neben dem Installer. */
|
||||||
|
export function pruefsumme(dateiPfad: string): string {
|
||||||
|
return createHash('sha256').update(readFileSync(dateiPfad)).digest('hex')
|
||||||
|
}
|
||||||
|
|
||||||
|
/** Welche Quelle ein Rückfrage braucht: alles außer Hersteller und eigener
|
||||||
|
* Basis. Das Internet Archive liefert eine unsignierte EXE, die mit
|
||||||
|
* Adminrechten läuft — das entscheidet der Nutzer, nicht Rippy (F16). */
|
||||||
|
export function brauchtFreigabe(quellenName: string): boolean {
|
||||||
|
return quellenName === 'Internet Archive'
|
||||||
}
|
}
|
||||||
|
|
||||||
/** Lädt den MakeMKV-Installer über die Quellenkette in Rippys
|
/** Lädt den MakeMKV-Installer über die Quellenkette in Rippys
|
||||||
@@ -297,6 +314,9 @@ export async function makemkvInstallerHolen(
|
|||||||
holen: typeof fetch = fetch,
|
holen: typeof fetch = fetch,
|
||||||
ordner: string = pfad.join(werkzeugOrdner(), 'downloads'),
|
ordner: string = pfad.join(werkzeugOrdner(), 'downloads'),
|
||||||
pruefen: typeof dateiPruefen = dateiPruefen,
|
pruefen: typeof dateiPruefen = dateiPruefen,
|
||||||
|
/** 5.7.0 (F16): Darf eine Quelle mit Rückfrage benutzt werden? Ohne
|
||||||
|
* diese Funktion wird sie übersprungen — nie still geladen. */
|
||||||
|
freigabe?: (quellenName: string, url: string) => Promise<boolean>,
|
||||||
): Promise<BeschaffungErgebnis> {
|
): Promise<BeschaffungErgebnis> {
|
||||||
mkdirSync(ordner, { recursive: true })
|
mkdirSync(ordner, { recursive: true })
|
||||||
const ziel = pfad.join(ordner, `Setup_MakeMKV_v${version}.exe`)
|
const ziel = pfad.join(ordner, `Setup_MakeMKV_v${version}.exe`)
|
||||||
@@ -304,6 +324,14 @@ export async function makemkvInstallerHolen(
|
|||||||
|
|
||||||
const fehlschlaege: string[] = []
|
const fehlschlaege: string[] = []
|
||||||
for (const [name, url] of makemkvQuellen(version, basis)) {
|
for (const [name, url] of makemkvQuellen(version, basis)) {
|
||||||
|
if (brauchtFreigabe(name)) {
|
||||||
|
const erlaubt = freigabe !== undefined && (await freigabe(name, url))
|
||||||
|
if (!erlaubt) {
|
||||||
|
fehlschlaege.push(`${name}: nicht freigegeben`)
|
||||||
|
melden(`${name} wurde nicht freigegeben.`, null)
|
||||||
|
continue
|
||||||
|
}
|
||||||
|
}
|
||||||
melden(`MakeMKV ${version} wird geladen (${name}) …`, 0)
|
melden(`MakeMKV ${version} wird geladen (${name}) …`, 0)
|
||||||
try {
|
try {
|
||||||
await dateiLaden(url, vorlaeufig, melden, holen)
|
await dateiLaden(url, vorlaeufig, melden, holen)
|
||||||
@@ -312,7 +340,7 @@ export async function makemkvInstallerHolen(
|
|||||||
// Erst tauschen, wenn geprüft — ein halber Download darf eine gute
|
// Erst tauschen, wenn geprüft — ein halber Download darf eine gute
|
||||||
// Datei nicht ersetzen.
|
// Datei nicht ersetzen.
|
||||||
renameSync(vorlaeufig, ziel)
|
renameSync(vorlaeufig, ziel)
|
||||||
return { pfad: ziel, quelle: name, version }
|
return { pfad: ziel, quelle: name, version, bytes: statSync(ziel).size, sha256: pruefsumme(ziel) }
|
||||||
} catch (fehler) {
|
} catch (fehler) {
|
||||||
fehlschlaege.push(`${name}: ${fehler instanceof Error ? fehler.message : String(fehler)}`)
|
fehlschlaege.push(`${name}: ${fehler instanceof Error ? fehler.message : String(fehler)}`)
|
||||||
melden(`${name} hat nicht geliefert.`, null)
|
melden(`${name} hat nicht geliefert.`, null)
|
||||||
|
|||||||
@@ -136,10 +136,11 @@ describe('dateiPruefen', () => {
|
|||||||
describe('makemkvInstallerHolen', () => {
|
describe('makemkvInstallerHolen', () => {
|
||||||
const GROSS = Buffer.concat([Buffer.from('MZ'), Buffer.alloc(1024 * 1024 + 100, 7)])
|
const GROSS = Buffer.concat([Buffer.from('MZ'), Buffer.alloc(1024 * 1024 + 100, 7)])
|
||||||
|
|
||||||
it('Fehlerseite mit HTTP 200 fällt durch die Mindestgröße — die nächste Quelle gewinnt', async () => {
|
it('Fehlerseite mit HTTP 200 fällt durch die Mindestgröße — die nächste Quelle gewinnt (mit Freigabe)', async () => {
|
||||||
const ordner = tempOrdner()
|
const ordner = tempOrdner()
|
||||||
const holen = (async (url: string | URL | Request) =>
|
const holen = (async (url: string | URL | Request) =>
|
||||||
String(url).includes('web.archive.org') ? antwort(GROSS) : antwort('<html>kaputt</html>')) as typeof fetch
|
String(url).includes('web.archive.org') ? antwort(GROSS) : antwort('<html>kaputt</html>')) as typeof fetch
|
||||||
|
const gefragt: string[] = []
|
||||||
const ergebnis = await makemkvInstallerHolen(
|
const ergebnis = await makemkvInstallerHolen(
|
||||||
'1.18.4',
|
'1.18.4',
|
||||||
() => {},
|
() => {},
|
||||||
@@ -147,16 +148,35 @@ describe('makemkvInstallerHolen', () => {
|
|||||||
holen,
|
holen,
|
||||||
ordner,
|
ordner,
|
||||||
(p, v) => dateiPruefen(p, v, () => ({ firma: 'GuinpinSoft inc', produkt: 'MakeMKV', version: 'v1.18.4' }), 'win32'),
|
(p, v) => dateiPruefen(p, v, () => ({ firma: 'GuinpinSoft inc', produkt: 'MakeMKV', version: 'v1.18.4' }), 'win32'),
|
||||||
|
async (quelle) => {
|
||||||
|
gefragt.push(quelle)
|
||||||
|
return true
|
||||||
|
},
|
||||||
)
|
)
|
||||||
|
expect(gefragt).toEqual(['Internet Archive'])
|
||||||
expect(ergebnis.quelle).toBe('Internet Archive')
|
expect(ergebnis.quelle).toBe('Internet Archive')
|
||||||
expect(readFileSync(ergebnis.pfad).length).toBe(GROSS.length)
|
expect(readFileSync(ergebnis.pfad).length).toBe(GROSS.length)
|
||||||
|
expect(ergebnis.bytes).toBe(GROSS.length)
|
||||||
|
expect(ergebnis.sha256).toMatch(/^[0-9a-f]{64}$/)
|
||||||
expect(existsSync(`${ergebnis.pfad}.neu`)).toBe(false)
|
expect(existsSync(`${ergebnis.pfad}.neu`)).toBe(false)
|
||||||
})
|
})
|
||||||
|
|
||||||
|
// 5.7.0 (Durchsicht F16): Ohne Freigabe wird das Archiv NIE benutzt — es
|
||||||
|
// liefert eine unsignierte EXE, die mit Adminrechten läuft.
|
||||||
|
it('ohne Freigabe bleibt das Archiv aus — und der Bericht sagt es', async () => {
|
||||||
|
const ordner = tempOrdner()
|
||||||
|
const holen = (async (url: string | URL | Request) =>
|
||||||
|
String(url).includes('web.archive.org') ? antwort(GROSS) : antwort('<html>kaputt</html>')) as typeof fetch
|
||||||
|
await expect(makemkvInstallerHolen('1.18.4', () => {}, '', holen, ordner)).rejects.toThrow(/Internet Archive: nicht freigegeben/)
|
||||||
|
await expect(makemkvInstallerHolen('1.18.4', () => {}, '', holen, ordner, undefined, async () => false)).rejects.toThrow(
|
||||||
|
/Internet Archive: nicht freigegeben/,
|
||||||
|
)
|
||||||
|
})
|
||||||
|
|
||||||
it('liefert keine Quelle, steht im Wurf der Bericht ALLER Versuche', async () => {
|
it('liefert keine Quelle, steht im Wurf der Bericht ALLER Versuche', async () => {
|
||||||
const ordner = tempOrdner()
|
const ordner = tempOrdner()
|
||||||
const holen = (async () => antwort('weg', 404)) as typeof fetch
|
const holen = (async () => antwort('weg', 404)) as typeof fetch
|
||||||
await expect(makemkvInstallerHolen('1.18.4', () => {}, '', holen, ordner)).rejects.toThrow(
|
await expect(makemkvInstallerHolen('1.18.4', () => {}, '', holen, ordner, undefined, async () => true)).rejects.toThrow(
|
||||||
/Hersteller: HTTP 404[\s\S]*Internet Archive: HTTP 404[\s\S]*makemkv\.com/,
|
/Hersteller: HTTP 404[\s\S]*Internet Archive: HTTP 404[\s\S]*makemkv\.com/,
|
||||||
)
|
)
|
||||||
})
|
})
|
||||||
@@ -166,6 +186,8 @@ describe('Nachrichten-Schema der Update-Strecke', () => {
|
|||||||
it('Fenster → Kern: makemkv-update und schluessel-pruefen', () => {
|
it('Fenster → Kern: makemkv-update und schluessel-pruefen', () => {
|
||||||
expect(istFensterNachricht({ art: 'makemkv-update' })).toBe(true)
|
expect(istFensterNachricht({ art: 'makemkv-update' })).toBe(true)
|
||||||
expect(istFensterNachricht({ art: 'schluessel-pruefen' })).toBe(true)
|
expect(istFensterNachricht({ art: 'schluessel-pruefen' })).toBe(true)
|
||||||
|
expect(istFensterNachricht({ art: 'beschaffung-antwort', ja: true })).toBe(true)
|
||||||
|
expect(istFensterNachricht({ art: 'beschaffung-antwort' })).toBe(false)
|
||||||
})
|
})
|
||||||
it('Haupt → Kern: installer-ergebnis', () => {
|
it('Haupt → Kern: installer-ergebnis', () => {
|
||||||
expect(istHauptNachricht({ art: 'installer-ergebnis', fehler: null })).toBe(true)
|
expect(istHauptNachricht({ art: 'installer-ergebnis', fehler: null })).toBe(true)
|
||||||
|
|||||||
Reference in New Issue
Block a user