Skip to content

Commit 4f771ff

Browse files
committed
fix(org): hold a declined composer message again once its text changes
The decline stayed armed for the exact text, so editing and retyping it while the lists were pending sent it with no hold or toast. Clear it as soon as the draft differs. The composer tests also stub toast.error: calling through with no provider mounted threw an unhandled rejection that failed the Vitest run.
1 parent 1bb3c4f commit 4f771ff

2 files changed

Lines changed: 23 additions & 1 deletion

File tree

‎apps/sim/app/o/[organizationId]/home/components/composer/composer.test.tsx‎

Lines changed: 22 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -116,7 +116,7 @@ let container: HTMLDivElement
116116
let queryClient: QueryClient
117117

118118
beforeEach(() => {
119-
vi.spyOn(toast, 'error')
119+
vi.spyOn(toast, 'error').mockReturnValue('')
120120
mocks.advanced = false
121121
mocks.workspacesLoading = false
122122
useMothershipEffortStore.getState().reset()
@@ -617,6 +617,27 @@ it('tells the viewer when the lists never land, keeps the message, and sends pla
617617
expect(mocks.submit.mock.lastCall?.[0]).toBe('/review this')
618618
})
619619

620+
it('a declined message edited and typed again waits and warns again', async () => {
621+
const firstExpiry = holdThenExpire()
622+
mocks.skillQuery.mockReturnValue(new Promise(() => {}))
623+
await render(true, '', 'agent')
624+
const input = required<HTMLTextAreaElement>('[aria-label="Ask Sim"]')
625+
const send = () => required<HTMLButtonElement>('button[aria-label="Send"]')
626+
await act(async () => typeInto(input, '/review this'))
627+
await act(async () => send().click())
628+
await act(async () => firstExpiry.abort())
629+
expect(toast.error).toHaveBeenCalledOnce()
630+
await act(async () => typeInto(input, '/review this now'))
631+
await act(async () => typeInto(input, '/review this'))
632+
const secondExpiry = holdThenExpire()
633+
await act(async () => send().click())
634+
expect(mocks.submit).not.toHaveBeenCalled()
635+
expect(input.closest('[aria-busy="true"]')).not.toBeNull()
636+
await act(async () => secondExpiry.abort())
637+
expect(toast.error).toHaveBeenCalledTimes(2)
638+
expect(mocks.submit).not.toHaveBeenCalled()
639+
})
640+
620641
it('a list that fails while the send waits tells the viewer the same way', async () => {
621642
let failSkills: (error: Error) => void = () => {}
622643
mocks.skillQuery.mockReturnValue(

‎apps/sim/app/o/[organizationId]/home/components/composer/use-composer.ts‎

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -110,6 +110,7 @@ export function useComposer({
110110
const [heldSend, setHeldSend] = useState<HeldSend | null>(null)
111111
/** The text the viewer was told would go out unchipped if they sent it again. */
112112
const [declinedWaitText, setDeclinedWaitText] = useState<string | null>(null)
113+
if (declinedWaitText !== null && value !== declinedWaitText) setDeclinedWaitText(null)
113114
const skillsWanted = resourceIntent || heldSend !== null || SLASH_TOKEN.test(value)
114115
const skillQueries = useQueries({
115116
queries: workspaces.map((workspace) => ({

0 commit comments

Comments
 (0)