2026-03-27 14:50:34 +09:00
|
|
|
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(),
|
|
|
|
|
};
|
|
|
|
|
});
|
|
|
|
|
|
2026-05-19 11:06:03 +09:00
|
|
|
vi.mock('../../../src/schemas/household.schema.js', () => {
|
2026-03-27 14:50:34 +09:00
|
|
|
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 };
|
|
|
|
|
});
|
|
|
|
|
|
2026-05-19 11:06:03 +09:00
|
|
|
import { HouseholdsRepository } from '../../../src/modules/households/households.repository.js';
|
2026-03-27 14:50:34 +09:00
|
|
|
|
|
|
|
|
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' });
|
|
|
|
|
});
|
|
|
|
|
});
|
|
|
|
|
});
|