chore: force localPaths to be resolved (#13544)
This commit is contained in:
parent
d44cfb93cb
commit
11179982fc
|
|
@ -284,7 +284,7 @@ export async function convertInputFiles(files: string | FilePayload | string[] |
|
||||||
}));
|
}));
|
||||||
return { streams };
|
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 => {
|
const filePayloads: SetInputFilesFiles = await Promise.all(items.map(async item => {
|
||||||
|
|
|
||||||
|
|
@ -24,7 +24,8 @@ import { JSHandleDispatcher, serializeResult, parseArgument } from './jsHandleDi
|
||||||
import type { FrameDispatcher } from './frameDispatcher';
|
import type { FrameDispatcher } from './frameDispatcher';
|
||||||
import type { CallMetadata } from '../instrumentation';
|
import type { CallMetadata } from '../instrumentation';
|
||||||
import type { WritableStreamDispatcher } from './writableStreamDispatcher';
|
import type { WritableStreamDispatcher } from './writableStreamDispatcher';
|
||||||
|
import { assert } from '../../utils';
|
||||||
|
import path from 'path';
|
||||||
export class ElementHandleDispatcher extends JSHandleDispatcher implements channels.ElementHandleChannel {
|
export class ElementHandleDispatcher extends JSHandleDispatcher implements channels.ElementHandleChannel {
|
||||||
_type_ElementHandle = true;
|
_type_ElementHandle = true;
|
||||||
|
|
||||||
|
|
@ -155,6 +156,8 @@ export class ElementHandleDispatcher extends JSHandleDispatcher implements chann
|
||||||
throw new Error('Neither localPaths nor streams is specified');
|
throw new Error('Neither localPaths nor streams is specified');
|
||||||
localPaths = params.streams.map(c => (c as WritableStreamDispatcher).path());
|
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);
|
return await this._elementHandle.setInputFiles(metadata, { localPaths }, params);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -25,6 +25,8 @@ import type { ResponseDispatcher } from './networkDispatchers';
|
||||||
import { RequestDispatcher } from './networkDispatchers';
|
import { RequestDispatcher } from './networkDispatchers';
|
||||||
import type { CallMetadata } from '../instrumentation';
|
import type { CallMetadata } from '../instrumentation';
|
||||||
import type { WritableStreamDispatcher } from './writableStreamDispatcher';
|
import type { WritableStreamDispatcher } from './writableStreamDispatcher';
|
||||||
|
import { assert } from '../../utils';
|
||||||
|
import path from 'path';
|
||||||
|
|
||||||
export class FrameDispatcher extends Dispatcher<Frame, channels.FrameChannel> implements channels.FrameChannel {
|
export class FrameDispatcher extends Dispatcher<Frame, channels.FrameChannel> implements channels.FrameChannel {
|
||||||
_type_Frame = true;
|
_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');
|
throw new Error('Neither localPaths nor streams is specified');
|
||||||
localPaths = params.streams.map(c => (c as WritableStreamDispatcher).path());
|
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);
|
return await this._frame.setInputFiles(metadata, params.selector, { localPaths }, params);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -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));
|
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 }) => {
|
it('should work @smoke', async ({ page, asset }) => {
|
||||||
await page.setContent(`<input type=file>`);
|
await page.setContent(`<input type=file>`);
|
||||||
await page.setInputFiles('input', asset('file-to-upload.txt'));
|
await page.setInputFiles('input', asset('file-to-upload.txt'));
|
||||||
|
|
|
||||||
Loading…
Reference in a new issue