test apps api
This commit is contained in:
230
apps/api/src/domain/auth/AuthService.test.ts
Normal file
230
apps/api/src/domain/auth/AuthService.test.ts
Normal file
@@ -0,0 +1,230 @@
|
||||
import { describe, expect, it, vi } from 'vitest';
|
||||
import { Result } from '@core/shared/application/Result';
|
||||
import { AuthService } from './AuthService';
|
||||
|
||||
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;
|
||||
}
|
||||
}
|
||||
|
||||
describe('AuthService', () => {
|
||||
it('getCurrentSession returns null when no session', async () => {
|
||||
const service = new AuthService(
|
||||
{ debug: vi.fn(), info: vi.fn(), warn: vi.fn(), error: vi.fn() } as any,
|
||||
{ getCurrentSession: vi.fn(async () => null), createSession: 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,
|
||||
);
|
||||
|
||||
await expect(service.getCurrentSession()).resolves.toBeNull();
|
||||
});
|
||||
|
||||
it('getCurrentSession maps core session to DTO', async () => {
|
||||
const service = new AuthService(
|
||||
{ debug: vi.fn(), info: vi.fn(), warn: vi.fn(), error: vi.fn() } as any,
|
||||
{
|
||||
getCurrentSession: vi.fn(async () => ({
|
||||
token: 't1',
|
||||
user: { id: 'u1', email: null, displayName: 'D' },
|
||||
})),
|
||||
createSession: 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,
|
||||
);
|
||||
|
||||
await expect(service.getCurrentSession()).resolves.toEqual({
|
||||
token: 't1',
|
||||
user: { userId: 'u1', email: '', displayName: 'D' },
|
||||
});
|
||||
});
|
||||
|
||||
it('signupWithEmail creates session and returns AuthSessionDTO', async () => {
|
||||
const authSessionPresenter = new FakeAuthSessionPresenter();
|
||||
const identitySessionPort = {
|
||||
getCurrentSession: vi.fn(),
|
||||
createSession: vi.fn(async () => ({ token: 't2' })),
|
||||
};
|
||||
|
||||
const signupUseCase = {
|
||||
execute: vi.fn(async () => {
|
||||
authSessionPresenter.present({ userId: 'u2', email: 'e2', displayName: 'd2' });
|
||||
return Result.ok(undefined);
|
||||
}),
|
||||
};
|
||||
|
||||
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,
|
||||
signupUseCase as any,
|
||||
{ execute: vi.fn() } as any,
|
||||
authSessionPresenter as any,
|
||||
new FakeCommandResultPresenter() as any,
|
||||
);
|
||||
|
||||
const session = await service.signupWithEmail({
|
||||
email: 'e2',
|
||||
password: 'p2',
|
||||
displayName: 'd2',
|
||||
} as any);
|
||||
|
||||
expect(signupUseCase.execute).toHaveBeenCalledWith({
|
||||
email: 'e2',
|
||||
password: 'p2',
|
||||
displayName: 'd2',
|
||||
});
|
||||
expect(identitySessionPort.createSession).toHaveBeenCalledWith({
|
||||
id: 'u2',
|
||||
displayName: 'd2',
|
||||
email: 'e2',
|
||||
});
|
||||
expect(session).toEqual({ token: 't2', user: { userId: 'u2', email: 'e2', displayName: 'd2' } });
|
||||
});
|
||||
|
||||
it('signupWithEmail throws with fallback when no details.message', 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(async () => Result.err({ code: 'REPOSITORY_ERROR' } as any)) } as any,
|
||||
{ execute: vi.fn() } as any,
|
||||
new FakeAuthSessionPresenter() as any,
|
||||
new FakeCommandResultPresenter() as any,
|
||||
);
|
||||
|
||||
await expect(
|
||||
service.signupWithEmail({ email: 'e2', password: 'p2', displayName: 'd2' } as any),
|
||||
).rejects.toThrow('Signup failed');
|
||||
});
|
||||
|
||||
it('loginWithEmail creates session and returns AuthSessionDTO', async () => {
|
||||
const authSessionPresenter = new FakeAuthSessionPresenter();
|
||||
const identitySessionPort = {
|
||||
getCurrentSession: vi.fn(),
|
||||
createSession: vi.fn(async () => ({ token: 't3' })),
|
||||
};
|
||||
|
||||
const loginUseCase = {
|
||||
execute: vi.fn(async () => {
|
||||
authSessionPresenter.present({ userId: 'u3', email: 'e3', displayName: 'd3' });
|
||||
return Result.ok(undefined);
|
||||
}),
|
||||
};
|
||||
|
||||
const service = new AuthService(
|
||||
{ debug: vi.fn(), info: vi.fn(), warn: vi.fn(), error: vi.fn() } as any,
|
||||
identitySessionPort as any,
|
||||
loginUseCase as any,
|
||||
{ execute: vi.fn() } as any,
|
||||
{ execute: vi.fn() } as any,
|
||||
authSessionPresenter as any,
|
||||
new FakeCommandResultPresenter() as any,
|
||||
);
|
||||
|
||||
await expect(service.loginWithEmail({ email: 'e3', password: 'p3' } as any)).resolves.toEqual({
|
||||
token: 't3',
|
||||
user: { userId: 'u3', email: 'e3', displayName: 'd3' },
|
||||
});
|
||||
|
||||
expect(loginUseCase.execute).toHaveBeenCalledWith({ email: 'e3', password: 'p3' });
|
||||
expect(identitySessionPort.createSession).toHaveBeenCalledWith({
|
||||
id: 'u3',
|
||||
displayName: 'd3',
|
||||
email: 'e3',
|
||||
});
|
||||
});
|
||||
|
||||
it('loginWithEmail throws on use case error and prefers details.message', 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(async () => Result.err({ code: 'INVALID_CREDENTIALS', details: { message: 'Bad login' } })) } as any,
|
||||
{ execute: vi.fn() } as any,
|
||||
{ execute: vi.fn() } as any,
|
||||
new FakeAuthSessionPresenter() as any,
|
||||
new FakeCommandResultPresenter() as any,
|
||||
);
|
||||
|
||||
await expect(service.loginWithEmail({ email: 'e', password: 'p' } as any)).rejects.toThrow('Bad login');
|
||||
});
|
||||
|
||||
it('loginWithEmail throws with fallback when no details.message', 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(async () => Result.err({ code: 'INVALID_CREDENTIALS' } as any)) } as any,
|
||||
{ execute: vi.fn() } as any,
|
||||
{ execute: vi.fn() } as any,
|
||||
new FakeAuthSessionPresenter() as any,
|
||||
new FakeCommandResultPresenter() as any,
|
||||
);
|
||||
|
||||
await expect(service.loginWithEmail({ email: 'e', password: 'p' } as any)).rejects.toThrow('Login failed');
|
||||
});
|
||||
|
||||
it('logout returns command result on success', async () => {
|
||||
const commandResultPresenter = new FakeCommandResultPresenter();
|
||||
const logoutUseCase = {
|
||||
execute: vi.fn(async () => {
|
||||
commandResultPresenter.present({ success: true });
|
||||
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,
|
||||
logoutUseCase as any,
|
||||
new FakeAuthSessionPresenter() as any,
|
||||
commandResultPresenter as any,
|
||||
);
|
||||
|
||||
await expect(service.logout()).resolves.toEqual({ success: true });
|
||||
});
|
||||
|
||||
it('logout throws with fallback when no details.message', 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(async () => Result.err({ code: 'REPOSITORY_ERROR' } as any)) } as any,
|
||||
new FakeAuthSessionPresenter() as any,
|
||||
new FakeCommandResultPresenter() as any,
|
||||
);
|
||||
|
||||
await expect(service.logout()).rejects.toThrow('Logout failed');
|
||||
});
|
||||
});
|
||||
@@ -133,7 +133,7 @@ export class AuthService {
|
||||
|
||||
this.commandResultPresenter.reset();
|
||||
|
||||
const result = await this.logoutUseCase.execute({});
|
||||
const result = await this.logoutUseCase.execute();
|
||||
|
||||
if (result.isErr()) {
|
||||
const error = result.unwrapErr() as LogoutApplicationError;
|
||||
|
||||
Reference in New Issue
Block a user