Skip to content

Commit

Permalink
fix: retry + deadline
Browse files Browse the repository at this point in the history
  • Loading branch information
lino-levan committed Aug 14, 2023
1 parent 03bedd2 commit 38a1a65
Show file tree
Hide file tree
Showing 4 changed files with 73 additions and 30 deletions.
42 changes: 41 additions & 1 deletion deno.lock

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

20 changes: 9 additions & 11 deletions src/elementHandle.ts
Original file line number Diff line number Diff line change
@@ -1,8 +1,7 @@
import { deadline } from "https://deno.land/[email protected]/async/deadline.ts";

import { Celestial } from "../bindings/celestial.ts";
import { KeyboardTypeOptions } from "./keyboard.ts";
import { Page, ScreenshotOptions } from "./page.ts";
import { retryDeadline } from "./util.ts";

export interface Offset {
x: number;
Expand Down Expand Up @@ -70,7 +69,7 @@ export class ElementHandle {
* ```
*/
async $(selector: string) {
const result = await deadline(
const result = await retryDeadline(
this.#celestial.DOM.querySelector({
nodeId: this.#id,
selector,
Expand All @@ -94,7 +93,7 @@ export class ElementHandle {
* ```
*/
async $$(selector: string) {
const result = await deadline(
const result = await retryDeadline(
this.#celestial.DOM.querySelectorAll({
nodeId: this.#id,
selector,
Expand Down Expand Up @@ -135,7 +134,7 @@ export class ElementHandle {
* This method returns boxes of the element, or `null` if the element is not visible.
*/
async boxModel(): Promise<BoxModel | null> {
const result = await deadline(
const result = await retryDeadline(
this.#celestial.DOM.getBoxModel({ nodeId: this.#id }),
this.#page.timeout,
);
Expand All @@ -161,10 +160,9 @@ export class ElementHandle {
*/
async click(opts?: { offset?: Offset }) {
await this.scrollIntoView();
let model: BoxModel | null;
do {
model = await this.boxModel();
} while (!model);

const model: BoxModel | null = await this.boxModel();
if (!model) throw new Error("Unable to get stable box model to click on");

const { x, y } = getTopLeft(model.content);

Expand All @@ -185,7 +183,7 @@ export class ElementHandle {
* Calls `focus` on the element.
*/
async focus() {
await deadline(
await retryDeadline(
this.#celestial.DOM.focus({ nodeId: this.#id }),
this.#page.timeout,
);
Expand Down Expand Up @@ -217,7 +215,7 @@ export class ElementHandle {
* Scrolls the element into view using the automation protocol client.
*/
async scrollIntoView() {
await deadline(
await retryDeadline(
this.#celestial.DOM.scrollIntoViewIfNeeded({ nodeId: this.#id }),
this.#page.timeout,
);
Expand Down
34 changes: 16 additions & 18 deletions src/page.ts
Original file line number Diff line number Diff line change
@@ -1,9 +1,7 @@
import { deadline } from "https://deno.land/[email protected]/async/deadline.ts";

import { Celestial, Network_Cookie } from "../bindings/celestial.ts";
import { Browser } from "./browser.ts";
import { ElementHandle } from "./elementHandle.ts";
import { BASE_URL, convertToUint8Array } from "./util.ts";
import { BASE_URL, convertToUint8Array, retryDeadline } from "./util.ts";
import { Mouse } from "./mouse.ts";
import { Keyboard } from "./keyboard.ts";
import { Touchscreen } from "./touchscreen.ts";
Expand Down Expand Up @@ -73,7 +71,7 @@ export class Page {
* ```
*/
async $(selector: string) {
const doc = await deadline(
const doc = await retryDeadline(
this.#celestial.DOM.getDocument({ depth: 0 }),
this.timeout,
);
Expand All @@ -90,12 +88,12 @@ export class Page {
* ```
*/
async $$(selector: string) {
const doc = await deadline(
const doc = await retryDeadline(
this.#celestial.DOM.getDocument({ depth: 0 }),
this.timeout,
);
const root = new ElementHandle(doc.root.nodeId, this.#celestial, this);
return deadline(root.$$(selector), this.timeout);
return retryDeadline(root.$$(selector), this.timeout);
}

/**
Expand All @@ -107,7 +105,7 @@ export class Page {
* ```
*/
async bringToFront() {
await deadline(this.#celestial.Page.bringToFront(), this.timeout);
await retryDeadline(this.#celestial.Page.bringToFront(), this.timeout);
}

/**
Expand Down Expand Up @@ -142,7 +140,7 @@ export class Page {
*/
async content(): Promise<string> {
// https://stackoverflow.com/questions/6088972/get-doctype-of-an-html-as-string-with-javascript
const { result } = await deadline(
const { result } = await retryDeadline(
this.#celestial.Runtime.evaluate({
expression:
`"<!DOCTYPE " + document.doctype.name + (document.doctype.publicId ? ' PUBLIC "' + document.doctype.publicId + '"' : '') + (!document.doctype.publicId && document.doctype.systemId ? ' SYSTEM' : '') + (document.doctype.systemId ? ' "' + document.doctype.systemId + '"' : '') + '>\\n' + document.documentElement.outerHTML`,
Expand All @@ -157,7 +155,7 @@ export class Page {
* If no URLs are specified, this method returns cookies for the current page URL. If URLs are specified, only cookies for those URLs are returned.
*/
async cookies(...urls: string[]): Promise<Cookie[]> {
const result = await deadline(
const result = await retryDeadline(
this.#celestial.Network.getCookies({ urls }),
this.timeout,
);
Expand All @@ -168,7 +166,7 @@ export class Page {
* Deletes browser cookies with matching name and url or domain/path pair.
*/
async deleteCookies(cookieDescription: DeleteCookieOptions) {
await deadline(
await retryDeadline(
this.#celestial.Network.deleteCookies(cookieDescription),
this.timeout,
);
Expand All @@ -180,7 +178,7 @@ export class Page {
* Enables CPU throttling to emulate slow CPUs.
*/
async emulateCPUThrottling(factor: number) {
await deadline(
await retryDeadline(
this.#celestial.Emulation.setCPUThrottlingRate({ rate: factor }),
this.timeout,
);
Expand All @@ -199,7 +197,7 @@ export class Page {
if (typeof func === "function") {
func = `(${func.toString()})()`;
}
const { result, exceptionDetails } = await deadline(
const { result, exceptionDetails } = await retryDeadline(
this.#celestial.Runtime.evaluate({
expression: func,
awaitPromise: true,
Expand Down Expand Up @@ -245,7 +243,7 @@ export class Page {
async goto(url: string, options?: GoToOptions) {
options = options ?? {};
await Promise.all([
deadline(
retryDeadline(
this.#celestial.Page.navigate({ url, ...options }),
this.timeout,
),
Expand All @@ -264,7 +262,7 @@ export class Page {
*/
async pdf(opts?: PdfOptions): Promise<Uint8Array> {
opts = opts ?? {};
const { data } = await deadline(
const { data } = await retryDeadline(
this.#celestial.Page.printToPDF(opts),
this.timeout,
);
Expand All @@ -281,7 +279,7 @@ export class Page {
*/
async reload(options?: WaitForOptions) {
await Promise.all([
deadline(this.#celestial.Page.reload({}), this.timeout),
retryDeadline(this.#celestial.Page.reload({}), this.timeout),
this.waitForNavigation(options),
]);
}
Expand All @@ -297,7 +295,7 @@ export class Page {
*/
async screenshot(opts?: ScreenshotOptions) {
opts = opts ?? {};
const { data } = await deadline(
const { data } = await retryDeadline(
this.#celestial.Page.captureScreenshot(opts),
this.timeout,
);
Expand All @@ -314,7 +312,7 @@ export class Page {
await this.waitForNavigation({ waitUntil: "load" });
}

return deadline(
return retryDeadline(
new Promise<void>((resolve) => {
if (options?.waitUntil === "load") {
const callback = () => {
Expand Down Expand Up @@ -345,7 +343,7 @@ export class Page {
const idleTime = options?.idleTime ?? 500;
const idleConnections = options?.idleConnections ?? 0;

return deadline(
return retryDeadline(
new Promise<void>((resolve) => {
const timeoutDone = () => {
this.#celestial.removeEventListener(
Expand Down
7 changes: 7 additions & 0 deletions src/util.ts
Original file line number Diff line number Diff line change
@@ -1,3 +1,6 @@
import { deadline } from "https://deno.land/[email protected]/async/deadline.ts";
import { retry } from "https://deno.land/[email protected]/async/retry.ts";

export const BASE_URL = "http://localhost:9222";

export async function websocketReady(ws: WebSocket) {
Expand All @@ -12,3 +15,7 @@ export function convertToUint8Array(data: string) {
const byteString = atob(data);
return new Uint8Array([...byteString].map((ch) => ch.charCodeAt(0)));
}

export function retryDeadline<T>(t: Promise<T>, timeout: number): Promise<T> {
return retry<T>(() => deadline(t, timeout));
}

0 comments on commit 38a1a65

Please sign in to comment.