aboutsummaryrefslogtreecommitdiffstats
path: root/frontend/src/App.test.tsx
blob: 5614d7d9c875005c597cf9b1714ed52b2f1f63d7 (plain) (blame)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
import React from 'react';
import '@testing-library/jest-dom';
import { render, screen, waitFor, fireEvent } from '@testing-library/react';
import App from './App';
import { describe, it, expect, vi, beforeEach } from 'vitest';

describe('App', () => {
    beforeEach(() => {
        vi.resetAllMocks();
        global.fetch = vi.fn();
    });

    it('renders login on initial load (unauthenticated)', async () => {
        (global.fetch as any).mockResolvedValueOnce({
            ok: false,
        });
        window.history.pushState({}, 'Test page', '/v2/login');
        render(<App />);
        expect(screen.getByRole('button', { name: /login/i })).toBeInTheDocument();
    });

    it('renders dashboard when authenticated', async () => {
        (global.fetch as any)
            .mockResolvedValueOnce({ ok: true }) // /api/auth
            .mockResolvedValueOnce({ ok: true, json: async () => [] }); // /api/feed/

        window.history.pushState({}, 'Test page', '/v2/');
        render(<App />);

        await waitFor(() => {
            expect(screen.getByText(/neko reader/i)).toBeInTheDocument();
        });

        // Test Logout
        const logoutBtn = screen.getByText(/logout/i);
        expect(logoutBtn).toBeInTheDocument();

        // Mock window.location
        Object.defineProperty(window, 'location', {
            configurable: true,
            value: { href: '' },
        });

        (global.fetch as any).mockResolvedValueOnce({ ok: true });

        fireEvent.click(logoutBtn);

        await waitFor(() => {
            expect(global.fetch).toHaveBeenCalledWith('/api/logout', expect.objectContaining({ method: 'POST' }));
            expect(window.location.href).toBe('/login/');
        });
    });
});