From 540f2d505e8af8ef33f729b826d2c02bde8f8be3 Mon Sep 17 00:00:00 2001 From: LimitedDelusions <88751373+LimitedDelusions@users.noreply.github.com> Date: Sun, 17 May 2026 10:39:42 -0400 Subject: [PATCH] Improve not found route handling --- deploy/nginx.conf | 8 +--- src/pages/notFound/index.spec.tsx | 56 ++++++++++++++++++++++++++ src/pages/notFound/index.tsx | 14 ++++++- src/pages/notFound/nginxConfig.spec.ts | 16 ++++++++ 4 files changed, 86 insertions(+), 8 deletions(-) create mode 100644 src/pages/notFound/index.spec.tsx create mode 100644 src/pages/notFound/nginxConfig.spec.ts diff --git a/deploy/nginx.conf b/deploy/nginx.conf index f993b6c1f..8dd8738c4 100644 --- a/deploy/nginx.conf +++ b/deploy/nginx.conf @@ -11,8 +11,6 @@ server { autoindex off; - error_page 404 /index.html; - location = /favicon.ico { log_not_found off; access_log off; @@ -32,13 +30,11 @@ server { location / { try_files $uri $uri/ /index.html; - - add_header X-Not-Found $request_uri; } - location ~* \.(js|css|png|jpg|jpeg|gif|ico)$ { + location ~* \.(js|css|png|jpg|jpeg|gif|ico|svg|json|txt|webp|woff|woff2)$ { expires max; log_not_found off; try_files $uri =404; } -} \ No newline at end of file +} diff --git a/src/pages/notFound/index.spec.tsx b/src/pages/notFound/index.spec.tsx new file mode 100644 index 000000000..81b35c468 --- /dev/null +++ b/src/pages/notFound/index.spec.tsx @@ -0,0 +1,56 @@ +import '@testing-library/jest-dom'; +import { fireEvent, render, screen, waitFor } from '@testing-library/react'; +import { createMemoryHistory } from 'history'; +import React from 'react'; +import { Router } from 'react-router-dom'; +import { NotFoundPage } from '.'; + +const mockCapture = jest.fn(); +const mockPostHog = { + capture: mockCapture +}; + +jest.mock('posthog-js/react', () => ({ + usePostHog: () => mockPostHog +})); + +describe('NotFoundPage', () => { + afterEach(() => { + jest.clearAllMocks(); + }); + + it('tracks the missing route with the current path and search params', async () => { + const history = createMemoryHistory({ + initialEntries: ['/does-not-exist?source=test'] + }); + + render( + + + + ); + + await waitFor(() => + expect(mockCapture).toHaveBeenCalledWith('not_found_page_view', { + path: '/does-not-exist', + search: '?source=test' + }) + ); + }); + + it('returns users to the home route', () => { + const history = createMemoryHistory({ + initialEntries: ['/missing-route'] + }); + + render( + + + + ); + + fireEvent.click(screen.getByRole('button', { name: 'Take me back' })); + + expect(history.location.pathname).toBe('/'); + }); +}); diff --git a/src/pages/notFound/index.tsx b/src/pages/notFound/index.tsx index 4cec899bc..9b80475b2 100644 --- a/src/pages/notFound/index.tsx +++ b/src/pages/notFound/index.tsx @@ -1,5 +1,6 @@ -import React from 'react'; -import { useHistory } from 'react-router-dom'; +import { usePostHog } from 'posthog-js/react'; +import React, { useEffect } from 'react'; +import { useHistory, useLocation } from 'react-router-dom'; import { NotFoundPageContainer, ContentWrapper, @@ -14,6 +15,15 @@ import { export function NotFoundPage() { const history = useHistory(); + const location = useLocation(); + const posthog = usePostHog(); + + useEffect(() => { + posthog?.capture('not_found_page_view', { + path: location.pathname, + search: location.search + }); + }, [location.pathname, location.search, posthog]); return ( diff --git a/src/pages/notFound/nginxConfig.spec.ts b/src/pages/notFound/nginxConfig.spec.ts new file mode 100644 index 000000000..3dcdfbe53 --- /dev/null +++ b/src/pages/notFound/nginxConfig.spec.ts @@ -0,0 +1,16 @@ +import fs from 'fs'; +import path from 'path'; + +describe('nginx 404 handling config', () => { + const config = fs.readFileSync(path.join(process.cwd(), 'deploy', 'nginx.conf'), 'utf8'); + + it('serves the React app for direct SPA route access', () => { + expect(config).toContain('try_files $uri $uri/ /index.html;'); + }); + + it('keeps missing static assets as nginx 404 responses', () => { + expect(config).toContain('location ~* \\.(js|css|png|jpg|jpeg|gif|ico|svg|json|txt|webp|woff|woff2)$'); + expect(config).toContain('try_files $uri =404;'); + expect(config).not.toContain('error_page 404 /index.html;'); + }); +});