22 * Core WebDriver + BiDi connection management
33 */
44
5- import { Builder , Browser , Capabilities } from 'selenium-webdriver' ;
5+ import { Builder , Browser , Capabilities , WebDriver } from 'selenium-webdriver' ;
66import firefox from 'selenium-webdriver/firefox.js' ;
77import { mkdirSync , openSync , closeSync } from 'node:fs' ;
88import { homedir } from 'node:os' ;
99import { join } from 'node:path' ;
1010import type { FirefoxLaunchOptions } from './types.js' ;
1111import { log , logDebug } from '../utils/logger.js' ;
1212
13- // ---------------------------------------------------------------------------
14- // Shared driver interface — the minimal surface used by all consumers
15- // (DomInteractions, PageManagement, SnapshotManager, UidResolver).
16- // ---------------------------------------------------------------------------
17-
18- export interface IElement {
19- click ( ) : Promise < void > ;
20- clear ( ) : Promise < void > ;
21- sendKeys ( ...args : Array < string | number > ) : Promise < void > ;
22- isDisplayed ( ) : Promise < boolean > ;
23- takeScreenshot ( ) : Promise < string > ;
24- }
25-
26- export interface IBiDiSocket {
27- readyState : number ;
28- on ( event : string , listener : ( data : unknown ) => void ) : void ;
29- off ( event : string , listener : ( data : unknown ) => void ) : void ;
30- send ( data : string ) : void ;
31- }
32-
33- export interface IBiDi {
34- socket : IBiDiSocket ;
35- subscribe ?: ( event : string , contexts ?: string [ ] ) => Promise < void > ;
36- }
37-
38- /* eslint-disable @typescript-eslint/no-explicit-any */
39- export interface IDriver {
40- getTitle ( ) : Promise < string > ;
41- getCurrentUrl ( ) : Promise < string > ;
42- getWindowHandle ( ) : Promise < string > ;
43- getAllWindowHandles ( ) : Promise < string [ ] > ;
44- get ( url : string ) : Promise < void > ;
45- getPageSource ( ) : Promise < string > ;
46- executeScript < T > ( script : string | ( ( ...a : any [ ] ) => any ) , ...args : unknown [ ] ) : Promise < T > ;
47- executeAsyncScript < T > ( script : string | ( ( ...a : any [ ] ) => any ) , ...args : unknown [ ] ) : Promise < T > ;
48- takeScreenshot ( ) : Promise < string > ;
49- close ( ) : Promise < void > ;
50- findElement ( locator : any ) : Promise < IElement > ;
51- switchTo ( ) : {
52- window ( handle : string ) : Promise < void > ;
53- newWindow ( type : string ) : Promise < { handle : string } > ;
54- alert ( ) : Promise < {
55- accept ( ) : Promise < void > ;
56- dismiss ( ) : Promise < void > ;
57- getText ( ) : Promise < string > ;
58- sendKeys ( text : string ) : Promise < void > ;
59- } > ;
60- } ;
61- navigate ( ) : {
62- back ( ) : Promise < void > ;
63- forward ( ) : Promise < void > ;
64- refresh ( ) : Promise < void > ;
65- } ;
66- manage ( ) : {
67- window ( ) : {
68- setRect ( rect : { width : number ; height : number } ) : Promise < void > ;
69- } ;
70- } ;
71- actions ( opts ?: { async ?: boolean } ) : {
72- move ( opts : { x ?: number ; y ?: number ; origin ?: unknown } ) : any ;
73- click ( ) : any ;
74- doubleClick ( el ?: unknown ) : any ;
75- perform ( ) : Promise < void > ;
76- clear ( ) : Promise < void > ;
77- } ;
78- getBidi ( ) : Promise < IBiDi > ;
79- }
80- /* eslint-enable @typescript-eslint/no-explicit-any */
81-
8213// ---------------------------------------------------------------------------
8314// Geckodriver binary finder — used only for --connect-existing mode
8415// ---------------------------------------------------------------------------
@@ -135,7 +66,7 @@ async function findGeckodriver(): Promise<string> {
13566}
13667
13768export class FirefoxCore {
138- private driver : IDriver | null = null ;
69+ private driver : WebDriver | null = null ;
13970 private currentContextId : string | null = null ;
14071 private originalEnv : Record < string , string | undefined > = { } ;
14172 private logFilePath : string | undefined ;
@@ -177,8 +108,7 @@ export class FirefoxCore {
177108 // createSession() returns synchronously; the session is established async under the hood.
178109 // Passing geckodriverPath to ServiceBuilder prevents getBinaryPaths() from running,
179110 // which would otherwise invoke selenium-manager with --browser firefox.
180- const seleniumDriver = firefox . Driver . createSession ( caps , serviceBuilder . build ( ) ) ;
181- this . driver = seleniumDriver as unknown as IDriver ;
111+ this . driver = firefox . Driver . createSession ( caps , serviceBuilder . build ( ) ) ;
182112 } else {
183113 // Set up output file for capturing Firefox stdout/stderr
184114 if ( this . options . logFile ) {
@@ -255,12 +185,11 @@ export class FirefoxCore {
255185 log ( `📝 Capturing Firefox output to: ${ this . logFilePath } ` ) ;
256186 }
257187
258- // selenium WebDriver satisfies IDriver structurally at runtime
259- this . driver = ( await new Builder ( )
188+ this . driver = await new Builder ( )
260189 . forBrowser ( Browser . FIREFOX )
261190 . setFirefoxOptions ( firefoxOptions )
262191 . setFirefoxService ( serviceBuilder )
263- . build ( ) ) as unknown as IDriver ;
192+ . build ( ) ;
264193 }
265194
266195 log (
@@ -285,7 +214,7 @@ export class FirefoxCore {
285214 /**
286215 * Get driver instance (throw if not connected)
287216 */
288- getDriver ( ) : IDriver {
217+ getDriver ( ) : WebDriver {
289218 if ( ! this . driver ) {
290219 throw new Error ( 'Driver not connected' ) ;
291220 }
@@ -395,7 +324,9 @@ export class FirefoxCore {
395324 }
396325
397326 const bidi = await this . driver . getBidi ( ) ;
398- const ws = bidi . socket ;
327+ // bidi.socket is a Node.js `ws` WebSocket (EventEmitter-style), but typed as browser WebSocket
328+ // eslint-disable-next-line @typescript-eslint/no-explicit-any
329+ const ws = bidi . socket as any ;
399330
400331 // Wait for WebSocket to be ready before sending
401332 await this . waitForWebSocketOpen ( ws ) ;
0 commit comments