From fa61cc0bbea0ea4e26946adf40fc9066aaf7bed1 Mon Sep 17 00:00:00 2001 From: blakebyrnes Date: Tue, 31 Aug 2021 15:53:38 -0400 Subject: [PATCH] fix(core): sinceCommandId validation --- client/lib/DomExtender.ts | 12 ++++++------ core/lib/FrameNavigationsObserver.ts | 5 ++++- core/lib/Tab.ts | 21 +++++++++++++++------ 3 files changed, 25 insertions(+), 13 deletions(-) diff --git a/client/lib/DomExtender.ts b/client/lib/DomExtender.ts index a5fe3186d..dbe0cfb38 100644 --- a/client/lib/DomExtender.ts +++ b/client/lib/DomExtender.ts @@ -12,9 +12,9 @@ const { getState } = StateMachine(); interface IBaseExtend { $: { click: () => Promise; - type: () => Promise; + type: (...typeInteractions: ITypeInteraction[]) => Promise; waitForVisible: () => Promise; - } + }; } declare module 'awaited-dom/base/interfaces/super' { @@ -28,12 +28,12 @@ for (const Super of [SuperElement, SuperNode, SuperHTMLElement]) { get: function $() { const click = async (): Promise => { const { awaitedOptions } = getState(this); - const coreFrame = await awaitedOptions?.coreFrame + const coreFrame = await awaitedOptions?.coreFrame; await Interactor.run(coreFrame, [{ click: this }]); }; const type = async (...typeInteractions: ITypeInteraction[]): Promise => { const { awaitedOptions } = getState(this); - const coreFrame = await awaitedOptions?.coreFrame + const coreFrame = await awaitedOptions?.coreFrame; await click(); await Interactor.run( coreFrame, @@ -42,11 +42,11 @@ for (const Super of [SuperElement, SuperNode, SuperHTMLElement]) { }; const waitForVisible = async (): Promise => { const { awaitedPath, awaitedOptions } = getState(this); - const coreFrame = await awaitedOptions?.coreFrame + const coreFrame = await awaitedOptions?.coreFrame; await coreFrame.waitForElement(awaitedPath.toJSON(), { waitForVisible: true }); }; return { click, type, waitForVisible }; - } + }, }); } diff --git a/core/lib/FrameNavigationsObserver.ts b/core/lib/FrameNavigationsObserver.ts index c56dcf3e1..7d4a0cf23 100644 --- a/core/lib/FrameNavigationsObserver.ts +++ b/core/lib/FrameNavigationsObserver.ts @@ -60,7 +60,10 @@ export default class FrameNavigationsObserver { assert(LocationTrigger[status], `Invalid location status: ${status}`); // determine if this location trigger has already been satisfied - const sinceCommandId = Number(options.sinceCommandId ?? this.defaultWaitForLocationCommandId); + const sinceCommandId = Number.isInteger(options.sinceCommandId) + ? options.sinceCommandId + : this.defaultWaitForLocationCommandId; + if (this.hasLocationTrigger(status, sinceCommandId)) { return Promise.resolve(); } diff --git a/core/lib/Tab.ts b/core/lib/Tab.ts index 8a7175834..9a642fcc5 100644 --- a/core/lib/Tab.ts +++ b/core/lib/Tab.ts @@ -441,7 +441,9 @@ export default class Tab extends TypedEventEmitter { public async waitForNewTab(options: IWaitForOptions = {}): Promise { // last command is the one running right now - const startCommandId = options?.sinceCommandId ?? this.lastCommandId - 1; + const startCommandId = Number.isInteger(options.sinceCommandId) + ? options.sinceCommandId + : this.lastCommandId - 1; let newTab: Tab; const startTime = new Date(); if (startCommandId >= 0) { @@ -468,11 +470,15 @@ export default class Tab extends TypedEventEmitter { public async waitForResource( filter: IResourceFilterProperties, - opts?: IWaitForResourceOptions, + options?: IWaitForResourceOptions, ): Promise { - const timer = new Timer(opts?.timeoutMs ?? 60e3, this.waitTimeouts); + const timer = new Timer(options?.timeoutMs ?? 60e3, this.waitTimeouts); const resourceMetas: IResourceMeta[] = []; const promise = createPromise(); + const sinceCommandId = + options?.sinceCommandId && Number.isInteger(options.sinceCommandId) + ? options.sinceCommandId + : -1; const onResource = (resourceMeta: IResourceMeta) => { if (resourceMeta.tabId !== this.id) return; @@ -481,7 +487,7 @@ export default class Tab extends TypedEventEmitter { // need to set directly since passed in object is a copy this.sessionState.getResourceMeta(resourceMeta.id).seenAtCommandId = this.lastCommandId; } - if (resourceMeta.seenAtCommandId <= opts?.sinceCommandId ?? -1) return; + if (resourceMeta.seenAtCommandId <= sinceCommandId) return; if (filter.type && resourceMeta.type !== filter.type) return; if (filter.url) { if (typeof filter.url === 'string') { @@ -508,7 +514,7 @@ export default class Tab extends TypedEventEmitter { await timer.waitForPromise(promise.promise, 'Timeout waiting for DomContentLoaded'); } catch (err) { const isTimeout = err instanceof TimeoutError; - if (isTimeout && opts?.throwIfTimeout === false) { + if (isTimeout && options?.throwIfTimeout === false) { return resourceMetas; } throw err; @@ -521,7 +527,10 @@ export default class Tab extends TypedEventEmitter { } public async waitForFileChooser(options?: IWaitForOptions): Promise { - let startCommandId = options?.sinceCommandId; + let startCommandId = + options?.sinceCommandId && Number.isInteger(options.sinceCommandId) + ? options.sinceCommandId + : null; if (!startCommandId && this.sessionState.commands.length >= 2) { startCommandId = this.sessionState.commands[this.sessionState.commands.length - 2]?.id;