fix(studio): release retained preview resources (#2924)

This commit is contained in:
Miguel Ángel
2026-07-31 14:31:43 +02:00
committed by GitHub
parent a3c8f897f2
commit fbfffb1aa7
6 changed files with 308 additions and 92 deletions
@@ -1,13 +1,20 @@
// @vitest-environment happy-dom
import { describe, expect, it } from "vitest";
import { afterEach, describe, expect, it, vi } from "vitest";
import {
findMatchingTimelineElementId,
findTimelineIdByAncestor,
resolveDroppedAssetDimensions,
resolveTimelineIdForSelection,
resolveTimelineSelectionSeekTime,
} from "./studioHelpers";
afterEach(() => {
vi.useRealTimers();
vi.unstubAllGlobals();
vi.restoreAllMocks();
});
describe("resolveTimelineSelectionSeekTime", () => {
it("keeps the current time when it is already inside the clip range", () => {
expect(resolveTimelineSelectionSeekTime(3, { start: 0, duration: 5 })).toBe(3);
@@ -148,3 +155,43 @@ describe("resolveTimelineIdForSelection", () => {
expect(resolveTimelineIdForSelection(selection, els, null)).toBe(null);
});
});
describe("resolveDroppedAssetDimensions", () => {
it("aborts an image probe when metadata times out", async () => {
vi.useFakeTimers();
const probe = {
addEventListener: vi.fn(),
naturalHeight: 0,
naturalWidth: 0,
src: "",
};
vi.stubGlobal(
"Image",
vi.fn(() => probe),
);
const result = resolveDroppedAssetDimensions("demo", "assets/hung.png", "image");
await vi.advanceTimersByTimeAsync(3000);
await expect(result).resolves.toBeNull();
expect(probe.src).toBe("");
});
it("aborts a video probe when metadata times out", async () => {
vi.useFakeTimers();
const video = document.createElement("video");
const load = vi.fn();
Object.defineProperty(video, "load", { configurable: true, value: load });
const createElement = document.createElement.bind(document);
vi.spyOn(document, "createElement").mockImplementation((tagName, options) =>
tagName === "video" ? video : createElement(tagName, options),
);
const result = resolveDroppedAssetDimensions("demo", "assets/hung.mp4", "video");
await vi.advanceTimersByTimeAsync(3000);
await expect(result).resolves.toBeNull();
expect(video.getAttribute("src")).toBe("");
expect(load).toHaveBeenCalledOnce();
});
});