All checks were successful
Build and Publish Docker Image / build-and-push (push) Successful in 50s
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
92 lines
2.7 KiB
TypeScript
92 lines
2.7 KiB
TypeScript
import "../../setup.ts";
|
|
import { assertEquals } from "@std/assert";
|
|
import { DatabaseSync } from "node:sqlite";
|
|
import { up as up0011 } from "../../../db/migrations/0011_split_favicon_thumbnail.ts";
|
|
import { up as up0012 } from "../../../db/migrations/0012_fix_favicon_reclassification.ts";
|
|
|
|
const SCHEMA = Deno.readTextFileSync(
|
|
new URL("../../../db/schema.sql", import.meta.url),
|
|
);
|
|
|
|
function freshDb(): DatabaseSync {
|
|
const db = new DatabaseSync(":memory:");
|
|
db.exec(SCHEMA);
|
|
return db;
|
|
}
|
|
|
|
function insertRich(db: DatabaseSync, id: string, url: string, rich: unknown) {
|
|
db.prepare(
|
|
`INSERT INTO users (id, username, password_hash, created_at, email)
|
|
VALUES ('u', 'u', 'x', 'now', 'u@x') ON CONFLICT DO NOTHING;`,
|
|
).run();
|
|
db.prepare(
|
|
`INSERT INTO dumps (id, kind, title, user_id, created_at, url, rich_content)
|
|
VALUES (?, 'url', 't', 'u', 'now', ?, ?);`,
|
|
).run(id, url, typeof rich === "string" ? rich : JSON.stringify(rich));
|
|
}
|
|
|
|
function richOf(db: DatabaseSync, id: string): Record<string, unknown> {
|
|
return JSON.parse(
|
|
(db.prepare(`SELECT rich_content FROM dumps WHERE id = ?;`).get(id) as {
|
|
rich_content: string;
|
|
}).rich_content,
|
|
);
|
|
}
|
|
|
|
Deno.test("0011 then 0012: icons move to faviconUrl, artwork stays or comes back", () => {
|
|
const db = freshDb();
|
|
const cases: Record<
|
|
string,
|
|
[string, string | undefined, string | undefined]
|
|
> = {
|
|
// id: [thumbnailUrl before, thumbnailUrl after, faviconUrl after]
|
|
ico: [
|
|
"https://a.test/favicon.ico",
|
|
undefined,
|
|
"https://a.test/favicon.ico",
|
|
],
|
|
touch: [
|
|
"https://a.test/apple-touch-icon.png",
|
|
undefined,
|
|
"https://a.test/apple-touch-icon.png",
|
|
],
|
|
art: ["https://a.test/cover.jpg", "https://a.test/cover.jpg", undefined],
|
|
// 0011 mistook these for icons; 0012 puts them back.
|
|
logoFavicon: [
|
|
"https://a.test/uploads/mir-logo-favicon.png",
|
|
"https://a.test/uploads/mir-logo-favicon.png",
|
|
undefined,
|
|
],
|
|
svgArt: [
|
|
"https://a.test/art/poster.svg",
|
|
"https://a.test/art/poster.svg",
|
|
undefined,
|
|
],
|
|
// 0011 missed this one; 0012 catches it.
|
|
iconName: [
|
|
"https://a.test/img/icon_SEARCH.png",
|
|
undefined,
|
|
"https://a.test/img/icon_SEARCH.png",
|
|
],
|
|
};
|
|
for (const [id, [thumbnailUrl]] of Object.entries(cases)) {
|
|
insertRich(db, id, "https://a.test/", {
|
|
type: "generic",
|
|
url: "u",
|
|
thumbnailUrl,
|
|
});
|
|
}
|
|
up0011(db);
|
|
up0011(db);
|
|
up0012(db);
|
|
up0012(db);
|
|
for (const [id, [, thumbnailUrl, faviconUrl]] of Object.entries(cases)) {
|
|
const rich = richOf(db, id);
|
|
assertEquals([rich.thumbnailUrl, rich.faviconUrl], [
|
|
thumbnailUrl,
|
|
faviconUrl,
|
|
], id);
|
|
}
|
|
db.close();
|
|
});
|