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
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:
+125
@@ -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',
|
||||
});
|
||||
});
|
||||
});
|
||||
});
|
||||
+81
@@ -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,
|
||||
);
|
||||
});
|
||||
});
|
||||
+98
@@ -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,
|
||||
);
|
||||
});
|
||||
});
|
||||
Reference in New Issue
Block a user