From 238366d269113dfe3298cd398bf1b7ed91985d2f Mon Sep 17 00:00:00 2001 From: Joshua Kitenge Date: Thu, 9 Jan 2025 15:25:10 +0000 Subject: [PATCH] Improve the 404 page to match scigateway #1237 --- cypress/e2e/with_mock_data/admin.cy.ts | 10 + .../with_mock_data/catalogueCategories.cy.ts | 6 +- .../e2e/with_mock_data/catalogueItems.cy.ts | 10 +- cypress/e2e/with_mock_data/homePage.cy.ts | 5 +- cypress/e2e/with_mock_data/items.cy.ts | 14 +- .../e2e/with_mock_data/manufacturers.cy.ts | 5 +- cypress/e2e/with_mock_data/systems.cy.ts | 7 +- .../adminLayout.component.test.tsx.snap | 51 +++- src/admin/adminLayout.component.tsx | 13 +- .../catalogueLayout.component.test.tsx.snap | 51 +++- src/catalogue/catalogueLayout.component.tsx | 7 +- .../pageNotFound.component.test.tsx.snap | 265 ++++++++++++++++++ .../pageNotFound.component.test.tsx | 38 +++ .../pageNotFound/pageNotFound.component.tsx | 84 ++++++ .../homePage.component.test.tsx.snap | 51 +++- src/homePage/homePage.component.tsx | 9 +- ...manufacturerLayout.component.test.tsx.snap | 51 +++- .../manufacturerLayout.component.tsx | 9 +- .../systemsLayout.component.test.tsx.snap | 51 +++- src/systems/systemsLayout.component.tsx | 9 +- 20 files changed, 645 insertions(+), 101 deletions(-) create mode 100644 src/common/pageNotFound/__snapshots__/pageNotFound.component.test.tsx.snap create mode 100644 src/common/pageNotFound/pageNotFound.component.test.tsx create mode 100644 src/common/pageNotFound/pageNotFound.component.tsx diff --git a/cypress/e2e/with_mock_data/admin.cy.ts b/cypress/e2e/with_mock_data/admin.cy.ts index 59f4872d9..a46f1582c 100644 --- a/cypress/e2e/with_mock_data/admin.cy.ts +++ b/cypress/e2e/with_mock_data/admin.cy.ts @@ -7,4 +7,14 @@ describe('Admin Page', () => { cy.findByText('Units').should('be.visible'); cy.findByText('Usage Statuses').should('be.visible'); }); + + it('display 404 page for invalid route', () => { + cy.visit('/admin-ims/not_exist'); + cy.findByText( + `We're sorry, the page you requested was not found on the server. If you entered the URL manually please check your spelling and try again. Otherwise, return to the`, + { exact: false } + ).should('exist'); + + cy.findByRole('link', { name: 'admin home page' }).should('exist'); + }); }); diff --git a/cypress/e2e/with_mock_data/catalogueCategories.cy.ts b/cypress/e2e/with_mock_data/catalogueCategories.cy.ts index 40067d420..d784dfd08 100644 --- a/cypress/e2e/with_mock_data/catalogueCategories.cy.ts +++ b/cypress/e2e/with_mock_data/catalogueCategories.cy.ts @@ -830,9 +830,11 @@ describe('Catalogue Category', () => { it('expired url displays search not found message', () => { cy.visit('/catalogue/not_exist'); cy.findByText( - `The catalogue route you are trying to access doesn't exist. Please click the Home button to navigate back to the Catalogue Home page.`, - { timeout: 10000 } + `We're sorry, the page you requested was not found on the server. If you entered the URL manually please check your spelling and try again. Otherwise, return to the`, + { exact: false } ).should('exist'); + + cy.findByRole('link', { name: 'catalogue home page' }).should('exist'); }); it('when root has no data it displays no categories error message', () => { diff --git a/cypress/e2e/with_mock_data/catalogueItems.cy.ts b/cypress/e2e/with_mock_data/catalogueItems.cy.ts index db7ff263a..d2cf06382 100644 --- a/cypress/e2e/with_mock_data/catalogueItems.cy.ts +++ b/cypress/e2e/with_mock_data/catalogueItems.cy.ts @@ -513,9 +513,12 @@ describe('Catalogue Items', () => { cy.visit('/catalogue/4/items/1fds'); cy.findByText( - `The catalogue route you are trying to access doesn't exist. Please click the Home button to navigate back to the Catalogue Home page.` + `We're sorry, the page you requested was not found on the server. If you entered the URL manually please check your spelling and try again. Otherwise, return to the`, + { exact: false } ).should('exist'); + cy.findByRole('link', { name: 'catalogue home page' }).should('exist'); + cy.findByRole('button', { name: 'navigate to catalogue home' }).click(); cy.findByText('Motion').should('exist'); @@ -525,8 +528,11 @@ describe('Catalogue Items', () => { cy.visit('/catalogue/4/items/89'); cy.findByText( - `The catalogue route you are trying to access doesn't exist. Please click the Home button to navigate back to the Catalogue Home page.` + `We're sorry, the page you requested was not found on the server. If you entered the URL manually please check your spelling and try again. Otherwise, return to the`, + { exact: false } ).should('exist'); + + cy.findByRole('link', { name: 'catalogue home page' }).should('exist'); }); it('displays error message when user tries to delete a catalogue item that has children elements', () => { diff --git a/cypress/e2e/with_mock_data/homePage.cy.ts b/cypress/e2e/with_mock_data/homePage.cy.ts index 716fb285b..d7c3c1c5f 100644 --- a/cypress/e2e/with_mock_data/homePage.cy.ts +++ b/cypress/e2e/with_mock_data/homePage.cy.ts @@ -28,7 +28,10 @@ describe('IMS HomePage', () => { cy.visit('/ims/fdsf'); cy.findByText( - `The route you are trying to access doesn't exist. Please click the Scigateway logo button in the header to navigate back to the Home page.` + `We're sorry, the page you requested was not found on the server. If you entered the URL manually please check your spelling and try again. Otherwise, return to the`, + { exact: false } ).should('exist'); + + cy.findByRole('link', { name: 'home page' }).should('exist'); }); }); diff --git a/cypress/e2e/with_mock_data/items.cy.ts b/cypress/e2e/with_mock_data/items.cy.ts index f5c376ed6..cb1db74fd 100644 --- a/cypress/e2e/with_mock_data/items.cy.ts +++ b/cypress/e2e/with_mock_data/items.cy.ts @@ -12,9 +12,11 @@ describe('Items', () => { cy.visit('/catalogue/4/items/1/items/1fds'); cy.findByText( - `The catalogue route you are trying to access doesn't exist. Please click the Home button to navigate back to the Catalogue Home page.` + `We're sorry, the page you requested was not found on the server. If you entered the URL manually please check your spelling and try again. Otherwise, return to the`, + { exact: false } ).should('exist'); + cy.findByRole('link', { name: 'catalogue home page' }).should('exist'); cy.findByRole('button', { name: 'navigate to catalogue home' }).click(); cy.findByText('Motion').should('exist'); @@ -24,16 +26,22 @@ describe('Items', () => { cy.visit('/catalogue/5/items/1/items/KvT2Ox7n'); cy.findByText( - `The catalogue route you are trying to access doesn't exist. Please click the Home button to navigate back to the Catalogue Home page.` + `We're sorry, the page you requested was not found on the server. If you entered the URL manually please check your spelling and try again. Otherwise, return to the`, + { exact: false } ).should('exist'); + + cy.findByRole('link', { name: 'catalogue home page' }).should('exist'); }); it('displays the expired landing page message if the catalogue_item_id does not match the item_id ', () => { cy.visit('/catalogue/4/items/89/items/G463gOIA'); cy.findByText( - `The catalogue route you are trying to access doesn't exist. Please click the Home button to navigate back to the Catalogue Home page.` + `We're sorry, the page you requested was not found on the server. If you entered the URL manually please check your spelling and try again. Otherwise, return to the`, + { exact: false } ).should('exist'); + + cy.findByRole('link', { name: 'catalogue home page' }).should('exist'); }); it('should be able to navigate back to the catalogue catalogue item table view', () => { cy.findByRole('link', { name: 'Cameras' }).click(); diff --git a/cypress/e2e/with_mock_data/manufacturers.cy.ts b/cypress/e2e/with_mock_data/manufacturers.cy.ts index 8871423df..d4676a777 100644 --- a/cypress/e2e/with_mock_data/manufacturers.cy.ts +++ b/cypress/e2e/with_mock_data/manufacturers.cy.ts @@ -379,9 +379,12 @@ describe('Manufacturer', () => { cy.visit('/manufacturers/invalid'); cy.findByText( - `The manufacturer route you are trying to access doesn't exist. Please click the Home button to navigate back to the Manufacturer Home page.` + `We're sorry, the page you requested was not found on the server. If you entered the URL manually please check your spelling and try again. Otherwise, return to the`, + { exact: false } ).should('exist'); + cy.findByRole('link', { name: 'manufacturers home page' }).should('exist'); + cy.findByRole('button', { name: 'navigate to manufacturers home' }).click(); cy.findByText('Manufacturer A').should('exist'); diff --git a/cypress/e2e/with_mock_data/systems.cy.ts b/cypress/e2e/with_mock_data/systems.cy.ts index 406c49642..7d835a7b3 100644 --- a/cypress/e2e/with_mock_data/systems.cy.ts +++ b/cypress/e2e/with_mock_data/systems.cy.ts @@ -15,11 +15,12 @@ describe('Systems', () => { it('should eventually load displaying system not found when system does not exist', () => { cy.visit('/systems/invalid_id'); - // Can take a moment to load due to react-query retries - cy.findByText('Invalid System Route', { timeout: 10000 }).should('exist'); cy.findByText( - `The system route you are trying to access doesn't exist. Please click the Home button to navigate back to the System Home page.` + `We're sorry, the page you requested was not found on the server. If you entered the URL manually please check your spelling and try again. Otherwise, return to the`, + { exact: false } ).should('exist'); + + cy.findByRole('link', { name: 'systems home page' }).should('exist'); }); it('should be able to navigate through subsystems', () => { diff --git a/src/admin/__snapshots__/adminLayout.component.test.tsx.snap b/src/admin/__snapshots__/adminLayout.component.test.tsx.snap index d72044ac0..a981bcc04 100644 --- a/src/admin/__snapshots__/adminLayout.component.test.tsx.snap +++ b/src/admin/__snapshots__/adminLayout.component.test.tsx.snap @@ -2,19 +2,48 @@ exports[`Admin Error Component > renders Admin error page correctly 1`] = ` -
-

+

- Invalid Admin Route -

-

+ 404 +

+
+
- The admin route you are trying to access doesn't exist. Please click the Home button to navigate back to the Admin Home page. -

+

+ Page not found +

+

+ We're sorry, the page you requested was not found on the server. If you entered the URL manually please check your spelling and try again. Otherwise, return to the + + admin home page + + . +

+
`; diff --git a/src/admin/adminLayout.component.tsx b/src/admin/adminLayout.component.tsx index d0f31630d..aff81c253 100644 --- a/src/admin/adminLayout.component.tsx +++ b/src/admin/adminLayout.component.tsx @@ -3,15 +3,10 @@ import { Outlet, useLocation } from 'react-router-dom'; import { BreadcrumbsInfo } from '../api/api.types'; import { paths } from '../App'; import BaseLayoutHeader from '../common/baseLayoutHeader.component'; -import ErrorPage from '../common/errorPage.component'; +import PageNotFoundComponent from '../common/pageNotFound/pageNotFound.component'; export const AdminErrorComponent = () => { - return ( - - ); + return ; }; // returns the admin function from the path (null when just on adminPage) @@ -37,7 +32,9 @@ function AdminLayout() { const adminBreadCrumbs: BreadcrumbsInfo | undefined = adminPageName ? { - trail: [adminBreadCrumbsTrails[adminPageName] ?? ['', '']], + trail: adminBreadCrumbsTrails[adminPageName] + ? [adminBreadCrumbsTrails[adminPageName]] + : [], full_trail: true, } : undefined; diff --git a/src/catalogue/__snapshots__/catalogueLayout.component.test.tsx.snap b/src/catalogue/__snapshots__/catalogueLayout.component.test.tsx.snap index d74f7be1a..ac8f1c309 100644 --- a/src/catalogue/__snapshots__/catalogueLayout.component.test.tsx.snap +++ b/src/catalogue/__snapshots__/catalogueLayout.component.test.tsx.snap @@ -889,19 +889,48 @@ exports[`Catalogue Layout Error Component > renders catalogue error page correct -
-

+

- Invalid Catalogue Route -

-

+ 404 +

+
+
- The catalogue route you are trying to access doesn't exist. Please click the Home button to navigate back to the Catalogue Home page. -

+

+ Page not found +

+

+ We're sorry, the page you requested was not found on the server. If you entered the URL manually please check your spelling and try again. Otherwise, return to the + + catalogue home page + + . +

+
diff --git a/src/catalogue/catalogueLayout.component.tsx b/src/catalogue/catalogueLayout.component.tsx index 6f909733f..dd1090889 100644 --- a/src/catalogue/catalogueLayout.component.tsx +++ b/src/catalogue/catalogueLayout.component.tsx @@ -17,13 +17,10 @@ import { } from '../api/catalogueItems'; import { getItemQuery, useGetItem } from '../api/items'; import BaseLayoutHeader from '../common/baseLayoutHeader.component'; -import ErrorPage from '../common/errorPage.component'; +import PageNotFoundComponent from '../common/pageNotFound/pageNotFound.component'; export const CatalogueErrorComponent = () => ( - + ); export const CatalogueLayoutErrorComponent = () => { diff --git a/src/common/pageNotFound/__snapshots__/pageNotFound.component.test.tsx.snap b/src/common/pageNotFound/__snapshots__/pageNotFound.component.test.tsx.snap new file mode 100644 index 000000000..a18255a26 --- /dev/null +++ b/src/common/pageNotFound/__snapshots__/pageNotFound.component.test.tsx.snap @@ -0,0 +1,265 @@ +// Vitest Snapshot v1, https://vitest.dev/guide/snapshot.html + +exports[`Page Not Found Component > renders Admin 404 page 1`] = ` + +
+
+
+ +

+ 404 +

+
+
+

+ Page not found +

+

+ We're sorry, the page you requested was not found on the server. If you entered the URL manually please check your spelling and try again. Otherwise, return to the + + + admin + home page + + + . +

+
+
+
+ +`; + +exports[`Page Not Found Component > renders Catalogue 404 page 1`] = ` + +
+
+
+ +

+ 404 +

+
+
+

+ Page not found +

+

+ We're sorry, the page you requested was not found on the server. If you entered the URL manually please check your spelling and try again. Otherwise, return to the + + + catalogue + home page + + + . +

+
+
+
+ +`; + +exports[`Page Not Found Component > renders Manufacturers 404 page 1`] = ` + +
+
+
+ +

+ 404 +

+
+
+

+ Page not found +

+

+ We're sorry, the page you requested was not found on the server. If you entered the URL manually please check your spelling and try again. Otherwise, return to the + + + manufacturers + home page + + + . +

+
+
+
+ +`; + +exports[`Page Not Found Component > renders Systems 404 page 1`] = ` + +
+
+
+ +

+ 404 +

+
+
+

+ Page not found +

+

+ We're sorry, the page you requested was not found on the server. If you entered the URL manually please check your spelling and try again. Otherwise, return to the + + + systems + home page + + + . +

+
+
+
+ +`; + +exports[`Page Not Found Component > renders the basic 404 page 1`] = ` + +
+
+
+ +

+ 404 +

+
+
+

+ Page not found +

+

+ We're sorry, the page you requested was not found on the server. If you entered the URL manually please check your spelling and try again. Otherwise, return to the + + + home page + + + . +

+
+
+
+ +`; diff --git a/src/common/pageNotFound/pageNotFound.component.test.tsx b/src/common/pageNotFound/pageNotFound.component.test.tsx new file mode 100644 index 000000000..90d5c8ca5 --- /dev/null +++ b/src/common/pageNotFound/pageNotFound.component.test.tsx @@ -0,0 +1,38 @@ +import { act } from 'react'; +import { + RoutesHomeLocation, + type RoutesHomeLocationType, +} from '../../app.types'; +import { renderComponentWithRouterProvider } from '../../testUtils'; +import PageNotFoundComponent, { + type PageNotFoundComponentProps, +} from './pageNotFound.component'; + +describe('Page Not Found Component', () => { + let props: PageNotFoundComponentProps; + + const createView = () => { + return renderComponentWithRouterProvider( + + ); + }; + + it('renders the basic 404 page', async () => { + let baseElement; + await act(async () => { + baseElement = createView().baseElement; + }); + expect(baseElement).toMatchSnapshot(); + }); + + Object.keys(RoutesHomeLocation).forEach((route) => { + it(`renders ${route} 404 page`, async () => { + props = { homeLocation: route as RoutesHomeLocationType }; + let baseElement; + await act(async () => { + baseElement = createView().baseElement; + }); + expect(baseElement).toMatchSnapshot(); + }); + }); +}); diff --git a/src/common/pageNotFound/pageNotFound.component.tsx b/src/common/pageNotFound/pageNotFound.component.tsx new file mode 100644 index 000000000..6b6ed615f --- /dev/null +++ b/src/common/pageNotFound/pageNotFound.component.tsx @@ -0,0 +1,84 @@ +import BugReportIcon from '@mui/icons-material/BugReport'; +import { Box, Link as MuiLink, Theme } from '@mui/material'; +import Typography from '@mui/material/Typography'; +import React from 'react'; +import { Link } from 'react-router-dom'; +import { + RoutesHomeLocation, + type RoutesHomeLocationType, +} from '../../app.types'; + +export interface PageNotFoundComponentProps { + homeLocation?: RoutesHomeLocationType; +} + +const PageNotFoundComponent = ( + props: PageNotFoundComponentProps +): React.ReactElement => { + const { homeLocation } = props; + return ( +
+ + theme.colours?.blue, + }} + /> + theme.colours?.blue, + }} + > + 404 + + + + + Page not found + + + We're sorry, the page you requested was not found on the server. + If you entered the URL manually please check your spelling and try + again. Otherwise, return to the{' '} + theme.palette.text.primary }} + to={`/${homeLocation ? RoutesHomeLocation[homeLocation] : ''}`} + > + {homeLocation?.toLocaleLowerCase()} home page + {' '} + . + + +
+ ); +}; + +export default PageNotFoundComponent; diff --git a/src/homePage/__snapshots__/homePage.component.test.tsx.snap b/src/homePage/__snapshots__/homePage.component.test.tsx.snap index 58c95fa9b..42a391843 100644 --- a/src/homePage/__snapshots__/homePage.component.test.tsx.snap +++ b/src/homePage/__snapshots__/homePage.component.test.tsx.snap @@ -2,19 +2,48 @@ exports[`Home Page Error Component > renders catalogue error page correctly 1`] = ` -
-

+

- Invalid Route -

-

+ 404 +

+
+
- The route you are trying to access doesn't exist. Please click the Scigateway logo button in the header to navigate back to the Home page. -

+

+ Page not found +

+

+ We're sorry, the page you requested was not found on the server. If you entered the URL manually please check your spelling and try again. Otherwise, return to the + + home page + + . +

+
`; diff --git a/src/homePage/homePage.component.tsx b/src/homePage/homePage.component.tsx index 43b98f429..f15c62905 100644 --- a/src/homePage/homePage.component.tsx +++ b/src/homePage/homePage.component.tsx @@ -2,7 +2,7 @@ import { Box, Button, Grid, Paper, alpha, styled } from '@mui/material'; import Typography from '@mui/material/Typography'; import React from 'react'; import { Link } from 'react-router-dom'; -import ErrorPage from '../common/errorPage.component'; +import PageNotFoundComponent from '../common/pageNotFound/pageNotFound.component'; import { InventoryManagementSystemSettingsContext } from '../configProvider.component'; import BackgroundImage from '/images/background.jpg'; import Decal1Image from '/images/decal1.svg'; @@ -15,12 +15,7 @@ import GreenSwirl2Image from '/images/green-swirl2.png'; import DGLogo from '/images/scigateway-white-text-blue-mark-logo.svg'; export const HomePageErrorComponent = () => { - return ( - - ); + return ; }; export interface BaseHomePageProps { diff --git a/src/manufacturer/__snapshots__/manufacturerLayout.component.test.tsx.snap b/src/manufacturer/__snapshots__/manufacturerLayout.component.test.tsx.snap index 5c6a81543..1f1c099e7 100644 --- a/src/manufacturer/__snapshots__/manufacturerLayout.component.test.tsx.snap +++ b/src/manufacturer/__snapshots__/manufacturerLayout.component.test.tsx.snap @@ -57,19 +57,48 @@ exports[`Manufacturer Layout Error Component > renders manufacturer error page c -
-

+

- Invalid Manufacturer Route -

-

+ 404 +

+
+
- The manufacturer route you are trying to access doesn't exist. Please click the Home button to navigate back to the Manufacturer Home page. -

+

+ Page not found +

+

+ We're sorry, the page you requested was not found on the server. If you entered the URL manually please check your spelling and try again. Otherwise, return to the + + manufacturers home page + + . +

+
diff --git a/src/manufacturer/manufacturerLayout.component.tsx b/src/manufacturer/manufacturerLayout.component.tsx index f6632bc30..12daad5db 100644 --- a/src/manufacturer/manufacturerLayout.component.tsx +++ b/src/manufacturer/manufacturerLayout.component.tsx @@ -5,15 +5,10 @@ import { BreadcrumbsInfo } from '../api/api.types'; import { getManufacturerQuery, useGetManufacturer } from '../api/manufacturers'; import { paths } from '../App'; import BaseLayoutHeader from '../common/baseLayoutHeader.component'; -import ErrorPage from '../common/errorPage.component'; +import PageNotFoundComponent from '../common/pageNotFound/pageNotFound.component'; export const ManufacturerErrorComponent = () => { - return ( - - ); + return ; }; export const ManufacturerLayoutErrorComponent = () => { diff --git a/src/systems/__snapshots__/systemsLayout.component.test.tsx.snap b/src/systems/__snapshots__/systemsLayout.component.test.tsx.snap index db700ff19..677e593f8 100644 --- a/src/systems/__snapshots__/systemsLayout.component.test.tsx.snap +++ b/src/systems/__snapshots__/systemsLayout.component.test.tsx.snap @@ -197,19 +197,48 @@ exports[`Systems Layout Error Component > renders system error page correctly 1` -
-

+

- Invalid System Route -

-

+ 404 +

+
+
- The system route you are trying to access doesn't exist. Please click the Home button to navigate back to the System Home page. -

+

+ Page not found +

+

+ We're sorry, the page you requested was not found on the server. If you entered the URL manually please check your spelling and try again. Otherwise, return to the + + systems home page + + . +

+
diff --git a/src/systems/systemsLayout.component.tsx b/src/systems/systemsLayout.component.tsx index 553aaf014..aef74f348 100644 --- a/src/systems/systemsLayout.component.tsx +++ b/src/systems/systemsLayout.component.tsx @@ -2,15 +2,10 @@ import type { QueryClient } from '@tanstack/react-query'; import { Outlet, useParams, type LoaderFunctionArgs } from 'react-router-dom'; import { getSystemQuery, useGetSystemsBreadcrumbs } from '../api/systems'; import BaseLayoutHeader from '../common/baseLayoutHeader.component'; -import ErrorPage from '../common/errorPage.component'; +import PageNotFoundComponent from '../common/pageNotFound/pageNotFound.component'; export const SystemsErrorComponent = () => { - return ( - - ); + return ; }; export const SystemsLayoutErrorComponent = () => {