Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
100 commits
Select commit Hold shift + click to select a range
c073d73
Generated with Hive: Refactor workflow_editor retry to use backend PA…
tomsmith8 Apr 3, 2026
99289b7
Merge branch 'master' into feature/cmnippeci000kjs04szrp3l9s-backend-…
tomsmith8 Apr 3, 2026
eaf413d
Merge branch 'master' into feature/cmnippeci000kjs04szrp3l9s-backend-…
tomsmith8 Apr 3, 2026
d4fe690
Merge branch 'master' into feature/cmnippeci000kjs04szrp3l9s-backend-…
tomsmith8 Apr 3, 2026
68c5304
Merge branch 'master' into feature/cmnippeci000kjs04szrp3l9s-backend-…
tomsmith8 Apr 3, 2026
134d707
Merge branch 'master' into feature/cmnippeci000kjs04szrp3l9s-backend-…
tomsmith8 Apr 3, 2026
2da61fe
Merge branch 'master' into feature/cmnippeci000kjs04szrp3l9s-backend-…
tomsmith8 Apr 3, 2026
8a54782
Merge branch 'master' into feature/cmnippeci000kjs04szrp3l9s-backend-…
tomsmith8 Apr 3, 2026
6c88f16
Merge branch 'master' into feature/cmnippeci000kjs04szrp3l9s-backend-…
tomsmith8 Apr 4, 2026
3bef227
Merge branch 'master' into feature/cmnippeci000kjs04szrp3l9s-backend-…
tomsmith8 Apr 4, 2026
14bde38
Merge branch 'master' into feature/cmnippeci000kjs04szrp3l9s-backend-…
tomsmith8 Apr 4, 2026
04a02ac
Merge branch 'master' into feature/cmnippeci000kjs04szrp3l9s-backend-…
tomsmith8 Apr 5, 2026
ac8ed76
Merge branch 'master' into feature/cmnippeci000kjs04szrp3l9s-backend-…
tomsmith8 Apr 5, 2026
16f88d6
Merge branch 'master' into feature/cmnippeci000kjs04szrp3l9s-backend-…
tomsmith8 Apr 5, 2026
15665cf
Merge branch 'master' into feature/cmnippeci000kjs04szrp3l9s-backend-…
tomsmith8 Apr 6, 2026
a915894
Merge branch 'master' into feature/cmnippeci000kjs04szrp3l9s-backend-…
tomsmith8 Apr 6, 2026
421f6c3
Merge branch 'master' into feature/cmnippeci000kjs04szrp3l9s-backend-…
tomsmith8 Apr 6, 2026
b6c8840
Merge branch 'master' into feature/cmnippeci000kjs04szrp3l9s-backend-…
tomsmith8 Apr 6, 2026
b691164
Merge branch 'master' into feature/cmnippeci000kjs04szrp3l9s-backend-…
tomsmith8 Apr 6, 2026
d640369
Merge branch 'master' into feature/cmnippeci000kjs04szrp3l9s-backend-…
tomsmith8 Apr 6, 2026
6531f99
Merge branch 'master' into feature/cmnippeci000kjs04szrp3l9s-backend-…
tomsmith8 Apr 6, 2026
2d299b5
Merge branch 'master' into feature/cmnippeci000kjs04szrp3l9s-backend-…
tomsmith8 Apr 6, 2026
4de85d3
Merge branch 'master' into feature/cmnippeci000kjs04szrp3l9s-backend-…
tomsmith8 Apr 6, 2026
0d80440
Merge branch 'master' into feature/cmnippeci000kjs04szrp3l9s-backend-…
tomsmith8 Apr 6, 2026
bbe7de9
Merge branch 'master' into feature/cmnippeci000kjs04szrp3l9s-backend-…
tomsmith8 Apr 6, 2026
376b8d1
Merge branch 'master' into feature/cmnippeci000kjs04szrp3l9s-backend-…
tomsmith8 Apr 6, 2026
082f29f
Merge branch 'master' into feature/cmnippeci000kjs04szrp3l9s-backend-…
tomsmith8 Apr 7, 2026
862faaa
Merge branch 'master' into feature/cmnippeci000kjs04szrp3l9s-backend-…
tomsmith8 Apr 7, 2026
b7d0101
Merge branch 'master' into feature/cmnippeci000kjs04szrp3l9s-backend-…
tomsmith8 Apr 7, 2026
a533fd6
Merge branch 'master' into feature/cmnippeci000kjs04szrp3l9s-backend-…
tomsmith8 Apr 7, 2026
b56b569
Merge branch 'master' into feature/cmnippeci000kjs04szrp3l9s-backend-…
tomsmith8 Apr 7, 2026
6167844
Merge branch 'master' into feature/cmnippeci000kjs04szrp3l9s-backend-…
tomsmith8 Apr 7, 2026
b723d96
Merge branch 'master' into feature/cmnippeci000kjs04szrp3l9s-backend-…
tomsmith8 Apr 7, 2026
ea0e66a
Merge branch 'master' into feature/cmnippeci000kjs04szrp3l9s-backend-…
tomsmith8 Apr 7, 2026
5d2525c
Merge branch 'master' into feature/cmnippeci000kjs04szrp3l9s-backend-…
tomsmith8 Apr 7, 2026
e12e0bb
Merge branch 'master' into feature/cmnippeci000kjs04szrp3l9s-backend-…
tomsmith8 Apr 8, 2026
1326950
Merge branch 'master' into feature/cmnippeci000kjs04szrp3l9s-backend-…
tomsmith8 Apr 8, 2026
c179224
Merge branch 'master' into feature/cmnippeci000kjs04szrp3l9s-backend-…
tomsmith8 Apr 8, 2026
f831c9a
Merge branch 'master' into feature/cmnippeci000kjs04szrp3l9s-backend-…
tomsmith8 Apr 8, 2026
be8ea1a
Merge branch 'master' into feature/cmnippeci000kjs04szrp3l9s-backend-…
tomsmith8 Apr 8, 2026
fc76cba
Merge branch 'master' into feature/cmnippeci000kjs04szrp3l9s-backend-…
tomsmith8 Apr 8, 2026
42ea696
Merge branch 'master' into feature/cmnippeci000kjs04szrp3l9s-backend-…
tomsmith8 Apr 8, 2026
e0b150e
Merge branch 'master' into feature/cmnippeci000kjs04szrp3l9s-backend-…
tomsmith8 Apr 8, 2026
82d126c
Merge branch 'master' into feature/cmnippeci000kjs04szrp3l9s-backend-…
tomsmith8 Apr 9, 2026
262422b
Merge branch 'master' into feature/cmnippeci000kjs04szrp3l9s-backend-…
tomsmith8 Apr 9, 2026
c4bc7d3
Merge branch 'master' into feature/cmnippeci000kjs04szrp3l9s-backend-…
tomsmith8 Apr 9, 2026
f29db4b
Merge branch 'master' into feature/cmnippeci000kjs04szrp3l9s-backend-…
tomsmith8 Apr 9, 2026
04f5c00
Merge branch 'master' into feature/cmnippeci000kjs04szrp3l9s-backend-…
tomsmith8 Apr 9, 2026
25050c8
Merge branch 'master' into feature/cmnippeci000kjs04szrp3l9s-backend-…
tomsmith8 Apr 9, 2026
60ce993
Merge branch 'master' into feature/cmnippeci000kjs04szrp3l9s-backend-…
tomsmith8 Apr 9, 2026
905fa21
Merge branch 'master' into feature/cmnippeci000kjs04szrp3l9s-backend-…
tomsmith8 Apr 9, 2026
0ab28c4
Merge branch 'master' into feature/cmnippeci000kjs04szrp3l9s-backend-…
tomsmith8 Apr 9, 2026
044e24e
Merge branch 'master' into feature/cmnippeci000kjs04szrp3l9s-backend-…
tomsmith8 Apr 10, 2026
fd931da
Merge branch 'master' into feature/cmnippeci000kjs04szrp3l9s-backend-…
tomsmith8 Apr 10, 2026
21447be
Merge branch 'master' into feature/cmnippeci000kjs04szrp3l9s-backend-…
tomsmith8 Apr 10, 2026
507fc7b
Merge branch 'master' into feature/cmnippeci000kjs04szrp3l9s-backend-…
tomsmith8 Apr 10, 2026
9da1deb
Merge branch 'master' into feature/cmnippeci000kjs04szrp3l9s-backend-…
tomsmith8 Apr 10, 2026
bbc79a7
Merge branch 'master' into feature/cmnippeci000kjs04szrp3l9s-backend-…
tomsmith8 Apr 10, 2026
9aab2fb
Merge branch 'master' into feature/cmnippeci000kjs04szrp3l9s-backend-…
tomsmith8 Apr 10, 2026
6a034d5
Merge branch 'master' into feature/cmnippeci000kjs04szrp3l9s-backend-…
tomsmith8 Apr 10, 2026
e457bd7
Merge branch 'master' into feature/cmnippeci000kjs04szrp3l9s-backend-…
tomsmith8 Apr 11, 2026
00285af
Merge branch 'master' into feature/cmnippeci000kjs04szrp3l9s-backend-…
tomsmith8 Apr 12, 2026
d097fd5
Merge branch 'master' into feature/cmnippeci000kjs04szrp3l9s-backend-…
tomsmith8 Apr 12, 2026
d7cdf80
Merge branch 'master' into feature/cmnippeci000kjs04szrp3l9s-backend-…
tomsmith8 Apr 12, 2026
802d8d1
Merge branch 'master' into feature/cmnippeci000kjs04szrp3l9s-backend-…
tomsmith8 Apr 13, 2026
d45ec45
Merge branch 'master' into feature/cmnippeci000kjs04szrp3l9s-backend-…
tomsmith8 Apr 13, 2026
9bb472f
Merge branch 'master' into feature/cmnippeci000kjs04szrp3l9s-backend-…
tomsmith8 Apr 13, 2026
3bd13ea
Merge branch 'master' into feature/cmnippeci000kjs04szrp3l9s-backend-…
tomsmith8 Apr 13, 2026
6552c08
Merge branch 'master' into feature/cmnippeci000kjs04szrp3l9s-backend-…
tomsmith8 Apr 13, 2026
4a37748
Merge branch 'master' into feature/cmnippeci000kjs04szrp3l9s-backend-…
tomsmith8 Apr 13, 2026
d3e5c78
Merge branch 'master' into feature/cmnippeci000kjs04szrp3l9s-backend-…
tomsmith8 Apr 14, 2026
a783469
Merge branch 'master' into feature/cmnippeci000kjs04szrp3l9s-backend-…
tomsmith8 Apr 14, 2026
9b27e7c
Merge branch 'master' into feature/cmnippeci000kjs04szrp3l9s-backend-…
tomsmith8 Apr 14, 2026
a70365b
Merge branch 'master' into feature/cmnippeci000kjs04szrp3l9s-backend-…
tomsmith8 Apr 14, 2026
14e8272
Merge branch 'master' into feature/cmnippeci000kjs04szrp3l9s-backend-…
tomsmith8 Apr 14, 2026
2bf19f0
Merge branch 'master' into feature/cmnippeci000kjs04szrp3l9s-backend-…
tomsmith8 Apr 14, 2026
e7f492c
Merge branch 'master' into feature/cmnippeci000kjs04szrp3l9s-backend-…
tomsmith8 Apr 14, 2026
c0064af
Merge branch 'master' into feature/cmnippeci000kjs04szrp3l9s-backend-…
tomsmith8 Apr 14, 2026
07354b0
Merge branch 'master' into feature/cmnippeci000kjs04szrp3l9s-backend-…
tomsmith8 Apr 14, 2026
e9d0f18
Merge branch 'master' into feature/cmnippeci000kjs04szrp3l9s-backend-…
tomsmith8 Apr 14, 2026
108f09d
Merge branch 'master' into feature/cmnippeci000kjs04szrp3l9s-backend-…
tomsmith8 Apr 14, 2026
2396106
Merge branch 'master' into feature/cmnippeci000kjs04szrp3l9s-backend-…
tomsmith8 Apr 14, 2026
d28b2cd
Merge branch 'master' into feature/cmnippeci000kjs04szrp3l9s-backend-…
tomsmith8 Apr 14, 2026
a9eebe5
Merge branch 'master' into feature/cmnippeci000kjs04szrp3l9s-backend-…
tomsmith8 Apr 14, 2026
b41e41c
Merge branch 'master' into feature/cmnippeci000kjs04szrp3l9s-backend-…
tomsmith8 Apr 14, 2026
d385dfc
Merge branch 'master' into feature/cmnippeci000kjs04szrp3l9s-backend-…
tomsmith8 Apr 14, 2026
eabb5d5
Merge branch 'master' into feature/cmnippeci000kjs04szrp3l9s-backend-…
tomsmith8 Apr 14, 2026
318a89c
Merge branch 'master' into feature/cmnippeci000kjs04szrp3l9s-backend-…
tomsmith8 Apr 14, 2026
2d85337
Merge branch 'master' into feature/cmnippeci000kjs04szrp3l9s-backend-…
tomsmith8 Apr 14, 2026
efb0bac
Merge branch 'master' into feature/cmnippeci000kjs04szrp3l9s-backend-…
tomsmith8 Apr 15, 2026
c7c422f
Merge branch 'master' into feature/cmnippeci000kjs04szrp3l9s-backend-…
tomsmith8 Apr 15, 2026
746b040
Merge branch 'master' into feature/cmnippeci000kjs04szrp3l9s-backend-…
tomsmith8 Apr 15, 2026
657f242
Merge branch 'master' into feature/cmnippeci000kjs04szrp3l9s-backend-…
tomsmith8 Apr 15, 2026
beec653
Merge branch 'master' into feature/cmnippeci000kjs04szrp3l9s-backend-…
tomsmith8 Apr 15, 2026
6966dd6
Merge branch 'master' into feature/cmnippeci000kjs04szrp3l9s-backend-…
tomsmith8 Apr 16, 2026
5a7a3cd
Merge branch 'master' into feature/cmnippeci000kjs04szrp3l9s-backend-…
tomsmith8 Apr 16, 2026
1e24a7d
Merge branch 'master' into feature/cmnippeci000kjs04szrp3l9s-backend-…
tomsmith8 Apr 16, 2026
4ca86b3
Merge branch 'master' into feature/cmnippeci000kjs04szrp3l9s-backend-…
tomsmith8 Apr 16, 2026
3222994
Merge branch 'master' into feature/cmnippeci000kjs04szrp3l9s-backend-…
tomsmith8 Apr 16, 2026
2ea60b2
Merge branch 'master' into feature/cmnippeci000kjs04szrp3l9s-backend-…
tomsmith8 Apr 16, 2026
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
203 changes: 54 additions & 149 deletions src/__tests__/unit/pages/task-workflow-editor-fixes.test.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -690,101 +690,33 @@ describe('Task Page - Workflow Editor fixes', () => {
});

// ────────────────────────────────────────────────────────────────────────────
// handleRetry — workflow_editor mode branching
// handleRetry — unified PATCH path (all modes)
// ────────────────────────────────────────────────────────────────────────────
describe('handleRetry — workflow_editor mode', () => {
// Minimal ChatRole enum matching the real one
enum ChatRole {
USER = 'USER',
ASSISTANT = 'ASSISTANT',
}

const baseContext = {
workflowId: 'wf-123',
workflowName: 'My Workflow',
workflowRefId: 'ref-abc',
workflowVersionId: undefined as string | undefined,
};

const messages = [
{ role: ChatRole.ASSISTANT, message: 'Hello!' },
{ role: ChatRole.USER, message: 'Make it faster' },
];

/** Simulates the handleRetry logic extracted from page.tsx */
describe('handleRetry — unified PATCH path', () => {
/** Simulates the simplified handleRetry logic from page.tsx */
async function runHandleRetry({
taskMode,
currentTaskId,
isRetrying,
currentWorkflowContext,
workflowEditorWebhook,
fetchMock,
setIsRetrying,
setWorkflowStatus,
setIsChainVisible,
setWorkflowEditorWebhook,
setProjectId,
toastError,
}: {
taskMode: string;
currentTaskId: string;
currentTaskId: string | null;
isRetrying: boolean;
currentWorkflowContext: typeof baseContext | null;
workflowEditorWebhook: string | null;
fetchMock: ReturnType<typeof vi.fn>;
setIsRetrying: ReturnType<typeof vi.fn>;
setWorkflowStatus: ReturnType<typeof vi.fn>;
setIsChainVisible: ReturnType<typeof vi.fn>;
setWorkflowEditorWebhook: ReturnType<typeof vi.fn>;
setProjectId: ReturnType<typeof vi.fn>;
toastError: ReturnType<typeof vi.fn>;
}) {
if (!currentTaskId || isRetrying) return;
setIsRetrying(true);

try {
if (taskMode === 'workflow_editor' && currentWorkflowContext) {
const lastUserMessage = [...messages].reverse().find((m) => m.role === ChatRole.USER);
const messageText = lastUserMessage?.message ?? '';

if (!messageText || !currentWorkflowContext.workflowRefId) {
toastError('Cannot retry: missing workflow context.');
return;
}

const webhookToUse = workflowEditorWebhook || undefined;

const res = await fetchMock('/api/workflow-editor', {
method: 'POST',
headers: { 'Content-Type': 'application/json' },
body: JSON.stringify({
taskId: currentTaskId,
message: messageText,
workflowId: currentWorkflowContext.workflowId,
workflowName: currentWorkflowContext.workflowName,
workflowRefId: currentWorkflowContext.workflowRefId,
...(currentWorkflowContext.workflowVersionId && {
workflowVersionId: currentWorkflowContext.workflowVersionId,
}),
...(webhookToUse && { webhook: webhookToUse }),
}),
});

if (!res.ok) throw new Error('Retry failed');

const result = await res.json();
if (result.workflow?.webhook) setWorkflowEditorWebhook(result.workflow.webhook);
if (result.workflow?.project_id) setProjectId(result.workflow.project_id.toString());
setWorkflowStatus(WorkflowStatus.IN_PROGRESS);
setIsChainVisible(true);
} else {
const res = await fetchMock(`/api/tasks/${currentTaskId}`, {
method: 'PATCH',
headers: { 'Content-Type': 'application/json' },
body: JSON.stringify({ retryWorkflow: true }),
});
if (!res.ok) throw new Error('Retry failed');
}
const res = await fetchMock(`/api/tasks/${currentTaskId}`, {
method: 'PATCH',
headers: { 'Content-Type': 'application/json' },
body: JSON.stringify({ retryWorkflow: true }),
});
if (!res.ok) throw new Error('Retry failed');
} catch {
toastError('Failed to retry task. Please try again.');
} finally {
Expand All @@ -795,146 +727,119 @@ describe('Task Page - Workflow Editor fixes', () => {
function makeSetters() {
return {
setIsRetrying: vi.fn(),
setWorkflowStatus: vi.fn(),
setIsChainVisible: vi.fn(),
setWorkflowEditorWebhook: vi.fn(),
setProjectId: vi.fn(),
toastError: vi.fn(),
};
}

it('workflow_editor mode — success: calls POST /api/workflow-editor with correct payload', async () => {
const fetchMock = vi.fn().mockResolvedValue({
ok: true,
json: async () => ({ success: true, workflow: { webhook: 'wh', project_id: 99 } }),
});
it('workflow_editor mode: calls PATCH /api/tasks/[taskId] with { retryWorkflow: true }', async () => {
const fetchMock = vi.fn().mockResolvedValue({ ok: true });
const setters = makeSetters();

await runHandleRetry({
taskMode: 'workflow_editor',
currentTaskId: 'task-1',
isRetrying: false,
currentWorkflowContext: baseContext,
workflowEditorWebhook: null,
fetchMock,
...setters,
});

expect(fetchMock).toHaveBeenCalledWith(
'/api/workflow-editor',
expect.objectContaining({ method: 'POST' }),
'/api/tasks/task-1',
expect.objectContaining({ method: 'PATCH' }),
);
const body = JSON.parse(fetchMock.mock.calls[0][1].body);
expect(body.workflowId).toBe(baseContext.workflowId);
expect(body.workflowName).toBe(baseContext.workflowName);
expect(body.workflowRefId).toBe(baseContext.workflowRefId);
expect(body.message).toBe('Make it faster');
expect(setters.setWorkflowStatus).toHaveBeenCalledWith(WorkflowStatus.IN_PROGRESS);
expect(setters.setIsChainVisible).toHaveBeenCalledWith(true);
expect(setters.setWorkflowEditorWebhook).toHaveBeenCalledWith('wh');
expect(setters.setProjectId).toHaveBeenCalledWith('99');
expect(setters.setIsRetrying).toHaveBeenCalledWith(false);
expect(body).toEqual({ retryWorkflow: true });
});

it('workflow_editor mode — API error: calls toast.error and always calls setIsRetrying(false)', async () => {
const fetchMock = vi.fn().mockResolvedValue({ ok: false });
it('never calls POST /api/workflow-editor in any mode', async () => {
const fetchMock = vi.fn().mockResolvedValue({ ok: true });
const setters = makeSetters();

await runHandleRetry({
taskMode: 'workflow_editor',
currentTaskId: 'task-1',
isRetrying: false,
currentWorkflowContext: baseContext,
workflowEditorWebhook: null,
fetchMock,
...setters,
});

expect(setters.toastError).toHaveBeenCalledWith('Failed to retry task. Please try again.');
expect(setters.setIsRetrying).toHaveBeenCalledWith(false);
expect(fetchMock).not.toHaveBeenCalledWith('/api/workflow-editor', expect.anything());
});

it('workflow_editor mode — missing workflowRefId: shows early toast and never calls fetch', async () => {
const fetchMock = vi.fn();
it('non-workflow_editor mode: also calls PATCH /api/tasks/[taskId] with { retryWorkflow: true }', async () => {
const fetchMock = vi.fn().mockResolvedValue({ ok: true });
const setters = makeSetters();

await runHandleRetry({
taskMode: 'workflow_editor',
currentTaskId: 'task-1',
currentTaskId: 'task-42',
isRetrying: false,
currentWorkflowContext: { ...baseContext, workflowRefId: '' },
workflowEditorWebhook: null,
fetchMock,
...setters,
});

expect(setters.toastError).toHaveBeenCalledWith('Cannot retry: missing workflow context.');
expect(fetchMock).not.toHaveBeenCalled();
expect(fetchMock).toHaveBeenCalledWith(
'/api/tasks/task-42',
expect.objectContaining({ method: 'PATCH' }),
);
const body = JSON.parse(fetchMock.mock.calls[0][1].body);
expect(body).toEqual({ retryWorkflow: true });
});

it('non-workflow_editor mode: calls PATCH /api/tasks/[taskId] with { retryWorkflow: true }', async () => {
const fetchMock = vi.fn().mockResolvedValue({ ok: true });
it('API error: calls toast.error and always calls setIsRetrying(false)', async () => {
const fetchMock = vi.fn().mockResolvedValue({ ok: false });
const setters = makeSetters();

await runHandleRetry({
taskMode: 'live',
currentTaskId: 'task-42',
currentTaskId: 'task-1',
isRetrying: false,
currentWorkflowContext: null,
workflowEditorWebhook: null,
fetchMock,
...setters,
});

expect(fetchMock).toHaveBeenCalledWith(
'/api/tasks/task-42',
expect.objectContaining({ method: 'PATCH' }),
);
const body = JSON.parse(fetchMock.mock.calls[0][1].body);
expect(body).toEqual({ retryWorkflow: true });
expect(fetchMock).not.toHaveBeenCalledWith('/api/workflow-editor', expect.anything());
expect(setters.toastError).toHaveBeenCalledWith('Failed to retry task. Please try again.');
expect(setters.setIsRetrying).toHaveBeenCalledWith(false);
});

it('workflowEditorWebhook forwarded in payload when set', async () => {
const fetchMock = vi.fn().mockResolvedValue({
ok: true,
json: async () => ({ success: true, workflow: {} }),
});
it('bails early when isRetrying is true', async () => {
const fetchMock = vi.fn();
const setters = makeSetters();

await runHandleRetry({
taskMode: 'workflow_editor',
currentTaskId: 'task-1',
isRetrying: false,
currentWorkflowContext: baseContext,
workflowEditorWebhook: 'my-webhook-url',
isRetrying: true,
fetchMock,
...setters,
});

const body = JSON.parse(fetchMock.mock.calls[0][1].body);
expect(body.webhook).toBe('my-webhook-url');
expect(fetchMock).not.toHaveBeenCalled();
expect(setters.setIsRetrying).not.toHaveBeenCalled();
});

it('workflowVersionId forwarded in payload when set in context', async () => {
const fetchMock = vi.fn().mockResolvedValue({
ok: true,
json: async () => ({ success: true, workflow: {} }),
it('bails early when currentTaskId is null', async () => {
const fetchMock = vi.fn();
const setters = makeSetters();

await runHandleRetry({
currentTaskId: null,
isRetrying: false,
fetchMock,
...setters,
});

expect(fetchMock).not.toHaveBeenCalled();
expect(setters.setIsRetrying).not.toHaveBeenCalled();
});

it('always calls setIsRetrying(false) in finally — success path', async () => {
const fetchMock = vi.fn().mockResolvedValue({ ok: true });
const setters = makeSetters();

await runHandleRetry({
taskMode: 'workflow_editor',
currentTaskId: 'task-1',
isRetrying: false,
currentWorkflowContext: { ...baseContext, workflowVersionId: 'v99' },
workflowEditorWebhook: null,
fetchMock,
...setters,
});

const body = JSON.parse(fetchMock.mock.calls[0][1].body);
expect(body.workflowVersionId).toBe('v99');
expect(setters.setIsRetrying).toHaveBeenCalledWith(false);
});
});
});
Loading
Loading