Skip to content

Commit

Permalink
docs: update custom query handler
Browse files Browse the repository at this point in the history
  • Loading branch information
Lightning00Blade committed Aug 16, 2023
1 parent c6e5bb2 commit a6cbd1f
Show file tree
Hide file tree
Showing 2 changed files with 90 additions and 6 deletions.
93 changes: 90 additions & 3 deletions docs/guides/query-selectors.md → docs/guides/query-selectors.mdx
Original file line number Diff line number Diff line change
Expand Up @@ -133,10 +133,97 @@ const node = await page.waitForSelector(

Puppeteer provides users the ability to add their own query selectors to Puppeteer using [Puppeteer.registerCustomQueryHandler](../api/puppeteer.registercustomqueryhandler.md). This is useful for creating custom selectors based on framework objects or other vendor-specific objects.

#### Example
#### Basic Custom Selectors

An example of registration of a custom selector called `getById` selector:

```ts
Puppeteer.registerCustomQueryHandler('getById', {
queryOne: (elementOrDocument, selector) => {
if (
// elementOrDocument may be a Node
elementOrDocument instanceof Element ||
elementOrDocument instanceof Document
) {
return elementOrDocument.querySelector(`[id="${selector}"]`);
}
return null;
},
queryAll: (elementOrDocument, selector) => {
if (
// elementOrDocument may be a Node
elementOrDocument instanceof Element ||
elementOrDocument instanceof Document
) {
return elementOrDocument.querySelectorAll(`[id="${selector}"]`);
}
return [];
},
});
```

You can now use it in these ways:

```ts
const node = await page.waitForSelector('getById/elementId');
// OR
const node = await page.waitForSelector('::-p-getById(elementId)');
```

#### Custom framework components selector

:::caution

Internal library/framework methods can change and/or brake at anytime use with caution.

:::

Suppose you register a custom selector called `lit`. You can use it like so:
Framework example using `vue` and it's internals to find by component name:

```ts
const node = await page.waitForSelector('::-p-lit(LitElement)');
Puppeteer.registerCustomQueryHandler('vue', {
queryOne: (element, name) => {
const walker = document.createTreeWalker(element, NodeFilter.SHOW_ELEMENT);
do {
const currentNode = walker.currentNode;
if (
// @ts-ignore
currentNode.__vnode?.ctx?.type?.name.toLowerCase() ===
name.toLocaleLowerCase()
) {
return currentNode;
}
} while (walker.nextNode());

return null;
},
});
```

Then we can use as following:

```ts
const element = await page.$('vue/MyComponent');
// OR
const element = await page.$('::-p-vue(MyComponent)');
```

#### Web Components

Web Components create their own tag so you can just query them by default using:

```ts
const element = await page.$('my-web-component');
```

To add a some typehiting to your tests you can add the following typing:

```ts
declare global {
interface HTMLElementTagNameMap {
'my-web-component': MyWebComponent;
}
}
```

This will let Puppeteer infer the type from the query above.
3 changes: 0 additions & 3 deletions packages/puppeteer-core/src/common/CustomQueryHandler.ts
Original file line number Diff line number Diff line change
Expand Up @@ -83,9 +83,6 @@ export class CustomQueryHandlerRegistry {
* @internal
*/
register(name: string, handler: CustomQueryHandler): void {
if (this.#handlers.has(name)) {
throw new Error(`Cannot register over existing handler: ${name}`);
}
assert(
!this.#handlers.has(name),
`Cannot register over existing handler: ${name}`
Expand Down

0 comments on commit a6cbd1f

Please sign in to comment.