fix(B10): add explicit not found route

This commit is contained in:
Saravana Achu Mac 2026-05-04 17:23:23 -07:00
parent 36544d10d4
commit ee7404ac61
2 changed files with 114 additions and 3 deletions

View File

@ -0,0 +1,64 @@
// @vitest-environment jsdom
import { render, screen } from '@testing-library/react';
import { MemoryRouter } from 'react-router-dom';
import { describe, expect, it, vi } from 'vitest';
import { AppShell } from './AppShell';
vi.mock('./Sidebar', () => ({
Sidebar: () => <aside>Sidebar</aside>,
}));
vi.mock('./Header', () => ({
Header: () => <header>Header</header>,
}));
vi.mock('./RightPanel', () => ({
RightPanel: () => <aside>Right panel</aside>,
}));
vi.mock('../../views/HomeView', () => ({
HomeView: () => <div>Home view</div>,
}));
vi.mock('../../views/PortfolioView', () => ({
PortfolioView: () => <div>Portfolio view</div>,
}));
vi.mock('../../views/ResearchView', () => ({
ResearchView: () => <div>Research view</div>,
}));
vi.mock('../../views/MarketsView', () => ({
MarketsView: () => <div>Markets view</div>,
}));
vi.mock('../../views/ScreenerView', () => ({
ScreenerView: () => <div>Screener view</div>,
}));
vi.mock('../../views/WatchlistView', () => ({
WatchlistView: () => <div>Watchlist view</div>,
}));
vi.mock('../../views/AlertsView', () => ({
AlertsView: () => <div>Alerts view</div>,
}));
vi.mock('../../views/SettingsView', () => ({
SettingsView: () => <div>Settings view</div>,
}));
describe('AppShell routing fallback', () => {
it('shows a useful 404 state for unknown routes', () => {
render(
<MemoryRouter initialEntries={['/missing/workspace']}>
<AppShell />
</MemoryRouter>,
);
expect(screen.getByRole('heading', { name: 'Route not found' })).toBeInTheDocument();
expect(screen.getByText('/missing/workspace')).toBeInTheDocument();
expect(screen.getByRole('link', { name: 'Return home' })).toHaveAttribute('href', '/');
expect(screen.queryByText('Home view')).not.toBeInTheDocument();
});
});

View File

@ -1,4 +1,4 @@
import { Routes, Route } from 'react-router-dom'; import { Link, Routes, Route, useLocation } from 'react-router-dom';
import { Sidebar } from './Sidebar'; import { Sidebar } from './Sidebar';
import { Header } from './Header'; import { Header } from './Header';
import { RightPanel } from './RightPanel'; import { RightPanel } from './RightPanel';
@ -11,6 +11,54 @@ import { WatchlistView } from '../../views/WatchlistView';
import { AlertsView } from '../../views/AlertsView'; import { AlertsView } from '../../views/AlertsView';
import { SettingsView } from '../../views/SettingsView'; import { SettingsView } from '../../views/SettingsView';
function NotFoundView() {
const location = useLocation();
return (
<section
aria-labelledby="not-found-title"
style={{
minHeight: 420,
borderRadius: 24,
border: '1px solid #E5E7EB',
background: 'linear-gradient(135deg, #FFF7ED 0%, #EFF6FF 100%)',
padding: '56px 32px',
display: 'flex',
flexDirection: 'column',
alignItems: 'center',
justifyContent: 'center',
textAlign: 'center',
color: '#111827',
}}
>
<div style={{ fontSize: 12, fontWeight: 900, letterSpacing: '0.16em', color: '#2563EB', textTransform: 'uppercase' }}>
404
</div>
<h1 id="not-found-title" style={{ margin: '10px 0 8px', fontSize: 34, fontWeight: 900 }}>
Route not found
</h1>
<p style={{ margin: 0, maxWidth: 520, color: '#4B5563', fontSize: 14, lineHeight: 1.6 }}>
No trading workspace exists at <code style={{ fontWeight: 800 }}>{location.pathname}</code>. The app is still running normally.
</p>
<Link
to="/"
style={{
marginTop: 24,
borderRadius: 999,
background: '#111827',
color: '#fff',
padding: '10px 18px',
fontSize: 13,
fontWeight: 800,
textDecoration: 'none',
}}
>
Return home
</Link>
</section>
);
}
export function AppShell() { export function AppShell() {
return ( return (
<div className="dashboard-shell"> <div className="dashboard-shell">
@ -35,8 +83,7 @@ export function AppShell() {
<Route path="/watchlist" element={<WatchlistView />} /> <Route path="/watchlist" element={<WatchlistView />} />
<Route path="/alerts" element={<AlertsView />} /> <Route path="/alerts" element={<AlertsView />} />
<Route path="/settings" element={<SettingsView />} /> <Route path="/settings" element={<SettingsView />} />
{/* Fallback */} <Route path="*" element={<NotFoundView />} />
<Route path="*" element={<HomeView />} />
</Routes> </Routes>
</main> </main>