Playwright: [Feature] writeFile method for creating screenshots or PDFs at browser launch

Created on 10 Mar 2020  路  1Comment  路  Source: microsoft/playwright

Feature idea: Abstract file system layer so that Playwright can be run isolated and better as a SaaS project to obtain the created files better

Main use cases:

  • Run it at scale for making screenshots or creating PDF files
  • You get the files directly as a Buffer instead of writing them first to the file system and then reading/moving them to a different location/storage provider
  • Maybe in the future also for downloading files (#853)

Related issues: https://github.com/mxschmitt/try-playwright/issues/12

Related code in the project:

https://github.com/microsoft/playwright/blob/ea6978a3d89fb8001332196e62b06ad224e978f5/src/screenshotter.ts#L141-L159

https://github.com/microsoft/playwright/blob/7f9df9488e3fcaacdea79956e98c4d538f0d859d/src/chromium/crProtocolHelper.ts#L64-L87

Possible implementation would be a writeFile(path: string, content: Buffer) method. For that readProtocolStream needs to be rewritten, so a Buffer will be returned instead of writing to the filesystem via fs.{open,write,close}.

I would pass this in the end as a .launch() argument.

Most helpful comment

(We discussed this offline, I'll put a summary here)

There are two ways to implement this:

  1. Overwrite Page.prototype.screenshot method (and Page.prototype.pdf).

    code snippet
const playwright = require('playwright');
const {Page} = require('playwright/lib/api');

const superScreenshot = Page.prototype.screenshot;

const BROWSER_ID = Symbol('BROWSER_ID');

Page.prototype.screenshot = async function(options) {
  const path = options.path;
  const browserId = this.context()._browser[BROWSER_ID];
  delete options.path;
  const buffer = await superScreenshot.call(this, options);
  console.log(`BrowserId = ${browserId}   screenshot to path: ${path}`);
  return buffer;
};

(async() => {
  for (let i = 0; i < 10; ++i) {
    const browser = await playwright.chromium.launch();
    browser[BROWSER_ID] = i;
    const page = await browser.newPage();
    await page.goto('https://example.com');
    await page.screenshot({path: 'foo.png'});
    await browser.close();
  }
})();

  1. Overwrite our //src/platform.ts - it provides a set of basic file system primitives we use to access file system. These are not guaranteed to be stable though - might be added/changed/removed in future.

Hope this helps!

>All comments

(We discussed this offline, I'll put a summary here)

There are two ways to implement this:

  1. Overwrite Page.prototype.screenshot method (and Page.prototype.pdf).

    code snippet
const playwright = require('playwright');
const {Page} = require('playwright/lib/api');

const superScreenshot = Page.prototype.screenshot;

const BROWSER_ID = Symbol('BROWSER_ID');

Page.prototype.screenshot = async function(options) {
  const path = options.path;
  const browserId = this.context()._browser[BROWSER_ID];
  delete options.path;
  const buffer = await superScreenshot.call(this, options);
  console.log(`BrowserId = ${browserId}   screenshot to path: ${path}`);
  return buffer;
};

(async() => {
  for (let i = 0; i < 10; ++i) {
    const browser = await playwright.chromium.launch();
    browser[BROWSER_ID] = i;
    const page = await browser.newPage();
    await page.goto('https://example.com');
    await page.screenshot({path: 'foo.png'});
    await browser.close();
  }
})();

  1. Overwrite our //src/platform.ts - it provides a set of basic file system primitives we use to access file system. These are not guaranteed to be stable though - might be added/changed/removed in future.

Hope this helps!

Was this page helpful?
0 / 5 - 0 ratings