qwen-code/packages/web-shell/client/hooks/useQueuedPrompts.test.ts
Nothing Chan 288140b28b
fix(web-shell): stop stacking duplicate copies when restoring prompt text (#7134)
Several restoration paths return a failed prompt's text to the composer
by prepending it above the current draft: failed queue submits, failed
mid-turn inserts, and queue clears. More than one of them can fire for
the same prompt across reconnects and refreshes, and a user retrying an
identical message produces identical text — each pass stacked another
copy, which surfaced as multiple sent messages concatenated back into
the input box after a page refresh (#7128).

Extract the merge into mergeRestoredPromptText() and make it
idempotent: restoring text that is already at the top of the editor is
a no-op. Restoring different text still prepends above the draft.

This addresses the text-stacking defect (bug 3 in the triage analysis).
The SSE-reconnect-on-prompt question (bug 1) is a behavioral decision
left to maintainers.

Fixes #7128

Co-authored-by: Claude Fable 5 <noreply@anthropic.com>
2026-07-17 22:22:50 +00:00

44 lines
1.6 KiB
TypeScript

import { describe, expect, it } from 'vitest';
import { mergeRestoredPromptText } from './useQueuedPrompts';
// Regression for #7128: restoration paths can fire more than once for the
// same prompt (failed submit + reconnect/refresh, queue clear racing an
// abort), and a user retrying an identical message restores identical text.
// Stacking those copies is what surfaced as "sent messages concatenated back
// into the input box after refresh".
describe('mergeRestoredPromptText', () => {
it('fills an empty editor with the restored text', () => {
expect(mergeRestoredPromptText('', 'hello')).toBe('hello');
expect(mergeRestoredPromptText(' ', 'hello')).toBe('hello');
});
it('prepends above a different draft the user is typing', () => {
expect(mergeRestoredPromptText('draft', 'restored')).toBe(
'restored\ndraft',
);
});
it('is a no-op when the same text was already restored', () => {
expect(mergeRestoredPromptText('hello', 'hello')).toBe('hello');
});
it('is a no-op when the text already sits at the top of the editor', () => {
expect(mergeRestoredPromptText('hello\ndraft', 'hello')).toBe(
'hello\ndraft',
);
});
it('stays idempotent across repeated restores of the same prompt', () => {
let editor = '';
for (let i = 0; i < 3; i++) {
editor = mergeRestoredPromptText(editor, '用python写一个hello world');
}
expect(editor).toBe('用python写一个hello world');
});
it('does not treat a same-prefix but different first line as a duplicate', () => {
expect(mergeRestoredPromptText('hello world\ndraft', 'hello')).toBe(
'hello\nhello world\ndraft',
);
});
});