fix(desktop): start recipe deeplink sessions from the recipe prompt (#8424)

Signed-off-by: sunilkumarvalmiki <g.sunilkumarvalmiki@gmail.com>
Co-authored-by: Lifei Zhou <lifei@squareup.com>
This commit is contained in:
g.sunilkumar
2026-04-10 11:46:23 +05:30
committed by GitHub
parent ed4836b923
commit b1eff5f7f9
5 changed files with 140 additions and 6 deletions
@@ -0,0 +1,92 @@
import { describe, it, expect, vi, beforeEach } from 'vitest';
import { renderHook } from '@testing-library/react';
import { MemoryRouter } from 'react-router-dom';
import type { PropsWithChildren } from 'react';
import { useAutoSubmit } from './useAutoSubmit';
import { ChatState } from '../types/chatState';
import type { Session } from '../api';
import type { UserInput } from '../types/message';
function makeSession(overrides: Partial<Session> = {}): Session {
return {
id: 'sess-1',
name: 'untitled',
message_count: 0,
created_at: new Date().toISOString(),
updated_at: new Date().toISOString(),
working_dir: '/tmp',
extension_data: { active: [], installed: [] },
...overrides,
} as Session;
}
const initialMessage: UserInput = {
msg: 'Run the recipe',
images: [],
};
describe('useAutoSubmit', () => {
beforeEach(() => {
vi.clearAllMocks();
});
it('does not auto-submit while recipe acceptance is unresolved', () => {
const handleSubmit = vi.fn();
const dispatchEventSpy = vi.spyOn(window, 'dispatchEvent');
const wrapper = ({ children }: PropsWithChildren) => (
<MemoryRouter initialEntries={['/pair?resumeSessionId=sess-1']}>{children}</MemoryRouter>
);
renderHook(
() =>
useAutoSubmit({
sessionId: 'sess-1',
session: makeSession(),
messages: [],
chatState: ChatState.Idle,
initialMessage,
canAutoSubmit: false,
handleSubmit,
}),
{ wrapper }
);
expect(handleSubmit).not.toHaveBeenCalled();
expect(dispatchEventSpy).not.toHaveBeenCalled();
});
it('auto-submits once recipe acceptance is confirmed', () => {
const handleSubmit = vi.fn();
const dispatchEventSpy = vi.spyOn(window, 'dispatchEvent');
const wrapper = ({ children }: PropsWithChildren) => (
<MemoryRouter initialEntries={['/pair?resumeSessionId=sess-1']}>{children}</MemoryRouter>
);
const { rerender } = renderHook(
({ canAutoSubmit }) =>
useAutoSubmit({
sessionId: 'sess-1',
session: makeSession(),
messages: [],
chatState: ChatState.Idle,
initialMessage,
canAutoSubmit,
handleSubmit,
}),
{
initialProps: { canAutoSubmit: false },
wrapper,
}
);
expect(handleSubmit).not.toHaveBeenCalled();
rerender({ canAutoSubmit: true });
expect(handleSubmit).toHaveBeenCalledTimes(1);
expect(handleSubmit).toHaveBeenCalledWith(initialMessage);
expect(dispatchEventSpy).toHaveBeenCalledTimes(1);
});
});
+7
View File
@@ -19,6 +19,7 @@ interface UseAutoSubmitProps {
messages: Message[];
chatState: ChatState;
initialMessage: UserInput | undefined;
canAutoSubmit?: boolean;
handleSubmit: (input: UserInput) => void;
}
@@ -32,6 +33,7 @@ export function useAutoSubmit({
messages,
chatState,
initialMessage,
canAutoSubmit = true,
handleSubmit,
}: UseAutoSubmitProps): UseAutoSubmitReturn {
const [searchParams] = useSearchParams();
@@ -65,6 +67,10 @@ export function useAutoSubmit({
return;
}
if (!canAutoSubmit) {
return;
}
if (chatState !== ChatState.Idle) {
return;
}
@@ -107,6 +113,7 @@ export function useAutoSubmit({
sessionId,
messages.length,
chatState,
canAutoSubmit,
clearInitialMessage,
hasUnfilledParameters,
]);