From c667116c4b0fd6cf4c4a50d854bdcc9427affa25 Mon Sep 17 00:00:00 2001 From: Stamsy Date: Sun, 15 Dec 2024 19:30:00 +0200 Subject: [PATCH] add handle pagination and aws request unit tests --- .../nodes/Aws/Cognito/test/AWSRequest.test.ts | 135 ++++++++++++++++++ .../Aws/Cognito/test/HandlePagination.test.ts | 85 +++++++++++ 2 files changed, 220 insertions(+) create mode 100644 packages/nodes-base/nodes/Aws/Cognito/test/AWSRequest.test.ts create mode 100644 packages/nodes-base/nodes/Aws/Cognito/test/HandlePagination.test.ts diff --git a/packages/nodes-base/nodes/Aws/Cognito/test/AWSRequest.test.ts b/packages/nodes-base/nodes/Aws/Cognito/test/AWSRequest.test.ts new file mode 100644 index 0000000000..49ccd9dd1f --- /dev/null +++ b/packages/nodes-base/nodes/Aws/Cognito/test/AWSRequest.test.ts @@ -0,0 +1,135 @@ +import { awsRequest } from '../GenericFunctions'; + +describe('GenericFunctions - awsRequest', () => { + let mockContext: any; + let mockRequestWithAuthentication: jest.Mock; + let mockGetCredentials: jest.Mock; + + beforeEach(() => { + mockRequestWithAuthentication = jest.fn(); + mockGetCredentials = jest.fn(); + mockContext = { + helpers: { + requestWithAuthentication: mockRequestWithAuthentication, + }, + getCredentials: mockGetCredentials, + }; + }); + + test('should make a successful request with correct options', async () => { + // Mock credentials and response + mockGetCredentials.mockResolvedValueOnce({ region: 'us-west-2' }); + mockRequestWithAuthentication.mockResolvedValueOnce({ success: true }); + + // Define request options with correct type for method + const requestOptions = { + method: 'POST' as const, + url: '/example-endpoint', + headers: { + 'X-Amz-Target': 'ExampleService.Action', + }, + body: { key: 'value' }, + }; + + const result = await awsRequest.call(mockContext, requestOptions); + + // Validate the request call + expect(mockGetCredentials).toHaveBeenCalledWith('aws'); + expect(mockRequestWithAuthentication).toHaveBeenCalledWith( + 'aws', + expect.objectContaining({ + method: 'POST', + baseURL: 'https://cognito-idp.us-west-2.amazonaws.com', + headers: expect.objectContaining({ + 'Content-Type': 'application/x-amz-json-1.1', + 'X-Amz-Target': 'ExampleService.Action', + }), + body: { key: 'value' }, + json: true, + }), + ); + + expect(result).toEqual({ success: true }); + }); + + test('should throw an error if AWS credentials are invalid (403)', async () => { + // Mock credentials and response + mockGetCredentials.mockResolvedValueOnce({ region: 'us-west-2' }); + mockRequestWithAuthentication.mockRejectedValueOnce({ + statusCode: 403, + response: { + body: { message: 'The security token included in the request is invalid.' }, + }, + }); + + const requestOptions = { + method: 'POST' as const, + url: '/example-endpoint', + headers: {}, + }; + + await expect(awsRequest.call(mockContext, requestOptions)).rejects.toThrow( + 'The AWS credentials are not valid!', + ); + + expect(mockRequestWithAuthentication).toHaveBeenCalled(); + }); + + test('should throw a descriptive error for other AWS errors', async () => { + // Mock credentials and response + mockGetCredentials.mockResolvedValueOnce({ region: 'us-east-1' }); + mockRequestWithAuthentication.mockRejectedValueOnce({ + statusCode: 400, + response: { + body: { message: 'Invalid request parameter' }, + }, + }); + + const requestOptions = { + method: 'POST' as const, + url: '/example-endpoint', + headers: {}, + }; + + await expect(awsRequest.call(mockContext, requestOptions)).rejects.toThrow( + 'AWS error response [400]: Invalid request parameter', + ); + }); + + test('should handle unexpected error structures gracefully', async () => { + // Mock credentials and response + mockGetCredentials.mockResolvedValueOnce({ region: 'us-east-1' }); + mockRequestWithAuthentication.mockRejectedValueOnce({ + cause: { error: { message: 'Something went wrong' } }, + }); + + const requestOptions = { + method: 'POST' as const, + url: '/example-endpoint', + headers: {}, + }; + + await expect(awsRequest.call(mockContext, requestOptions)).rejects.toThrow( + 'AWS error response [undefined]: Something went wrong', + ); + }); + + test('should throw a generic error if no meaningful information is provided', async () => { + // Mock credentials and response + mockGetCredentials.mockResolvedValueOnce({ region: 'us-east-1' }); + mockRequestWithAuthentication.mockRejectedValueOnce({ + statusCode: 500, + message: 'Internal Server Error', + }); + + const requestOptions = { + method: 'POST' as const, + url: '/example-endpoint', + headers: {}, + }; + + await expect(awsRequest.call(mockContext, requestOptions)).rejects.toThrow( + 'AWS error response [500]: Internal Server Error', + ); + }); +}); diff --git a/packages/nodes-base/nodes/Aws/Cognito/test/HandlePagination.test.ts b/packages/nodes-base/nodes/Aws/Cognito/test/HandlePagination.test.ts new file mode 100644 index 0000000000..904d2b7974 --- /dev/null +++ b/packages/nodes-base/nodes/Aws/Cognito/test/HandlePagination.test.ts @@ -0,0 +1,85 @@ +import { handlePagination } from '../GenericFunctions'; // Adjust the import path if necessary + +describe('GenericFunctions - handlePagination', () => { + let mockContext: any; + let mockMakeRoutingRequest: jest.Mock; + let mockGetNodeParameter: jest.Mock; + let resultOptions: any; + + beforeEach(() => { + mockMakeRoutingRequest = jest.fn(); + mockGetNodeParameter = jest.fn(); + mockContext = { + makeRoutingRequest: mockMakeRoutingRequest, + getNodeParameter: mockGetNodeParameter, + }; + + resultOptions = { + maxResults: 60, + options: { body: {} }, + }; + }); + + test('should stop fetching when the limit is reached and returnAll is false', async () => { + // Mock responses for pagination + mockMakeRoutingRequest.mockResolvedValueOnce([ + { json: { Users: [{ id: 1 }, { id: 2 }, { id: 3 }], PaginationToken: undefined } }, + ]); + + // Mock parameters + mockGetNodeParameter.mockReturnValueOnce(false); // returnAll = false + mockGetNodeParameter.mockReturnValueOnce(2); // limit = 2 + + const result = await handlePagination.call(mockContext, resultOptions); + + expect(mockMakeRoutingRequest).toHaveBeenCalledTimes(1); + expect(result).toEqual([{ json: { id: 1 } }, { json: { id: 2 } }]); + }); + + test('should fetch all items when returnAll is true', async () => { + // Mock responses for pagination + mockMakeRoutingRequest + .mockResolvedValueOnce([ + { json: { Users: [{ id: 1 }, { id: 2 }], PaginationToken: 'token1' } }, + ]) + .mockResolvedValueOnce([{ json: { Users: [{ id: 3 }], PaginationToken: undefined } }]); + + // Mock parameters + mockGetNodeParameter.mockReturnValueOnce(true); // returnAll = true + + const result = await handlePagination.call(mockContext, resultOptions); + + expect(mockMakeRoutingRequest).toHaveBeenCalledTimes(2); + expect(result).toEqual([{ json: { id: 1 } }, { json: { id: 2 } }, { json: { id: 3 } }]); + }); + + test('should handle resource-specific token key', async () => { + // Mock responses for group resource + mockMakeRoutingRequest.mockResolvedValueOnce([ + { json: { Groups: [{ id: 1 }, { id: 2 }], NextToken: undefined } }, + ]); + + // Mock parameters + mockGetNodeParameter.mockReturnValueOnce('group'); // resource = group + mockGetNodeParameter.mockReturnValueOnce(false); // returnAll = false + mockGetNodeParameter.mockReturnValueOnce(10); // limit = 10 + + const result = await handlePagination.call(mockContext, resultOptions); + + expect(mockMakeRoutingRequest).toHaveBeenCalledTimes(1); + expect(result).toEqual([{ json: { id: 1 } }, { json: { id: 2 } }]); + }); + + test('should handle empty results', async () => { + // Mock empty response + mockMakeRoutingRequest.mockResolvedValueOnce([]); + + // Mock parameters + mockGetNodeParameter.mockReturnValueOnce(true); // returnAll = true + + const result = await handlePagination.call(mockContext, resultOptions); + + expect(mockMakeRoutingRequest).toHaveBeenCalledTimes(1); + expect(result).toEqual([]); + }); +});