@@ -58,15 +58,16 @@ jest.mock("@canvas/players/player", () => ({
5858jest . mock ( "@shotstack/shotstack-canvas" , ( ) => ( {
5959 Html5AssetSchema : { safeParse : ( data : unknown ) => ( { success : true , data } ) } ,
6060 composeHtml5IframeSrcdoc : jest . fn ( ( ) => "<html><body>Updated</body></html>" ) ,
61- computeHtml5FrameCount : ( { clipLengthSeconds, fps } : { clipLengthSeconds : number ; fps : number } ) => ( {
61+ computeHtml5FrameCount : jest . fn ( ( { clipLengthSeconds, fps } : { clipLengthSeconds : number ; fps : number } ) => ( {
6262 frameCount : Math . ceil ( clipLengthSeconds * fps )
63- } ) ,
63+ } ) ) ,
6464 findHtml5IngestUrls : jest . fn ( ( ) => [ ] ) ,
6565 html5ClipLongestEdge : jest . fn ( ( ) => 1280 ) ,
6666 inlineHtml5IngestAssets : jest . fn ( )
6767} ) ) ;
6868const canvasLib = jest . requireMock ( "@shotstack/shotstack-canvas" ) as {
6969 composeHtml5IframeSrcdoc : jest . Mock ;
70+ computeHtml5FrameCount : jest . Mock ;
7071 findHtml5IngestUrls : jest . Mock ;
7172 html5ClipLongestEdge : jest . Mock ;
7273 inlineHtml5IngestAssets : jest . Mock ;
@@ -280,6 +281,24 @@ it("ignores an older iframe timeout while newer content is loading", async () =>
280281 expect ( harness . contentContainer . children ) . toEqual ( [ expect . objectContaining ( { kind : "loading" } ) ] ) ;
281282} ) ;
282283
284+ // A page animated only by a style block in its markup has frames to capture, as it does in the render.
285+ it ( "counts frames from the page's markup when keying and capturing it" , async ( ) => {
286+ const { player, harness, iframe } = createPlayer ( ) ;
287+ Object . assign ( player , { getLength : ( ) => 1 } ) ;
288+ jest . spyOn ( harness , "seekHarness" ) . mockImplementation ( ( ) => {
289+ throw new Error ( "stop after first seek" ) ;
290+ } ) ;
291+
292+ await harness . hashAsset ( ) ;
293+ const capture = harness . captureFrames ( ) ;
294+ await until ( ( ) => iframe . srcdoc === "<html><body>Updated</body></html>" ) ;
295+ iframe . dispatchEvent ( new Event ( "load" ) ) ;
296+ await expect ( capture ) . rejects . toThrow ( "stop after first seek" ) ;
297+
298+ const counted = canvasLib . computeHtml5FrameCount . mock . calls . map ( ( [ args ] ) => args . htmlContent ) ;
299+ expect ( counted ) . toEqual ( [ "<div>Background</div>" , "<div>Background</div>" ] ) ;
300+ } ) ;
301+
283302it ( "captures from a freshly loaded document rather than the live-edited one" , async ( ) => {
284303 const { player, harness, iframe } = createPlayer ( ) ;
285304 Object . assign ( player , { getLength : ( ) => 1 } ) ;
@@ -647,6 +666,17 @@ it("renders a still from its own page without waiting for the clip's capture", a
647666 expect ( loading . visible ) . toBe ( true ) ;
648667} ) ;
649668
669+ it ( "counts frames from the page's markup when rendering a still" , async ( ) => {
670+ const { player, harness } = createStillPlayer ( ) ;
671+ jest . spyOn ( harness , "captureFrames" ) . mockImplementation ( ( ) => new Promise ( ( ) => { } ) ) ;
672+ harness . beginCapture ( ) ;
673+
674+ await player . prepareStaticRender ( ) ;
675+ player . endStaticRender ( ) ;
676+
677+ expect ( canvasLib . computeHtml5FrameCount ) . toHaveBeenCalledWith ( expect . objectContaining ( { htmlContent : "<div>Background</div>" } ) ) ;
678+ } ) ;
679+
650680it ( "takes a still from captured frames, in memory or cached, without rendering one" , async ( ) => {
651681 const { player, harness } = createStillPlayer ( ) ;
652682 Object . assign ( player , { getPlaybackTime : ( ) => 1 } ) ;
0 commit comments