Skip to content

Commit

Permalink
fix: update file chooser events (#11057)
Browse files Browse the repository at this point in the history
  • Loading branch information
jrandolf committed Oct 6, 2023
1 parent eb99509 commit 317f820
Show file tree
Hide file tree
Showing 4 changed files with 30 additions and 18 deletions.
4 changes: 2 additions & 2 deletions docs/api/puppeteer.filechooser.cancel.md
Original file line number Diff line number Diff line change
Expand Up @@ -10,10 +10,10 @@ Closes the file chooser without selecting any files.

```typescript
class FileChooser {
cancel(): void;
cancel(): Promise<void>;
}
```

**Returns:**

void
Promise&lt;void&gt;
35 changes: 21 additions & 14 deletions packages/puppeteer-core/src/cdp/ElementHandle.ts
Original file line number Diff line number Diff line change
Expand Up @@ -133,30 +133,37 @@ export class CdpElementHandle<
return path.resolve(filePath);
}
});
const {node} = await this.client.send('DOM.describeNode', {
objectId: this.id,
});
const {backendNodeId} = node;

/* 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.
/**
* 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}));
element.dispatchEvent(
new Event('input', {bubbles: true, composed: true})
);
element.dispatchEvent(new Event('change', {bubbles: true}));
});
} else {
await this.client.send('DOM.setFileInputFiles', {
objectId: this.id,
files,
backendNodeId,
});
return;
}

const {
node: {backendNodeId},
} = await this.client.send('DOM.describeNode', {
objectId: this.id,
});
await this.client.send('DOM.setFileInputFiles', {
objectId: this.id,
files,
backendNodeId,
});
}

@throwIfDisposed()
Expand Down
7 changes: 6 additions & 1 deletion packages/puppeteer-core/src/common/FileChooser.ts
Original file line number Diff line number Diff line change
Expand Up @@ -87,11 +87,16 @@ export class FileChooser {
/**
* Closes the file chooser without selecting any files.
*/
cancel(): void {
async cancel(): Promise<void> {
assert(
!this.#handled,
'Cannot cancel FileChooser which is already handled!'
);
this.#handled = true;
// XXX: These events should converted to trusted events. Perhaps do this
// in `DOM.setFileInputFiles`?
await this.#element.evaluate(element => {
element.dispatchEvent(new Event('cancel', {bubbles: true}));
});
}
}
2 changes: 1 addition & 1 deletion test/src/input.spec.ts
Original file line number Diff line number Diff line change
Expand Up @@ -358,7 +358,7 @@ describe('input tests', function () {
let error!: Error;

try {
fileChooser.cancel();
await fileChooser.cancel();
} catch (error_) {
error = error_ as Error;
}
Expand Down

0 comments on commit 317f820

Please sign in to comment.