From 5752a28f877c09301b9a465fb94d8729f2750051 Mon Sep 17 00:00:00 2001 From: Pavel Feldman Date: Mon, 23 Oct 2023 09:31:30 -0700 Subject: [PATCH] chore: make tests strict (1) (#27731) --- tests/android/android.spec.ts | 2 +- tests/android/androidTest.ts | 2 +- tests/android/device.spec.ts | 2 +- tests/android/launch-server.spec.ts | 10 +- tests/android/playwright.config.ts | 4 +- tests/config/baseTest.ts | 2 +- tests/config/browserTest.ts | 2 +- tests/config/commonFixtures.ts | 14 +- tests/config/remoteServer.ts | 29 ++- tests/library/browser.spec.ts | 4 +- .../browsercontext-add-cookies.spec.ts | 10 +- .../browsercontext-add-init-script.spec.ts | 30 ++-- tests/library/browsercontext-base-url.spec.ts | 24 +-- tests/library/browsercontext-basic.spec.ts | 9 +- .../browsercontext-credentials.spec.ts | 24 +-- tests/library/browsercontext-device.spec.ts | 8 +- tests/library/browsercontext-events.spec.ts | 6 +- .../browsercontext-expose-function.spec.ts | 17 +- tests/library/browsercontext-fetch.spec.ts | 10 +- tests/library/browsercontext-har.spec.ts | 10 +- .../browsercontext-network-event.spec.ts | 15 +- tests/library/browsercontext-pages.spec.ts | 14 +- tests/library/browsercontext-route.spec.ts | 27 +-- .../browsercontext-viewport-mobile.spec.ts | 10 +- tests/library/chromium/oopif.spec.ts | 51 +++--- tests/library/har.spec.ts | 64 +++---- tests/library/inspector/cli-codegen-1.spec.ts | 162 ++++++++--------- tests/library/inspector/cli-codegen-2.spec.ts | 140 +++++++-------- tests/library/inspector/cli-codegen-3.spec.ts | 166 +++++++++--------- tests/library/inspector/console-api.spec.ts | 2 +- tests/library/inspector/pause.spec.ts | 16 +- tests/library/slowmo.spec.ts | 12 +- tests/page/page-wait-for-selector-1.spec.ts | 29 +-- tests/page/page-wait-for-selector-2.spec.ts | 48 ++--- tests/page/retarget.spec.ts | 33 ++-- tests/page/selectors-css.spec.ts | 21 +-- 36 files changed, 518 insertions(+), 511 deletions(-) diff --git a/tests/android/android.spec.ts b/tests/android/android.spec.ts index 7b78258f3f..1142551d3c 100644 --- a/tests/android/android.spec.ts +++ b/tests/android/android.spec.ts @@ -24,7 +24,7 @@ test('androidDevice.close', async function({ playwright }) { const devices = await playwright._android.devices(); expect(devices.length).toBe(1); const device = devices[0]; - const events = []; + const events: string[] = []; device.on('close', () => events.push('close')); await device.close(); await device.close(); diff --git a/tests/android/androidTest.ts b/tests/android/androidTest.ts index 20a46087f4..4a30894cd5 100644 --- a/tests/android/androidTest.ts +++ b/tests/android/androidTest.ts @@ -38,7 +38,7 @@ export const androidTest = baseTest.extend line.includes('versionName=')) + .find(line => line.includes('versionName='))! .trim() .split('=')[1]; await run(browserVersion); diff --git a/tests/android/device.spec.ts b/tests/android/device.spec.ts index 6ae375a987..1288e7320b 100644 --- a/tests/android/device.spec.ts +++ b/tests/android/device.spec.ts @@ -28,7 +28,7 @@ test('androidDevice.open', async function({ androidDevice }) { const socket = await androidDevice.open('shell:/bin/cat'); await socket.write(Buffer.from('321\n')); const output = await new Promise(resolve => socket.on('data', resolve)); - expect(output.toString()).toBe('321\n'); + expect(output!.toString()).toBe('321\n'); const closedPromise = new Promise(resolve => socket.on('close', resolve)); await socket.close(); await closedPromise; diff --git a/tests/android/launch-server.spec.ts b/tests/android/launch-server.spec.ts index 3593f668bc..4166e098a3 100644 --- a/tests/android/launch-server.spec.ts +++ b/tests/android/launch-server.spec.ts @@ -31,7 +31,7 @@ test('android.launchServer should connect to a device', async ({ playwright }) = }); test('android.launchServer should handle close event correctly', async ({ playwright }) => { - const receivedEvents = []; + const receivedEvents: string[] = []; const browserServer = await playwright._android.launchServer(); const device = await playwright._android.connect(browserServer.wsEndpoint()); device.on('close', () => receivedEvents.push('device')); @@ -116,7 +116,7 @@ test('android.launchServer BrowserServer.kill() will disconnect the device', as test('android.launchServer should terminate WS connection when device gets disconnected', async ({ playwright }) => { const browserServer = await playwright._android.launchServer(); const forwardingServer = new ws.Server({ port: 0, path: '/connect' }); - let receivedConnection: ws.WebSocket; + let receivedConnection: ws.WebSocket | undefined; forwardingServer.on('connection', connection => { receivedConnection = connection; const actualConnection = new ws.WebSocket(browserServer.wsEndpoint()); @@ -130,11 +130,11 @@ test('android.launchServer should terminate WS connection when device gets disco try { const device = await playwright._android.connect(`ws://localhost:${(forwardingServer.address() as ws.AddressInfo).port}/connect`); expect((await device.shell('echo 123')).toString()).toBe('123\n'); - expect(receivedConnection.readyState).toBe(ws.OPEN); - const waitToClose = new Promise(f => receivedConnection.on('close', f)); + expect(receivedConnection!.readyState).toBe(ws.OPEN); + const waitToClose = new Promise(f => receivedConnection!.on('close', f)); await device.close(); await waitToClose; - expect(receivedConnection.readyState).toBe(ws.CLOSED); + expect(receivedConnection!.readyState).toBe(ws.CLOSED); } finally { await browserServer.close(); await new Promise(f => forwardingServer.close(f)); diff --git a/tests/android/playwright.config.ts b/tests/android/playwright.config.ts index 1422f1511d..9b41c9b755 100644 --- a/tests/android/playwright.config.ts +++ b/tests/android/playwright.config.ts @@ -49,7 +49,7 @@ const metadata = { video: false, }; -config.projects.push({ +config.projects!.push({ name: 'android', use: { loopback: '10.0.2.2', @@ -60,7 +60,7 @@ config.projects.push({ metadata, }); -config.projects.push({ +config.projects!.push({ name: 'android', use: { loopback: '10.0.2.2', diff --git a/tests/config/baseTest.ts b/tests/config/baseTest.ts index c49eec6699..7401e0f017 100644 --- a/tests/config/baseTest.ts +++ b/tests/config/baseTest.ts @@ -30,7 +30,7 @@ export const baseTest = mergeTests(base, coverageTest, platformTest, testModeTes .extend(commonFixtures) .extend(serverFixtures); -export function step( +export function step( target: (this: This, ...args: Args) => Promise, context: ClassMethodDecoratorContext Promise> ) { diff --git a/tests/config/browserTest.ts b/tests/config/browserTest.ts index 10116e08cb..cab7e6f285 100644 --- a/tests/config/browserTest.ts +++ b/tests/config/browserTest.ts @@ -28,7 +28,7 @@ import { parseHar } from '../config/utils'; export type BrowserTestWorkerFixtures = PageWorkerFixtures & { browserVersion: string; defaultSameSiteCookieValue: string; - allowsThirdParty + allowsThirdParty: boolean; browserMajorVersion: number; browserType: BrowserType; isAndroid: boolean; diff --git a/tests/config/commonFixtures.ts b/tests/config/commonFixtures.ts index 18ef897a30..35621ab426 100644 --- a/tests/config/commonFixtures.ts +++ b/tests/config/commonFixtures.ts @@ -47,7 +47,7 @@ function readAllProcessesLinux(): { pid: number, ppid: number, pgrp: number }[] const statFile = fs.readFileSync(`/proc/${pid}/stat`, 'utf8'); // Format of /proc/*/stat is described https://man7.org/linux/man-pages/man5/proc.5.html const match = statFile.match(/^(?\d+)\s+\((?.*)\)\s+(?R|S|D|Z|T|t|W|X|x|K|W|P)\s+(?\d+)\s+(?\d+)/); - if (match) { + if (match && match.groups) { result.push({ pid: +match.groups.pid, ppid: +match.groups.ppid, @@ -89,7 +89,7 @@ function buildProcessTreePosix(pid: number): ProcessData { if (parent && child) parent.children.add(child); } - return pidToProcess.get(pid); + return pidToProcess.get(pid)!; } export class TestChildProcess { @@ -98,8 +98,8 @@ export class TestChildProcess { output = ''; fullOutput = ''; onOutput?: (chunk: string | Buffer) => void; - exited: Promise<{ exitCode: number, signal: string | null }>; - exitCode: Promise; + exited: Promise<{ exitCode: number | null, signal: string | null }>; + exitCode: Promise; private _outputCallbacks = new Set<() => void>(); @@ -133,8 +133,8 @@ export class TestChildProcess { this._outputCallbacks.clear(); }; - this.process.stderr.on('data', appendChunk); - this.process.stdout.on('data', appendChunk); + this.process.stderr!.on('data', appendChunk); + this.process.stdout!.on('data', appendChunk); const killProcessGroup = this._killProcessTree.bind(this, 'SIGKILL'); process.on('exit', killProcessGroup); @@ -214,7 +214,7 @@ export class TestChildProcess { } write(chars: string) { - this.process.stdin.write(chars); + this.process.stdin!.write(chars); } } diff --git a/tests/config/remoteServer.ts b/tests/config/remoteServer.ts index 34f6dcb4ca..39c6e1aa25 100644 --- a/tests/config/remoteServer.ts +++ b/tests/config/remoteServer.ts @@ -24,8 +24,8 @@ export interface PlaywrightServer { } export class RunServer implements PlaywrightServer { - private _process: TestChildProcess; - _wsEndpoint: string; + private _process!: TestChildProcess; + _wsEndpoint!: string; async start(childProcess: CommonFixtures['childProcess'], mode?: 'extension' | 'default', env?: NodeJS.ProcessEnv) { const command = ['node', path.join(__dirname, '..', '..', 'packages', 'playwright-core', 'lib', 'cli', 'cli.js'), 'run-server']; @@ -40,7 +40,7 @@ export class RunServer implements PlaywrightServer { }, }); - let wsEndpointCallback; + let wsEndpointCallback: (value: string) => void; const wsEndpointPromise = new Promise(f => wsEndpointCallback = f); this._process.onOutput = data => { const prefix = 'Listening on '; @@ -71,18 +71,15 @@ export type RemoteServerOptions = { }; export class RemoteServer implements PlaywrightServer { - private _process: TestChildProcess; - _output: Map; - _outputCallback: Map void>; - _browserType: BrowserType; - _exitAndDisconnectPromise: Promise; - _browser: Browser; - _wsEndpoint: string; + private _process!: TestChildProcess; + readonly _output = new Map(); + readonly _outputCallback = new Map void>(); + _browserType!: BrowserType; + _exitAndDisconnectPromise: Promise | undefined; + _browser: Browser | undefined; + _wsEndpoint!: string; async _start(childProcess: CommonFixtures['childProcess'], browserType: BrowserType, remoteServerOptions: RemoteServerOptions = {}) { - this._output = new Map(); - this._outputCallback = new Map(); - this._browserType = browserType; const browserOptions = (browserType as any)._defaultLaunchOptions; // Copy options to prevent a large JSON string when launching subprocess. @@ -114,7 +111,7 @@ export class RemoteServer implements PlaywrightServer { const key = match[1]; const value = match[2]; this._addOutput(key, value); - index += match.index + match[0].length; + index += match.index! + match[0].length; } }; @@ -135,10 +132,10 @@ export class RemoteServer implements PlaywrightServer { cb(); } - async out(key: string) { + async out(key: string): Promise { if (!this._output.has(key)) await new Promise(f => this._outputCallback.set(key, f)); - return this._output.get(key); + return this._output.get(key)!; } wsEndpoint() { diff --git a/tests/library/browser.spec.ts b/tests/library/browser.spec.ts index f201b55988..17bdc14213 100644 --- a/tests/library/browser.spec.ts +++ b/tests/library/browser.spec.ts @@ -37,10 +37,10 @@ test('should create new page @smoke', async function({ browser }) { test('should throw upon second create new page', async function({ browser }) { const page = await browser.newPage(); - let error; + let error: Error; await page.context().newPage().catch(e => error = e); await page.close(); - expect(error.message).toContain('Please use browser.newContext()'); + expect(error!.message).toContain('Please use browser.newContext()'); }); test('version should work', async function({ browser, browserName }) { diff --git a/tests/library/browsercontext-add-cookies.spec.ts b/tests/library/browsercontext-add-cookies.spec.ts index a320bc947a..bdfe14ef0a 100644 --- a/tests/library/browsercontext-add-cookies.spec.ts +++ b/tests/library/browsercontext-add-cookies.spec.ts @@ -87,7 +87,7 @@ it('should roundtrip cookie', async ({ context, page, server }) => { it('should send cookie header', async ({ server, context }) => { let cookie = ''; server.setRoute('/empty.html', (req, res) => { - cookie = req.headers.cookie; + cookie = req.headers.cookie!; res.end(); }); await context.addCookies([{ url: server.EMPTY_PAGE, name: 'cookie', value: 'value' }]); @@ -345,7 +345,7 @@ it('should set cookies for a frame', async ({ context, page, server }) => { { url: server.PREFIX, name: 'frame-cookie', value: 'value' } ]); await page.evaluate(src => { - let fulfill; + let fulfill!: (value: unknown) => void; const promise = new Promise(x => fulfill = x); const iframe = document.createElement('iframe'); document.body.appendChild(iframe); @@ -360,7 +360,7 @@ it('should set cookies for a frame', async ({ context, page, server }) => { it('should(not) block third party cookies', async ({ context, page, server, browserName, allowsThirdParty }) => { await page.goto(server.EMPTY_PAGE); await page.evaluate(src => { - let fulfill; + let fulfill!: (value: unknown) => void; const promise = new Promise(x => fulfill = x); const iframe = document.createElement('iframe'); document.body.appendChild(iframe); @@ -438,10 +438,10 @@ it('should allow unnamed cookies', async ({ page, context, server, browserName, // Round-trip behavior const resp = await page.goto(server.PREFIX + '/cookies'); if (browserName === 'webkit' && platform === 'darwin') { - expect.soft(await resp.text()).toBe('undefined-on-server'); + expect.soft(await resp!.text()).toBe('undefined-on-server'); expect.soft(await page.evaluate('document.cookie')).toBe(''); } else { - expect.soft(await resp.text()).toBe('unnamed-via-add-cookies'); + expect.soft(await resp!.text()).toBe('unnamed-via-add-cookies'); expect.soft(await page.evaluate('document.cookie')).toBe('unnamed-via-add-cookies'); } // Within PW behavior diff --git a/tests/library/browsercontext-add-init-script.spec.ts b/tests/library/browsercontext-add-init-script.spec.ts index 369c5713e2..f372020225 100644 --- a/tests/library/browsercontext-add-init-script.spec.ts +++ b/tests/library/browsercontext-add-init-script.spec.ts @@ -18,51 +18,51 @@ import { contextTest as it, expect } from '../config/browserTest'; it('should work with browser context scripts @smoke', async ({ context, server }) => { - await context.addInitScript(() => window['temp'] = 123); + await context.addInitScript(() => (window as any)['temp'] = 123); const page = await context.newPage(); - await page.addInitScript(() => window['injected'] = window['temp']); + await page.addInitScript(() => (window as any)['injected'] = (window as any)['temp']); await page.goto(server.PREFIX + '/tamperable.html'); - expect(await page.evaluate(() => window['result'])).toBe(123); + expect(await page.evaluate(() => (window as any)['result'])).toBe(123); }); it('should work without navigation, after all bindings', async ({ context }) => { - let callback; + let callback: (arg: unknown) => void; const promise = new Promise(f => callback = f); - await context.exposeFunction('woof', function(arg) { + await context.exposeFunction('woof', function(arg: any) { callback(arg); }); await context.addInitScript(() => { - window['woof']('hey'); - window['temp'] = 123; + (window as any)['woof']('hey'); + (window as any)['temp'] = 123; }); const page = await context.newPage(); - expect(await page.evaluate(() => window['temp'])).toBe(123); + expect(await page.evaluate(() => (window as any)['temp'])).toBe(123); expect(await promise).toBe('hey'); }); it('should work without navigation in popup', async ({ context }) => { - await context.addInitScript(() => window['temp'] = 123); + await context.addInitScript(() => (window as any)['temp'] = 123); const page = await context.newPage(); const [popup] = await Promise.all([ page.waitForEvent('popup'), - page.evaluate(() => window['win'] = window.open()), + page.evaluate(() => (window as any)['win'] = window.open()), ]); - expect(await popup.evaluate(() => window['temp'])).toBe(123); + expect(await popup.evaluate(() => (window as any)['temp'])).toBe(123); }); it('should work with browser context scripts with a path', async ({ context, server, asset }) => { await context.addInitScript({ path: asset('injectedfile.js') }); const page = await context.newPage(); await page.goto(server.PREFIX + '/tamperable.html'); - expect(await page.evaluate(() => window['result'])).toBe(123); + expect(await page.evaluate(() => (window as any)['result'])).toBe(123); }); it('should work with browser context scripts for already created pages', async ({ context, server }) => { const page = await context.newPage(); - await context.addInitScript(() => window['temp'] = 123); - await page.addInitScript(() => window['injected'] = window['temp']); + await context.addInitScript(() => (window as any)['temp'] = 123); + await page.addInitScript(() => (window as any)['injected'] = (window as any)['temp']); await page.goto(server.PREFIX + '/tamperable.html'); - expect(await page.evaluate(() => window['result'])).toBe(123); + expect(await page.evaluate(() => (window as any)['result'])).toBe(123); }); diff --git a/tests/library/browsercontext-base-url.spec.ts b/tests/library/browsercontext-base-url.spec.ts index b6dd40b90d..a549e30db9 100644 --- a/tests/library/browsercontext-base-url.spec.ts +++ b/tests/library/browsercontext-base-url.spec.ts @@ -22,7 +22,7 @@ it('should construct a new URL when a baseURL in browser.newContext is passed to baseURL: server.PREFIX, }); const page = await context.newPage(); - expect((await page.goto('/empty.html')).url()).toBe(server.EMPTY_PAGE); + expect((await page.goto('/empty.html'))!.url()).toBe(server.EMPTY_PAGE); await context.close(); }); @@ -30,7 +30,7 @@ it('should construct a new URL when a baseURL in browser.newPage is passed to pa const page = await browser.newPage({ baseURL: server.PREFIX, }); - expect((await page.goto('/empty.html')).url()).toBe(server.EMPTY_PAGE); + expect((await page.goto('/empty.html'))!.url()).toBe(server.EMPTY_PAGE); await page.close(); }); @@ -40,7 +40,7 @@ it('should construct a new URL when a baseURL in browserType.launchPersistentCon baseURL: server.PREFIX, }); const page = await context.newPage(); - expect((await page.goto('/empty.html')).url()).toBe(server.EMPTY_PAGE); + expect((await page.goto('/empty.html'))!.url()).toBe(server.EMPTY_PAGE); await context.close(); }); @@ -48,9 +48,9 @@ it('should construct the URLs correctly when a baseURL without a trailing slash const page = await browser.newPage({ baseURL: server.PREFIX + '/url-construction', }); - expect((await page.goto('mypage.html')).url()).toBe(server.PREFIX + '/mypage.html'); - expect((await page.goto('./mypage.html')).url()).toBe(server.PREFIX + '/mypage.html'); - expect((await page.goto('/mypage.html')).url()).toBe(server.PREFIX + '/mypage.html'); + expect((await page.goto('mypage.html'))!.url()).toBe(server.PREFIX + '/mypage.html'); + expect((await page.goto('./mypage.html'))!.url()).toBe(server.PREFIX + '/mypage.html'); + expect((await page.goto('/mypage.html'))!.url()).toBe(server.PREFIX + '/mypage.html'); await page.close(); }); @@ -58,11 +58,11 @@ it('should construct the URLs correctly when a baseURL with a trailing slash in const page = await browser.newPage({ baseURL: server.PREFIX + '/url-construction/', }); - expect((await page.goto('mypage.html')).url()).toBe(server.PREFIX + '/url-construction/mypage.html'); - expect((await page.goto('./mypage.html')).url()).toBe(server.PREFIX + '/url-construction/mypage.html'); - expect((await page.goto('/mypage.html')).url()).toBe(server.PREFIX + '/mypage.html'); - expect((await page.goto('.')).url()).toBe(server.PREFIX + '/url-construction/'); - expect((await page.goto('/')).url()).toBe(server.PREFIX + '/'); + expect((await page.goto('mypage.html'))!.url()).toBe(server.PREFIX + '/url-construction/mypage.html'); + expect((await page.goto('./mypage.html'))!.url()).toBe(server.PREFIX + '/url-construction/mypage.html'); + expect((await page.goto('/mypage.html'))!.url()).toBe(server.PREFIX + '/mypage.html'); + expect((await page.goto('.'))!.url()).toBe(server.PREFIX + '/url-construction/'); + expect((await page.goto('/'))!.url()).toBe(server.PREFIX + '/'); await page.close(); }); @@ -70,7 +70,7 @@ it('should not construct a new URL when valid URLs are passed', async function({ const page = await browser.newPage({ baseURL: 'http://microsoft.com', }); - expect((await page.goto(server.EMPTY_PAGE)).url()).toBe(server.EMPTY_PAGE); + expect((await page.goto(server.EMPTY_PAGE))!.url()).toBe(server.EMPTY_PAGE); await page.goto('data:text/html,Hello world'); expect(await page.evaluate(() => window.location.href)).toBe('data:text/html,Hello world'); diff --git a/tests/library/browsercontext-basic.spec.ts b/tests/library/browsercontext-basic.spec.ts index d2e6aac8e6..21ea63f860 100644 --- a/tests/library/browsercontext-basic.spec.ts +++ b/tests/library/browsercontext-basic.spec.ts @@ -18,6 +18,7 @@ import { kTargetClosedErrorMessage } from '../config/errors'; import { browserTest as it, expect } from '../config/browserTest'; import { attachFrame, verifyViewport } from '../config/utils'; +import type { Page } from '@playwright/test'; it('should create new context @smoke', async function({ browser }) { expect(browser.contexts().length).toBe(0); @@ -154,7 +155,7 @@ it('should not report frameless pages on error', async ({ browser, server }) => server.setRoute('/empty.html', (req, res) => { res.end(`Click me`); }); - let popup; + let popup: Page | undefined; context.on('page', p => popup = p); await page.goto(server.EMPTY_PAGE); await page.click('"Click me"'); @@ -194,9 +195,9 @@ it('should disable javascript', async ({ browser, browserName }) => { let error = null; await page.evaluate('something').catch(e => error = e); if (browserName === 'webkit') - expect(error.message).toContain('Can\'t find variable: something'); + expect(error!.message).toContain('Can\'t find variable: something'); else - expect(error.message).toContain('something is not defined'); + expect(error!.message).toContain('something is not defined'); await context.close(); } @@ -240,7 +241,7 @@ it('should work with offline option', async ({ browser, server }) => { expect(error).toBeTruthy(); await context.setOffline(false); const response = await page.goto(server.EMPTY_PAGE); - expect(response.status()).toBe(200); + expect(response!.status()).toBe(200); await context.close(); }); diff --git a/tests/library/browsercontext-credentials.spec.ts b/tests/library/browsercontext-credentials.spec.ts index faa75183bd..cc991e0e5a 100644 --- a/tests/library/browsercontext-credentials.spec.ts +++ b/tests/library/browsercontext-credentials.spec.ts @@ -32,7 +32,7 @@ it('should fail without credentials', async ({ browser, server, isChromiumHeaded const page = await context.newPage(); try { const response = await page.goto(server.EMPTY_PAGE); - expect(response.status()).toBe(401); + expect(response!.status()).toBe(401); } finally { await context.close(); } @@ -45,10 +45,10 @@ it('should work with setHTTPCredentials', async ({ browser, server, isChromiumHe const context = await browser.newContext(); const page = await context.newPage(); let response = await page.goto(server.EMPTY_PAGE); - expect(response.status()).toBe(401); + expect(response!.status()).toBe(401); await context.setHTTPCredentials({ username: 'user', password: 'pass' }); response = await page.reload(); - expect(response.status()).toBe(200); + expect(response!.status()).toBe(200); await context.close(); }); @@ -59,7 +59,7 @@ it('should work with correct credentials @smoke', async ({ browser, server }) => }); const page = await context.newPage(); const response = await page.goto(server.EMPTY_PAGE); - expect(response.status()).toBe(200); + expect(response!.status()).toBe(200); await context.close(); }); @@ -70,7 +70,7 @@ it('should fail with wrong credentials', async ({ browser, server }) => { }); const page = await context.newPage(); const response = await page.goto(server.EMPTY_PAGE); - expect(response.status()).toBe(401); + expect(response!.status()).toBe(401); await context.close(); }); @@ -81,9 +81,9 @@ it('should return resource body', async ({ browser, server }) => { }); const page = await context.newPage(); const response = await page.goto(server.PREFIX + '/playground.html'); - expect(response.status()).toBe(200); + expect(response!.status()).toBe(200); expect(await page.title()).toBe('Playground'); - expect((await response.body()).toString()).toContain('Playground'); + expect((await response!.body()).toString()).toContain('Playground'); await context.close(); }); @@ -94,7 +94,7 @@ it('should work with correct credentials and matching origin', async ({ browser, }); const page = await context.newPage(); const response = await page.goto(server.EMPTY_PAGE); - expect(response.status()).toBe(200); + expect(response!.status()).toBe(200); await context.close(); }); @@ -105,7 +105,7 @@ it('should work with correct credentials and matching origin case insensitive', }); const page = await context.newPage(); const response = await page.goto(server.EMPTY_PAGE); - expect(response.status()).toBe(200); + expect(response!.status()).toBe(200); await context.close(); }); @@ -117,7 +117,7 @@ it('should fail with correct credentials and mismatching scheme', async ({ brows }); const page = await context.newPage(); const response = await page.goto(server.EMPTY_PAGE); - expect(response.status()).toBe(401); + expect(response!.status()).toBe(401); await context.close(); }); @@ -131,7 +131,7 @@ it('should fail with correct credentials and mismatching hostname', async ({ bro }); const page = await context.newPage(); const response = await page.goto(server.EMPTY_PAGE); - expect(response.status()).toBe(401); + expect(response!.status()).toBe(401); await context.close(); }); @@ -144,6 +144,6 @@ it('should fail with correct credentials and mismatching port', async ({ browser }); const page = await context.newPage(); const response = await page.goto(server.EMPTY_PAGE); - expect(response.status()).toBe(401); + expect(response!.status()).toBe(401); await context.close(); }); diff --git a/tests/library/browsercontext-device.spec.ts b/tests/library/browsercontext-device.spec.ts index 12624650da..1dd2aca71c 100644 --- a/tests/library/browsercontext-device.spec.ts +++ b/tests/library/browsercontext-device.spec.ts @@ -36,8 +36,8 @@ it.describe('device', () => { const page = await context.newPage(); await page.goto(server.PREFIX + '/input/button.html'); const button = await page.$('button'); - await page.evaluate(button => button.style.marginTop = '200px', button); - await button.click(); + await page.evaluate(button => button!.style.marginTop = '200px', button); + await button!.click(); expect(await page.evaluate('result')).toBe('Clicked'); await context.close(); }); @@ -54,8 +54,8 @@ it.describe('device', () => { const page = await context.newPage(); await page.goto(server.PREFIX + '/input/scrollable.html'); const element = await page.$('#button-91'); - await element.click(); - expect(await element.textContent()).toBe('clicked'); + await element!.click(); + expect(await element!.textContent()).toBe('clicked'); await context.close(); }); diff --git a/tests/library/browsercontext-events.spec.ts b/tests/library/browsercontext-events.spec.ts index 60fcd2e9ce..4ad1ccc1f0 100644 --- a/tests/library/browsercontext-events.spec.ts +++ b/tests/library/browsercontext-events.spec.ts @@ -45,7 +45,7 @@ test('console event should work in popup 2', async ({ page, browserName }) => { const [, message, popup] = await Promise.all([ page.evaluate(async () => { - const win = window.open('javascript:console.log("hello")'); + const win = window.open('javascript:console.log("hello")')!; await new Promise(f => setTimeout(f, 0)); win.close(); }), @@ -62,7 +62,7 @@ test('console event should work in immediately closed popup', async ({ page, bro const [, message, popup] = await Promise.all([ page.evaluate(async () => { - const win = window.open(); + const win = window.open()!; (win as any).console.log('hello'); win.close(); }), @@ -122,7 +122,7 @@ test('dialog event should work in popup 2', async ({ page, browserName }) => { test('dialog event should work in immediately closed popup', async ({ page }) => { const promise = page.evaluate(async () => { - const win = window.open(); + const win = window.open()!; const result = (win as any).prompt('hey?'); win.close(); return result; diff --git a/tests/library/browsercontext-expose-function.spec.ts b/tests/library/browsercontext-expose-function.spec.ts index 57fc466316..4786cabede 100644 --- a/tests/library/browsercontext-expose-function.spec.ts +++ b/tests/library/browsercontext-expose-function.spec.ts @@ -16,9 +16,10 @@ */ import { contextTest as it, expect } from '../config/browserTest'; +import type { JSHandle } from '@playwright/test'; it('expose binding should work', async ({ context }) => { - let bindingSource; + let bindingSource: any; await context.exposeBinding('add', (source, a, b) => { bindingSource = source; return a + b; @@ -32,10 +33,10 @@ it('expose binding should work', async ({ context }) => { }); it('should work', async ({ context, server }) => { - await context.exposeFunction('add', (a, b) => a + b); + await context.exposeFunction('add', (a: number, b: number) => a + b); const page = await context.newPage(); - await page.exposeFunction('mul', (a, b) => a * b); - await context.exposeFunction('sub', (a, b) => a - b); + await page.exposeFunction('mul', (a: number, b: number) => a * b); + await context.exposeFunction('sub', (a: number, b: number) => a - b); await context.exposeBinding('addHandle', async ({ frame }, a, b) => { const handle = await frame.evaluateHandle(([a, b]) => a + b, [a, b]); return handle; @@ -58,8 +59,8 @@ it('should throw for duplicate registrations', async ({ context, server }) => { }); it('should be callable from-inside addInitScript', async ({ context, server }) => { - let args = []; - await context.exposeFunction('woof', function(arg) { + let args: string[] = []; + await context.exposeFunction('woof', function(arg: string) { args.push(arg); }); await context.addInitScript('window["woof"]("context")'); @@ -73,14 +74,14 @@ it('should be callable from-inside addInitScript', async ({ context, server }) = }); it('exposeBindingHandle should work', async ({ context }) => { - let target; + let target!: JSHandle; await context.exposeBinding('logme', (source, t) => { target = t; return 17; }, { handle: true }); const page = await context.newPage(); const result = await page.evaluate(async function() { - return window['logme']({ foo: 42 }); + return (window as any)['logme']({ foo: 42 }); }); expect(await target.evaluate(x => x.foo)).toBe(42); expect(result).toEqual(17); diff --git a/tests/library/browsercontext-fetch.spec.ts b/tests/library/browsercontext-fetch.spec.ts index 742d4a7f99..3a3bdb0717 100644 --- a/tests/library/browsercontext-fetch.spec.ts +++ b/tests/library/browsercontext-fetch.spec.ts @@ -134,7 +134,7 @@ for (const method of ['fetch', 'delete', 'get', 'head', 'patch', 'post', 'put'] } }), ]); - const params = new URLSearchParams(request.url.substr(request.url.indexOf('?'))); + const params = new URLSearchParams(request.url!.substr(request.url!.indexOf('?'))); expect(params.get('p1')).toEqual('v1'); expect(params.get('парам2')).toEqual('знач2'); }); @@ -337,7 +337,7 @@ it('should handle cookies on redirects', async ({ context, server, browserName, context.request.get(`${server.PREFIX}/redirect1`), ]); expect(req1.headers.cookie).toBe('r1=v1'); - expect(req2.headers.cookie.split(';').map(s => s.trim()).sort()).toEqual(['r1=v1', 'r2=v2']); + expect(req2.headers.cookie!.split(';').map(s => s.trim()).sort()).toEqual(['r1=v1', 'r2=v2']); expect(req3.headers.cookie).toBe('r1=v1'); } const cookies = await context.cookies(); @@ -369,7 +369,7 @@ it('should return raw headers', async ({ context, page, server }) => { server.setRoute('/headers', (req, res) => { // Headers array is only supported since Node v14.14.0 so we write directly to the socket. // res.writeHead(200, ['name-a', 'v1','name-b', 'v4','Name-a', 'v2', 'name-A', 'v3']); - const conn = res.connection; + const conn = res.connection!; conn.write('HTTP/1.1 200 OK\r\n'); conn.write('Name-A: v1\r\n'); conn.write('name-b: v4\r\n'); @@ -773,7 +773,7 @@ it('should throw on a redirect with an invalid URL', async ({ context, server }) server.setRedirect('/redirect', '/test'); server.setRoute('/test', (req, res) => { // Node.js prevents us from responding with an invalid header, therefore we manually write the response. - const conn = res.connection; + const conn = res.connection!; conn.write('HTTP/1.1 302\r\n'); conn.write('Location: https://здравствуйте/\r\n'); conn.write('\r\n'); @@ -1029,7 +1029,7 @@ it('should accept bool and numeric params', async ({ page, server }) => { 'bool2': false, } }); - const params = new URLSearchParams(request.url.substr(request.url.indexOf('?'))); + const params = new URLSearchParams(request!.url.substr(request!.url.indexOf('?'))); expect(params.get('str')).toEqual('s'); expect(params.get('num')).toEqual('10'); expect(params.get('bool')).toEqual('true'); diff --git a/tests/library/browsercontext-har.spec.ts b/tests/library/browsercontext-har.spec.ts index cf56bf97e0..3f67309bbb 100644 --- a/tests/library/browsercontext-har.spec.ts +++ b/tests/library/browsercontext-har.spec.ts @@ -151,7 +151,7 @@ it('should change document URL after redirected navigation', async ({ context, a page.goto('https://theverge.com/') ]); await expect(page).toHaveURL('https://www.theverge.com/'); - expect(response.request().url()).toBe('https://www.theverge.com/'); + expect(response!.request().url()).toBe('https://www.theverge.com/'); expect(await page.evaluate(() => location.href)).toBe('https://www.theverge.com/'); }); @@ -166,7 +166,7 @@ it('should change document URL after redirected navigation on click', async ({ s page.click('text=click me'), ]); await expect(page).toHaveURL('https://www.theverge.com/'); - expect(response.request().url()).toBe('https://www.theverge.com/'); + expect(response!.request().url()).toBe('https://www.theverge.com/'); expect(await page.evaluate(() => location.href)).toBe('https://www.theverge.com/'); }); @@ -179,7 +179,7 @@ it('should goBack to redirected navigation', async ({ context, asset, server }) await expect(page).toHaveURL(server.EMPTY_PAGE); const response = await page.goBack(); await expect(page).toHaveURL('https://www.theverge.com/'); - expect(response.request().url()).toBe('https://www.theverge.com/'); + expect(response!.request().url()).toBe('https://www.theverge.com/'); expect(await page.evaluate(() => location.href)).toBe('https://www.theverge.com/'); }); @@ -195,7 +195,7 @@ it('should goForward to redirected navigation', async ({ context, asset, server, await expect(page).toHaveURL(server.EMPTY_PAGE); const response = await page.goForward(); await expect(page).toHaveURL('https://www.theverge.com/'); - expect(response.request().url()).toBe('https://www.theverge.com/'); + expect(response!.request().url()).toBe('https://www.theverge.com/'); expect(await page.evaluate(() => location.href)).toBe('https://www.theverge.com/'); }); @@ -207,7 +207,7 @@ it('should reload redirected navigation', async ({ context, asset, server }) => await expect(page).toHaveURL('https://www.theverge.com/'); const response = await page.reload(); await expect(page).toHaveURL('https://www.theverge.com/'); - expect(response.request().url()).toBe('https://www.theverge.com/'); + expect(response!.request().url()).toBe('https://www.theverge.com/'); expect(await page.evaluate(() => location.href)).toBe('https://www.theverge.com/'); }); diff --git a/tests/library/browsercontext-network-event.spec.ts b/tests/library/browsercontext-network-event.spec.ts index d423f07388..14684d82c0 100644 --- a/tests/library/browsercontext-network-event.spec.ts +++ b/tests/library/browsercontext-network-event.spec.ts @@ -16,10 +16,11 @@ */ import { browserTest as it, expect } from '../config/browserTest'; +import type { Request, Response } from '@playwright/test'; it('BrowserContext.Events.Request', async ({ context, server }) => { const page = await context.newPage(); - const requests = []; + const requests: Request[] = []; context.on('request', request => requests.push(request)); await page.goto(server.EMPTY_PAGE); await page.setContent('yo'); @@ -38,7 +39,7 @@ it('BrowserContext.Events.Request', async ({ context, server }) => { it('BrowserContext.Events.Response', async ({ context, server }) => { const page = await context.newPage(); - const responses = []; + const responses: Response[] = []; context.on('response', response => responses.push(response)); await page.goto(server.EMPTY_PAGE); await page.setContent('yo'); @@ -58,10 +59,10 @@ it('BrowserContext.Events.Response', async ({ context, server }) => { it('BrowserContext.Events.RequestFailed', async ({ context, server }) => { server.setRoute('/one-style.css', (_, res) => { res.setHeader('Content-Type', 'text/css'); - res.connection.destroy(); + res.connection!.destroy(); }); const page = await context.newPage(); - const failedRequests = []; + const failedRequests: Request[] = []; context.on('requestfailed', request => failedRequests.push(request)); await page.goto(server.PREFIX + '/one-style.html'); expect(failedRequests.length).toBe(1); @@ -78,7 +79,7 @@ it('BrowserContext.Events.RequestFinished', async ({ context, server }) => { page.goto(server.EMPTY_PAGE), context.waitForEvent('requestfinished') ]); - const request = response.request(); + const request = response!.request(); expect(request.url()).toBe(server.EMPTY_PAGE); expect(await request.response()).toBeTruthy(); expect(request.frame() === page.mainFrame()).toBe(true); @@ -88,7 +89,7 @@ it('BrowserContext.Events.RequestFinished', async ({ context, server }) => { it('should fire events in proper order', async ({ context, server }) => { const page = await context.newPage(); - const events = []; + const events: string[] = []; context.on('request', () => events.push('request')); context.on('response', () => events.push('response')); context.on('requestfinished', () => events.push('requestfinished')); @@ -127,7 +128,7 @@ it('should not fire events for favicon or favicon redirects', async ({ context, `); }); - const events = []; + const events: string[] = []; context.on('request', req => events.push(req.url())); context.on('response', res => events.push(res.url())); context.on('requestfinished', req => events.push(req.url())); diff --git a/tests/library/browsercontext-pages.spec.ts b/tests/library/browsercontext-pages.spec.ts index e6903303f6..c66fa9b99a 100644 --- a/tests/library/browsercontext-pages.spec.ts +++ b/tests/library/browsercontext-pages.spec.ts @@ -39,7 +39,7 @@ it('frame.focus should work multiple times', async ({ contextFactory }) => { for (const page of [page1, page2]) { await page.setContent(``); await page.focus('#foo'); - expect(await page.evaluate(() => !!window['gotFocus'])).toBe(true); + expect(await page.evaluate(() => !!(window as any)['gotFocus'])).toBe(true); } }); @@ -74,8 +74,8 @@ it('should click the button with deviceScaleFactor set', async ({ browser, serve await attachFrame(page, 'button-test', server.PREFIX + '/input/button.html'); const frame = page.frames()[1]; const button = await frame.$('button'); - await button.click(); - expect(await frame.evaluate(() => window['result'])).toBe('Clicked'); + await button!.click(); + expect(await frame.evaluate(() => (window as any)['result'])).toBe('Clicked'); await context.close(); }); @@ -91,7 +91,7 @@ it('should click the button with offset with page scale', async ({ browser, serv }); await page.click('button', { position: { x: 20, y: 10 } }); expect(await page.evaluate('result')).toBe('Clicked'); - const expectCloseTo = (expected, actual) => { + const expectCloseTo = (expected: number, actual: number) => { if (Math.abs(expected - actual) > 2) throw new Error(`Expected: ${expected}, received: ${actual}`); }; @@ -108,7 +108,7 @@ it('should return bounding box with page scale', async ({ browser, server, brows const context = await browser.newContext({ viewport: { width: 400, height: 400 }, isMobile: true }); const page = await context.newPage(); await page.goto(server.PREFIX + '/input/button.html'); - const button = await page.$('button'); + const button = (await page.$('button'))!; await button.evaluate(button => { document.body.style.margin = '0'; button.style.borderWidth = '0'; @@ -117,7 +117,7 @@ it('should return bounding box with page scale', async ({ browser, server, brows button.style.marginLeft = '17px'; button.style.marginTop = '23px'; }); - const box = await button.boundingBox(); + const box = (await button.boundingBox())!; expect(Math.round(box.x * 100)).toBe(17 * 100); expect(Math.round(box.y * 100)).toBe(23 * 100); expect(Math.round(box.width * 100)).toBe(200 * 100); @@ -130,7 +130,7 @@ it('should not leak listeners during navigation of 20 pages', async ({ contextFa const context = await contextFactory(); let warning = null; - const warningHandler = w => warning = w; + const warningHandler = (w: string) => warning = w; process.on('warning', warningHandler); const pages = await Promise.all([...Array(20)].map(() => context.newPage())); await Promise.all(pages.map(page => page.goto(server.EMPTY_PAGE))); diff --git a/tests/library/browsercontext-route.spec.ts b/tests/library/browsercontext-route.spec.ts index a1d4a83a29..e600948216 100644 --- a/tests/library/browsercontext-route.spec.ts +++ b/tests/library/browsercontext-route.spec.ts @@ -16,6 +16,7 @@ */ import { browserTest as it, expect } from '../config/browserTest'; +import type { Route } from '@playwright/test'; it('should intercept', async ({ browser, server }) => { const context = await browser.newContext(); @@ -35,7 +36,7 @@ it('should intercept', async ({ browser, server }) => { }); const page = await context.newPage(); const response = await page.goto(server.EMPTY_PAGE); - expect(response.ok()).toBe(true); + expect(response!.ok()).toBe(true); expect(intercepted).toBe(true); await context.close(); }); @@ -44,7 +45,7 @@ it('should unroute', async ({ browser, server }) => { const context = await browser.newContext(); const page = await context.newPage(); - let intercepted = []; + let intercepted: number[] = []; await context.route('**/*', route => { intercepted.push(1); void route.fallback(); @@ -57,7 +58,7 @@ it('should unroute', async ({ browser, server }) => { intercepted.push(3); void route.fallback(); }); - const handler4 = route => { + const handler4 = (route: Route) => { intercepted.push(4); void route.fallback(); }; @@ -87,7 +88,7 @@ it('should yield to page.route', async ({ browser, server }) => { await page.route('**/empty.html', route => { void route.fulfill({ status: 200, body: 'page' }); }); - const response = await page.goto(server.EMPTY_PAGE); + const response = (await page.goto(server.EMPTY_PAGE))!; expect(response.ok()).toBe(true); expect(await response.text()).toBe('page'); await context.close(); @@ -102,7 +103,7 @@ it('should fall back to context.route', async ({ browser, server }) => { await page.route('**/non-empty.html', route => { void route.fulfill({ status: 200, body: 'page' }); }); - const response = await page.goto(server.EMPTY_PAGE); + const response = (await page.goto(server.EMPTY_PAGE))!; expect(response.ok()).toBe(true); expect(await response.text()).toBe('context'); await context.close(); @@ -178,7 +179,7 @@ it('should use Set-Cookie header in future requests', async ({ contextFactory, s let cookie = ''; server.setRoute('/foo.html', (req, res) => { - cookie = req.headers.cookie; + cookie = req.headers.cookie!; res.end(); }); await page.goto(server.PREFIX + '/foo.html'); @@ -191,12 +192,12 @@ it('should work with ignoreHTTPSErrors', async ({ browser, httpsServer }) => { await page.route('**/*', route => route.continue()); const response = await page.goto(httpsServer.EMPTY_PAGE); - expect(response.status()).toBe(200); + expect(response!.status()).toBe(200); await context.close(); }); it('should support the times parameter with route matching', async ({ context, page, server }) => { - const intercepted = []; + const intercepted: number[] = []; await context.route('**/empty.html', route => { intercepted.push(1); void route.continue(); @@ -247,7 +248,7 @@ it('should overwrite post body with empty string', async ({ context, server, pag }); it('should chain fallback', async ({ context, page, server }) => { - const intercepted = []; + const intercepted: number[] = []; await context.route('**/empty.html', route => { intercepted.push(1); void route.fallback(); @@ -265,7 +266,7 @@ it('should chain fallback', async ({ context, page, server }) => { }); it('should chain fallback w/ dynamic URL', async ({ context, page, server }) => { - const intercepted = []; + const intercepted: number[] = []; await context.route('**/bar', route => { intercepted.push(1); void route.fallback({ url: server.EMPTY_PAGE }); @@ -296,7 +297,7 @@ it('should not chain fulfill', async ({ context, page, server }) => { void route.fallback(); }); const response = await page.goto(server.EMPTY_PAGE); - const body = await response.body(); + const body = await response!.body(); expect(body.toString()).toEqual('fulfilled'); expect(failed).toBeFalsy(); }); @@ -318,7 +319,7 @@ it('should not chain abort', async ({ context, page, server }) => { }); it('should chain fallback into page', async ({ context, page, server }) => { - const intercepted = []; + const intercepted: number[] = []; await context.route('**/empty.html', route => { intercepted.push(1); void route.fallback(); @@ -348,7 +349,7 @@ it('should chain fallback into page', async ({ context, page, server }) => { }); it('should fall back async', async ({ page, context, server }) => { - const intercepted = []; + const intercepted: number[] = []; await context.route('**/empty.html', async route => { intercepted.push(1); await new Promise(r => setTimeout(r, 100)); diff --git a/tests/library/browsercontext-viewport-mobile.spec.ts b/tests/library/browsercontext-viewport-mobile.spec.ts index 96832da254..8160d5601e 100644 --- a/tests/library/browsercontext-viewport-mobile.spec.ts +++ b/tests/library/browsercontext-viewport-mobile.spec.ts @@ -41,7 +41,7 @@ it.describe('mobile viewport', () => { await context.close(); function dispatchTouch() { - let fulfill; + let fulfill!: (s: string) => void; const promise = new Promise(x => fulfill = x); window.ontouchstart = function(e) { fulfill('Received touch'); @@ -59,7 +59,7 @@ it.describe('mobile viewport', () => { const context = await browser.newContext({ ...iPhone }); const page = await context.newPage(); await page.goto(server.PREFIX + '/detect-touch.html'); - expect(await page.evaluate(() => document.body.textContent.trim())).toBe('YES'); + expect(await page.evaluate(() => document.body.textContent!.trim())).toBe('YES'); await context.close(); }); @@ -68,7 +68,7 @@ it.describe('mobile viewport', () => { const page = await context.newPage(); await page.goto(server.EMPTY_PAGE); await page.addScriptTag({ url: server.PREFIX + '/modernizr.js' }); - expect(await page.evaluate(() => window['Modernizr'].touchevents)).toBe(true); + expect(await page.evaluate(() => (window as any)['Modernizr'].touchevents)).toBe(true); await context.close(); }); @@ -164,7 +164,7 @@ it.describe('mobile viewport', () => { await page.goto(server.CROSS_PROCESS_PREFIX + '/mobile.html'); await page.evaluate(() => { document.addEventListener('click', event => { - window['result'] = { x: event.clientX, y: event.clientY }; + (window as any)['result'] = { x: event.clientX, y: event.clientY }; }); }); @@ -224,7 +224,7 @@ it.describe('mobile viewport', () => { }); await page.goto('http://localhost/button.html'); await page.getByText('Click me').click({ force: true }); - const box = await page.locator('button').boundingBox(); + const box = (await page.locator('button').boundingBox())!; const clicks = await page.evaluate(() => (window as any).clicks); expect(clicks.length).toBe(1); const [{ x, y }] = clicks; diff --git a/tests/library/chromium/oopif.spec.ts b/tests/library/chromium/oopif.spec.ts index 9931f39521..8a8db75745 100644 --- a/tests/library/chromium/oopif.spec.ts +++ b/tests/library/chromium/oopif.spec.ts @@ -15,6 +15,7 @@ */ import { contextTest as it, expect } from '../../config/browserTest'; +import type { Frame, Browser } from '@playwright/test'; it.use({ launchOptions: async ({ launchOptions }, use) => { @@ -37,7 +38,7 @@ it('should handle oopif detach', async function({ page, browser, server }) { expect(await frame.evaluate(() => '' + location.href)).toBe(server.CROSS_PROCESS_PREFIX + '/grid.html'); const [detachedFrame] = await Promise.all([ page.waitForEvent('framedetached'), - page.evaluate(() => document.querySelector('iframe').remove()), + page.evaluate(() => document.querySelector('iframe')!.remove()), ]); expect(detachedFrame).toBe(frame); }); @@ -87,9 +88,9 @@ it('should expose function', async ({ page, browser, server }) => { expect(page.frames().length).toBe(2); expect(await countOOPIFs(browser)).toBe(1); const oopif = page.frames()[1]; - await page.exposeFunction('mul', (a, b) => a * b); + await page.exposeFunction('mul', (a: number, b: number) => a * b); const result = await oopif.evaluate(async function() { - return await window['mul'](9, 4); + return await (window as any)['mul'](9, 4); }); expect(result).toBe(36); }); @@ -163,9 +164,9 @@ it('should load oopif iframes with subresources and route', async function({ pag }); it('should report main requests', async function({ page, browser, server }) { - const requestFrames = []; + const requestFrames: Frame[] = []; page.on('request', r => requestFrames.push(r.frame())); - const finishedFrames = []; + const finishedFrames: Frame[] = []; page.on('requestfinished', r => finishedFrames.push(r.frame())); await page.goto(server.PREFIX + '/empty.html'); @@ -201,34 +202,34 @@ it('should report main requests', async function({ page, browser, server }) { }); it('should support exposeFunction', async function({ page, browser, server }) { - await page.context().exposeFunction('dec', a => a - 1); - await page.exposeFunction('inc', a => a + 1); + await page.context().exposeFunction('dec', (a: number) => a - 1); + await page.exposeFunction('inc', (a: number) => a + 1); await page.goto(server.PREFIX + '/dynamic-oopif.html'); expect(await countOOPIFs(browser)).toBe(1); expect(page.frames().length).toBe(2); - expect(await page.frames()[0].evaluate(() => window['inc'](3))).toBe(4); - expect(await page.frames()[1].evaluate(() => window['inc'](4))).toBe(5); - expect(await page.frames()[0].evaluate(() => window['dec'](3))).toBe(2); - expect(await page.frames()[1].evaluate(() => window['dec'](4))).toBe(3); + expect(await page.frames()[0].evaluate(() => (window as any)['inc'](3))).toBe(4); + expect(await page.frames()[1].evaluate(() => (window as any)['inc'](4))).toBe(5); + expect(await page.frames()[0].evaluate(() => (window as any)['dec'](3))).toBe(2); + expect(await page.frames()[1].evaluate(() => (window as any)['dec'](4))).toBe(3); }); it('should support addInitScript', async function({ page, browser, server }) { - await page.context().addInitScript(() => window['bar'] = 17); - await page.addInitScript(() => window['foo'] = 42); + await page.context().addInitScript(() => (window as any)['bar'] = 17); + await page.addInitScript(() => (window as any)['foo'] = 42); await page.goto(server.PREFIX + '/dynamic-oopif.html'); expect(await countOOPIFs(browser)).toBe(1); expect(page.frames().length).toBe(2); - expect(await page.frames()[0].evaluate(() => window['foo'])).toBe(42); - expect(await page.frames()[1].evaluate(() => window['foo'])).toBe(42); - expect(await page.frames()[0].evaluate(() => window['bar'])).toBe(17); - expect(await page.frames()[1].evaluate(() => window['bar'])).toBe(17); + expect(await page.frames()[0].evaluate(() => (window as any)['foo'])).toBe(42); + expect(await page.frames()[1].evaluate(() => (window as any)['foo'])).toBe(42); + expect(await page.frames()[0].evaluate(() => (window as any)['bar'])).toBe(17); + expect(await page.frames()[1].evaluate(() => (window as any)['bar'])).toBe(17); }); // @see https://github.com/microsoft/playwright/issues/1240 it('should click a button when it overlays oopif', async function({ page, browser, server }) { await page.goto(server.PREFIX + '/button-overlay-oopif.html'); expect(await countOOPIFs(browser)).toBe(1); await page.click('button'); - expect(await page.evaluate(() => window['BUTTON_CLICKED'])).toBe(true); + expect(await page.evaluate(() => (window as any)['BUTTON_CLICKED'])).toBe(true); }); it('should report google.com frame with headed', async ({ browserType, server }) => { @@ -268,7 +269,7 @@ it('ElementHandle.boundingBox() should work', async function({ page, browser, se expect(await countOOPIFs(browser)).toBe(1); const handle1 = await page.frames()[1].$('.box:nth-of-type(13)'); - expect(await handle1.boundingBox()).toEqual({ x: 100 + 42, y: 50 + 17, width: 50, height: 50 }); + expect(await handle1!.boundingBox()).toEqual({ x: 100 + 42, y: 50 + 17, width: 50, height: 50 }); await Promise.all([ page.frames()[1].waitForNavigation(), @@ -276,7 +277,7 @@ it('ElementHandle.boundingBox() should work', async function({ page, browser, se ]); expect(await countOOPIFs(browser)).toBe(0); const handle2 = await page.frames()[1].$('.box:nth-of-type(13)'); - expect(await handle2.boundingBox()).toEqual({ x: 100 + 42, y: 50 + 17, width: 50, height: 50 }); + expect(await handle2!.boundingBox()).toEqual({ x: 100 + 42, y: 50 + 17, width: 50, height: 50 }); }); it('should click', async function({ page, browser, server }) { @@ -290,10 +291,10 @@ it('should click', async function({ page, browser, server }) { await page.frames()[1].goto(page.frames()[1].url()); expect(await countOOPIFs(browser)).toBe(1); - const handle1 = await page.frames()[1].$('.box:nth-of-type(13)'); - await handle1.evaluate(div => div.addEventListener('click', () => window['_clicked'] = true, false)); + const handle1 = (await page.frames()[1].$('.box:nth-of-type(13)'))!; + await handle1.evaluate(div => div.addEventListener('click', () => (window as any)['_clicked'] = true, false)); await handle1.click(); - expect(await handle1.evaluate(() => window['_clicked'])).toBe(true); + expect(await handle1.evaluate(() => (window as any)['_clicked'])).toBe(true); }); it('should allow cdp sessions on oopifs', async function({ page, browser, server }) { @@ -331,7 +332,7 @@ it('should not throw on exposeFunction when oopif detaches', async ({ page, brow expect(await countOOPIFs(browser)).toBe(1); await Promise.all([ page.exposeFunction('myFunc', () => 2022), - page.evaluate(() => document.querySelector('iframe').remove()), + page.evaluate(() => document.querySelector('iframe')!.remove()), ]); expect(await page.evaluate(() => (window as any).myFunc())).toBe(2022); }); @@ -345,7 +346,7 @@ it('should intercept response body from oopif', async function({ page, browser, expect(await response.text()).toBeTruthy(); }); -async function countOOPIFs(browser) { +async function countOOPIFs(browser: Browser) { const browserSession = await browser.newBrowserCDPSession(); const oopifs = []; browserSession.on('Target.targetCreated', async ({ targetInfo }) => { diff --git a/tests/library/har.spec.ts b/tests/library/har.spec.ts index ba71839448..67a31c5912 100644 --- a/tests/library/har.spec.ts +++ b/tests/library/har.spec.ts @@ -60,8 +60,8 @@ it('should have browser', async ({ browserName, browser, contextFactory, server const { page, getLog } = await pageWithHar(contextFactory, testInfo); await page.goto(server.EMPTY_PAGE); const log = await getLog(); - expect(log.browser.name.toLowerCase()).toBe(browserName); - expect(log.browser.version).toBe(browser.version()); + expect(log.browser!.name.toLowerCase()).toBe(browserName); + expect(log.browser!.version).toBe(browser.version()); }); it('should have pages', async ({ contextFactory, server }, testInfo) => { @@ -70,8 +70,8 @@ it('should have pages', async ({ contextFactory, server }, testInfo) => { // For data: load comes before domcontentloaded... await page.waitForLoadState('domcontentloaded'); const log = await getLog(); - expect(log.pages.length).toBe(1); - const pageEntry = log.pages[0]; + expect(log.pages!.length).toBe(1); + const pageEntry = log.pages![0]; expect(pageEntry.id).toBeTruthy(); expect(pageEntry.title).toBe('Hello'); expect(new Date(pageEntry.startedDateTime).valueOf()).toBeGreaterThan(Date.now() - 3600 * 1000); @@ -108,7 +108,7 @@ it('should include request', async ({ contextFactory, server }, testInfo) => { const log = await getLog(); expect(log.entries.length).toBe(1); const entry = log.entries[0]; - expect(entry.pageref).toBe(log.pages[0].id); + expect(entry.pageref).toBe(log.pages![0].id); expect(entry.request.url).toBe(server.EMPTY_PAGE); expect(entry.request.method).toBe('GET'); expect(entry.request.httpVersion).toBe('HTTP/1.1'); @@ -126,7 +126,7 @@ it('should include response', async ({ contextFactory, server }, testInfo) => { expect(entry.response.statusText).toBe('OK'); expect(entry.response.httpVersion).toBe('HTTP/1.1'); expect(entry.response.headers.length).toBeGreaterThan(1); - expect(entry.response.headers.find(h => h.name.toLowerCase() === 'content-type').value).toContain('text/html'); + expect(entry.response.headers.find(h => h.name.toLowerCase() === 'content-type')!.value).toContain('text/html'); }); it('should include redirectURL', async ({ contextFactory, server }, testInfo) => { @@ -223,7 +223,7 @@ it('should include set-cookies', async ({ contextFactory, server }, testInfo) => const cookies = log.entries[0].response.cookies; expect(cookies[0]).toEqual({ name: 'name1', value: 'value1', httpOnly: true }); expect(cookies[1]).toEqual({ name: 'name2', value: '"value2"' }); - expect(new Date(cookies[2].expires).valueOf()).toBeGreaterThan(Date.now()); + expect(new Date(cookies[2].expires!).valueOf()).toBeGreaterThan(Date.now()); }); it('should skip invalid Expires', async ({ contextFactory, server }, testInfo) => { @@ -316,7 +316,7 @@ it('should include content @smoke', async ({ contextFactory, server }, testInfo) expect(log.entries[2].response.content.encoding).toBe('base64'); expect(log.entries[2].response.content.mimeType).toBe('image/png'); - expect(Buffer.from(log.entries[2].response.content.text, 'base64').byteLength).toBeGreaterThan(0); + expect(Buffer.from(log.entries[2].response.content.text!, 'base64').byteLength).toBeGreaterThan(0); expect(log.entries[2].response.content.size).toBeGreaterThanOrEqual(6000); expect(log.entries[2].response.content.compression).toBe(0); }); @@ -326,9 +326,9 @@ it('should use attach mode for zip extension', async ({ contextFactory, server } await page.goto(server.PREFIX + '/har.html'); await page.evaluate(() => fetch('/pptr.png').then(r => r.arrayBuffer())); const zip = await getZip(); - const log = JSON.parse(zip.get('har.har').toString())['log'] as Log; + const log = JSON.parse(zip.get('har.har')!.toString())['log'] as Log; expect(log.entries[0].response.content.text).toBe(undefined); - expect(zip.get('75841480e2606c03389077304342fac2c58ccb1b.html').toString()).toContain('HAR Page'); + expect(zip.get('75841480e2606c03389077304342fac2c58ccb1b.html')!.toString()).toContain('HAR Page'); }); it('should omit content', async ({ contextFactory, server }, testInfo) => { @@ -354,7 +354,7 @@ it('should attach content', async ({ contextFactory, server }, testInfo) => { await page.goto(server.PREFIX + '/har.html'); await page.evaluate(() => fetch('/pptr.png').then(r => r.arrayBuffer())); const zip = await getZip(); - const log = JSON.parse(zip.get('har.har').toString())['log'] as Log; + const log = JSON.parse(zip.get('har.har')!.toString())['log'] as Log; expect(log.entries[0].response.content.encoding).toBe(undefined); expect(log.entries[0].response.content.mimeType).toBe('text/html; charset=utf-8'); @@ -374,9 +374,9 @@ it('should attach content', async ({ contextFactory, server }, testInfo) => { expect(log.entries[2].response.content.size).toBeGreaterThanOrEqual(6000); expect(log.entries[2].response.content.compression).toBe(0); - expect(zip.get('75841480e2606c03389077304342fac2c58ccb1b.html').toString()).toContain('HAR Page'); - expect(zip.get('79f739d7bc88e80f55b9891a22bf13a2b4e18adb.css').toString()).toContain('pink'); - expect(zip.get('a4c3a18f0bb83f5d9fe7ce561e065c36205762fa.png').byteLength).toBe(log.entries[2].response.content.size); + expect(zip.get('75841480e2606c03389077304342fac2c58ccb1b.html')!.toString()).toContain('HAR Page'); + expect(zip.get('79f739d7bc88e80f55b9891a22bf13a2b4e18adb.css')!.toString()).toContain('pink'); + expect(zip.get('a4c3a18f0bb83f5d9fe7ce561e065c36205762fa.png')!.byteLength).toBe(log.entries[2].response.content.size); }); it('should filter by glob', async ({ contextFactory, server }, testInfo) => { @@ -422,7 +422,7 @@ it('should work with gzip compression', async ({ contextFactory, server, browser const { page, getLog } = await pageWithHar(contextFactory, testInfo); server.enableGzip('/simplezip.json'); const response = await page.goto(server.PREFIX + '/simplezip.json'); - expect(response.headers()['content-encoding']).toBe('gzip'); + expect(response!.headers()['content-encoding']).toBe('gzip'); const log = await getLog(); expect(log.entries.length).toBe(1); expect(log.entries[0].response.content.compression).toBeGreaterThan(4000); @@ -456,7 +456,7 @@ it('should have -1 _transferSize when its a failed request', async ({ contextFac const { page, getLog } = await pageWithHar(contextFactory, testInfo); server.setRoute('/one-style.css', (req, res) => { res.setHeader('Content-Type', 'text/css'); - res.socket.destroy(); + res.socket!.destroy(); }); const failedRequests = []; page.on('requestfailed', request => failedRequests.push(request)); @@ -469,7 +469,7 @@ it('should have -1 _transferSize when its a failed request', async ({ contextFac it('should record failed request headers', async ({ contextFactory, server }, testInfo) => { const { page, getLog } = await pageWithHar(contextFactory, testInfo); server.setRoute('/har.html', (req, res) => { - res.socket.destroy(); + res.socket!.destroy(); }); await page.goto(server.PREFIX + '/har.html').catch(() => {}); const log = await getLog(); @@ -483,7 +483,7 @@ it('should record failed request headers', async ({ contextFactory, server }, te it('should record failed request overrides', async ({ contextFactory, server }, testInfo) => { const { page, getLog } = await pageWithHar(contextFactory, testInfo); server.setRoute('/empty.html', (req, res) => { - res.socket.destroy(); + res.socket!.destroy(); }); await page.route('**/foo', route => { void route.fallback({ @@ -546,7 +546,7 @@ it('should report the correct request body size when the bodySize is 0', async ( it('should report the correct response body size when the bodySize is 0', async ({ contextFactory, server }, testInfo) => { const { page, getLog } = await pageWithHar(contextFactory, testInfo); const response = await page.goto(server.EMPTY_PAGE); - await response.finished(); + await response!.finished(); const log = await getLog(); expect(log.entries[0].response.bodySize).toBe(0); }); @@ -562,9 +562,9 @@ it('should have popup requests', async ({ contextFactory, server }, testInfo) => await popup.waitForLoadState(); const log = await getLog(); - expect(log.pages.length).toBe(2); + expect(log.pages!.length).toBe(2); - const entries = log.entries.filter(entry => entry.pageref === log.pages[1].id); + const entries = log.entries.filter(entry => entry.pageref === log.pages![1].id); expect(entries.length).toBe(2); expect(entries[0].request.url).toBe(server.PREFIX + '/one-style.html'); expect(entries[0].response.status).toBe(200); @@ -589,7 +589,7 @@ it('should not contain internal pages', async ({ browserName, contextFactory, se await context.storageState(); const log = await getLog(); - expect(log.pages.length).toBe(1); + expect(log.pages!.length).toBe(1); }); it('should have connection details', async ({ contextFactory, server, browserName, platform, mode }, testInfo) => { @@ -649,7 +649,7 @@ it('should have connection details for redirects', async ({ contextFactory, serv it('should have connection details for failed requests', async ({ contextFactory, server, browserName, platform, mode }, testInfo) => { server.setRoute('/one-style.css', (_, res) => { res.setHeader('Content-Type', 'text/css'); - res.socket.destroy(); + res.socket!.destroy(); }); const { page, getLog } = await pageWithHar(contextFactory, testInfo); await page.goto(server.PREFIX + '/one-style.html'); @@ -664,7 +664,7 @@ it('should have connection details for failed requests', async ({ contextFactory it('should return server address directly from response', async ({ page, server, mode }) => { const response = await page.goto(server.EMPTY_PAGE); if (!mode.startsWith('service')) { - const { ipAddress, port } = await response.serverAddr(); + const { ipAddress, port } = (await response!.serverAddr())!; expect(ipAddress).toMatch(/^127\.0\.0\.1|\[::1\]/); expect(port).toBe(server.PORT); } @@ -676,7 +676,7 @@ it('should return security details directly from response', async ({ contextFact const context = await contextFactory({ ignoreHTTPSErrors: true }); const page = await context.newPage(); const response = await page.goto(httpsServer.EMPTY_PAGE); - const securityDetails = await response.securityDetails(); + const securityDetails = await response!.securityDetails(); if (browserName === 'webkit' && platform === 'win32') expect({ ...securityDetails, protocol: undefined }).toEqual({ subjectName: 'playwright-test', validFrom: 1691708270, validTo: 2007068270 }); else if (browserName === 'webkit') @@ -775,15 +775,15 @@ it('should have different hars for concurrent contexts', async ({ contextFactory ]); { - expect(log0.pages.length).toBe(1); - const pageEntry = log0.pages[0]; + expect(log0.pages!.length).toBe(1); + const pageEntry = log0.pages![0]; expect(pageEntry.title).toBe('Zero'); } { - expect(log1.pages.length).toBe(1); - const pageEntry = log1.pages[0]; - expect(pageEntry.id).not.toBe(log0.pages[0].id); + expect(log1.pages!.length).toBe(1); + const pageEntry = log1.pages![0]; + expect(pageEntry.id).not.toBe(log0.pages![0].id); expect(pageEntry.title).toBe('One'); } }); @@ -874,6 +874,6 @@ it('should not hang on slow chunked response', async ({ browserName, browser, co await page.goto(server.EMPTY_PAGE); await page.evaluate(() => (window as any).receivedFirstData); const log = await getLog(); - expect(log.browser.name.toLowerCase()).toBe(browserName); - expect(log.browser.version).toBe(browser.version()); + expect(log.browser!.name.toLowerCase()).toBe(browserName); + expect(log.browser!.version).toBe(browser.version()); }); diff --git a/tests/library/inspector/cli-codegen-1.spec.ts b/tests/library/inspector/cli-codegen-1.spec.ts index 091bb23aa9..a3f837fa82 100644 --- a/tests/library/inspector/cli-codegen-1.spec.ts +++ b/tests/library/inspector/cli-codegen-1.spec.ts @@ -33,19 +33,19 @@ test.describe('cli codegen', () => { recorder.trustedClick(), ]); - expect.soft(sources.get('JavaScript').text).toContain(` + expect.soft(sources.get('JavaScript')!.text).toContain(` await page.getByRole('button', { name: 'Submit' }).click();`); - expect.soft(sources.get('Python').text).toContain(` + expect.soft(sources.get('Python')!.text).toContain(` page.get_by_role("button", name="Submit").click()`); - expect.soft(sources.get('Python Async').text).toContain(` + expect.soft(sources.get('Python Async')!.text).toContain(` await page.get_by_role("button", name="Submit").click()`); - expect.soft(sources.get('Java').text).toContain(` + expect.soft(sources.get('Java')!.text).toContain(` page.getByRole(AriaRole.BUTTON, new Page.GetByRoleOptions().setName("Submit")).click()`); - expect.soft(sources.get('C#').text).toContain(` + expect.soft(sources.get('C#')!.text).toContain(` await page.GetByRole(AriaRole.Button, new() { Name = "Submit" }).ClickAsync();`); expect(message.text()).toBe('click'); @@ -68,7 +68,7 @@ test.describe('cli codegen', () => { recorder.trustedClick() ]); - const clicks = recorder.sources().get('Playwright Test').actions.filter(l => l.includes('Submit')); + const clicks = recorder.sources().get('Playwright Test')!.actions!.filter(l => l.includes('Submit')); expect(clicks.length).toBe(1); }); @@ -97,7 +97,7 @@ test.describe('cli codegen', () => { recorder.trustedClick(), ]); - expect(sources.get('JavaScript').text).toContain(` + expect(sources.get('JavaScript')!.text).toContain(` await page.getByRole('button', { name: 'Submit' }).click();`); expect(message.text()).toBe('click'); }); @@ -125,7 +125,7 @@ test.describe('cli codegen', () => { recorder.trustedClick(), ]); - expect(sources.get('JavaScript').text).toContain(` + expect(sources.get('JavaScript')!.text).toContain(` await page.locator('canvas').click({ position: { x: 250, @@ -133,17 +133,17 @@ test.describe('cli codegen', () => { } });`); - expect(sources.get('Python').text).toContain(` + expect(sources.get('Python')!.text).toContain(` page.locator("canvas").click(position={"x":250,"y":250})`); - expect(sources.get('Python Async').text).toContain(` + expect(sources.get('Python Async')!.text).toContain(` await page.locator("canvas").click(position={"x":250,"y":250})`); - expect(sources.get('Java').text).toContain(` + expect(sources.get('Java')!.text).toContain(` page.locator("canvas").click(new Locator.ClickOptions() .setPosition(250, 250));`); - expect(sources.get('C#').text).toContain(` + expect(sources.get('C#')!.text).toContain(` await page.Locator("canvas").ClickAsync(new LocatorClickOptions { Position = new Position @@ -175,19 +175,19 @@ test.describe('cli codegen', () => { recorder.trustedClick(), ]); - expect.soft(sources.get('JavaScript').text).toContain(` + expect.soft(sources.get('JavaScript')!.text).toContain(` await page.getByRole('button', { name: 'Submit' }).click();`); - expect.soft(sources.get('Python').text).toContain(` + expect.soft(sources.get('Python')!.text).toContain(` page.get_by_role("button", name="Submit").click()`); - expect.soft(sources.get('Python Async').text).toContain(` + expect.soft(sources.get('Python Async')!.text).toContain(` await page.get_by_role("button", name="Submit").click()`); - expect.soft(sources.get('Java').text).toContain(` + expect.soft(sources.get('Java')!.text).toContain(` page.getByRole(AriaRole.BUTTON, new Page.GetByRoleOptions().setName("Submit")).click()`); - expect.soft(sources.get('C#').text).toContain(` + expect.soft(sources.get('C#')!.text).toContain(` await page.GetByRole(AriaRole.Button, new() { Name = "Submit" }).ClickAsync();`); expect(message.text()).toBe('click'); @@ -219,7 +219,7 @@ test.describe('cli codegen', () => { recorder.waitForOutput('JavaScript', 'click'), recorder.trustedMove('div').then(() => recorder.trustedClick()), ]); - expect(sources.get('JavaScript').text).toContain(` + expect(sources.get('JavaScript')!.text).toContain(` await page.getByText('Some long text here').click();`); expect(message.text()).toBe('click'); }); @@ -237,18 +237,18 @@ test.describe('cli codegen', () => { page.fill('input', 'John') ]); - expect(sources.get('JavaScript').text).toContain(` + expect(sources.get('JavaScript')!.text).toContain(` await page.locator('#input').fill('John');`); - expect(sources.get('Java').text).toContain(` + expect(sources.get('Java')!.text).toContain(` page.locator("#input").fill("John");`); - expect(sources.get('Python').text).toContain(` + expect(sources.get('Python')!.text).toContain(` page.locator("#input").fill(\"John\")`); - expect(sources.get('Python Async').text).toContain(` + expect(sources.get('Python Async')!.text).toContain(` await page.locator("#input").fill(\"John\")`); - expect(sources.get('C#').text).toContain(` + expect(sources.get('C#')!.text).toContain(` await page.Locator("#input").FillAsync(\"John\");`); expect(message.text()).toBe('John'); @@ -271,18 +271,18 @@ test.describe('cli codegen', () => { await recorder.page.dispatchEvent('input', 'keyup', { key: 'Process' }); })() ]); - expect(sources.get('JavaScript').text).toContain(` + expect(sources.get('JavaScript')!.text).toContain(` await page.locator('#input').fill('てすと');`); - expect(sources.get('Java').text).toContain(` + expect(sources.get('Java')!.text).toContain(` page.locator("#input").fill("てすと");`); - expect(sources.get('Python').text).toContain(` + expect(sources.get('Python')!.text).toContain(` page.locator("#input").fill(\"てすと\")`); - expect(sources.get('Python Async').text).toContain(` + expect(sources.get('Python Async')!.text).toContain(` await page.locator("#input").fill(\"てすと\")`); - expect(sources.get('C#').text).toContain(` + expect(sources.get('C#')!.text).toContain(` await page.Locator("#input").FillAsync(\"てすと\");`); expect(message.text()).toBe('てすと'); @@ -300,7 +300,7 @@ test.describe('cli codegen', () => { recorder.waitForOutput('JavaScript', 'fill'), page.fill('textarea', 'John') ]); - expect(sources.get('JavaScript').text).toContain(` + expect(sources.get('JavaScript')!.text).toContain(` await page.locator('#textarea').fill('John');`); expect(message.text()).toBe('John'); }); @@ -316,8 +316,8 @@ test.describe('cli codegen', () => { // Issue was that the input event was not fired for the last newline, so we check for that. await page.waitForFunction(() => (window as any).lastInputValue === 'Hello\n'); const sources = await waitForOutputPromise; - expect(sources.get('JavaScript').text).toContain(`await page.locator('#textarea').fill('Hello\\n');`); - expect(sources.get('JavaScript').text).not.toContain(`Enter`); + expect(sources.get('JavaScript')!.text).toContain(`await page.locator('#textarea').fill('Hello\\n');`); + expect(sources.get('JavaScript')!.text).not.toContain(`Enter`); }); test('should fill [contentEditable]', async ({ page, openRecorder }) => { @@ -332,7 +332,7 @@ test.describe('cli codegen', () => { recorder.waitForOutput('JavaScript', 'fill'), page.fill('div', 'John Doe') ]); - expect(sources.get('JavaScript').text).toContain(` + expect(sources.get('JavaScript')!.text).toContain(` await page.locator('#content').fill('John Doe');`); expect(message.text()).toBe('John Doe'); }); @@ -353,19 +353,19 @@ test.describe('cli codegen', () => { page.press('input', 'Shift+Enter') ]); - expect(sources.get('JavaScript').text).toContain(` + expect(sources.get('JavaScript')!.text).toContain(` await page.getByRole('textbox').press('Shift+Enter');`); - expect(sources.get('Java').text).toContain(` + expect(sources.get('Java')!.text).toContain(` page.getByRole(AriaRole.TEXTBOX).press("Shift+Enter");`); - expect(sources.get('Python').text).toContain(` + expect(sources.get('Python')!.text).toContain(` page.get_by_role("textbox").press("Shift+Enter")`); - expect(sources.get('Python Async').text).toContain(` + expect(sources.get('Python Async')!.text).toContain(` await page.get_by_role("textbox").press("Shift+Enter")`); - expect(sources.get('C#').text).toContain(` + expect(sources.get('C#')!.text).toContain(` await page.GetByRole(AriaRole.Textbox).PressAsync("Shift+Enter");`); expect(messages[0].text()).toBe('press'); @@ -389,7 +389,7 @@ test.describe('cli codegen', () => { await page.keyboard.type('barfoo321'); await recorder.waitForOutput('JavaScript', 'barfoo321'); - const text = recorder.sources().get('JavaScript').text; + const text = recorder.sources().get('JavaScript')!.text; expect(text).toContain(` await page.locator('input[name="one"]').fill('foobar123');`); @@ -417,7 +417,7 @@ test.describe('cli codegen', () => { recorder.waitForOutput('JavaScript', 'press'), page.press('input', 'ArrowDown') ]); - expect(sources.get('JavaScript').text).toContain(` + expect(sources.get('JavaScript')!.text).toContain(` await page.getByRole('textbox').press('ArrowDown');`); expect(messages[0].text()).toBe('press:ArrowDown'); }); @@ -440,7 +440,7 @@ test.describe('cli codegen', () => { recorder.waitForOutput('JavaScript', 'press'), page.press('input', 'ArrowDown') ]); - expect(sources.get('JavaScript').text).toContain(` + expect(sources.get('JavaScript')!.text).toContain(` await page.getByRole('textbox').press('ArrowDown');`); expect(messages.length).toBe(2); expect(messages[0].text()).toBe('down:ArrowDown'); @@ -461,19 +461,19 @@ test.describe('cli codegen', () => { page.click('input') ]); - expect(sources.get('JavaScript').text).toContain(` + expect(sources.get('JavaScript')!.text).toContain(` await page.locator('#checkbox').check();`); - expect(sources.get('Java').text).toContain(` + expect(sources.get('Java')!.text).toContain(` page.locator("#checkbox").check();`); - expect(sources.get('Python').text).toContain(` + expect(sources.get('Python')!.text).toContain(` page.locator("#checkbox").check()`); - expect(sources.get('Python Async').text).toContain(` + expect(sources.get('Python Async')!.text).toContain(` await page.locator("#checkbox").check()`); - expect(sources.get('C#').text).toContain(` + expect(sources.get('C#')!.text).toContain(` await page.Locator("#checkbox").CheckAsync();`); expect(message.text()).toBe('true'); @@ -493,7 +493,7 @@ test.describe('cli codegen', () => { page.click('input') ]); - expect(sources.get('JavaScript').text).toContain(` + expect(sources.get('JavaScript')!.text).toContain(` await page.locator('#checkbox').check();`); expect(message.text()).toBe('true'); }); @@ -512,7 +512,7 @@ test.describe('cli codegen', () => { page.keyboard.press('Space') ]); - expect(sources.get('JavaScript').text).toContain(` + expect(sources.get('JavaScript')!.text).toContain(` await page.locator('#checkbox').check();`); expect(message.text()).toBe('true'); }); @@ -531,19 +531,19 @@ test.describe('cli codegen', () => { page.click('input') ]); - expect(sources.get('JavaScript').text).toContain(` + expect(sources.get('JavaScript')!.text).toContain(` await page.locator('#checkbox').uncheck();`); - expect(sources.get('Java').text).toContain(` + expect(sources.get('Java')!.text).toContain(` page.locator("#checkbox").uncheck();`); - expect(sources.get('Python').text).toContain(` + expect(sources.get('Python')!.text).toContain(` page.locator("#checkbox").uncheck()`); - expect(sources.get('Python Async').text).toContain(` + expect(sources.get('Python Async')!.text).toContain(` await page.locator("#checkbox").uncheck()`); - expect(sources.get('C#').text).toContain(` + expect(sources.get('C#')!.text).toContain(` await page.Locator("#checkbox").UncheckAsync();`); expect(message.text()).toBe('false'); @@ -563,19 +563,19 @@ test.describe('cli codegen', () => { page.selectOption('select', '2') ]); - expect(sources.get('JavaScript').text).toContain(` + expect(sources.get('JavaScript')!.text).toContain(` await page.locator('#age').selectOption('2');`); - expect(sources.get('Java').text).toContain(` + expect(sources.get('Java')!.text).toContain(` page.locator("#age").selectOption("2");`); - expect(sources.get('Python').text).toContain(` + expect(sources.get('Python')!.text).toContain(` page.locator("#age").select_option("2")`); - expect(sources.get('Python Async').text).toContain(` + expect(sources.get('Python Async')!.text).toContain(` await page.locator("#age").select_option("2")`); - expect(sources.get('C#').text).toContain(` + expect(sources.get('C#')!.text).toContain(` await page.Locator("#age").SelectOptionAsync(new[] { "2" });`); expect(message.text()).toBe('2'); @@ -604,19 +604,19 @@ test.describe('cli codegen', () => { page.mouse.click(10, 25) ]); - expect(sources.get('JavaScript').text).toContain(` + expect(sources.get('JavaScript')!.text).toContain(` await page.locator('#age').selectOption('2');`); - expect(sources.get('Java').text).toContain(` + expect(sources.get('Java')!.text).toContain(` page.locator("#age").selectOption("2");`); - expect(sources.get('Python').text).toContain(` + expect(sources.get('Python')!.text).toContain(` page.locator(\"#age\").select_option(\"2\")`); - expect(sources.get('Python Async').text).toContain(` + expect(sources.get('Python Async')!.text).toContain(` await page.locator(\"#age\").select_option(\"2\")`); - expect(sources.get('C#').text).toContain(` + expect(sources.get('C#')!.text).toContain(` await page.Locator(\"#age\").SelectOptionAsync(new[] { \"2\" });`); expect(message.text()).toBe('2'); @@ -635,27 +635,27 @@ test.describe('cli codegen', () => { recorder.trustedClick(), ]); - expect.soft(sources.get('JavaScript').text).toContain(` + expect.soft(sources.get('JavaScript')!.text).toContain(` const page1Promise = page.waitForEvent('popup'); await page.getByRole('link', { name: 'link' }).click(); const page1 = await page1Promise;`); - expect.soft(sources.get('Java').text).toContain(` + expect.soft(sources.get('Java')!.text).toContain(` Page page1 = page.waitForPopup(() -> { page.getByRole(AriaRole.LINK, new Page.GetByRoleOptions().setName("link")).click(); });`); - expect.soft(sources.get('Python').text).toContain(` + expect.soft(sources.get('Python')!.text).toContain(` with page.expect_popup() as page1_info: page.get_by_role("link", name="link").click() page1 = page1_info.value`); - expect.soft(sources.get('Python Async').text).toContain(` + expect.soft(sources.get('Python Async')!.text).toContain(` async with page.expect_popup() as page1_info: await page.get_by_role("link", name="link").click() page1 = await page1_info.value`); - expect.soft(sources.get('C#').text).toContain(` + expect.soft(sources.get('C#')!.text).toContain(` var page1 = await page.RunAndWaitForPopupAsync(async () => { await page.GetByRole(AriaRole.Link, new() { Name = "link" }).ClickAsync(); @@ -677,25 +677,25 @@ test.describe('cli codegen', () => { recorder.trustedClick(), ]); - expect.soft(sources.get('JavaScript').text).toContain(` + expect.soft(sources.get('JavaScript')!.text).toContain(` await page.getByText('link').click();`); - expect.soft(sources.get('Playwright Test').text).toContain(` + expect.soft(sources.get('Playwright Test')!.text).toContain(` await page.getByText('link').click();`); - expect.soft(sources.get('Java').text).toContain(` + expect.soft(sources.get('Java')!.text).toContain(` page.getByText("link").click();`); - expect.soft(sources.get('Python').text).toContain(` + expect.soft(sources.get('Python')!.text).toContain(` page.get_by_text("link").click()`); - expect.soft(sources.get('Python Async').text).toContain(` + expect.soft(sources.get('Python Async')!.text).toContain(` await page.get_by_text("link").click()`); - expect.soft(sources.get('Pytest').text).toContain(` + expect.soft(sources.get('Pytest')!.text).toContain(` page.get_by_text("link").click()`); - expect.soft(sources.get('C#').text).toContain(` + expect.soft(sources.get('C#')!.text).toContain(` await page.GetByText("link").ClickAsync();`); expect(page.url()).toContain('about:blank#foo'); @@ -711,8 +711,8 @@ test.describe('cli codegen', () => { await recorder.page.keyboard.insertText('@'); await recorder.page.keyboard.type('example.com'); await recorder.waitForOutput('JavaScript', 'example.com'); - expect(recorder.sources().get('JavaScript').text).not.toContain(`await page.getByRole('textbox').press('AltGraph');`); - expect(recorder.sources().get('JavaScript').text).toContain(`await page.getByRole('textbox').fill('playwright@example.com');`); + expect(recorder.sources().get('JavaScript')!.text).not.toContain(`await page.getByRole('textbox').press('AltGraph');`); + expect(recorder.sources().get('JavaScript')!.text).toContain(`await page.getByRole('textbox').fill('playwright@example.com');`); }); test('should middle click', async ({ page, openRecorder, server }) => { @@ -725,22 +725,22 @@ test.describe('cli codegen', () => { page.click('a', { button: 'middle' }), ]); - expect(sources.get('JavaScript').text).toContain(` + expect(sources.get('JavaScript')!.text).toContain(` await page.getByText('Click me').click({ button: 'middle' });`); - expect(sources.get('Python').text).toContain(` + expect(sources.get('Python')!.text).toContain(` page.get_by_text("Click me").click(button="middle")`); - expect(sources.get('Python Async').text).toContain(` + expect(sources.get('Python Async')!.text).toContain(` await page.get_by_text("Click me").click(button="middle")`); - expect(sources.get('Java').text).toContain(` + expect(sources.get('Java')!.text).toContain(` page.getByText("Click me").click(new Locator.ClickOptions() .setButton(MouseButton.MIDDLE));`); - expect(sources.get('C#').text).toContain(` + expect(sources.get('C#')!.text).toContain(` await page.GetByText("Click me").ClickAsync(new LocatorClickOptions { Button = MouseButton.Middle, diff --git a/tests/library/inspector/cli-codegen-2.spec.ts b/tests/library/inspector/cli-codegen-2.spec.ts index 50b4be415d..1f1b673b36 100644 --- a/tests/library/inspector/cli-codegen-2.spec.ts +++ b/tests/library/inspector/cli-codegen-2.spec.ts @@ -27,19 +27,19 @@ test.describe('cli codegen', () => { await recorder.setContentAndWait(``); const sources = await recorder.waitForOutput('JavaScript', `page.goto`); - expect(sources.get('JavaScript').text).toContain(` + expect(sources.get('JavaScript')!.text).toContain(` const page = await context.newPage();`); - expect(sources.get('Java').text).toContain(` + expect(sources.get('Java')!.text).toContain(` Page page = context.newPage();`); - expect(sources.get('Python').text).toContain(` + expect(sources.get('Python')!.text).toContain(` page = context.new_page()`); - expect(sources.get('Python Async').text).toContain(` + expect(sources.get('Python Async')!.text).toContain(` page = await context.new_page()`); - expect(sources.get('C#').text).toContain(` + expect(sources.get('C#')!.text).toContain(` var page = await context.NewPageAsync();`); }); @@ -50,19 +50,19 @@ test.describe('cli codegen', () => { await page.context().newPage(); const sources = await recorder.waitForOutput('JavaScript', 'page1'); - expect(sources.get('JavaScript').text).toContain(` + expect(sources.get('JavaScript')!.text).toContain(` const page1 = await context.newPage();`); - expect(sources.get('Java').text).toContain(` + expect(sources.get('Java')!.text).toContain(` Page page1 = context.newPage();`); - expect(sources.get('Python').text).toContain(` + expect(sources.get('Python')!.text).toContain(` page1 = context.new_page()`); - expect(sources.get('Python Async').text).toContain(` + expect(sources.get('Python Async')!.text).toContain(` page1 = await context.new_page()`); - expect(sources.get('C#').text).toContain(` + expect(sources.get('C#')!.text).toContain(` var page1 = await context.NewPageAsync();`); }); @@ -74,19 +74,19 @@ test.describe('cli codegen', () => { await recorder.page.close(); const sources = await recorder.waitForOutput('JavaScript', 'page.close();'); - expect(sources.get('JavaScript').text).toContain(` + expect(sources.get('JavaScript')!.text).toContain(` await page.close();`); - expect(sources.get('Java').text).toContain(` + expect(sources.get('Java')!.text).toContain(` page.close();`); - expect(sources.get('Python').text).toContain(` + expect(sources.get('Python')!.text).toContain(` page.close()`); - expect(sources.get('Python Async').text).toContain(` + expect(sources.get('Python Async')!.text).toContain(` await page.close()`); - expect(sources.get('C#').text).toContain(` + expect(sources.get('C#')!.text).toContain(` await page.CloseAsync();`); }); @@ -97,7 +97,7 @@ test.describe('cli codegen', () => { await page.context().newPage(); const errors: any[] = []; recorder.page.on('pageerror', e => errors.push(e)); - await recorder.page.evaluate(() => document.querySelector('body').remove()); + await recorder.page.evaluate(() => document.querySelector('body')!.remove()); await page.dispatchEvent('html', 'mousemove', { detail: 1 }); await recorder.page.close(); await recorder.waitForOutput('JavaScript', 'page.close();'); @@ -119,19 +119,19 @@ test.describe('cli codegen', () => { const sources = await recorder.waitForOutput('JavaScript', 'setInputFiles'); - expect(sources.get('JavaScript').text).toContain(` + expect(sources.get('JavaScript')!.text).toContain(` await page.getByRole('textbox').setInputFiles('file-to-upload.txt');`); - expect(sources.get('Java').text).toContain(` + expect(sources.get('Java')!.text).toContain(` page.getByRole(AriaRole.TEXTBOX).setInputFiles(Paths.get("file-to-upload.txt"));`); - expect(sources.get('Python').text).toContain(` + expect(sources.get('Python')!.text).toContain(` page.get_by_role("textbox").set_input_files(\"file-to-upload.txt\")`); - expect(sources.get('Python Async').text).toContain(` + expect(sources.get('Python Async')!.text).toContain(` await page.get_by_role("textbox").set_input_files(\"file-to-upload.txt\")`); - expect(sources.get('C#').text).toContain(` + expect(sources.get('C#')!.text).toContain(` await page.GetByRole(AriaRole.Textbox).SetInputFilesAsync(new[] { \"file-to-upload.txt\" });`); }); @@ -150,19 +150,19 @@ test.describe('cli codegen', () => { const sources = await recorder.waitForOutput('JavaScript', 'setInputFiles'); - expect(sources.get('JavaScript').text).toContain(` + expect(sources.get('JavaScript')!.text).toContain(` await page.getByRole('textbox').setInputFiles(['file-to-upload.txt', 'file-to-upload-2.txt']);`); - expect(sources.get('Java').text).toContain(` + expect(sources.get('Java')!.text).toContain(` page.getByRole(AriaRole.TEXTBOX).setInputFiles(new Path[] {Paths.get("file-to-upload.txt"), Paths.get("file-to-upload-2.txt")});`); - expect(sources.get('Python').text).toContain(` + expect(sources.get('Python')!.text).toContain(` page.get_by_role("textbox").set_input_files([\"file-to-upload.txt\", \"file-to-upload-2.txt\"]`); - expect(sources.get('Python Async').text).toContain(` + expect(sources.get('Python Async')!.text).toContain(` await page.get_by_role("textbox").set_input_files([\"file-to-upload.txt\", \"file-to-upload-2.txt\"]`); - expect(sources.get('C#').text).toContain(` + expect(sources.get('C#')!.text).toContain(` await page.GetByRole(AriaRole.Textbox).SetInputFilesAsync(new[] { \"file-to-upload.txt\", \"file-to-upload-2.txt\" });`); }); @@ -181,19 +181,19 @@ test.describe('cli codegen', () => { const sources = await recorder.waitForOutput('JavaScript', 'setInputFiles'); - expect(sources.get('JavaScript').text).toContain(` + expect(sources.get('JavaScript')!.text).toContain(` await page.getByRole('textbox').setInputFiles([]);`); - expect(sources.get('Java').text).toContain(` + expect(sources.get('Java')!.text).toContain(` page.getByRole(AriaRole.TEXTBOX).setInputFiles(new Path[0]);`); - expect(sources.get('Python').text).toContain(` + expect(sources.get('Python')!.text).toContain(` page.get_by_role("textbox").set_input_files([])`); - expect(sources.get('Python Async').text).toContain(` + expect(sources.get('Python Async')!.text).toContain(` await page.get_by_role("textbox").set_input_files([])`); - expect(sources.get('C#').text).toContain(` + expect(sources.get('C#')!.text).toContain(` await page.GetByRole(AriaRole.Textbox).SetInputFilesAsync(new[] { });`); }); @@ -225,48 +225,48 @@ test.describe('cli codegen', () => { ]); const sources = await recorder.waitForOutput('JavaScript', 'download1Promise'); - expect.soft(sources.get('JavaScript').text).toContain(` + expect.soft(sources.get('JavaScript')!.text).toContain(` const downloadPromise = page.waitForEvent('download'); await page.getByRole('link', { name: 'Download' }).click(); const download = await downloadPromise;`); - expect.soft(sources.get('JavaScript').text).toContain(` + expect.soft(sources.get('JavaScript')!.text).toContain(` const download1Promise = page.waitForEvent('download'); await page.getByRole('link', { name: 'Download' }).click(); const download1 = await download1Promise;`); - expect.soft(sources.get('Java').text).toContain(` + expect.soft(sources.get('Java')!.text).toContain(` Download download = page.waitForDownload(() -> { page.getByRole(AriaRole.LINK, new Page.GetByRoleOptions().setName("Download")).click(); });`); - expect.soft(sources.get('Java').text).toContain(` + expect.soft(sources.get('Java')!.text).toContain(` Download download1 = page.waitForDownload(() -> { page.getByRole(AriaRole.LINK, new Page.GetByRoleOptions().setName("Download")).click(); });`); - expect.soft(sources.get('Python').text).toContain(` + expect.soft(sources.get('Python')!.text).toContain(` with page.expect_download() as download_info: page.get_by_role("link", name="Download").click() download = download_info.value`); - expect.soft(sources.get('Python').text).toContain(` + expect.soft(sources.get('Python')!.text).toContain(` with page.expect_download() as download1_info: page.get_by_role("link", name="Download").click() download1 = download1_info.value`); - expect.soft(sources.get('Python Async').text).toContain(` + expect.soft(sources.get('Python Async')!.text).toContain(` async with page.expect_download() as download_info: await page.get_by_role("link", name="Download").click() download = await download_info.value`); - expect.soft(sources.get('Python Async').text).toContain(` + expect.soft(sources.get('Python Async')!.text).toContain(` async with page.expect_download() as download1_info: await page.get_by_role("link", name="Download").click() download1 = await download1_info.value`); - expect.soft(sources.get('C#').text).toContain(` + expect.soft(sources.get('C#')!.text).toContain(` var download = await page.RunAndWaitForDownloadAsync(async () => { await page.GetByRole(AriaRole.Link, new() { Name = "Download" }).ClickAsync(); });`); - expect.soft(sources.get('C#').text).toContain(` + expect.soft(sources.get('C#')!.text).toContain(` var download1 = await page.RunAndWaitForDownloadAsync(async () => { await page.GetByRole(AriaRole.Link, new() { Name = "Download" }).ClickAsync(); @@ -287,29 +287,29 @@ test.describe('cli codegen', () => { const sources = await recorder.waitForOutput('JavaScript', 'once'); - expect.soft(sources.get('JavaScript').text).toContain(` + expect.soft(sources.get('JavaScript')!.text).toContain(` page.once('dialog', dialog => { console.log(\`Dialog message: \${dialog.message()}\`); dialog.dismiss().catch(() => {}); }); await page.getByRole('button', { name: 'click me' }).click();`); - expect.soft(sources.get('Java').text).toContain(` + expect.soft(sources.get('Java')!.text).toContain(` page.onceDialog(dialog -> { System.out.println(String.format("Dialog message: %s", dialog.message())); dialog.dismiss(); }); page.getByRole(AriaRole.BUTTON, new Page.GetByRoleOptions().setName("click me")).click();`); - expect.soft(sources.get('Python').text).toContain(` + expect.soft(sources.get('Python')!.text).toContain(` page.once(\"dialog\", lambda dialog: dialog.dismiss()) page.get_by_role("button", name="click me").click()`); - expect.soft(sources.get('Python Async').text).toContain(` + expect.soft(sources.get('Python Async')!.text).toContain(` page.once(\"dialog\", lambda dialog: dialog.dismiss()) await page.get_by_role("button", name="click me").click()`); - expect.soft(sources.get('C#').text).toContain(` + expect.soft(sources.get('C#')!.text).toContain(` void page_Dialog_EventHandler(object sender, IDialog dialog) { Console.WriteLine($\"Dialog message: {dialog.Message}\"); @@ -348,17 +348,17 @@ test.describe('cli codegen', () => { const sources = await recorder.waitForOutput('JavaScript', 'page1'); if (browserName !== 'firefox') { - expect(sources.get('JavaScript').text).toContain(` + expect(sources.get('JavaScript')!.text).toContain(` const page1 = await context.newPage(); await page1.goto('about:blank?foo');`); - expect(sources.get('Python Async').text).toContain(` + expect(sources.get('Python Async')!.text).toContain(` page1 = await context.new_page() await page1.goto("about:blank?foo")`); - expect(sources.get('C#').text).toContain(` + expect(sources.get('C#')!.text).toContain(` var page1 = await context.NewPageAsync(); await page1.GotoAsync("about:blank?foo");`); } else { - expect(sources.get('JavaScript').text).toContain(` + expect(sources.get('JavaScript')!.text).toContain(` const page1Promise = page.waitForEvent('popup'); await page.getByRole('link', { name: 'link' }).click({ modifiers: ['${platform === 'darwin' ? 'Meta' : 'Control'}'] @@ -388,20 +388,20 @@ test.describe('cli codegen', () => { await recorder.waitForOutput('JavaScript', 'TextB'); const sources = recorder.sources(); - expect(sources.get('JavaScript').text).toContain(`await page1.locator('#name').fill('TextA');`); - expect(sources.get('JavaScript').text).toContain(`await page2.locator('#name').fill('TextB');`); + expect(sources.get('JavaScript')!.text).toContain(`await page1.locator('#name').fill('TextA');`); + expect(sources.get('JavaScript')!.text).toContain(`await page2.locator('#name').fill('TextB');`); - expect(sources.get('Java').text).toContain(`page1.locator("#name").fill("TextA");`); - expect(sources.get('Java').text).toContain(`page2.locator("#name").fill("TextB");`); + expect(sources.get('Java')!.text).toContain(`page1.locator("#name").fill("TextA");`); + expect(sources.get('Java')!.text).toContain(`page2.locator("#name").fill("TextB");`); - expect(sources.get('Python').text).toContain(`page1.locator("#name").fill("TextA")`); - expect(sources.get('Python').text).toContain(`page2.locator("#name").fill("TextB")`); + expect(sources.get('Python')!.text).toContain(`page1.locator("#name").fill("TextA")`); + expect(sources.get('Python')!.text).toContain(`page2.locator("#name").fill("TextB")`); - expect(sources.get('Python Async').text).toContain(`await page1.locator("#name").fill("TextA")`); - expect(sources.get('Python Async').text).toContain(`await page2.locator("#name").fill("TextB")`); + expect(sources.get('Python Async')!.text).toContain(`await page1.locator("#name").fill("TextA")`); + expect(sources.get('Python Async')!.text).toContain(`await page2.locator("#name").fill("TextB")`); - expect(sources.get('C#').text).toContain(`await page1.Locator("#name").FillAsync("TextA");`); - expect(sources.get('C#').text).toContain(`await page2.Locator("#name").FillAsync("TextB");`); + expect(sources.get('C#')!.text).toContain(`await page1.Locator("#name").FillAsync("TextA");`); + expect(sources.get('C#')!.text).toContain(`await page2.Locator("#name").FillAsync("TextB");`); }); test('click should emit events in order', async ({ page, openRecorder }) => { @@ -528,19 +528,19 @@ test.describe('cli codegen', () => { page.fill('textarea', 'Hello\'\"\`\nWorld') ]); - expect(sources.get('JavaScript').text).toContain(` + expect(sources.get('JavaScript')!.text).toContain(` await page.locator('#textarea').fill('Hello\\'"\`\\nWorld');`); - expect(sources.get('Java').text).toContain(` + expect(sources.get('Java')!.text).toContain(` page.locator("#textarea").fill("Hello'\\"\`\\nWorld");`); - expect(sources.get('Python').text).toContain(` + expect(sources.get('Python')!.text).toContain(` page.locator("#textarea").fill(\"Hello'\\"\`\\nWorld\")`); - expect(sources.get('Python Async').text).toContain(` + expect(sources.get('Python Async')!.text).toContain(` await page.locator("#textarea").fill(\"Hello'\\"\`\\nWorld\")`); - expect(sources.get('C#').text).toContain(` + expect(sources.get('C#')!.text).toContain(` await page.Locator("#textarea").FillAsync(\"Hello'\\"\`\\nWorld\");`); expect(message.text()).toBe('Hello\'\"\`\nWorld'); @@ -555,9 +555,9 @@ test('should --test-id-attribute', async ({ page, openRecorder }) => { await page.click('[my-test-id=foo]'); const sources = await recorder.waitForOutput('JavaScript', `page.getByTestId`); - expect.soft(sources.get('JavaScript').text).toContain(`await page.getByTestId('foo').click()`); - expect.soft(sources.get('Java').text).toContain(`page.getByTestId("foo").click()`); - expect.soft(sources.get('Python').text).toContain(`page.get_by_test_id("foo").click()`); - expect.soft(sources.get('Python Async').text).toContain(`await page.get_by_test_id("foo").click()`); - expect.soft(sources.get('C#').text).toContain(`await page.GetByTestId("foo").ClickAsync();`); + expect.soft(sources.get('JavaScript')!.text).toContain(`await page.getByTestId('foo').click()`); + expect.soft(sources.get('Java')!.text).toContain(`page.getByTestId("foo").click()`); + expect.soft(sources.get('Python')!.text).toContain(`page.get_by_test_id("foo").click()`); + expect.soft(sources.get('Python Async')!.text).toContain(`await page.get_by_test_id("foo").click()`); + expect.soft(sources.get('C#')!.text).toContain(`await page.GetByTestId("foo").ClickAsync();`); }); diff --git a/tests/library/inspector/cli-codegen-3.spec.ts b/tests/library/inspector/cli-codegen-3.spec.ts index 856fc06feb..c8858832f7 100644 --- a/tests/library/inspector/cli-codegen-3.spec.ts +++ b/tests/library/inspector/cli-codegen-3.spec.ts @@ -36,19 +36,19 @@ test.describe('cli codegen', () => { recorder.trustedClick() ]); - expect.soft(sources.get('JavaScript').text).toContain(` + expect.soft(sources.get('JavaScript')!.text).toContain(` await page.getByRole('button', { name: 'Submit' }).first().click();`); - expect.soft(sources.get('Python').text).toContain(` + expect.soft(sources.get('Python')!.text).toContain(` page.get_by_role("button", name="Submit").first.click()`); - expect.soft(sources.get('Python Async').text).toContain(` + expect.soft(sources.get('Python Async')!.text).toContain(` await page.get_by_role("button", name="Submit").first.click()`); - expect.soft(sources.get('Java').text).toContain(` + expect.soft(sources.get('Java')!.text).toContain(` page.getByRole(AriaRole.BUTTON, new Page.GetByRoleOptions().setName("Submit")).first().click();`); - expect.soft(sources.get('C#').text).toContain(` + expect.soft(sources.get('C#')!.text).toContain(` await page.GetByRole(AriaRole.Button, new() { Name = "Submit" }).First.ClickAsync();`); expect(message.text()).toBe('click1'); @@ -71,19 +71,19 @@ test.describe('cli codegen', () => { recorder.trustedClick() ]); - expect.soft(sources.get('JavaScript').text).toContain(` + expect.soft(sources.get('JavaScript')!.text).toContain(` await page.getByRole('button', { name: 'Submit' }).nth(1).click();`); - expect.soft(sources.get('Python').text).toContain(` + expect.soft(sources.get('Python')!.text).toContain(` page.get_by_role("button", name="Submit").nth(1).click()`); - expect.soft(sources.get('Python Async').text).toContain(` + expect.soft(sources.get('Python Async')!.text).toContain(` await page.get_by_role("button", name="Submit").nth(1).click()`); - expect.soft(sources.get('Java').text).toContain(` + expect.soft(sources.get('Java')!.text).toContain(` page.getByRole(AriaRole.BUTTON, new Page.GetByRoleOptions().setName("Submit")).nth(1).click();`); - expect.soft(sources.get('C#').text).toContain(` + expect.soft(sources.get('C#')!.text).toContain(` await page.GetByRole(AriaRole.Button, new() { Name = "Submit" }).Nth(1).ClickAsync();`); expect(message.text()).toBe('click2'); @@ -108,11 +108,11 @@ test.describe('cli codegen', () => { `, server.EMPTY_PAGE, 6); const frameHello1 = page.mainFrame().childFrames()[0]; const frameHello2 = frameHello1.childFrames()[0]; - const frameOne = page.frame({ name: 'one' }); + const frameOne = page.frame({ name: 'one' })!; await frameOne.setContent(`
HelloNameOne
`); - const frameTwo = page.frame({ name: 'two' }); + const frameTwo = page.frame({ name: 'two' })!; await frameTwo.setContent(`
HelloNameTwo
`); - const frameAnonymous = frameHello2.childFrames().find(f => !f.name()); + const frameAnonymous = frameHello2.childFrames().find(f => !f.name())!; await frameAnonymous.setContent(`
HelloNameAnonymous
`); let [sources] = await Promise.all([ @@ -120,19 +120,19 @@ test.describe('cli codegen', () => { frameHello1.click('text=Hello1'), ]); - expect(sources.get('JavaScript').text).toContain(` + expect(sources.get('JavaScript')!.text).toContain(` await page.frameLocator('#frame1').getByText('Hello1').click();`); - expect(sources.get('Java').text).toContain(` + expect(sources.get('Java')!.text).toContain(` page.frameLocator("#frame1").getByText("Hello1").click();`); - expect(sources.get('Python').text).toContain(` + expect(sources.get('Python')!.text).toContain(` page.frame_locator("#frame1").get_by_text("Hello1").click()`); - expect(sources.get('Python Async').text).toContain(` + expect(sources.get('Python Async')!.text).toContain(` await page.frame_locator("#frame1").get_by_text("Hello1").click()`); - expect(sources.get('C#').text).toContain(` + expect(sources.get('C#')!.text).toContain(` await page.FrameLocator("#frame1").GetByText("Hello1").ClickAsync();`); @@ -141,19 +141,19 @@ test.describe('cli codegen', () => { frameHello2.click('text=Hello2'), ]); - expect.soft(sources.get('JavaScript').text).toContain(` + expect.soft(sources.get('JavaScript')!.text).toContain(` await page.frameLocator('#frame1').frameLocator('iframe').getByText('Hello2').click();`); - expect.soft(sources.get('Java').text).toContain(` + expect.soft(sources.get('Java')!.text).toContain(` page.frameLocator("#frame1").frameLocator("iframe").getByText("Hello2").click();`); - expect.soft(sources.get('Python').text).toContain(` + expect.soft(sources.get('Python')!.text).toContain(` page.frame_locator("#frame1").frame_locator("iframe").get_by_text("Hello2").click()`); - expect.soft(sources.get('Python Async').text).toContain(` + expect.soft(sources.get('Python Async')!.text).toContain(` await page.frame_locator("#frame1").frame_locator("iframe").get_by_text("Hello2").click()`); - expect.soft(sources.get('C#').text).toContain(` + expect.soft(sources.get('C#')!.text).toContain(` await page.FrameLocator("#frame1").FrameLocator("iframe").GetByText("Hello2").ClickAsync();`); @@ -162,21 +162,21 @@ test.describe('cli codegen', () => { frameOne.click('text=HelloNameOne'), ]); - expect.soft(sources.get('JavaScript').text).toContain(` + expect.soft(sources.get('JavaScript')!.text).toContain(` await page.frame({ name: 'one' }).getByText('HelloNameOne').click();`); - expect.soft(sources.get('Java').text).toContain(` + expect.soft(sources.get('Java')!.text).toContain(` page.frame("one").getByText("HelloNameOne").click();`); - expect.soft(sources.get('Python').text).toContain(` + expect.soft(sources.get('Python')!.text).toContain(` page.frame(name=\"one\").get_by_text(\"HelloNameOne\").click()`); - expect.soft(sources.get('Python Async').text).toContain(` + expect.soft(sources.get('Python Async')!.text).toContain(` await page.frame(name=\"one\").get_by_text(\"HelloNameOne\").click()`); - expect.soft(sources.get('C#').text).toContain(` + expect.soft(sources.get('C#')!.text).toContain(` await page.Frame(\"one\").GetByText(\"HelloNameOne\").ClickAsync();`); @@ -185,21 +185,21 @@ test.describe('cli codegen', () => { frameAnonymous.click('text=HelloNameAnonymous'), ]); - expect.soft(sources.get('JavaScript').text).toContain(` + expect.soft(sources.get('JavaScript')!.text).toContain(` await page.frame({ url: 'about:blank' }).getByText('HelloNameAnonymous').click();`); - expect.soft(sources.get('Java').text).toContain(` + expect.soft(sources.get('Java')!.text).toContain(` page.frameByUrl("about:blank").getByText("HelloNameAnonymous").click();`); - expect.soft(sources.get('Python').text).toContain(` + expect.soft(sources.get('Python')!.text).toContain(` page.frame(url=\"about:blank\").get_by_text(\"HelloNameAnonymous\").click()`); - expect.soft(sources.get('Python Async').text).toContain(` + expect.soft(sources.get('Python Async')!.text).toContain(` await page.frame(url=\"about:blank\").get_by_text(\"HelloNameAnonymous\").click()`); - expect.soft(sources.get('C#').text).toContain(` + expect.soft(sources.get('C#')!.text).toContain(` await page.FrameByUrl(\"about:blank\").GetByText(\"HelloNameAnonymous\").ClickAsync();`); }); @@ -214,23 +214,23 @@ test.describe('cli codegen', () => { page.frameLocator('[title="hello world"]').getByRole('button', { name: 'Click me' }).click(), ]); - expect(sources.get('JavaScript').text).toContain( + expect(sources.get('JavaScript')!.text).toContain( `await page.frameLocator('iframe[title="hello world"]').getByRole('button', { name: 'Click me' }).click();` ); - expect(sources.get('Java').text).toContain( + expect(sources.get('Java')!.text).toContain( `page.frameLocator(\"iframe[title=\\\"hello world\\\"]\").getByRole(AriaRole.BUTTON, new FrameLocator.GetByRoleOptions().setName(\"Click me\")).click();` ); - expect(sources.get('Python').text).toContain( + expect(sources.get('Python')!.text).toContain( `page.frame_locator(\"iframe[title=\\\"hello world\\\"]\").get_by_role(\"button\", name=\"Click me\").click()` ); - expect(sources.get('Python Async').text).toContain( + expect(sources.get('Python Async')!.text).toContain( `await page.frame_locator("iframe[title=\\\"hello world\\\"]").get_by_role("button", name="Click me").click()` ); - expect(sources.get('C#').text).toContain( + expect(sources.get('C#')!.text).toContain( `await page.FrameLocator("iframe[title=\\\"hello world\\\"]").GetByRole(AriaRole.Button, new() { Name = "Click me" }).ClickAsync();` ); }); @@ -246,23 +246,23 @@ test.describe('cli codegen', () => { page.frameLocator('[name="hello world"]').getByRole('button', { name: 'Click me' }).click(), ]); - expect(sources.get('JavaScript').text).toContain( + expect(sources.get('JavaScript')!.text).toContain( `await page.frameLocator('iframe[name="hello world"]').getByRole('button', { name: 'Click me' }).click();` ); - expect(sources.get('Java').text).toContain( + expect(sources.get('Java')!.text).toContain( `page.frameLocator(\"iframe[name=\\\"hello world\\\"]\").getByRole(AriaRole.BUTTON, new FrameLocator.GetByRoleOptions().setName(\"Click me\")).click();` ); - expect(sources.get('Python').text).toContain( + expect(sources.get('Python')!.text).toContain( `page.frame_locator(\"iframe[name=\\\"hello world\\\"]\").get_by_role(\"button\", name=\"Click me\").click()` ); - expect(sources.get('Python Async').text).toContain( + expect(sources.get('Python Async')!.text).toContain( `await page.frame_locator("iframe[name=\\\"hello world\\\"]").get_by_role("button", name="Click me").click()` ); - expect(sources.get('C#').text).toContain( + expect(sources.get('C#')!.text).toContain( `await page.FrameLocator("iframe[name=\\\"hello world\\\"]").GetByRole(AriaRole.Button, new() { Name = "Click me" }).ClickAsync();` ); }); @@ -278,23 +278,23 @@ test.describe('cli codegen', () => { page.frameLocator('[id="hello-world"]').getByRole('button', { name: 'Click me' }).click(), ]); - expect(sources.get('JavaScript').text).toContain( + expect(sources.get('JavaScript')!.text).toContain( `await page.frameLocator('#hello-world').getByRole('button', { name: 'Click me' }).click();` ); - expect(sources.get('Java').text).toContain( + expect(sources.get('Java')!.text).toContain( `page.frameLocator(\"#hello-world\").getByRole(AriaRole.BUTTON, new FrameLocator.GetByRoleOptions().setName(\"Click me\")).click();` ); - expect(sources.get('Python').text).toContain( + expect(sources.get('Python')!.text).toContain( `page.frame_locator(\"#hello-world\").get_by_role(\"button\", name=\"Click me\").click()` ); - expect(sources.get('Python Async').text).toContain( + expect(sources.get('Python Async')!.text).toContain( `await page.frame_locator("#hello-world").get_by_role("button", name="Click me").click()` ); - expect(sources.get('C#').text).toContain( + expect(sources.get('C#')!.text).toContain( `await page.FrameLocator("#hello-world").GetByRole(AriaRole.Button, new() { Name = "Click me" }).ClickAsync();` ); }); @@ -310,23 +310,23 @@ test.describe('cli codegen', () => { page.frameLocator('iframe[data-testid="my-testid"]').getByRole('button', { name: 'Click me' }).click(), ]); - expect(sources.get('JavaScript').text).toContain( + expect(sources.get('JavaScript')!.text).toContain( `await page.frameLocator('[data-testid="my-testid"]').getByRole('button', { name: 'Click me' }).click();` ); - expect(sources.get('Java').text).toContain( + expect(sources.get('Java')!.text).toContain( `page.frameLocator(\"[data-testid=\\\"my-testid\\\"]\").getByRole(AriaRole.BUTTON, new FrameLocator.GetByRoleOptions().setName(\"Click me\")).click();` ); - expect(sources.get('Python').text).toContain( + expect(sources.get('Python')!.text).toContain( `page.frame_locator(\"[data-testid=\\\"my-testid\\\"]\").get_by_role(\"button\", name=\"Click me\").click()` ); - expect(sources.get('Python Async').text).toContain( + expect(sources.get('Python Async')!.text).toContain( `await page.frame_locator("[data-testid=\\\"my-testid\\\"]").get_by_role("button", name="Click me").click()` ); - expect(sources.get('C#').text).toContain( + expect(sources.get('C#')!.text).toContain( `await page.FrameLocator("[data-testid=\\\"my-testid\\\"]").GetByRole(AriaRole.Button, new() { Name = "Click me" }).ClickAsync();` ); }); @@ -341,19 +341,19 @@ test.describe('cli codegen', () => { frame.click('button'), ]); - expect.soft(sources.get('JavaScript').text).toContain(` + expect.soft(sources.get('JavaScript')!.text).toContain(` await page.frameLocator('#frame1').getByRole('button', { name: 'Submit' }).click();`); - expect.soft(sources.get('Java').text).toContain(` + expect.soft(sources.get('Java')!.text).toContain(` page.frameLocator("#frame1").getByRole(AriaRole.BUTTON, new FrameLocator.GetByRoleOptions().setName("Submit")).click();`); - expect.soft(sources.get('Python').text).toContain(` + expect.soft(sources.get('Python')!.text).toContain(` page.frame_locator("#frame1").get_by_role("button", name="Submit").click()`); - expect.soft(sources.get('Python Async').text).toContain(` + expect.soft(sources.get('Python Async')!.text).toContain(` await page.frame_locator("#frame1").get_by_role("button", name="Submit").click()`); - expect.soft(sources.get('C#').text).toContain(` + expect.soft(sources.get('C#')!.text).toContain(` await page.FrameLocator("#frame1").GetByRole(AriaRole.Button, new() { Name = "Submit" }).ClickAsync();`); }); @@ -371,19 +371,19 @@ test.describe('cli codegen', () => { recorder.trustedClick(), ]); - expect.soft(sources.get('JavaScript').text).toContain(` + expect.soft(sources.get('JavaScript')!.text).toContain(` await page.getByTestId('testid').click();`); - expect.soft(sources.get('Python').text).toContain(` + expect.soft(sources.get('Python')!.text).toContain(` page.get_by_test_id("testid").click()`); - expect.soft(sources.get('Python Async').text).toContain(` + expect.soft(sources.get('Python Async')!.text).toContain(` await page.get_by_test_id("testid").click()`); - expect.soft(sources.get('Java').text).toContain(` + expect.soft(sources.get('Java')!.text).toContain(` page.getByTestId("testid").click()`); - expect.soft(sources.get('C#').text).toContain(` + expect.soft(sources.get('C#')!.text).toContain(` await page.GetByTestId("testid").ClickAsync();`); expect(message.text()).toBe('click'); @@ -402,19 +402,19 @@ test.describe('cli codegen', () => { recorder.trustedClick(), ]); - expect.soft(sources.get('JavaScript').text).toContain(` + expect.soft(sources.get('JavaScript')!.text).toContain(` await page.getByPlaceholder('Country').click();`); - expect.soft(sources.get('Python').text).toContain(` + expect.soft(sources.get('Python')!.text).toContain(` page.get_by_placeholder("Country").click()`); - expect.soft(sources.get('Python Async').text).toContain(` + expect.soft(sources.get('Python Async')!.text).toContain(` await page.get_by_placeholder("Country").click()`); - expect.soft(sources.get('Java').text).toContain(` + expect.soft(sources.get('Java')!.text).toContain(` page.getByPlaceholder("Country").click()`); - expect.soft(sources.get('C#').text).toContain(` + expect.soft(sources.get('C#')!.text).toContain(` await page.GetByPlaceholder("Country").ClickAsync();`); }); @@ -431,19 +431,19 @@ test.describe('cli codegen', () => { recorder.trustedClick(), ]); - expect.soft(sources.get('JavaScript').text).toContain(` + expect.soft(sources.get('JavaScript')!.text).toContain(` await page.getByAltText('Country').click();`); - expect.soft(sources.get('Python').text).toContain(` + expect.soft(sources.get('Python')!.text).toContain(` page.get_by_alt_text("Country").click()`); - expect.soft(sources.get('Python Async').text).toContain(` + expect.soft(sources.get('Python Async')!.text).toContain(` await page.get_by_alt_text("Country").click()`); - expect.soft(sources.get('Java').text).toContain(` + expect.soft(sources.get('Java')!.text).toContain(` page.getByAltText("Country").click()`); - expect.soft(sources.get('C#').text).toContain(` + expect.soft(sources.get('C#')!.text).toContain(` await page.GetByAltText("Country").ClickAsync();`); }); @@ -460,19 +460,19 @@ test.describe('cli codegen', () => { recorder.trustedClick(), ]); - expect.soft(sources.get('JavaScript').text).toContain(` + expect.soft(sources.get('JavaScript')!.text).toContain(` await page.getByLabel('Country').click();`); - expect.soft(sources.get('Python').text).toContain(` + expect.soft(sources.get('Python')!.text).toContain(` page.get_by_label("Country").click()`); - expect.soft(sources.get('Python Async').text).toContain(` + expect.soft(sources.get('Python Async')!.text).toContain(` await page.get_by_label("Country").click()`); - expect.soft(sources.get('Java').text).toContain(` + expect.soft(sources.get('Java')!.text).toContain(` page.getByLabel("Country").click()`); - expect.soft(sources.get('C#').text).toContain(` + expect.soft(sources.get('C#')!.text).toContain(` await page.GetByLabel("Country").ClickAsync();`); }); @@ -489,19 +489,19 @@ test.describe('cli codegen', () => { recorder.trustedClick(), ]); - expect.soft(sources.get('JavaScript').text).toContain(` + expect.soft(sources.get('JavaScript')!.text).toContain(` await page.getByLabel('Coun\"try').click();`); - expect.soft(sources.get('Python').text).toContain(` + expect.soft(sources.get('Python')!.text).toContain(` page.get_by_label("Coun\\"try").click()`); - expect.soft(sources.get('Python Async').text).toContain(` + expect.soft(sources.get('Python Async')!.text).toContain(` await page.get_by_label("Coun\\"try").click()`); - expect.soft(sources.get('Java').text).toContain(` + expect.soft(sources.get('Java')!.text).toContain(` page.getByLabel("Coun\\"try").click()`); - expect.soft(sources.get('C#').text).toContain(` + expect.soft(sources.get('C#')!.text).toContain(` await page.GetByLabel("Coun\\"try").ClickAsync();`); }); }); diff --git a/tests/library/inspector/console-api.spec.ts b/tests/library/inspector/console-api.spec.ts index 6901ca15c5..02a2bd58e0 100644 --- a/tests/library/inspector/console-api.spec.ts +++ b/tests/library/inspector/console-api.spec.ts @@ -18,7 +18,7 @@ import { test as it, expect } from './inspectorTest'; it.skip(({ mode }) => mode !== 'default'); -let scriptPromise; +let scriptPromise: Promise; it.beforeEach(async ({ page, recorderPageGetter }) => { scriptPromise = (async () => { diff --git a/tests/library/inspector/pause.spec.ts b/tests/library/inspector/pause.spec.ts index bb5c23c1ce..ac58fcf8bb 100644 --- a/tests/library/inspector/pause.spec.ts +++ b/tests/library/inspector/pause.spec.ts @@ -181,10 +181,10 @@ it.describe('pause', () => { const iframeActionPoint = await iframe.$('x-pw-action-point'); expect(await iframeActionPoint?.boundingBox()).toBeFalsy(); - const x1 = box1.x + box1.width / 2; - const y1 = box1.y + box1.height / 2; - const x2 = box2.x + box2.width / 2; - const y2 = box2.y + box2.height / 2; + const x1 = box1!.x + box1!.width / 2; + const y1 = box1!.y + box1!.height / 2; + const x2 = box2!.x + box2!.width / 2; + const y2 = box2!.y + box2!.height / 2; expect(Math.abs(x1 - x2) < 2).toBeTruthy(); expect(Math.abs(y1 - y2) < 2).toBeTruthy(); @@ -391,8 +391,8 @@ it.describe('pause', () => { const box1 = await box1Promise; const button = await page.$('text=Submit'); - const box2 = await button.boundingBox(); - expect(roundBox(box1)).toEqual(roundBox(box2)); + const box2 = await button!.boundingBox(); + expect(roundBox(box1)).toEqual(roundBox(box2!)); await recorderPage.click('[title="Resume (F8)"]'); await scriptPromise; }); @@ -473,7 +473,7 @@ it.describe('pause', () => { const box1Promise = waitForTestLog(page, 'Highlight box for test: '); await recorderPage.click('[title="Step over (F10)"]'); - const box2 = roundBox(await page.locator('#target').boundingBox()); + const box2 = roundBox((await page.locator('#target').boundingBox())!); const box1 = roundBox(await box1Promise); expect(box1).toEqual(box2); @@ -485,7 +485,7 @@ it.describe('pause', () => { async function sanitizeLog(recorderPage: Page): Promise { const results = []; for (const entry of await recorderPage.$$('.call-log-call')) { - const header = (await (await entry.$('.call-log-call-header')).textContent()).replace(/— [\d.]+(ms|s)/, '- XXms'); + const header = (await (await entry.$('.call-log-call-header'))!.textContent())!.replace(/— [\d.]+(ms|s)/, '- XXms'); results.push(header.replace(/page\.waitForEvent\(console\).*/, 'page.waitForEvent(console)')); results.push(...await entry.$$eval('.call-log-message', ee => ee.map(e => { return (e.classList.contains('error') ? 'error: ' : '') + e.textContent; diff --git a/tests/library/slowmo.spec.ts b/tests/library/slowmo.spec.ts index 5f70b5d852..de25e6cdb1 100644 --- a/tests/library/slowmo.spec.ts +++ b/tests/library/slowmo.spec.ts @@ -14,10 +14,12 @@ * limitations under the License. */ +import type { Page, Frame, ElementHandle } from '@playwright/test'; import { contextTest as it, expect } from '../config/browserTest'; import { attachFrame } from '../config/utils'; +import type { TestServer } from '../config/testserver'; -async function checkSlowMo(toImpl, page, task) { +async function checkSlowMo(toImpl: (api: any) => any, page: Page, task: () => Promise) { let didSlowMo = false; const contextDebugger = toImpl(page.context()).debugger(); contextDebugger._slowMo = 100; @@ -33,7 +35,7 @@ async function checkSlowMo(toImpl, page, task) { expect(!!didSlowMo).toBe(true); } -async function checkPageSlowMo(toImpl, page, task) { +async function checkPageSlowMo(toImpl: (api: any) => any, page: Page, task: () => Promise) { await page.setContent(` @@ -169,7 +171,7 @@ it.describe('slowMo', () => { }); }); -async function checkFrameSlowMo(toImpl, page, server, task) { +async function checkFrameSlowMo(toImpl: (api: any) => any, page: Page, server: TestServer, task: (frame: Frame) => Promise) { const frame = await attachFrame(page, 'frame1', server.EMPTY_PAGE); await frame.setContent(` @@ -185,7 +187,7 @@ async function checkFrameSlowMo(toImpl, page, server, task) { } -async function checkElementSlowMo(toImpl, page, selector, task) { +async function checkElementSlowMo(toImpl: (api: any) => any, page: Page, selector: string, task: (element: ElementHandle) => Promise) { await page.setContent(` @@ -196,6 +198,6 @@ async function checkElementSlowMo(toImpl, page, selector, task) { `); - const element = await page.$(selector); + const element = (await page.$(selector)) as ElementHandle; await checkSlowMo(toImpl, page, task.bind(null, element)); } diff --git a/tests/page/page-wait-for-selector-1.spec.ts b/tests/page/page-wait-for-selector-1.spec.ts index e0f758e75b..d20165af66 100644 --- a/tests/page/page-wait-for-selector-1.spec.ts +++ b/tests/page/page-wait-for-selector-1.spec.ts @@ -15,22 +15,23 @@ * limitations under the License. */ +import type { Frame } from '@playwright/test'; import { test as it, expect } from './pageTest'; import { attachFrame, detachFrame } from '../config/utils'; -async function giveItTimeToLog(frame) { +async function giveItTimeToLog(frame: Frame) { await frame.evaluate(() => new Promise(f => requestAnimationFrame(() => requestAnimationFrame(f)))); await frame.evaluate(() => new Promise(f => requestAnimationFrame(() => requestAnimationFrame(f)))); } -const addElement = tag => document.body.appendChild(document.createElement(tag)); +const addElement = (tag: string) => document.body.appendChild(document.createElement(tag)); it('should throw on waitFor', async ({ page, server }) => { await page.goto(server.EMPTY_PAGE); let error; // @ts-expect-error waitFor is undocumented await page.waitForSelector('*', { waitFor: 'attached' }).catch(e => error = e); - expect(error.message).toContain('options.waitFor is not supported, did you mean options.state?'); + expect(error!.message).toContain('options.waitFor is not supported, did you mean options.state?'); }); it('should tolerate waitFor=visible', async ({ page, server }) => { @@ -51,14 +52,14 @@ it('should immediately resolve promise if node exists', async ({ page, server }) it('elementHandle.waitForSelector should immediately resolve if node exists', async ({ page }) => { await page.setContent(`extra
target
`); - const div = await page.$('div'); + const div = (await page.$('div'))!; const span = await div.waitForSelector('span', { state: 'attached' }); expect(await span.evaluate(e => e.textContent)).toBe('target'); }); it('elementHandle.waitForSelector should wait', async ({ page }) => { await page.setContent(`
`); - const div = await page.$('div'); + const div = (await page.$('div'))!; const promise = div.waitForSelector('span', { state: 'attached' }); await div.evaluate(div => div.innerHTML = 'target'); const span = await promise; @@ -67,14 +68,14 @@ it('elementHandle.waitForSelector should wait', async ({ page }) => { it('elementHandle.waitForSelector should timeout', async ({ page }) => { await page.setContent(`
`); - const div = await page.$('div'); + const div = (await page.$('div'))!; const error = await div.waitForSelector('span', { timeout: 100 }).catch(e => e); expect(error.message).toContain('Timeout 100ms exceeded.'); }); it('elementHandle.waitForSelector should throw on navigation', async ({ page, server }) => { await page.setContent(`
`); - const div = await page.$('div'); + const div = (await page.$('div'))!; const promise = div.waitForSelector('span').catch(e => e); // Give it some time before navigating. for (let i = 0; i < 10; i++) @@ -84,8 +85,8 @@ it('elementHandle.waitForSelector should throw on navigation', async ({ page, se expect(error.message).toContain(`waiting for locator('span') to be visible`); }); -it('should work with removed MutationObserver', async ({ page, server }) => { - await page.evaluate(() => delete window.MutationObserver); +it('should work with removed MutationObserver', async ({ page }) => { + await page.evaluate(() => delete (window as any).MutationObserver); const [handle] = await Promise.all([ page.waitForSelector('.zombo'), page.setContent(`
anything
`), @@ -120,7 +121,7 @@ it('should report logs while waiting for visible', async ({ page, server }) => { }); await giveItTimeToLog(frame); - await frame.evaluate(() => document.querySelector('div').remove()); + await frame.evaluate(() => document.querySelector('div')!.remove()); await giveItTimeToLog(frame); await frame.evaluate(() => { @@ -153,7 +154,7 @@ it('should report logs while waiting for hidden', async ({ page, server }) => { await giveItTimeToLog(frame); await frame.evaluate(() => { - document.querySelector('div').remove(); + document.querySelector('div')!.remove(); const div = document.createElement('div'); div.className = 'another'; div.textContent = 'hello'; @@ -192,7 +193,7 @@ it('should resolve promise when node is added in shadow dom', async ({ page, ser await page.evaluate(() => { const span = document.createElement('span'); span.textContent = 'Hello from shadow'; - document.querySelector('div').shadowRoot.appendChild(span); + document.querySelector('div')!.shadowRoot!.appendChild(span); }); const handle = await watchdog; expect(await handle.evaluate(e => e.textContent)).toBe('Hello from shadow'); @@ -202,7 +203,7 @@ it('should work when node is added through innerHTML', async ({ page, server }) await page.goto(server.EMPTY_PAGE); const watchdog = page.waitForSelector('h3 div', { state: 'attached' }); await page.evaluate(addElement, 'span'); - await page.evaluate(() => document.querySelector('span').innerHTML = '

'); + await page.evaluate(() => document.querySelector('span')!.innerHTML = '

'); await watchdog; }); @@ -237,5 +238,5 @@ it('should throw when frame is detached', async ({ page, server }) => { await detachFrame(page, 'frame1'); await waitPromise; expect(waitError).toBeTruthy(); - expect(waitError.message).toContain('frame.waitForSelector: Frame was detached'); + expect(waitError!.message).toContain('frame.waitForSelector: Frame was detached'); }); diff --git a/tests/page/page-wait-for-selector-2.spec.ts b/tests/page/page-wait-for-selector-2.spec.ts index eb71c784cf..5a23e581c7 100644 --- a/tests/page/page-wait-for-selector-2.spec.ts +++ b/tests/page/page-wait-for-selector-2.spec.ts @@ -18,7 +18,7 @@ import { test as it, expect } from './pageTest'; import { attachFrame, detachFrame } from '../config/utils'; -const addElement = tag => document.body.appendChild(document.createElement(tag)); +const addElement = (tag: string) => document.body.appendChild(document.createElement(tag)); it('should survive cross-process navigation', async ({ page, server }) => { let boxFound = false; @@ -37,9 +37,9 @@ it('should wait for visible', async ({ page, server }) => { const waitForSelector = page.waitForSelector('div').then(() => divFound = true); await page.setContent(`
1
`); expect(divFound).toBe(false); - await page.evaluate(() => document.querySelector('div').style.removeProperty('display')); + await page.evaluate(() => document.querySelector('div')!.style.removeProperty('display')); expect(divFound).toBe(false); - await page.evaluate(() => document.querySelector('div').style.removeProperty('visibility')); + await page.evaluate(() => document.querySelector('div')!.style.removeProperty('visibility')); expect(await waitForSelector).toBe(true); expect(divFound).toBe(true); }); @@ -48,10 +48,10 @@ it('should not consider visible when zero-sized', async ({ page, server }) => { await page.setContent(`
1
`); let error = await page.waitForSelector('div', { timeout: 1000 }).catch(e => e); expect(error.message).toContain('page.waitForSelector: Timeout 1000ms exceeded'); - await page.evaluate(() => document.querySelector('div').style.width = '10px'); + await page.evaluate(() => document.querySelector('div')!.style.width = '10px'); error = await page.waitForSelector('div', { timeout: 1000 }).catch(e => e); expect(error.message).toContain('page.waitForSelector: Timeout 1000ms exceeded'); - await page.evaluate(() => document.querySelector('div').style.height = '10px'); + await page.evaluate(() => document.querySelector('div')!.style.height = '10px'); expect(await page.waitForSelector('div', { timeout: 1000 })).toBeTruthy(); }); @@ -60,9 +60,9 @@ it('should wait for visible recursively', async ({ page, server }) => { const waitForSelector = page.waitForSelector('div#inner').then(() => divVisible = true); await page.setContent(`
hi
`); expect(divVisible).toBe(false); - await page.evaluate(() => document.querySelector('div').style.removeProperty('display')); + await page.evaluate(() => document.querySelector('div')!.style.removeProperty('display')); expect(divVisible).toBe(false); - await page.evaluate(() => document.querySelector('div').style.removeProperty('visibility')); + await page.evaluate(() => document.querySelector('div')!.style.removeProperty('visibility')); expect(await waitForSelector).toBe(true); expect(divVisible).toBe(true); }); @@ -94,7 +94,7 @@ it('hidden should wait for hidden', async ({ page, server }) => { const waitForSelector = page.waitForSelector('div', { state: 'hidden' }).then(() => divHidden = true); await page.waitForSelector('div'); // do a round trip expect(divHidden).toBe(false); - await page.evaluate(() => document.querySelector('div').style.setProperty('visibility', 'hidden')); + await page.evaluate(() => document.querySelector('div')!.style.setProperty('visibility', 'hidden')); expect(await waitForSelector).toBe(true); expect(divHidden).toBe(true); }); @@ -105,7 +105,7 @@ it('hidden should wait for display: none', async ({ page, server }) => { const waitForSelector = page.waitForSelector('div', { state: 'hidden' }).then(() => divHidden = true); await page.waitForSelector('div'); // do a round trip expect(divHidden).toBe(false); - await page.evaluate(() => document.querySelector('div').style.setProperty('display', 'none')); + await page.evaluate(() => document.querySelector('div')!.style.setProperty('display', 'none')); expect(await waitForSelector).toBe(true); expect(divHidden).toBe(true); }); @@ -116,7 +116,7 @@ it('hidden should wait for removal', async ({ page, server }) => { const waitForSelector = page.waitForSelector('div', { state: 'hidden' }).then(() => divRemoved = true); await page.waitForSelector('div'); // do a round trip expect(divRemoved).toBe(false); - await page.evaluate(() => document.querySelector('div').remove()); + await page.evaluate(() => document.querySelector('div')!.remove()); expect(await waitForSelector).toBe(true); expect(divRemoved).toBe(true); }); @@ -127,21 +127,21 @@ it('should return null if waiting to hide non-existing element', async ({ page, }); it('should respect timeout', async ({ page, playwright }) => { - let error = null; + let error: Error | undefined; await page.waitForSelector('div', { timeout: 3000, state: 'attached' }).catch(e => error = e); expect(error).toBeTruthy(); - expect(error.message).toContain('page.waitForSelector: Timeout 3000ms exceeded'); - expect(error.message).toContain('waiting for locator(\'div\')'); + expect(error!.message).toContain('page.waitForSelector: Timeout 3000ms exceeded'); + expect(error!.message).toContain('waiting for locator(\'div\')'); expect(error).toBeInstanceOf(playwright.errors.TimeoutError); }); it('should have an error message specifically for awaiting an element to be hidden', async ({ page, server }) => { await page.setContent(`
content
`); - let error = null; + let error: Error | undefined; await page.waitForSelector('div', { state: 'hidden', timeout: 1000 }).catch(e => error = e); expect(error).toBeTruthy(); - expect(error.message).toContain('page.waitForSelector: Timeout 1000ms exceeded'); - expect(error.message).toContain('waiting for locator(\'div\') to be hidden'); + expect(error!.message).toContain('page.waitForSelector: Timeout 1000ms exceeded'); + expect(error!.message).toContain('waiting for locator(\'div\') to be hidden'); }); it('should respond to node attribute mutation', async ({ page, server }) => { @@ -149,7 +149,7 @@ it('should respond to node attribute mutation', async ({ page, server }) => { const waitForSelector = page.waitForSelector('.zombo', { state: 'attached' }).then(() => divFound = true); await page.setContent(`
`); expect(divFound).toBe(false); - await page.evaluate(() => document.querySelector('div').className = 'zombo'); + await page.evaluate(() => document.querySelector('div')!.className = 'zombo'); expect(await waitForSelector).toBe(true); }); @@ -162,7 +162,7 @@ it('should return the element handle', async ({ page, server }) => { it('should have correct stack trace for timeout', async ({ page, server }) => { let error; await page.waitForSelector('.zombo', { timeout: 10 }).catch(e => error = e); - expect(error.stack).toContain('wait-for-selector'); + expect(error!.stack).toContain('wait-for-selector'); }); it('should throw for unknown state option', async ({ page, server }) => { @@ -199,7 +199,7 @@ it('should support >> selector syntax', async ({ page, server }) => { const watchdog = frame.waitForSelector('css=div >> css=span', { state: 'attached' }); await frame.evaluate(addElement, 'br'); await frame.evaluate(addElement, 'div'); - await frame.evaluate(() => document.querySelector('div').appendChild(document.createElement('span'))); + await frame.evaluate(() => document.querySelector('div')!.appendChild(document.createElement('span'))); const eHandle = await watchdog; const tagName = await eHandle.getProperty('tagName').then(e => e.jsonValue()); expect(tagName).toBe('SPAN'); @@ -229,11 +229,11 @@ it('should support some fancy xpath', async ({ page, server }) => { }); it('should respect timeout xpath', async ({ page, playwright }) => { - let error = null; + let error: Error | undefined; await page.waitForSelector('//div', { state: 'attached', timeout: 3000 }).catch(e => error = e); expect(error).toBeTruthy(); - expect(error.message).toContain('page.waitForSelector: Timeout 3000ms exceeded'); - expect(error.message).toContain('waiting for locator(\'//div\')'); + expect(error!.message).toContain('page.waitForSelector: Timeout 3000ms exceeded'); + expect(error!.message).toContain('waiting for locator(\'//div\')'); expect(error).toBeInstanceOf(playwright.errors.TimeoutError); }); @@ -252,12 +252,12 @@ it('should run in specified frame xpath', async ({ page, server }) => { it('should throw when frame is detached xpath', async ({ page, server }) => { await attachFrame(page, 'frame1', server.EMPTY_PAGE); const frame = page.frames()[1]; - let waitError = null; + let waitError: Error | undefined; const waitPromise = frame.waitForSelector('//*[@class="box"]').catch(e => waitError = e); await detachFrame(page, 'frame1'); await waitPromise; expect(waitError).toBeTruthy(); - expect(waitError.message).toContain('frame.waitForSelector: Frame was detached'); + expect(waitError!.message).toContain('frame.waitForSelector: Frame was detached'); }); it('should return the element handle xpath', async ({ page, server }) => { diff --git a/tests/page/retarget.spec.ts b/tests/page/retarget.spec.ts index e7fb10381f..203ac5bd16 100644 --- a/tests/page/retarget.spec.ts +++ b/tests/page/retarget.spec.ts @@ -15,9 +15,10 @@ * limitations under the License. */ +import type { Page } from '@playwright/test'; import { test as it, expect } from './pageTest'; -async function giveItAChanceToResolve(page) { +async function giveItAChanceToResolve(page: Page) { for (let i = 0; i < 5; i++) await page.evaluate(() => new Promise(f => requestAnimationFrame(() => requestAnimationFrame(f)))); } @@ -40,7 +41,7 @@ it('element state checks should work as expected for label with zero-sized input it('should wait for enclosing disabled button', async ({ page }) => { await page.setContent(''); - const span = await page.$('text=Target'); + const span = (await page.$('text=Target'))!; let done = false; const promise = span.waitForElementState('disabled').then(() => done = true); await giveItAChanceToResolve(page); @@ -51,18 +52,18 @@ it('should wait for enclosing disabled button', async ({ page }) => { it('should wait for enclosing button with a disabled fieldset', async ({ page }) => { await page.setContent('
'); - const span = await page.$('text=Target'); + const span = (await page.$('text=Target'))!; let done = false; const promise = span.waitForElementState('enabled').then(() => done = true); await giveItAChanceToResolve(page); expect(done).toBe(false); - await span.evaluate(span => (span.parentElement.parentElement as HTMLFieldSetElement).disabled = false); + await span.evaluate((span: HTMLElement) => (span.parentElement!.parentElement as HTMLFieldSetElement).disabled = false); await promise; }); it('should wait for enclosing enabled button', async ({ page, server }) => { await page.setContent(''); - const span = await page.$('text=Target'); + const span = (await page.$('text=Target'))!; let done = false; const promise = span.waitForElementState('enabled').then(() => done = true); await giveItAChanceToResolve(page); @@ -91,8 +92,8 @@ it('should check the box outside shadow dom label', async ({ page }) => { it('setInputFiles should work with label', async ({ page, asset }) => { await page.setContent(``); await page.setInputFiles('text=Choose a file', asset('file-to-upload.txt')); - expect(await page.$eval('input', input => input.files.length)).toBe(1); - expect(await page.$eval('input', input => input.files[0].name)).toBe('file-to-upload.txt'); + expect(await page.$eval('input', (input: HTMLInputElement) => input.files!.length)).toBe(1); + expect(await page.$eval('input', (input: HTMLInputElement) => input.files?.[0].name)).toBe('file-to-upload.txt'); }); type Options = { disabled?: boolean, hidden?: boolean, readonly?: boolean }; @@ -123,7 +124,7 @@ it('enabled/disabled retargeting', async ({ page, asset }) => { await it.step(`"${locator}" in "${dom}" should be enabled=${enabled}`, async () => { await page.setContent(dom); const target = page.locator(locator); - const handle = await page.$(locator); + const handle = (await page.$(locator))!; expect(await target.isEnabled()).toBe(enabled); expect(await target.isDisabled()).toBe(!enabled); if (enabled) { @@ -161,7 +162,7 @@ it('visible/hidden retargeting', async ({ page, asset }) => { await it.step(`"${locator}" in "${dom}" should be visible=${visible}`, async () => { await page.setContent(dom); const target = page.locator(locator); - const handle = await page.$(locator); + const handle = (await page.$(locator))!; expect(await target.isVisible()).toBe(visible); expect(await target.isHidden()).toBe(!visible); if (visible) { @@ -197,7 +198,7 @@ it('editable retargeting', async ({ page, asset }) => { await it.step(`"${locator}" in "${dom}" should be editable=${editable}`, async () => { await page.setContent(dom); const target = page.locator(locator); - const handle = await page.$(locator); + const handle = (await page.$(locator))!; expect(await target.isEditable()).toBe(editable); if (editable) { await expect(target).toBeEditable(); @@ -222,7 +223,7 @@ it('input value retargeting', async ({ page, browserName }) => { await it.step(`"${locator}" in "${dom}" input value`, async () => { await page.setContent(dom); const target = page.locator(locator); - const handle = await page.$(locator); + const handle = (await page.$(locator))!; expect(await target.inputValue()).toBe(''); expect(await handle.inputValue()).toBe(''); @@ -243,7 +244,7 @@ it('input value retargeting', async ({ page, browserName }) => { expect(await page.locator('#target').evaluate((el: HTMLInputElement) => el.selectionStart)).toBe(0); expect(await page.locator('#target').evaluate((el: HTMLInputElement) => el.selectionEnd)).toBe(3); } else { - expect(await page.evaluate(() => window.getSelection().toString())).toBe('bar'); + expect(await page.evaluate(() => window.getSelection()!.toString())).toBe('bar'); } }); } @@ -260,7 +261,7 @@ it.fixme('selection retargeting', async ({ page, browserName }) => { await it.step(`"${locator}" in "${dom}" text selection`, async () => { await page.setContent(dom); const target = page.locator(locator); - const handle = await page.$(locator); + const handle = (await page.$(locator))!; expect(await target.isEditable()).toBe(true); expect(await handle.isEditable()).toBe(true); @@ -272,11 +273,11 @@ it.fixme('selection retargeting', async ({ page, browserName }) => { await target.selectText(); if (browserName === 'firefox') { expect(await page.$eval('#target', target => { - const selection = window.getSelection(); + const selection = window.getSelection()!; return selection.anchorNode === target && selection.focusNode === target; })).toBe(true); } else { - expect(await page.evaluate(() => window.getSelection().toString())).toBe('foo'); + expect(await page.evaluate(() => window.getSelection()!.toString())).toBe('foo'); } }); } @@ -295,7 +296,7 @@ it('select options retargeting', async ({ page }) => { await it.step(`"${locator}" in "${dom}" select option`, async () => { await page.setContent(dom); const target = page.locator(locator); - const handle = await page.$(locator); + const handle = (await page.$(locator))!; expect(await target.inputValue()).toBe('dog'); expect(await handle.inputValue()).toBe('dog'); diff --git a/tests/page/selectors-css.spec.ts b/tests/page/selectors-css.spec.ts index cb12f40807..302def0a51 100644 --- a/tests/page/selectors-css.spec.ts +++ b/tests/page/selectors-css.spec.ts @@ -15,6 +15,7 @@ * limitations under the License. */ +import type { ElementHandle } from '@playwright/test'; import { test as it, expect } from './pageTest'; it('should work with large DOM @smoke', async ({ page, server }) => { @@ -90,10 +91,10 @@ it('should work for open shadow roots', async ({ page, server }) => { expect(await page.$eval(`css=section > div div span:nth-child(2)`, e => e.textContent)).toBe('Hello from root3 #2'); expect(await page.$(`css=section div div div div`)).toBe(null); - const root2 = await page.$(`css=div div`); + const root2 = (await page.$(`css=div div`))!; expect(await root2.$eval(`css=#target`, e => e.textContent)).toBe('Hello from root2'); expect(await root2.$(`css:light=#target`)).toBe(null); - const root2Shadow = await root2.evaluateHandle(r => r.shadowRoot); + const root2Shadow = (await root2.evaluateHandle(r => r.shadowRoot) as ElementHandle)!; expect(await root2Shadow.$eval(`css:light=#target`, e => e.textContent)).toBe('Hello from root2'); const root3 = (await page.$$(`css=div div`))[1]; expect(await root3.$eval(`text=root3`, e => e.textContent)).toBe('Hello from root3'); @@ -178,7 +179,7 @@ it('should work with comma inside text', async ({ page }) => { it('should work with attribute selectors', async ({ page }) => { await page.setContent(`
`); - await page.evaluate(() => window['div'] = document.querySelector('div')); + await page.evaluate(() => (window as any)['div'] = document.querySelector('div')); const selectors = [ `[attr="hello world"]`, `[attr = "hello world"]`, @@ -194,10 +195,10 @@ it('should work with attribute selectors', async ({ page }) => { `[attr2 $="foo=bar[]"]`, ]; for (const selector of selectors) - expect(await page.$eval(selector, e => e === window['div'])).toBe(true); - expect(await page.$eval(`[attr*=hello] span`, e => e.parentNode === window['div'])).toBe(true); - expect(await page.$eval(`[attr*=hello] >> span`, e => e.parentNode === window['div'])).toBe(true); - expect(await page.$eval(`[attr3="] span"] >> span`, e => e.parentNode === window['div'])).toBe(true); + expect(await page.$eval(selector, e => e === (window as any)['div'])).toBe(true); + expect(await page.$eval(`[attr*=hello] span`, e => e.parentNode === (window as any)['div'])).toBe(true); + expect(await page.$eval(`[attr*=hello] >> span`, e => e.parentNode === (window as any)['div'])).toBe(true); + expect(await page.$eval(`[attr3="] span"] >> span`, e => e.parentNode === (window as any)['div'])).toBe(true); }); it('should not match root after >>', async ({ page, server }) => { @@ -236,7 +237,7 @@ it('should work with *', async ({ page }) => { expect(await page.$$eval('div *', els => els.length)).toBe(2); expect(await page.$$eval('* > *', els => els.length)).toBe(6); - const body = await page.$('body'); + const body = (await page.$('body')) as ElementHandle; // Does not include html, head or body. expect(await body.$$eval('*', els => els.length)).toBe(4); expect(await body.$$eval('*#div1', els => els.length)).toBe(1); @@ -386,7 +387,7 @@ it('should work with :scope', async ({ page, server }) => { // 'has' does change the scope, so it becomes the 'div' we are querying. expect(await page.$$eval(`css=div:has(:scope > #target)`, els => els.length)).toBe(1); - const handle = await page.$(`css=span`); + const handle = await page.$(`css=span`) as ElementHandle; for (const scope of [page, handle]) { expect(await scope.$$eval(`css=:scope`, els => els.length)).toBe(1); expect(await scope.$$eval(`css=* :scope`, els => els.length)).toBe(0); @@ -439,7 +440,7 @@ it('css on the handle should be relative', async ({ page }) => { `); expect(await page.$eval(`.find-me`, e => e.id)).toBe('target1'); - const div = await page.$('div'); + const div = await page.$('div') as ElementHandle; expect(await div.$eval(`.find-me`, e => e.id)).toBe('target2'); expect(await page.$eval(`div >> .find-me`, e => e.id)).toBe('target2'); });