mirror of
https://github.com/heygen-com/hyperframes.git
synced 2026-09-07 18:26:17 +00:00
* refactor: extract @hyperframes/studio-server package from core Moves all studio-api routes, helpers, and Hono server wiring from packages/core/src/studio-api/ into a new standalone packages/studio-server package (@hyperframes/studio-server). Core keeps thin re-export stubs at @hyperframes/core/studio-api and the subpath helpers (screenshot-clip, draft-markers, etc.) for backward compatibility. Consumer imports (cli studioServer, vite adapter/config, producer htmlCompiler, studio manualEditsTypes) are updated to import from @hyperframes/studio-server directly. Also exports rewriteInlineStyleAssetUrls from @hyperframes/core root (was in compiler/rewriteSubCompPaths.ts but not re-exported), required by @hyperframes/studio-server/helpers/subComposition. Removes postcss-selector-parser from @hyperframes/core dependencies (moved to @hyperframes/studio-server which owns the routes that used it). Depends on @hyperframes/parsers (PR #1755). * fix(ci): add parsers+studio-server to Dockerfile and build before preview tests * fix(ci): build @hyperframes/studio-server before Test and studio load smoke Studio's vite.config.ts imports @hyperframes/studio-server, which resolves via its "node" export condition to built dist. The Test and studio-load-smoke jobs only built parsers + core, so esbuild's config load failed to resolve the package entry. Build studio-server too. * fix(studio): repoint sdkCutoverParity test import to studio-server sourceMutation moved from core's studio-api to @hyperframes/studio-server; the test still imported the deleted core path. This was masked while studio's vite.config failed to load (couldn't resolve studio-server); now that the config loads, the test runs and the stale import surfaced.
72 lines
2.1 KiB
TypeScript
72 lines
2.1 KiB
TypeScript
import { describe, expect, it } from "vitest";
|
|
import { validateUploadedMedia, validateUploadedMediaBuffer } from "./mediaValidation.js";
|
|
|
|
describe("validateUploadedMedia", () => {
|
|
it("passes through non-media files", () => {
|
|
expect(
|
|
validateUploadedMedia("/tmp/test.svg", () => ({ status: 0, stdout: "", stderr: "" })),
|
|
).toEqual({
|
|
ok: true,
|
|
});
|
|
});
|
|
|
|
it("accepts video files with a video stream", () => {
|
|
expect(
|
|
validateUploadedMedia("/tmp/test.mp4", () => ({
|
|
status: 0,
|
|
stdout: JSON.stringify({ streams: [{ codec_type: "video" }] }),
|
|
stderr: "",
|
|
})),
|
|
).toEqual({ ok: true });
|
|
});
|
|
|
|
it("rejects video files with no supported video stream", () => {
|
|
expect(
|
|
validateUploadedMedia("/tmp/test.mp4", () => ({
|
|
status: 0,
|
|
stdout: JSON.stringify({ streams: [] }),
|
|
stderr: "",
|
|
})),
|
|
).toEqual({ ok: false, reason: "no supported video stream found" });
|
|
});
|
|
|
|
it("accepts audio files with an audio stream", () => {
|
|
expect(
|
|
validateUploadedMedia("/tmp/test.wav", () => ({
|
|
status: 0,
|
|
stdout: JSON.stringify({ streams: [{ codec_type: "audio" }] }),
|
|
stderr: "",
|
|
})),
|
|
).toEqual({ ok: true });
|
|
});
|
|
|
|
it("does not block upload when ffprobe is unavailable", () => {
|
|
expect(
|
|
validateUploadedMedia("/tmp/test.mp4", () => ({
|
|
status: null,
|
|
stdout: "",
|
|
stderr: "",
|
|
error: { code: "ENOENT" } as NodeJS.ErrnoException,
|
|
})),
|
|
).toEqual({ ok: true });
|
|
});
|
|
});
|
|
|
|
describe("validateUploadedMediaBuffer", () => {
|
|
it("validates media from a temp file that preserves the extension", () => {
|
|
let inspectedPath = "";
|
|
expect(
|
|
validateUploadedMediaBuffer("raycast.mp4", new Uint8Array([0, 1, 2]), (_command, args) => {
|
|
inspectedPath = args.at(-1) ?? "";
|
|
return {
|
|
status: 0,
|
|
stdout: JSON.stringify({ streams: [{ codec_type: "video" }] }),
|
|
stderr: "",
|
|
};
|
|
}),
|
|
).toEqual({ ok: true });
|
|
|
|
expect(inspectedPath).toMatch(/raycast\.mp4$/);
|
|
});
|
|
});
|