From 67813e5412601c10232098072334b9899b39caf4 Mon Sep 17 00:00:00 2001 From: Joshua Kitenge Date: Wed, 18 Oct 2023 12:33:10 +0000 Subject: [PATCH 1/9] remove catalogue item query when deleted and add progress bar to landing page --- src/api/catalogueItem.tsx | 1 + .../catalogueItemsLandingPage.component.tsx | 40 ++++++++++++------- 2 files changed, 27 insertions(+), 14 deletions(-) diff --git a/src/api/catalogueItem.tsx b/src/api/catalogueItem.tsx index 124e82cab..c481b4ef4 100644 --- a/src/api/catalogueItem.tsx +++ b/src/api/catalogueItem.tsx @@ -146,6 +146,7 @@ export const useDeleteCatalogueItem = (): UseMutationResult< }, onSuccess: () => { queryClient.invalidateQueries({ queryKey: ['CatalogueItems'] }); + queryClient.removeQueries({ queryKey: ['CatalogueItem'] }); }, } ); diff --git a/src/catalogue/items/catalogueItemsLandingPage.component.tsx b/src/catalogue/items/catalogueItemsLandingPage.component.tsx index 825d79c5e..5abcc7c62 100644 --- a/src/catalogue/items/catalogueItemsLandingPage.component.tsx +++ b/src/catalogue/items/catalogueItemsLandingPage.component.tsx @@ -7,7 +7,13 @@ import ListItem from '@mui/material/ListItem'; import ListItemText from '@mui/material/ListItemText'; import ExpandMoreIcon from '@mui/icons-material/ExpandMore'; import ExpandLessIcon from '@mui/icons-material/ExpandLess'; -import { Box, Button, Collapse, Link as MuiLink } from '@mui/material'; +import { + Box, + Button, + Collapse, + LinearProgress, + Link as MuiLink, +} from '@mui/material'; import { useCatalogueCategoryById } from '../../api/catalogueCategory'; function CatalogueItemsLandingPage() { @@ -213,19 +219,25 @@ function CatalogueItemsLandingPage() { )} - {!catalogueItemIdData && !catalogueItemIdDataLoading && ( - - No result found - - This item doesn't exist. Please click the Home button to navigate to - the catalogue home - + {!catalogueItemIdDataLoading ? ( + !catalogueItemIdData && ( + + No result found + + This item doesn't exist. Please click the Home button to navigate + to the catalogue home + + + ) + ) : ( + + )} From 7ec64e3464c8858698726468031eba2667aacd2c Mon Sep 17 00:00:00 2001 From: Joshua Kitenge <83226114+joshuadkitenge@users.noreply.github.com> Date: Wed, 18 Oct 2023 13:33:48 +0100 Subject: [PATCH 2/9] Update src/catalogue/items/catalogueItemsTable.component.test.tsx Co-authored-by: Joel Davies <90245114+joelvdavies@users.noreply.github.com> --- src/catalogue/items/catalogueItemsTable.component.test.tsx | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/catalogue/items/catalogueItemsTable.component.test.tsx b/src/catalogue/items/catalogueItemsTable.component.test.tsx index e45dde7b2..8ad66d0ca 100644 --- a/src/catalogue/items/catalogueItemsTable.component.test.tsx +++ b/src/catalogue/items/catalogueItemsTable.component.test.tsx @@ -109,7 +109,7 @@ describe('Catalogue Items Table', () => { }); }); - it('opens the delete catalogue item dialog', async () => { + it('opens the delete catalogue item dialog and can delete an item', async () => { createView(); await waitFor(() => { From 8d59c46e4c80ddd4683dd7ecf120fd7ce0863b82 Mon Sep 17 00:00:00 2001 From: Joshua Kitenge Date: Wed, 18 Oct 2023 12:45:26 +0000 Subject: [PATCH 3/9] formatitng --- src/catalogue/items/catalogueItemsTable.component.test.tsx | 1 + 1 file changed, 1 insertion(+) diff --git a/src/catalogue/items/catalogueItemsTable.component.test.tsx b/src/catalogue/items/catalogueItemsTable.component.test.tsx index 8ad66d0ca..adce0de72 100644 --- a/src/catalogue/items/catalogueItemsTable.component.test.tsx +++ b/src/catalogue/items/catalogueItemsTable.component.test.tsx @@ -123,6 +123,7 @@ describe('Catalogue Items Table', () => { const deleteButton = screen.getByRole('button', { name: 'Delete Energy Meters 26 catalogue item', }); + await user.click(deleteButton); await waitFor(() => { From 9de678855c918170c104d80856318fdf78bf734f Mon Sep 17 00:00:00 2001 From: Joshua Kitenge Date: Wed, 18 Oct 2023 14:56:58 +0000 Subject: [PATCH 4/9] add unit test for the loading indicator --- .../items/catalogueItemsLandingPage.component.test.tsx | 8 ++++++++ 1 file changed, 8 insertions(+) diff --git a/src/catalogue/items/catalogueItemsLandingPage.component.test.tsx b/src/catalogue/items/catalogueItemsLandingPage.component.test.tsx index 59d080fd5..860fc3295 100644 --- a/src/catalogue/items/catalogueItemsLandingPage.component.test.tsx +++ b/src/catalogue/items/catalogueItemsLandingPage.component.test.tsx @@ -73,6 +73,14 @@ describe('Catalogue Items Landing Page', () => { ).toBeInTheDocument(); }); }); + + it('shows the loading indicator', async () => { + createView('/inventory-management-system/catalogue/items/1'); + + await waitFor(() => { + expect(screen.getByRole('progressbar')).toBeInTheDocument(); + }); + }); it('toggles the manufacturer so it is either visible or hidden', async () => { createView('/inventory-management-system/catalogue/items/1'); await waitFor(() => { From 13feebaad9f4237ccc460f15cb5561b4b84e8e73 Mon Sep 17 00:00:00 2001 From: Joshua Kitenge Date: Thu, 19 Oct 2023 09:06:39 +0000 Subject: [PATCH 5/9] add extra check for url to match the backend --- cypress/e2e/catalogue/catalogueItems.cy.ts | 4 ++-- .../items/catalogueItemsDialog.component.test.tsx | 2 +- src/catalogue/items/catalogueItemsDialog.component.tsx | 7 +++++-- 3 files changed, 8 insertions(+), 5 deletions(-) diff --git a/cypress/e2e/catalogue/catalogueItems.cy.ts b/cypress/e2e/catalogue/catalogueItems.cy.ts index cd0c4de75..a7abe3146 100644 --- a/cypress/e2e/catalogue/catalogueItems.cy.ts +++ b/cypress/e2e/catalogue/catalogueItems.cy.ts @@ -120,13 +120,13 @@ describe('Catalogue Items', () => { cy.findByRole('button', { name: 'Save' }).click(); cy.findByText( - 'Please enter a valid Manufacturer URL. Only "http://" and "https://" links are accepted' + 'Please enter a valid Manufacturer URL. Only "http://" and "https://" links with typical top-level domain are accepted' ).should('exist'); cy.findByLabelText('Manufacturer URL *').clear(); cy.findByLabelText('Manufacturer URL *').type('https://test.co.uk'); cy.findByText( - 'Please enter a valid Manufacturer URL. Only "http://" and "https://" links are accepted' + 'Please enter a valid Manufacturer URL. Only "http://" and "https://" links with typical top-level domain are accepted' ).should('not.exist'); }); diff --git a/src/catalogue/items/catalogueItemsDialog.component.test.tsx b/src/catalogue/items/catalogueItemsDialog.component.test.tsx index 8880480a2..f3a563988 100644 --- a/src/catalogue/items/catalogueItemsDialog.component.test.tsx +++ b/src/catalogue/items/catalogueItemsDialog.component.test.tsx @@ -399,7 +399,7 @@ describe('Catalogue Items Dialog', () => { expect( screen.getByText( - 'Please enter a valid Manufacturer URL. Only "http://" and "https://" links are accepted' + 'Please enter a valid Manufacturer URL. Only "http://" and "https://" links with typical top-level domain are accepted' ) ).toBeInTheDocument(); }); diff --git a/src/catalogue/items/catalogueItemsDialog.component.tsx b/src/catalogue/items/catalogueItemsDialog.component.tsx index 3ec08b509..6cec19321 100644 --- a/src/catalogue/items/catalogueItemsDialog.component.tsx +++ b/src/catalogue/items/catalogueItemsDialog.component.tsx @@ -58,7 +58,10 @@ export interface CatalogueItemsDialogProps { function isValidUrl(url: string) { try { const parsedUrl = new URL(url); - return parsedUrl.protocol === 'http:' || parsedUrl.protocol === 'https:'; + return ( + (parsedUrl.protocol === 'http:' || parsedUrl.protocol === 'https:') && + parsedUrl.hostname.includes('.') // Checks for the typical top-level domain + ); } catch (error) { return false; } @@ -354,7 +357,7 @@ function CatalogueItemsDialog(props: CatalogueItemsDialogProps) { setManufacturerWebUrlErrorMessage( !catalogueItemManufacturer.web_url.trim() ? 'Please enter a Manufacturer URL' - : 'Please enter a valid Manufacturer URL. Only "http://" and "https://" links are accepted' + : 'Please enter a valid Manufacturer URL. Only "http://" and "https://" links with typical top-level domain are accepted' ); hasErrors = true; } From b579c9b357720c9ba37206473a401f94a8881b8f Mon Sep 17 00:00:00 2001 From: Joshua Kitenge <83226114+joshuadkitenge@users.noreply.github.com> Date: Thu, 19 Oct 2023 12:55:17 +0100 Subject: [PATCH 6/9] Apply suggestions from code review Co-authored-by: Joel Davies <90245114+joelvdavies@users.noreply.github.com> --- cypress/e2e/catalogue/catalogueItems.cy.ts | 2 +- src/catalogue/items/catalogueItemsDialog.component.test.tsx | 2 +- .../items/catalogueItemsLandingPage.component.test.tsx | 2 +- 3 files changed, 3 insertions(+), 3 deletions(-) diff --git a/cypress/e2e/catalogue/catalogueItems.cy.ts b/cypress/e2e/catalogue/catalogueItems.cy.ts index a7abe3146..e26c49ccc 100644 --- a/cypress/e2e/catalogue/catalogueItems.cy.ts +++ b/cypress/e2e/catalogue/catalogueItems.cy.ts @@ -240,7 +240,7 @@ describe('Catalogue Items', () => { }); }); - it('displays error message if not of the field have been edited', () => { + it('displays error message if none of the fields have been edited', () => { cy.visit( '/inventory-management-system/catalogue/beam-characterization/energy-meters' ); diff --git a/src/catalogue/items/catalogueItemsDialog.component.test.tsx b/src/catalogue/items/catalogueItemsDialog.component.test.tsx index f3a563988..36ec4f4a1 100644 --- a/src/catalogue/items/catalogueItemsDialog.component.test.tsx +++ b/src/catalogue/items/catalogueItemsDialog.component.test.tsx @@ -349,7 +349,7 @@ describe('Catalogue Items Dialog', () => { expect(onClose).toHaveBeenCalled(); }); - it('display error message when invalid number format', async () => { + it('display error message when invalid number format in property values and invalid manufacturer url', async () => { props = { ...props, parentId: '4', diff --git a/src/catalogue/items/catalogueItemsLandingPage.component.test.tsx b/src/catalogue/items/catalogueItemsLandingPage.component.test.tsx index 886eed5e0..b0409035d 100644 --- a/src/catalogue/items/catalogueItemsLandingPage.component.test.tsx +++ b/src/catalogue/items/catalogueItemsLandingPage.component.test.tsx @@ -95,7 +95,7 @@ describe('Catalogue Items Landing Page', () => { }); }); - it('opens the edit catalogue item dialog', async () => { + it('opens and closes the edit catalogue item dialog', async () => { createView('/inventory-management-system/catalogue/items/1'); await waitFor(() => { From 522f7de9f6d6fbb760d6d83aff17763c5d3bfdd2 Mon Sep 17 00:00:00 2001 From: Joshua Kitenge Date: Thu, 19 Oct 2023 13:06:50 +0100 Subject: [PATCH 7/9] address review comments --- src/catalogue/items/catalogueItemsDialog.component.test.tsx | 4 ++-- src/catalogue/items/catalogueItemsDialog.component.tsx | 2 +- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/src/catalogue/items/catalogueItemsDialog.component.test.tsx b/src/catalogue/items/catalogueItemsDialog.component.test.tsx index 36ec4f4a1..47e61083f 100644 --- a/src/catalogue/items/catalogueItemsDialog.component.test.tsx +++ b/src/catalogue/items/catalogueItemsDialog.component.test.tsx @@ -254,7 +254,7 @@ describe('Catalogue Items Dialog', () => { expect( screen.getByText( - 'Please enter a valid Manufacturer URL. Only "http://" and "https://" links are accepted' + 'Please enter a valid Manufacturer URL. Only "http://" and "https://" links with typical top-level domain are accepted' ) ).toBeInTheDocument(); @@ -724,7 +724,7 @@ describe('Catalogue Items Dialog', () => { ); }); - it('displays error message if no form fields have been changed', async () => { + it('displays error message if no fields have been changed (when they are no catalogue property fields)', async () => { props = { ...props, parentId: '1', diff --git a/src/catalogue/items/catalogueItemsDialog.component.tsx b/src/catalogue/items/catalogueItemsDialog.component.tsx index 6cec19321..55048a9a6 100644 --- a/src/catalogue/items/catalogueItemsDialog.component.tsx +++ b/src/catalogue/items/catalogueItemsDialog.component.tsx @@ -216,7 +216,7 @@ function CatalogueItemsDialog(props: CatalogueItemsDialogProps) { setManufacturerWebUrlErrorMessage( !catalogueItemManufacturer.web_url.trim() ? 'Please enter a Manufacturer URL' - : 'Please enter a valid Manufacturer URL. Only "http://" and "https://" links are accepted' + : 'Please enter a valid Manufacturer URL. Only "http://" and "https://" links with typical top-level domain are accepted' ); hasErrors = true; } From ed6f4c42730163c68182a418b955fd7019c8eea9 Mon Sep 17 00:00:00 2001 From: Joshua Kitenge Date: Thu, 19 Oct 2023 16:04:11 +0000 Subject: [PATCH 8/9] stop msw running in development if there is a apiUrl --- src/index.tsx | 12 +++++++++++- src/mocks/handlers.ts | 4 ++-- 2 files changed, 13 insertions(+), 3 deletions(-) diff --git a/src/index.tsx b/src/index.tsx index d7cca1586..0914fee36 100644 --- a/src/index.tsx +++ b/src/index.tsx @@ -174,13 +174,23 @@ function prepare() { } const settings = fetchSettings(); + setSettings(settings); if ( process.env.NODE_ENV === 'development' || process.env.REACT_APP_E2E_TESTING ) { - prepare().then(() => render()); + settings + .then((settings) => { + if (settings && settings.apiUrl !== '') { + render(); + } else { + prepare().then(() => render()); + } + }) + .catch((error) => log.error(`Got error: ${error.message}`)); + log.setDefaultLevel(log.levels.DEBUG); } else { log.setDefaultLevel(log.levels.ERROR); diff --git a/src/mocks/handlers.ts b/src/mocks/handlers.ts index f917f1601..555cc384c 100644 --- a/src/mocks/handlers.ts +++ b/src/mocks/handlers.ts @@ -123,7 +123,7 @@ export const handlers = [ }) ); } else { - return res(ctx.status(200), ctx.json('')); + return res(ctx.status(204)); } } else { return res(ctx.status(400), ctx.json('')); @@ -183,7 +183,7 @@ export const handlers = [ }) ); } else { - return res(ctx.status(200), ctx.json('')); + return res(ctx.status(204)); } } else { return res(ctx.status(400), ctx.json('')); From 2b164065fa5e4fbf139c5f221b1cd671402d103d Mon Sep 17 00:00:00 2001 From: Joshua Kitenge Date: Fri, 20 Oct 2023 11:14:09 +0100 Subject: [PATCH 9/9] fix e2e test --- cypress/e2e/catalogue/catalogueCategory.cy.ts | 13 +++------ cypress/e2e/catalogue/catalogueItems.cy.ts | 2 +- cypress/support/commands.ts | 28 +++++++++++++++++-- src/index.tsx | 7 +++-- 4 files changed, 35 insertions(+), 15 deletions(-) diff --git a/cypress/e2e/catalogue/catalogueCategory.cy.ts b/cypress/e2e/catalogue/catalogueCategory.cy.ts index 064d88045..ab275e6cd 100644 --- a/cypress/e2e/catalogue/catalogueCategory.cy.ts +++ b/cypress/e2e/catalogue/catalogueCategory.cy.ts @@ -277,15 +277,10 @@ describe('Catalogue Category', () => { }); it('when root has no data it displays no catagories error message', () => { - cy.window().then(async (window) => { - // Reference global instances set in "src/mocks/browser.js". - - const { worker, rest } = window.msw; - worker.use( - rest.get('/v1/catalogue-categories/', (req, res, ctx) => { - return res(ctx.status(200), ctx.json([])); - }) - ); + cy.editEndpointResponse({ + url: '/v1/catalogue-categories/', + data: [], + statusCode: 200, }); cy.findByText( 'There are no catalogue categories. Please add a category using the plus icon in the top left of your screen' diff --git a/cypress/e2e/catalogue/catalogueItems.cy.ts b/cypress/e2e/catalogue/catalogueItems.cy.ts index d8aa733e5..f003ab7be 100644 --- a/cypress/e2e/catalogue/catalogueItems.cy.ts +++ b/cypress/e2e/catalogue/catalogueItems.cy.ts @@ -137,7 +137,7 @@ describe('Catalogue Items', () => { cy.findByText('Cameras 4').should('exist'); }); - it.only('navigates to the landing page, toggles the properties and navigates back to the table view', () => { + it('navigates to the landing page, toggles the properties and navigates back to the table view', () => { cy.findByText('Cameras 1').click(); cy.findByText( 'High-resolution cameras for beam characterization. 1' diff --git a/cypress/support/commands.ts b/cypress/support/commands.ts index cba8d3ceb..e7d950bb5 100644 --- a/cypress/support/commands.ts +++ b/cypress/support/commands.ts @@ -43,6 +43,18 @@ Cypress.Commands.add('clearMocks', () => { mockedRequests = []; }); +Cypress.Commands.add('editEndpointResponse', ({ url, data, statusCode }) => { + cy.window().then((window) => { + const { worker, rest } = window.msw; + + worker.use( + rest.get(url, (req, res, ctx) => { + return res(ctx.status(statusCode), ctx.json(data)); + }) + ); + }); +}); + Cypress.Commands.add('startSnoopingBrowserMockedRequest', () => { cy.window().then((window) => { const worker = window?.msw?.worker; @@ -91,12 +103,12 @@ declare global { * Clear all mocks * @example cy.clearMocks() */ - clearMocks(): Chainable> + clearMocks(): Chainable>; /** * Use before findBrowserMockedRequests for checking specific requests were sent * @example cy.startSnoopingBrowserMockedRequest() */ - startSnoopingBrowserMockedRequest(): Chainable> + startSnoopingBrowserMockedRequest(): Chainable>; /** * Returns a request that was recorded after 'startSnoopingBrowserMockedRequest' was called * @@ -113,7 +125,17 @@ declare global { ); }); */ - findBrowserMockedRequests({method, url}: any): Chainable + editEndpointResponse({ url, data, statusCode }: any): Chainable; + /** + * Edits the response of the endpoint request + * + * @example cy.editEndpointResponse({ + url: '/v1/catalogue-categories/', + data: [], + statusCode: 200, + }); + */ + findBrowserMockedRequests({ method, url }: any): Chainable; } } } diff --git a/src/index.tsx b/src/index.tsx index 0914fee36..8945a8334 100644 --- a/src/index.tsx +++ b/src/index.tsx @@ -178,8 +178,8 @@ const settings = fetchSettings(); setSettings(settings); if ( - process.env.NODE_ENV === 'development' || - process.env.REACT_APP_E2E_TESTING + process.env.NODE_ENV === 'development' && + !process.env.REACT_APP_E2E_TESTING ) { settings .then((settings) => { @@ -191,6 +191,9 @@ if ( }) .catch((error) => log.error(`Got error: ${error.message}`)); + log.setDefaultLevel(log.levels.DEBUG); +} else if (process.env.REACT_APP_E2E_TESTING) { + prepare().then(() => render()); log.setDefaultLevel(log.levels.DEBUG); } else { log.setDefaultLevel(log.levels.ERROR);