fix: resolve LRU cache test failures in CI

- Fix module resolution by adding proper vi.mock() for instance-context
- Fix mock call count by ensuring all test contexts have valid API keys
- Improve test isolation with vi.clearAllMocks() in beforeEach
- Use mockReturnValueOnce() for single-use validation mocks
- All 17 LRU cache tests now pass consistently
This commit is contained in:
czlonkowski
2025-09-19 20:20:52 +02:00
parent a5ac4297bc
commit 7e76369d2a

View File

@@ -8,7 +8,7 @@ import { describe, it, expect, beforeEach, afterEach, vi, Mock } from 'vitest';
import { LRUCache } from 'lru-cache'; import { LRUCache } from 'lru-cache';
import { createHash } from 'crypto'; import { createHash } from 'crypto';
import { getN8nApiClient } from '../../../src/mcp/handlers-n8n-manager'; import { getN8nApiClient } from '../../../src/mcp/handlers-n8n-manager';
import { InstanceContext } from '../../../src/types/instance-context'; import { InstanceContext, validateInstanceContext } from '../../../src/types/instance-context';
import { N8nApiClient } from '../../../src/services/n8n-api-client'; import { N8nApiClient } from '../../../src/services/n8n-api-client';
import { getN8nApiConfigFromContext } from '../../../src/config/n8n-api'; import { getN8nApiConfigFromContext } from '../../../src/config/n8n-api';
import { logger } from '../../../src/utils/logger'; import { logger } from '../../../src/utils/logger';
@@ -17,19 +17,29 @@ import { logger } from '../../../src/utils/logger';
vi.mock('../../../src/services/n8n-api-client'); vi.mock('../../../src/services/n8n-api-client');
vi.mock('../../../src/config/n8n-api'); vi.mock('../../../src/config/n8n-api');
vi.mock('../../../src/utils/logger'); vi.mock('../../../src/utils/logger');
vi.mock('../../../src/types/instance-context', async () => {
const actual = await vi.importActual('../../../src/types/instance-context');
return {
...actual,
validateInstanceContext: vi.fn()
};
});
describe('LRU Cache Behavior Tests', () => { describe('LRU Cache Behavior Tests', () => {
let mockN8nApiClient: Mock; let mockN8nApiClient: Mock;
let mockGetN8nApiConfigFromContext: Mock; let mockGetN8nApiConfigFromContext: Mock;
let mockLogger: Mock; let mockLogger: Mock;
let mockValidateInstanceContext: Mock;
beforeEach(() => { beforeEach(() => {
vi.resetAllMocks(); vi.resetAllMocks();
vi.resetModules(); vi.resetModules();
vi.clearAllMocks();
mockN8nApiClient = vi.mocked(N8nApiClient); mockN8nApiClient = vi.mocked(N8nApiClient);
mockGetN8nApiConfigFromContext = vi.mocked(getN8nApiConfigFromContext); mockGetN8nApiConfigFromContext = vi.mocked(getN8nApiConfigFromContext);
mockLogger = vi.mocked(logger); mockLogger = vi.mocked(logger);
mockValidateInstanceContext = vi.mocked(validateInstanceContext);
// Default mock returns valid config // Default mock returns valid config
mockGetN8nApiConfigFromContext.mockReturnValue({ mockGetN8nApiConfigFromContext.mockReturnValue({
@@ -38,6 +48,15 @@ describe('LRU Cache Behavior Tests', () => {
timeout: 30000, timeout: 30000,
maxRetries: 3 maxRetries: 3
}); });
// Default mock returns valid context validation
mockValidateInstanceContext.mockReturnValue({
valid: true,
errors: undefined
});
// Force re-import of the module to get fresh cache state
vi.resetModules();
}); });
afterEach(() => { afterEach(() => {
@@ -92,7 +111,7 @@ describe('LRU Cache Behavior Tests', () => {
}); });
it('should handle potential cache key collisions gracefully', () => { it('should handle potential cache key collisions gracefully', () => {
// Create contexts that might produce similar hashes // Create contexts that might produce similar hashes but are valid
const contexts = [ const contexts = [
{ {
n8nApiUrl: 'https://a.com', n8nApiUrl: 'https://a.com',
@@ -106,7 +125,7 @@ describe('LRU Cache Behavior Tests', () => {
}, },
{ {
n8nApiUrl: 'https://abc.com', n8nApiUrl: 'https://abc.com',
n8nApiKey: '', n8nApiKey: 'differentkey', // Fixed: empty string causes config creation to fail
instanceId: 'key' instanceId: 'key'
} }
]; ];
@@ -353,6 +372,10 @@ describe('LRU Cache Behavior Tests', () => {
describe('Cache Interaction with Validation', () => { describe('Cache Interaction with Validation', () => {
it('should not cache when context validation fails', () => { it('should not cache when context validation fails', () => {
// Reset mocks to ensure clean state for this test
vi.clearAllMocks();
mockValidateInstanceContext.mockClear();
const invalidContext: InstanceContext = { const invalidContext: InstanceContext = {
n8nApiUrl: 'invalid-url', n8nApiUrl: 'invalid-url',
n8nApiKey: 'test-key', n8nApiKey: 'test-key',
@@ -360,8 +383,7 @@ describe('LRU Cache Behavior Tests', () => {
}; };
// Mock validation failure // Mock validation failure
const { validateInstanceContext } = require('../../../src/types/instance-context'); mockValidateInstanceContext.mockReturnValue({
vi.mocked(validateInstanceContext).mockReturnValue({
valid: false, valid: false,
errors: ['Invalid n8nApiUrl format'] errors: ['Invalid n8nApiUrl format']
}); });
@@ -391,6 +413,16 @@ describe('LRU Cache Behavior Tests', () => {
describe('Complex Cache Scenarios', () => { describe('Complex Cache Scenarios', () => {
it('should handle mixed valid and invalid contexts', () => { it('should handle mixed valid and invalid contexts', () => {
// Reset mocks to ensure clean state for this test
vi.clearAllMocks();
mockValidateInstanceContext.mockClear();
// First, set up default valid behavior
mockValidateInstanceContext.mockReturnValue({
valid: true,
errors: undefined
});
const validContext: InstanceContext = { const validContext: InstanceContext = {
n8nApiUrl: 'https://api.n8n.cloud', n8nApiUrl: 'https://api.n8n.cloud',
n8nApiKey: 'valid-key', n8nApiKey: 'valid-key',
@@ -407,9 +439,8 @@ describe('LRU Cache Behavior Tests', () => {
const validClient = getN8nApiClient(validContext); const validClient = getN8nApiClient(validContext);
expect(validClient).toBeDefined(); expect(validClient).toBeDefined();
// Invalid context should return null // Change mock for invalid context
const { validateInstanceContext } = require('../../../src/types/instance-context'); mockValidateInstanceContext.mockReturnValueOnce({
vi.mocked(validateInstanceContext).mockReturnValue({
valid: false, valid: false,
errors: ['Invalid URL'] errors: ['Invalid URL']
}); });
@@ -417,6 +448,12 @@ describe('LRU Cache Behavior Tests', () => {
const invalidClient = getN8nApiClient(invalidContext); const invalidClient = getN8nApiClient(invalidContext);
expect(invalidClient).toBeNull(); expect(invalidClient).toBeNull();
// Reset mock back to valid for subsequent calls
mockValidateInstanceContext.mockReturnValue({
valid: true,
errors: undefined
});
// Valid context should still work (cache hit) // Valid context should still work (cache hit)
const validClient2 = getN8nApiClient(validContext); const validClient2 = getN8nApiClient(validContext);
expect(validClient2).toBe(validClient); expect(validClient2).toBe(validClient);