first commit
Security: Sync from Public / sync-from-public (push) Has been cancelled
Test: Benchmark Nightly / build (push) Has been cancelled
Test: Benchmark Nightly / Notify Cats on failure (push) Has been cancelled
CI: Python / Checks (push) Has been cancelled
Test: Evals Python / Workflow Comparison Python (push) Has been cancelled
Util: Check Docs URLs / check-docs-urls (push) Has been cancelled
Test: Visual Storybook / Cloudflare Pages (push) Has been cancelled
Test: E2E Performance / build-and-test-performance (push) Has been cancelled
Test: Workflows Nightly / Run Workflow Tests (push) Has been cancelled
Util: Cleanup CI Docker Images / Delete stale CI images (push) Has been cancelled
Test: Benchmark Destroy Env / build (push) Has been cancelled
Util: Update Node Popularity / update-popularity (push) Has been cancelled
Test: E2E Coverage Weekly / Coverage Tests (push) Has been cancelled

This commit is contained in:
2026-03-17 16:22:57 +03:30
commit 3d5eaf9445
15349 changed files with 2847338 additions and 0 deletions
@@ -0,0 +1,125 @@
import { ClientOAuth2 } from '@n8n/client-oauth2';
import type { INode } from 'n8n-workflow';
import { NodeOperationError } from 'n8n-workflow';
import { N8nOAuth2TokenCredential } from '../credentials/N8nOAuth2TokenCredential';
import type { AzureEntraCognitiveServicesOAuth2ApiCredential } from '../types';
// Mock ClientOAuth2
jest.mock('@n8n/client-oauth2', () => {
return {
ClientOAuth2: jest.fn().mockImplementation(() => {
return {
credentials: {
getToken: jest.fn().mockResolvedValue({
data: {
access_token: 'fresh-test-token',
expires_on: 1234567890,
},
}),
},
};
}),
};
});
const mockNode: INode = {
id: '1',
name: 'Mock node',
typeVersion: 2,
type: 'n8n-nodes-base.mock',
position: [0, 0],
parameters: {},
};
describe('N8nOAuth2TokenCredential', () => {
let mockCredential: AzureEntraCognitiveServicesOAuth2ApiCredential;
let credential: N8nOAuth2TokenCredential;
beforeEach(() => {
// Create a mock credential with all required properties
mockCredential = {
authQueryParameters: '',
authentication: 'body',
authUrl: '',
accessTokenUrl: '',
grantType: 'clientCredentials',
clientId: '',
clientSecret: 'secret',
customScopes: false,
apiVersion: '2023-05-15',
endpoint: 'https://test.openai.azure.com',
resourceName: 'test-resource',
oauthTokenData: {
access_token: 'test-token',
expires_on: 1234567890,
ext_expires_on: 0,
},
scope: '',
tenantId: '',
};
credential = new N8nOAuth2TokenCredential(mockNode, mockCredential);
});
afterEach(() => {
jest.clearAllMocks();
});
describe('getToken', () => {
it('should return a token when credentials are valid', async () => {
// Act
const result = await credential.getToken();
// Assert
expect(result).toEqual({
token: 'fresh-test-token',
expiresOnTimestamp: 1234567890,
});
expect(ClientOAuth2).toHaveBeenCalledWith(
expect.objectContaining({
clientId: mockCredential.clientId,
clientSecret: mockCredential.clientSecret,
}),
);
});
it('should throw NodeOperationError when credentials do not contain token', async () => {
// Arrange - remove the token
mockCredential.oauthTokenData.access_token = '';
credential = new N8nOAuth2TokenCredential(mockNode, mockCredential);
// Act & Assert
await expect(credential.getToken()).rejects.toThrow(NodeOperationError);
});
it('should throw NodeOperationError when oauthTokenData is missing', async () => {
// Arrange - remove oauthTokenData
const incompleteCredential = { ...mockCredential };
// @ts-expect-error: purposely making it invalid for test
delete incompleteCredential.oauthTokenData;
credential = new N8nOAuth2TokenCredential(
mockNode,
incompleteCredential as AzureEntraCognitiveServicesOAuth2ApiCredential,
);
// Act & Assert
await expect(credential.getToken()).rejects.toThrow(NodeOperationError);
});
});
describe('getDeploymentDetails', () => {
it('should return deployment details from credentials', async () => {
// Act
const result = await credential.getDeploymentDetails();
// Assert
expect(result).toEqual({
apiVersion: '2023-05-15',
endpoint: 'https://test.openai.azure.com',
resourceName: 'test-resource',
});
});
});
});
@@ -0,0 +1,81 @@
/* eslint-disable @typescript-eslint/unbound-method */
import { createMockExecuteFunction } from 'n8n-nodes-base/test/nodes/Helpers';
import type { INode, ISupplyDataFunctions } from 'n8n-workflow';
import { NodeOperationError } from 'n8n-workflow';
import { setupApiKeyAuthentication } from '../credentials/api-key';
describe('setupApiKeyAuthentication', () => {
let ctx: ISupplyDataFunctions;
beforeEach(() => {
const mockNode: INode = {
id: '1',
name: 'Mock node',
typeVersion: 2,
type: 'n8n-nodes-base.mock',
position: [0, 0],
parameters: {},
};
ctx = createMockExecuteFunction<ISupplyDataFunctions>({}, mockNode);
ctx.logger = {
debug: jest.fn(),
info: jest.fn(),
warn: jest.fn(),
error: jest.fn(),
};
});
afterEach(() => {
jest.clearAllMocks();
});
it('should return valid configuration when API key is provided', async () => {
// Arrange
const mockCredentials = {
apiKey: 'test-api-key',
resourceName: 'test-resource',
apiVersion: '2023-05-15',
endpoint: 'https://test.openai.azure.com',
};
ctx.getCredentials = jest.fn().mockResolvedValue(mockCredentials);
// Act
const result = await setupApiKeyAuthentication.call(ctx, 'testCredential');
// Assert
expect(result).toEqual({
azureOpenAIApiKey: 'test-api-key',
azureOpenAIApiInstanceName: 'test-resource',
azureOpenAIApiVersion: '2023-05-15',
azureOpenAIEndpoint: 'https://test.openai.azure.com',
});
expect(ctx.getCredentials).toHaveBeenCalledWith('testCredential');
});
it('should throw NodeOperationError when API key is missing', async () => {
// Arrange
const mockCredentials = {
// No apiKey
resourceName: 'test-resource',
apiVersion: '2023-05-15',
};
ctx.getCredentials = jest.fn().mockResolvedValue(mockCredentials);
// Act & Assert
await expect(setupApiKeyAuthentication.call(ctx, 'testCredential')).rejects.toThrow(
NodeOperationError,
);
});
it('should throw NodeOperationError when credential retrieval fails', async () => {
// Arrange
const testError = new Error('Credential fetch failed');
ctx.getCredentials = jest.fn().mockRejectedValue(testError);
// Act & Assert
await expect(setupApiKeyAuthentication.call(ctx, 'testCredential')).rejects.toThrow(
NodeOperationError,
);
});
});
@@ -0,0 +1,98 @@
/* eslint-disable @typescript-eslint/unbound-method */
import { createMockExecuteFunction } from 'n8n-nodes-base/test/nodes/Helpers';
import type { INode, ISupplyDataFunctions } from 'n8n-workflow';
import { NodeOperationError } from 'n8n-workflow';
import { setupOAuth2Authentication } from '../credentials/oauth2';
import type { AzureEntraCognitiveServicesOAuth2ApiCredential } from '../types';
// Mock the N8nOAuth2TokenCredential
jest.mock('../credentials/N8nOAuth2TokenCredential', () => ({
N8nOAuth2TokenCredential: jest.fn().mockImplementation(() => ({
getToken: jest.fn().mockResolvedValue({
token: 'test-token',
expiresOnTimestamp: 1234567890,
}),
getDeploymentDetails: jest.fn().mockResolvedValue({
apiVersion: '2023-05-15',
endpoint: 'https://test.openai.azure.com',
resourceName: 'test-resource',
}),
})),
}));
const mockNode: INode = {
id: '1',
name: 'Mock node',
typeVersion: 2,
type: 'n8n-nodes-base.mock',
position: [0, 0],
parameters: {},
};
describe('setupOAuth2Authentication', () => {
let mockCredential: AzureEntraCognitiveServicesOAuth2ApiCredential;
let ctx: ISupplyDataFunctions;
beforeEach(() => {
// Set up a mock credential
mockCredential = {
authQueryParameters: '',
authentication: 'body', // Set valid authentication type
authUrl: '',
accessTokenUrl: '', // Added missing property
grantType: 'clientCredentials', // Corrected grant type value
clientId: '',
customScopes: false,
apiVersion: '2023-05-15',
endpoint: 'https://test.openai.azure.com',
resourceName: 'test-resource',
oauthTokenData: {
access_token: 'test-token',
expires_on: 1234567890,
ext_expires_on: 0,
},
scope: '',
tenantId: '',
};
ctx = createMockExecuteFunction<ISupplyDataFunctions>({}, mockNode);
ctx.getCredentials = jest.fn().mockResolvedValue(mockCredential);
ctx.logger = {
debug: jest.fn(),
info: jest.fn(),
warn: jest.fn(),
error: jest.fn(),
};
});
afterEach(() => {
jest.clearAllMocks();
});
it('should return token provider and deployment details when successful', async () => {
// Act
const result = await setupOAuth2Authentication.call(ctx, 'testCredential');
// Assert
expect(result).toHaveProperty('azureADTokenProvider');
expect(typeof result.azureADTokenProvider).toBe('function');
expect(result).toEqual(
expect.objectContaining({
azureOpenAIApiInstanceName: 'test-resource',
azureOpenAIApiVersion: '2023-05-15',
azureOpenAIEndpoint: 'https://test.openai.azure.com',
}),
);
expect(ctx.getCredentials).toHaveBeenCalledWith('testCredential');
});
it('should throw NodeOperationError when credential retrieval fails', async () => {
// Arrange
const testError = new Error('Credential fetch failed');
ctx.getCredentials = jest.fn().mockRejectedValue(testError);
// Act & Assert
await expect(setupOAuth2Authentication.call(ctx, 'testCredential')).rejects.toThrow(
NodeOperationError,
);
});
});