Skip to content

Commit

Permalink
chore: implement BiDi set files
Browse files Browse the repository at this point in the history
  • Loading branch information
jrandolf committed Feb 26, 2024
1 parent 414f433 commit 32943f2
Show file tree
Hide file tree
Showing 6 changed files with 55 additions and 5 deletions.
2 changes: 1 addition & 1 deletion docs/webdriver-bidi.md
Original file line number Diff line number Diff line change
Expand Up @@ -52,6 +52,7 @@ This is an exciting step towards a more unified and efficient cross-browser auto
- Page.reload (except for `ignoreCache` parameter)
- Page.setViewport (`width`, `height`, `deviceScaleFactor` only)
- Puppeteer.launch
- ElementHandle.uploadFile()

- [Script evaluation](https://pptr.dev/guides/evaluate-javascript):

Expand Down Expand Up @@ -141,7 +142,6 @@ This is an exciting step towards a more unified and efficient cross-browser auto
- Other methods:

- Browser.userAgent()
- ElementHandle.uploadFile()
- Frame.isOOPFrame()
- Frame.waitForDevicePrompt()
- HTTPResponse.buffer()
Expand Down
27 changes: 24 additions & 3 deletions packages/puppeteer-core/src/bidi/ElementHandle.ts
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,6 @@
import type * as Bidi from 'chromium-bidi/lib/cjs/protocol/protocol.js';

import {ElementHandle, type AutofillData} from '../api/ElementHandle.js';
import {UnsupportedOperation} from '../common/Errors.js';
import {throwIfDisposed} from '../util/decorators.js';

import type {BidiFrame} from './Frame.js';
Expand Down Expand Up @@ -90,7 +89,29 @@ export class BidiElementHandle<
return null;
}

override uploadFile(this: ElementHandle<HTMLInputElement>): never {
throw new UnsupportedOperation();
override async uploadFile(
this: BidiElementHandle<HTMLInputElement>,
...filePaths: string[]
): Promise<void> {
/**
* The zero-length array is a special case, it seems that
* DOM.setFileInputFiles does not actually update the files in that case, so
* the solution is to eval the element value to a new FileList directly.
*/
if (files.length === 0) {
// XXX: These events should converted to trusted events. Perhaps do this
// in `DOM.setFileInputFiles`?
await this.evaluate(element => {
element.files = new DataTransfer().files;

// Dispatch events for this case because it should behave akin to a user action.
element.dispatchEvent(
new Event('input', {bubbles: true, composed: true})
);
element.dispatchEvent(new Event('change', {bubbles: true}));
});
return;
}
await this.frame.setFiles(this, filePaths);
}
}
10 changes: 10 additions & 0 deletions packages/puppeteer-core/src/bidi/Frame.ts
Original file line number Diff line number Diff line change
Expand Up @@ -42,6 +42,7 @@ import {BidiCdpSession} from './CDPSession.js';
import type {BrowsingContext} from './core/BrowsingContext.js';
import {BidiDeserializer} from './Deserializer.js';
import {BidiDialog} from './Dialog.js';
import type {BidiElementHandle} from './ElementHandle.js';
import {ExposeableFunction} from './ExposedFunction.js';
import {BidiHTTPRequest, requests} from './HTTPRequest.js';
import type {BidiHTTPResponse} from './HTTPResponse.js';
Expand Down Expand Up @@ -519,6 +520,15 @@ export class BidiFrame extends Frame {
concurrency,
});
}

@throwIfDetached
async setFiles(element: BidiElementHandle, files: string[]): Promise<void> {
await this.browsingContext.setFiles(
// SAFETY: ElementHandles are always remote references.
element.remoteValue() as Bidi.Script.SharedReference,
files
);
}
}

function isConsoleLogEntry(
Expand Down
15 changes: 15 additions & 0 deletions packages/puppeteer-core/src/bidi/core/BrowsingContext.ts
Original file line number Diff line number Diff line change
Expand Up @@ -524,6 +524,21 @@ export class BrowsingContext extends EventEmitter<{
});
}

@throwIfDisposed<BrowsingContext>(context => {
// SAFETY: Disposal implies this exists.
return context.#reason!;
})
async setFiles(
element: Bidi.Script.SharedReference,
files: string[]
): Promise<void> {
await this.#session.send('input.setFiles', {
context: this.id,
element,
files,
});
}

[disposeSymbol](): void {
this.#reason ??=
'Browsing context already closed, probably because the user context closed.';
Expand Down
4 changes: 4 additions & 0 deletions packages/puppeteer-core/src/bidi/core/Connection.ts
Original file line number Diff line number Diff line change
Expand Up @@ -106,6 +106,10 @@ export interface Commands {
params: Bidi.Input.ReleaseActionsParameters;
returnType: Bidi.EmptyResult;
};
'input.setFiles': {
params: Bidi.Input.SetFilesParameters;
returnType: Bidi.EmptyResult;
};

'permissions.setPermission': {
params: Bidi.Permissions.SetPermissionParameters;
Expand Down
2 changes: 1 addition & 1 deletion test/src/input.spec.ts
Original file line number Diff line number Diff line change
Expand Up @@ -18,7 +18,7 @@ describe('input tests', function () {
setupTestBrowserHooks();

describe('input', function () {
it('should upload the file', async () => {
it.only('should upload the file', async () => {
const {page, server} = await getTestState();

await page.goto(server.PREFIX + '/input/fileupload.html');
Expand Down

0 comments on commit 32943f2

Please sign in to comment.