import {vi, describe, it, expect, beforeEach, type Mock} from 'vitest'; vi.mock('../../src/models/admin/users/users.admin.service.js', () => ({ countActiveAdmins: vi.fn(), findUserByEmail: vi.fn(), grantPermission: vi.fn() })); vi.mock('../../src/models/admin/invitations/invitations.service.js', () => ({ hasOpenInvitationFor: vi.fn(), createInvitation: vi.fn() })); vi.mock('../../src/models/admin/admin.mail.js', () => ({ sendInvitationMail: vi.fn() })); vi.mock('../../src/models/admin/admin.config.js', () => ({ ADMIN_BOOTSTRAP_EMAIL: 'boss@nachklang.art', ADMIN_APP_URL: 'http://localhost:3002', isProd: false })); import * as UsersService from '../../src/models/admin/users/users.admin.service.js'; import * as InvitationsService from '../../src/models/admin/invitations/invitations.service.js'; import {sendInvitationMail} from '../../src/models/admin/admin.mail.js'; import {bootstrapAdmin} from '../../src/models/admin/admin.bootstrap.js'; const countActiveAdmins = UsersService.countActiveAdmins as Mock; const findUserByEmail = UsersService.findUserByEmail as Mock; const grantPermission = UsersService.grantPermission as Mock; const hasOpenInvitationFor = InvitationsService.hasOpenInvitationFor as Mock; const createInvitation = InvitationsService.createInvitation as Mock; const mockMail = sendInvitationMail as Mock; beforeEach(() => { countActiveAdmins.mockReset(); findUserByEmail.mockReset(); grantPermission.mockReset(); hasOpenInvitationFor.mockReset(); createInvitation.mockReset(); mockMail.mockReset(); mockMail.mockResolvedValue(true); createInvitation.mockResolvedValue({id: 1, token: 'raw-token', expiresAt: new Date()}); }); describe('bootstrapAdmin', () => { it('does nothing when an active admin already exists', async () => { countActiveAdmins.mockResolvedValue(1); await bootstrapAdmin(); expect(createInvitation).not.toHaveBeenCalled(); expect(grantPermission).not.toHaveBeenCalled(); }); it('grants admin directly when the bootstrap address is already a user', async () => { countActiveAdmins.mockResolvedValue(0); findUserByEmail.mockResolvedValue({id: 'u9', email: 'boss@nachklang.art'}); await bootstrapAdmin(); expect(grantPermission).toHaveBeenCalledWith('u9', 'admin', null); expect(createInvitation).not.toHaveBeenCalled(); }); it('does not re-invite (or re-mail) while an open invitation exists', async () => { countActiveAdmins.mockResolvedValue(0); findUserByEmail.mockResolvedValue(null); hasOpenInvitationFor.mockResolvedValue(true); await bootstrapAdmin(); expect(createInvitation).not.toHaveBeenCalled(); expect(mockMail).not.toHaveBeenCalled(); }); it('invites with the admin permission when there is nothing to work with', async () => { countActiveAdmins.mockResolvedValue(0); findUserByEmail.mockResolvedValue(null); hasOpenInvitationFor.mockResolvedValue(false); await bootstrapAdmin(); expect(createInvitation).toHaveBeenCalledWith( 'boss@nachklang.art', 'Nachklang Admin', [{app: 'admin', role: 'access'}], null ); expect(mockMail).toHaveBeenCalled(); }); it('never throws when the database is unreachable at boot', async () => { countActiveAdmins.mockRejectedValue(new Error('connect ECONNREFUSED')); await expect(bootstrapAdmin()).resolves.toBeUndefined(); }); });