import { describe, it, expect, vi, beforeEach } from 'vitest' vi.mock('../../../server/models/counter.js', () => ({ default: { findOneAndUpdate: vi.fn() } })) vi.mock('../../../server/models/member.js', () => ({ default: { findByIdAndUpdate: vi.fn() } })) import Counter from '../../../server/models/counter.js' import Member from '../../../server/models/member.js' import { assignMemberNumber } from '../../../server/utils/memberNumber.js' describe('assignMemberNumber', () => { beforeEach(() => { vi.clearAllMocks() Member.findByIdAndUpdate.mockResolvedValue(undefined) }) it('returns 1 for the first member', async () => { Counter.findOneAndUpdate.mockResolvedValue({ seq: 1 }) const result = await assignMemberNumber('member-abc') expect(result).toBe(1) }) it('increments atomically using findOneAndUpdate with $inc and upsert', async () => { Counter.findOneAndUpdate.mockResolvedValue({ seq: 5 }) await assignMemberNumber('member-xyz') expect(Counter.findOneAndUpdate).toHaveBeenCalledWith( { _id: 'memberNumber' }, { $inc: { seq: 1 } }, { new: true, upsert: true } ) }) it('saves the member number to the member record without running validators', async () => { Counter.findOneAndUpdate.mockResolvedValue({ seq: 3 }) await assignMemberNumber('member-abc') expect(Member.findByIdAndUpdate).toHaveBeenCalledWith( 'member-abc', { memberNumber: 3 }, { runValidators: false } ) }) it('returns the sequence number for the given member', async () => { Counter.findOneAndUpdate.mockResolvedValue({ seq: 42 }) const result = await assignMemberNumber('member-999') expect(result).toBe(42) }) })