Refactor to vertical slice

This commit is contained in:
Jose Selesan
2026-06-26 14:05:37 -03:00
parent 3949c9add1
commit c8477de5d2
149 changed files with 5011 additions and 5127 deletions

View File

@@ -1,26 +1,17 @@
import { beforeEach, expect, mock, test } from 'bun:test';
import { Errors } from '@/lib/errors';
import { err, ok } from '@/lib/result';
import type { InviteComplexUserResponse } from '@repo/api-contract';
const inviteComplexUserMock = mock(async () => undefined as unknown as InviteComplexUserResponse);
class MockComplexMembersError extends Error {
status: 400 | 403 | 404 | 409;
constructor(message: string, status: 400 | 403 | 404 | 409 = 400) {
super(message);
this.name = 'ComplexMembersError';
this.status = status;
}
}
const { createInviteComplexUserHandler } = await import(
'@/modules/complex/handlers/invite-complex-user.handler'
'@/modules/complex/features/invite-complex-user/invite-complex-user.handler'
);
const inviteComplexUserHandler = createInviteComplexUserHandler({
inviteComplexUser: inviteComplexUserMock,
ComplexMembersError: MockComplexMembersError,
});
type HandlerContext = {
@@ -78,7 +69,7 @@ test('returns 201 with the service result', async () => {
},
} as const;
inviteComplexUserMock.mockResolvedValue(serviceResult);
inviteComplexUserMock.mockResolvedValue(ok(serviceResult));
const { c, json } = createContext({
userId: 'admin-1',
@@ -99,8 +90,8 @@ test('returns 201 with the service result', async () => {
});
test('maps ComplexMembersError to an error response', async () => {
inviteComplexUserMock.mockRejectedValue(
new MockComplexMembersError('Solo un ADMIN puede administrar usuarios.', 403)
inviteComplexUserMock.mockResolvedValue(
err(Errors.forbidden('Solo un ADMIN puede administrar usuarios.'))
);
const { c, json } = createContext({
@@ -117,8 +108,11 @@ test('maps ComplexMembersError to an error response', async () => {
{ email: 'new.member@example.com' }
);
expect(json.mock.calls[0]?.[0]).toEqual({
message: 'Solo un ADMIN puede administrar usuarios.',
type: 'https://api.myapp.dev/problems/forbidden',
title: 'Forbidden',
status: 403,
detail: 'Solo un ADMIN puede administrar usuarios.',
});
expect(json.mock.calls[0]?.[1]).toEqual({ status: 403 });
expect(json.mock.calls[0]?.[1]).toBe(403);
expect(response).toBeDefined();
});

View File

@@ -2,8 +2,8 @@ import { beforeEach, expect, test } from 'bun:test';
import { prismaMock, sendMailMock, transactionMock } from '../support/prisma.mock';
const { ComplexMembersError, inviteComplexUser } = await import(
'@/modules/complex/services/complex-members.service'
const { inviteComplexUser } = await import(
'@/modules/complex/features/invite-complex-user/invite-complex-user.business'
);
beforeEach(() => {
@@ -32,8 +32,10 @@ test('creates a pending invitation and sends the email', async () => {
email: ' New.Member@example.com ',
});
expect(result.invitation.email).toBe('new.member@example.com');
expect(result.invitation.status).toBe('PENDING');
expect(result.ok).toBe(true);
if (!result.ok) return;
expect(result.value.invitation.email).toBe('new.member@example.com');
expect(result.value.invitation.status).toBe('PENDING');
expect(prismaMock.complexInvitation.create).toHaveBeenCalledTimes(1);
const createArgs = prismaMock.complexInvitation.create.mock.calls[0]?.[0] as {
@@ -69,18 +71,11 @@ test('rejects when the invite target already belongs to the complex', async () =
prismaMock.complex.findUnique.mockResolvedValue({ complexName: 'Playzer Norte' } as never);
prismaMock.user.findUnique.mockResolvedValue({ id: 'member-1' } as never);
let caught: unknown;
const result = await inviteComplexUser('admin-1', 'complex-1', {
email: 'member@example.com',
});
try {
await inviteComplexUser('admin-1', 'complex-1', {
email: 'member@example.com',
});
} catch (error) {
caught = error;
}
expect(caught).toBeInstanceOf(ComplexMembersError);
expect((caught as InstanceType<typeof ComplexMembersError>).status).toBe(409);
expect(result.ok).toBe(false);
expect(transactionMock).not.toHaveBeenCalled();
expect(sendMailMock).not.toHaveBeenCalled();
});