From e23ffccca8248aa76435be9d20cc3df6bd6c3773 Mon Sep 17 00:00:00 2001 From: RomanDavydchuk Date: Thu, 22 May 2025 17:09:50 +0300 Subject: [PATCH] fix(Jira Software Node): Use old endpoints to get all issues on self-hosted instances (#15591) --- packages/nodes-base/nodes/Jira/Jira.node.ts | 49 ++++++--- .../{test/node => __test__}/Jira.node.test.ts | 102 +++++++++++++++++- 2 files changed, 133 insertions(+), 18 deletions(-) rename packages/nodes-base/nodes/Jira/{test/node => __test__}/Jira.node.test.ts (59%) diff --git a/packages/nodes-base/nodes/Jira/Jira.node.ts b/packages/nodes-base/nodes/Jira/Jira.node.ts index 47a19e810f8..ed39dce9966 100644 --- a/packages/nodes-base/nodes/Jira/Jira.node.ts +++ b/packages/nodes-base/nodes/Jira/Jira.node.ts @@ -822,24 +822,43 @@ export class Jira implements INodeType { } } if (returnAll) { - responseData = await jiraSoftwareCloudApiRequestAllItems.call( - this, - 'issues', - '/api/2/search/jql', - 'POST', - body, - {}, - 'token', - ); + if (jiraVersion === 'server' || jiraVersion === 'serverPat') { + responseData = await jiraSoftwareCloudApiRequestAllItems.call( + this, + 'issues', + '/api/2/search', + 'POST', + body, + ); + } else { + responseData = await jiraSoftwareCloudApiRequestAllItems.call( + this, + 'issues', + '/api/2/search/jql', + 'POST', + body, + {}, + 'token', + ); + } } else { const limit = this.getNodeParameter('limit', i); body.maxResults = limit; - responseData = await jiraSoftwareCloudApiRequest.call( - this, - '/api/2/search/jql', - 'POST', - body, - ); + if (jiraVersion === 'server' || jiraVersion === 'serverPat') { + responseData = await jiraSoftwareCloudApiRequest.call( + this, + '/api/2/search', + 'POST', + body, + ); + } else { + responseData = await jiraSoftwareCloudApiRequest.call( + this, + '/api/2/search/jql', + 'POST', + body, + ); + } responseData = responseData.issues; } diff --git a/packages/nodes-base/nodes/Jira/test/node/Jira.node.test.ts b/packages/nodes-base/nodes/Jira/__test__/Jira.node.test.ts similarity index 59% rename from packages/nodes-base/nodes/Jira/test/node/Jira.node.test.ts rename to packages/nodes-base/nodes/Jira/__test__/Jira.node.test.ts index f20aeebc732..1c3ac3bdc2a 100644 --- a/packages/nodes-base/nodes/Jira/test/node/Jira.node.test.ts +++ b/packages/nodes-base/nodes/Jira/__test__/Jira.node.test.ts @@ -2,14 +2,17 @@ import type { DeepMockProxy } from 'jest-mock-extended'; import { mockDeep } from 'jest-mock-extended'; import type { IExecuteFunctions } from 'n8n-workflow'; -import * as GenericFunctions from '../../GenericFunctions'; -import { Jira } from '../../Jira.node'; +import * as GenericFunctions from '../GenericFunctions'; +import { Jira } from '../Jira.node'; -jest.mock('../../GenericFunctions', () => ({ +jest.mock('../GenericFunctions', () => ({ jiraSoftwareCloudApiRequest: jest.fn().mockResolvedValue({ issues: [] }), + jiraSoftwareCloudApiRequestAllItems: jest.fn().mockResolvedValue([]), })); const jiraSoftwareCloudApiRequestMock = GenericFunctions.jiraSoftwareCloudApiRequest as jest.Mock; +const jiraSoftwareCloudApiRequestAllItems = + GenericFunctions.jiraSoftwareCloudApiRequestAllItems as jest.Mock; describe('Jira Node', () => { let jiraNode: Jira; @@ -148,5 +151,98 @@ describe('Jira Node', () => { }), ); }); + + it('should call new endpoint for the cloud version with return all = true', async () => { + executeFunctionsMock.getNodeParameter.mockImplementation((parameterName: string) => { + switch (parameterName) { + case 'resource': + return 'issue'; + case 'operation': + return 'getAll'; + case 'jiraVersion': + return 'cloud'; + case 'returnAll': + return true; + case 'options': + return {}; + default: + return null; + } + }); + + await jiraNode.execute.call(executeFunctionsMock); + + expect(jiraSoftwareCloudApiRequestAllItems).toHaveBeenCalledWith( + 'issues', + '/api/2/search/jql', + 'POST', + expect.anything(), + {}, + 'token', + ); + }); + + it.each([['server'], ['serverPat']])( + 'should call old endpoint for the self-hosted version with return all = false', + async (jiraVersion: string) => { + executeFunctionsMock.getNodeParameter.mockImplementation((parameterName: string) => { + switch (parameterName) { + case 'resource': + return 'issue'; + case 'operation': + return 'getAll'; + case 'jiraVersion': + return jiraVersion; + case 'returnAll': + return false; + case 'limit': + return 10; + case 'options': + return {}; + default: + return null; + } + }); + + await jiraNode.execute.call(executeFunctionsMock); + + expect(jiraSoftwareCloudApiRequestMock).toHaveBeenCalledWith( + '/api/2/search', + 'POST', + expect.anything(), + ); + }, + ); + + it.each([['server'], ['serverPat']])( + 'should call old endpoint for the self-hosted version with return all = true', + async (jiraVersion: string) => { + executeFunctionsMock.getNodeParameter.mockImplementation((parameterName: string) => { + switch (parameterName) { + case 'resource': + return 'issue'; + case 'operation': + return 'getAll'; + case 'jiraVersion': + return jiraVersion; + case 'returnAll': + return true; + case 'options': + return {}; + default: + return null; + } + }); + + await jiraNode.execute.call(executeFunctionsMock); + + expect(jiraSoftwareCloudApiRequestAllItems).toHaveBeenCalledWith( + 'issues', + '/api/2/search', + 'POST', + expect.anything(), + ); + }, + ); }); });