Files
edgeever/apps/api/src/resource-service.test.mjs
T

75 lines
2.3 KiB
JavaScript

import { describe, expect, test } from "bun:test";
import {
MAX_ATTACHMENT_UPLOAD_BYTES,
MAX_IMAGE_UPLOAD_BYTES,
contentDispositionAttachment,
inferImageExtension,
mapResourceListItem,
normalizeFilename,
validateAttachmentUpload,
validateImageUpload,
} from "./resource-service.ts";
const resourceRow = {
id: "res_1",
memo_id: "memo_1",
original_memo_id: null,
bucket_name: "resources",
object_key: "workspaces/ws/memos/memo_1/res_1",
storage_config_id: "builtin",
kind: "image",
mime_type: "image/png",
filename: "diagram.png",
byte_size: 128,
sha256: "checksum",
width: 640,
height: 480,
created_at: "2026-08-08T00:00:00.000Z",
updated_at: "2026-08-08T01:00:00.000Z",
memo_title: "Architecture",
memo_excerpt: "System overview",
memo_is_deleted: 0,
};
describe("resource service contracts", () => {
test("maps storage-only fields out of public resource responses", () => {
expect(mapResourceListItem(resourceRow)).toEqual({
id: "res_1",
memoId: "memo_1",
originalMemoId: null,
kind: "image",
mimeType: "image/png",
filename: "diagram.png",
byteSize: 128,
sha256: "checksum",
width: 640,
height: 480,
createdAt: "2026-08-08T00:00:00.000Z",
updatedAt: "2026-08-08T01:00:00.000Z",
url: "/api/v1/resources/res_1/blob",
memoTitle: "Architecture",
memoExcerpt: "System overview",
memoDeleted: false,
});
});
test("normalizes filenames and keeps UTF-8 download names", () => {
expect(normalizeFilename(" reports/季度\u0000.pdf ")).toBe("reports-季度.pdf");
expect(contentDispositionAttachment("季度报告.pdf")).toContain(
"filename*=UTF-8''%E5%AD%A3%E5%BA%A6%E6%8A%A5%E5%91%8A.pdf",
);
});
test("infers normalized image extensions", () => {
expect(inferImageExtension("photo.JPEG", "application/octet-stream")).toBe(".jpg");
expect(inferImageExtension("photo", "image/avif")).toBe(".avif");
});
test("enforces upload type and size boundaries", () => {
expect(() => validateImageUpload("image/png", MAX_IMAGE_UPLOAD_BYTES)).not.toThrow();
expect(() => validateAttachmentUpload(MAX_ATTACHMENT_UPLOAD_BYTES)).not.toThrow();
expect(() => validateImageUpload("image/svg+xml", 128)).toThrow();
expect(() => validateAttachmentUpload(MAX_ATTACHMENT_UPLOAD_BYTES + 1)).toThrow();
});
});