Skip to content

Commit

Permalink
Document how chain works in BrowserInterface and chain to `browser.ev…
Browse files Browse the repository at this point in the history
…al` (#44085)

Co-authored-by: kodiakhq[bot] <49736102+kodiakhq[bot]@users.noreply.github.com>
  • Loading branch information
jankaifer and kodiakhq[bot] committed Dec 20, 2022
1 parent f6cba80 commit 6640846
Show file tree
Hide file tree
Showing 2 changed files with 45 additions and 20 deletions.
35 changes: 30 additions & 5 deletions test/lib/browsers/base.ts
@@ -1,11 +1,18 @@
export type Event = 'request'

// This is the base Browser interface all browser
// classes should build off of, it is the bare
// methods we aim to support across tests
export class BrowserInterface {
/**
* This is the base Browser interface all browser
* classes should build off of, it is the bare
* methods we aim to support across tests
*
* They will always await last executed command.
* The interface is mutable - it doesn't have to be in sequece.
*
* You can manually await this interface to wait for completion of the last scheduled command.
*/
export class BrowserInterface implements PromiseLike<any> {
private promise: any
private then: any
then: PromiseLike<any>['then']
private catch: any

protected chain(nextCall: any): BrowserInterface {
Expand All @@ -18,6 +25,24 @@ export class BrowserInterface {
return this
}

/**
* This function will run in chain - it will wait for previous commands.
* But it won't have an effect on chain value and chain will still be green if this throws.
*/
protected chainWithReturnValue<T>(
callback: (...args: any[]) => Promise<T>
): Promise<T> {
return new Promise<T>((resolve, reject) => {
this.chain(async (...args: any[]) => {
try {
resolve(await callback(...args))
} catch (error) {
reject(error)
}
})
})
}

async setup(browserName: string, locale?: string): Promise<void> {}
async close(): Promise<void> {}
async quit(): Promise<void> {}
Expand Down
30 changes: 15 additions & 15 deletions test/lib/browsers/playwright.ts
Expand Up @@ -281,8 +281,8 @@ export class Playwright extends BrowserInterface {
return this.chain((el) => el.getAttribute(attr))
}

async hasElementByCssSelector(selector: string) {
return this.eval(`!!document.querySelector('${selector}')`) as any
hasElementByCssSelector(selector: string) {
return this.eval<boolean>(`!!document.querySelector('${selector}')`)
}

keydown(key: string): BrowserInterface {
Expand Down Expand Up @@ -344,19 +344,19 @@ export class Playwright extends BrowserInterface {
})
}

async eval(snippet) {
// TODO: should this and evalAsync be chained? Might lead
// to bad chains
return page
.evaluate(snippet)
.catch((err) => {
console.error('eval error:', err)
return null
})
.then(async (val) => {
await page.waitForLoadState()
return val
})
eval<T = any>(snippet): Promise<T> {
return this.chainWithReturnValue(() =>
page
.evaluate(snippet)
.catch((err) => {
console.error('eval error:', err)
return null
})
.then(async (val) => {
await page.waitForLoadState()
return val as T
})
)
}

async evalAsync(snippet) {
Expand Down

0 comments on commit 6640846

Please sign in to comment.