import { cleanup, fireEvent, render, screen } from '@testing-library/react'; import { afterEach, beforeEach, describe, expect, it, vi } from 'vitest'; import { BoxUserCard } from '../../src/components/machine/box-user-card'; const { mockUseQuery, fetchSpy } = vi.hoisted(() => ({ mockUseQuery: vi.fn(), fetchSpy: vi.fn(), })); vi.mock('convex/react', () => ({ useQuery: mockUseQuery, })); vi.mock('sonner', () => ({ toast: { error: vi.fn(), success: vi.fn() }, })); describe('BoxUserCard', () => { beforeEach(() => { vi.stubGlobal('fetch', fetchSpy); fetchSpy.mockResolvedValue( new Response(JSON.stringify({ hasPassword: true, applied: true })), ); }); afterEach(() => { cleanup(); vi.unstubAllGlobals(); vi.clearAllMocks(); }); it('shows the identity line and not-set state', () => { mockUseQuery.mockReturnValue({ hasPassword: false }); render(); expect(screen.getByText('gabriel@gabriel-box')).toBeInTheDocument(); expect(screen.getByText('Not set')).toBeInTheDocument(); expect(screen.getByText('Set password')).toBeInTheDocument(); expect(screen.queryByText('Remove password')).not.toBeInTheDocument(); }); it('offers change/remove when a password is set', () => { mockUseQuery.mockReturnValue({ hasPassword: true }); render(); expect(screen.getByText('Set')).toBeInTheDocument(); expect(screen.getByText('Change password')).toBeInTheDocument(); expect(screen.getByText('Remove password')).toBeInTheDocument(); }); it('blocks submit on mismatched confirmation', () => { mockUseQuery.mockReturnValue({ hasPassword: false }); render(); fireEvent.change(screen.getByLabelText('New password'), { target: { value: 'longenough' }, }); fireEvent.change(screen.getByLabelText('Confirm'), { target: { value: 'different1' }, }); expect(screen.getByText('Passwords do not match.')).toBeInTheDocument(); expect(screen.getByText('Set password').closest('button')!.disabled).toBe( true, ); expect(fetchSpy).not.toHaveBeenCalled(); }); it('posts the password and shows the restart note when not applied live', async () => { mockUseQuery.mockReturnValue({ hasPassword: false }); fetchSpy.mockResolvedValue( new Response(JSON.stringify({ hasPassword: true, applied: false })), ); render(); fireEvent.change(screen.getByLabelText('New password'), { target: { value: 'longenough' }, }); fireEvent.change(screen.getByLabelText('Confirm'), { target: { value: 'longenough' }, }); fireEvent.click(screen.getByText('Set password')); expect( await screen.findByText(/takes effect the next time it starts/), ).toBeInTheDocument(); expect(fetchSpy).toHaveBeenCalledWith( '/api/box/set-password', expect.objectContaining({ method: 'POST' }), ); }); });