mirror of
https://github.com/n8n-io/n8n.git
synced 2025-02-21 02:56:40 -08:00
test: Add unit tests for CredentialsOverwrites (#13372)
This commit is contained in:
parent
ac1f651905
commit
b5e2f331cc
136
packages/cli/src/__tests__/credentials-overwrites.test.ts
Normal file
136
packages/cli/src/__tests__/credentials-overwrites.test.ts
Normal file
|
@ -0,0 +1,136 @@
|
|||
import type { GlobalConfig } from '@n8n/config';
|
||||
import { mock } from 'jest-mock-extended';
|
||||
import { UnrecognizedCredentialTypeError, type Logger } from 'n8n-core';
|
||||
import type { ICredentialType } from 'n8n-workflow';
|
||||
|
||||
import type { CredentialTypes } from '@/credential-types';
|
||||
import { CredentialsOverwrites } from '@/credentials-overwrites';
|
||||
|
||||
describe('CredentialsOverwrites', () => {
|
||||
const testCredentialType = mock<ICredentialType>({ name: 'test', extends: ['parent'] });
|
||||
const parentCredentialType = mock<ICredentialType>({ name: 'parent', extends: undefined });
|
||||
|
||||
const globalConfig = mock<GlobalConfig>({ credentials: { overwrite: {} } });
|
||||
const credentialTypes = mock<CredentialTypes>();
|
||||
const logger = mock<Logger>();
|
||||
let credentialsOverwrites: CredentialsOverwrites;
|
||||
|
||||
beforeEach(() => {
|
||||
jest.resetAllMocks();
|
||||
|
||||
globalConfig.credentials.overwrite.data = JSON.stringify({
|
||||
test: { username: 'user' },
|
||||
parent: { password: 'pass' },
|
||||
});
|
||||
credentialTypes.recognizes.mockReturnValue(true);
|
||||
credentialTypes.getByName.mockImplementation((credentialType) => {
|
||||
if (credentialType === testCredentialType.name) return testCredentialType;
|
||||
if (credentialType === parentCredentialType.name) return parentCredentialType;
|
||||
throw new UnrecognizedCredentialTypeError(credentialType);
|
||||
});
|
||||
credentialTypes.getParentTypes
|
||||
.calledWith(testCredentialType.name)
|
||||
.mockReturnValue([parentCredentialType.name]);
|
||||
|
||||
credentialsOverwrites = new CredentialsOverwrites(globalConfig, credentialTypes, logger);
|
||||
});
|
||||
|
||||
describe('constructor', () => {
|
||||
it('should parse and set overwrite data from config', () => {
|
||||
expect(credentialsOverwrites.getAll()).toEqual({
|
||||
parent: { password: 'pass' },
|
||||
test: {
|
||||
password: 'pass',
|
||||
username: 'user',
|
||||
},
|
||||
});
|
||||
});
|
||||
});
|
||||
|
||||
describe('setData', () => {
|
||||
it('should reset resolvedTypes when setting new data', () => {
|
||||
const newData = { test: { token: 'test-token' } };
|
||||
credentialsOverwrites.setData(newData);
|
||||
|
||||
expect(credentialsOverwrites.getAll()).toEqual(newData);
|
||||
});
|
||||
});
|
||||
|
||||
describe('applyOverwrite', () => {
|
||||
it('should apply overwrites only for empty fields', () => {
|
||||
const result = credentialsOverwrites.applyOverwrite('test', {
|
||||
username: 'existingUser',
|
||||
password: '',
|
||||
});
|
||||
|
||||
expect(result).toEqual({
|
||||
username: 'existingUser',
|
||||
password: 'pass',
|
||||
});
|
||||
});
|
||||
|
||||
it('should return original data if no overwrites exist', () => {
|
||||
const data = {
|
||||
username: 'user1',
|
||||
password: 'pass1',
|
||||
};
|
||||
|
||||
credentialTypes.getParentTypes.mockReturnValueOnce([]);
|
||||
|
||||
const result = credentialsOverwrites.applyOverwrite('unknownCredential', data);
|
||||
expect(result).toEqual(data);
|
||||
});
|
||||
});
|
||||
|
||||
describe('getOverwrites', () => {
|
||||
it('should return undefined for unrecognized credential type', () => {
|
||||
credentialTypes.recognizes.mockReturnValue(false);
|
||||
|
||||
const result = credentialsOverwrites.getOverwrites('unknownType');
|
||||
|
||||
expect(result).toBeUndefined();
|
||||
expect(logger.warn).toHaveBeenCalledWith(expect.stringContaining('Unknown credential type'));
|
||||
});
|
||||
|
||||
it('should cache resolved types', () => {
|
||||
credentialsOverwrites.getOverwrites('parent');
|
||||
const firstCall = credentialsOverwrites.getOverwrites('test');
|
||||
const secondCall = credentialsOverwrites.getOverwrites('test');
|
||||
|
||||
expect(firstCall).toEqual(secondCall);
|
||||
expect(credentialTypes.getByName).toHaveBeenCalledTimes(2);
|
||||
// eslint-disable-next-line @typescript-eslint/dot-notation
|
||||
expect(credentialsOverwrites['resolvedTypes']).toEqual(['parent', 'test']);
|
||||
});
|
||||
|
||||
it('should merge overwrites from parent types', () => {
|
||||
credentialTypes.getByName.mockImplementation((credentialType) => {
|
||||
if (credentialType === 'childType')
|
||||
return mock<ICredentialType>({ extends: ['parentType1', 'parentType2'] });
|
||||
if (credentialType === 'parentType1') return mock<ICredentialType>({ extends: undefined });
|
||||
if (credentialType === 'parentType2') return mock<ICredentialType>({ extends: undefined });
|
||||
throw new UnrecognizedCredentialTypeError(credentialType);
|
||||
});
|
||||
|
||||
globalConfig.credentials.overwrite.data = JSON.stringify({
|
||||
childType: { specificField: 'childValue' },
|
||||
parentType1: { parentField1: 'value1' },
|
||||
parentType2: { parentField2: 'value2' },
|
||||
});
|
||||
|
||||
const credentialsOverwrites = new CredentialsOverwrites(
|
||||
globalConfig,
|
||||
credentialTypes,
|
||||
logger,
|
||||
);
|
||||
|
||||
const result = credentialsOverwrites.getOverwrites('childType');
|
||||
|
||||
expect(result).toEqual({
|
||||
parentField1: 'value1',
|
||||
parentField2: 'value2',
|
||||
specificField: 'childValue',
|
||||
});
|
||||
});
|
||||
});
|
||||
});
|
|
@ -60,7 +60,7 @@ export class CredentialsOverwrites {
|
|||
return returnData;
|
||||
}
|
||||
|
||||
private getOverwrites(type: string): ICredentialDataDecryptedObject | undefined {
|
||||
getOverwrites(type: string): ICredentialDataDecryptedObject | undefined {
|
||||
if (this.resolvedTypes.includes(type)) {
|
||||
// Type got already resolved and can so returned directly
|
||||
return this.overwriteData[type];
|
||||
|
|
Loading…
Reference in a new issue