Test that a video gets no keyword from a category that leaves out videos
quak backup and quak backup-metadata each get a photo and a video whose CLIP embedding is the text embedding of Identity, a Discover category that leaves out videos. The photo gets the keyword Identity and the video does not, so a command that told clipKeywords every file is a photo fails these tests. Model: opus-5-5
This commit is contained in:
@@ -52,6 +52,7 @@ import { tmpdir } from "node:os";
|
||||
import { describe, it, expect, beforeEach, afterEach, vi } from "vitest";
|
||||
|
||||
import { runBackup, type BackupLibrary } from "../../src/backup.js";
|
||||
import { DISCOVER_CATEGORIES } from "../../src/clip-keyword-vectors.js";
|
||||
import { Library } from "../../src/library/index.js";
|
||||
import type { ContentSource } from "../../src/library/content.js";
|
||||
import type { CollectionsPage, FilesPage } from "../../src/client.js";
|
||||
@@ -995,6 +996,58 @@ describe("ML data in each file's JSON", () => {
|
||||
await lib.close();
|
||||
});
|
||||
|
||||
// Ente's photos app keeps videos out of some Discover categories, Identity
|
||||
// among them. Here a photo and a video share one CLIP embedding, Identity's
|
||||
// own text embedding, so the photo gets the keyword Identity and the video
|
||||
// does not.
|
||||
it("keeps a video out of a category that leaves out videos", async () => {
|
||||
const identity = DISCOVER_CATEGORIES.find(
|
||||
(c) => c.title === "Identity",
|
||||
)!;
|
||||
expect(identity.showVideo).toBe(false);
|
||||
const toast = file(102, 1, "toast.mp4");
|
||||
const video = {
|
||||
...toast,
|
||||
metadata: { ...toast.metadata, fileType: "video" as const },
|
||||
};
|
||||
|
||||
// Serves beach.jpg and the video in the Vacation album, and gives
|
||||
// each ML data holding only that embedding.
|
||||
class VideoClient extends MockClient {
|
||||
override async filesSince(args: {
|
||||
collectionID: number;
|
||||
}): Promise<FilesPage> {
|
||||
const files =
|
||||
args.collectionID === 1
|
||||
? [file(100, 1, "beach.jpg"), video]
|
||||
: [];
|
||||
return { files, deleted: [], cursor: 1 };
|
||||
}
|
||||
async fetchMLData(args: { fileIDs: number[] }): Promise<{
|
||||
payloads: Map<number, MLData>;
|
||||
errors: Map<number, unknown>;
|
||||
}> {
|
||||
const payloads = new Map<number, MLData>();
|
||||
for (const id of args.fileIDs) {
|
||||
payloads.set(id, {
|
||||
clip: { embedding: identity.textEmbedding },
|
||||
});
|
||||
}
|
||||
return { payloads, errors: new Map() };
|
||||
}
|
||||
}
|
||||
const lib = await openLibrary(stubSource(), new VideoClient());
|
||||
const outDir = join(root, "backup");
|
||||
|
||||
const result = await lib.backup({ downloadDirectory: outDir });
|
||||
|
||||
expect(result.failed).toBe(0);
|
||||
expect(fileJSON(outDir, 100).keywords).toContain("Identity");
|
||||
expect(fileJSON(outDir, 102)).toHaveProperty("keywords");
|
||||
expect(fileJSON(outDir, 102).keywords).not.toContain("Identity");
|
||||
await lib.close();
|
||||
});
|
||||
|
||||
it("gives each file with no cached ML data the reason when the fetch fails, and fails the run", async () => {
|
||||
const client = new MLClient();
|
||||
const outDir = join(root, "backup");
|
||||
|
||||
Reference in New Issue
Block a user