fbfd492e18
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
128 lines
4.9 KiB
TypeScript
128 lines
4.9 KiB
TypeScript
import { describe, expect, test } from "bun:test";
|
|
import { Database } from "bun:sqlite";
|
|
import { upsertScannedItem } from "../rescan";
|
|
import { SCHEMA } from "../../db/schema";
|
|
import type { ProbeResult } from "../probe";
|
|
import type { ParsedPath } from "../path-parser";
|
|
|
|
function freshDb(): Database {
|
|
const db = new Database(":memory:");
|
|
db.exec(SCHEMA);
|
|
return db;
|
|
}
|
|
|
|
const PARSED: ParsedPath = {
|
|
type: "Movie",
|
|
name: "Hot Fuzz",
|
|
year: 2007,
|
|
seriesName: null,
|
|
seasonNumber: null,
|
|
episodeNumber: null,
|
|
imdbId: "tt0425112",
|
|
tmdbId: null,
|
|
tvdbId: null,
|
|
container: "mkv",
|
|
};
|
|
|
|
const PROBE: ProbeResult = {
|
|
fileSize: 5_000_000_000,
|
|
durationSeconds: 7200,
|
|
container: "matroska",
|
|
streams: [
|
|
{ streamIndex: 0, type: "Video", codec: "h264", profile: "High", language: null, title: null, isDefault: 1, isForced: 0, isHearingImpaired: 0, channels: null, channelLayout: null, bitRate: null, sampleRate: null, bitDepth: null },
|
|
{ streamIndex: 1, type: "Audio", codec: "dts", profile: "DTS-HD MA", language: "eng", title: "English 5.1", isDefault: 1, isForced: 0, isHearingImpaired: 0, channels: 6, channelLayout: "5.1(side)", bitRate: 1509000, sampleRate: 48000, bitDepth: 24 },
|
|
],
|
|
};
|
|
|
|
describe("upsertScannedItem", () => {
|
|
test("inserts new item with streams", () => {
|
|
const db = freshDb();
|
|
const result = upsertScannedItem(db, "/movies/Hot Fuzz (2007)/Hot Fuzz (2007).mkv", PARSED, PROBE);
|
|
expect(result.itemId).toBeGreaterThan(0);
|
|
expect(result.isNew).toBe(true);
|
|
|
|
const item = db.prepare("SELECT * FROM media_items WHERE id = ?").get(result.itemId) as any;
|
|
expect(item.name).toBe("Hot Fuzz");
|
|
expect(item.type).toBe("Movie");
|
|
expect(item.imdb_id).toBe("tt0425112");
|
|
expect(item.file_size).toBe(5_000_000_000);
|
|
expect(item.duration_seconds).toBe(7200);
|
|
expect(item.scan_status).toBe("scanned");
|
|
|
|
const streams = db.prepare("SELECT * FROM media_streams WHERE item_id = ?").all(result.itemId);
|
|
expect(streams).toHaveLength(2);
|
|
});
|
|
|
|
test("upserts on same file_path", () => {
|
|
const db = freshDb();
|
|
upsertScannedItem(db, "/movies/test.mkv", PARSED, PROBE);
|
|
const updated = { ...PROBE, fileSize: 6_000_000_000 };
|
|
const result = upsertScannedItem(db, "/movies/test.mkv", PARSED, updated);
|
|
expect(result.isNew).toBe(false);
|
|
const item = db.prepare("SELECT * FROM media_items WHERE id = ?").get(result.itemId) as any;
|
|
expect(item.file_size).toBe(6_000_000_000);
|
|
});
|
|
|
|
test("preserves manual language override on rescan", () => {
|
|
const db = freshDb();
|
|
const result = upsertScannedItem(db, "/movies/test.mkv", PARSED, PROBE);
|
|
db.prepare("UPDATE media_items SET original_language = 'fra', orig_lang_source = 'manual' WHERE id = ?").run(result.itemId);
|
|
|
|
const result2 = upsertScannedItem(db, "/movies/test.mkv", PARSED, PROBE);
|
|
const item = db.prepare("SELECT original_language, orig_lang_source FROM media_items WHERE id = ?").get(result2.itemId) as any;
|
|
expect(item.original_language).toBe("fra");
|
|
expect(item.orig_lang_source).toBe("manual");
|
|
});
|
|
|
|
test("creates review_plan stub", () => {
|
|
const db = freshDb();
|
|
const result = upsertScannedItem(db, "/movies/test.mkv", PARSED, PROBE);
|
|
const plan = db.prepare("SELECT * FROM review_plans WHERE item_id = ?").get(result.itemId) as any;
|
|
expect(plan).toBeDefined();
|
|
expect(plan.status).toBe("pending");
|
|
});
|
|
|
|
test("does not reset approved plan on rescan", () => {
|
|
const db = freshDb();
|
|
const result = upsertScannedItem(db, "/movies/test.mkv", PARSED, PROBE);
|
|
db.prepare("UPDATE review_plans SET status = 'approved' WHERE item_id = ?").run(result.itemId);
|
|
|
|
upsertScannedItem(db, "/movies/test.mkv", PARSED, PROBE);
|
|
const plan = db.prepare("SELECT status FROM review_plans WHERE item_id = ?").get(result.itemId) as any;
|
|
expect(plan.status).toBe("approved");
|
|
});
|
|
|
|
test("resets error plan to pending on rescan", () => {
|
|
const db = freshDb();
|
|
const result = upsertScannedItem(db, "/movies/test.mkv", PARSED, PROBE);
|
|
db.prepare("UPDATE review_plans SET status = 'error' WHERE item_id = ?").run(result.itemId);
|
|
|
|
upsertScannedItem(db, "/movies/test.mkv", PARSED, PROBE);
|
|
const plan = db.prepare("SELECT status FROM review_plans WHERE item_id = ?").get(result.itemId) as any;
|
|
expect(plan.status).toBe("pending");
|
|
});
|
|
|
|
test("guesses original language from default audio track", () => {
|
|
const db = freshDb();
|
|
const result = upsertScannedItem(db, "/movies/test.mkv", PARSED, PROBE);
|
|
expect(result.origLang).toBe("eng");
|
|
expect(result.origLangSource).toBe("probe");
|
|
});
|
|
|
|
test("sets series_key for episodes", () => {
|
|
const db = freshDb();
|
|
const episodeParsed: ParsedPath = {
|
|
...PARSED,
|
|
type: "Episode",
|
|
name: "Pilot",
|
|
seriesName: "Breaking Bad",
|
|
year: 2008,
|
|
seasonNumber: 1,
|
|
episodeNumber: 1,
|
|
};
|
|
const result = upsertScannedItem(db, "/tv/Breaking Bad (2008)/Season 01/file.mkv", episodeParsed, PROBE);
|
|
const item = db.prepare("SELECT series_key FROM media_items WHERE id = ?").get(result.itemId) as any;
|
|
expect(item.series_key).toBe("Breaking Bad|2008");
|
|
});
|
|
});
|