From cba29e6aae637b04ff6eaf28f74bc15b6242b9ea Mon Sep 17 00:00:00 2001
From: Adam Mathes <adam@adammathes.com>
Date: Mon, 16 Feb 2026 19:37:50 -0800
Subject: Remove legacy V2 React frontend and update build/test scripts to
 focus on Vanilla JS (V3)

---
 frontend/src/components/Settings.test.tsx | 207 ------------------------------
 1 file changed, 207 deletions(-)
 delete mode 100644 frontend/src/components/Settings.test.tsx

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

diff --git a/frontend/src/components/Settings.test.tsx b/frontend/src/components/Settings.test.tsx
deleted file mode 100644
index 5b0518c..0000000
--- a/frontend/src/components/Settings.test.tsx
+++ /dev/null
@@ -1,207 +0,0 @@
-import React from 'react';
-import '@testing-library/jest-dom';
-import { render, screen, waitFor, fireEvent } from '@testing-library/react';
-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);
-  });
-
-  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' },
-    ];
-
-    vi.mocked(global.fetch).mockResolvedValueOnce({
-      ok: true,
-      json: async () => mockFeeds,
-    } as Response);
-
-    render(<Settings />);
-
-    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 () => {
-    vi.mocked(global.fetch)
-      .mockResolvedValueOnce({ ok: true, json: async () => [] } as Response) // Initial load
-      .mockResolvedValueOnce({ ok: true, json: async () => ({}) } as Response) // Add feed
-      .mockResolvedValueOnce({
-        ok: true,
-        json: async () => [{ _id: 3, title: 'New Feed', url: 'http://new.com/rss' }],
-      } as Response); // 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');
-
-    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' }),
-        })
-      );
-    });
-
-    // 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' },
-    ];
-
-    vi.mocked(global.fetch)
-      .mockResolvedValueOnce({ ok: true, json: async () => mockFeeds } as Response) // Initial load
-      .mockResolvedValueOnce({ ok: true } as Response); // Delete
-
-    render(<Settings />);
-
-    await waitFor(() => {
-      expect(screen.queryByText('Loading...')).not.toBeInTheDocument();
-      expect(screen.getByText('Tech News')).toBeInTheDocument();
-    });
-
-    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();
-    });
-  });
-
-  it('imports an OPML file', async () => {
-    vi.mocked(global.fetch)
-      .mockResolvedValueOnce({ ok: true, json: async () => [] } as Response) // Initial load
-      .mockResolvedValueOnce({ ok: true, json: async () => ({ status: 'ok' }) } as Response) // Import
-      .mockResolvedValueOnce({
-        ok: true,
-        json: async () => [{ _id: 1, title: 'Imported Feed', url: 'http://imported.com/rss' }],
-      } as Response); // Refresh load
-
-    render(<Settings />);
-
-    const file = new File(['<opml>...</opml>'], 'feeds.opml', { type: 'text/xml' });
-    const fileInput = screen.getByLabelText(/import feeds/i, { selector: 'input[type="file"]' });
-    const importButton = screen.getByText('Import');
-
-    fireEvent.change(fileInput, { target: { files: [file] } });
-    await waitFor(() => {
-      expect(importButton).not.toBeDisabled();
-    });
-
-    fireEvent.click(importButton);
-
-    await waitFor(() => {
-      expect(global.fetch).toHaveBeenCalledWith(
-        '/api/import',
-        expect.objectContaining({
-          method: 'POST',
-          body: expect.any(FormData),
-        })
-      );
-    });
-
-    // Check if refresh happens
-    await waitFor(() => {
-      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

