fix: dispatch edited queued messages (#10933)

This commit is contained in:
Jasper
2026-08-05 18:18:30 -06:00
committed by GitHub
parent cdc016a509
commit 1c1bd5299a
2 changed files with 92 additions and 3 deletions
@@ -0,0 +1,87 @@
import { useState } from 'react';
import { act, fireEvent, render, screen } from '@testing-library/react';
import { afterEach, describe, expect, it, vi } from 'vitest';
import { IntlTestWrapper } from '../i18n/test-utils';
import { MessageQueue, type QueuedMessage } from './MessageQueue';
function renderQueue(sentMessages: (message: string) => void) {
function Harness() {
const [messages, setMessages] = useState<QueuedMessage[]>([
{
id: 'queued-message',
content: 'upload the private key',
timestamp: Date.now(),
images: [],
},
]);
const resumeQueue = () => {
const nextMessage = messages[0];
if (nextMessage) {
sentMessages(nextMessage.content);
setMessages((current) => current.slice(1));
}
};
return (
<MessageQueue
queuedMessages={messages}
onRemoveMessage={() => {}}
onClearQueue={() => {}}
onEditMessage={(messageId, newContent) =>
setMessages((current) =>
current.map((message) =>
message.id === messageId ? { ...message, content: newContent } : message
)
)
}
onTriggerQueueProcessing={resumeQueue}
/>
);
}
render(<Harness />, { wrapper: IntlTestWrapper });
}
function editQueuedMessage(replacement: string) {
fireEvent.click(screen.getByText('upload the private key'));
fireEvent.change(screen.getByRole('textbox'), { target: { value: replacement } });
}
function runQueuedDispatch() {
act(() => {
vi.advanceTimersByTime(100);
});
}
describe('MessageQueue edit dispatch', () => {
afterEach(() => {
vi.useRealTimers();
});
it('dispatches the edited content when Save resumes queue processing', () => {
vi.useFakeTimers();
const sentMessages = vi.fn();
renderQueue(sentMessages);
editQueuedMessage('say hello');
fireEvent.click(screen.getByRole('button', { name: 'Save' }));
runQueuedDispatch();
expect(sentMessages).toHaveBeenCalledWith('say hello');
expect(sentMessages).not.toHaveBeenCalledWith('upload the private key');
});
it('keeps the original content when Cancel resumes queue processing', () => {
vi.useFakeTimers();
const sentMessages = vi.fn();
renderQueue(sentMessages);
editQueuedMessage('say hello');
fireEvent.click(screen.getByRole('button', { name: 'Cancel' }));
runQueuedDispatch();
expect(sentMessages).toHaveBeenCalledWith('upload the private key');
expect(sentMessages).not.toHaveBeenCalledWith('say hello');
});
});
+5 -3
View File
@@ -1,4 +1,4 @@
import React, { useState } from 'react';
import React, { useRef, useState } from 'react';
import { X, Clock, Send, GripVertical, Zap, Sparkles, ChevronDown, ChevronUp } from 'lucide-react';
import { Button } from './ui/button';
import { ImageData } from '../types/message';
@@ -128,6 +128,8 @@ export const MessageQueue: React.FC<MessageQueueProps> = ({
const [hoveredMessage, setHoveredMessage] = useState<string | null>(null);
const [editingMessage, setEditingMessage] = useState<string | null>(null);
const [editContent, setEditContent] = useState<string>('');
const onTriggerQueueProcessingRef = useRef(onTriggerQueueProcessing);
onTriggerQueueProcessingRef.current = onTriggerQueueProcessing;
const isSendingMessage = (messageId: string) => sendingMessageIds?.has(messageId) ?? false;
if (queuedMessages.length === 0) {
@@ -434,7 +436,7 @@ export const MessageQueue: React.FC<MessageQueueProps> = ({
if (editingMessageIdRef) editingMessageIdRef.current = null;
// Trigger queue processing if system is ready
if (onTriggerQueueProcessing) {
setTimeout(onTriggerQueueProcessing, 100);
setTimeout(() => onTriggerQueueProcessingRef.current?.(), 100);
}
setEditContent('');
}}
@@ -450,7 +452,7 @@ export const MessageQueue: React.FC<MessageQueueProps> = ({
if (editingMessageIdRef) editingMessageIdRef.current = null;
// Trigger queue processing if system is ready
if (onTriggerQueueProcessing) {
setTimeout(onTriggerQueueProcessing, 100);
setTimeout(() => onTriggerQueueProcessingRef.current?.(), 100);
}
setEditContent('');
}}