fix: resolve TypeScript errors in test files

- Add type assertions for factory options arrays
- Add 'this' type annotations to mock functions
- Fix missing required properties in test objects
- Change Mock to MockInstance for Vitest compatibility
- Add non-null assertions where needed

All 943 tests now passing
This commit is contained in:
czlonkowski
2025-07-28 20:28:45 +02:00
parent d870d0ab71
commit 41c6a29b08
9 changed files with 549 additions and 40 deletions

499
coverage-report.json Normal file

File diff suppressed because one or more lines are too long

View File

@@ -61,7 +61,7 @@ export interface PropertyDefinition {
type: string; type: string;
default?: any; default?: any;
description?: string; description?: string;
options?: Array<{ name: string; value: string; description?: string }>; options?: Array<{ name: string; value: string; description?: string; action?: string; displayName?: string }> | any[];
required?: boolean; required?: boolean;
displayOptions?: { displayOptions?: {
show?: Record<string, any[]>; show?: Record<string, any[]>;
@@ -132,10 +132,10 @@ export const operationPropertyFactory = optionsPropertyFactory.params({
} }
}, },
options: [ options: [
{ name: 'Create', value: 'create', action: 'Create a user' }, { name: 'Create', value: 'create', action: 'Create a user' } as any,
{ name: 'Get', value: 'get', action: 'Get a user' }, { name: 'Get', value: 'get', action: 'Get a user' } as any,
{ name: 'Update', value: 'update', action: 'Update a user' }, { name: 'Update', value: 'update', action: 'Update a user' } as any,
{ name: 'Delete', value: 'delete', action: 'Delete a user' } { name: 'Delete', value: 'delete', action: 'Delete a user' } as any
] ]
}); });
@@ -144,8 +144,8 @@ export const collectionPropertyFactory = propertyFactory.params({
type: 'collection', type: 'collection',
default: {}, default: {},
options: [ options: [
stringPropertyFactory.build({ name: 'field1', displayName: 'Field 1' }), stringPropertyFactory.build({ name: 'field1', displayName: 'Field 1' }) as any,
numberPropertyFactory.build({ name: 'field2', displayName: 'Field 2' }) numberPropertyFactory.build({ name: 'field2', displayName: 'Field 2' }) as any
] ]
}); });
@@ -317,7 +317,7 @@ export const nestedPropertyFactory = Factory.define<PropertyDefinition>(() => ({
] ]
} }
] ]
}, } as any,
{ {
displayName: 'Query Parameters', displayName: 'Query Parameters',
name: 'queryParams', name: 'queryParams',
@@ -325,8 +325,8 @@ export const nestedPropertyFactory = Factory.define<PropertyDefinition>(() => ({
options: [ options: [
stringPropertyFactory.build({ name: 'key', displayName: 'Key' }), stringPropertyFactory.build({ name: 'key', displayName: 'Key' }),
stringPropertyFactory.build({ name: 'value', displayName: 'Value' }) stringPropertyFactory.build({ name: 'value', displayName: 'Value' })
] ] as any[]
} } as any
] ]
})); }));
@@ -371,7 +371,11 @@ export const versionedNodeTypeClassFactory = Factory.define<any>(({ params }) =>
currentVersion = baseDescription.defaultVersion; currentVersion = baseDescription.defaultVersion;
constructor() { constructor() {
this.constructor.name = 'VersionedNodeType'; Object.defineProperty(this.constructor, 'name', {
value: 'VersionedNodeType',
writable: false,
configurable: true
});
} }
}; };
}); });

View File

@@ -13,30 +13,31 @@ export class MockDatabase {
prepare(sql: string) { prepare(sql: string) {
const key = this.extractTableName(sql); const key = this.extractTableName(sql);
const self = this;
return { return {
all: vi.fn(() => this.data.get(key) || []), all: vi.fn(() => self.data.get(key) || []),
get: vi.fn((id: string) => { get: vi.fn((id: string) => {
const items = this.data.get(key) || []; const items = self.data.get(key) || [];
return items.find(item => item.id === id); return items.find(item => item.id === id);
}), }),
run: vi.fn((params: any) => { run: vi.fn((params: any) => {
const items = this.data.get(key) || []; const items = self.data.get(key) || [];
items.push(params); items.push(params);
this.data.set(key, items); self.data.set(key, items);
return { changes: 1, lastInsertRowid: items.length }; return { changes: 1, lastInsertRowid: items.length };
}), }),
iterate: vi.fn(function* () { iterate: vi.fn(function* () {
const items = this.data.get(key) || []; const items = self.data.get(key) || [];
for (const item of items) { for (const item of items) {
yield item; yield item;
} }
}), }),
pluck: vi.fn(function() { return this; }), pluck: vi.fn(function(this: any) { return this; }),
expand: vi.fn(function() { return this; }), expand: vi.fn(function(this: any) { return this; }),
raw: vi.fn(function() { return this; }), raw: vi.fn(function(this: any) { return this; }),
columns: vi.fn(() => []), columns: vi.fn(() => []),
bind: vi.fn(function() { return this; }) bind: vi.fn(function(this: any) { return this; })
}; };
} }

View File

@@ -65,11 +65,11 @@ describe('Database Adapter - Unit Tests', () => {
get: vi.fn(), get: vi.fn(),
all: vi.fn(() => []), all: vi.fn(() => []),
iterate: vi.fn(function* () {}), iterate: vi.fn(function* () {}),
pluck: vi.fn(function() { return this as any; }), pluck: vi.fn(function(this: any) { return this; }),
expand: vi.fn(function() { return this as any; }), expand: vi.fn(function(this: any) { return this; }),
raw: vi.fn(function() { return this as any; }), raw: vi.fn(function(this: any) { return this; }),
columns: vi.fn(() => []), columns: vi.fn(() => []),
bind: vi.fn(function() { return this as any; }) bind: vi.fn(function(this: any) { return this; })
}; };
expect(mockStmt).toBeDefined(); expect(mockStmt).toBeDefined();

View File

@@ -136,13 +136,14 @@ describe('TemplateRepository - Core Functionality', () => {
name: 'Test Workflow', name: 'Test Workflow',
description: 'A test workflow', description: 'A test workflow',
user: { user: {
id: 1,
name: 'John Doe', name: 'John Doe',
username: 'johndoe', username: 'johndoe',
verified: true verified: true
}, },
nodes: [ nodes: [
{ name: 'n8n-nodes-base.httpRequest', position: [0, 0] }, { id: 1, name: 'n8n-nodes-base.httpRequest', icon: 'fa:globe' },
{ name: 'n8n-nodes-base.slack', position: [100, 0] } { id: 2, name: 'n8n-nodes-base.slack', icon: 'fa:slack' }
], ],
totalViews: 1000, totalViews: 1000,
createdAt: '2024-01-01T00:00:00Z' createdAt: '2024-01-01T00:00:00Z'
@@ -150,6 +151,10 @@ describe('TemplateRepository - Core Functionality', () => {
const detail: TemplateDetail = { const detail: TemplateDetail = {
id: 123, id: 123,
name: 'Test Workflow',
description: 'A test workflow',
views: 1000,
createdAt: '2024-01-01T00:00:00Z',
workflow: { workflow: {
nodes: [], nodes: [],
connections: {}, connections: {},

View File

@@ -1,4 +1,4 @@
import { describe, it, expect, vi, beforeEach, afterEach, Mock } from 'vitest'; import { describe, it, expect, vi, beforeEach, afterEach, MockInstance } from 'vitest';
// Mock path module // Mock path module
vi.mock('path', async () => { vi.mock('path', async () => {
@@ -11,9 +11,9 @@ vi.mock('path', async () => {
describe('N8nNodeLoader', () => { describe('N8nNodeLoader', () => {
let N8nNodeLoader: any; let N8nNodeLoader: any;
let consoleLogSpy: Mock; let consoleLogSpy: MockInstance;
let consoleErrorSpy: Mock; let consoleErrorSpy: MockInstance;
let consoleWarnSpy: Mock; let consoleWarnSpy: MockInstance;
// Create mocks for require and require.resolve // Create mocks for require and require.resolve
const mockRequire = vi.fn(); const mockRequire = vi.fn();
@@ -31,7 +31,7 @@ describe('N8nNodeLoader', () => {
// Reset mocks // Reset mocks
mockRequire.mockReset(); mockRequire.mockReset();
mockRequireResolve.mockReset(); mockRequireResolve.mockReset();
mockRequire.resolve = mockRequireResolve; (mockRequire as any).resolve = mockRequireResolve;
// Default implementation for require.resolve // Default implementation for require.resolve
mockRequireResolve.mockImplementation((path: string) => path); mockRequireResolve.mockImplementation((path: string) => path);

View File

@@ -105,7 +105,7 @@ describe('DocsMapper', () => {
// Check that it eventually tried an index.md path // Check that it eventually tried an index.md path
expect(fs.readFile).toHaveBeenCalledTimes(6); expect(fs.readFile).toHaveBeenCalledTimes(6);
const calls = vi.mocked(fs.readFile).mock.calls; const calls = vi.mocked(fs.readFile).mock.calls;
const indexCalls = calls.filter(call => call[0].includes('index.md')); const indexCalls = calls.filter(call => (call[0] as string).includes('index.md'));
expect(indexCalls.length).toBeGreaterThan(0); expect(indexCalls.length).toBeGreaterThan(0);
}); });
}); });

View File

@@ -287,7 +287,7 @@ describe('n8nDocumentationToolsFinal', () => {
); );
toolsWithRequired.forEach(tool => { toolsWithRequired.forEach(tool => {
tool.inputSchema.required.forEach(requiredParam => { tool.inputSchema.required!.forEach(requiredParam => {
expect(tool.inputSchema.properties).toHaveProperty(requiredParam); expect(tool.inputSchema.properties).toHaveProperty(requiredParam);
}); });
}); });

View File

@@ -55,7 +55,7 @@ describe('SimpleParser', () => {
{ name: 'Create User', value: 'createUser' }, { name: 'Create User', value: 'createUser' },
{ name: 'Get User', value: 'getUser' } { name: 'Get User', value: 'getUser' }
] ]
}; } as any;
const NodeClass = nodeClassFactory.build({ description: nodeDefinition }); const NodeClass = nodeClassFactory.build({ description: nodeDefinition });
const result = parser.parse(NodeClass); const result = parser.parse(NodeClass);
@@ -89,7 +89,7 @@ describe('SimpleParser', () => {
options: [ options: [
{ name: 'Create', value: 'create' } { name: 'Create', value: 'create' }
] ]
}; } as any;
const NodeClass = nodeClassFactory.build({ description: nodeDefinition }); const NodeClass = nodeClassFactory.build({ description: nodeDefinition });
const result = parser.parse(NodeClass); const result = parser.parse(NodeClass);
@@ -102,7 +102,7 @@ describe('SimpleParser', () => {
const VersionedNodeClass = class VersionedNodeType { const VersionedNodeClass = class VersionedNodeType {
baseDescription = versionedDef.baseDescription; baseDescription = versionedDef.baseDescription;
nodeVersions = versionedDef.nodeVersions; nodeVersions = versionedDef.nodeVersions;
currentVersion = versionedDef.baseDescription.defaultVersion; currentVersion = versionedDef.baseDescription!.defaultVersion;
constructor() { constructor() {
Object.defineProperty(this.constructor, 'name', { Object.defineProperty(this.constructor, 'name', {
@@ -115,9 +115,9 @@ describe('SimpleParser', () => {
const result = parser.parse(VersionedNodeClass); const result = parser.parse(VersionedNodeClass);
expect(result.isVersioned).toBe(true); expect(result.isVersioned).toBe(true);
expect(result.nodeType).toBe(versionedDef.baseDescription.name); expect(result.nodeType).toBe(versionedDef.baseDescription!.name);
expect(result.displayName).toBe(versionedDef.baseDescription.displayName); expect(result.displayName).toBe(versionedDef.baseDescription!.displayName);
expect(result.version).toBe(versionedDef.baseDescription.defaultVersion.toString()); expect(result.version).toBe(versionedDef.baseDescription!.defaultVersion.toString());
}); });
it('should merge baseDescription with version-specific description', () => { it('should merge baseDescription with version-specific description', () => {
@@ -305,7 +305,7 @@ describe('SimpleParser', () => {
options: [ options: [
{ name: 'Create', value: 'create' }, { name: 'Create', value: 'create' },
{ name: 'Get', value: 'get' } { name: 'Get', value: 'get' }
] ] as any
}; };
const NodeClass = nodeClassFactory.build({ description: nodeDefinition }); const NodeClass = nodeClassFactory.build({ description: nodeDefinition });