/** * Smoke tests for the shared TeamSettingsPage composer (startsim-o7s). * * The real auth hooks are mocked so the test doesn't spin up an AuthProvider * — we just confirm the page wires the supplied api shape through to the * presentational components (MembersTable, invitations table, danger zone). */ import { render, screen, waitFor, fireEvent, act } from '@testing-library/react' import { TeamSettingsPage } from '../pages/TeamSettingsPage' import { DomainsSettingsPage } from '../pages/DomainsSettingsPage' jest.mock('@startsimpli/auth', () => { const noop = () => {} return { __esModule: true, useAuth: () => ({ user: { id: 'u1', email: 'q@x.com' }, logout: jest.fn().mockResolvedValue(undefined), }), buildCentralAuthUrl: (flow: string, opts: { app: string }) => `https://auth.startsimpli.com/${flow}?app=${opts.app}`, useMembershipFromApi: () => ({ company: { id: 'c1', slug: 'acme', name: 'Acme' }, currentTeam: { id: 't1', slug: 'core', name: 'Core', companyId: 'c1' }, role: 'owner', isOwner: true, isAdmin: true, isMemberOrAbove: true, canInvite: true, memberships: [], isLoading: false, error: null, refresh: jest.fn().mockResolvedValue(undefined), }), useInvitations: ({ fetchInvitations, autoFetch: _ }: { fetchInvitations: () => Promise; autoFetch?: boolean }) => ({ pending: [], isLoading: false, error: null, refresh: async () => { await fetchInvitations() }, revoke: noop, bulkInvite: async () => ({ invited: [] }), }), useDomainClaims: () => ({ claims: [], isLoading: false, error: null, refresh: jest.fn().mockResolvedValue(undefined), create: jest.fn(), verifyDns: jest.fn(), initiateEmail: jest.fn(), verifyEmail: jest.fn(), revoke: jest.fn(), }), } }) function buildApi() { return { teams: { myTeams: jest.fn().mockResolvedValue([]), retrieve: jest.fn(), members: jest.fn().mockResolvedValue([ { id: 'm1', userId: 'u1', teamId: 't1', role: 'owner', joinedAt: '2025-01-01', user: { id: 'u1', email: 'q@x.com', firstName: 'Quinn' }, }, ]), updateRole: jest.fn().mockResolvedValue(undefined), removeMember: jest.fn().mockResolvedValue(undefined), bulkInvite: jest.fn().mockResolvedValue({ invited: [], skipped: [] }), }, teamInvitations: { list: jest.fn().mockResolvedValue({ results: [] }), create: jest.fn(), revoke: jest.fn().mockResolvedValue(undefined), }, companies: { retrieve: jest.fn(), }, domainClaims: { list: jest.fn().mockResolvedValue({ results: [] }), create: jest.fn(), verifyDns: jest.fn(), verifyEmailInitiate: jest.fn(), verifyEmailCode: jest.fn(), revoke: jest.fn(), }, } as any } describe('TeamSettingsPage', () => { it('renders header + members table after fetch', async () => { const api = buildApi() render() expect(screen.getByText('Team & members')).toBeInTheDocument() expect(screen.getByText('Acme · Core')).toBeInTheDocument() await waitFor(() => { expect(api.teams.members).toHaveBeenCalledWith('core') }) expect(screen.getByText(/Quinn/)).toBeInTheDocument() }) it('shows the danger-zone Leave button for the current team', async () => { const api = buildApi() render() await waitFor(() => expect(api.teams.members).toHaveBeenCalled()) expect(screen.getByText('Danger zone')).toBeInTheDocument() expect(screen.getByRole('button', { name: /Leave team/i })).toBeInTheDocument() }) it('exposes the +Invite trigger when the current user is admin', async () => { const api = buildApi() render() await waitFor(() => expect(api.teams.members).toHaveBeenCalled()) expect(screen.getByRole('button', { name: '+ Invite' })).toBeInTheDocument() }) }) describe('DomainsSettingsPage', () => { it('renders the title + Add Domain trigger when admin + has companyId', async () => { const api = buildApi() render() expect(screen.getByText('Email domains')).toBeInTheDocument() expect(screen.getByRole('button', { name: /Add domain/i })).toBeInTheDocument() }) it('opens the add-domain form when clicked + validates input', async () => { const api = buildApi() render() act(() => { fireEvent.click(screen.getByRole('button', { name: /Add domain/i })) }) const input = screen.getByLabelText(/Domain/i) as HTMLInputElement fireEvent.change(input, { target: { value: 'nope' } }) fireEvent.click(screen.getByRole('button', { name: /Add domain/i })) expect( await screen.findByText(/valid domain/i), ).toBeInTheDocument() }) })