mirror of
https://github.com/danny-avila/LibreChat.git
synced 2026-08-04 14:57:42 +00:00
test(e2e): cover interrupt & steer sealing mid-stream
The mock Playwright suite covered every sibling during-run action — steer at a tool boundary, steer degrading to a queued follow-up, queue, and interrupt & send — but not interrupt & steer, the one this stack adds. Uses E2E_SLOW_REPLY, which streams pure text with no tools, so the scenario is the same one where an ordinary steer provably degrades to a queued follow-up turn. Injecting in-thread there is something only a mid-stream seal can do, which makes the assertion discriminating rather than incidental: the steer part lands in the response, the final chunk never arrives, the text written before the seal survives, and no follow-up turn pair is created.
This commit is contained in:
parent
1a84222fca
commit
0ece357170
1 changed files with 53 additions and 0 deletions
|
|
@ -481,4 +481,57 @@ test.describe('mid-run steering and queuing', () => {
|
||||||
// arrived (an uninterrupted slow run always ends with it).
|
// arrived (an uninterrupted slow run always ends with it).
|
||||||
await expect(messagesView(page).getByText(SLOW_REPLY_LAST_CHUNK)).toHaveCount(0);
|
await expect(messagesView(page).getByText(SLOW_REPLY_LAST_CHUNK)).toHaveCount(0);
|
||||||
});
|
});
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Interrupt & steer is the only path that can inject with NO tool boundary
|
||||||
|
* ahead of it: the server asks the generating replica to seal the model
|
||||||
|
* stream at the next provider-safe chunk, keeps the partial answer, and
|
||||||
|
* resumes in the same message.
|
||||||
|
*
|
||||||
|
* The contrast with the two tests above IS the feature. `E2E_SLOW_REPLY`
|
||||||
|
* streams pure text with no tools, so an ordinary steer there provably
|
||||||
|
* degrades to a queued follow-up turn ("steer after the last tool boundary"
|
||||||
|
* above), and interrupt & send discards the half-written answer entirely.
|
||||||
|
* This path does neither: same absence of a boundary, opposite outcome.
|
||||||
|
*/
|
||||||
|
test('interrupt & steer (Cmd/Ctrl+Shift+Enter) seals mid-stream and injects with no tool boundary', async ({
|
||||||
|
page,
|
||||||
|
}) => {
|
||||||
|
test.setTimeout(150000);
|
||||||
|
const label = uniqueLabel('preempt');
|
||||||
|
const steerText = `Preempt steer ${label}`;
|
||||||
|
|
||||||
|
await page.goto(NEW_CHAT_PATH, { timeout: 10000 });
|
||||||
|
await selectMockEndpoint(page, MOCK_ENDPOINTS[0]);
|
||||||
|
await establishConversation(page, `preempt-setup-${label}`);
|
||||||
|
|
||||||
|
const run = await sendMessage(page, `E2E_SLOW_REPLY:${label}`);
|
||||||
|
expect(run.ok()).toBeTruthy();
|
||||||
|
// Let it visibly stream first, so the seal lands mid-generation.
|
||||||
|
await expect(messagesView(page).getByText('chunk-010')).toBeVisible({ timeout: 15000 });
|
||||||
|
|
||||||
|
await typeDuringRun(page, steerText);
|
||||||
|
const [steerResponse] = await Promise.all([
|
||||||
|
page.waitForResponse(isSteerRequest, { timeout: 15000 }),
|
||||||
|
messageInput(page).press('ControlOrMeta+Shift+Enter'),
|
||||||
|
]);
|
||||||
|
expect(steerResponse.status()).toBe(202);
|
||||||
|
|
||||||
|
// Injected in-thread with no tool boundary available — only a mid-stream
|
||||||
|
// seal can put a steer part here.
|
||||||
|
await expect(appliedSteerParts(page).filter({ hasText: steerText })).toHaveCount(1, {
|
||||||
|
timeout: 90000,
|
||||||
|
});
|
||||||
|
await expect(inFlightSteers(page)).toHaveCount(0);
|
||||||
|
|
||||||
|
// Sealed, not run to completion: the last chunk never arrives. And unlike
|
||||||
|
// interrupt & send, the text written before the seal survives.
|
||||||
|
await expect(messagesView(page).getByText(SLOW_REPLY_LAST_CHUNK)).toHaveCount(0);
|
||||||
|
await expect(messagesView(page).getByText('chunk-010')).toBeVisible();
|
||||||
|
|
||||||
|
// Stayed INSIDE the response: the setup pair plus this pair, with no
|
||||||
|
// auto-sent follow-up pair (which both degradation paths produce).
|
||||||
|
await expect(messageTurns(page)).toHaveCount(4);
|
||||||
|
await expect(queuedRows(page)).toHaveCount(0);
|
||||||
|
});
|
||||||
});
|
});
|
||||||
|
|
|
||||||
Loading…
Add table
Add a link
Reference in a new issue