test apps api

This commit is contained in:
2025-12-23 23:14:51 +01:00
parent 16cd572c63
commit efcdbd17f2
71 changed files with 3924 additions and 913 deletions

View 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');
});
});

View File

@@ -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;