Files
rippy/rippy-windows/test/filme.test.ts
HitonabiandClaude Fable 5.1 f5dab5d1c1 feat(v5): 5.6.0 — Vorgangs-Leiste, mehrere Filme je Disc, Filmnamen für Ordner und Dateien, Untertitel-Vorwahl je Extra, Restzeit, Hell-Modus
Die sechs Punkte des Commanders vom 02.09.2026 abends und seine Entscheide:

* Restzeit der Kompression aus HandBrakes eigener ETA-Klammer (Formatstring
  aus dem Binary 1.11.2 gelesen), KompressionStand.restS.
* Kachel zeigt nach dem Rip nur noch eine Zeile — Balken, Prozent, Ziel in
  der Kompressions-Karte und im Verlauf ("nur in der Kompressions-Karte").
* Kopfzeile bleibt beim Scrollen stehen (sticky), Sektionswahl darunter.
* Untertitel-Vorwahl je Extra ("NUR für Extras, IMMER OPTIONAL"): welche
  Untertitel-Spur beim Abspielen an ist — weiche Spur, nie eingebrannt;
  RipAuftragTitel/RohDatei.untertitelVorwahl, sprachwahl.
* Mehrere Filme je Disc: "anderer Film …" je Titel mit TMDb-Suche;
  filme.ts filmGruppen trennt am Rip-Ende in eigene Roh-Ordner, Vorgänge
  und Kompressions-Aufträge mit voller Zuordnung (erkennung.zuordnungAus).
* Roh-Ordner und Dateien tragen den Filmnamen (filme.ts rohOrdnerName,
  ablage/dateinamen.ts: Akira (1988).mkv, - Fassung n, - Extra nn).
* Hell-Modus: Einstellung design (dunkel/hell/system), data-design auf
  <html>, Token --color-tinte statt white/-Alpha-Klassen.
* Vorgangs-Leiste (Commander: "Phase 1–4 plus Komprimierung — zu einem
  machen"): gemeinsam/vorgangsleiste.ts + uebersicht/VorgangsLeiste.tsx,
  vier Stationen (Rettung als Zwischenstation), Segment-Balken in der
  aktiven Station; Kachel, Kompressions-Karte, Verlauf. PHASE-x/4-Texte weg.
* Automatik-Kasten leert sich, sobald ein Rip startet.

Beweise: 446 Tests (neu: filme, dateinamen, vorgangsleiste; erweitert:
auftrag, handbrake, automatik, ablegen), drei Typprüfungen, Klick-Beweis
33 Schritte inkl. Vorwahl, anderer Film, Vorgangs-Leiste, Restzeit,
Hell-Modus (Bilder beweise/klick/01…11).

Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com>
2026-09-03 19:17:37 +02:00

74 lines
3.8 KiB
TypeScript

// Tests zu mehreren Filmen je Disc und Ordnern mit Filmnamen
// (kern/ablauf/filme.ts, 5.6.0).
import { describe, expect, it } from 'vitest'
import type { MetaVorschlag } from '../src/gemeinsam/nachrichten'
import type { RohDatei } from '../src/kern/ablauf/auftrag'
import { filmGruppen, rohOrdnerName, zuordnungAusVorschlag } from '../src/kern/ablauf/filme'
import { LEERER_TREFFER, type Zuordnung } from '../src/kern/metadaten/zuordnung'
function zuordnung(titel: string, jahr: number | null, typ: 'movie' | 'tv' = 'movie', id = 1): Zuordnung {
return { titel, jahr, confidence: 0.95, meta: { ...LEERER_TREFFER, typ, id, titel, jahr, quelle: 'tmdb' } }
}
function datei(pfad: string, film?: MetaVorschlag): RohDatei {
return { pfad, titelNr: 0, rolle: 'hauptfilm', dauerS: 6000, groesseBytes: 1e9, audioSprachen: [], untertitelSprachen: [], ...(film !== undefined ? { film } : {}) }
}
const akira: MetaVorschlag = { typ: 'movie', tmdbId: 149, titel: 'Akira', jahr: 1988, posterPfad: '/a.jpg' }
const ghost: MetaVorschlag = { typ: 'movie', tmdbId: 9323, titel: 'Ghost in the Shell', jahr: 1995, posterPfad: '' }
describe('rohOrdnerName', () => {
it('Film: „Titel (Jahr)"', () => {
expect(rohOrdnerName(zuordnung('Akira', 1988), null, 'bluray-2026', () => false)).toBe('Akira (1988)')
})
it('Serie: Titel, Staffel und Disc', () => {
expect(rohOrdnerName(zuordnung('Spartacus', 2010, 'tv'), { staffel: 1, discNr: 2 }, 'bluray-2026', () => false)).toBe('Spartacus - Staffel 1 Disc 2')
expect(rohOrdnerName(zuordnung('Spartacus', 2010, 'tv'), { staffel: null, discNr: null }, 'bluray-2026', () => false)).toBe('Spartacus')
})
it('bei Wiederholung mit Zusatz (2), (3) …', () => {
const da = new Set(['Akira (1988)', 'Akira (1988) (2)'])
expect(rohOrdnerName(zuordnung('Akira', 1988), null, 'bluray-2026', (n) => da.has(n))).toBe('Akira (1988) (3)')
})
it('ohne Zuordnung oder ohne brauchbaren Namen bleibt der Vorgangsname', () => {
expect(rohOrdnerName(null, null, 'bluray-2026', () => false)).toBe('bluray-2026')
expect(rohOrdnerName(zuordnung(' ', null), null, 'bluray-2026', () => false)).toBe('bluray-2026')
expect(rohOrdnerName(zuordnung('???', null), null, 'bluray-2026', () => false)).toBe('bluray-2026')
})
it('Sonderzeichen werden entschärft', () => {
expect(rohOrdnerName(zuordnung('Alien: Covenant', 2017), null, 'x', () => false)).not.toContain(':')
})
})
describe('filmGruppen', () => {
it('ohne Film-Zuordnung je Titel bleibt alles beim Hauptvorgang', () => {
const g = filmGruppen([datei('a'), datei('b')], 149)
expect(g.primaer).toHaveLength(2)
expect(g.primaerFilm).toBeNull()
expect(g.weitere).toHaveLength(0)
})
it('ein Titel, der zur Disc-Zuordnung passt, zählt als Hauptvorgang; ein anderer Film wird eigene Gruppe', () => {
const g = filmGruppen([datei('a', akira), datei('b', ghost), datei('c', ghost)], 149)
expect(g.primaer.map((d) => d.pfad)).toEqual(['a'])
expect(g.weitere).toHaveLength(1)
expect(g.weitere[0].film.titel).toBe('Ghost in the Shell')
expect(g.weitere[0].dateien.map((d) => d.pfad)).toEqual(['b', 'c'])
})
it('hat kein Titel die Disc-Zuordnung behalten, wird die erste Gruppe zum Hauptvorgang', () => {
const g = filmGruppen([datei('a', ghost), datei('b', akira)], 42)
expect(g.primaerFilm?.titel).toBe('Ghost in the Shell')
expect(g.primaer.map((d) => d.pfad)).toEqual(['a'])
expect(g.weitere.map((w) => w.film.titel)).toEqual(['Akira'])
})
})
describe('zuordnungAusVorschlag', () => {
it('ist sicher (vom Nutzer) und trägt Titel, Jahr, Poster', () => {
const z = zuordnungAusVorschlag(akira)
expect(z.confidence).toBe(1)
expect(z.titel).toBe('Akira')
expect(z.meta.id).toBe(149)
expect(z.meta.posterPfad).toBe('/a.jpg')
expect(z.meta.typ).toBe('movie')
})
})