@@ -6,6 +6,7 @@ import { createApp, type ServerConfig } from '../../src/server/app';
66import type { EventEnvelope } from '../../src/server/events' ;
77
88type TestApp = ReturnType < typeof createApp > ;
9+ const clientModuleUrl = new URL ( '../../../core/src/client.ts' , import . meta. url ) . href ;
910
1011async function getAvailablePort ( ) : Promise < number > {
1112 return await new Promise ( ( resolve , reject ) => {
@@ -59,23 +60,84 @@ async function waitForFlowEvent(
5960 throw new Error ( `Timed out waiting for ${ eventType } for flow ${ flowId } ` ) ;
6061}
6162
62- function createTestConfig ( workspaceRoot : string , port : number ) : ServerConfig {
63+ function createTestConfig ( workspaceRoot : string , port : number , profile ?: string ) : ServerConfig {
6364 return {
6465 workspace : workspaceRoot ,
6566 port,
6667 host : '127.0.0.1' ,
68+ profile,
6769 maxBodyBytes : 1024 * 1024 ,
6870 maxSessions : 10
6971 } ;
7072}
7173
74+ function buildRunnerScriptSource ( ) : string {
75+ return `import { createClient } from '${ clientModuleUrl } ';
76+
77+ const client = createClient({ server: process.env.TREQ_SERVER });
78+ const response = await client.run('profile.http');
79+
80+ if (!response.ok) {
81+ throw new Error(\`Unexpected status: \${response.status}\`);
82+ }
83+
84+ await client.close();
85+ ` ;
86+ }
87+
88+ function buildRunnerTestSource ( ) : string {
89+ return `import { expect, test } from 'bun:test';
90+ import { createClient } from '${ clientModuleUrl } ';
91+
92+ test('uses the active profile', async () => {
93+ const client = createClient({ server: process.env.TREQ_SERVER });
94+ const response = await client.run('profile.http');
95+
96+ expect(response.status).toBe(200);
97+
98+ await client.close();
99+ });
100+ ` ;
101+ }
102+
72103describe ( 'Runner profile propagation' , ( ) => {
73104 let workspaceRoot = '' ;
74105 let appPort = 0 ;
75106 let appResult : TestApp | undefined ;
76107 let appServer : Bun . Server | undefined ;
77108 let upstreamServer : Bun . Server | undefined ;
78109
110+ function getAppResult ( ) : TestApp {
111+ if ( ! appResult ) {
112+ throw new Error ( 'App is not running' ) ;
113+ }
114+ return appResult ;
115+ }
116+
117+ async function startApp ( profile ?: string ) : Promise < void > {
118+ appResult = createApp ( createTestConfig ( workspaceRoot , appPort , profile ) ) ;
119+ appServer = Bun . serve ( {
120+ fetch : appResult . app . fetch ,
121+ websocket : appResult . websocket ,
122+ port : appPort ,
123+ hostname : '127.0.0.1'
124+ } ) ;
125+ }
126+
127+ async function stopApp ( ) : Promise < void > {
128+ appServer ?. stop ( true ) ;
129+ appServer = undefined ;
130+
131+ if ( ! appResult ) {
132+ return ;
133+ }
134+
135+ appResult . eventManager . closeAll ( ) ;
136+ await appResult . service . dispose ( ) ;
137+ appResult . dispose ( ) ;
138+ appResult = undefined ;
139+ }
140+
79141 beforeEach ( async ( ) => {
80142 workspaceRoot = await mkdtemp ( join ( dirname ( import . meta. dir ) , 'tmp-profile-runner-' ) ) ;
81143 appPort = await getAvailablePort ( ) ;
@@ -117,47 +179,20 @@ describe('Runner profile propagation', () => {
117179 `GET {{baseUrl}}/profile-check
118180`
119181 ) ;
120-
121- appResult = createApp ( createTestConfig ( workspaceRoot , appPort ) ) ;
122- appServer = Bun . serve ( {
123- fetch : appResult . app . fetch ,
124- websocket : appResult . websocket ,
125- port : appPort ,
126- hostname : '127.0.0.1'
127- } ) ;
182+ await startApp ( ) ;
128183 } ) ;
129184
130185 afterEach ( async ( ) => {
131- appServer ?. stop ( true ) ;
186+ await stopApp ( ) ;
132187 upstreamServer ?. stop ( true ) ;
133188
134- if ( appResult ) {
135- appResult . eventManager . closeAll ( ) ;
136- await appResult . service . dispose ( ) ;
137- appResult . dispose ( ) ;
138- }
139-
140189 if ( workspaceRoot ) {
141190 await rm ( workspaceRoot , { recursive : true , force : true } ) ;
142191 }
143192 } ) ;
144193
145194 test ( 'POST /script applies a profile-only baseUrl for spawned clients' , async ( ) => {
146- await writeWorkspaceFile (
147- workspaceRoot ,
148- 'runner-script.ts' ,
149- `import { createClient } from '../../../core/src/client.ts';
150-
151- const client = createClient({ server: process.env.TREQ_SERVER });
152- const response = await client.run('profile.http');
153-
154- if (!response.ok) {
155- throw new Error(\`Unexpected status: \${response.status}\`);
156- }
157-
158- await client.close();
159- `
160- ) ;
195+ await writeWorkspaceFile ( workspaceRoot , 'runner-script.ts' , buildRunnerScriptSource ( ) ) ;
161196
162197 const response = await fetch ( `http://127.0.0.1:${ appPort } /script` , {
163198 method : 'POST' ,
@@ -174,35 +209,79 @@ await client.close();
174209 expect ( data . flowId ) . toBeDefined ( ) ;
175210 expect ( data . runId ) . toBeDefined ( ) ;
176211
177- const finished = await waitForFlowEvent ( appResult ! . eventManager , data . flowId , 'scriptFinished' ) ;
212+ const finished = await waitForFlowEvent (
213+ getAppResult ( ) . eventManager ,
214+ data . flowId ,
215+ 'scriptFinished'
216+ ) ;
178217 expect ( finished . payload . exitCode ) . toBe ( 0 ) ;
179218 } ) ;
180219
181220 test ( 'POST /test applies a profile-only baseUrl for spawned clients' , async ( ) => {
182- await writeWorkspaceFile (
183- workspaceRoot ,
184- 'runner.test.ts' ,
185- `import { expect, test } from 'bun:test';
186- import { createClient } from '../../../core/src/client.ts';
221+ await writeWorkspaceFile ( workspaceRoot , 'runner.test.ts' , buildRunnerTestSource ( ) ) ;
187222
188- test('uses the active profile', async () => {
189- const client = createClient({ server: process.env.TREQ_SERVER });
190- const response = await client.run('profile.http');
223+ const response = await fetch ( `http://127.0.0.1:${ appPort } /test` , {
224+ method : 'POST' ,
225+ headers : { 'Content-Type' : 'application/json' } ,
226+ body : JSON . stringify ( {
227+ filePath : 'runner.test.ts' ,
228+ frameworkId : 'bun' ,
229+ profile : 'playground'
230+ } )
231+ } ) ;
191232
192- expect(response.status).toBe(200);
233+ const data = ( await response . json ( ) ) as { flowId : string ; runId : string } ;
234+ expect ( response . status ) . toBe ( 200 ) ;
235+ expect ( data . flowId ) . toBeDefined ( ) ;
236+ expect ( data . runId ) . toBeDefined ( ) ;
193237
194- await client.close();
195- });
196- `
238+ const finished = await waitForFlowEvent (
239+ getAppResult ( ) . eventManager ,
240+ data . flowId ,
241+ 'testFinished'
197242 ) ;
243+ expect ( finished . payload . exitCode ) . toBe ( 0 ) ;
244+ expect ( finished . payload . status ) . toBe ( 'passed' ) ;
245+ } ) ;
246+
247+ test ( 'POST /script falls back to the server default profile when request.profile is omitted' , async ( ) => {
248+ await stopApp ( ) ;
249+ await startApp ( 'playground' ) ;
250+ await writeWorkspaceFile ( workspaceRoot , 'runner-script.ts' , buildRunnerScriptSource ( ) ) ;
251+
252+ const response = await fetch ( `http://127.0.0.1:${ appPort } /script` , {
253+ method : 'POST' ,
254+ headers : { 'Content-Type' : 'application/json' } ,
255+ body : JSON . stringify ( {
256+ filePath : 'runner-script.ts' ,
257+ runnerId : 'bun'
258+ } )
259+ } ) ;
260+
261+ const data = ( await response . json ( ) ) as { flowId : string ; runId : string } ;
262+ expect ( response . status ) . toBe ( 200 ) ;
263+ expect ( data . flowId ) . toBeDefined ( ) ;
264+ expect ( data . runId ) . toBeDefined ( ) ;
265+
266+ const finished = await waitForFlowEvent (
267+ getAppResult ( ) . eventManager ,
268+ data . flowId ,
269+ 'scriptFinished'
270+ ) ;
271+ expect ( finished . payload . exitCode ) . toBe ( 0 ) ;
272+ } ) ;
273+
274+ test ( 'POST /test falls back to the server default profile when request.profile is omitted' , async ( ) => {
275+ await stopApp ( ) ;
276+ await startApp ( 'playground' ) ;
277+ await writeWorkspaceFile ( workspaceRoot , 'runner.test.ts' , buildRunnerTestSource ( ) ) ;
198278
199279 const response = await fetch ( `http://127.0.0.1:${ appPort } /test` , {
200280 method : 'POST' ,
201281 headers : { 'Content-Type' : 'application/json' } ,
202282 body : JSON . stringify ( {
203283 filePath : 'runner.test.ts' ,
204- frameworkId : 'bun' ,
205- profile : 'playground'
284+ frameworkId : 'bun'
206285 } )
207286 } ) ;
208287
@@ -211,7 +290,11 @@ test('uses the active profile', async () => {
211290 expect ( data . flowId ) . toBeDefined ( ) ;
212291 expect ( data . runId ) . toBeDefined ( ) ;
213292
214- const finished = await waitForFlowEvent ( appResult ! . eventManager , data . flowId , 'testFinished' ) ;
293+ const finished = await waitForFlowEvent (
294+ getAppResult ( ) . eventManager ,
295+ data . flowId ,
296+ 'testFinished'
297+ ) ;
215298 expect ( finished . payload . exitCode ) . toBe ( 0 ) ;
216299 expect ( finished . payload . status ) . toBe ( 'passed' ) ;
217300 } ) ;
0 commit comments