chore: force localPaths to be resolved (#13544)

This commit is contained in:
Ross Wollman 2022-04-14 11:19:36 -07:00 committed by GitHub
parent d44cfb93cb
commit 11179982fc
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
4 changed files with 58 additions and 2 deletions

View file

@ -284,7 +284,7 @@ export async function convertInputFiles(files: string | FilePayload | string[] |
}));
return { streams };
}
return { localPaths: items as string[] };
return { localPaths: items.map(f => path.resolve(f as string)) as string[] };
}
const filePayloads: SetInputFilesFiles = await Promise.all(items.map(async item => {

View file

@ -24,7 +24,8 @@ import { JSHandleDispatcher, serializeResult, parseArgument } from './jsHandleDi
import type { FrameDispatcher } from './frameDispatcher';
import type { CallMetadata } from '../instrumentation';
import type { WritableStreamDispatcher } from './writableStreamDispatcher';
import { assert } from '../../utils';
import path from 'path';
export class ElementHandleDispatcher extends JSHandleDispatcher implements channels.ElementHandleChannel {
_type_ElementHandle = true;
@ -155,6 +156,8 @@ export class ElementHandleDispatcher extends JSHandleDispatcher implements chann
throw new Error('Neither localPaths nor streams is specified');
localPaths = params.streams.map(c => (c as WritableStreamDispatcher).path());
}
for (const p of localPaths)
assert(path.isAbsolute(p) && path.resolve(p) === p, 'Paths provided to localPaths must be absolute and fully resolved.');
return await this._elementHandle.setInputFiles(metadata, { localPaths }, params);
}

View file

@ -25,6 +25,8 @@ import type { ResponseDispatcher } from './networkDispatchers';
import { RequestDispatcher } from './networkDispatchers';
import type { CallMetadata } from '../instrumentation';
import type { WritableStreamDispatcher } from './writableStreamDispatcher';
import { assert } from '../../utils';
import path from 'path';
export class FrameDispatcher extends Dispatcher<Frame, channels.FrameChannel> implements channels.FrameChannel {
_type_Frame = true;
@ -215,6 +217,8 @@ export class FrameDispatcher extends Dispatcher<Frame, channels.FrameChannel> im
throw new Error('Neither localPaths nor streams is specified');
localPaths = params.streams.map(c => (c as WritableStreamDispatcher).path());
}
for (const p of localPaths)
assert(path.isAbsolute(p) && path.resolve(p) === p, 'Paths provided to localPaths must be absolute and fully resolved.');
return await this._frame.setInputFiles(metadata, params.selector, { localPaths }, params);
}

View file

@ -84,6 +84,55 @@ it('should upload large file', async ({ page, server, browserName, isMac }, test
await Promise.all([uploadFile, file1.filepath].map(fs.promises.unlink));
});
it('should upload large file with relative path', async ({ page, server, browserName, isMac }, testInfo) => {
it.skip(browserName === 'webkit' && isMac && parseInt(os.release(), 10) < 20, 'WebKit for macOS 10.15 is frozen and does not have corresponding protocol features.');
it.slow();
await page.goto(server.PREFIX + '/input/fileupload.html');
const uploadFile = testInfo.outputPath('200MB.zip');
const str = 'A'.repeat(4 * 1024);
const stream = fs.createWriteStream(uploadFile);
for (let i = 0; i < 50 * 1024; i++) {
await new Promise<void>((fulfill, reject) => {
stream.write(str, err => {
if (err)
reject(err);
else
fulfill();
});
});
}
await new Promise(f => stream.end(f));
const input = page.locator('input[type="file"]');
const events = await input.evaluateHandle(e => {
const events = [];
e.addEventListener('input', () => events.push('input'));
e.addEventListener('change', () => events.push('change'));
return events;
});
const relativeUploadPath = path.relative(process.cwd(), uploadFile);
expect(path.isAbsolute(relativeUploadPath)).toBeFalsy();
await input.setInputFiles(relativeUploadPath);
expect(await input.evaluate(e => (e as HTMLInputElement).files[0].name)).toBe('200MB.zip');
expect(await events.evaluate(e => e)).toEqual(['input', 'change']);
const serverFilePromise = new Promise<formidable.File>(fulfill => {
server.setRoute('/upload', async (req, res) => {
const form = new formidable.IncomingForm({ uploadDir: testInfo.outputPath() });
form.parse(req, function(err, fields, f) {
res.end();
const files = f as Record<string, formidable.File>;
fulfill(files.file1);
});
});
});
const [file1] = await Promise.all([
serverFilePromise,
page.click('input[type=submit]')
]);
expect(file1.originalFilename).toBe('200MB.zip');
expect(file1.size).toBe(200 * 1024 * 1024);
await Promise.all([uploadFile, file1.filepath].map(fs.promises.unlink));
});
it('should work @smoke', async ({ page, asset }) => {
await page.setContent(`<input type=file>`);
await page.setInputFiles('input', asset('file-to-upload.txt'));