auth
This commit is contained in:
248
apps/api/src/domain/auth/AuthService.new.test.ts
Normal file
248
apps/api/src/domain/auth/AuthService.new.test.ts
Normal file
@@ -0,0 +1,248 @@
|
||||
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,
|
||||
{ execute: vi.fn() } 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: () => 'Demo Driver',
|
||||
getEmail: () => 'demo.driver@example.com',
|
||||
};
|
||||
|
||||
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: 'Demo Driver',
|
||||
email: 'demo.driver@example.com',
|
||||
});
|
||||
expect(result).toEqual({
|
||||
token: 'demo-token-123',
|
||||
user: {
|
||||
userId: 'demo-user-123',
|
||||
email: 'demo.driver@example.com',
|
||||
displayName: 'Demo 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');
|
||||
});
|
||||
});
|
||||
});
|
||||
Reference in New Issue
Block a user