/* eslint-disable n8n-nodes-base/node-filename-against-convention */ import type { IExecuteFunctions, INodeTypeBaseDescription } from 'n8n-workflow'; import { HttpRequestV3 } from '../../V3/HttpRequestV3.node'; describe('HttpRequestV3', () => { let node: HttpRequestV3; let executeFunctions: IExecuteFunctions; const baseUrl = 'http://example.com'; const options = { redirect: '', batching: { batch: { batchSize: 1, batchInterval: 1 } }, proxy: '', timeout: '', allowUnauthoridCerts: '', queryParameterArrays: '', response: '', lowercaseHeaders: '', }; beforeEach(() => { const baseDescription: INodeTypeBaseDescription = { displayName: 'HTTP Request', name: 'httpRequest', description: 'Makes an HTTP request and returns the response data', group: [], }; node = new HttpRequestV3(baseDescription); executeFunctions = { getInputData: jest.fn(), getNodeParameter: jest.fn(), getNode: jest.fn(() => { return { type: 'n8n-nodes-base.httpRequest', typeVersion: 3, }; }), getCredentials: jest.fn(), helpers: { request: jest.fn(), requestOAuth1: jest.fn( async () => await Promise.resolve({ statusCode: 200, headers: { 'content-type': 'application/json' }, body: Buffer.from(JSON.stringify({ success: true })), }), ), requestOAuth2: jest.fn( async () => await Promise.resolve({ statusCode: 200, headers: { 'content-type': 'application/json' }, body: Buffer.from(JSON.stringify({ success: true })), }), ), requestWithAuthentication: jest.fn(), requestWithAuthenticationPaginated: jest.fn(), assertBinaryData: jest.fn(), getBinaryStream: jest.fn(), getBinaryMetadata: jest.fn(), binaryToString: jest.fn((buffer: Buffer) => { return buffer.toString(); }), prepareBinaryData: jest.fn(), }, getContext: jest.fn(), sendMessageToUI: jest.fn(), continueOnFail: jest.fn(), getMode: jest.fn(), } as unknown as IExecuteFunctions; }); it('should make a GET request', async () => { (executeFunctions.getInputData as jest.Mock).mockReturnValue([{ json: {} }]); (executeFunctions.getNodeParameter as jest.Mock).mockImplementation((paramName: string) => { switch (paramName) { case 'method': return 'GET'; case 'url': return baseUrl; case 'authentication': return 'none'; case 'options': return options; default: return undefined; } }); const response = { headers: { 'content-type': 'application/json' }, body: Buffer.from(JSON.stringify({ success: true })), }; (executeFunctions.helpers.request as jest.Mock).mockResolvedValue(response); const result = await node.execute.call(executeFunctions); expect(result).toEqual([[{ json: { success: true }, pairedItem: { item: 0 } }]]); }); it('should handle authentication', async () => { (executeFunctions.getInputData as jest.Mock).mockReturnValue([{ json: {} }]); (executeFunctions.getNodeParameter as jest.Mock).mockImplementation((paramName: string) => { switch (paramName) { case 'method': return 'GET'; case 'url': return baseUrl; case 'authentication': return 'genericCredentialType'; case 'genericAuthType': return 'httpBasicAuth'; case 'options': return options; default: return undefined; } }); (executeFunctions.getCredentials as jest.Mock).mockResolvedValue({ user: 'username', password: 'password', }); const response = { headers: { 'content-type': 'application/json' }, body: Buffer.from(JSON.stringify({ success: true })), }; (executeFunctions.helpers.request as jest.Mock).mockResolvedValue(response); const result = await node.execute.call(executeFunctions); expect(result).toEqual([[{ json: { success: true }, pairedItem: { item: 0 } }]]); expect(executeFunctions.helpers.request).toHaveBeenCalledWith( expect.objectContaining({ auth: { user: 'username', pass: 'password', }, }), ); }); describe('Authentication Handling', () => { const authenticationTypes = [ { genericCredentialType: 'httpBasicAuth', credentials: { user: 'username', password: 'password' }, authField: 'auth', authValue: { user: 'username', pass: 'password' }, }, { genericCredentialType: 'httpDigestAuth', credentials: { user: 'username', password: 'password' }, authField: 'auth', authValue: { user: 'username', pass: 'password', sendImmediately: false }, }, { genericCredentialType: 'httpHeaderAuth', credentials: { name: 'Authorization', value: 'Bearer token' }, authField: 'headers', authValue: { Authorization: 'Bearer token' }, }, { genericCredentialType: 'httpQueryAuth', credentials: { name: 'Token', value: 'secretToken' }, authField: 'qs', authValue: { Token: 'secretToken' }, }, { genericCredentialType: 'oAuth1Api', credentials: { oauth_token: 'token', oauth_token_secret: 'secret' }, authField: 'oauth', authValue: { oauth_token: 'token', oauth_token_secret: 'secret' }, }, { genericCredentialType: 'oAuth2Api', credentials: { access_token: 'accessToken' }, authField: 'auth', authValue: { bearer: 'accessToken' }, }, ]; it.each(authenticationTypes)( 'should handle %s authentication', async ({ genericCredentialType, credentials, authField, authValue }) => { (executeFunctions.getInputData as jest.Mock).mockReturnValue([{ json: {} }]); (executeFunctions.getNodeParameter as jest.Mock).mockImplementation((paramName: string) => { switch (paramName) { case 'method': return 'GET'; case 'url': return baseUrl; case 'authentication': return 'genericCredentialType'; case 'genericAuthType': return genericCredentialType; case 'options': return options; default: return undefined; } }); (executeFunctions.getCredentials as jest.Mock).mockResolvedValue(credentials); const response = { headers: { 'content-type': 'application/json' }, body: Buffer.from(JSON.stringify({ success: true })), }; (executeFunctions.helpers.request as jest.Mock).mockResolvedValue(response); const result = await node.execute.call(executeFunctions); expect(result).toEqual([[{ json: { success: true }, pairedItem: { item: 0 } }]]); if (genericCredentialType === 'oAuth1Api') { expect(executeFunctions.helpers.requestOAuth1).toHaveBeenCalled(); } else if (genericCredentialType === 'oAuth2Api') { expect(executeFunctions.helpers.requestOAuth2).toHaveBeenCalled(); } else { expect(executeFunctions.helpers.request).toHaveBeenCalledWith( expect.objectContaining({ [authField]: expect.objectContaining(authValue), }), ); } }, ); }); });