MeshiTrack/packages/api/tests/modules/households/households.repository.test.ts

134 lines
3.9 KiB
TypeScript

import { describe, it, expect, vi, beforeEach } from 'vitest';
import { HouseholdRole } from '@meshitrack/shared';
const { _mockLean, mockExec, mockFindById, mockFindOne, mockFindByIdAndUpdate, mockSave } =
vi.hoisted(() => {
const mockExec = vi.fn();
const mockLean = vi.fn(() => ({ exec: mockExec }));
return {
mockExec,
mockLean,
mockFindById: vi.fn(() => ({ lean: mockLean })),
mockFindOne: vi.fn(() => ({ lean: mockLean })),
mockFindByIdAndUpdate: vi.fn(() => ({ exec: mockExec })),
mockSave: vi.fn(),
};
});
vi.mock('../../../src/schemas/household.schema.js', () => {
class MockHouseholdModel {
_data: Record<string, unknown>;
constructor(data: Record<string, unknown>) {
this._data = data;
Object.assign(this, data);
}
save() {
mockSave();
return Promise.resolve(this);
}
toObject() {
return { _id: 'hh-new', ...this._data };
}
static findById = mockFindById;
static findOne = mockFindOne;
static findByIdAndUpdate = mockFindByIdAndUpdate;
}
return { HouseholdModel: MockHouseholdModel };
});
import { HouseholdsRepository } from '../../../src/modules/households/households.repository.js';
describe('HouseholdsRepository', () => {
let repo: HouseholdsRepository;
beforeEach(() => {
vi.clearAllMocks();
repo = new HouseholdsRepository();
});
describe('findById', () => {
it('calls findById with lean', async () => {
const household = { _id: 'hh1', name: 'Test' };
mockExec.mockResolvedValue(household);
const result = await repo.findById('hh1');
expect(mockFindById).toHaveBeenCalledWith('hh1');
expect(result).toEqual(household);
});
});
describe('findByInviteCode', () => {
it('calls findOne with inviteCode', async () => {
const household = { _id: 'hh1', inviteCode: 'ABCD' };
mockExec.mockResolvedValue(household);
const result = await repo.findByInviteCode('ABCD');
expect(mockFindOne).toHaveBeenCalledWith({ inviteCode: 'ABCD' });
expect(result).toEqual(household);
});
});
describe('create', () => {
it('creates a household with owner as first member', async () => {
mockSave.mockResolvedValue({});
const result = await repo.create({ name: 'Test' }, 'owner-1', 'INVITE1');
expect(mockSave).toHaveBeenCalled();
expect(result).toMatchObject({ name: 'Test', ownerUserId: 'owner-1', inviteCode: 'INVITE1' });
});
});
describe('update', () => {
it('calls findByIdAndUpdate with $set', async () => {
mockExec.mockResolvedValue({ _id: 'hh1', name: 'Updated' });
const result = await repo.update('hh1', { name: 'Updated' });
expect(mockFindByIdAndUpdate).toHaveBeenCalledWith(
'hh1',
{ $set: { name: 'Updated' } },
{ new: true, lean: true },
);
expect(result).toEqual({ _id: 'hh1', name: 'Updated' });
});
});
describe('addMember', () => {
it('pushes a new member to the array', async () => {
mockExec.mockResolvedValue({ _id: 'hh1', members: [] });
await repo.addMember('hh1', 'user-2', HouseholdRole.MEMBER);
expect(mockFindByIdAndUpdate).toHaveBeenCalledWith(
'hh1',
{
$push: {
members: expect.objectContaining({
userId: 'user-2',
role: HouseholdRole.MEMBER,
}),
},
},
{ new: true, lean: true },
);
});
});
describe('updateInviteCode', () => {
it('sets the new invite code', async () => {
mockExec.mockResolvedValue({ _id: 'hh1', inviteCode: 'NEWCODE' });
const result = await repo.updateInviteCode('hh1', 'NEWCODE');
expect(mockFindByIdAndUpdate).toHaveBeenCalledWith(
'hh1',
{ $set: { inviteCode: 'NEWCODE' } },
{ new: true, lean: true },
);
expect(result).toEqual({ _id: 'hh1', inviteCode: 'NEWCODE' });
});
});
});