Skip to content

Commit 683664e

Browse files
committed
preserved inherited treq profile in spawned profile
1 parent 7bfc04f commit 683664e

File tree

4 files changed

+136
-51
lines changed

4 files changed

+136
-51
lines changed

packages/app/src/server/app.ts

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -171,6 +171,7 @@ export type ServerConfig = {
171171
workspace?: string;
172172
port: number;
173173
host: string;
174+
profile?: string;
174175
token?: string;
175176
corsOrigins?: string[];
176177
maxBodyBytes: number;
@@ -239,6 +240,7 @@ export function createApp(config: ServerConfig) {
239240
workspaceRoot,
240241
maxBodyBytes: config.maxBodyBytes,
241242
maxSessions: config.maxSessions,
243+
profile: config.profile,
242244
onEvent: (sessionId, runId, event) => {
243245
eventManager.emit(sessionId, runId, event);
244246
}

packages/app/src/server/script-runner.ts

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -335,10 +335,10 @@ export function runScript(options: RunScriptOptions): RunningScript {
335335
const env: Record<string, string | undefined> = {
336336
...process.env,
337337
TREQ_SERVER: serverUrl,
338-
TREQ_PROFILE: profile,
339338
TREQ_FLOW_ID: flowId,
340339
TREQ_SESSION_ID: sessionId,
341-
TREQ_TOKEN: scriptToken // Scoped token (not the main server token)
340+
TREQ_TOKEN: scriptToken, // Scoped token (not the main server token)
341+
...(profile !== undefined ? { TREQ_PROFILE: profile } : {})
342342
};
343343

344344
// Spawn the process

packages/app/src/server/test-runner.ts

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -320,10 +320,10 @@ export function runTest(options: RunTestOptions): RunningTest {
320320
const env: Record<string, string | undefined> = {
321321
...process.env,
322322
TREQ_SERVER: serverUrl,
323-
TREQ_PROFILE: profile,
324323
TREQ_FLOW_ID: flowId,
325324
TREQ_SESSION_ID: sessionId,
326-
TREQ_TOKEN: scriptToken // Scoped token (not the main server token)
325+
TREQ_TOKEN: scriptToken, // Scoped token (not the main server token)
326+
...(profile !== undefined ? { TREQ_PROFILE: profile } : {})
327327
};
328328

329329
// Spawn the process

packages/app/test/integration/profile-runner.test.ts

Lines changed: 130 additions & 47 deletions
Original file line numberDiff line numberDiff line change
@@ -6,6 +6,7 @@ import { createApp, type ServerConfig } from '../../src/server/app';
66
import type { EventEnvelope } from '../../src/server/events';
77

88
type TestApp = ReturnType<typeof createApp>;
9+
const clientModuleUrl = new URL('../../../core/src/client.ts', import.meta.url).href;
910

1011
async 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+
72103
describe('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

Comments
 (0)