Files
netfelix-audio-fix/server/api/__tests__/execute-clear.test.ts
T
felixfoertsch 686434f5c3 remove jellyfin, mqtt, webhook services, fix tests, add schema migrations
- delete server/services/jellyfin.ts, webhook.ts, mqtt.ts and their tests
- strip jellyfin/mqtt imports and startup calls from index.tsx and settings.ts
- remove /jellyfin, /mqtt, /mqtt/status, /mqtt/test, /jellyfin/webhook-plugin endpoints from settings router
- clean ENV_MAP and isEnvConfigured of jellyfin/mqtt keys
- add db/index.ts migrations for series_key, duration_seconds, scan_status, scan_error, last_scanned_at (new columns absent on older dev DBs)
- move idx_media_items_series_key out of SCHEMA into migrate() so it runs after the column is added
- fix all test fixtures: drop jellyfin_id/series_jellyfin_id column refs, update MediaItem/MediaStream object literals to match current types

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-04-21 06:31:54 +02:00

85 lines
2.7 KiB
TypeScript

import { Database } from "bun:sqlite";
import { describe, expect, test } from "bun:test";
import { SCHEMA } from "../../db/schema";
import { clearQueue } from "../execute";
function makeDb(): Database {
const db = new Database(":memory:");
for (const stmt of SCHEMA.split(";")) {
const trimmed = stmt.trim();
if (trimmed) db.run(trimmed);
}
return db;
}
function seedQueuedItem(db: Database, id: number, autoClass: "auto" | "auto_heuristic" | "manual") {
db
.prepare(
"INSERT INTO media_items (id, type, name, file_path, container) VALUES (?, 'Movie', ?, ?, 'mkv')",
)
.run(id, `Item ${id}`, `/x/${id}.mkv`);
db
.prepare(
"INSERT INTO review_plans (item_id, status, is_noop, auto_class, sorted, apple_compat, job_type) VALUES (?, 'approved', 0, ?, 1, 'direct_play', 'copy')",
)
.run(id, autoClass);
db.prepare("INSERT INTO jobs (item_id, command, job_type, status) VALUES (?, 'ffmpeg …', 'audio', 'pending')").run(id);
}
describe("clearQueue", () => {
test("deletes pending jobs and returns plans to the Inbox (sorted=0, pending)", () => {
const db = makeDb();
seedQueuedItem(db, 1, "auto");
seedQueuedItem(db, 2, "auto");
const cleared = clearQueue(db);
expect(cleared).toBe(2);
const plans = db.prepare("SELECT item_id, status, sorted FROM review_plans ORDER BY item_id").all() as {
item_id: number;
status: string;
sorted: number;
}[];
expect(plans).toEqual([
{ item_id: 1, status: "pending", sorted: 0 },
{ item_id: 2, status: "pending", sorted: 0 },
]);
const jobCount = (db.prepare("SELECT COUNT(*) as n FROM jobs WHERE status = 'pending'").get() as { n: number }).n;
expect(jobCount).toBe(0);
});
test("leaves running + completed jobs alone", () => {
const db = makeDb();
seedQueuedItem(db, 1, "auto");
db.prepare("UPDATE jobs SET status = 'running' WHERE item_id = 1").run();
seedQueuedItem(db, 2, "auto");
db.prepare("UPDATE jobs SET status = 'done' WHERE item_id = 2").run();
seedQueuedItem(db, 3, "auto"); // stays pending
const cleared = clearQueue(db);
expect(cleared).toBe(1);
const surviving = db.prepare("SELECT item_id, status FROM jobs ORDER BY item_id").all() as {
item_id: number;
status: string;
}[];
expect(surviving).toEqual([
{ item_id: 1, status: "running" },
{ item_id: 2, status: "done" },
]);
// Only the plan whose job was pending should be reset.
const plan3 = db.prepare("SELECT status, sorted FROM review_plans WHERE item_id = 3").get() as {
status: string;
sorted: number;
};
expect(plan3).toEqual({ status: "pending", sorted: 0 });
const plan1 = db.prepare("SELECT status, sorted FROM review_plans WHERE item_id = 1").get() as {
status: string;
sorted: number;
};
expect(plan1).toEqual({ status: "approved", sorted: 1 });
});
});