🧪 test: Decouple lazy provisioning assertions from tool completion

The lazy specs asserted the fake-model completion text before checking the fake
servers. Provisioning fires at ON_TOOL_EXECUTE, before the tool itself runs, so
assert it directly and independent of the tool result:
- code: poll the fake code server for the original filename (uploadCodeEnvFile
  preserves it).
- RAG: correlate on file_id from the upload response — uploadVectors streams from
  a temp path, so the fake RAG records provision-<file_id>.csv, not the original.
This commit is contained in:
Danny Avila 2026-07-09 10:48:57 -04:00
parent 6f8f6a57f8
commit f620673d97
2 changed files with 14 additions and 11 deletions

View file

@ -1,4 +1,5 @@
import { expect, test } from '@playwright/test';
import type { UploadedFile } from './helpers';
import {
MOCK_ENDPOINTS,
NEW_CHAT_PATH,
@ -106,14 +107,13 @@ test.describe('file provisioning — lazy (unified upload, at tool-execute)', ()
await expect(page.getByRole('button', { name: fileName })).toBeVisible({ timeout: 15000 });
// A tool run triggers lazy provisioning: the fake model emits an execute_code call.
// Provisioning fires at ON_TOOL_EXECUTE, before the execute_code tool itself runs,
// so assert it reached the code env independent of the tool's own result.
await sendMessage(page, `E2E_EXECUTE_CODE:${uniqueName('run')}`);
await expect(
page.getByTestId('messages-view').getByText(/E2E execute_code complete:/),
).toBeVisible({ timeout: 30000 });
await expect
.poll(async () => (await getCodeProvisionedUploads(page)).map((u) => u.filename), {
timeout: 15000,
timeout: 30000,
})
.toContain(fileName);
});
@ -134,19 +134,21 @@ test.describe('file provisioning — lazy (unified upload, at tool-execute)', ()
content: 'k,v\nfoo,bar\n',
});
expect(response.ok()).toBeTruthy();
// uploadVectors streams from a temp path, so the fake RAG records the file_id,
// not the original filename — correlate on the id from the upload response.
const fileId = ((await response.json()) as UploadedFile).file_id;
expect(fileId, 'upload response should include a file_id').toBeTruthy();
expect(
(await getRagEmbedded(page)).map((e) => e.filename),
(await getRagEmbedded(page)).map((e) => e.file_id),
'unified upload must not embed until file_search runs',
).not.toContain(fileName);
).not.toContain(fileId);
await expect(page.getByRole('button', { name: fileName })).toBeVisible({ timeout: 15000 });
// Embedding fires at ON_TOOL_EXECUTE, independent of the file_search tool result.
await sendMessage(page, `E2E_FILE_SEARCH:${uniqueName('q')}`);
await expect(
page.getByTestId('messages-view').getByText(/E2E file_search complete:/),
).toBeVisible({ timeout: 30000 });
await expect
.poll(async () => (await getRagEmbedded(page)).map((e) => e.filename), { timeout: 15000 })
.toContain(fileName);
.poll(async () => (await getRagEmbedded(page)).map((e) => e.file_id), { timeout: 30000 })
.toContain(fileId);
});
});

View file

@ -243,6 +243,7 @@ export async function resetProvisioning(page: Page): Promise<void> {
/** Shape of a file record as returned by POST /api/files and GET /api/files. */
export type UploadedFile = {
file_id?: string;
filename?: string;
type?: string;
llmDeliveryPath?: string;