File size: 5,284 Bytes
cd99321
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
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
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
import { describe, it, expect, beforeEach } from 'vitest';
import { render, screen, waitFor } from '../../tests/helpers/render';
import userEvent from '@testing-library/user-event';
import { resetAllStores, seedStore } from '../../tests/helpers/store';
import { buildUser } from '../../tests/helpers/factories';
import { useAuthStore } from '../store/authStore';
import SettingsPage from './SettingsPage';

// Mock heavy settings sub-tabs to focus on page-level concerns
vi.mock('../components/Settings/DisplaySettingsTab', () => ({
  default: () => <div data-testid="display-settings-tab">Display Settings</div>,
}));

vi.mock('../components/Settings/MapSettingsTab', () => ({
  default: () => <div data-testid="map-settings-tab">Map Settings</div>,
}));

vi.mock('../components/Settings/NotificationsTab', () => ({
  default: () => <div data-testid="notifications-tab">Notifications Settings</div>,
}));

vi.mock('../components/Settings/IntegrationsTab', () => ({
  default: () => <div data-testid="integrations-tab">Integrations Settings</div>,
}));

vi.mock('../components/Settings/AccountTab', () => ({
  default: () => <div data-testid="account-tab">Account Settings</div>,
}));

vi.mock('../components/Settings/AboutTab', () => ({
  default: ({ appVersion }: { appVersion: string }) => (
    <div data-testid="about-tab">About v{appVersion}</div>
  ),
}));

beforeEach(() => {
  resetAllStores();
  seedStore(useAuthStore, { isAuthenticated: true, user: buildUser() });
});

describe('SettingsPage', () => {
  describe('FE-PAGE-SETTINGS-001: Settings page renders', () => {
    it('shows the Settings heading', () => {
      render(<SettingsPage />);
      expect(screen.getByRole('heading', { name: /settings/i })).toBeInTheDocument();
    });
  });

  describe('FE-PAGE-SETTINGS-002: Default tab (Display) is active', () => {
    it('shows Display tab content by default', async () => {
      render(<SettingsPage />);

      await waitFor(() => {
        expect(screen.getByTestId('display-settings-tab')).toBeInTheDocument();
      });
    });
  });

  describe('FE-PAGE-SETTINGS-003: Tab navigation', () => {
    it('switching to Map tab shows map settings content', async () => {
      const user = userEvent.setup();
      render(<SettingsPage />);

      await waitFor(() => {
        expect(screen.getByRole('button', { name: /map/i })).toBeInTheDocument();
      });

      await user.click(screen.getByRole('button', { name: /^map$/i }));

      await waitFor(() => {
        expect(screen.getByTestId('map-settings-tab')).toBeInTheDocument();
      });
    });

    it('switching to Account tab shows account settings', async () => {
      const user = userEvent.setup();
      render(<SettingsPage />);

      await waitFor(() => {
        expect(screen.getByRole('button', { name: /account/i })).toBeInTheDocument();
      });

      await user.click(screen.getByRole('button', { name: /account/i }));

      await waitFor(() => {
        expect(screen.getByTestId('account-tab')).toBeInTheDocument();
      });
    });

    it('switching to Notifications tab shows notifications content', async () => {
      const user = userEvent.setup();
      render(<SettingsPage />);

      await waitFor(() => {
        expect(screen.getByRole('button', { name: /notifications/i })).toBeInTheDocument();
      });

      await user.click(screen.getByRole('button', { name: /notifications/i }));

      await waitFor(() => {
        expect(screen.getByTestId('notifications-tab')).toBeInTheDocument();
      });
    });
  });

  describe('FE-PAGE-SETTINGS-004: All standard tabs are present', () => {
    it('renders Display, Map, Notifications, Account tabs', async () => {
      render(<SettingsPage />);

      await waitFor(() => {
        expect(screen.getByRole('button', { name: /display/i })).toBeInTheDocument();
      });

      expect(screen.getByRole('button', { name: /^map$/i })).toBeInTheDocument();
      expect(screen.getByRole('button', { name: /notifications/i })).toBeInTheDocument();
      expect(screen.getByRole('button', { name: /account/i })).toBeInTheDocument();
    });
  });

  describe('FE-PAGE-SETTINGS-005: MFA redirect switches to Account tab', () => {
    it('auto-switches to account tab when ?mfa=required is in URL', async () => {
      render(<SettingsPage />, { initialEntries: ['/settings?mfa=required'] });

      await waitFor(() => {
        expect(screen.getByTestId('account-tab')).toBeInTheDocument();
      });
    });
  });

  describe('FE-PAGE-SETTINGS-006: About tab shown when version loads', () => {
    it('About tab appears when app version is returned by API', async () => {
      const { http, HttpResponse } = await import('msw');
      const { server } = await import('../../tests/helpers/msw/server');

      server.use(
        http.get('/api/auth/app-config', () => {
          return HttpResponse.json({
            has_users: true,
            allow_registration: true,
            demo_mode: false,
            oidc_configured: false,
            oidc_only_mode: false,
            version: '2.9.10',
          });
        }),
      );

      render(<SettingsPage />);

      await waitFor(() => {
        expect(screen.getByRole('button', { name: /about/i })).toBeInTheDocument();
      });
    });
  });
});