Files
minstrel/web/src/lib/components/PublicAddressCard.test.ts
T
bvandeusenandClaude Opus 5.5 94a9c8cbe3 chore(deps): SvelteKit 3 with adapter-static 4 and TypeScript 6, full-tree npm audit (#5021)
Merges Renovate's kit 3 (PR #149) and adapter-static 4 (PR #148) bumps,
plus the migration they need. The mechanical part is `sv migrate
sveltekit-3`, run one task at a time and reviewed:

- svelte.config.js is gone. Its options move into sveltekit() in
  vite.config.ts, exported as kitOptions so vitest.config.ts runs the
  same kit setup, including the $test-utils alias the tests import.
- $lib becomes #lib through package.json "imports". There is no
  src/lib/index, so only the "#lib/*" entry is kept.
- tsconfig extends $app/tsconfig.
- Peer floors raised to kit 3's requirements: svelte ^5.57.1, vite
  ^8.0.12, svelte-check ^4.7.5.

By hand, from the codemod's list of non-automated tasks:

- goto's replaceState option is now replace; keepFocus becomes
  reset: false. For the search typeahead, reset: false also stops the
  scroll-to-top, which is wanted while typing.
- The test setup mocks drop pushState/replaceState and $app/paths
  base/assets, which kit 3 removed, and mock refreshAll in place of
  invalidateAll.
- The other flagged files only read page.url or goto internal routes,
  so they needed no change.

TypeScript goes to ^6, not the ^7 Renovate offers: kit 3 declares
typescript ^6 as a peer and svelte-check 4.7 accepts ^5 || ^6. Move to
7 once both accept it.

With Tailwind 4 and kit 3 in, `npm audit` on the whole tree reports 0,
so the web lane now audits every dependency rather than only what
ships to browsers.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-10-08 10:50:39 -04:00

76 lines
2.7 KiB
TypeScript
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
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');
});
});