[READ-ONLY] Mirror of https://github.com/vitest-dev/vitest. Next generation testing framework powered by Vite. vitest.dev
test testing-tools vite
12

Configure Feed

Select the types of activity you want to include in your feed.

fix(browser): types of `getCDPSession` and `cdp()` (#9716)

authored by

Ari Perkkiö and committed by
GitHub
(Mar 5, 2026, 10:01 AM +0100) 689a22a1 fc2006e9

+104 -29
+3
pnpm-lock.yaml
··· 718 718 '@vitest/browser': 719 719 specifier: workspace:* 720 720 version: link:../browser 721 + '@vitest/browser-playwright': 722 + specifier: workspace:* 723 + version: link:../browser-playwright 721 724 pathe: 722 725 specifier: 'catalog:' 723 726 version: 2.0.3
+3 -5
packages/browser/context.d.ts
··· 1 1 import { SerializedConfig } from 'vitest' 2 - import { StringifyOptions, BrowserCommands } from 'vitest/internal/browser' 2 + import { StringifyOptions, CDPSession, BrowserCommands } from 'vitest/internal/browser' 3 3 import { ARIARole } from './aria-role.js' 4 4 import {} from './matchers.js' 5 5 ··· 17 17 | 'binary' 18 18 | 'hex' 19 19 20 - export interface CDPSession { 21 - // methods are defined by the provider type augmentation 22 - } 20 + export { CDPSession }; 23 21 24 22 export interface ScreenshotOptions extends SelectorOptions { 25 23 /** ··· 497 495 selected?: boolean 498 496 } 499 497 500 - interface LocatorScreenshotOptions extends Omit<ScreenshotOptions, 'element'> {} 498 + export interface LocatorScreenshotOptions extends Omit<ScreenshotOptions, 'element'> {} 501 499 502 500 export interface LocatorSelectors { 503 501 /**
+1
packages/coverage-v8/package.json
··· 70 70 "@types/istanbul-lib-report": "catalog:", 71 71 "@types/istanbul-reports": "catalog:", 72 72 "@vitest/browser": "workspace:*", 73 + "@vitest/browser-playwright": "workspace:*", 73 74 "pathe": "catalog:", 74 75 "vitest": "workspace:*" 75 76 }
+5
test/browser/vitest.config.mts
··· 87 87 return false 88 88 } 89 89 }, 90 + typecheck: { 91 + enabled: true, 92 + include: ['test/*.test-d.ts'], 93 + ignoreSourceErrors: true, 94 + }, 90 95 }, 91 96 plugins: [ 92 97 {
+1
packages/browser-playwright/src/index.ts
··· 1 1 export { 2 + type CDPSession, 2 3 playwright, 3 4 PlaywrightBrowserProvider, 4 5 type PlaywrightProviderOptions,
+11 -10
packages/browser-playwright/src/playwright.ts
··· 529 529 const page = this.getPage(sessionid) 530 530 const cdp = await page.context().newCDPSession(page) 531 531 return { 532 - async send(method: string, params: any) { 533 - const result = await cdp.send(method as 'DOM.querySelector', params) 534 - return result as unknown 532 + send(method, params) { 533 + return cdp.send(method as any, params) 535 534 }, 536 - on(event: string, listener: (...args: any[]) => void) { 537 - cdp.on(event as 'Accessibility.loadComplete', listener) 535 + on(event, listener) { 536 + return cdp.on(event as any, listener) 538 537 }, 539 - off(event: string, listener: (...args: any[]) => void) { 540 - cdp.off(event as 'Accessibility.loadComplete', listener) 538 + off(event, listener) { 539 + return cdp.off(event as any, listener) 541 540 }, 542 - once(event: string, listener: (...args: any[]) => void) { 543 - cdp.once(event as 'Accessibility.loadComplete', listener) 541 + once(event, listener) { 542 + return cdp.once(event as any, listener) 544 543 }, 545 544 } 546 545 } ··· 638 637 type PWDragAndDropOptions = NonNullable<Parameters<Page['dragAndDrop']>[2]> 639 638 type PWSetInputFiles = NonNullable<Parameters<Page['setInputFiles']>[2]> 640 639 // Must be re-aliased here or rollup-plugin-dts removes the import alias and you end up with a circular reference 641 - type PWCDPSession = PlaywrightCDPSession 640 + type PWCDPSession = Pick<PlaywrightCDPSession, 'send' | 'on' | 'off' | 'once'> 641 + 642 + export { type PWCDPSession as CDPSession } 642 643 643 644 declare module 'vitest/browser' { 644 645 export interface UserEventHoverOptions extends PWHoverOptions {}
+10 -1
packages/browser-webdriverio/src/webdriverio.ts
··· 269 269 270 270 async getCDPSession(_sessionId: string): Promise<CDPSession> { 271 271 return { 272 - send: (method: string, params: any) => { 272 + send: (method, params) => { 273 273 if (!this.browser) { 274 274 throw new Error(`The environment was torn down.`) 275 275 } ··· 308 308 export interface LocatorScreenshotOptions extends SelectorOptions {} 309 309 } 310 310 311 + interface WebdriverCDPSession { 312 + send: (method: string, params?: Record<string, unknown>) => Promise<unknown> 313 + on: (event: string, listener: (...args: unknown[]) => void) => void 314 + once: (event: string, listener: (...args: unknown[]) => void) => void 315 + off: (event: string, listener: (...args: unknown[]) => void) => void 316 + } 317 + 311 318 declare module 'vitest/node' { 312 319 export interface BrowserCommandContext { 313 320 browser: WebdriverIO.Browser ··· 325 332 326 333 export interface ToMatchScreenshotComparators 327 334 extends ScreenshotComparatorRegistry {} 335 + 336 + export interface CDPSession extends WebdriverCDPSession {} 328 337 }
+2 -1
packages/coverage-v8/src/browser.ts
··· 1 + import type { CDPSession } from '@vitest/browser-playwright' 1 2 import type { CoverageProviderModule } from 'vitest/node' 2 3 import type { V8CoverageProvider } from './provider' 3 4 import { cdp } from 'vitest/browser' 4 5 import { loadProvider } from './load-provider' 5 6 6 - const session = cdp() 7 + const session = cdp() as CDPSession 7 8 let enabled = false 8 9 9 10 type ScriptCoverage = Awaited<ReturnType<typeof session.send<'Profiler.takePreciseCoverage'>>>
+1 -1
packages/vitest/browser/context.d.ts
··· 4 4 export * from '@vitest/browser-webdriverio/context' 5 5 // @ts-ignore -- @vitest/browser-preview might not be installed 6 6 export * from '@vitest/browser-preview/context' 7 - export { BrowserCommands, FsOptions } from 'vitest/internal/browser' 7 + export { BrowserCommands, CDPSession, FsOptions } from 'vitest/internal/browser'
+3 -1
test/browser/specs/utils.ts
··· 35 35 viteOverrides?: Partial<ViteUserConfig>, 36 36 runnerOptions?: VitestRunnerCLIOptions, 37 37 ) { 38 - return runVitest({ 38 + const result = await runVitest({ 39 39 watch: false, 40 40 reporters: 'none', 41 41 ...config, 42 42 browser: { headless: true, ...config?.browser }, 43 43 $viteConfig: viteOverrides, 44 44 }, include, runnerOptions) 45 + 46 + return { ...result, stderr: result.stderr.replace('Testing types with tsc and vue-tsc is an experimental feature.\nBreaking changes might not follow SemVer, please pin Vitest\'s version when using it.\n', '') } 45 47 }
+54
test/browser/test/cdp.test-d.ts
··· 1 + import { PlaywrightBrowserProvider } from '@vitest/browser-playwright' 2 + import { expectTypeOf, test } from 'vitest' 3 + import { cdp } from 'vitest/browser' 4 + import { } from 'vitest/config' 5 + 6 + test('server side cdp', async () => { 7 + const session = await (new PlaywrightBrowserProvider('project' as any, {}).getCDPSession('')) 8 + 9 + expectTypeOf(session).toHaveProperty('on') 10 + expectTypeOf(session).toHaveProperty('off') 11 + expectTypeOf(session).toHaveProperty('once') 12 + expectTypeOf(session).toHaveProperty('send') 13 + expectTypeOf(session).not.toHaveProperty('emit') 14 + 15 + session.on('Profiler.preciseCoverageDeltaUpdate', (event) => { 16 + expectTypeOf(event).toHaveProperty('result').items.toHaveProperty('functions').items.toHaveProperty('ranges').items.toHaveProperty('startOffset') 17 + }) 18 + 19 + expectTypeOf(session.send('Profiler.startPreciseCoverage', { 20 + allowTriggeredUpdates: true, 21 + callCount: true, 22 + detailed: true, 23 + })).resolves.toHaveProperty('timestamp') 24 + 25 + expectTypeOf(session.send).toBeCallableWith('Fetch.enable') 26 + 27 + // @ts-expect-error -- not.toBeCallableWith() does not work 28 + expectTypeOf(session.send).toBeCallableWith('Some.NonExisting.Command') 29 + }) 30 + 31 + test('client side cdps', async () => { 32 + const session = cdp() 33 + 34 + expectTypeOf(session).toHaveProperty('on') 35 + expectTypeOf(session).toHaveProperty('off') 36 + expectTypeOf(session).toHaveProperty('once') 37 + expectTypeOf(session).toHaveProperty('send') 38 + expectTypeOf(session).not.toHaveProperty('emit') 39 + 40 + session.on('Profiler.preciseCoverageDeltaUpdate', (event) => { 41 + expectTypeOf(event).toHaveProperty('result').items.toHaveProperty('functions').items.toHaveProperty('ranges').items.toHaveProperty('startOffset') 42 + }) 43 + 44 + expectTypeOf(session.send('Profiler.startPreciseCoverage', { 45 + allowTriggeredUpdates: true, 46 + callCount: true, 47 + detailed: true, 48 + })).resolves.toHaveProperty('timestamp') 49 + 50 + expectTypeOf(session.send).toBeCallableWith('Fetch.enable') 51 + 52 + // @ts-expect-error -- not.toBeCallableWith() does not work 53 + expectTypeOf(session.send).toBeCallableWith('Some.NonExisting.Command') 54 + })
+3 -3
packages/browser/src/node/cdp.ts
··· 12 12 ) {} 13 13 14 14 send(method: string, params?: Record<string, unknown>): Promise<unknown> { 15 - return this.session.send(method, params) 15 + return this.session.send(method as any, params) 16 16 } 17 17 18 18 on(event: string, id: string, once = false): void { ··· 32 32 } 33 33 } 34 34 35 - this.session.on(event, this.listeners[event]) 35 + this.session.on(event as any, this.listeners[event]) 36 36 } 37 37 } 38 38 ··· 43 43 this.listenerIds[event] = this.listenerIds[event].filter(l => l !== id) 44 44 45 45 if (!this.listenerIds[event].length) { 46 - this.session.off(event, this.listeners[event]) 46 + this.session.off(event as any, this.listeners[event]) 47 47 delete this.listeners[event] 48 48 } 49 49 }
+5
packages/vitest/src/public/browser.ts
··· 43 43 ) => Promise<void> 44 44 removeFile: (path: string) => Promise<void> 45 45 } 46 + 47 + export interface CDPSession { 48 + // methods are defined by the provider type augmentation 49 + } 50 + 46 51 /** 47 52 * @internal 48 53 */
+2 -7
packages/vitest/src/node/types/browser.ts
··· 3 3 import type { Awaitable, ParsedStack, TestError } from '@vitest/utils' 4 4 import type { StackTraceParserOptions } from '@vitest/utils/source-map' 5 5 import type { Plugin, ViteDevServer } from 'vite' 6 - import type { BrowserCommands } from 'vitest/browser' 6 + import type { BrowserCommands, CDPSession } from 'vitest/browser' 7 7 import type { BrowserTraceViewMode } from '../../runtime/config' 8 8 import type { BrowserTesterOptions } from '../../types/browser' 9 9 import type { TestProject } from '../project' 10 10 import type { ApiConfig, ProjectConfig } from './config' 11 11 12 - export interface CDPSession { 13 - send: (method: string, params?: Record<string, unknown>) => Promise<unknown> 14 - on: (event: string, listener: (...args: unknown[]) => void) => void 15 - once: (event: string, listener: (...args: unknown[]) => void) => void 16 - off: (event: string, listener: (...args: unknown[]) => void) => void 17 - } 12 + export type { CDPSession } 18 13 19 14 export interface BrowserModuleMocker { 20 15 register: (sessionId: string, module: MockedModule) => Promise<void>