feat(web/m7-user-mgmt): /reset-password page + admin SMTP card + tests (U3-T5b)
Completes the U3 frontend that T5a's crashed dispatch left half-done. - /reset-password/[token] — public; new password + confirm. Calls POST /api/auth/reset-password with the URL's token. invalid_token, password_too_short, and mismatched-passwords surface as inline errors. Success redirects to /login?reset=ok. - /admin/integrations gains an SMTP card (alongside Lidarr) with enabled toggle + all fields + Save and Send-test-email buttons. Password input is a separate state from the loaded form, so empty submission preserves the stored server-side value (matches the backend's empty-password-preserves contract). Test button error codes (no_email_on_file / not_configured / send_failed) surface as actionable toasts. Tests cover both new pages plus extensions to settings + integrations test files for the cards landed in T5a. Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
This commit is contained in:
@@ -0,0 +1,30 @@
|
||||
import { describe, it, expect, vi, beforeEach } from 'vitest';
|
||||
import { render, fireEvent, screen, waitFor } from '@testing-library/svelte';
|
||||
|
||||
vi.mock('$lib/auth/store.svelte', () => ({
|
||||
forgotPassword: vi.fn(),
|
||||
}));
|
||||
|
||||
import { forgotPassword } from '$lib/auth/store.svelte';
|
||||
import ForgotPasswordPage from './+page.svelte';
|
||||
|
||||
describe('/forgot-password page', () => {
|
||||
beforeEach(() => vi.clearAllMocks());
|
||||
|
||||
it('shows success message after submit regardless of whether email exists', async () => {
|
||||
(forgotPassword as unknown as ReturnType<typeof vi.fn>).mockResolvedValue(undefined);
|
||||
render(ForgotPasswordPage);
|
||||
await fireEvent.input(screen.getByLabelText(/Email/i), { target: { value: 'test@example.com' } });
|
||||
await fireEvent.click(screen.getByRole('button', { name: /Send reset link/i }));
|
||||
await waitFor(() => expect(screen.getByText(/If your email is on file/i)).toBeInTheDocument());
|
||||
expect(forgotPassword).toHaveBeenCalledWith('test@example.com');
|
||||
});
|
||||
|
||||
it('still shows success message when the API call rejects (no enumeration)', async () => {
|
||||
(forgotPassword as unknown as ReturnType<typeof vi.fn>).mockRejectedValue({ code: 'server_error' });
|
||||
render(ForgotPasswordPage);
|
||||
await fireEvent.input(screen.getByLabelText(/Email/i), { target: { value: 'test@example.com' } });
|
||||
await fireEvent.click(screen.getByRole('button', { name: /Send reset link/i }));
|
||||
await waitFor(() => expect(screen.getByText(/If your email is on file/i)).toBeInTheDocument());
|
||||
});
|
||||
});
|
||||
Reference in New Issue
Block a user