import { afterEach, describe, expect, it, vi } from "vite-plus/test"; import type { ComposerFileAttachment } from "../../composerDraftStore";import { attachVideoThumbnail, buildExpandedImagePreview, resolveMarkdownMediaPreview,} from "./ExpandedImagePreview"; describe("resolveMarkdownMediaPreview", () => { afterEach(() => { vi.unstubAllGlobals(); }); it.each([ ["t3code:", "https:"], ["t3code-dev:", "https:"], ["http:", "http:"], ["https:", "https:"], ])( "resolves protocol-relative media on %s without changing its source", async (pageProtocol, mediaProtocol) => { vi.stubGlobal("window", { location: { protocol: pageProtocol } }); const source = "//cdn.example.com/recording.mp4?token=a%2FB&v=1#t=2"; const preview = await resolveMarkdownMediaPreview({ source, createAssetUrl: async () => { throw new Error("Remote media must not request a local asset URL."); }, }); expect(preview?.images[0]).toMatchObject({ src: `${mediaProtocol}${source}`, originalUrl: source, actionsSource: { src: `${mediaProtocol}${source}`, reference: { kind: "url", url: source }, }, }); }, );}); describe("buildExpandedImagePreview", () => { it("keeps window capture details with the expanded image", () => { const source = { kind: "snap-shot" as const, capturedAt: "2026-09-01T00:00:00.000Z", appName: "Editor", windowTitle: "main.ts", accessibleText: "const answer = 42;", }; const preview = buildExpandedImagePreview( [ { type: "image", id: "capture-1", name: "window.png", mimeType: "image/png", sizeBytes: 3, previewUrl: "data:image/png;base64,AQID", source, }, ], "capture-1", ); expect(preview?.images[0]?.source).toEqual(source); }); it("builds a video preview for a local video attachment", () => { const file = new File([new Uint8Array([1, 2, 3])], "demo.mp4", { type: "video/mp4" }); const attachment: ComposerFileAttachment = { type: "file", id: "video-1", name: file.name, mimeType: file.type, sizeBytes: file.size, file, }; const preview = buildExpandedImagePreview([attachment], attachment.id); expect(preview).toMatchObject({ images: [{ name: "demo.mp4", type: "video" }], index: 0, }); expect(preview?.images[0]?.src).toMatch(/^blob:/); URL.revokeObjectURL(preview?.images[0]?.src ?? ""); }); it("releases a video thumbnail URL when detached", async () => { const video = { src: "" } as HTMLVideoElement; const file = new File([new Uint8Array([1, 2, 3])], "demo.mp4", { type: "video/mp4" }); const detach = attachVideoThumbnail(video, file); const url = video.src; expect((await fetch(url)).ok).toBe(true); detach(); await expect(fetch(url)).rejects.toThrow(); });});
import { afterEach, describe, expect, it, vi } from "vite-plus/test";
import type { ComposerFileAttachment } from "../../composerDraftStore";
import {
attachVideoThumbnail,
buildExpandedImagePreview,
resolveMarkdownMediaPreview,
} from "./ExpandedImagePreview";
describe("resolveMarkdownMediaPreview", () => {
afterEach(() => {
vi.unstubAllGlobals();
});
it.each([
["t3code:", "https:"],
["t3code-dev:", "https:"],
["http:", "http:"],
["https:", "https:"],
])(
"resolves protocol-relative media on %s without changing its source",
async (pageProtocol, mediaProtocol) => {
vi.stubGlobal("window", { location: { protocol: pageProtocol } });
const source = "//cdn.example.com/recording.mp4?token=a%2FB&v=1#t=2";
const preview = await resolveMarkdownMediaPreview({
source,
createAssetUrl: async () => {
throw new Error("Remote media must not request a local asset URL.");
},
});
expect(preview?.images[0]).toMatchObject({
src: `${mediaProtocol}${source}`,
originalUrl: source,
actionsSource: {
src: `${mediaProtocol}${source}`,
reference: { kind: "url", url: source },
},
});
},
);
});
describe("buildExpandedImagePreview", () => {
it("keeps window capture details with the expanded image", () => {
const source = {
kind: "snap-shot" as const,
capturedAt: "2026-09-01T00:00:00.000Z",
appName: "Editor",
windowTitle: "main.ts",
accessibleText: "const answer = 42;",
};
const preview = buildExpandedImagePreview(
[
{
type: "image",
id: "capture-1",
name: "window.png",
mimeType: "image/png",
sizeBytes: 3,
previewUrl: "data:image/png;base64,AQID",
source,
},
],
"capture-1",
);
expect(preview?.images[0]?.source).toEqual(source);
});
it("builds a video preview for a local video attachment", () => {
const file = new File([new Uint8Array([1, 2, 3])], "demo.mp4", { type: "video/mp4" });
const attachment: ComposerFileAttachment = {
type: "file",
id: "video-1",
name: file.name,
mimeType: file.type,
sizeBytes: file.size,
file,
};
const preview = buildExpandedImagePreview([attachment], attachment.id);
expect(preview).toMatchObject({
images: [{ name: "demo.mp4", type: "video" }],
index: 0,
});
expect(preview?.images[0]?.src).toMatch(/^blob:/);
URL.revokeObjectURL(preview?.images[0]?.src ?? "");
});
it("releases a video thumbnail URL when detached", async () => {
const video = { src: "" } as HTMLVideoElement;
const file = new File([new Uint8Array([1, 2, 3])], "demo.mp4", { type: "video/mp4" });
const detach = attachVideoThumbnail(video, file);
const url = video.src;
expect((await fetch(url)).ok).toBe(true);
detach();
await expect(fetch(url)).rejects.toThrow();
});
});