import { describe, expect, test, vi, beforeEach } from 'vitest'; import { render, screen, fireEvent, waitFor } from '@testing-library/svelte'; import PublicAddressCard from './PublicAddressCard.svelte'; const getNetworkSettings = vi.fn(); const updatePublicUrl = vi.fn(); vi.mock('#lib/api/admin.js', () => ({ getNetworkSettings: () => getNetworkSettings(), updatePublicUrl: (url: string) => updatePublicUrl(url) })); const pushToast = vi.fn(); vi.mock('#lib/stores/toast.svelte.js', () => ({ pushToast: (...args: unknown[]) => pushToast(...args) })); function settings(publicUrl: string) { return { trusted_proxy_hops: 1, max_hops: 10, detected_client_ip: '198.51.100.7', forwarded_chain: '198.51.100.7', remote_addr: '172.18.0.1:40000', public_url: publicUrl }; } beforeEach(() => { vi.clearAllMocks(); }); describe('PublicAddressCard', () => { test('warns that reset emails are not sent while the address is unset', async () => { getNetworkSettings.mockResolvedValue(settings('')); render(PublicAddressCard); expect(await screen.findByText(/password-reset emails are not being sent/i)).toBeTruthy(); }); test('no warning once an address is saved', async () => { getNetworkSettings.mockResolvedValue(settings('https://music.example.com')); render(PublicAddressCard); await screen.findByDisplayValue('https://music.example.com'); expect(screen.queryByText(/not being sent/i)).toBeNull(); }); test('offers this page’s own origin and saves it trimmed', async () => { getNetworkSettings.mockResolvedValue(settings('')); updatePublicUrl.mockResolvedValue(settings(window.location.origin)); render(PublicAddressCard); await fireEvent.click(await screen.findByRole('button', { name: /^Use / })); await fireEvent.click(screen.getByRole('button', { name: /save/i })); await waitFor(() => expect(updatePublicUrl).toHaveBeenCalledWith(window.location.origin)); expect(pushToast).toHaveBeenCalledWith('Public address saved.'); }); test('shows the server’s reason when an address is refused', async () => { getNetworkSettings.mockResolvedValue(settings('')); updatePublicUrl.mockRejectedValue({ code: 'invalid_public_url', message: 'public URL must be an http:// or https:// address', status: 400 }); render(PublicAddressCard); const input = await screen.findByPlaceholderText('https://music.example.com'); await fireEvent.input(input, { target: { value: 'music.example.com' } }); await fireEvent.click(screen.getByRole('button', { name: /save/i })); await waitFor(() => expect(pushToast).toHaveBeenCalled()); expect(pushToast.mock.calls[0][1]).toBe('error'); }); });