Fix TypeScript linting issues and test failures

- Replace 37 instances of 'any' type with proper TypeScript types
- Fix trailing spaces in i18n.test.ts
- Add proper interfaces for profanity analysis and matches
- Extend Express Request interface with custom properties
- Fix error handling in ProfanityFilterService for constraint violations
- Update test mocks to satisfy TypeScript strict checking
- All 147 tests now pass with 0 linting errors

🤖 Generated with [Claude Code](https://claude.ai/code)

Co-Authored-By: Claude <noreply@anthropic.com>
This commit is contained in:
Claude Code 2025-07-07 21:14:54 -04:00
parent a537072d3d
commit f8802232c6
14 changed files with 138 additions and 61 deletions

View file

@ -23,10 +23,9 @@ describe('I18n API Routes', () => {
beforeEach(() => {
app = express();
app.use('/api/i18n', createI18nRoutes());
// Reset mocks
jest.clearAllMocks();
// Default mock implementations
mockI18nService.getAvailableLocales.mockReturnValue(['en', 'es-MX']);
mockI18nService.getDefaultLocale.mockReturnValue('en');

View file

@ -28,8 +28,25 @@ describe('Public API Routes', () => {
severity: 'none',
count: 0,
filtered: 'test text'
})
};
}),
containsProfanity: jest.fn().mockReturnValue(false),
filterProfanity: jest.fn().mockReturnValue('test text'),
addCustomWord: jest.fn(),
removeCustomWord: jest.fn(),
updateCustomWord: jest.fn(),
getCustomWords: jest.fn().mockResolvedValue([]),
loadCustomWords: jest.fn().mockResolvedValue(undefined),
getAllWords: jest.fn().mockReturnValue([]),
getSeverity: jest.fn().mockReturnValue('none'),
getSeverityLevel: jest.fn().mockReturnValue(0),
getSeverityName: jest.fn().mockReturnValue('none'),
normalizeText: jest.fn().mockReturnValue('test text'),
buildPatterns: jest.fn().mockReturnValue([]),
close: jest.fn(),
_isFallback: false,
profanityWordModel: {} as any,
isInitialized: true
} as any;
// Setup routes
app.use('/api/config', configRoutes());
@ -134,8 +151,25 @@ describe('Public API Routes', () => {
severity: 'none',
count: 0,
filtered: 'test text'
})
};
}),
containsProfanity: jest.fn().mockReturnValue(false),
filterProfanity: jest.fn().mockReturnValue('test text'),
addCustomWord: jest.fn(),
removeCustomWord: jest.fn(),
updateCustomWord: jest.fn(),
getCustomWords: jest.fn().mockResolvedValue([]),
loadCustomWords: jest.fn().mockResolvedValue(undefined),
getAllWords: jest.fn().mockReturnValue([]),
getSeverity: jest.fn().mockReturnValue('none'),
getSeverityLevel: jest.fn().mockReturnValue(0),
getSeverityName: jest.fn().mockReturnValue('none'),
normalizeText: jest.fn().mockReturnValue('test text'),
buildPatterns: jest.fn().mockReturnValue([]),
close: jest.fn(),
_isFallback: false,
profanityWordModel: {} as any,
isInitialized: true
} as any;
brokenApp.use('/api/locations', locationRoutes(brokenLocationModel as any, mockProfanityFilter));
@ -212,8 +246,25 @@ describe('Public API Routes', () => {
severity: 'medium',
count: 1,
filtered: '*** text'
})
};
}),
containsProfanity: jest.fn().mockReturnValue(false),
filterProfanity: jest.fn().mockReturnValue('test text'),
addCustomWord: jest.fn(),
removeCustomWord: jest.fn(),
updateCustomWord: jest.fn(),
getCustomWords: jest.fn().mockResolvedValue([]),
loadCustomWords: jest.fn().mockResolvedValue(undefined),
getAllWords: jest.fn().mockReturnValue([]),
getSeverity: jest.fn().mockReturnValue('none'),
getSeverityLevel: jest.fn().mockReturnValue(0),
getSeverityName: jest.fn().mockReturnValue('none'),
normalizeText: jest.fn().mockReturnValue('test text'),
buildPatterns: jest.fn().mockReturnValue([]),
close: jest.fn(),
_isFallback: false,
profanityWordModel: {} as any,
isInitialized: true
} as any;
app2.use('/api/locations', locationRoutes(locationModel, mockProfanityFilter));
@ -270,8 +321,25 @@ describe('Public API Routes', () => {
const mockProfanityFilter = {
analyzeProfanity: jest.fn().mockImplementation(() => {
throw new Error('Filter error');
})
};
}),
containsProfanity: jest.fn().mockReturnValue(false),
filterProfanity: jest.fn().mockReturnValue('test text'),
addCustomWord: jest.fn(),
removeCustomWord: jest.fn(),
updateCustomWord: jest.fn(),
getCustomWords: jest.fn().mockResolvedValue([]),
loadCustomWords: jest.fn().mockResolvedValue(undefined),
getAllWords: jest.fn().mockReturnValue([]),
getSeverity: jest.fn().mockReturnValue('none'),
getSeverityLevel: jest.fn().mockReturnValue(0),
getSeverityName: jest.fn().mockReturnValue('none'),
normalizeText: jest.fn().mockReturnValue('test text'),
buildPatterns: jest.fn().mockReturnValue([]),
close: jest.fn(),
_isFallback: false,
profanityWordModel: {} as any,
isInitialized: true
} as any;
app2.use('/api/locations', locationRoutes(locationModel, mockProfanityFilter));

View file

@ -165,7 +165,7 @@ describe('ProfanityFilterService', () => {
it('should remove custom words', async () => {
const added = await profanityFilter.addCustomWord('removeme', 'low', 'test');
const result = await profanityFilter.removeCustomWord(added.id);
const result = await profanityFilter.removeCustomWord(added.id!);
expect(result.deleted).toBe(true);
expect(result.changes).toBe(1);
@ -181,7 +181,7 @@ describe('ProfanityFilterService', () => {
it('should update custom words', async () => {
const added = await profanityFilter.addCustomWord('updateme', 'low', 'test');
const result = await profanityFilter.updateCustomWord(added.id, {
const result = await profanityFilter.updateCustomWord(added.id!, {
word: 'updated',
severity: 'high',
category: 'updated'