Skip to content

Commit

Permalink
Merge pull request #115 from ral-facilities/view-systems-#18
Browse files Browse the repository at this point in the history
View systems #18
  • Loading branch information
joelvdavies authored Nov 10, 2023
2 parents 91e7100 + 9d9df42 commit 6ce62a5
Show file tree
Hide file tree
Showing 11 changed files with 474 additions and 84 deletions.
46 changes: 46 additions & 0 deletions cypress/e2e/system.cy.ts
Original file line number Diff line number Diff line change
Expand Up @@ -12,6 +12,52 @@ describe('System', () => {
cy.findByText('Giant laser').should('be.visible');
});

it('should be able to navigate through subsystems', () => {
cy.findByText('No system selected').should('be.visible');
cy.findByText('Please select a system').should('be.visible');

// Navigate deeper
cy.findByRole('link', { name: 'Giant laser' }).click();
cy.url().should('include', '/systems/65328f34a40ff5301575a4e3');
cy.findByText('No system selected').should('not.exist');
cy.findByText('Please select a system').should('not.exist');

cy.findByText('Smaller laser').should('be.visible');
cy.findByText('Description').should('be.visible');

// Navigate deeper again
cy.findByRole('link', { name: 'Smaller laser' }).click();
cy.url().should('include', '/systems/65328f34a40ff5301575a4e4');

cy.findByText('Pulse Laser').should('be.visible');
cy.findByText('Description').should('be.visible');
});

it('breadcrumbs should work correctly', () => {
cy.visit('/inventory-management-system/systems/65328f34a40ff5301575a4e9');

cy.findByRole('link', { name: 'Pulse Laser' }).should('be.visible');
cy.findByRole('link', { name: 'Giant laser' }).should('be.visible');
cy.findByRole('link', { name: 'Laser Star' }).should('be.visible');
cy.findByRole('link', { name: 'Smaller laser' }).should('be.visible');

// One in title, one in breadcrumbs
cy.findAllByText('Plasma Beam').should('have.length', 2);

// Check can navigate back with breadcrumbs
cy.findByRole('link', { name: 'Giant laser' }).click();
cy.url().should('include', '/systems/65328f34a40ff5301575a4e6');
cy.findAllByText('Giant laser').should('have.length', 2);

// Check can go back to root
cy.findByRole('button', { name: 'navigate to systems home' }).click();
cy.url().then((url) => {
expect(url.endsWith('/systems'));
});
cy.findByText('No system selected').should('be.visible');
cy.findByText('Please select a system').should('be.visible');
});

it('adds a root system with only required parameters', () => {
cy.findByRole('button', { name: 'add system' }).click();

Expand Down
39 changes: 37 additions & 2 deletions src/api/systems.test.tsx
Original file line number Diff line number Diff line change
@@ -1,9 +1,14 @@
import { renderHook, waitFor } from '@testing-library/react';
import { AddSystem, SystemImportanceType } from '../app.types';
import SystemBreadcrumbsJSON from '../mocks/SystemBreadcrumbs.json';
import SystemsJSON from '../mocks/Systems.json';
import { hooksWrapperWithProviders } from '../setupTests';
import { useAddSystem, useSystems, useSystemsBreadcrumbs } from './systems';
import { SystemImportanceType, AddSystem } from '../app.types';
import {
useAddSystem,
useSystem,
useSystems,
useSystemsBreadcrumbs,
} from './systems';

describe('System api functions', () => {
afterEach(() => {
Expand Down Expand Up @@ -59,6 +64,36 @@ describe('System api functions', () => {
});
});

describe('useSystem', () => {
it('does not send a request when given an id of null', async () => {
const { result } = renderHook(() => useSystem(null), {
wrapper: hooksWrapperWithProviders(),
});

expect(result.current.isFetching).toBeFalsy();
expect(result.current.data).toEqual(undefined);
});

it('sends request to fetch a system and returns successful response', async () => {
const { result } = renderHook(
() => useSystem('65328f34a40ff5301575a4e3'),
{
wrapper: hooksWrapperWithProviders(),
}
);

await waitFor(() => {
expect(result.current.isSuccess).toBeTruthy();
});

expect(result.current.data).toEqual(
SystemsJSON.filter(
(system) => system.id === '65328f34a40ff5301575a4e3'
)[0]
);
});
});

describe('useSystemsBreadcrumbs', () => {
it('does not send a request to fetch breadcrumbs data for a system when its id is null', async () => {
const { result } = renderHook(() => useSystemsBreadcrumbs(null), {
Expand Down
52 changes: 51 additions & 1 deletion src/api/systems.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -6,9 +6,28 @@ import {
useQueryClient,
} from '@tanstack/react-query';
import axios, { AxiosError } from 'axios';
import { BreadcrumbsInfo, System, AddSystem } from '../app.types';
import {
AddSystem,
BreadcrumbsInfo,
System,
SystemImportanceType,
} from '../app.types';
import { settings } from '../settings';

/** Utility for turning an importance into an MUI palette colour to display */
export const getSystemImportanceColour = (
importance: SystemImportanceType
): 'success' | 'warning' | 'error' => {
switch (importance) {
case SystemImportanceType.LOW:
return 'success';
case SystemImportanceType.MEDIUM:
return 'warning';
case SystemImportanceType.HIGH:
return 'error';
}
};

const fetchSystems = async (parent_id?: string): Promise<System[]> => {
let apiUrl: string;
apiUrl = '';
Expand Down Expand Up @@ -43,6 +62,37 @@ export const useSystems = (
);
};

const fetchSystem = async (id: string): Promise<System> => {
let apiUrl: string;
apiUrl = '';
const settingsResult = await settings;
if (settingsResult) {
apiUrl = settingsResult['apiUrl'];
}

return axios.get(`${apiUrl}/v1/systems/${id}`).then((response) => {
return response.data;
});
};

// Allows a value of null to disable
export const useSystem = (
id: string | null
): UseQueryResult<System, AxiosError> => {
return useQuery<System, AxiosError>(
['System', id],
() => {
return fetchSystem(id ?? '');
},
{
enabled: id !== null,
onError: (error) => {
console.log('Got error ' + error.message);
},
}
);
};

const fetchSystemsBreadcrumbs = async (
id: string
): Promise<BreadcrumbsInfo> => {
Expand Down
10 changes: 5 additions & 5 deletions src/mocks/Systems.json
Original file line number Diff line number Diff line change
@@ -1,10 +1,10 @@
[
{
"name": "Giant laser",
"location": "80371 Alvarado Drive Apt. 272\nHeatherhaven, MP 33307",
"location": "80371 Alvarado Drive Apt. 272, Heatherhaven, MP 33307",
"owner": "Juan Horton",
"importance": "high",
"description": "Take Democrat early money some. Tree meet fly her likely.",
"description": "Take Democrat early money some.\nTree meet fly her likely.",
"parent_id": null,
"id": "65328f34a40ff5301575a4e3",
"code": "laser-tech"
Expand All @@ -21,10 +21,10 @@
},
{
"name": "Pulse Laser",
"location": "8988 Richard Mews\nCatherinemouth, IL 68034",
"owner": "Sarah Parker",
"location": null,
"owner": null,
"importance": "medium",
"description": "State still last to think.",
"description": null,
"parent_id": "65328f34a40ff5301575a4e4",
"id": "65328f34a40ff5301575a4e5",
"code": "pulse-laser"
Expand Down
11 changes: 11 additions & 0 deletions src/mocks/handlers.ts
Original file line number Diff line number Diff line change
Expand Up @@ -372,6 +372,17 @@ export const handlers = [
return res(ctx.status(200), ctx.json(data));
}),

rest.get('/v1/systems/:id', (req, res, ctx) => {
const { id } = req.params;
const data = SystemsJSON.filter((system) => system.id === id);
if (data.length > 0) return res(ctx.status(200), ctx.json(data[0]));
else
return res(
ctx.status(404),
ctx.json({ detail: 'A System with such ID was not found' })
);
}),

rest.get('/v1/systems/:id/breadcrumbs', (req, res, ctx) => {
const { id } = req.params;
const data = SystemBreadcrumbsJSON.find(
Expand Down
10 changes: 9 additions & 1 deletion src/systems/__snapshots__/systemDialog.component.test.tsx.snap
Original file line number Diff line number Diff line change
Expand Up @@ -239,7 +239,15 @@ exports[`Systems Dialog renders correctly when adding 1`] = `
role="button"
tabindex="0"
>
medium
<div
class="MuiChip-root MuiChip-filled MuiChip-sizeMedium MuiChip-colorWarning MuiChip-filledWarning css-1mtfbl3-MuiChip-root"
>
<span
class="MuiChip-label MuiChip-labelMedium css-6od3lo-MuiChip-label"
>
medium
</span>
</div>
</div>
<input
aria-hidden="true"
Expand Down
79 changes: 79 additions & 0 deletions src/systems/systemDetails.component.test.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,79 @@
import { screen, waitFor } from '@testing-library/react';
import React from 'react';
import { System } from '../app.types';
import { renderComponentWithBrowserRouter } from '../setupTests';
import SystemsJSON from '../mocks/Systems.json';
import SystemDetails, { SystemDetailsProps } from './systemDetails.component';

describe('SystemDetails', () => {
let props: SystemDetailsProps;
let mockSystemDetails: System;

const createView = () => {
if (props.id)
mockSystemDetails = SystemsJSON.filter(
(system) => system.id === props.id
)[0];
return renderComponentWithBrowserRouter(<SystemDetails {...props} />);
};

beforeEach(() => {
props = {
id: '65328f34a40ff5301575a4e3',
};
});

it('renders correctly when no system is selected', async () => {
props.id = null;

createView();

expect(screen.getByText('No system selected')).toBeInTheDocument();
expect(screen.getByText('Please select a system')).toBeInTheDocument();
});

it('renders correctly when a system is selected', async () => {
createView();

await waitFor(() => {
expect(screen.getByText(mockSystemDetails.name)).toBeInTheDocument();
});
expect(screen.queryByText('Please select a system')).toBeFalsy();
expect(
screen.getByText(mockSystemDetails.location ?? '')
).toBeInTheDocument();
expect(screen.getByText(mockSystemDetails.owner ?? '')).toBeInTheDocument();
expect(
screen.getByText(mockSystemDetails.importance ?? '')
).toBeInTheDocument();
// Can have new line character which breaks normal matching
expect(
screen.getByText(
(_, element) => element?.textContent === mockSystemDetails.description
)
).toBeInTheDocument();
});

it('renders correctly when a system with only required values is selected', async () => {
props.id = '65328f34a40ff5301575a4e5';
createView();

await waitFor(() => {
expect(screen.getByText(mockSystemDetails.name)).toBeInTheDocument();
});
expect(screen.queryByText('Please select a system')).toBeFalsy();
// One for each of location, owner and description
expect(await screen.findAllByText('None')).toHaveLength(3);
});

it('renders correctly when the system is not found', async () => {
props.id = 'invalid_id';

createView();

await waitFor(() => {
expect(screen.getByText('No system selected')).toBeInTheDocument();
});
expect(screen.getByText('Please select a system')).toBeInTheDocument();
});
});
Loading

0 comments on commit 6ce62a5

Please sign in to comment.