From e3c379d069ffa9661561d25cdbf2f5894a2f8ee8 Mon Sep 17 00:00:00 2001
From: Adam Mathes <adam@adammathes.com>
Date: Sat, 14 Feb 2026 08:58:38 -0800
Subject: Refactor: project structure, implement dependency injection, and
 align v2 UI with v1

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

(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 a15192d..f46ce6f 100644
--- a/frontend/src/components/Settings.test.tsx
+++ b/frontend/src/components/Settings.test.tsx
@@ -5,88 +5,97 @@ import { describe, it, expect, vi, beforeEach } from 'vitest';
 import Settings from './Settings';
 
 describe('Settings Component', () => {
-    beforeEach(() => {
-        vi.resetAllMocks();
-        global.fetch = vi.fn();
-        // Mock confirm
-        global.confirm = vi.fn(() => true);
+  beforeEach(() => {
+    vi.resetAllMocks();
+    global.fetch = vi.fn();
+    // Mock confirm
+    global.confirm = vi.fn(() => true);
+  });
+
+  it('renders feed list', async () => {
+    const mockFeeds = [
+      { _id: 1, title: 'Tech News', url: 'http://tech.com/rss', category: 'tech' },
+      { _id: 2, title: 'Gaming', url: 'http://gaming.com/rss', category: 'gaming' },
+    ];
+
+    (global.fetch as any).mockResolvedValueOnce({
+      ok: true,
+      json: async () => mockFeeds,
     });
 
-    it('renders feed list', async () => {
-        const mockFeeds = [
-            { _id: 1, title: 'Tech News', url: 'http://tech.com/rss', category: 'tech' },
-            { _id: 2, title: 'Gaming', url: 'http://gaming.com/rss', category: 'gaming' },
-        ];
+    render(<Settings />);
 
-        (global.fetch as any).mockResolvedValueOnce({
-            ok: true,
-            json: async () => mockFeeds,
-        });
-
-        render(<Settings />);
-
-        await waitFor(() => {
-            expect(screen.getByText('Tech News')).toBeInTheDocument();
-            expect(screen.getByText('http://tech.com/rss')).toBeInTheDocument();
-            expect(screen.getByText('Gaming')).toBeInTheDocument();
-        });
+    await waitFor(() => {
+      expect(screen.getByText('Tech News')).toBeInTheDocument();
+      expect(screen.getByText('http://tech.com/rss')).toBeInTheDocument();
+      expect(screen.getByText('Gaming')).toBeInTheDocument();
+    });
+  });
+
+  it('adds a new feed', async () => {
+    (global.fetch as any)
+      .mockResolvedValueOnce({ ok: true, json: async () => [] }) // Initial load
+      .mockResolvedValueOnce({ ok: true, json: async () => ({}) }) // Add feed
+      .mockResolvedValueOnce({
+        ok: true,
+        json: async () => [{ _id: 3, title: 'New Feed', url: 'http://new.com/rss' }],
+      }); // Refresh load
+
+    render(<Settings />);
+
+    // Wait for initial load to finish
+    await waitFor(() => {
+      expect(screen.queryByText('Loading...')).not.toBeInTheDocument();
     });
 
-    it('adds a new feed', async () => {
-        (global.fetch as any)
-            .mockResolvedValueOnce({ ok: true, json: async () => [] }) // Initial load
-            .mockResolvedValueOnce({ ok: true, json: async () => ({}) }) // Add feed
-            .mockResolvedValueOnce({ ok: true, json: async () => [{ _id: 3, title: 'New Feed', url: 'http://new.com/rss' }] }); // Refresh load
-
-        render(<Settings />);
-
-        // Wait for initial load to finish
-        await waitFor(() => {
-            expect(screen.queryByText('Loading...')).not.toBeInTheDocument();
-        });
-
-        const input = screen.getByPlaceholderText('https://example.com/feed.xml');
-        const button = screen.getByText('Add Feed');
+    const input = screen.getByPlaceholderText('https://example.com/feed.xml');
+    const button = screen.getByText('Add Feed');
 
-        fireEvent.change(input, { target: { value: 'http://new.com/rss' } });
-        fireEvent.click(button);
+    fireEvent.change(input, { target: { value: 'http://new.com/rss' } });
+    fireEvent.click(button);
 
-        await waitFor(() => {
-            expect(global.fetch).toHaveBeenCalledWith('/api/feed/', expect.objectContaining({
-                method: 'POST',
-                body: JSON.stringify({ url: 'http://new.com/rss' }),
-            }));
-        });
+    await waitFor(() => {
+      expect(global.fetch).toHaveBeenCalledWith(
+        '/api/feed/',
+        expect.objectContaining({
+          method: 'POST',
+          body: JSON.stringify({ url: 'http://new.com/rss' }),
+        })
+      );
+    });
 
-        // Wait for refresh
-        await waitFor(() => {
-            expect(screen.getByText('New Feed')).toBeInTheDocument();
-        });
+    // Wait for refresh
+    await waitFor(() => {
+      expect(screen.getByText('New Feed')).toBeInTheDocument();
     });
+  });
 
-    it('deletes a feed', async () => {
-        const mockFeeds = [
-            { _id: 1, title: 'Tech News', url: 'http://tech.com/rss', category: 'tech' },
-        ];
+  it('deletes a feed', async () => {
+    const mockFeeds = [
+      { _id: 1, title: 'Tech News', url: 'http://tech.com/rss', category: 'tech' },
+    ];
 
-        (global.fetch as any)
-            .mockResolvedValueOnce({ ok: true, json: async () => mockFeeds }) // Initial load
-            .mockResolvedValueOnce({ ok: true }); // Delete
+    (global.fetch as any)
+      .mockResolvedValueOnce({ ok: true, json: async () => mockFeeds }) // Initial load
+      .mockResolvedValueOnce({ ok: true }); // Delete
 
-        render(<Settings />);
+    render(<Settings />);
 
-        await waitFor(() => {
-            expect(screen.queryByText('Loading...')).not.toBeInTheDocument();
-            expect(screen.getByText('Tech News')).toBeInTheDocument();
-        });
+    await waitFor(() => {
+      expect(screen.queryByText('Loading...')).not.toBeInTheDocument();
+      expect(screen.getByText('Tech News')).toBeInTheDocument();
+    });
 
-        const deleteBtn = screen.getByTitle('Delete Feed');
-        fireEvent.click(deleteBtn);
+    const deleteBtn = screen.getByTitle('Delete Feed');
+    fireEvent.click(deleteBtn);
 
-        await waitFor(() => {
-            expect(global.confirm).toHaveBeenCalled();
-            expect(global.fetch).toHaveBeenCalledWith('/api/feed/1', expect.objectContaining({ method: 'DELETE' }));
-            expect(screen.queryByText('Tech News')).not.toBeInTheDocument();
-        });
+    await waitFor(() => {
+      expect(global.confirm).toHaveBeenCalled();
+      expect(global.fetch).toHaveBeenCalledWith(
+        '/api/feed/1',
+        expect.objectContaining({ method: 'DELETE' })
+      );
+      expect(screen.queryByText('Tech News')).not.toBeInTheDocument();
     });
+  });
 });
-- 
cgit v1.2.3

