@@ -80,7 +80,6 @@ function checkTauriDriver(): boolean {
8080 }
8181}
8282
83-
8483// Clear the app's SQLite database and related files for a clean start
8584function clearAppData ( ) : void {
8685 const filesToDelete = [
@@ -125,7 +124,7 @@ function clearBundleCache(): void {
125124async function waitForServer ( port : number , name : string , timeout = 30000 ) : Promise < void > {
126125 const start = Date . now ( ) ;
127126 const healthUrl = `http://localhost:${ port } /health` ;
128-
127+
129128 while ( Date . now ( ) - start < timeout ) {
130129 try {
131130 const response = await fetch ( healthUrl ) ;
@@ -138,44 +137,68 @@ async function waitForServer(port: number, name: string, timeout = 30000): Promi
138137 }
139138 await new Promise ( ( resolve ) => setTimeout ( resolve , 200 ) ) ;
140139 }
141-
140+
142141 throw new Error ( `[e2e] ${ name } failed to start within ${ timeout } ms` ) ;
143142}
144143
145144// Start mock servers
146145async function startMockServers ( ) : Promise < void > {
147146 const mocksDir = path . resolve ( './tests/e2e/mocks' ) ;
148-
147+
149148 // Start Mock Bundle API
150149 console . log ( '[e2e] Starting Mock Bundle API...' ) ;
151- mockBundleApi = spawn ( 'pnpm' , [ 'exec' , 'tsx' , path . join ( mocksDir , 'mock-bundle-api' , 'server.ts' ) ] , {
152- env : { ...process . env , PORT : String ( MOCK_BUNDLE_API_PORT ) } ,
153- stdio : [ 'ignore' , 'pipe' , 'pipe' ] ,
154- shell : true ,
155- } ) ;
156- mockBundleApi . stdout ?. on ( 'data' , ( data ) => console . log ( `[mock-bundle-api] ${ data . toString ( ) . trim ( ) } ` ) ) ;
157- mockBundleApi . stderr ?. on ( 'data' , ( data ) => console . error ( `[mock-bundle-api] ${ data . toString ( ) . trim ( ) } ` ) ) ;
158-
150+ mockBundleApi = spawn (
151+ 'pnpm' ,
152+ [ 'exec' , 'tsx' , path . join ( mocksDir , 'mock-bundle-api' , 'server.ts' ) ] ,
153+ {
154+ env : { ...process . env , PORT : String ( MOCK_BUNDLE_API_PORT ) } ,
155+ stdio : [ 'ignore' , 'pipe' , 'pipe' ] ,
156+ shell : true ,
157+ }
158+ ) ;
159+ mockBundleApi . stdout ?. on ( 'data' , ( data ) =>
160+ console . log ( `[mock-bundle-api] ${ data . toString ( ) . trim ( ) } ` )
161+ ) ;
162+ mockBundleApi . stderr ?. on ( 'data' , ( data ) =>
163+ console . error ( `[mock-bundle-api] ${ data . toString ( ) . trim ( ) } ` )
164+ ) ;
165+
159166 // Start Stub MCP HTTP Server
160167 console . log ( '[e2e] Starting Stub MCP HTTP Server...' ) ;
161- stubMcpHttp = spawn ( 'pnpm' , [ 'exec' , 'tsx' , path . join ( mocksDir , 'stub-mcp-server' , 'http-server.ts' ) ] , {
162- env : { ...process . env , PORT : String ( STUB_MCP_HTTP_PORT ) } ,
163- stdio : [ 'ignore' , 'pipe' , 'pipe' ] ,
164- shell : true ,
165- } ) ;
166- stubMcpHttp . stdout ?. on ( 'data' , ( data ) => console . log ( `[stub-mcp-http] ${ data . toString ( ) . trim ( ) } ` ) ) ;
167- stubMcpHttp . stderr ?. on ( 'data' , ( data ) => console . error ( `[stub-mcp-http] ${ data . toString ( ) . trim ( ) } ` ) ) ;
168-
168+ stubMcpHttp = spawn (
169+ 'pnpm' ,
170+ [ 'exec' , 'tsx' , path . join ( mocksDir , 'stub-mcp-server' , 'http-server.ts' ) ] ,
171+ {
172+ env : { ...process . env , PORT : String ( STUB_MCP_HTTP_PORT ) } ,
173+ stdio : [ 'ignore' , 'pipe' , 'pipe' ] ,
174+ shell : true ,
175+ }
176+ ) ;
177+ stubMcpHttp . stdout ?. on ( 'data' , ( data ) =>
178+ console . log ( `[stub-mcp-http] ${ data . toString ( ) . trim ( ) } ` )
179+ ) ;
180+ stubMcpHttp . stderr ?. on ( 'data' , ( data ) =>
181+ console . error ( `[stub-mcp-http] ${ data . toString ( ) . trim ( ) } ` )
182+ ) ;
183+
169184 // Start Stub MCP OAuth Server
170185 console . log ( '[e2e] Starting Stub MCP OAuth Server...' ) ;
171- stubMcpOauth = spawn ( 'pnpm' , [ 'exec' , 'tsx' , path . join ( mocksDir , 'stub-mcp-server' , 'http-oauth-server.ts' ) ] , {
172- env : { ...process . env , PORT : String ( STUB_MCP_OAUTH_PORT ) } ,
173- stdio : [ 'ignore' , 'pipe' , 'pipe' ] ,
174- shell : true ,
175- } ) ;
176- stubMcpOauth . stdout ?. on ( 'data' , ( data ) => console . log ( `[stub-mcp-oauth] ${ data . toString ( ) . trim ( ) } ` ) ) ;
177- stubMcpOauth . stderr ?. on ( 'data' , ( data ) => console . error ( `[stub-mcp-oauth] ${ data . toString ( ) . trim ( ) } ` ) ) ;
178-
186+ stubMcpOauth = spawn (
187+ 'pnpm' ,
188+ [ 'exec' , 'tsx' , path . join ( mocksDir , 'stub-mcp-server' , 'http-oauth-server.ts' ) ] ,
189+ {
190+ env : { ...process . env , PORT : String ( STUB_MCP_OAUTH_PORT ) } ,
191+ stdio : [ 'ignore' , 'pipe' , 'pipe' ] ,
192+ shell : true ,
193+ }
194+ ) ;
195+ stubMcpOauth . stdout ?. on ( 'data' , ( data ) =>
196+ console . log ( `[stub-mcp-oauth] ${ data . toString ( ) . trim ( ) } ` )
197+ ) ;
198+ stubMcpOauth . stderr ?. on ( 'data' , ( data ) =>
199+ console . error ( `[stub-mcp-oauth] ${ data . toString ( ) . trim ( ) } ` )
200+ ) ;
201+
179202 // Wait for all servers to be ready
180203 await Promise . all ( [
181204 waitForServer ( MOCK_BUNDLE_API_PORT , 'Mock Bundle API' ) ,
@@ -239,7 +262,14 @@ function killPortProcesses(): void {
239262 try {
240263 if ( process . platform === 'win32' ) {
241264 // Find PIDs listening on this port and kill them
242- const result = spawnSync ( 'cmd' , [ '/c' , `for /f "tokens=5" %a in ('netstat -ano ^| findstr ":${ port } " ^| findstr LISTEN') do taskkill /F /PID %a` ] , { stdio : 'pipe' , shell : true } ) ;
265+ const result = spawnSync (
266+ 'cmd' ,
267+ [
268+ '/c' ,
269+ `for /f "tokens=5" %a in ('netstat -ano ^| findstr ":${ port } " ^| findstr LISTEN') do taskkill /F /PID %a` ,
270+ ] ,
271+ { stdio : 'pipe' , shell : true }
272+ ) ;
243273 if ( result . stdout ?. toString ( ) . includes ( 'SUCCESS' ) ) {
244274 console . log ( `[e2e] Killed process on port ${ port } ` ) ;
245275 }
@@ -338,22 +368,30 @@ export const config: Options.Testrunner = {
338368 framework : 'mocha' ,
339369 reporters : [
340370 'spec' ,
341- [ 'junit' , {
342- outputDir : './tests/e2e/reports/' ,
343- outputFileFormat : function ( options ) {
344- return `wdio-junit-${ options . cid } .xml` ;
371+ [
372+ 'junit' ,
373+ {
374+ outputDir : './tests/e2e/reports/' ,
375+ outputFileFormat : function ( options ) {
376+ return `wdio-junit-${ options . cid } .xml` ;
377+ } ,
345378 } ,
346- } ] ,
379+ ] ,
347380 // Only enable video reporter when explicitly requested via SAVE_ALL_VIDEOS=true.
348381 // The video reporter takes a screenshot after every WebDriver command, including
349382 // during session teardown. This races with deleteSession killing the Tauri app,
350383 // causing UND_ERR_SOCKET errors that mark passing specs as FAILED.
351384 ...( process . env . SAVE_ALL_VIDEOS === 'true'
352- ? [ [ video , {
353- saveAllVideos : true ,
354- videoSlowdownMultiplier : 1 ,
355- outputDir : './tests/e2e/videos/' ,
356- } ] ]
385+ ? [
386+ [
387+ video ,
388+ {
389+ saveAllVideos : true ,
390+ videoSlowdownMultiplier : 1 ,
391+ outputDir : './tests/e2e/videos/' ,
392+ } ,
393+ ] ,
394+ ]
357395 : [ ] ) ,
358396 ] ,
359397
@@ -363,7 +401,7 @@ export const config: Options.Testrunner = {
363401 } ,
364402
365403 // Take screenshot on test failure
366- afterTest : async function ( test , context , { error } ) {
404+ afterTest : async function ( test , context , { error } ) {
367405 if ( error ) {
368406 const timestamp = new Date ( ) . toISOString ( ) . replace ( / [: .] / g, '-' ) ;
369407 // Sanitize test title: replace invalid filename chars (NTFS: " : < > | * ? \r \n) and spaces
@@ -458,12 +496,16 @@ export const config: Options.Testrunner = {
458496 process . platform === 'win32' ? 'tauri-driver.exe' : 'tauri-driver'
459497 ) ;
460498
461- // Pass registry URL environment variable to tauri-driver (which passes to the app)
499+ // Pass environment variables to tauri-driver (which passes to the app)
500+ // MCPMUX_E2E_TEST=1 enables test-only endpoints:
501+ // - POST /oauth/consent/approve (HTTP consent for programmatic OAuth flow)
502+ // - approve_oauth_client Tauri IPC command
462503 tauriDriver = spawn ( tauriDriverPath , [ ] , {
463504 stdio : [ null , process . stdout , process . stderr ] ,
464505 env : {
465506 ...process . env ,
466507 MCPMUX_REGISTRY_URL : `http://localhost:${ MOCK_BUNDLE_API_PORT } ` ,
508+ MCPMUX_E2E_TEST : '1' ,
467509 } ,
468510 } ) ;
469511
0 commit comments