code quality

This commit is contained in:
2026-01-26 01:36:22 +01:00
parent f06a00da1b
commit 49cc91e046
23 changed files with 68 additions and 54 deletions

View File

@@ -521,7 +521,9 @@
],
"parserOptions": {
"ecmaVersion": 2022,
"sourceType": "module"
"sourceType": "module",
"project": "./tsconfig.eslint.json",
"tsconfigRootDir": "."
},
"settings": {
"boundaries/elements": [

File diff suppressed because one or more lines are too long

View File

@@ -8,13 +8,13 @@
*/
import { describe, it, expect, vi, beforeEach } from 'vitest';
import type { Mock } from 'vitest';
import { GetDashboardUseCase } from './GetDashboardUseCase';
import { ValidationError } from '../../../shared/errors/ValidationError';
import { DriverNotFoundError } from '../../domain/errors/DriverNotFoundError';
import { DashboardRepository } from '../ports/DashboardRepository';
import { DashboardRepository, DriverData, RaceData } from '../ports/DashboardRepository';
import { DashboardEventPublisher } from '../ports/DashboardEventPublisher';
import { Logger } from '../../../shared/domain/Logger';
import { DriverData, RaceData, LeagueStandingData, ActivityData } from '../ports/DashboardRepository';
describe('GetDashboardUseCase', () => {
let mockDriverRepository: DashboardRepository;
@@ -120,7 +120,7 @@ describe('GetDashboardUseCase', () => {
it('should throw DriverNotFoundError when driverRepository.findDriverById returns null', async () => {
// Given
const query = { driverId: 'driver-123' };
(mockDriverRepository.findDriverById as any).mockResolvedValue(null);
(mockDriverRepository.findDriverById as Mock).mockResolvedValue(null);
// When & Then
await expect(useCase.execute(query)).rejects.toThrow(DriverNotFoundError);
@@ -143,7 +143,7 @@ describe('GetDashboardUseCase', () => {
const query = { driverId: 'driver-123' };
// Mock driver exists
(mockDriverRepository.findDriverById as any).mockResolvedValue({
(mockDriverRepository.findDriverById as Mock).mockResolvedValue({
id: 'driver-123',
name: 'Test Driver',
rating: 1500,
@@ -155,7 +155,7 @@ describe('GetDashboardUseCase', () => {
} as DriverData);
// Mock races with missing trackName
(mockRaceRepository.getUpcomingRaces as any).mockResolvedValue([
(mockRaceRepository.getUpcomingRaces as Mock).mockResolvedValue([
{
id: 'race-1',
trackName: '', // Missing trackName
@@ -170,8 +170,8 @@ describe('GetDashboardUseCase', () => {
},
] as RaceData[]);
(mockLeagueRepository.getLeagueStandings as any).mockResolvedValue([]);
(mockActivityRepository.getRecentActivity as any).mockResolvedValue([]);
(mockLeagueRepository.getLeagueStandings as Mock).mockResolvedValue([]);
(mockActivityRepository.getRecentActivity as Mock).mockResolvedValue([]);
// When
const result = await useCase.execute(query);
@@ -186,7 +186,7 @@ describe('GetDashboardUseCase', () => {
const query = { driverId: 'driver-123' };
// Mock driver exists
(mockDriverRepository.findDriverById as any).mockResolvedValue({
(mockDriverRepository.findDriverById as Mock).mockResolvedValue({
id: 'driver-123',
name: 'Test Driver',
rating: 1500,
@@ -198,7 +198,7 @@ describe('GetDashboardUseCase', () => {
} as DriverData);
// Mock races with past dates
(mockRaceRepository.getUpcomingRaces as any).mockResolvedValue([
(mockRaceRepository.getUpcomingRaces as Mock).mockResolvedValue([
{
id: 'race-1',
trackName: 'Track A',
@@ -213,8 +213,8 @@ describe('GetDashboardUseCase', () => {
},
] as RaceData[]);
(mockLeagueRepository.getLeagueStandings as any).mockResolvedValue([]);
(mockActivityRepository.getRecentActivity as any).mockResolvedValue([]);
(mockLeagueRepository.getLeagueStandings as Mock).mockResolvedValue([]);
(mockActivityRepository.getRecentActivity as Mock).mockResolvedValue([]);
// When
const result = await useCase.execute(query);
@@ -229,7 +229,7 @@ describe('GetDashboardUseCase', () => {
const query = { driverId: 'driver-123' };
// Mock driver exists
(mockDriverRepository.findDriverById as any).mockResolvedValue({
(mockDriverRepository.findDriverById as Mock).mockResolvedValue({
id: 'driver-123',
name: 'Test Driver',
rating: 1500,
@@ -241,7 +241,7 @@ describe('GetDashboardUseCase', () => {
} as DriverData);
// Mock races with various invalid states
(mockRaceRepository.getUpcomingRaces as any).mockResolvedValue([
(mockRaceRepository.getUpcomingRaces as Mock).mockResolvedValue([
{
id: 'race-1',
trackName: '', // Missing trackName
@@ -262,8 +262,8 @@ describe('GetDashboardUseCase', () => {
},
] as RaceData[]);
(mockLeagueRepository.getLeagueStandings as any).mockResolvedValue([]);
(mockActivityRepository.getRecentActivity as any).mockResolvedValue([]);
(mockLeagueRepository.getLeagueStandings as Mock).mockResolvedValue([]);
(mockActivityRepository.getRecentActivity as Mock).mockResolvedValue([]);
// When
const result = await useCase.execute(query);
@@ -278,7 +278,7 @@ describe('GetDashboardUseCase', () => {
const query = { driverId: 'driver-123' };
// Mock driver exists
(mockDriverRepository.findDriverById as any).mockResolvedValue({
(mockDriverRepository.findDriverById as Mock).mockResolvedValue({
id: 'driver-123',
name: 'Test Driver',
rating: 1500,
@@ -290,7 +290,7 @@ describe('GetDashboardUseCase', () => {
} as DriverData);
// Mock races with valid data
(mockRaceRepository.getUpcomingRaces as any).mockResolvedValue([
(mockRaceRepository.getUpcomingRaces as Mock).mockResolvedValue([
{
id: 'race-1',
trackName: 'Track A',
@@ -305,8 +305,8 @@ describe('GetDashboardUseCase', () => {
},
] as RaceData[]);
(mockLeagueRepository.getLeagueStandings as any).mockResolvedValue([]);
(mockActivityRepository.getRecentActivity as any).mockResolvedValue([]);
(mockLeagueRepository.getLeagueStandings as Mock).mockResolvedValue([]);
(mockActivityRepository.getRecentActivity as Mock).mockResolvedValue([]);
// When
const result = await useCase.execute(query);

View File

@@ -5,7 +5,7 @@
*/
import { beforeEach, describe, expect, it, vi } from 'vitest';
import { CheckApiHealthUseCase, CheckApiHealthUseCasePorts } from './CheckApiHealthUseCase';
import { CheckApiHealthUseCase } from './CheckApiHealthUseCase';
import { HealthCheckQuery, HealthCheckResult } from '../ports/HealthCheckQuery';
import { HealthEventPublisher } from '../ports/HealthEventPublisher';

View File

@@ -5,7 +5,7 @@
* This Use Case orchestrates the retrieval of connection status information.
*/
import { HealthCheckQuery, ConnectionHealth, ConnectionStatus } from '../ports/HealthCheckQuery';
import { HealthCheckQuery, ConnectionStatus } from '../ports/HealthCheckQuery';
export interface GetConnectionStatusUseCasePorts {
healthCheckAdapter: HealthCheckQuery;

View File

@@ -4,7 +4,7 @@
import { describe, it, expect, vi, beforeEach } from 'vitest';
import { GetUserRatingLedgerQueryHandler } from './GetUserRatingLedgerQuery';
import { RatingEventRepository } from '../../domain/repositories/RatingEventRepository';
import { RatingEventRepository, RatingEventFilter } from '../../domain/repositories/RatingEventRepository';
// Mock repository
const createMockRepository = () => ({

View File

@@ -6,8 +6,6 @@
import { describe, it, expect, vi, beforeEach } from 'vitest';
import { CastAdminVoteUseCase } from './CastAdminVoteUseCase';
import { AdminVoteSessionRepository } from '../../domain/repositories/AdminVoteSessionRepository';
import { AdminVoteSession } from '../../domain/entities/AdminVoteSession';
// Mock repository
const createMockRepository = () => ({
@@ -55,7 +53,7 @@ describe('CastAdminVoteUseCase', () => {
const result = await useCase.execute({
voteSessionId: 'session-123',
voterId: 'voter-123',
positive: 'true' as any,
positive: 'true' as unknown as boolean,
});
expect(result.success).toBe(false);

View File

@@ -1,6 +1,6 @@
import { LeagueRepository } from '../ports/LeagueRepository';
import { DriverRepository } from '../ports/DriverRepository';
import { EventPublisher } from '../ports/EventPublisher';
import { DriverRepository } from '../../../racing/domain/repositories/DriverRepository';
import { EventPublisher } from '../../../shared/ports/EventPublisher';
import { ApproveMembershipRequestCommand } from '../ports/ApproveMembershipRequestCommand';
export class ApproveMembershipRequestUseCase {

View File

@@ -1,5 +1,5 @@
import { LeagueRepository } from '../ports/LeagueRepository';
import { DriverRepository } from '../ports/DriverRepository';
import { DriverRepository } from '../../../racing/domain/repositories/DriverRepository';
import { LeagueEventPublisher } from '../ports/LeagueEventPublisher';
import { DemoteAdminCommand } from '../ports/DemoteAdminCommand';

View File

@@ -1,6 +1,6 @@
import { LeagueRepository, LeagueData } from '../ports/LeagueRepository';
import { DriverRepository } from '../ports/DriverRepository';
import { EventPublisher } from '../ports/EventPublisher';
import { DriverRepository } from '../../../racing/domain/repositories/DriverRepository';
import { EventPublisher } from '../../../shared/ports/EventPublisher';
import { JoinLeagueCommand } from '../ports/JoinLeagueCommand';
export class JoinLeagueUseCase {
@@ -16,7 +16,7 @@ export class JoinLeagueUseCase {
throw new Error('League not found');
}
const driver = await this.driverRepository.findDriverById(command.driverId);
const driver = await this.driverRepository.findById(command.driverId);
if (!driver) {
throw new Error('Driver not found');
}
@@ -26,7 +26,7 @@ export class JoinLeagueUseCase {
{
id: `request-${Date.now()}`,
driverId: command.driverId,
name: driver.name,
name: driver.name.toString(),
requestDate: new Date(),
},
]);
@@ -34,7 +34,7 @@ export class JoinLeagueUseCase {
await this.leagueRepository.addLeagueMembers(command.leagueId, [
{
driverId: command.driverId,
name: driver.name,
name: driver.name.toString(),
role: 'member',
joinDate: new Date(),
},

View File

@@ -1,6 +1,6 @@
import { LeagueRepository } from '../ports/LeagueRepository';
import { DriverRepository } from '../ports/DriverRepository';
import { EventPublisher } from '../ports/EventPublisher';
import { DriverRepository } from '../../../racing/domain/repositories/DriverRepository';
import { EventPublisher } from '../../../shared/ports/EventPublisher';
import { LeaveLeagueCommand } from '../ports/LeaveLeagueCommand';
export class LeaveLeagueUseCase {

View File

@@ -1,6 +1,6 @@
import { LeagueRepository } from '../ports/LeagueRepository';
import { DriverRepository } from '../ports/DriverRepository';
import { EventPublisher } from '../ports/EventPublisher';
import { DriverRepository } from '../../../racing/domain/repositories/DriverRepository';
import { EventPublisher } from '../../../shared/ports/EventPublisher';
import { PromoteMemberCommand } from '../ports/PromoteMemberCommand';
export class PromoteMemberUseCase {

View File

@@ -1,5 +1,5 @@
import { LeagueRepository } from '../ports/LeagueRepository';
import { DriverRepository } from '../ports/DriverRepository';
import { DriverRepository } from '../../../racing/domain/repositories/DriverRepository';
import { LeagueEventPublisher } from '../ports/LeagueEventPublisher';
import { RejectMembershipRequestCommand } from '../ports/RejectMembershipRequestCommand';

View File

@@ -1,6 +1,6 @@
import { LeagueRepository } from '../ports/LeagueRepository';
import { DriverRepository } from '../ports/DriverRepository';
import { EventPublisher } from '../ports/EventPublisher';
import { DriverRepository } from '../../../racing/domain/repositories/DriverRepository';
import { EventPublisher } from '../../../shared/ports/EventPublisher';
import { RemoveMemberCommand } from '../ports/RemoveMemberCommand';
export class RemoveMemberUseCase {

View File

@@ -180,6 +180,7 @@ export class CompleteRaceUseCase {
startPosition,
fastestLap,
incidents,
points: 0,
}),
);
}

View File

@@ -16,6 +16,7 @@ export type ImportRaceResultDTO = {
fastestLap: number;
incidents: number;
startPosition: number;
points: number;
};
export type ImportRaceResultsApiInput = {
@@ -145,6 +146,7 @@ export class ImportRaceResultsApiUseCase {
fastestLap: dto.fastestLap,
incidents: dto.incidents,
startPosition: dto.startPosition,
points: dto.points,
}),
);
}),

View File

@@ -15,6 +15,7 @@ export type ImportRaceResultRow = {
fastestLap: number;
incidents: number;
startPosition: number;
points: number;
};
export type ImportRaceResultsInput = {
@@ -127,6 +128,7 @@ export class ImportRaceResultsUseCase {
fastestLap: row.fastestLap,
incidents: row.incidents,
startPosition: row.startPosition,
points: row.points,
}),
);
}),

View File

@@ -62,6 +62,7 @@ export class RaceResultGenerator {
startPosition,
fastestLap,
incidents,
points: 0,
})
);
}

View File

@@ -294,7 +294,7 @@ describe('Result', () => {
it('should stop chaining on first error', () => {
const result = Result.ok(2)
.andThen((x) => Result.ok(x * 3))
.andThen((x) => Result.err(new Error('stopped here')))
.andThen((x) => Result.err(new Error(`stopped at ${x}`)))
.andThen((x) => Result.ok(x + 1)); // This should not execute
expect(result.isErr()).toBe(true);

View File

@@ -36,14 +36,14 @@ describe('ValueObject', () => {
it('should return false when comparing with undefined', () => {
const vo = new TestValueObject('test', 42);
// Testing that equals method handles undefined gracefully
const result = vo.equals as any;
const result = vo.equals as (other: unknown) => boolean;
expect(result(undefined)).toBe(false);
});
it('should return false when comparing with null', () => {
const vo = new TestValueObject('test', 42);
// Testing that equals method handles null gracefully
const result = vo.equals as any;
const result = vo.equals as (other: unknown) => boolean;
expect(result(null)).toBe(false);
});
});

View File

@@ -1,7 +0,0 @@
export * from './DomainEvent';
export * from './Entity';
export * from './Logger';
export * from './Option';
export * from './Result';
export * from './Service';
export * from './ValueObject';

View File

@@ -92,16 +92,16 @@ describe('ApplicationErrorCode', () => {
// This test verifies the type compatibility
type MyErrorCodes = 'USER_NOT_FOUND' | 'VALIDATION_ERROR' | 'PERMISSION_DENIED';
const userNotFound: ApplicationErrorCode<'USER_NOT_FOUND'> = {
const userNotFound: ApplicationErrorCode<MyErrorCodes> = {
code: 'USER_NOT_FOUND'
};
const validationError: ApplicationErrorCode<'VALIDATION_ERROR', { field: string }> = {
const validationError: ApplicationErrorCode<MyErrorCodes, { field: string }> = {
code: 'VALIDATION_ERROR',
details: { field: 'email' }
};
const permissionError: ApplicationErrorCode<'PERMISSION_DENIED', { resource: string }> = {
const permissionError: ApplicationErrorCode<MyErrorCodes, { resource: string }> = {
code: 'PERMISSION_DENIED',
details: { resource: 'admin-panel' }
};

14
tsconfig.eslint.json Normal file
View File

@@ -0,0 +1,14 @@
{
"extends": "./tsconfig.base.json",
"compilerOptions": {
"baseUrl": ".",
"paths": {
"@/*": ["apps/website/*"],
"@core/*": ["core/*"],
"@adapters/*": ["adapters/*"],
"@testing/*": ["adapters/testing/*"]
}
},
"include": ["**/*"],
"exclude": ["node_modules", "dist", "**/dist/**", "**/.next/**"]
}