From 6e28d1530aa08b878f5082bbcd85a95f84f830e8 Mon Sep 17 00:00:00 2001
From: Adam Mathes <adam@adammathes.com>
Date: Sat, 14 Feb 2026 21:34:49 -0800
Subject: chore: update build artifacts and finalize test improvements

---
 frontend/src/components/Settings.test.tsx | 68 +++++++++++++++++++++++++++++++
 1 file changed, 68 insertions(+)

(limited to 'frontend/src/components/Settings.test.tsx')

diff --git a/frontend/src/components/Settings.test.tsx b/frontend/src/components/Settings.test.tsx
index a0e7de4..5b0518c 100644
--- a/frontend/src/components/Settings.test.tsx
+++ b/frontend/src/components/Settings.test.tsx
@@ -136,4 +136,72 @@ describe('Settings Component', () => {
       expect(screen.getByText('Imported Feed')).toBeInTheDocument();
     });
   });
+
+  it('triggers a crawl', async () => {
+    vi.mocked(global.fetch)
+      .mockResolvedValueOnce({ ok: true, json: async () => [] } as Response) // Initial load
+      .mockResolvedValueOnce({ ok: true, json: async () => ({ message: 'crawl started' }) } as Response); // Crawl
+
+    // Mock alert
+    const alertMock = vi.spyOn(window, 'alert').mockImplementation(() => { });
+
+    render(<Settings />);
+
+    // Wait for load
+    await waitFor(() => {
+      expect(screen.queryByText('Loading...')).not.toBeInTheDocument();
+    });
+
+    const crawlBtn = screen.getByText(/crawl all feeds now/i);
+    fireEvent.click(crawlBtn);
+
+    await waitFor(() => {
+      expect(global.fetch).toHaveBeenCalledWith(
+        '/api/crawl',
+        expect.objectContaining({ method: 'POST' })
+      );
+      expect(alertMock).toHaveBeenCalledWith('Crawl started!');
+    });
+    alertMock.mockRestore();
+  });
+
+  it('handles API errors', async () => {
+    vi.mocked(global.fetch)
+      .mockResolvedValueOnce({ ok: true, json: async () => [] } as Response) // Initial load load
+      .mockResolvedValueOnce({ ok: false, json: async () => ({}) } as Response); // Add feed error
+
+    render(<Settings />);
+
+    // Wait for load
+    await waitFor(() => {
+      expect(screen.queryByText('Loading...')).not.toBeInTheDocument();
+    });
+
+    const input = screen.getByPlaceholderText('https://example.com/feed.xml');
+    const button = screen.getByText('Add Feed');
+
+    fireEvent.change(input, { target: { value: 'http://fail.com/rss' } });
+    fireEvent.click(button);
+
+    await waitFor(() => {
+      expect(screen.getByText(/failed to add feed/i)).toBeInTheDocument();
+    });
+  });
+
+  it('handles font theme change', async () => {
+    const setFontTheme = vi.fn();
+    vi.mocked(global.fetch).mockResolvedValueOnce({ ok: true, json: async () => [] } as Response);
+
+    render(<Settings fontTheme="default" setFontTheme={setFontTheme} />);
+
+    // Wait for load
+    await waitFor(() => {
+      expect(screen.queryByText('Loading...')).not.toBeInTheDocument();
+    });
+
+    const select = screen.getByLabelText(/font theme/i);
+    fireEvent.change(select, { target: { value: 'serif' } });
+
+    expect(setFontTheme).toHaveBeenCalledWith('serif');
+  });
 });
-- 
cgit v1.2.3

