Skip to content

[Docs]: Discourage Download.createReadStream #37805

@WiseNat

Description

@WiseNat

Page(s)

https://playwright.dev/docs/downloads

Description

The Downloads documentation is rather limited surrounding the createReadStream method. I appreciate the Readable Object is not a Playwright Object but information on how to block Playwright so that file content assertions can be performed would be useful.

When I naively created a test with the Readable Object documentations recommended way of reading content, Playwright did not wait for the stream to finish reading and would show false-positives with tests passing. This is visible with the following:

  // Act
  const [download] = await Promise.all([
    page.waitForEvent("download"),
    // Trigger a file download
  ]);

  const readable = await download.createReadStream();
  readable.setEncoding("binary");

  const chunks: string[] = [];

  readable.on("readable", () => {
    let chunk;
    while (null !== (chunk = readable.read())) {
      chunks.push(chunk);
    }
  });

  readable.on("end", () => {
    const actual = chunks.join("");
    const expected = "Example File Content";

    expect(actual).toEqual(expected);
    expect("A").toEqual("B"); // Should fail for all tests
  });

The expect("A").toEqual("B"); in the "end" event should cause all tests to fail. However, both "readable" and "end" events are asynchronous and so Playwright does not block for them. So, when reading the file data into chunks, Playwright will simultaneously close leading to the following error:
Error: readableStreamImpl._read: Target page, context or browser has been closed

The way I've managed to get this to work is with the following:

// Act
const [download] = await Promise.all([
  page.waitForEvent("download"),
  // Trigger a file download
]);

const readable = await download.createReadStream();
readable.setEncoding("binary");

let actual = "";
readable.on("data", (chunk) => (actual += chunk));

await finished(readable);

const expected = "Example File Content";

expect(actual).toEqual(expected);

With await finished(readable);, Playwright is blocked, removing the flakiness of testing the contents of a downloaded file.

I appreciate people may come to the same conclusion as me, in hindsight it's fairly obvious why the flakiness occurred, but adding information for asserting on a downloaded file's content to the documentation would help people testing this.

Metadata

Metadata

Assignees

Labels

Type

No type

Projects

No projects

Milestone

No milestone

Relationships

None yet

Development

No branches or pull requests

Issue actions