Add coordinate validation and ESLint integration

- Add explicit latitude/longitude validation in location submissions
- Implement ESLint with TypeScript support and flat config
- Auto-fix 621 formatting issues across codebase
- Add comprehensive tests for coordinate validation
- Update documentation with lint scripts and validation rules
- Maintain 128 passing tests with enhanced security

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

Co-Authored-By: Claude <noreply@anthropic.com>
This commit is contained in:
Claude Code 2025-07-05 22:12:37 -04:00
parent 5176636f6d
commit 30fdd72cc5
20 changed files with 2171 additions and 599 deletions

View file

@ -138,7 +138,7 @@ describe('Location Model', () => {
// Check that we have all locations and they're ordered by created_at DESC
expect(allLocations).toHaveLength(3);
// The query uses ORDER BY created_at DESC, so the most recent should be first
// Since they're created in the same moment, check that ordering is consistent
expect(allLocations[0]).toHaveProperty('id');

View file

@ -5,7 +5,7 @@ describe('DatabaseService', () => {
beforeEach(() => {
databaseService = new DatabaseService();
// Mock console methods to reduce test noise
jest.spyOn(console, 'log').mockImplementation(() => {});
jest.spyOn(console, 'error').mockImplementation(() => {});
@ -88,7 +88,7 @@ describe('DatabaseService', () => {
it('should allow multiple instances', () => {
const service1 = new DatabaseService();
const service2 = new DatabaseService();
expect(service1).toBeInstanceOf(DatabaseService);
expect(service2).toBeInstanceOf(DatabaseService);
expect(service1).not.toBe(service2);

View file

@ -27,10 +27,10 @@ describe('ProfanityFilterService', () => {
it('should load custom words during initialization', async () => {
await profanityWordModel.create('customword', 'high', 'test');
const newFilter = new ProfanityFilterService(profanityWordModel);
await newFilter.initialize();
expect(newFilter.containsProfanity('customword')).toBe(true);
});
});
@ -50,7 +50,7 @@ describe('ProfanityFilterService', () => {
// Test basic profanity detection - may or may not be case insensitive
const testWord = 'damn';
expect(profanityFilter.containsProfanity(testWord)).toBe(true);
// Test with sentences containing profanity
expect(profanityFilter.containsProfanity('This is DAMN cold')).toBe(true);
expect(profanityFilter.containsProfanity('What the HELL')).toBe(true);
@ -104,7 +104,7 @@ describe('ProfanityFilterService', () => {
it('should determine severity levels correctly', () => {
const lowResult = profanityFilter.analyzeProfanity('damn');
const mediumResult = profanityFilter.analyzeProfanity('shit');
expect(lowResult.severity).toBe('low');
expect(mediumResult.severity).toBe('medium');
});
@ -164,7 +164,7 @@ describe('ProfanityFilterService', () => {
it('should remove custom words', async () => {
const added = await profanityFilter.addCustomWord('removeme', 'low', 'test');
const result = await profanityFilter.removeCustomWord(added.id);
expect(result.deleted).toBe(true);
@ -180,7 +180,7 @@ describe('ProfanityFilterService', () => {
it('should update custom words', async () => {
const added = await profanityFilter.addCustomWord('updateme', 'low', 'test');
const result = await profanityFilter.updateCustomWord(added.id, {
word: 'updated',
severity: 'high',
@ -208,14 +208,14 @@ describe('ProfanityFilterService', () => {
describe('text normalization', () => {
it('should normalize text correctly', () => {
const normalized = profanityFilter.normalizeText('Hello World!!!');
expect(typeof normalized).toBe('string');
expect(normalized.length).toBeGreaterThan(0);
});
it('should handle special characters', () => {
const normalized = profanityFilter.normalizeText('h3ll0 w0rld');
expect(normalized).toContain('hello world');
});
@ -228,13 +228,13 @@ describe('ProfanityFilterService', () => {
describe('severity and category helpers', () => {
it('should get severity for words', () => {
const severity = profanityFilter.getSeverity('damn');
expect(['low', 'medium', 'high']).toContain(severity);
});
it('should get category for words', () => {
const category = profanityFilter.getCategory('damn');
expect(typeof category).toBe('string');
expect(category.length).toBeGreaterThan(0);
});
@ -242,7 +242,7 @@ describe('ProfanityFilterService', () => {
it('should return default values for unknown words', () => {
const severity = profanityFilter.getSeverity('unknownword');
const category = profanityFilter.getCategory('unknownword');
expect(['low', 'medium', 'high']).toContain(severity);
expect(typeof category).toBe('string');
});
@ -251,26 +251,26 @@ describe('ProfanityFilterService', () => {
describe('utility methods', () => {
it('should get all words', () => {
const words = profanityFilter.getAllWords();
expect(Array.isArray(words)).toBe(true);
expect(words.length).toBeGreaterThan(0);
});
it('should get severity level as number', () => {
const level = profanityFilter.getSeverityLevel();
expect(typeof level).toBe('number');
});
it('should get severity name', () => {
const name = profanityFilter.getSeverityName();
expect(typeof name).toBe('string');
});
it('should have close method', () => {
expect(typeof profanityFilter.close).toBe('function');
// Should not throw
profanityFilter.close();
});