Merge #18: Unbekannte Jellyfin-Titel zur Auswahl stellen und nachladen
CI / pruefen (push) Canceled after 0s
CI / pruefen (push) Canceled after 0s
Closes #16
This commit was merged in pull request #18.
This commit is contained in:
Vendored
+11
@@ -77,6 +77,17 @@ export const items = {
|
||||
ProviderIds: { Tmdb: "424242" },
|
||||
UserData: { Played: false, PlayCount: 0, LastPlayedDate: null },
|
||||
},
|
||||
/**
|
||||
* Zweite Datei zu demselben fremden Film — so führt Jellyfin Extended
|
||||
* Editions. In der Auswahlliste muss der Titel trotzdem einmal stehen.
|
||||
*/
|
||||
fremdZweiteFassung: {
|
||||
Id: "jf-movie-5",
|
||||
Name: "Ein fremder Film (Extended)",
|
||||
Type: "Movie",
|
||||
ProviderIds: { Tmdb: "424242" },
|
||||
UserData: { Played: false, PlayCount: 0, LastPlayedDate: null },
|
||||
},
|
||||
} as const;
|
||||
|
||||
export const seriesItem = {
|
||||
|
||||
+153
-1
@@ -12,6 +12,7 @@ import { decryptSecret, encryptSecret } from "../src/lib/secrets";
|
||||
import {
|
||||
connectJellyfin,
|
||||
deleteConnection,
|
||||
importUnassigned,
|
||||
syncConnection,
|
||||
testConnection,
|
||||
} from "../src/lib/mediaserver";
|
||||
@@ -140,7 +141,7 @@ test("Bestand wird zugeordnet, Unzuordenbares landet im Bericht", async () => {
|
||||
|
||||
const bericht = await syncConnection(userId, verbindung.id);
|
||||
|
||||
assert.equal(bericht.gelesen, 6, "alle Items wurden gelesen");
|
||||
assert.equal(bericht.gelesen, 7, "alle Items wurden gelesen");
|
||||
assert.equal(bericht.aufgenommen, 0, "ohne ausdrückliche Erlaubnis wird nichts aufgenommen");
|
||||
assert.equal(bericht.bestandGesetzt, 1, "nur der vorhandene Eintrag bekommt „hab ich“");
|
||||
|
||||
@@ -160,6 +161,12 @@ test("Bestand wird zugeordnet, Unzuordenbares landet im Bericht", async () => {
|
||||
gruende.some((grund) => grund.includes("nicht im Katalog")),
|
||||
"der fremde Film steht im Bericht",
|
||||
);
|
||||
// Die zwei Dateien zum fremden Film stehen als ein Eintrag da.
|
||||
assert.equal(
|
||||
bericht.nichtZugeordnet.length,
|
||||
2,
|
||||
"zusammengefasst: ein fremder Film und ein Video ohne Kennung",
|
||||
);
|
||||
} finally {
|
||||
jf.restore();
|
||||
}
|
||||
@@ -315,3 +322,148 @@ test("fremde Verbindungen sind unerreichbar", async () => {
|
||||
jf.restore();
|
||||
}
|
||||
});
|
||||
|
||||
// --- Nachladen unbekannter Titel (#16) ---------------------------------------
|
||||
|
||||
test("der Bericht fasst Dubletten zusammen und nennt Typ und Kennung", async () => {
|
||||
const jf = installJellyfinStub();
|
||||
try {
|
||||
const verbindung = await verbinden();
|
||||
const bericht = await syncConnection(userId, verbindung.id);
|
||||
|
||||
// Zwei Jellyfin-Dateien zeigen auf denselben fremden Film.
|
||||
const fremd = bericht.nichtZugeordnet.filter((eintrag) => eintrag.tmdbId === 424242);
|
||||
assert.equal(fremd.length, 1, "derselbe Titel steht nur einmal in der Liste");
|
||||
assert.equal(fremd[0]!.dateien, 2, "beide Dateien werden gezaehlt");
|
||||
assert.equal(fremd[0]!.typ, "MOVIE");
|
||||
|
||||
// Das Urlaubsvideo hat keine Kennung — es steht drin, aber ohne Typ.
|
||||
const ohneKennung = bericht.nichtZugeordnet.filter((eintrag) => eintrag.tmdbId === null);
|
||||
assert.equal(ohneKennung.length, 1);
|
||||
assert.equal(ohneKennung[0]!.typ, null, "ohne Kennung laesst sich nichts holen");
|
||||
|
||||
assert.equal(bericht.weitereNichtZugeordnet, 0, "nichts abgeschnitten");
|
||||
} finally {
|
||||
jf.restore();
|
||||
}
|
||||
});
|
||||
|
||||
test("ausgewaehlte Titel werden aus TMDB nachgeladen", async () => {
|
||||
const jf = installJellyfinStub();
|
||||
try {
|
||||
const verbindung = await verbinden();
|
||||
await syncConnection(userId, verbindung.id);
|
||||
|
||||
// MOVIE_2_ID kennt der TMDB-Stub, steht aber in diesem Lauf nicht in der
|
||||
// Bibliothek — genau der Fall, den #16 loest.
|
||||
await prisma.title.deleteMany({ where: { tmdbId: MOVIE_2_ID } });
|
||||
|
||||
const ergebnis = await importUnassigned(userId, verbindung.id, [
|
||||
{ tmdbId: MOVIE_2_ID, typ: "MOVIE" },
|
||||
]);
|
||||
|
||||
assert.equal(ergebnis.nachgeladen, 1);
|
||||
assert.deepEqual(ergebnis.fehler, []);
|
||||
assert.equal(ergebnis.uebrig, 0);
|
||||
|
||||
const titel = await prisma.title.findFirst({ where: { tmdbId: MOVIE_2_ID } });
|
||||
assert.ok(titel, "der Titel steht jetzt im Katalog");
|
||||
|
||||
const eintrag = await prisma.libraryEntry.findFirstOrThrow({
|
||||
where: { userId, titleId: titel.id },
|
||||
select: { status: true, owned: true, ownedSource: true },
|
||||
});
|
||||
assert.equal(eintrag.status, "WATCHLIST");
|
||||
assert.equal(eintrag.owned, true, "was auf dem Server liegt, ist vorhanden");
|
||||
assert.equal(eintrag.ownedSource, "Jellyfin");
|
||||
} finally {
|
||||
jf.restore();
|
||||
}
|
||||
});
|
||||
|
||||
test("ein einzelner Fehlschlag bricht den Import nicht ab", async () => {
|
||||
const jf = installJellyfinStub();
|
||||
try {
|
||||
const verbindung = await verbinden();
|
||||
await prisma.title.deleteMany({ where: { tmdbId: MOVIE_2_ID } });
|
||||
|
||||
const ergebnis = await importUnassigned(userId, verbindung.id, [
|
||||
// Diese Kennung kennt der Stub nicht — sie muss scheitern.
|
||||
{ tmdbId: 424242, typ: "MOVIE" },
|
||||
{ tmdbId: MOVIE_2_ID, typ: "MOVIE" },
|
||||
]);
|
||||
|
||||
assert.equal(ergebnis.nachgeladen, 1, "der zweite Titel kommt trotzdem an");
|
||||
assert.equal(ergebnis.fehler.length, 1);
|
||||
assert.ok(ergebnis.fehler[0]!.includes("424242"));
|
||||
} finally {
|
||||
jf.restore();
|
||||
}
|
||||
});
|
||||
|
||||
test("nachgeladene Titel verschwinden aus der Auswahlliste", async () => {
|
||||
const jf = installJellyfinStub();
|
||||
try {
|
||||
const verbindung = await verbinden();
|
||||
await syncConnection(userId, verbindung.id);
|
||||
await prisma.title.deleteMany({ where: { tmdbId: MOVIE_2_ID } });
|
||||
|
||||
const vorher = await gespeicherterBericht(verbindung.id);
|
||||
assert.ok(vorher.nichtZugeordnet.some((eintrag) => eintrag.tmdbId === 424242));
|
||||
|
||||
await importUnassigned(userId, verbindung.id, [{ tmdbId: MOVIE_2_ID, typ: "MOVIE" }]);
|
||||
// Der fremde Film wurde nicht ausgewaehlt und bleibt stehen …
|
||||
const nachher = await gespeicherterBericht(verbindung.id);
|
||||
assert.ok(nachher.nichtZugeordnet.some((eintrag) => eintrag.tmdbId === 424242));
|
||||
|
||||
// Ein Fehlschlag laesst den Eintrag dagegen stehen: TMDB kennt 424242
|
||||
// nicht, und wer es spaeter erneut versuchen will, soll ihn noch finden.
|
||||
const misslungen = await importUnassigned(userId, verbindung.id, [
|
||||
{ tmdbId: 424242, typ: "MOVIE" },
|
||||
]);
|
||||
assert.equal(misslungen.nachgeladen, 0);
|
||||
assert.equal(misslungen.fehler.length, 1);
|
||||
|
||||
const zuletzt = await gespeicherterBericht(verbindung.id);
|
||||
assert.ok(
|
||||
zuletzt.nichtZugeordnet.some((eintrag) => eintrag.tmdbId === 424242),
|
||||
"was nicht geholt werden konnte, bleibt in der Liste",
|
||||
);
|
||||
} finally {
|
||||
jf.restore();
|
||||
}
|
||||
});
|
||||
|
||||
test("fremde Verbindungen lassen sich nicht befuellen", async () => {
|
||||
const jf = installJellyfinStub();
|
||||
try {
|
||||
const verbindung = await verbinden();
|
||||
const fremderId = (
|
||||
await prisma.user.create({
|
||||
data: { email: "test-mediaserver-import@flimmer.invalid", name: "Fremd" },
|
||||
select: { id: true },
|
||||
})
|
||||
).id;
|
||||
|
||||
try {
|
||||
await assert.rejects(
|
||||
() => importUnassigned(fremderId, verbindung.id, [{ tmdbId: MOVIE_2_ID, typ: "MOVIE" }]),
|
||||
/gibt es nicht/,
|
||||
);
|
||||
} finally {
|
||||
await prisma.user.delete({ where: { id: fremderId } });
|
||||
}
|
||||
} finally {
|
||||
jf.restore();
|
||||
}
|
||||
});
|
||||
|
||||
async function gespeicherterBericht(connectionId: string) {
|
||||
const verbindung = await prisma.mediaServerConnection.findUniqueOrThrow({
|
||||
where: { id: connectionId },
|
||||
select: { lastSyncReport: true },
|
||||
});
|
||||
return verbindung.lastSyncReport as unknown as {
|
||||
nichtZugeordnet: { tmdbId: number | null }[];
|
||||
};
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user