Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
15 changes: 15 additions & 0 deletions src/app/routes/AppRoutes.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,15 @@
import { Route, Routes } from 'react-router';
import { AppPage } from '@/pages/app';
import { MapPage } from '@/pages/map';
import { NotFoundPage } from '@/pages/not-found';

export function AppRoutes() {
return (
<Routes>
<Route path="/" element={<MapPage />} />
<Route path="/map" element={<MapPage />} />
<Route path="/app" element={<AppPage />} />
<Route path="*" element={<NotFoundPage />} />
</Routes>
);
}
17 changes: 17 additions & 0 deletions src/main.test.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,17 @@
import { render, screen } from '@testing-library/react';
import { MemoryRouter } from 'react-router';
import { describe, expect, it } from 'vitest';
import { AppRoutes } from '@/app/routes/AppRoutes';

describe('application routing', () => {
it('shows a not-found page for an unknown path', () => {
render(
<MemoryRouter initialEntries={['/missing-page']}>
<AppRoutes />
</MemoryRouter>,
);

expect(screen.getByRole('heading', { name: 'Страница не найдена' })).toBeVisible();
expect(screen.getByRole('link', { name: 'Вернуться к карте' })).toHaveAttribute('href', '/map');
});
});
11 changes: 3 additions & 8 deletions src/main.tsx
Original file line number Diff line number Diff line change
@@ -1,9 +1,8 @@
import { StrictMode } from 'react';
import { createRoot } from 'react-dom/client';
import { BrowserRouter, Routes, Route } from 'react-router';
import { BrowserRouter } from 'react-router';
import { AppProviders } from '@/app/providers';
import { AppPage } from '@/pages/app';
import { MapPage } from '@/pages/map';
import { AppRoutes } from '@/app/routes/AppRoutes';
import '@/index.css';

// VITE_API_MODE controls MSW registration.
Expand All @@ -25,11 +24,7 @@ function renderApp() {
<StrictMode>
<BrowserRouter>
<AppProviders>
<Routes>
<Route path="/" element={<MapPage />} />
<Route path="/map" element={<MapPage />} />
<Route path="/app" element={<AppPage />} />
</Routes>
<AppRoutes />
</AppProviders>
</BrowserRouter>
</StrictMode>,
Expand Down
28 changes: 28 additions & 0 deletions src/pages/not-found/NotFoundPage.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,28 @@
import { ArrowLeft, MapPinned } from 'lucide-react';
import { Link } from 'react-router';

export function NotFoundPage() {
return (
<main className="flex min-h-dvh items-center justify-center bg-zinc-50 px-4 py-10 sm:px-6">
<section aria-labelledby="not-found-page-title" className="w-full max-w-lg text-center">
<div className="mx-auto mb-6 flex size-16 items-center justify-center rounded-2xl bg-emerald-600 text-white shadow-lg shadow-emerald-600/20">
<MapPinned aria-hidden="true" className="size-8" />
</div>
<p className="text-sm font-semibold uppercase tracking-[0.2em] text-emerald-700">Ошибка 404</p>
<h1 id="not-found-page-title" className="mt-3 text-3xl font-bold tracking-tight text-zinc-900 sm:text-4xl">
Страница не найдена
</h1>
<p className="mx-auto mt-3 max-w-md text-base leading-6 text-zinc-600">
Возможно, ссылка устарела или адрес был введён с ошибкой.
</p>
<Link
className="mt-8 inline-flex items-center gap-2 rounded-xl bg-emerald-600 px-5 py-3 text-sm font-semibold text-white shadow-sm transition hover:bg-emerald-700 focus-visible:outline-2 focus-visible:outline-offset-2 focus-visible:outline-emerald-600"
to="/map"
>
<ArrowLeft aria-hidden="true" className="size-4" />
Вернуться к карте
</Link>
</section>
</main>
);
}
1 change: 1 addition & 0 deletions src/pages/not-found/index.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
export { NotFoundPage } from './NotFoundPage';
8 changes: 8 additions & 0 deletions tests/e2e/not-found.spec.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,8 @@
import { expect, test } from '@playwright/test';

test('unknown paths show the not-found page and a way back to the map', async ({ page }) => {
await page.goto('/missing-page');

await expect(page.getByRole('heading', { name: 'Страница не найдена' })).toBeVisible();
await expect(page.getByRole('link', { name: 'Вернуться к карте' })).toHaveAttribute('href', '/map');
});
Loading