diff --git a/src/__tests__/unit/api/api-chat-message.test.ts b/src/__tests__/unit/api/api-chat-message.test.ts index 207bab5548..c3069f61d5 100644 --- a/src/__tests__/unit/api/api-chat-message.test.ts +++ b/src/__tests__/unit/api/api-chat-message.test.ts @@ -582,7 +582,8 @@ describe("POST /api/chat/message", () => { expect(fetchCall).toBeTruthy(); - const body = JSON.parse(fetchCall![1]!.body as string); + const _rawBody = JSON.parse(fetchCall![1]!.body as string); + const body = (_rawBody && typeof _rawBody === "object" && "project" in _rawBody) ? _rawBody.project : _rawBody; expect(body.workflow_params.set_var.attributes.vars).toMatchObject({ alias: "testuser", username: "testuser", @@ -616,7 +617,8 @@ describe("POST /api/chat/message", () => { const fetchCall = mockFetch.mock.calls.find((call) => call[0].toString().includes("stakwork")); - const body = JSON.parse(fetchCall![1]!.body as string); + const _rawBody = JSON.parse(fetchCall![1]!.body as string); + const body = (_rawBody && typeof _rawBody === "object" && "project" in _rawBody) ? _rawBody.project : _rawBody; expect(body.workflow_id).toBe(parseInt(expectedWorkflowId)); }); }); diff --git a/src/__tests__/unit/api/chat/call-stakwork.test.ts b/src/__tests__/unit/api/chat/call-stakwork.test.ts index 72b7db14d8..e063b4993c 100644 --- a/src/__tests__/unit/api/chat/call-stakwork.test.ts +++ b/src/__tests__/unit/api/chat/call-stakwork.test.ts @@ -206,13 +206,15 @@ const TestHelpers = { ); const fetchCall = mockFetch.mock.calls[0]; - const payload = JSON.parse(fetchCall[1]?.body as string); + const _rawPayload = JSON.parse(fetchCall[1]?.body as string); + const payload = (_rawPayload && typeof _rawPayload === 'object' && 'project' in _rawPayload) ? _rawPayload.project : _rawPayload; expect(payload.workflow_id).toBe(workflowId); }, expectFetchCalledWithVarsContaining: (expectedVars: Record) => { const fetchCall = mockFetch.mock.calls[0]; - const payload = JSON.parse(fetchCall[1]?.body as string); + const _rawPayload = JSON.parse(fetchCall[1]?.body as string); + const payload = (_rawPayload && typeof _rawPayload === 'object' && 'project' in _rawPayload) ? _rawPayload.project : _rawPayload; const vars = payload.workflow_params.set_var.attributes.vars; Object.entries(expectedVars).forEach(([key, value]) => { @@ -500,7 +502,8 @@ describe("callStakwork Function Unit Tests", () => { await POST(request); const fetchCall = mockFetch.mock.calls[0]; - const payload = JSON.parse(fetchCall[1]?.body as string); + const _rawPayload = JSON.parse(fetchCall[1]?.body as string); + const payload = (_rawPayload && typeof _rawPayload === 'object' && 'project' in _rawPayload) ? _rawPayload.project : _rawPayload; expect(payload.webhook_url).toBe("http://localhost:3000/api/stakwork/webhook?task_id=test-task-id"); }); @@ -719,7 +722,8 @@ describe("callStakwork Function Unit Tests", () => { await POST(request); const fetchCall = mockFetch.mock.calls[0]; - const payload = JSON.parse(fetchCall[1]?.body as string); + const _rawPayload = JSON.parse(fetchCall[1]?.body as string); + const payload = (_rawPayload && typeof _rawPayload === 'object' && 'project' in _rawPayload) ? _rawPayload.project : _rawPayload; expect(payload).toMatchObject({ name: expect.stringMatching(/^hive-task-/), @@ -745,7 +749,8 @@ describe("callStakwork Function Unit Tests", () => { await POST(request); const fetchCall = mockFetch.mock.calls[0]; - const payload = JSON.parse(fetchCall[1]?.body as string); + const _rawPayload = JSON.parse(fetchCall[1]?.body as string); + const payload = (_rawPayload && typeof _rawPayload === 'object' && 'project' in _rawPayload) ? _rawPayload.project : _rawPayload; expect(payload.name).toBe("hive-task-test-task-id"); }); @@ -757,7 +762,8 @@ describe("callStakwork Function Unit Tests", () => { await POST(request); const fetchCall = mockFetch.mock.calls[0]; - const payload = JSON.parse(fetchCall[1]?.body as string); + const _rawPayload = JSON.parse(fetchCall[1]?.body as string); + const payload = (_rawPayload && typeof _rawPayload === 'object' && 'project' in _rawPayload) ? _rawPayload.project : _rawPayload; expect(payload.workflow_params).toHaveProperty("set_var"); expect(payload.workflow_params.set_var).toHaveProperty("attributes"); diff --git a/src/__tests__/unit/api/chat/message/call-stakwork.test.ts b/src/__tests__/unit/api/chat/message/call-stakwork.test.ts index d7d57f23c8..b9c1119f50 100644 --- a/src/__tests__/unit/api/chat/message/call-stakwork.test.ts +++ b/src/__tests__/unit/api/chat/message/call-stakwork.test.ts @@ -588,7 +588,8 @@ describe("callStakwork Function - Chat Message Processing", () => { // Verify context tags were passed to Stakwork API const fetchCall = mockFetch.mock.calls[0]; - const requestBody = JSON.parse(fetchCall[1].body as string); + const _rawRequestBody = JSON.parse(fetchCall[1].body as string); + const requestBody = (_rawRequestBody && typeof _rawRequestBody === 'object' && 'project' in _rawRequestBody) ? _rawRequestBody.project : _rawRequestBody; const vars = requestBody.workflow_params.set_var.attributes.vars; expect(vars.contextTags).toEqual(contextTags); @@ -1027,7 +1028,8 @@ describe("callStakwork Function - Chat Message Processing", () => { await POST(request); const fetchCall = mockFetch.mock.calls[0]; - const requestBody = JSON.parse(fetchCall[1].body as string); + const _rawRequestBody = JSON.parse(fetchCall[1].body as string); + const requestBody = (_rawRequestBody && typeof _rawRequestBody === 'object' && 'project' in _rawRequestBody) ? _rawRequestBody.project : _rawRequestBody; expect(requestBody.workflow_id).toBe(101); // First ID from "101,102,103" }); @@ -1048,7 +1050,8 @@ describe("callStakwork Function - Chat Message Processing", () => { await POST(request); const fetchCall = mockFetch.mock.calls[0]; - const requestBody = JSON.parse(fetchCall[1].body as string); + const _rawRequestBody = JSON.parse(fetchCall[1].body as string); + const requestBody = (_rawRequestBody && typeof _rawRequestBody === 'object' && 'project' in _rawRequestBody) ? _rawRequestBody.project : _rawRequestBody; expect(requestBody.workflow_id).toBe(103); // Third ID from "101,102,103" }); @@ -1069,7 +1072,8 @@ describe("callStakwork Function - Chat Message Processing", () => { await POST(request); const fetchCall = mockFetch.mock.calls[0]; - const requestBody = JSON.parse(fetchCall[1].body as string); + const _rawRequestBody = JSON.parse(fetchCall[1].body as string); + const requestBody = (_rawRequestBody && typeof _rawRequestBody === 'object' && 'project' in _rawRequestBody) ? _rawRequestBody.project : _rawRequestBody; expect(requestBody.workflow_id).toBe(102); // Second ID from "101,102,103" }); @@ -1239,7 +1243,8 @@ describe("callStakwork Function - Chat Message Processing", () => { await POST(request); const fetchCall = mockFetch.mock.calls[0]; - const requestBody = JSON.parse(fetchCall[1].body as string); + const _rawRequestBody = JSON.parse(fetchCall[1].body as string); + const requestBody = (_rawRequestBody && typeof _rawRequestBody === 'object' && 'project' in _rawRequestBody) ? _rawRequestBody.project : _rawRequestBody; const vars = requestBody.workflow_params.set_var.attributes.vars; expect(vars).toMatchObject({ @@ -1309,7 +1314,8 @@ describe("callStakwork Function - Chat Message Processing", () => { await POST(request); const fetchCall = mockFetch.mock.calls[0]; - const requestBody = JSON.parse(fetchCall[1].body as string); + const _rawRequestBody = JSON.parse(fetchCall[1].body as string); + const requestBody = (_rawRequestBody && typeof _rawRequestBody === 'object' && 'project' in _rawRequestBody) ? _rawRequestBody.project : _rawRequestBody; expect(requestBody.webhook_url).toBe( `http://localhost:3000/api/stakwork/webhook?task_id=${mockTaskId}` @@ -1386,7 +1392,8 @@ describe("callStakwork Function - Chat Message Processing", () => { expect(mockS3Service.generatePresignedDownloadUrl).toHaveBeenCalledWith("uploads/file2.jpg"); const fetchCall = mockFetch.mock.calls[0]; - const requestBody = JSON.parse(fetchCall[1].body as string); + const _rawRequestBody = JSON.parse(fetchCall[1].body as string); + const requestBody = (_rawRequestBody && typeof _rawRequestBody === 'object' && 'project' in _rawRequestBody) ? _rawRequestBody.project : _rawRequestBody; const vars = requestBody.workflow_params.set_var.attributes.vars; expect(vars.attachments).toEqual([ diff --git a/src/__tests__/unit/api/chat/message/route.test.ts b/src/__tests__/unit/api/chat/message/route.test.ts index 53186f4a3f..dec6a43640 100644 --- a/src/__tests__/unit/api/chat/message/route.test.ts +++ b/src/__tests__/unit/api/chat/message/route.test.ts @@ -709,7 +709,8 @@ describe("POST /api/chat/message - callStakwork Unit Tests", () => { await POST(request); const fetchCall = mockFetch.mock.calls[0]; - const requestBody = JSON.parse(fetchCall[1].body as string); + const _rawRequestBody = JSON.parse(fetchCall[1].body as string); + const requestBody = (_rawRequestBody && typeof _rawRequestBody === 'object' && 'project' in _rawRequestBody) ? _rawRequestBody.project : _rawRequestBody; expect(requestBody.workflow_id).toBe(101); // First workflow ID }); @@ -728,7 +729,8 @@ describe("POST /api/chat/message - callStakwork Unit Tests", () => { await POST(request); const fetchCall = mockFetch.mock.calls[0]; - const requestBody = JSON.parse(fetchCall[1].body as string); + const _rawRequestBody = JSON.parse(fetchCall[1].body as string); + const requestBody = (_rawRequestBody && typeof _rawRequestBody === 'object' && 'project' in _rawRequestBody) ? _rawRequestBody.project : _rawRequestBody; expect(requestBody.workflow_id).toBe(103); // Third workflow ID }); @@ -747,7 +749,8 @@ describe("POST /api/chat/message - callStakwork Unit Tests", () => { await POST(request); const fetchCall = mockFetch.mock.calls[0]; - const requestBody = JSON.parse(fetchCall[1].body as string); + const _rawRequestBody = JSON.parse(fetchCall[1].body as string); + const requestBody = (_rawRequestBody && typeof _rawRequestBody === 'object' && 'project' in _rawRequestBody) ? _rawRequestBody.project : _rawRequestBody; expect(requestBody.workflow_id).toBe(103); // Third workflow ID }); @@ -766,7 +769,8 @@ describe("POST /api/chat/message - callStakwork Unit Tests", () => { await POST(request); const fetchCall = mockFetch.mock.calls[0]; - const requestBody = JSON.parse(fetchCall[1].body as string); + const _rawRequestBody = JSON.parse(fetchCall[1].body as string); + const requestBody = (_rawRequestBody && typeof _rawRequestBody === 'object' && 'project' in _rawRequestBody) ? _rawRequestBody.project : _rawRequestBody; expect(requestBody.workflow_id).toBe(102); // Second workflow ID (default) }); @@ -784,7 +788,8 @@ describe("POST /api/chat/message - callStakwork Unit Tests", () => { await POST(request); const fetchCall = mockFetch.mock.calls[0]; - const requestBody = JSON.parse(fetchCall[1].body as string); + const _rawRequestBody = JSON.parse(fetchCall[1].body as string); + const requestBody = (_rawRequestBody && typeof _rawRequestBody === 'object' && 'project' in _rawRequestBody) ? _rawRequestBody.project : _rawRequestBody; expect(requestBody.workflow_id).toBe(102); // Second workflow ID (default) }); @@ -850,7 +855,8 @@ describe("POST /api/chat/message - callStakwork Unit Tests", () => { await POST(request); const fetchCall = mockFetch.mock.calls[0]; - const requestBody = JSON.parse(fetchCall[1].body as string); + const _rawRequestBody = JSON.parse(fetchCall[1].body as string); + const requestBody = (_rawRequestBody && typeof _rawRequestBody === 'object' && 'project' in _rawRequestBody) ? _rawRequestBody.project : _rawRequestBody; const vars = requestBody.workflow_params.set_var.attributes.vars; expect(vars).toMatchObject({ @@ -919,7 +925,8 @@ describe("POST /api/chat/message - callStakwork Unit Tests", () => { expect(s3Service.generatePresignedDownloadUrl).toHaveBeenCalledWith("uploads/test/file.pdf"); const fetchCall = mockFetch.mock.calls[0]; - const requestBody = JSON.parse(fetchCall[1].body as string); + const _rawRequestBody = JSON.parse(fetchCall[1].body as string); + const requestBody = (_rawRequestBody && typeof _rawRequestBody === 'object' && 'project' in _rawRequestBody) ? _rawRequestBody.project : _rawRequestBody; const vars = requestBody.workflow_params.set_var.attributes.vars; expect(vars.attachments).toEqual(["https://s3.test.com/presigned-url"]); @@ -948,7 +955,8 @@ describe("POST /api/chat/message - callStakwork Unit Tests", () => { expect(vi.mocked(getBaseUrl)).toHaveBeenCalledWith(); const fetchCall = mockFetch.mock.calls[0]; - const requestBody = JSON.parse(fetchCall[1].body as string); + const _rawRequestBody = JSON.parse(fetchCall[1].body as string); + const requestBody = (_rawRequestBody && typeof _rawRequestBody === 'object' && 'project' in _rawRequestBody) ? _rawRequestBody.project : _rawRequestBody; const vars = requestBody.workflow_params.set_var.attributes.vars; expect(vars.webhookUrl).toBe("https://production.example.com/api/chat/response"); @@ -969,7 +977,8 @@ describe("POST /api/chat/message - callStakwork Unit Tests", () => { await POST(request); const fetchCall = mockFetch.mock.calls[0]; - const requestBody = JSON.parse(fetchCall[1].body as string); + const _rawRequestBody = JSON.parse(fetchCall[1].body as string); + const requestBody = (_rawRequestBody && typeof _rawRequestBody === 'object' && 'project' in _rawRequestBody) ? _rawRequestBody.project : _rawRequestBody; const vars = requestBody.workflow_params.set_var.attributes.vars; expect(vars.webhookUrl).toBe("https://custom-webhook.example.com"); @@ -990,7 +999,8 @@ describe("POST /api/chat/message - callStakwork Unit Tests", () => { await POST(request); const fetchCall = mockFetch.mock.calls[0]; - const requestBody = JSON.parse(fetchCall[1].body as string); + const _rawRequestBody = JSON.parse(fetchCall[1].body as string); + const requestBody = (_rawRequestBody && typeof _rawRequestBody === 'object' && 'project' in _rawRequestBody) ? _rawRequestBody.project : _rawRequestBody; expect(requestBody.webhook_url).toBe(`http://localhost:3000/api/stakwork/webhook?task_id=${mockTaskId}`); }); @@ -1012,7 +1022,8 @@ describe("POST /api/chat/message - callStakwork Unit Tests", () => { expect(vi.mocked(transformSwarmUrlToRepo2Graph)).toHaveBeenCalledWith("https://test-swarm.com/api"); const fetchCall = mockFetch.mock.calls[0]; - const requestBody = JSON.parse(fetchCall[1].body as string); + const _rawRequestBody = JSON.parse(fetchCall[1].body as string); + const requestBody = (_rawRequestBody && typeof _rawRequestBody === 'object' && 'project' in _rawRequestBody) ? _rawRequestBody.project : _rawRequestBody; const vars = requestBody.workflow_params.set_var.attributes.vars; expect(vars.repo2graph_url).toBe("https://custom-graph.com:3355"); @@ -1404,7 +1415,8 @@ describe("POST /api/chat/message - callStakwork Unit Tests", () => { await POST(request); const fetchCall = mockFetch.mock.calls[0]; - const requestBody = JSON.parse(fetchCall[1].body as string); + const _rawRequestBody = JSON.parse(fetchCall[1].body as string); + const requestBody = (_rawRequestBody && typeof _rawRequestBody === 'object' && 'project' in _rawRequestBody) ? _rawRequestBody.project : _rawRequestBody; const vars = requestBody.workflow_params.set_var.attributes.vars; expect(vars.runBuild).toBe(false); @@ -1427,7 +1439,8 @@ describe("POST /api/chat/message - callStakwork Unit Tests", () => { await POST(request); const fetchCall = mockFetch.mock.calls[0]; - const requestBody = JSON.parse(fetchCall[1].body as string); + const _rawRequestBody = JSON.parse(fetchCall[1].body as string); + const requestBody = (_rawRequestBody && typeof _rawRequestBody === 'object' && 'project' in _rawRequestBody) ? _rawRequestBody.project : _rawRequestBody; const vars = requestBody.workflow_params.set_var.attributes.vars; expect(vars.runTestSuite).toBe(false); @@ -1450,7 +1463,8 @@ describe("POST /api/chat/message - callStakwork Unit Tests", () => { await POST(request); const fetchCall = mockFetch.mock.calls[0]; - const requestBody = JSON.parse(fetchCall[1].body as string); + const _rawRequestBody = JSON.parse(fetchCall[1].body as string); + const requestBody = (_rawRequestBody && typeof _rawRequestBody === 'object' && 'project' in _rawRequestBody) ? _rawRequestBody.project : _rawRequestBody; const vars = requestBody.workflow_params.set_var.attributes.vars; expect(vars.autoMergePr).toBe(true); @@ -1473,7 +1487,8 @@ describe("POST /api/chat/message - callStakwork Unit Tests", () => { await POST(request); const fetchCall = mockFetch.mock.calls[0]; - const requestBody = JSON.parse(fetchCall[1].body as string); + const _rawRequestBody = JSON.parse(fetchCall[1].body as string); + const requestBody = (_rawRequestBody && typeof _rawRequestBody === 'object' && 'project' in _rawRequestBody) ? _rawRequestBody.project : _rawRequestBody; const vars = requestBody.workflow_params.set_var.attributes.vars; expect(vars.runBuild).toBe(false); @@ -1557,7 +1572,8 @@ describe("POST /api/chat/message - callStakwork Unit Tests", () => { ]); const fetchCall = mockFetch.mock.calls[0]; - const requestBody = JSON.parse(fetchCall[1].body as string); + const _rawRequestBody = JSON.parse(fetchCall[1].body as string); + const requestBody = (_rawRequestBody && typeof _rawRequestBody === 'object' && 'project' in _rawRequestBody) ? _rawRequestBody.project : _rawRequestBody; const vars = requestBody.workflow_params.set_var.attributes.vars; expect(vars.contextTags).toEqual([ @@ -1679,7 +1695,8 @@ describe("POST /api/chat/message - callStakwork Unit Tests", () => { expect(s3Service.generatePresignedDownloadUrl).toHaveBeenCalledWith("uploads/file2.jpg"); const fetchCall = mockFetch.mock.calls[0]; - const requestBody = JSON.parse(fetchCall[1].body as string); + const _rawRequestBody = JSON.parse(fetchCall[1].body as string); + const requestBody = (_rawRequestBody && typeof _rawRequestBody === 'object' && 'project' in _rawRequestBody) ? _rawRequestBody.project : _rawRequestBody; const vars = requestBody.workflow_params.set_var.attributes.vars; expect(vars.attachments).toEqual(["https://s3.test.com/file1.pdf", "https://s3.test.com/file2.jpg"]); diff --git a/src/__tests__/unit/services/call-stakwork-api.test.ts b/src/__tests__/unit/services/call-stakwork-api.test.ts index d6d1128084..01531fd8f0 100644 --- a/src/__tests__/unit/services/call-stakwork-api.test.ts +++ b/src/__tests__/unit/services/call-stakwork-api.test.ts @@ -96,7 +96,8 @@ describe("callStakworkAPI", () => { await callStakworkAPI(createTestParams()); const fetchCall = mockFetch.mock.calls[0]; - const body = JSON.parse(fetchCall[1]?.body as string); + const _rawBody = JSON.parse(fetchCall[1]?.body as string); + const body = (_rawBody && typeof _rawBody === 'object' && 'project' in _rawBody) ? _rawBody.project : _rawBody; expect(body.workflow_params.set_var.attributes.vars.tokenReference).toBe( "{{HIVE_STAGING}}" @@ -112,7 +113,8 @@ describe("callStakworkAPI", () => { await callStakworkAPI(createTestParams()); const fetchCall = mockFetch.mock.calls[0]; - const body = JSON.parse(fetchCall[1]?.body as string); + const _rawBody = JSON.parse(fetchCall[1]?.body as string); + const body = (_rawBody && typeof _rawBody === 'object' && 'project' in _rawBody) ? _rawBody.project : _rawBody; expect(body.workflow_params.set_var.attributes.vars.tokenReference).toBe( "{{HIVE_PROD}}" @@ -271,7 +273,8 @@ describe("callStakworkAPI", () => { await callStakworkAPI(params); const fetchCall = mockFetch.mock.calls[0]; - const body = JSON.parse(fetchCall[1]?.body as string); + const _rawBody = JSON.parse(fetchCall[1]?.body as string); + const body = (_rawBody && typeof _rawBody === 'object' && 'project' in _rawBody) ? _rawBody.project : _rawBody; expect(body.workflow_params.set_var.attributes.vars).toMatchObject({ message: "Test message content", @@ -295,7 +298,8 @@ describe("callStakworkAPI", () => { await callStakworkAPI(createTestParams()); const fetchCall = mockFetch.mock.calls[0]; - const body = JSON.parse(fetchCall[1]?.body as string); + const _rawBody = JSON.parse(fetchCall[1]?.body as string); + const body = (_rawBody && typeof _rawBody === 'object' && 'project' in _rawBody) ? _rawBody.project : _rawBody; expect(body).toHaveProperty("name", "hive-task-test-task-123"); expect(body).toHaveProperty("workflow_id"); @@ -311,7 +315,8 @@ describe("callStakworkAPI", () => { ); const fetchCall = mockFetch.mock.calls[0]; - const body = JSON.parse(fetchCall[1]?.body as string); + const _rawBody = JSON.parse(fetchCall[1]?.body as string); + const body = (_rawBody && typeof _rawBody === 'object' && 'project' in _rawBody) ? _rawBody.project : _rawBody; expect(body.workflow_params.set_var.attributes.vars.taskSource).toBe( "codebase_recommendation" @@ -548,7 +553,8 @@ describe("callStakworkAPI", () => { await callStakworkAPI(createTestParams({ mode: "plan_mode" })); const fetchCall = mockFetch.mock.calls[0]; - const body = JSON.parse(fetchCall[1]?.body as string); + const _rawBody = JSON.parse(fetchCall[1]?.body as string); + const body = (_rawBody && typeof _rawBody === 'object' && 'project' in _rawBody) ? _rawBody.project : _rawBody; expect(body.workflow_params.set_var.attributes.vars.model).toBe( "claude-3-5-sonnet" @@ -571,7 +577,8 @@ describe("callStakworkAPI", () => { await callStakworkAPI(createTestParams({ mode: "plan_mode" })); const fetchCall = mockFetch.mock.calls[0]; - const body = JSON.parse(fetchCall[1]?.body as string); + const _rawBody = JSON.parse(fetchCall[1]?.body as string); + const body = (_rawBody && typeof _rawBody === 'object' && 'project' in _rawBody) ? _rawBody.project : _rawBody; expect(body.workflow_params.set_var.attributes.vars.model).toBeUndefined(); @@ -589,7 +596,8 @@ describe("callStakworkAPI", () => { await callStakworkAPI(createTestParams({ contextTags: [] })); const fetchCall = mockFetch.mock.calls[0]; - const body = JSON.parse(fetchCall[1]?.body as string); + const _rawBody = JSON.parse(fetchCall[1]?.body as string); + const body = (_rawBody && typeof _rawBody === 'object' && 'project' in _rawBody) ? _rawBody.project : _rawBody; expect(body.workflow_params.set_var.attributes.vars.contextTags).toEqual( [] @@ -602,7 +610,8 @@ describe("callStakworkAPI", () => { await callStakworkAPI(createTestParams({ attachments: [] })); const fetchCall = mockFetch.mock.calls[0]; - const body = JSON.parse(fetchCall[1]?.body as string); + const _rawBody = JSON.parse(fetchCall[1]?.body as string); + const body = (_rawBody && typeof _rawBody === 'object' && 'project' in _rawBody) ? _rawBody.project : _rawBody; expect(body.workflow_params.set_var.attributes.vars.attachments).toEqual( [] @@ -615,7 +624,8 @@ describe("callStakworkAPI", () => { await callStakworkAPI(createTestParams({ userName: null })); const fetchCall = mockFetch.mock.calls[0]; - const body = JSON.parse(fetchCall[1]?.body as string); + const _rawBody = JSON.parse(fetchCall[1]?.body as string); + const body = (_rawBody && typeof _rawBody === 'object' && 'project' in _rawBody) ? _rawBody.project : _rawBody; expect(body.workflow_params.set_var.attributes.vars.alias).toBeNull(); expect(body.workflow_params.set_var.attributes.vars.username).toBeNull(); @@ -627,7 +637,8 @@ describe("callStakworkAPI", () => { await callStakworkAPI(createTestParams({ accessToken: null })); const fetchCall = mockFetch.mock.calls[0]; - const body = JSON.parse(fetchCall[1]?.body as string); + const _rawBody = JSON.parse(fetchCall[1]?.body as string); + const body = (_rawBody && typeof _rawBody === 'object' && 'project' in _rawBody) ? _rawBody.project : _rawBody; expect(body.workflow_params.set_var.attributes.vars.accessToken).toBeNull(); }); @@ -638,7 +649,8 @@ describe("callStakworkAPI", () => { await callStakworkAPI(createTestParams({ swarmSecretAlias: null })); const fetchCall = mockFetch.mock.calls[0]; - const body = JSON.parse(fetchCall[1]?.body as string); + const _rawBody = JSON.parse(fetchCall[1]?.body as string); + const body = (_rawBody && typeof _rawBody === 'object' && 'project' in _rawBody) ? _rawBody.project : _rawBody; expect( body.workflow_params.set_var.attributes.vars.swarmSecretAlias @@ -651,7 +663,8 @@ describe("callStakworkAPI", () => { await callStakworkAPI(createTestParams({ poolName: null })); const fetchCall = mockFetch.mock.calls[0]; - const body = JSON.parse(fetchCall[1]?.body as string); + const _rawBody = JSON.parse(fetchCall[1]?.body as string); + const body = (_rawBody && typeof _rawBody === 'object' && 'project' in _rawBody) ? _rawBody.project : _rawBody; expect(body.workflow_params.set_var.attributes.vars.poolName).toBeNull(); }); diff --git a/src/__tests__/unit/services/task-workflow-createChatMessageAndTriggerStakwork.test.ts b/src/__tests__/unit/services/task-workflow-createChatMessageAndTriggerStakwork.test.ts index 9e88d415ed..870b315c21 100644 --- a/src/__tests__/unit/services/task-workflow-createChatMessageAndTriggerStakwork.test.ts +++ b/src/__tests__/unit/services/task-workflow-createChatMessageAndTriggerStakwork.test.ts @@ -321,7 +321,8 @@ describe("createChatMessageAndTriggerStakwork", () => { ); const call = mockFetch.mock.calls[0]; - const body = JSON.parse(call[1].body); + const _rawBody = JSON.parse(call[1].body); + const body = (_rawBody && typeof _rawBody === 'object' && 'project' in _rawBody) ? _rawBody.project : _rawBody; expect(body.workflow_id).toBeDefined(); expect(body.webhook_url).toContain("/api/stakwork/webhook"); }); @@ -356,7 +357,8 @@ describe("createChatMessageAndTriggerStakwork", () => { // Assert const call = mockFetch.mock.calls[0]; - const body = JSON.parse(call[1].body); + const _rawBody = JSON.parse(call[1].body); + const body = (_rawBody && typeof _rawBody === 'object' && 'project' in _rawBody) ? _rawBody.project : _rawBody; expect(body.workflow_id).toBeDefined(); if (mode === "live") { @@ -599,7 +601,8 @@ describe("createChatMessageAndTriggerStakwork", () => { // Assert - Feature context should be included in the Stakwork API call expect(mockFetch).toHaveBeenCalled(); const call = mockFetch.mock.calls[0]; - const body = JSON.parse(call[1].body); + const _rawBody = JSON.parse(call[1].body); + const body = (_rawBody && typeof _rawBody === 'object' && 'project' in _rawBody) ? _rawBody.project : _rawBody; expect(body.workflow_params.set_var.attributes.vars.featureContext).toEqual(featureContext); }); }); diff --git a/src/__tests__/unit/services/task-workflow.test.ts b/src/__tests__/unit/services/task-workflow.test.ts index 52e0337c53..c6e18cce07 100644 --- a/src/__tests__/unit/services/task-workflow.test.ts +++ b/src/__tests__/unit/services/task-workflow.test.ts @@ -297,7 +297,8 @@ const TestHelpers = { expectStakworkCalledWithVars: (expectedVars: Record) => { const fetchCall = mockFetch.mock.calls[0]; - const payload = JSON.parse(fetchCall[1]?.body as string); + const _rawPayload = JSON.parse(fetchCall[1]?.body as string); + const payload = (_rawPayload && typeof _rawPayload === 'object' && 'project' in _rawPayload) ? _rawPayload.project : _rawPayload; const vars = payload.workflow_params.set_var.attributes.vars; Object.entries(expectedVars).forEach(([key, value]) => { @@ -311,7 +312,8 @@ const TestHelpers = { vars?: Record; }) => { const fetchCall = mockFetch.mock.calls[0]; - const payload = JSON.parse(fetchCall[1]?.body as string); + const _rawPayload = JSON.parse(fetchCall[1]?.body as string); + const payload = (_rawPayload && typeof _rawPayload === 'object' && 'project' in _rawPayload) ? _rawPayload.project : _rawPayload; if (expectedPayload.workflow_id !== undefined) { expect(payload.workflow_id).toBe(expectedPayload.workflow_id); @@ -701,7 +703,8 @@ describe("createChatMessageAndTriggerStakwork (via sendMessageToStakwork)", () = }); const fetchCall = mockFetch.mock.calls[0]; - const payload = JSON.parse(fetchCall[1]?.body as string); + const _rawPayload = JSON.parse(fetchCall[1]?.body as string); + const payload = (_rawPayload && typeof _rawPayload === 'object' && 'project' in _rawPayload) ? _rawPayload.project : _rawPayload; expect(payload.webhook_url).toBe( "http://localhost:3000/api/stakwork/webhook?task_id=test-task-id" @@ -729,7 +732,8 @@ describe("createChatMessageAndTriggerStakwork (via sendMessageToStakwork)", () = }); const fetchCall = mockFetch.mock.calls[0]; - const payload = JSON.parse(fetchCall[1]?.body as string); + const _rawPayload = JSON.parse(fetchCall[1]?.body as string); + const payload = (_rawPayload && typeof _rawPayload === 'object' && 'project' in _rawPayload) ? _rawPayload.project : _rawPayload; expect(payload.workflow_id).toBe(123); // First ID in "123,456,789" for live mode }); @@ -1028,7 +1032,8 @@ describe("createChatMessageAndTriggerStakwork (via createTaskWithStakworkWorkflo }); const fetchCall = mockFetch.mock.calls[0]; - const payload = JSON.parse(fetchCall[1]?.body as string); + const _rawPayload = JSON.parse(fetchCall[1]?.body as string); + const payload = (_rawPayload && typeof _rawPayload === 'object' && 'project' in _rawPayload) ? _rawPayload.project : _rawPayload; expect(payload.workflow_id).toBe(123); // First ID in "123,456,789" for live mode TestHelpers.expectStakworkCalledWithVars({ taskMode: "live", @@ -1048,7 +1053,8 @@ describe("createChatMessageAndTriggerStakwork (via createTaskWithStakworkWorkflo }); const fetchCall = mockFetch.mock.calls[0]; - const payload = JSON.parse(fetchCall[1]?.body as string); + const _rawPayload = JSON.parse(fetchCall[1]?.body as string); + const payload = (_rawPayload && typeof _rawPayload === 'object' && 'project' in _rawPayload) ? _rawPayload.project : _rawPayload; expect(payload.workflow_id).toBe(456); // Second ID for default mode TestHelpers.expectStakworkCalledWithVars({ taskMode: "default", @@ -1069,7 +1075,8 @@ describe("createChatMessageAndTriggerStakwork (via createTaskWithStakworkWorkflo }); const fetchCall = mockFetch.mock.calls[0]; - const payload = JSON.parse(fetchCall[1]?.body as string); + const _rawPayload = JSON.parse(fetchCall[1]?.body as string); + const payload = (_rawPayload && typeof _rawPayload === 'object' && 'project' in _rawPayload) ? _rawPayload.project : _rawPayload; expect(payload.workflow_id).toBe(789); // Third ID for unit mode }); @@ -1087,7 +1094,8 @@ describe("createChatMessageAndTriggerStakwork (via createTaskWithStakworkWorkflo }); const fetchCall = mockFetch.mock.calls[0]; - const payload = JSON.parse(fetchCall[1]?.body as string); + const _rawPayload = JSON.parse(fetchCall[1]?.body as string); + const payload = (_rawPayload && typeof _rawPayload === 'object' && 'project' in _rawPayload) ? _rawPayload.project : _rawPayload; expect(payload.workflow_id).toBe(789); // Third ID for integration mode }); }); @@ -1501,7 +1509,8 @@ describe("Feature Context Integration", () => { }); const fetchCall = mockFetch.mock.calls[0]; - const payload = JSON.parse(fetchCall[1]?.body as string); + const _rawPayload = JSON.parse(fetchCall[1]?.body as string); + const payload = (_rawPayload && typeof _rawPayload === 'object' && 'project' in _rawPayload) ? _rawPayload.project : _rawPayload; const vars = payload.workflow_params.set_var.attributes.vars; expect(vars.featureContext).toBeUndefined(); @@ -1937,7 +1946,8 @@ describe("generateChatTitle Parameter Handling", () => { }); const fetchCall = mockFetch.mock.calls[0]; - const payload = JSON.parse(fetchCall[1]?.body as string); + const _rawPayload = JSON.parse(fetchCall[1]?.body as string); + const payload = (_rawPayload && typeof _rawPayload === 'object' && 'project' in _rawPayload) ? _rawPayload.project : _rawPayload; const vars = payload.workflow_params.set_var.attributes.vars; expect(vars.generateChatTitle).toBeUndefined(); @@ -2190,7 +2200,8 @@ describe("Feature Context Integration", () => { }); const fetchCall = mockFetch.mock.calls[0]; - const payload = JSON.parse(fetchCall[1]?.body as string); + const _rawPayload = JSON.parse(fetchCall[1]?.body as string); + const payload = (_rawPayload && typeof _rawPayload === 'object' && 'project' in _rawPayload) ? _rawPayload.project : _rawPayload; const vars = payload.workflow_params.set_var.attributes.vars; expect(vars.featureContext).toBeUndefined(); @@ -2625,7 +2636,8 @@ describe("generateChatTitle Parameter Handling", () => { }); const fetchCall = mockFetch.mock.calls[0]; - const payload = JSON.parse(fetchCall[1]?.body as string); + const _rawPayload = JSON.parse(fetchCall[1]?.body as string); + const payload = (_rawPayload && typeof _rawPayload === 'object' && 'project' in _rawPayload) ? _rawPayload.project : _rawPayload; const vars = payload.workflow_params.set_var.attributes.vars; expect(vars.generateChatTitle).toBeUndefined(); @@ -2782,7 +2794,8 @@ describe("callStakworkAPI - Direct Unit Tests", () => { await callStakworkAPI(params); const fetchCall = mockFetch.mock.calls[0]; - const payload = JSON.parse(fetchCall[1]?.body as string); + const _rawPayload = JSON.parse(fetchCall[1]?.body as string); + const payload = (_rawPayload && typeof _rawPayload === 'object' && 'project' in _rawPayload) ? _rawPayload.project : _rawPayload; expect(payload.name).toBe("hive-task-test-task-id"); }); @@ -2804,7 +2817,8 @@ describe("callStakworkAPI - Direct Unit Tests", () => { await callStakworkAPI(params); const fetchCall = mockFetch.mock.calls[0]; - const payload = JSON.parse(fetchCall[1]?.body as string); + const _rawPayload = JSON.parse(fetchCall[1]?.body as string); + const payload = (_rawPayload && typeof _rawPayload === 'object' && 'project' in _rawPayload) ? _rawPayload.project : _rawPayload; expect(payload.name).toBe(`hive-plan-${featureId}`); }); @@ -3063,7 +3077,8 @@ describe("callStakworkAPI - Direct Unit Tests", () => { const body = fetchCall[1]?.body as string; expect(() => JSON.parse(body)).not.toThrow(); - const payload = JSON.parse(body); + const _rawPayload = JSON.parse(body); + const payload = (_rawPayload && typeof _rawPayload === "object" && "project" in _rawPayload) ? _rawPayload.project : _rawPayload; expect(payload).toHaveProperty("workflow_id"); expect(payload).toHaveProperty("workflow_params"); }); @@ -4849,7 +4864,8 @@ describe("startTaskWorkflow with includeHistory", () => { }); const fetchCall = mockFetch.mock.calls[0]; - const payload = JSON.parse(fetchCall[1]?.body as string); + const _rawPayload = JSON.parse(fetchCall[1]?.body as string); + const payload = (_rawPayload && typeof _rawPayload === 'object' && 'project' in _rawPayload) ? _rawPayload.project : _rawPayload; const vars = payload.workflow_params.set_var.attributes.vars; expect(vars).not.toHaveProperty("podId"); @@ -4896,7 +4912,8 @@ describe("startTaskWorkflow - featureId forwarding", () => { }); const fetchCall = mockFetch.mock.calls[0]; - const payload = JSON.parse(fetchCall[1]?.body as string); + const _rawPayload = JSON.parse(fetchCall[1]?.body as string); + const payload = (_rawPayload && typeof _rawPayload === 'object' && 'project' in _rawPayload) ? _rawPayload.project : _rawPayload; const vars = payload.workflow_params.set_var.attributes.vars; expect(vars.featureId).toBe("feature-123"); @@ -4927,7 +4944,8 @@ describe("startTaskWorkflow - featureId forwarding", () => { }); const fetchCall = mockFetch.mock.calls[0]; - const payload = JSON.parse(fetchCall[1]?.body as string); + const _rawPayload = JSON.parse(fetchCall[1]?.body as string); + const payload = (_rawPayload && typeof _rawPayload === 'object' && 'project' in _rawPayload) ? _rawPayload.project : _rawPayload; const vars = payload.workflow_params.set_var.attributes.vars; expect(vars).not.toHaveProperty("featureId"); diff --git a/src/services/task-workflow.ts b/src/services/task-workflow.ts index 56dbb4a298..90e6d9399f 100644 --- a/src/services/task-workflow.ts +++ b/src/services/task-workflow.ts @@ -908,7 +908,7 @@ export async function callStakworkAPI(params: { try { const response = await fetch(stakworkURL, { method: "POST", - body: JSON.stringify(stakworkPayload), + body: JSON.stringify({ project: stakworkPayload }), headers: { Authorization: `Token token=${config.STAKWORK_API_KEY}`, "Content-Type": "application/json",