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' }),
);
});
});