fix(setInputFiles): make it work with CSP enabled (#3756)
We used to do fetch() to decode the file buffer. However, this is blocked by strict CSP policy. Instead, we can use explicit string -> bytes conversion, and trade performance for CSP compliance.
This commit is contained in:
parent
f232f34dae
commit
c190310335
|
|
@ -452,7 +452,7 @@ export class InjectedScript {
|
||||||
throw new Error('Not a checkbox');
|
throw new Error('Not a checkbox');
|
||||||
}
|
}
|
||||||
|
|
||||||
async setInputFiles(node: Node, payloads: { name: string, mimeType: string, buffer: string }[]) {
|
setInputFiles(node: Node, payloads: { name: string, mimeType: string, buffer: string }[]) {
|
||||||
if (node.nodeType !== Node.ELEMENT_NODE)
|
if (node.nodeType !== Node.ELEMENT_NODE)
|
||||||
return 'Node is not of type HTMLElement';
|
return 'Node is not of type HTMLElement';
|
||||||
const element: Element | undefined = node as Element;
|
const element: Element | undefined = node as Element;
|
||||||
|
|
@ -463,10 +463,10 @@ export class InjectedScript {
|
||||||
if (type !== 'file')
|
if (type !== 'file')
|
||||||
return 'Not an input[type=file] element';
|
return 'Not an input[type=file] element';
|
||||||
|
|
||||||
const files = await Promise.all(payloads.map(async file => {
|
const files = payloads.map(file => {
|
||||||
const result = await fetch(`data:${file.mimeType};base64,${file.buffer}`);
|
const bytes = Uint8Array.from(atob(file.buffer), c => c.charCodeAt(0));
|
||||||
return new File([await result.blob()], file.name, {type: file.mimeType});
|
return new File([bytes], file.name, { type: file.mimeType });
|
||||||
}));
|
});
|
||||||
const dt = new DataTransfer();
|
const dt = new DataTransfer();
|
||||||
for (const file of files)
|
for (const file of files)
|
||||||
dt.items.add(file);
|
dt.items.add(file);
|
||||||
|
|
|
||||||
|
|
@ -115,6 +115,15 @@ it('should work when file input is not attached to DOM', async ({page, server})
|
||||||
expect(chooser).toBeTruthy();
|
expect(chooser).toBeTruthy();
|
||||||
});
|
});
|
||||||
|
|
||||||
|
it('should work with CSP', async ({page, server}) => {
|
||||||
|
server.setCSP('/empty.html', 'default-src "none"');
|
||||||
|
await page.goto(server.EMPTY_PAGE);
|
||||||
|
await page.setContent(`<input type=file>`);
|
||||||
|
await page.setInputFiles('input', path.join(__dirname, '/assets/file-to-upload.txt'));
|
||||||
|
expect(await page.$eval('input', input => input.files.length)).toBe(1);
|
||||||
|
expect(await page.$eval('input', input => input.files[0].name)).toBe('file-to-upload.txt');
|
||||||
|
});
|
||||||
|
|
||||||
it('should respect timeout', async ({page, playwright}) => {
|
it('should respect timeout', async ({page, playwright}) => {
|
||||||
let error = null;
|
let error = null;
|
||||||
await page.waitForEvent('filechooser', {timeout: 1}).catch(e => error = e);
|
await page.waitForEvent('filechooser', {timeout: 1}).catch(e => error = e);
|
||||||
|
|
|
||||||
Loading…
Reference in a new issue