Bohdan Nesteruk
Bohdan Nesteruk

Reputation: 914

Playwright: a buffer is incorrectly serialized when passing it to page.evaluateHandle?

I need to emulate a file dropping from the file system to a page. So I use this example: https://charliedigital.com/2021/12/20/simulate-drag-and-drop-of-files-with-playwright/

let fileBuffer = await fs.readFileSync(itemFilePath)
const dataTransfer = await buildTabPage.page.evaluateHandle((fileBuffer) => {
    const dt = new DataTransfer();

    console.log(JSON.stringify(fileBuffer))

   const file = new File([fileBuffer.toString('hex')], '140185A.zip', { type: 'application/octet-stream' });
   dt.items.add(file);
   return dt ;
}, fileBuffer);

await buildTabPage.page.dispatchEvent('.file-dropzone', 'drop', { dataTransfer });

It works, the drop event is triggered and I see the file coming to the backend.

The problem is that inside the function each buffer chain item looks like an object instead of a simple number.

After reading the file, the fileBuffer matches the buffer that comes to the backend when I drop a file manually. If I print it, it looks like a values chain:

 [
    80,
    75,
    3,
    4
    ...
]

But inside the evaluateHandle each buffer's item looks like an object:

{
    k: '0', 
    v: {
        n: 80
    }
}

Instead of just 80.

As far as I see, this happens in node_modules\playwright-core\lib\protocol\serializers.js -> function serializeValue(value, handleSerializer, visited)

So when I call the fileBuffer.toString('hex') it does not provide the file content. instead, it provides the [object Object] output.

And I cannot convert it to buffer again there, as the Buffer is undefined in that context.

How to properly pass a buffer into the page context?

Upvotes: 1

Views: 1288

Answers (1)

Bohdan Nesteruk
Bohdan Nesteruk

Reputation: 914

The solution is to pass not the entire buffer but the only buffer items chain into the evaluateHandle function (or to pass the hex string instead of the buffer).

let fileBuffer = await fs.readFileSync(itemFilePath)
const dataTransfer = await buildTabPage.page.evaluateHandle((fileBuffer) => {
        const dt = new DataTransfer();
        const file = new File([new Uint8Array(fileBuffer)], '140185A.zip', { type: 'application/octet-stream' });
        dt.items.add(file);
        return dt;
}, fileBuffer.toJSON().data); // or fileBuffer.toString('hex')

Upvotes: 1

Related Questions