Skip to content
This repository was archived by the owner on Aug 6, 2025. It is now read-only.

Commit 0fa0305

Browse files
committed
refactor: modify library integration to work with Playwright API
1 parent 84004d1 commit 0fa0305

File tree

6 files changed

+37
-58
lines changed

6 files changed

+37
-58
lines changed

lib/extend.ts

Lines changed: 5 additions & 23 deletions
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,5 @@
1-
import {ElementHandle} from 'puppeteer'
2-
31
import {getDocument, getQueriesForElement} from '.'
4-
import {IScopedQueryUtils} from './typedefs'
2+
import {ElementHandle, IScopedQueryUtils} from './typedefs'
53

64
// tslint:disable-next-line
75
let Page, ElementHandle
@@ -13,26 +11,10 @@ function requireOrUndefined(path: string): any {
1311
}
1412

1513
try {
16-
Page = require('puppeteer/lib/Page.js') // tslint:disable-line
14+
Page = require('playwright-core/lib/page.js') // tslint:disable-line
1715
if (Page.Page) Page = Page.Page
1816

19-
ElementHandle = requireOrUndefined('puppeteer/lib/ElementHandle.js') // tslint:disable-line variable-name
20-
if (ElementHandle && ElementHandle.ElementHandle) ElementHandle = ElementHandle.ElementHandle
21-
22-
if (!ElementHandle) {
23-
const ExecutionContext = requireOrUndefined('puppeteer/lib/ExecutionContext.js') // tslint:disable-line variable-name
24-
if (ExecutionContext && ExecutionContext.ElementHandle) {
25-
ElementHandle = ExecutionContext.ElementHandle
26-
}
27-
}
28-
if (ElementHandle && ElementHandle.ElementHandle) ElementHandle = ElementHandle.ElementHandle
29-
30-
if (!ElementHandle) {
31-
const JSHandle = require('puppeteer/lib/JSHandle.js') // tslint:disable-line
32-
if (JSHandle && JSHandle.ElementHandle) {
33-
ElementHandle = JSHandle.ElementHandle
34-
}
35-
}
17+
ElementHandle = requireOrUndefined('playwright-core/lib/api.js') // tslint:disable-line variable-name
3618
if (ElementHandle && ElementHandle.ElementHandle) ElementHandle = ElementHandle.ElementHandle
3719

3820
Page.prototype.getDocument = getDocument
@@ -45,12 +27,12 @@ try {
4527
}
4628
} catch (err) {
4729
// tslint:disable-next-line
48-
console.error('Could not augment puppeteer functions, do you have a conflicting version?')
30+
console.error('Could not augment playwright functions, do you have a conflicting version?')
4931
throw err
5032
}
5133

5234
/* tslint:disable */
53-
declare module 'puppeteer' {
35+
declare module 'playwright-core/types/types' {
5436
interface Page {
5537
getDocument(): Promise<ElementHandle>
5638
}

lib/index.ts

Lines changed: 11 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -1,9 +1,9 @@
11
import {readFileSync} from 'fs'
22
import * as path from 'path'
3-
import {ElementHandle, EvaluateFn, JSHandle, Page} from 'puppeteer'
3+
import {JSHandle, Page} from 'playwright'
44
import waitForExpect from 'wait-for-expect'
55

6-
import {IQueryUtils, IScopedQueryUtils} from './typedefs'
6+
import {ElementHandle, IQueryUtils, IScopedQueryUtils} from './typedefs'
77

88
const domLibraryAsString = readFileSync(
99
path.join(__dirname, '../dom-testing-library.js'),
@@ -33,7 +33,7 @@ type ContextFn = (...args: any[]) => ElementHandle
3333

3434
async function createElementHandleArray(handle: JSHandle): Promise<ElementHandle[]> {
3535
const lengthHandle = await handle.getProperty('length')
36-
const length = await lengthHandle.jsonValue() as number
36+
const length = (await lengthHandle.jsonValue()) as number
3737

3838
const elements: ElementHandle[] = []
3939
for (let i = 0; i < length; i++) {
@@ -57,18 +57,14 @@ async function covertToElementHandle(handle: JSHandle, asArray: boolean): Promis
5757
}
5858

5959
function processNodeText(handles: IHandleSet): Promise<string> {
60-
return handles.containerHandle
61-
.executionContext()
62-
.evaluate(handles.evaluateFn, handles.containerHandle, 'getNodeText')
60+
return handles.containerHandle.evaluate(handles.evaluateFn, ['getNodeText'])
6361
}
6462

6563
async function processQuery(handles: IHandleSet): Promise<DOMReturnType> {
6664
const {containerHandle, evaluateFn, fnName, argsToForward} = handles
6765

6866
try {
69-
const handle = await containerHandle
70-
.executionContext()
71-
.evaluateHandle(evaluateFn, containerHandle, fnName, ...argsToForward)
67+
const handle = await containerHandle.evaluateHandle(evaluateFn, [fnName, ...argsToForward])
7268
return await covertToElementHandle(handle, fnName.includes('All'))
7369
} catch (err) {
7470
err.message = err.message.replace('[fnName]', `[${fnName}]`)
@@ -79,7 +75,10 @@ async function processQuery(handles: IHandleSet): Promise<DOMReturnType> {
7975

8076
interface IHandleSet {
8177
containerHandle: ElementHandle
82-
evaluateFn: EvaluateFn
78+
// FIXME: Playwright doesn't expose a type for this like Puppeteer does with
79+
// `EvaluateFn`. This *should* be something like the `PageFunction` type that
80+
// is unfortunately not exported from the Playwright modules.
81+
evaluateFn: any
8382
fnName: string
8483
argsToForward: any[]
8584
}
@@ -97,11 +96,9 @@ function createDelegateFor<T = DOMReturnType>(
9796
return async function(...args: any[]): Promise<T> {
9897
// @ts-ignore
9998
const containerHandle: ElementHandle = contextFn ? contextFn.apply(this, args) : this
99+
100100
// @ts-ignore
101-
const evaluateFn: EvaluateFn = new Function(
102-
'container, fnName, ...args',
103-
delegateFnBodyToExecuteInPage,
104-
)
101+
const evaluateFn = new Function('container, [fnName, ...args]', delegateFnBodyToExecuteInPage)
105102

106103
// Convert RegExp to a special format since they don't serialize well
107104
let argsToForward = args.map(arg => (arg instanceof RegExp ? convertRegExp(arg) : arg))

lib/typedefs.ts

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,7 @@
11
import {Matcher, MatcherOptions, SelectorMatcherOptions} from '@testing-library/dom'
2-
import {ElementHandle} from 'puppeteer'
2+
import {ElementHandle as PlaywrightElementHandle} from 'playwright'
3+
4+
export type ElementHandle = PlaywrightElementHandle<SVGElement | HTMLElement>
35

46
type Element = ElementHandle
57

test/__snapshots__/extend.test.ts.snap

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -3,7 +3,7 @@
33
exports[`lib/extend.ts should handle the LabelText methods 1`] = `"<input id=\\"label-text-input\\" type=\\"text\\">"`;
44
55
exports[`lib/extend.ts should handle the get* method failures 1`] = `
6-
"Evaluation failed: Error: Unable to find an element with the title: missing.
6+
"Evaluation failed: TestingLibraryElementError: Unable to find an element with the title: missing.
77
88
<div
99
id=\\"scoped\\"

test/extend.test.ts

Lines changed: 12 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -1,22 +1,22 @@
11
import * as path from 'path'
2-
import * as puppeteer from 'puppeteer'
2+
import * as playwright from 'playwright'
33

44
describe('lib/extend.ts', () => {
5-
let browser: puppeteer.Browser
6-
let page: puppeteer.Page
7-
let document: puppeteer.ElementHandle
5+
let browser: playwright.ChromiumBrowser
6+
let page: playwright.Page
7+
let document: playwright.ElementHandle
88

99
it('should require without error', async () => {
1010
await import('../lib/extend')
1111
})
1212

13-
it('should launch puppeteer', async () => {
14-
browser = await puppeteer.launch({args: ['--no-sandbox', '--disable-setuid-sandbox']})
13+
it('should launch playwright', async () => {
14+
browser = await playwright.chromium.launch({args: ['--no-sandbox', '--disable-setuid-sandbox']})
1515
page = await browser.newPage()
1616
await page.goto(`file://${path.join(__dirname, 'fixtures/page.html')}`)
1717
})
1818

19-
it('should extend puppeteer ElementHandle', async () => {
19+
it('should extend playwright ElementHandle', async () => {
2020
document = await page.getDocument()
2121
expect(typeof document.queryAllByAltText).toBe('function')
2222
})
@@ -25,21 +25,21 @@ describe('lib/extend.ts', () => {
2525
const element = await document.queryByText('Hello h1')
2626
expect(element).toBeTruthy()
2727
/* istanbul ignore next */
28-
expect(await page.evaluate(el => el.textContent, element)).toEqual('Hello h1')
28+
expect(await page.evaluate(el => el?.textContent, element)).toEqual('Hello h1')
2929
})
3030

3131
it('should use the new v3 methods', async () => {
3232
const element = await document.queryByRole('presentation')
3333
expect(element).toBeTruthy()
3434
/* istanbul ignore next */
35-
expect(await page.evaluate(el => el.textContent, element)).toContain('Layout table')
35+
expect(await page.evaluate(el => el?.textContent, element)).toContain('Layout table')
3636
})
3737

3838
it('should handle regex matching', async () => {
3939
const element = await document.queryByText(/HeLlO h(1|7)/i)
4040
expect(element).toBeTruthy()
4141
/* istanbul ignore next */
42-
expect(await page.evaluate(el => el.textContent, element)).toEqual('Hello h1')
42+
expect(await page.evaluate(el => el?.textContent, element)).toEqual('Hello h1')
4343
})
4444

4545
it('should handle the get* methods', async () => {
@@ -56,9 +56,7 @@ describe('lib/extend.ts', () => {
5656
await scope!.getByTitle('missing')
5757
fail()
5858
} catch (err) {
59-
err.message = err.message
60-
.replace(/(\s*at .*(\n|$))+/gm, '\n <stack>:X:X')
61-
.replace('TestingLibraryElementError', 'Error') // Puppeteer 1.7 returns a generic error
59+
err.message = err.message.replace(/(\s*at .*(\n|$))+/gm, '\n <stack>:X:X')
6260
expect(err.message).toMatchSnapshot()
6361
}
6462
})
@@ -86,7 +84,7 @@ describe('lib/extend.ts', () => {
8684
const scope = await document.$('#scoped')
8785
const element = await scope!.queryByText(/Hello/)
8886
/* istanbul ignore next */
89-
expect(await page.evaluate(el => el.textContent, element)).toEqual('Hello h3')
87+
expect(await page.evaluate(el => el?.textContent, element)).toEqual('Hello h3')
9088
})
9189

9290
it('should get text content', async () => {

test/index.test.ts

Lines changed: 5 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -1,13 +1,13 @@
11
import * as path from 'path'
2-
import * as puppeteer from 'puppeteer'
2+
import * as playwright from 'playwright'
33
import {getDocument, queries, getQueriesForElement, wait} from '../lib'
44

55
describe('lib/index.ts', () => {
6-
let browser: puppeteer.Browser
7-
let page: puppeteer.Page
6+
let browser: playwright.Browser
7+
let page: playwright.Page
88

9-
it('should launch puppeteer', async () => {
10-
browser = await puppeteer.launch({args: ['--no-sandbox', '--disable-setuid-sandbox']})
9+
it('should launch playwright', async () => {
10+
browser = await playwright.chromium.launch({args: ['--no-sandbox', '--disable-setuid-sandbox']})
1111
page = await browser.newPage()
1212
await page.goto(`file://${path.join(__dirname, 'fixtures/page.html')}`)
1313
})

0 commit comments

Comments
 (0)