tests/videoEmbed.test.ts
Rama main · réplica de lectura del repositorio original.
// FILM IN A NOTE — the pure half (shared/mediaEmbeds.ts, shared/videoEmbeds.ts,
// shared/fileKinds.ts, shared/attachments.ts, shared/limits.ts,
// shared/embedActions.ts): which
// names are films, what `#t=` and `|poster=` say, the fallback decision a
// browser's `canPlayType` makes, what the server calls each film, and the
// embed menu's rows for one.
import assert from "node:assert/strict";
import { describe, it } from "node:test";
import { isAudioName, isTimedMediaName, isVideoName } from "../shared/mediaEmbeds.ts";
import {
mediaFragmentHash,
parseMediaFragment,
parseVideoAlias,
posterNamesIn,
videoPlayable,
videoProbeTypes,
} from "../shared/videoEmbeds.ts";
import { attachmentKindOf, contentTypeFor, isAcceptedAttachment } from "../shared/attachments.ts";
import { UPLOAD_MAX_MB, VIDEO_UPLOAD_MAX_MB, uploadCapMb } from "../shared/limits.ts";
import { embedMenuActions } from "../shared/embedActions.ts";
describe("the film kind", () => {
it("knows the six containers, case-blind, and nothing else", () => {
for (const name of ["clip.mp4", "Clip.MOV", "a b.webm", "x.m4v", "film.mkv", "old.ogv", " media/clip.mp4 "]) {
assert.equal(isVideoName(name), true, name);
}
for (const name of ["lecture.mp3", "pic.png", "notes.md", "mp4", "clip.mp4.md"]) assert.equal(isVideoName(name), false, name);
});
it("a WebM is both: a film to draw, a sound a `#t=` link may seek", () => {
assert.equal(isVideoName("2026-09-23 1402.webm"), true);
assert.equal(isAudioName("2026-09-23 1402.webm"), true);
assert.equal(isTimedMediaName("clip.mp4"), true);
assert.equal(isTimedMediaName("lecture.mp3"), true);
assert.equal(isTimedMediaName("paper.pdf"), false);
});
it("every film extension is a video in the tree and is served with its own type", () => {
const want: Record<string, string> = {
mp4: "video/mp4",
m4v: "video/mp4",
webm: "video/webm",
mov: "video/quicktime",
mkv: "video/x-matroska",
ogv: "video/ogg",
};
for (const [ext, type] of Object.entries(want)) {
assert.equal(attachmentKindOf(`clip.${ext}`), "video", ext);
assert.equal(contentTypeFor(`clip.${ext}`), type, ext);
assert.equal(isAcceptedAttachment(`clip.${ext}`), true, `${ext} may be uploaded`);
}
});
it("a film has its own upload cap, larger than a picture's", () => {
assert.ok(VIDEO_UPLOAD_MAX_MB > UPLOAD_MAX_MB);
assert.equal(uploadCapMb("mp4"), VIDEO_UPLOAD_MAX_MB);
assert.equal(uploadCapMb("MKV"), VIDEO_UPLOAD_MAX_MB);
assert.equal(uploadCapMb("png"), UPLOAD_MAX_MB);
assert.equal(uploadCapMb(""), UPLOAD_MAX_MB);
});
});
describe("`#t=` on a film", () => {
it("reads a start, a range, a range from the top, clock times and Arabic digits", () => {
assert.deepEqual(parseMediaFragment("t=12"), { start: 12, end: null });
assert.deepEqual(parseMediaFragment("t=12,30"), { start: 12, end: 30 });
assert.deepEqual(parseMediaFragment("t=1:05,1:30"), { start: 65, end: 90 });
assert.deepEqual(parseMediaFragment("t=,30"), { start: 0, end: 30 });
assert.deepEqual(parseMediaFragment("t=١٢,٣٠"), { start: 12, end: 30 });
});
it("refuses what is not a time, and a range that ends before it starts", () => {
for (const bad of [null, "", "t=", "t=a", "t=30,12", "t=12,12", "t=12,", "page=3", "Heading"]) {
assert.equal(parseMediaFragment(bad), null, String(bad));
}
});
it("writes the fragment back as the URL hash the player loads", () => {
assert.equal(mediaFragmentHash({ start: 12, end: null }), "#t=12");
assert.equal(mediaFragmentHash({ start: 12, end: 30 }), "#t=12,30");
assert.equal(mediaFragmentHash({ start: 1.23456, end: null }), "#t=1.235");
// No time named: the first frame, which is what makes it the poster.
assert.equal(mediaFragmentHash(null), "#t=0.001");
});
});
describe("`|…` on a film", () => {
it("is a width, a poster, both in either order, and nothing else", () => {
assert.deepEqual(parseVideoAlias(null), { width: null, poster: null });
assert.deepEqual(parseVideoAlias("480"), { width: 480, poster: null });
assert.deepEqual(parseVideoAlias("poster=frame.jpg"), { width: null, poster: "frame.jpg" });
assert.deepEqual(parseVideoAlias("480|poster=stills/a frame.png"), { width: 480, poster: "stills/a frame.png" });
assert.deepEqual(parseVideoAlias("poster = f.jpg | 320"), { width: 320, poster: "f.jpg" });
assert.deepEqual(parseVideoAlias("My holiday"), { width: null, poster: null }, "a caption does no harm");
assert.deepEqual(parseVideoAlias("poster="), { width: null, poster: null });
});
it("finds every poster a body's film embeds name — and no picture's alias", () => {
const body = "![[clip.mp4|poster=a.jpg]]\n![[b.webm#t=3|480|poster=b.png]] and ![[pic.png|poster=no.jpg]]\n![[clip.mp4|poster=a.jpg]]";
assert.deepEqual(posterNamesIn(body), ["a.jpg", "b.png"]);
});
});
describe("the fallback decision", () => {
// A stand-in for HTMLMediaElement.canPlayType on a browser that plays
// WebM and MP4 and says nothing for QuickTime or Matroska.
const chromeLike = (type: string): string => (type === "video/webm" || type === "video/mp4" ? "maybe" : "");
const nothing = (): string => "";
it("asks the containers a film is most likely to be", () => {
assert.deepEqual(videoProbeTypes("a.mov"), ["video/quicktime", "video/mp4"]);
assert.deepEqual(videoProbeTypes("a.mkv"), ["video/x-matroska", "video/webm"]);
assert.deepEqual(videoProbeTypes("a.txt"), []);
});
it("draws a player for anything the browser says it may play", () => {
for (const name of ["a.mp4", "a.m4v", "a.webm", "a.mov", "a.mkv"]) assert.equal(videoPlayable(name, chromeLike), true, name);
});
it("falls back to the card when the browser has no answer", () => {
assert.equal(videoPlayable("a.ogv", chromeLike), false);
for (const name of ["a.mp4", "a.mkv"]) assert.equal(videoPlayable(name, nothing), false, name);
assert.equal(videoPlayable("notes.md", () => "probably"), false, "not a film at all");
});
});
describe("the embed menu on a film", () => {
const base = { admin: true, resolved: true, clipboardImage: true, clipboardText: true, canEdit: true, touch: false };
it("offers the file's verbs and never Copy image", () => {
const rows = embedMenuActions({ ...base, kind: "video" });
assert.ok(!rows.includes("copyImage"));
for (const verb of ["copyLink", "copyMarkdown", "copyPath", "open", "reveal", "saveAs", "rename", "remove"] as const) {
assert.ok(rows.includes(verb), verb);
}
});
it("on a finger, Move… stands in for the drag and Reveal goes", () => {
const rows = embedMenuActions({ ...base, kind: "video", touch: true });
assert.ok(rows.includes("move"));
assert.ok(!rows.includes("reveal"));
});
it("a visitor gets Copy link, Open and Save as", () => {
const rows = embedMenuActions({ ...base, kind: "video", admin: false, canEdit: false }).filter((r) => r !== null);
assert.deepEqual(rows, ["copyLink", "open", "saveAs"]);
});
});