import { mockDeep } from 'jest-mock-extended'; import type { IExecuteFunctions, INode } from 'n8n-workflow'; import { microsoftApiRequest } from '../GenericFunctions'; describe('Microsoft ToDo GenericFunctions', () => { let mockExecuteFunctions: jest.Mocked; let mockNode: INode; let mockRequestOAuth2: jest.Mock; beforeEach(() => { mockExecuteFunctions = mockDeep(); mockRequestOAuth2 = jest.fn(); mockExecuteFunctions.helpers.requestOAuth2 = mockRequestOAuth2; mockNode = { id: 'test-node', name: 'Test ToDo Node', type: 'n8n-nodes-base.microsoftToDo', typeVersion: 1, position: [0, 0], parameters: {}, }; mockExecuteFunctions.getNode.mockReturnValue(mockNode); jest.clearAllMocks(); }); afterEach(() => { jest.resetAllMocks(); }); describe('microsoftApiRequest', () => { describe('graphApiBaseUrl from credentials', () => { it('should use base URL from credentials', async () => { const mockResponse = { data: 'test' }; mockRequestOAuth2.mockResolvedValue(mockResponse); mockExecuteFunctions.getCredentials.mockResolvedValue({ oauthTokenData: { access_token: 'test-access-token', }, graphApiBaseUrl: 'https://graph.microsoft.us', }); await microsoftApiRequest.call(mockExecuteFunctions, 'GET', '/todo/lists'); expect(mockRequestOAuth2).toHaveBeenCalledWith( 'microsoftToDoOAuth2Api', expect.objectContaining({ method: 'GET', uri: 'https://graph.microsoft.us/v1.0/me/todo/lists', json: true, }), ); }); it('should fall back to default when credentials.graphApiBaseUrl is empty', async () => { const mockResponse = { data: 'test' }; mockRequestOAuth2.mockResolvedValue(mockResponse); mockExecuteFunctions.getCredentials.mockResolvedValue({ oauthTokenData: { access_token: 'test-access-token', }, graphApiBaseUrl: '', }); await microsoftApiRequest.call(mockExecuteFunctions, 'GET', '/todo/lists'); expect(mockRequestOAuth2).toHaveBeenCalledWith( 'microsoftToDoOAuth2Api', expect.objectContaining({ method: 'GET', uri: 'https://graph.microsoft.com/v1.0/me/todo/lists', json: true, }), ); }); it('should fall back to default when credentials.graphApiBaseUrl is undefined', async () => { const mockResponse = { data: 'test' }; mockRequestOAuth2.mockResolvedValue(mockResponse); mockExecuteFunctions.getCredentials.mockResolvedValue({ oauthTokenData: { access_token: 'test-access-token', }, }); await microsoftApiRequest.call(mockExecuteFunctions, 'GET', '/todo/lists'); expect(mockRequestOAuth2).toHaveBeenCalledWith( 'microsoftToDoOAuth2Api', expect.objectContaining({ method: 'GET', uri: 'https://graph.microsoft.com/v1.0/me/todo/lists', json: true, }), ); }); it('should strip trailing slashes from base URL using regex', async () => { const mockResponse = { data: 'test' }; mockRequestOAuth2.mockResolvedValue(mockResponse); mockExecuteFunctions.getCredentials.mockResolvedValue({ oauthTokenData: { access_token: 'test-access-token', }, graphApiBaseUrl: 'https://graph.microsoft.com/', }); await microsoftApiRequest.call(mockExecuteFunctions, 'GET', '/todo/lists'); expect(mockRequestOAuth2).toHaveBeenCalledWith( 'microsoftToDoOAuth2Api', expect.objectContaining({ method: 'GET', uri: 'https://graph.microsoft.com/v1.0/me/todo/lists', json: true, }), ); }); it('should strip multiple trailing slashes from base URL', async () => { const mockResponse = { data: 'test' }; mockRequestOAuth2.mockResolvedValue(mockResponse); mockExecuteFunctions.getCredentials.mockResolvedValue({ oauthTokenData: { access_token: 'test-access-token', }, graphApiBaseUrl: 'https://graph.microsoft.com///', }); await microsoftApiRequest.call(mockExecuteFunctions, 'GET', '/todo/lists'); expect(mockRequestOAuth2).toHaveBeenCalledWith( 'microsoftToDoOAuth2Api', expect.objectContaining({ method: 'GET', uri: 'https://graph.microsoft.com/v1.0/me/todo/lists', json: true, }), ); }); it('should use US Government cloud endpoint', async () => { const mockResponse = { data: 'test' }; mockRequestOAuth2.mockResolvedValue(mockResponse); mockExecuteFunctions.getCredentials.mockResolvedValue({ oauthTokenData: { access_token: 'test-access-token', }, graphApiBaseUrl: 'https://graph.microsoft.us', }); await microsoftApiRequest.call(mockExecuteFunctions, 'GET', '/todo/lists'); expect(mockRequestOAuth2).toHaveBeenCalledWith( 'microsoftToDoOAuth2Api', expect.objectContaining({ method: 'GET', uri: 'https://graph.microsoft.us/v1.0/me/todo/lists', json: true, }), ); }); it('should use US Government DOD cloud endpoint', async () => { const mockResponse = { data: 'test' }; mockRequestOAuth2.mockResolvedValue(mockResponse); mockExecuteFunctions.getCredentials.mockResolvedValue({ oauthTokenData: { access_token: 'test-access-token', }, graphApiBaseUrl: 'https://dod-graph.microsoft.us', }); await microsoftApiRequest.call(mockExecuteFunctions, 'GET', '/todo/lists'); expect(mockRequestOAuth2).toHaveBeenCalledWith( 'microsoftToDoOAuth2Api', expect.objectContaining({ method: 'GET', uri: 'https://dod-graph.microsoft.us/v1.0/me/todo/lists', json: true, }), ); }); it('should use China cloud endpoint', async () => { const mockResponse = { data: 'test' }; mockRequestOAuth2.mockResolvedValue(mockResponse); mockExecuteFunctions.getCredentials.mockResolvedValue({ oauthTokenData: { access_token: 'test-access-token', }, graphApiBaseUrl: 'https://microsoftgraph.chinacloudapi.cn', }); await microsoftApiRequest.call(mockExecuteFunctions, 'GET', '/todo/lists'); expect(mockRequestOAuth2).toHaveBeenCalledWith( 'microsoftToDoOAuth2Api', expect.objectContaining({ method: 'GET', uri: 'https://microsoftgraph.chinacloudapi.cn/v1.0/me/todo/lists', json: true, }), ); }); }); }); });