Video attachments on failed scenarios are truncated (read before context.close())

Open Beginner friendly
#407 0 comments 0 reactions 0 assignees View on GitHub

Nobody has claimed this yet.

Assessment

Difficulty
2/5
Estimated time
1-3 hours
Newbie friendliness
85/100
Issue type
Bug
Clarity
Clearly specified
Activity status
Active
Tech stack
playwright, typescript
Domain
testing

Research direction

Start in src/support/hooks.ts around the After hook and utils/page-utils.ts:762, then review Playwright's video lifecycle and the existing screenshot attachment flow. Confirm that failed-scenario videos are finalized before attachment, remain valid WebM files, and show the failure state alongside the screenshot.

Written by the indexing model from the issue text.

Description

Summary

Every failed scenario's attached video (video/webm cucumber attachment) is truncated to whatever was flushed to disk at the moment the After hook reads it — it does not capture the actual failure moment. The attached screenshot is accurate; the video is not, and the two end up showing different page states for the same failure.

Root cause

createScreenShot() in utils/page-utils.ts:762:

public async createScreenShot(world: ICustomWorld, pickle: Pickle): Promise<void> {        
    const img: Buffer = await this.page?.screenshot({ path: `./test-results/screenshots/${pickle.name}.png`, type: "png" })
    const videoPath: string = await this.page?.video().path();

    world.attach(img, "image/png");

    const file = await fs.readFile(videoPath);
    world.attach(file, 'video/webm');
}

This runs from the After hook (src/support/hooks.ts:262) before this.page?.close() / this.context?.close() (hooks.ts:218-219). Per Playwright's video-recording contract, a recording isn't finalized into a valid webm container until the browser context closes — fs.readFile(videoPath) here reads whatever partial bytes had been flushed to disk up to that instant, not the completed file.

page.screenshot() in the same function is unaffected since it's a live, synchronous capture — so the screenshot correctly shows the real failure state while the video, read moments later in the same function, is an incomplete/unfinalized capture from earlier in the scenario.

Evidence

Reproduced while investigating a different issue (#406). Extracting the attached video with ffmpeg gives:

[matroska,webm] File ended prematurely

The video's last decodable frame shows the settings page mid-interaction ("Settings saved." banner still visible), while the screenshot attached to the same failed step shows a completely different page state (a License-validation error) — the actual moment of failure, which the video never reaches.

Impact

This isn't scenario-specific — any scenario where createScreenShot() runs (i.e. any failure) gets a video attachment that stops short of the actual failure. This quietly undermines debugging across the whole suite: the video looks like a normal recording but doesn't show what actually went wrong.

Suggested fix

Read/attach the video only after the context is closed — e.g. move the fs.readFile(videoPath) + world.attach(..., 'video/webm') call to after this.context?.close() in the After hook, or use Playwright's page.video().saveAs() (documented to be called post-close) instead of a manual fs.readFile.

Dominant language
TypeScript
Stars
1
Forks
1
Avg merge
3d 22h
Merged PRs (30d)
3

Contributor guide

No contributing guide indexed for this repository

First steps

  1. Read the whole issue, then the project's contributing guide.
  2. Comment on the issue to say you are picking it up — it saves two people doing the same work.
  3. Fork the repository and make your change on a branch.
  4. Open a pull request that references the issue number.

More from wp-media/wp-rocket-e2e

All issues in wp-media/wp-rocket-e2e

Similar issues

More TypeScript issues

Get new issues in your inbox

A short digest of beginner-friendly GitHub issues.