fix: compute payload mime type on server (#6647)

This commit is contained in:
Yury Semikhatsky 2021-05-19 01:30:20 +00:00 committed by GitHub
parent 33a505b1e5
commit 475a417dfc
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
6 changed files with 19 additions and 11 deletions

View file

@ -302,7 +302,6 @@ export async function convertInputFiles(files: string | FilePayload | string[] |
if (typeof item === 'string') {
return {
name: path.basename(item),
mimeType: mime.getType(item) || 'application/octet-stream',
buffer: (await util.promisify(fs.readFile)(item)).toString('base64')
};
} else {

View file

@ -1676,7 +1676,7 @@ export type FrameSetInputFilesParams = {
selector: string,
files: {
name: string,
mimeType: string,
mimeType?: string,
buffer: Binary,
}[],
timeout?: number,
@ -2181,7 +2181,7 @@ export type ElementHandleSelectTextResult = void;
export type ElementHandleSetInputFilesParams = {
files: {
name: string,
mimeType: string,
mimeType?: string,
buffer: Binary,
}[],
timeout?: number,

View file

@ -1328,7 +1328,7 @@ Frame:
type: object
properties:
name: string
mimeType: string
mimeType: string?
buffer: binary
timeout: number?
noWaitAfter: boolean?
@ -1747,7 +1747,7 @@ ElementHandle:
type: object
properties:
name: string
mimeType: string
mimeType: string?
buffer: binary
timeout: number?
noWaitAfter: boolean?

View file

@ -687,7 +687,7 @@ export function createScheme(tChannel: (name: string) => Validator): Scheme {
selector: tString,
files: tArray(tObject({
name: tString,
mimeType: tString,
mimeType: tOptional(tString),
buffer: tBinary,
})),
timeout: tOptional(tNumber),
@ -874,7 +874,7 @@ export function createScheme(tChannel: (name: string) => Validator): Scheme {
scheme.ElementHandleSetInputFilesParams = tObject({
files: tArray(tObject({
name: tString,
mimeType: tString,
mimeType: tOptional(tString),
buffer: tBinary,
})),
timeout: tOptional(tNumber),

View file

@ -14,11 +14,13 @@
* limitations under the License.
*/
import * as channels from '../protocol/channels';
import * as frames from './frames';
import { assert } from '../utils/utils';
import type { ElementStateWithoutStable, InjectedScript, InjectedScriptPoll } from './injected/injectedScript';
import * as injectedScriptSource from '../generated/injectedScriptSource';
import * as js from './javascript';
import * as mime from 'mime';
import { Page } from './page';
import { SelectorInfo } from './selectors';
import * as types from './types';
@ -26,6 +28,8 @@ import { Progress, ProgressController } from './progress';
import { FatalDOMError, RetargetableDOMError } from './common/domErrors';
import { CallMetadata } from './instrumentation';
type SetInputFilesFiles = channels.ElementHandleSetInputFilesParams['files'];
export class FrameExecutionContext extends js.ExecutionContext {
readonly frame: frames.Frame;
private _injectedScriptPromise?: Promise<js.JSHandle>;
@ -528,7 +532,7 @@ export class ElementHandle<T extends Node = Node> extends js.JSHandle<T> {
}, this._page._timeoutSettings.timeout(options));
}
async setInputFiles(metadata: CallMetadata, files: types.FilePayload[], options: types.NavigatingActionWaitOptions) {
async setInputFiles(metadata: CallMetadata, files: SetInputFilesFiles, options: types.NavigatingActionWaitOptions) {
const controller = new ProgressController(metadata, this);
return controller.run(async progress => {
const result = await this._setInputFiles(progress, files, options);
@ -536,7 +540,11 @@ export class ElementHandle<T extends Node = Node> extends js.JSHandle<T> {
}, this._page._timeoutSettings.timeout(options));
}
async _setInputFiles(progress: Progress, files: types.FilePayload[], options: types.NavigatingActionWaitOptions): Promise<'error:notconnected' | 'done'> {
async _setInputFiles(progress: Progress, files: SetInputFilesFiles, options: types.NavigatingActionWaitOptions): Promise<'error:notconnected' | 'done'> {
for (const payload of files) {
if (!payload.mimeType)
payload.mimeType = mime.getType(payload.name) || 'application/octet-stream';
}
const multiple = throwFatalDOMError(await this.evaluateInUtility(([injected, node]): 'error:notinput' | 'error:notconnected' | boolean => {
if (node.nodeType !== Node.ELEMENT_NODE || (node as Node as Element).tagName !== 'INPUT')
return 'error:notinput';
@ -549,7 +557,7 @@ export class ElementHandle<T extends Node = Node> extends js.JSHandle<T> {
await progress.beforeInputAction(this);
await this._page._frameManager.waitForSignalsCreatedBy(progress, options.noWaitAfter, async () => {
progress.throwIfAborted(); // Avoid action that has side-effects.
await this._page._delegate.setInputFiles(this as any as ElementHandle<HTMLInputElement>, files);
await this._page._delegate.setInputFiles(this as any as ElementHandle<HTMLInputElement>, files as types.FilePayload[]);
});
await this._page._doSlowMo();
return 'done';

View file

@ -15,6 +15,7 @@
* limitations under the License.
*/
import * as channels from '../protocol/channels';
import { ConsoleMessage } from './console';
import * as dom from './dom';
import { helper, RegisteredListener } from './helper';
@ -1060,7 +1061,7 @@ export class Frame extends SdkObject {
}, this._page._timeoutSettings.timeout(options));
}
async setInputFiles(metadata: CallMetadata, selector: string, files: types.FilePayload[], options: types.NavigatingActionWaitOptions = {}): Promise<void> {
async setInputFiles(metadata: CallMetadata, selector: string, files: channels.ElementHandleSetInputFilesParams['files'], options: types.NavigatingActionWaitOptions = {}): Promise<void> {
const controller = new ProgressController(metadata, this);
return controller.run(async progress => {
return dom.assertDone(await this._retryWithProgressIfNotConnected(progress, selector, handle => handle._setInputFiles(progress, files, options)));