Files
playzer/apps/backend/test/complex/invite-complex-user.test.ts
2026-06-26 14:05:37 -03:00

82 lines
2.8 KiB
TypeScript

import { beforeEach, expect, test } from 'bun:test';
import { prismaMock, sendMailMock, transactionMock } from '../support/prisma.mock';
const { inviteComplexUser } = await import(
'@/modules/complex/features/invite-complex-user/invite-complex-user.business'
);
beforeEach(() => {
prismaMock._reset();
sendMailMock.mockClear();
transactionMock.mockClear();
});
test('creates a pending invitation and sends the email', async () => {
prismaMock.complexUser.findUnique.mockResolvedValue({ role: 'ADMIN' } as never);
prismaMock.complex.findUnique.mockResolvedValue({ complexName: 'Playzer Norte' } as never);
prismaMock.user.findUnique.mockResolvedValue(null);
prismaMock.complexInvitation.findFirst.mockResolvedValue(null);
prismaMock.complexInvitation.create.mockResolvedValue({
id: 'inv-1',
complexId: 'complex-1',
email: 'new.member@example.com',
tokenHash: 'token-hash',
expiresAt: new Date('2027-01-01T00:00:00.000Z'),
acceptedAt: null,
revokedAt: null,
createdAt: new Date('2026-12-01T00:00:00.000Z'),
} as never);
const result = await inviteComplexUser('admin-1', 'complex-1', {
email: ' New.Member@example.com ',
});
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 {
data: {
complexId: string;
email: string;
id: string;
tokenHash: string;
expiresAt: Date;
};
};
expect(createArgs.data.complexId).toBe('complex-1');
expect(createArgs.data.email).toBe('new.member@example.com');
expect(typeof createArgs.data.id).toBe('string');
expect(typeof createArgs.data.tokenHash).toBe('string');
expect(sendMailMock).toHaveBeenCalledTimes(1);
expect(transactionMock).toHaveBeenCalledTimes(1);
const mailArgs = sendMailMock.mock.calls[0][0] as {
to: string;
subject: string;
};
expect(mailArgs.to).toBe('new.member@example.com');
expect(mailArgs.subject).toContain('Playzer Norte');
});
test('rejects when the invite target already belongs to the complex', async () => {
prismaMock.complexUser.findUnique
.mockResolvedValueOnce({ role: 'ADMIN' } as never)
.mockResolvedValueOnce({ userId: 'member-1' } as never);
prismaMock.complex.findUnique.mockResolvedValue({ complexName: 'Playzer Norte' } as never);
prismaMock.user.findUnique.mockResolvedValue({ id: 'member-1' } as never);
const result = await inviteComplexUser('admin-1', 'complex-1', {
email: 'member@example.com',
});
expect(result.ok).toBe(false);
expect(transactionMock).not.toHaveBeenCalled();
expect(sendMailMock).not.toHaveBeenCalled();
});