Files
gridpilot.gg/apps/api/src/domain/auth/AuthService.new.test.ts
2026-01-03 02:42:47 +01:00

253 lines
9.0 KiB
TypeScript

import { describe, expect, it, vi } from 'vitest';
import { AuthService } from './AuthService';
import { Result } from '@core/shared/application/Result';
class FakeAuthSessionPresenter {
private model: any = null;
reset() { this.model = null; }
present(model: any) { this.model = model; }
get responseModel() {
if (!this.model) throw new Error('Presenter not presented');
return this.model;
}
}
class FakeCommandResultPresenter {
private model: any = null;
reset() { this.model = null; }
present(model: any) { this.model = model; }
get responseModel() {
if (!this.model) throw new Error('Presenter not presented');
return this.model;
}
}
class FakeForgotPasswordPresenter {
private model: any = null;
reset() { this.model = null; }
present(model: any) { this.model = model; }
get responseModel() {
if (!this.model) throw new Error('Presenter not presented');
return this.model;
}
}
class FakeResetPasswordPresenter {
private model: any = null;
reset() { this.model = null; }
present(model: any) { this.model = model; }
get responseModel() {
if (!this.model) throw new Error('Presenter not presented');
return this.model;
}
}
class FakeDemoLoginPresenter {
private model: any = null;
reset() { this.model = null; }
present(model: any) { this.model = model; }
get responseModel() {
if (!this.model) throw new Error('Presenter not presented');
return this.model;
}
}
describe('AuthService - New Methods', () => {
describe('forgotPassword', () => {
it('should execute forgot password use case and return result', async () => {
const forgotPasswordPresenter = new FakeForgotPasswordPresenter();
const forgotPasswordUseCase = {
execute: vi.fn(async () => {
forgotPasswordPresenter.present({ message: 'Reset link sent', magicLink: 'http://example.com/reset?token=abc123' });
return Result.ok(undefined);
}),
};
const service = new AuthService(
{ debug: vi.fn(), info: vi.fn(), warn: vi.fn(), error: vi.fn() } as any,
{ getCurrentSession: vi.fn(), createSession: vi.fn() } as any,
{ execute: vi.fn() } as any,
{ execute: vi.fn() } as any,
{ execute: vi.fn() } as any,
forgotPasswordUseCase as any,
{ execute: vi.fn() } as any,
{ execute: vi.fn() } as any,
new FakeAuthSessionPresenter() as any,
new FakeCommandResultPresenter() as any,
forgotPasswordPresenter as any,
new FakeResetPasswordPresenter() as any,
new FakeDemoLoginPresenter() as any,
);
const result = await service.forgotPassword({ email: 'test@example.com' });
expect(forgotPasswordUseCase.execute).toHaveBeenCalledWith({ email: 'test@example.com' });
expect(result).toEqual({
message: 'Reset link sent',
magicLink: 'http://example.com/reset?token=abc123',
});
});
it('should throw error on use case failure', async () => {
const service = new AuthService(
{ debug: vi.fn(), info: vi.fn(), warn: vi.fn(), error: vi.fn() } as any,
{ getCurrentSession: vi.fn(), createSession: vi.fn() } as any,
{ execute: vi.fn() } as any,
{ execute: vi.fn() } as any,
{ execute: vi.fn() } as any,
{ execute: vi.fn(async () => Result.err({ code: 'RATE_LIMIT_EXCEEDED', details: { message: 'Too many attempts' } })) } as any,
{ execute: vi.fn() } as any,
{ execute: vi.fn() } as any,
new FakeAuthSessionPresenter() as any,
new FakeCommandResultPresenter() as any,
new FakeForgotPasswordPresenter() as any,
new FakeResetPasswordPresenter() as any,
new FakeDemoLoginPresenter() as any,
);
await expect(service.forgotPassword({ email: 'test@example.com' })).rejects.toThrow('Too many attempts');
});
});
describe('resetPassword', () => {
it('should execute reset password use case and return result', async () => {
const resetPasswordPresenter = new FakeResetPasswordPresenter();
const resetPasswordUseCase = {
execute: vi.fn(async () => {
resetPasswordPresenter.present({ message: 'Password reset successfully' });
return Result.ok(undefined);
}),
};
const service = new AuthService(
{ debug: vi.fn(), info: vi.fn(), warn: vi.fn(), error: vi.fn() } as any,
{ getCurrentSession: vi.fn(), createSession: vi.fn() } as any,
{ execute: vi.fn() } as any,
{ execute: vi.fn() } as any,
{ execute: vi.fn() } as any,
{ execute: vi.fn() } as any,
resetPasswordUseCase as any,
{ execute: vi.fn() } as any,
new FakeAuthSessionPresenter() as any,
new FakeCommandResultPresenter() as any,
new FakeForgotPasswordPresenter() as any,
resetPasswordPresenter as any,
new FakeDemoLoginPresenter() as any,
);
const result = await service.resetPassword({
token: 'abc123',
newPassword: 'NewPass123!',
});
expect(resetPasswordUseCase.execute).toHaveBeenCalledWith({
token: 'abc123',
newPassword: 'NewPass123!',
});
expect(result).toEqual({ message: 'Password reset successfully' });
});
it('should throw error on use case failure', async () => {
const service = new AuthService(
{ debug: vi.fn(), info: vi.fn(), warn: vi.fn(), error: vi.fn() } as any,
{ getCurrentSession: vi.fn(), createSession: vi.fn() } as any,
{ execute: vi.fn() } as any,
{ execute: vi.fn() } as any,
{ execute: vi.fn() } as any,
{ execute: vi.fn() } as any,
{ execute: vi.fn(async () => Result.err({ code: 'INVALID_TOKEN', details: { message: 'Invalid token' } })) } as any,
{ execute: vi.fn() } as any,
new FakeAuthSessionPresenter() as any,
new FakeCommandResultPresenter() as any,
new FakeForgotPasswordPresenter() as any,
new FakeResetPasswordPresenter() as any,
new FakeDemoLoginPresenter() as any,
);
await expect(
service.resetPassword({ token: 'invalid', newPassword: 'NewPass123!' })
).rejects.toThrow('Invalid token');
});
});
describe('demoLogin', () => {
it('should execute demo login use case and create session', async () => {
const demoLoginPresenter = new FakeDemoLoginPresenter();
const mockUser = {
getId: () => ({ value: 'demo-user-123' }),
getDisplayName: () => 'Alex Johnson',
getEmail: () => 'demo.driver@example.com',
getPrimaryDriverId: () => undefined,
};
const demoLoginUseCase = {
execute: vi.fn(async () => {
demoLoginPresenter.present({ user: mockUser });
return Result.ok(undefined);
}),
};
const identitySessionPort = {
getCurrentSession: vi.fn(),
createSession: vi.fn(async () => ({ token: 'demo-token-123' })),
};
const service = new AuthService(
{ debug: vi.fn(), info: vi.fn(), warn: vi.fn(), error: vi.fn() } as any,
identitySessionPort as any,
{ execute: vi.fn() } as any,
{ execute: vi.fn() } as any,
{ execute: vi.fn() } as any,
{ execute: vi.fn() } as any,
{ execute: vi.fn() } as any,
demoLoginUseCase as any,
new FakeAuthSessionPresenter() as any,
new FakeCommandResultPresenter() as any,
new FakeForgotPasswordPresenter() as any,
new FakeResetPasswordPresenter() as any,
demoLoginPresenter as any,
);
const result = await service.demoLogin({ role: 'driver' });
expect(demoLoginUseCase.execute).toHaveBeenCalledWith({ role: 'driver' });
expect(identitySessionPort.createSession).toHaveBeenCalledWith(
{
id: 'demo-user-123',
displayName: 'Alex Johnson',
email: 'demo.driver@example.com',
},
undefined
);
expect(result).toEqual({
token: 'demo-token-123',
user: {
userId: 'demo-user-123',
email: 'demo.driver@example.com',
displayName: 'Alex Johnson',
role: 'driver',
},
});
});
it('should throw error on use case failure', async () => {
const service = new AuthService(
{ debug: vi.fn(), info: vi.fn(), warn: vi.fn(), error: vi.fn() } as any,
{ getCurrentSession: vi.fn(), createSession: vi.fn() } as any,
{ execute: vi.fn() } as any,
{ execute: vi.fn() } as any,
{ execute: vi.fn() } as any,
{ execute: vi.fn() } as any,
{ execute: vi.fn() } as any,
{ execute: vi.fn(async () => Result.err({ code: 'DEMO_NOT_ALLOWED', details: { message: 'Demo not allowed' } })) } as any,
new FakeAuthSessionPresenter() as any,
new FakeCommandResultPresenter() as any,
new FakeForgotPasswordPresenter() as any,
new FakeResetPasswordPresenter() as any,
new FakeDemoLoginPresenter() as any,
);
await expect(service.demoLogin({ role: 'driver' })).rejects.toThrow('Demo not allowed');
});
});
});