Files
UHD_Media_Tool/packages/domain/test/release-facets.test.ts
T
rootandClaude Opus 5.5 970296218c feat(search): multi-select quick filters for search results and site releases (SEARCH-3)
- domain release-facets: bucket resolution / codec / release type / site / promotion / HDR /
  release group / season / episode; OR within a dimension, AND across; disjunctive counts
- GET /search/releases and GET /sites/{id}/releases accept qf and return facets; site list
  facets come from local source_release rows only (no site requests), paging stays consistent
- web QuickFilterBar shared by search results and site resources tab: per-dimension popover
  (bottom sheet on phones) with counts, removable tags, clear all, localStorage memory per page
- runbook: quick filter params and bucket definitions

Co-Authored-By: Claude Opus 5.5 <[email protected]>
2026-09-29 20:52:29 +08:00

177 lines
6.7 KiB
TypeScript

import { describe, expect, it } from "vitest";
import {
applyFacets,
type FacetInput,
formatFacetParam,
parseFacetParam,
promotionBuckets,
releaseTypeBucket,
} from "../src/index.ts";
// SEARCH-3 快速筛选:档位、计数(按其它维度已选条件)、同维度 OR / 跨维度 AND、qf 编解码
const NOW = Date.parse("2026-09-29T00:00:00Z");
const none = { type: "none", downloadFactor: 1, uploadFactor: 1, expiresAt: null };
const mk = (id: string, o: Partial<FacetInput> = {}): FacetInput & { id: string } => ({
id,
siteId: "a",
siteName: "站 A",
resolution: "1080p",
source: "WEB-DL",
videoCodec: "H.264",
hdr: [],
releaseGroup: null,
season: null,
episodes: null,
promotion: none,
...o,
});
const items = [
mk("1", {
resolution: "2160p",
source: "REMUX",
videoCodec: "H.265",
hdr: ["DV", "HDR10"],
releaseGroup: "FraMeSToR",
}),
mk("2", {
resolution: "2160p",
source: "WEB-DL",
videoCodec: "H.265",
hdr: ["HDR10"],
releaseGroup: "FLUX",
siteId: "b",
siteName: "站 B",
}),
mk("3", {
resolution: "1080p",
source: "BluRay",
videoCodec: "H.264",
releaseGroup: "flux",
promotion: { type: "free", downloadFactor: 0, uploadFactor: 1, expiresAt: null },
}),
mk("4", {
resolution: "720p",
source: "HDTV",
videoCodec: null,
promotion: { type: "2xfree", downloadFactor: 0, uploadFactor: 2, expiresAt: null },
}),
mk("5", { resolution: null, source: "BluRay-Disc", videoCodec: "AV1", siteId: "b", siteName: "站 B" }),
];
const run = (sel: Parameters<typeof applyFacets>[2]) => applyFacets(items, (x) => x, sel, { now: NOW });
const ids = (r: { items: { id: string }[] }) => r.items.map((i) => i.id);
const counts = (opts: { value: string; count: number }[]) => Object.fromEntries(opts.map((o) => [o.value, o.count]));
describe("release-facets", () => {
it("未筛选:各维度计数等于全部结果里的档位分布", () => {
const r = run({});
expect(ids(r)).toEqual(["1", "2", "3", "4", "5"]);
expect(counts(r.facets.resolution)).toEqual({ "2160p": 2, "1080p": 1, "720p": 1, other: 1 });
expect(counts(r.facets.videoCodec)).toEqual({ "H.265": 2, "H.264": 1, AV1: 1, other: 1 });
expect(counts(r.facets.releaseType)).toEqual({ disc: 1, remux: 1, encode: 1, webdl: 1, hdtv: 1 });
expect(r.facets.releaseType.map((o) => o.label)).toEqual(["原盘", "Remux", "蓝光压制", "WEB-DL", "HDTV"]);
expect(counts(r.facets.hdr)).toEqual({ DV: 1, HDR10: 2, "HDR10+": 0, SDR: 3 });
expect(counts(r.facets.promotion)).toEqual({ free: 2, "2x": 1, "50%": 0, none: 3 });
expect(r.facets.site).toEqual([
{ value: "a", label: "站 A", count: 3 },
{ value: "b", label: "站 B", count: 2 },
]);
// 制作组不分大小写合并
expect(r.facets.releaseGroup).toEqual([
{ value: "FLUX", label: "FLUX", count: 2 },
{ value: "FraMeSToR", label: "FraMeSToR", count: 1 },
]);
expect(r.facets.season).toEqual([]);
});
it("同维度 OR、不同维度 AND;计数按其它维度的已选条件", () => {
const r = run({ resolution: ["2160p", "1080p"], videoCodec: ["H.265"] });
expect(ids(r)).toEqual(["1", "2"]);
// 分辨率的计数只受编码条件影响:1080p 在 H.265 下没有结果 → 0
expect(counts(r.facets.resolution)).toEqual({ "2160p": 2, "1080p": 0, "720p": 0, other: 0 });
// 编码计数只受分辨率条件影响
expect(counts(r.facets.videoCodec)).toEqual({ "H.265": 2, "H.264": 1, AV1: 0, other: 0 });
// 其它维度按全部条件
expect(counts(r.facets.releaseType)).toMatchObject({ remux: 1, webdl: 1, encode: 0 });
expect(ids(run({ site: ["b"], releaseType: ["disc", "webdl"] }))).toEqual(["2", "5"]);
expect(ids(run({ releaseGroup: ["flux"] }))).toEqual(["2", "3"]);
expect(ids(run({ hdr: ["SDR"] }))).toEqual(["3", "4", "5"]);
expect(ids(run({ promotion: ["2x"] }))).toEqual(["4"]);
});
it("已选但没有结果的值仍列出(计数 0)", () => {
const r = run({ releaseGroup: ["NoSuch"], site: ["zzz"] });
expect(r.items).toEqual([]);
expect(r.facets.releaseGroup.find((o) => o.value === "NoSuch")).toEqual({
value: "NoSuch",
label: "NoSuch",
count: 0,
});
expect(r.facets.site.find((o) => o.value === "zzz")?.count).toBe(0);
});
it("制作组只列前 20(已选的补在后面)", () => {
const many = Array.from({ length: 25 }, (_, i) => mk(String(i), { releaseGroup: `G${i}` }));
const r = applyFacets(many, (x) => x, { releaseGroup: ["g9"] }, { now: NOW });
expect(r.facets.releaseGroup.length).toBe(21);
expect(r.facets.releaseGroup.at(-1)?.value).toBe("G9");
});
it("季 / 集:多季合集展开,整季资源记为整季", () => {
const tv = [
mk("s1", { season: 1, episodes: null }),
mk("s1e2", { season: 1, episodes: { start: 2, end: 3 } }),
mk("s13", { season: 1, seasonEnd: 3, episodes: null }),
mk("movie"),
];
const r = applyFacets(tv, (x) => x, { season: ["2"] }, { now: NOW });
expect(ids(r)).toEqual(["s13"]);
expect(r.facets.season).toEqual([
{ value: "1", label: "S01", count: 3 },
{ value: "2", label: "S02", count: 1 },
{ value: "3", label: "S03", count: 1 },
]);
expect(r.facets.episode).toEqual([
{ value: "pack", label: "整季", count: 1 },
{ value: "2", label: "E02", count: 0 },
{ value: "3", label: "E03", count: 0 },
]);
expect(ids(applyFacets(tv, (x) => x, { season: ["1"], episode: ["3"] }, { now: NOW }))).toEqual(["s1e2"]);
});
it("促销与版本类型档位", () => {
expect(promotionBuckets({ type: "2x50%", downloadFactor: 0.5, uploadFactor: 2, expiresAt: null }, NOW)).toEqual([
"2x",
"50%",
]);
expect(promotionBuckets({ type: "30%", downloadFactor: 0.3, uploadFactor: 1, expiresAt: null }, NOW)).toEqual([
"other",
]);
expect(
promotionBuckets({ type: "unknown", downloadFactor: null, uploadFactor: null, expiresAt: null }, NOW),
).toEqual(["none"]);
// 促销已过期 → 无
expect(
promotionBuckets({ type: "free", downloadFactor: 0, uploadFactor: 1, expiresAt: "2026-09-28T00:00:00Z" }, NOW),
).toEqual(["none"]);
expect(["BluRay-Disc", "REMUX", "BluRay", "WEB-DL", "HDTV", "WEBRip", null].map(releaseTypeBucket)).toEqual([
"disc",
"remux",
"encode",
"webdl",
"hdtv",
"other",
"other",
]);
});
it("qf 参数编解码", () => {
const sel = { resolution: ["2160p", "1080p"], promotion: ["50%"], releaseGroup: ["A;B,C:D"] };
const s = formatFacetParam(sel);
expect(s).toBe("resolution:2160p,1080p;promotion:50%25;releaseGroup:A%3BB%2CC%3AD");
expect(parseFacetParam(s)).toEqual(sel);
expect(parseFacetParam("bogus:1;hdr:;hdr:DV,DV")).toEqual({ hdr: ["DV"] });
});
});