Skip to content

Commit

Permalink
feat(core): timeouts for back/fwd/goto, add reload
Browse files Browse the repository at this point in the history
  • Loading branch information
blakebyrnes committed Jan 19, 2021
1 parent faaef19 commit bae2a8e
Show file tree
Hide file tree
Showing 19 changed files with 191 additions and 92 deletions.
20 changes: 10 additions & 10 deletions client/lib/Agent.ts
Expand Up @@ -224,16 +224,20 @@ export default class Agent extends AwaitedEventTarget<{ close: void }> {

/////// METHODS THAT DELEGATE TO ACTIVE TAB //////////////////////////////////////////////////////////////////////////

public goto(href: string): Promise<Resource> {
return this.activeTab.goto(href);
public goto(href: string, timeoutMs?: number): Promise<Resource> {
return this.activeTab.goto(href, timeoutMs);
}

public goBack(): Promise<string> {
return this.activeTab.goBack();
public goBack(timeoutMs?: number): Promise<string> {
return this.activeTab.goBack(timeoutMs);
}

public goForward(): Promise<string> {
return this.activeTab.goForward();
public goForward(timeoutMs?: number): Promise<string> {
return this.activeTab.goForward(timeoutMs);
}

public reload(timeoutMs?: number): Promise<void> {
return this.activeTab.reload(timeoutMs);
}

public fetch(request: Request | string, init?: IRequestInit): Promise<Response> {
Expand Down Expand Up @@ -275,10 +279,6 @@ export default class Agent extends AwaitedEventTarget<{ close: void }> {
return this.activeTab.waitForMillis(millis);
}

public waitForWebSocket(url: string | RegExp): Promise<void> {
return this.activeTab.waitForWebSocket(url);
}

/////// THENABLE ///////////////////////////////////////////////////////////////////////////////////////////////////

public then<TResult1 = Agent, TResult2 = never>(
Expand Down
20 changes: 10 additions & 10 deletions client/lib/CoreTab.ts
Expand Up @@ -77,16 +77,20 @@ export default class CoreTab implements IJsPathEventTarget {
return await this.commandQueue.run('getLocationHref');
}

public async goto(href: string): Promise<IResourceMeta> {
return await this.commandQueue.run('goto', href);
public async goto(href: string, timeoutMs?: number): Promise<IResourceMeta> {
return await this.commandQueue.run('goto', href, timeoutMs);
}

public async goBack(): Promise<string> {
return await this.commandQueue.run('goBack');
public async goBack(timeoutMs?: number): Promise<string> {
return await this.commandQueue.run('goBack', timeoutMs);
}

public async goForward(): Promise<string> {
return await this.commandQueue.run('goForward');
public async goForward(timeoutMs?: number): Promise<string> {
return await this.commandQueue.run('goForward', timeoutMs);
}

public async reload(timeoutMs?: number): Promise<void> {
return await this.commandQueue.run('reload', timeoutMs);
}

public async interact(interactionGroups: IInteractionGroups): Promise<void> {
Expand Down Expand Up @@ -140,10 +144,6 @@ export default class CoreTab implements IJsPathEventTarget {
await this.commandQueue.run('waitForMillis', millis);
}

public async waitForWebSocket(url: string | RegExp): Promise<void> {
await this.commandQueue.run('waitForWebSocket', url);
}

public async waitForNewTab(opts: IWaitForOptions): Promise<CoreTab> {
const sessionMeta = await this.commandQueue.run<ISessionMeta>('waitForNewTab', opts);
const session = this.connection.getSession(sessionMeta.sessionId);
Expand Down
22 changes: 11 additions & 11 deletions client/lib/Tab.ts
Expand Up @@ -129,20 +129,25 @@ export default class Tab extends AwaitedEventTarget<IEventType> {
) as CSSStyleDeclaration;
}

public async goto(href: string): Promise<Resource> {
public async goto(href: string, timeoutMs?: number): Promise<Resource> {
const coreTab = await getCoreTab(this);
const resource = await coreTab.goto(href);
const resource = await coreTab.goto(href, timeoutMs);
return createResource(resource, Promise.resolve(coreTab));
}

public async goBack(): Promise<string> {
public async goBack(timeoutMs?: number): Promise<string> {
const coreTab = await getCoreTab(this);
return coreTab.goBack();
return coreTab.goBack(timeoutMs);
}

public async goForward(): Promise<string> {
public async goForward(timeoutMs?: number): Promise<string> {
const coreTab = await getCoreTab(this);
return coreTab.goForward();
return coreTab.goForward(timeoutMs);
}

public async reload(timeoutMs?: number): Promise<void> {
const coreTab = await getCoreTab(this);
return coreTab.reload(timeoutMs);
}

public async getJsValue<T>(path: string): Promise<{ value: T; type: string }> {
Expand Down Expand Up @@ -195,11 +200,6 @@ export default class Tab extends AwaitedEventTarget<IEventType> {
await coreTab.waitForMillis(millis);
}

public async waitForWebSocket(url: string | RegExp): Promise<void> {
const coreTab = await getCoreTab(this);
await coreTab.waitForWebSocket(url);
}

public focus(): Promise<void> {
const { secretAgent, coreTab } = getState(this);
agentState.getState(secretAgent).connection.activeTab = this;
Expand Down
5 changes: 3 additions & 2 deletions commons/Timer.ts
Expand Up @@ -10,8 +10,9 @@ export default class Timer {
private readonly expirePromise = createPromise();

constructor(readonly timeoutMillis: number, readonly registry?: IRegistry[]) {
this.timeout = setTimeout(this.expire.bind(this), timeoutMillis).unref();
if (registry) {
this.timeout =
timeoutMillis > 0 ? setTimeout(this.expire.bind(this), timeoutMillis).unref() : null;
if (registry && this.timeout) {
registry.push({ reject: this.expirePromise.reject, timeout: this.timeout });
}
}
Expand Down
2 changes: 1 addition & 1 deletion core/lib/LocationTracker.ts
Expand Up @@ -96,7 +96,7 @@ export default class LocationTracker {
}
}

const resolvablePromise = createPromise<void>(options.timeoutMs);
const resolvablePromise = createPromise<void>(options.timeoutMs ?? 30e3);
this.waitForCbs[status].push(resolvablePromise);
return resolvablePromise.promise;
}
Expand Down
40 changes: 33 additions & 7 deletions core/lib/Tab.ts
Expand Up @@ -128,6 +128,7 @@ export default class Tab extends TypedEventEmitter<ITabEventParams> {
this.goto,
this.goBack,
this.goForward,
this.reload,
this.getCookies,
this.getJsValue,
this.getLocationHref,
Expand Down Expand Up @@ -252,7 +253,7 @@ export default class Tab extends TypedEventEmitter<ITabEventParams> {

/////// COMMANDS /////////////////////////////////////////////////////////////////////////////////////////////////////

public async goto(url: string): Promise<IResourceMeta> {
public async goto(url: string, timeoutMs = 30e3): Promise<IResourceMeta> {
const formattedUrl = Url.format(url);

this.navigationTracker.navigationRequested(
Expand All @@ -262,24 +263,49 @@ export default class Tab extends TypedEventEmitter<ITabEventParams> {
this.lastCommandId,
);

await this.puppetPage.navigate(formattedUrl);
const timeoutMessage = `Timeout waiting for "tab.goto(${url})"`;

const resource = await this.locationTracker.waitForLocationResourceId();
const timer = new Timer(timeoutMs, this.waitTimeouts);
await timer.waitForPromise(this.puppetPage.navigate(formattedUrl), timeoutMessage);

const resource = await timer.waitForPromise(
this.locationTracker.waitForLocationResourceId(),
timeoutMessage,
);
return this.sessionState.getResourceMeta(resource);
}

public async goBack(): Promise<string> {
public async goBack(timeoutMs?: number): Promise<string> {
await this.puppetPage.goBack();
await this.locationTracker.waitFor('AllContentLoaded');
await this.locationTracker.waitFor('AllContentLoaded', { timeoutMs });
return this.navigationTracker.currentUrl;
}

public async goForward(): Promise<string> {
public async goForward(timeoutMs?: number): Promise<string> {
await this.puppetPage.goForward();
await this.locationTracker.waitFor('AllContentLoaded');
await this.locationTracker.waitFor('AllContentLoaded', { timeoutMs });
return this.navigationTracker.currentUrl;
}

public async reload(timeoutMs?: number): Promise<IResourceMeta> {
this.navigationTracker.navigationRequested(
'reload',
this.navigationTracker.currentUrl,
this.mainFrameId,
this.lastCommandId,
);

const timer = new Timer(timeoutMs, this.waitTimeouts);
const timeoutMessage = `Timeout waiting for "tab.reload()"`;

await timer.waitForPromise(this.puppetPage.reload(), timeoutMessage);
const resource = await timer.waitForPromise(
this.locationTracker.waitForLocationResourceId(),
timeoutMessage,
);
return this.sessionState.getResourceMeta(resource);
}

public async interact(...interactionGroups: IInteractionGroups): Promise<void> {
await this.locationTracker.waitFor('READY');
await this.interactor.play(interactionGroups);
Expand Down

0 comments on commit bae2a8e

Please sign in to comment.