diff --git a/src/elementHandle.ts b/src/elementHandle.ts index 199c240..5fec084 100644 --- a/src/elementHandle.ts +++ b/src/elementHandle.ts @@ -1,3 +1,5 @@ +import { deadline } from "https://deno.land/std@0.198.0/async/deadline.ts"; + import { Celestial } from "../bindings/celestial.ts"; import { KeyboardTypeOptions } from "./keyboard.ts"; import { Page, ScreenshotOptions } from "./page.ts"; @@ -228,4 +230,28 @@ export class ElementHandle { await this.focus(); await this.#page.keyboard.type(text, opts); } + + /** + * Wait for an element matching the given selector to appear in the current element. + */ + async waitForSelector(selector: string) { + // TODO(lino-levan): Make this easier to read, it's a little scuffed + return await deadline( + (async () => { + while (true) { + const result = await this.#celestial.DOM.querySelector({ + nodeId: this.#id, + selector, + }); + + if (!result) { + continue; + } + + return new ElementHandle(result.nodeId, this.#celestial, this.#page); + } + })(), + this.#page.timeout, + ); + } } diff --git a/src/page.ts b/src/page.ts index ec69128..edbabf6 100644 --- a/src/page.ts +++ b/src/page.ts @@ -397,6 +397,23 @@ export class Page { ); } + /** + * Wait for the `selector` to appear in page. If at the moment of calling the method the `selector` already exists, the method will return immediately. If the `selector` doesn't appear after the timeout milliseconds of waiting, the function will throw. + * + * @example + * ```ts + * await page.waitForSelector(".class"); + * ``` + */ + async waitForSelector(selector: string) { + const doc = await retryDeadline( + this.#celestial.DOM.getDocument({ depth: 0 }), + this.timeout, + ); + const root = new ElementHandle(doc.root.nodeId, this.#celestial, this); + return root.waitForSelector(selector); + } + /** * Do not use if there is an alterate way of doing your thing * diff --git a/tests/wait_test.ts b/tests/wait_test.ts new file mode 100644 index 0000000..307d974 --- /dev/null +++ b/tests/wait_test.ts @@ -0,0 +1,16 @@ +import { launch } from "../mod.ts"; + +Deno.test("Wait for selector", async () => { + // Launch browser + const browser = await launch(); + + // Open the webpage + const page = await browser.newPage("http://deno.land"); + + // Wait for selector + const selected = await page.waitForSelector(".font-bold"); + console.log(selected); + + // Close browser + await browser.close(); +});