mirror of
https://github.com/heygen-com/hyperframes.git
synced 2026-10-30 09:16:55 +00:00
fix(studio): a reload refused because the page is missing mid-edit warns instead of erroring (#6491)
This commit is contained in:
@@ -0,0 +1,16 @@
|
||||
import { describe, expect, it } from "vitest";
|
||||
import { refusedPreviewMessage, refusedPreviewStatus } from "./studioPreviewMark";
|
||||
|
||||
describe("refusedPreviewStatus", () => {
|
||||
it.each([404, 410, 500])("reads %i back out of the refused page's message", (status) => {
|
||||
expect(refusedPreviewStatus(refusedPreviewMessage(status))).toBe(status);
|
||||
});
|
||||
|
||||
it.each([
|
||||
"Composition timeline not found after 8s",
|
||||
"it took too long to load",
|
||||
"x The preview page could not be loaded (HTTP 404).",
|
||||
])("finds no status in %j", (cause) => {
|
||||
expect(refusedPreviewStatus(cause)).toBeNull();
|
||||
});
|
||||
});
|
||||
@@ -3,6 +3,13 @@ export const STUDIO_PREVIEW_CAPTURE_MODE = "capture";
|
||||
export const STUDIO_PREVIEW_UPCOMING_ATTR = "data-hf-upcoming";
|
||||
export const STUDIO_PREVIEW_LAZY_ATTR = "data-hf-preview-lazy";
|
||||
export const STUDIO_PREVIEW_ERRORS = "__hfPreviewErrors";
|
||||
|
||||
export const refusedPreviewMessage = (status: number) =>
|
||||
`The preview page could not be loaded (HTTP ${status}).`;
|
||||
export function refusedPreviewStatus(message: string): number | null {
|
||||
const status = /^The preview page could not be loaded \(HTTP (\d{3})\)\.$/.exec(message)?.[1];
|
||||
return status ? Number(status) : null;
|
||||
}
|
||||
export const PREVIEW_RASTER_ATTR = "data-hf-preview-raster";
|
||||
export const RUNTIME_STAMPED_ATTR = "data-hf-autostamped";
|
||||
export const CLIP_HIDDEN_ATTR = "data-hf-clip-hidden";
|
||||
|
||||
@@ -1,6 +1,9 @@
|
||||
import { STUDIO_PREVIEW_ERRORS } from "@hyperframes/core/studio-preview-mark";
|
||||
import {
|
||||
refusedPreviewMessage,
|
||||
STUDIO_PREVIEW_ERRORS,
|
||||
} from "@hyperframes/core/studio-preview-mark";
|
||||
|
||||
export function previewErrorPage(status: number): string {
|
||||
const message = `The preview page could not be loaded (HTTP ${status}).`;
|
||||
const message = refusedPreviewMessage(status);
|
||||
return `<!doctype html><meta charset="utf-8"><script>window.${STUDIO_PREVIEW_ERRORS}=[${JSON.stringify(message)}]</script><p>${message}</p>`;
|
||||
}
|
||||
|
||||
@@ -8,6 +8,7 @@ import {
|
||||
isStudioManualEditGestureLiveIn,
|
||||
studioManualEditSavesIn,
|
||||
} from "../../components/editor/manualEditsDom";
|
||||
import { refusedPreviewStatus } from "@hyperframes/core/studio-preview-mark";
|
||||
import { logReload } from "../../utils/reloadDebug";
|
||||
import {
|
||||
useTimelineSyncCallbacks,
|
||||
@@ -131,7 +132,9 @@ export function useShadowPreviewReload({
|
||||
setPreviewReloading(false);
|
||||
const message = `The preview did not reload (${cause}). It was still waiting for ${waitingFor}. The previous preview is still showing.`;
|
||||
logReload("shadow-failed", { cause, waitingFor });
|
||||
console.error(`[studio] ${message}`);
|
||||
const refused = refusedPreviewStatus(cause);
|
||||
const pageMissingNow = refused !== null && refused < 500;
|
||||
(pageMissingNow ? console.warn : console.error)(`[studio] ${message}`);
|
||||
onReloadFailedRef.current?.(message);
|
||||
},
|
||||
[stopPendingShadow, isRefreshingRef, pendingSeekRef],
|
||||
|
||||
@@ -5,6 +5,7 @@ import React, { act } from "react";
|
||||
import { createRoot } from "react-dom/client";
|
||||
import { afterEach, describe, expect, it, vi } from "vitest";
|
||||
import { SHADOW_READY_BUDGETS, SHADOW_READY_TIMEOUT_MS } from "./useShadowPreviewReload";
|
||||
import { refusedPreviewMessage } from "@hyperframes/core/studio-preview-mark";
|
||||
import { usePlayerStore } from "../store/playerStore";
|
||||
import { isPreviewChanging } from "../previewReloading";
|
||||
import { NLEProvider, useNLEContext, type NLEContextValue } from "../../components/nle/NLEContext";
|
||||
@@ -639,6 +640,26 @@ describe("shadow reload readiness and failure", () => {
|
||||
unmount(root);
|
||||
});
|
||||
|
||||
// An agent's edit moves the page away for a few saves: each reload is refused until it is back.
|
||||
it.each([
|
||||
[404, "warn"],
|
||||
[500, "error"],
|
||||
] as const)("reports a reload the server refused with %i as a console %s", (status, level) => {
|
||||
const warn = vi.spyOn(console, "warn").mockImplementation(() => {});
|
||||
const error = vi.spyOn(console, "error").mockImplementation(() => {});
|
||||
const onPreviewReloadFailed = vi.fn();
|
||||
const { getApi, live, gen, root } = beginReload({ onPreviewReloadFailed });
|
||||
|
||||
act(() => getApi().onShadowError(gen, refusedPreviewMessage(status)));
|
||||
|
||||
expect(getApi().iframeRef.current).toBe(live);
|
||||
expect(onPreviewReloadFailed).toHaveBeenCalledOnce();
|
||||
const said = (spy: typeof warn) =>
|
||||
spy.mock.calls.some(([text]) => String(text).includes(`(HTTP ${status})`));
|
||||
expect([said(warn), said(error)]).toEqual([level === "warn", level === "error"]);
|
||||
unmount(root);
|
||||
});
|
||||
|
||||
it("runs no load side effects for a superseded shadow", () => {
|
||||
const { getApi, gen, root } = beginReload();
|
||||
usePlayerStore.getState().setCurrentTime(7);
|
||||
|
||||
Reference in New Issue
Block a user