From 842adad55aabd386edbd320ecfa85cb835d78227 Mon Sep 17 00:00:00 2001 From: Himakshi Date: Sun, 18 Jan 2026 19:30:13 +0530 Subject: [PATCH 1/3] feat(ui): add custom branded 404 error page - Created custom not-found.tsx with BrowsePing branding - Added navigation cards to help users find their way back - Implemented responsive design for all screen sizes - Added comprehensive unit tests in NotFound.test.tsx - Supports light/dark theme automatically - Includes gradient styling matching existing design system --- src/__tests__/NotFound.test.tsx | 65 ++++++++++++++++++++ src/app/not-found.tsx | 101 ++++++++++++++++++++++++++++++++ 2 files changed, 166 insertions(+) create mode 100644 src/__tests__/NotFound.test.tsx create mode 100644 src/app/not-found.tsx diff --git a/src/__tests__/NotFound.test.tsx b/src/__tests__/NotFound.test.tsx new file mode 100644 index 0000000..dbae08c --- /dev/null +++ b/src/__tests__/NotFound.test.tsx @@ -0,0 +1,65 @@ +import { render, screen } from '@testing-library/react'; +import { expect, test, describe } from 'vitest'; +import NotFound from '@/app/not-found'; + +describe('NotFound Component', () => { + test('renders 404 heading', () => { + render(); + const heading = screen.getByRole('heading', { level: 1 }); + expect(heading).toHaveTextContent('404'); + }); + + test('renders error message', () => { + render(); + const errorMessage = screen.getByText(/Oops! Page Not Found/i); + expect(errorMessage).toBeInTheDocument(); + }); + + test('renders descriptive text', () => { + render(); + const description = screen.getByText(/The page you're looking for seems to have wandered off/i); + expect(description).toBeInTheDocument(); + }); + + test('renders all navigation cards', () => { + render(); + + // Check for all navigation card titles + expect(screen.getByText('Go Home')).toBeInTheDocument(); + expect(screen.getByText('Download Extension')).toBeInTheDocument(); + expect(screen.getByText('View Leaderboard')).toBeInTheDocument(); + expect(screen.getByText('Contact Us')).toBeInTheDocument(); + }); + + test('navigation links have correct hrefs', () => { + render(); + + const homeLink = screen.getByRole('link', { name: /Go Home/i }); + expect(homeLink).toHaveAttribute('href', '/'); + + const downloadLink = screen.getByRole('link', { name: /Download Extension/i }); + expect(downloadLink).toHaveAttribute('href', '/download'); + + const leaderboardLink = screen.getByRole('link', { name: /View Leaderboard/i }); + expect(leaderboardLink).toHaveAttribute('href', '/leaderboard'); + + const contactLink = screen.getByRole('link', { name: /Contact Us/i }); + expect(contactLink).toHaveAttribute('href', '/contact'); + }); + + test('renders navigation card descriptions', () => { + render(); + + expect(screen.getByText('Return to the homepage')).toBeInTheDocument(); + expect(screen.getByText('Get BrowsePing for your browser')).toBeInTheDocument(); + expect(screen.getByText('Check out top contributors')).toBeInTheDocument(); + expect(screen.getByText('Get in touch with our team')).toBeInTheDocument(); + }); + + test('renders support contact link', () => { + render(); + + const supportLink = screen.getByRole('link', { name: /contact our support team/i }); + expect(supportLink).toHaveAttribute('href', '/contact'); + }); +}); diff --git a/src/app/not-found.tsx b/src/app/not-found.tsx new file mode 100644 index 0000000..24e35d1 --- /dev/null +++ b/src/app/not-found.tsx @@ -0,0 +1,101 @@ +import React from 'react'; +import Link from 'next/link'; +import Layout from '@/components/layout/Layout'; +import { FiHome, FiDownload, FiBarChart, FiMail } from 'react-icons/fi'; + +export default function NotFound() { + const navigationCards = [ + { + href: '/', + icon: , + title: 'Go Home', + description: 'Return to the homepage', + }, + { + href: '/download', + icon: , + title: 'Download Extension', + description: 'Get BrowsePing for your browser', + }, + { + href: '/leaderboard', + icon: , + title: 'View Leaderboard', + description: 'Check out top contributors', + }, + { + href: '/contact', + icon: , + title: 'Contact Us', + description: 'Get in touch with our team', + }, + ]; + + return ( + +
+
+ {/* 404 Header */} +
+

+ 404 +

+

+ Oops! Page Not Found +

+

+ The page you're looking for seems to have wandered off into the digital void. + Don't worry though, we can help you find your way back! +

+
+ + {/* Navigation Cards */} +
+ {navigationCards.map((card) => ( + + {/* Gradient overlay on hover */} +
+ + {/* Content */} +
+
+ {card.icon} +
+

+ {card.title} +

+

+ {card.description} +

+
+ + {/* Animated border effect */} +
+
+
+ + ))} +
+ + {/* Additional Help Text */} +
+

+ If you believe this is an error, please{' '} + + contact our support team + + . +

+
+
+
+ + ); +} From e90508e301f291cd0780fc0ff4c956885e6ec000 Mon Sep 17 00:00:00 2001 From: Himakshi Date: Sun, 18 Jan 2026 19:37:38 +0530 Subject: [PATCH 2/3] refactor(ui): simplify 404 page per maintainer feedback - Removed navigation cards for cleaner design - Added simple inline link to homepage - Updated unit tests to match simplified design - Kept gradient 404 heading and error message --- src/__tests__/NotFound.test.tsx | 41 +------------ src/app/not-found.tsx | 105 ++++++-------------------------- 2 files changed, 22 insertions(+), 124 deletions(-) diff --git a/src/__tests__/NotFound.test.tsx b/src/__tests__/NotFound.test.tsx index dbae08c..ceeeba6 100644 --- a/src/__tests__/NotFound.test.tsx +++ b/src/__tests__/NotFound.test.tsx @@ -17,49 +17,14 @@ describe('NotFound Component', () => { test('renders descriptive text', () => { render(); - const description = screen.getByText(/The page you're looking for seems to have wandered off/i); + const description = screen.getByText(/The page you're looking for doesn't exist or has been moved/i); expect(description).toBeInTheDocument(); }); - test('renders all navigation cards', () => { + test('renders home page link', () => { render(); - // Check for all navigation card titles - expect(screen.getByText('Go Home')).toBeInTheDocument(); - expect(screen.getByText('Download Extension')).toBeInTheDocument(); - expect(screen.getByText('View Leaderboard')).toBeInTheDocument(); - expect(screen.getByText('Contact Us')).toBeInTheDocument(); - }); - - test('navigation links have correct hrefs', () => { - render(); - - const homeLink = screen.getByRole('link', { name: /Go Home/i }); + const homeLink = screen.getByRole('link', { name: /Go back to the homepage/i }); expect(homeLink).toHaveAttribute('href', '/'); - - const downloadLink = screen.getByRole('link', { name: /Download Extension/i }); - expect(downloadLink).toHaveAttribute('href', '/download'); - - const leaderboardLink = screen.getByRole('link', { name: /View Leaderboard/i }); - expect(leaderboardLink).toHaveAttribute('href', '/leaderboard'); - - const contactLink = screen.getByRole('link', { name: /Contact Us/i }); - expect(contactLink).toHaveAttribute('href', '/contact'); - }); - - test('renders navigation card descriptions', () => { - render(); - - expect(screen.getByText('Return to the homepage')).toBeInTheDocument(); - expect(screen.getByText('Get BrowsePing for your browser')).toBeInTheDocument(); - expect(screen.getByText('Check out top contributors')).toBeInTheDocument(); - expect(screen.getByText('Get in touch with our team')).toBeInTheDocument(); - }); - - test('renders support contact link', () => { - render(); - - const supportLink = screen.getByRole('link', { name: /contact our support team/i }); - expect(supportLink).toHaveAttribute('href', '/contact'); }); }); diff --git a/src/app/not-found.tsx b/src/app/not-found.tsx index 24e35d1..638a44a 100644 --- a/src/app/not-found.tsx +++ b/src/app/not-found.tsx @@ -1,99 +1,32 @@ import React from 'react'; import Link from 'next/link'; import Layout from '@/components/layout/Layout'; -import { FiHome, FiDownload, FiBarChart, FiMail } from 'react-icons/fi'; export default function NotFound() { - const navigationCards = [ - { - href: '/', - icon: , - title: 'Go Home', - description: 'Return to the homepage', - }, - { - href: '/download', - icon: , - title: 'Download Extension', - description: 'Get BrowsePing for your browser', - }, - { - href: '/leaderboard', - icon: , - title: 'View Leaderboard', - description: 'Check out top contributors', - }, - { - href: '/contact', - icon: , - title: 'Contact Us', - description: 'Get in touch with our team', - }, - ]; - return (
-
+
{/* 404 Header */} -
-

- 404 -

-

- Oops! Page Not Found -

-

- The page you're looking for seems to have wandered off into the digital void. - Don't worry though, we can help you find your way back! -

-
- - {/* Navigation Cards */} -
- {navigationCards.map((card) => ( - - {/* Gradient overlay on hover */} -
- - {/* Content */} -
-
- {card.icon} -
-

- {card.title} -

-

- {card.description} -

-
- - {/* Animated border effect */} -
-
-
- - ))} -
+

+ 404 +

+

+ Oops! Page Not Found +

+

+ The page you're looking for doesn't exist or has been moved. +

- {/* Additional Help Text */} -
-

- If you believe this is an error, please{' '} - - contact our support team - - . -

-
+ {/* Simple Home Link */} +

+ + Go back to the homepage + +

From 3a08ea6a5d1c35223922ed21527ce776a463ce17 Mon Sep 17 00:00:00 2001 From: Himakshi Date: Sun, 18 Jan 2026 20:20:17 +0530 Subject: [PATCH 3/3] fix(lint): escape apostrophes in 404 page text - Fixed ESLint errors by using ' for apostrophes - Ensures CI/CD lint checks pass --- src/app/not-found.tsx | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/app/not-found.tsx b/src/app/not-found.tsx index 638a44a..5c9031a 100644 --- a/src/app/not-found.tsx +++ b/src/app/not-found.tsx @@ -15,7 +15,7 @@ export default function NotFound() { Oops! Page Not Found

- The page you're looking for doesn't exist or has been moved. + The page you're looking for doesn't exist or has been moved.

{/* Simple Home Link */}