Skip to content

Commit 09204f9

Browse files
Merge pull request #1717 from ral-facilities/catalogue-items-flaggging-#1656
Catalogue items flagging #1656
2 parents 90299b4 + 630853a commit 09204f9

38 files changed

+2288
-398
lines changed

cypress/e2e/with_api/catalogueCategories/functions.ts

Lines changed: 4 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -258,13 +258,15 @@ export const addCatalogueCategories = (ignoreChecks?: boolean) => {
258258
};
259259

260260
export const editCatalogueCategories = () => {
261-
cy.findByRole('button', { name: 'navigate to catalogue home' }).click();
262-
cy.findByText('Spherical Lenses').should('not.exist');
261+
cy.get('body').type('{esc}');
263262
cy.intercept({
264263
method: 'GET',
265264
url: '**/catalogue-categories?parent_id=null',
266265
}).as('getCatalogueCategoryDataRoot');
266+
cy.findByRole('button', { name: 'navigate to catalogue home' }).click();
267267
cy.wait('@getCatalogueCategoryDataRoot', { timeout: 10000 });
268+
cy.findByText('Spherical Lenses').should('not.exist');
269+
268270
cy.findByText('Lenses').should('exist');
269271

270272
modifyCatalogueCategory({

cypress/e2e/with_api/catalogueItems/functions.ts

Lines changed: 4 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -254,6 +254,7 @@ export const copyToCatalogueItems = (values: { checkedItems: string[] }) => {
254254
}
255255
cy.go('back');
256256
cy.go('back');
257+
cy.go('back');
257258
};
258259

259260
export const moveToCatalogueItems = (values: { checkedItems: string[] }) => {
@@ -454,9 +455,10 @@ export const downloadFile = (
454455
cy.findByLabelText(`Download ${fileName} attachment`).click();
455456
}
456457

457-
cy.findByRole('dialog').should('be.visible');
458+
cy.findByRole('dialog').should('exist');
458459

459460
cy.findByRole('button', { name: 'Continue' }).click();
461+
cy.findByRole('dialog').should('not.exist');
460462
};
461463

462464
export const deleteFile = (
@@ -476,7 +478,7 @@ export const deleteFile = (
476478
cy.findByLabelText(`Delete attachment ${fileName}`).click();
477479
}
478480

479-
cy.findByRole('dialog').should('be.visible');
481+
cy.findByRole('dialog').should('exist');
480482

481483
cy.findByRole('button', { name: 'Continue' }).click();
482484
});

cypress/e2e/with_api/systems/functions.ts

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -216,7 +216,7 @@ export const navigateToItemsTableViaSpares = () => {
216216
cy.findByText('Number of spares').should('exist');
217217
// eslint-disable-next-line cypress/no-unnecessary-waiting
218218
cy.wait(1000);
219-
cy.findByRole('link', { name: '1' }).click();
219+
cy.findAllByRole('link', { name: '1' }).first().click();
220220
cy.findByText('MX432424').should('exist');
221221

222222
// Catalogue items landing page
@@ -226,7 +226,7 @@ export const navigateToItemsTableViaSpares = () => {
226226
// eslint-disable-next-line cypress/no-unnecessary-waiting
227227
cy.wait(100);
228228
cy.findByText('Number of spares').should('exist');
229-
cy.findByRole('link', { name: '1' }).click();
229+
cy.findAllByRole('link', { name: '1' }).first().click();
230230
cy.findByText('MX432424').should('exist');
231231
cy.visit('/systems');
232232
};

cypress/e2e/with_mock_data/catalogueItems.cy.ts

Lines changed: 41 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -86,7 +86,7 @@ describe('Catalogue Items', () => {
8686
it('navigates to items page with spares definition applied', () => {
8787
cy.visit('/catalogue/9/items');
8888

89-
cy.findByRole('link', { name: '1' }).click();
89+
cy.findAllByRole('link', { name: '1' }).first().click();
9090

9191
cy.findByText('dfzqkOJbqifO').should('exist');
9292

@@ -96,7 +96,7 @@ describe('Catalogue Items', () => {
9696
it('navigates to items page with spares definition applied (from landing page)', () => {
9797
cy.visit('/catalogue/9/items/11');
9898

99-
cy.findByRole('link', { name: '1' }).click();
99+
cy.findAllByRole('link', { name: '1' }).first().click();
100100

101101
cy.findByText('dfzqkOJbqifO').should('exist');
102102

@@ -113,7 +113,7 @@ describe('Catalogue Items', () => {
113113

114114
cy.findAllByLabelText('Expand').eq(1).click();
115115

116-
cy.findByRole('link', { name: '1' }).click();
116+
cy.findAllByRole('link', { name: '1' }).first().click();
117117

118118
cy.findByText('dfzqkOJbqifO').should('exist');
119119

@@ -429,6 +429,29 @@ describe('Catalogue Items', () => {
429429
cy.findByText('Cameras 4').should('exist');
430430
});
431431

432+
it('displays the table view correctly (Criticality)', () => {
433+
cy.visit('/catalogue/6');
434+
435+
cy.setMode({ critical: true });
436+
cy.findByText('Wavefront Sensors 31').should('exist');
437+
cy.findByText('Wavefront Sensors 30').should('exist');
438+
439+
cy.findByTestId('ErrorIcon').should('exist');
440+
cy.findByTestId('ErrorIcon').trigger('mouseover');
441+
cy.findByText('This catalogue item is critical.').should('exist');
442+
});
443+
444+
it('displays the catalogue item landing page (Criticality)', () => {
445+
cy.visit('/catalogue/6/items/10');
446+
447+
cy.setMode({ critical: true });
448+
449+
cy.findByTestId('ErrorIcon').should('exist');
450+
cy.findByTestId('ErrorIcon').trigger('mouseover');
451+
cy.findByText('This catalogue item is critical.').should('exist');
452+
cy.findAllByText('-4.6').should('have.length', 2);
453+
});
454+
432455
it('navigates to the landing page and navigates back to the table view', () => {
433456
cy.findByText('Cameras 1').click();
434457
cy.findByText(
@@ -502,8 +525,6 @@ describe('Catalogue Items', () => {
502525
cy.url().should('contain', '/manufacturers/1');
503526
});
504527

505-
506-
507528
it('checks the href property of the manufacturer link', () => {
508529
cy.findByRole('button', { name: 'Show/Hide columns' }).click();
509530
cy.findByText('Hide all').click();
@@ -758,6 +779,7 @@ describe('Catalogue Items', () => {
758779
});
759780

760781
it('check table state persists on page reload', () => {
782+
cy.setMode({ critical: false });
761783
cy.findByText('Cameras 1').should('exist');
762784
cy.findByRole('button', { name: 'Clear Filters' }).should('be.disabled');
763785

@@ -940,7 +962,14 @@ describe('Catalogue Items', () => {
940962
it('can navigate to an items page from the table view', () => {
941963
cy.visit('/catalogue/5');
942964

943-
cy.findAllByRole('link', { name: 'Click here' }).eq(0).click();
965+
cy.findAllByRole('link', { name: 'Click here' }).first().scrollIntoView();
966+
cy.findAllByRole('link', { name: 'Click here' })
967+
.first()
968+
.should('be.visible');
969+
970+
cy.findAllByRole('link', { name: 'Click here' })
971+
.first()
972+
.click({ force: true });
944973

945974
cy.url().should('contain', 'catalogue/5/items/89/items');
946975
});
@@ -1102,6 +1131,9 @@ describe('Catalogue Items', () => {
11021131
created_time: '2024-01-01T12:00:00.000+00:00',
11031132
modified_time: '2024-01-02T13:10:10.000+00:00',
11041133
number_of_spares: 0,
1134+
number_of_spares_required: null,
1135+
criticality: null,
1136+
is_flagged: false,
11051137
})
11061138
);
11071139
expect(JSON.stringify(await patchRequests[1].json())).equal(
@@ -1128,6 +1160,9 @@ describe('Catalogue Items', () => {
11281160
created_time: '2024-01-01T12:00:00.000+00:00',
11291161
modified_time: '2024-01-02T13:10:10.000+00:00',
11301162
number_of_spares: 0,
1163+
number_of_spares_required: null,
1164+
criticality: null,
1165+
is_flagged: false,
11311166
})
11321167
);
11331168
});

cypress/e2e/with_mock_data/items.cy.ts

Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -50,6 +50,17 @@ describe('Items', () => {
5050
cy.findByText('Cameras 3').should('be.visible');
5151
});
5252

53+
it('displays the item landing page (Criticality)', () => {
54+
cy.visit('/catalogue/6/items/10/items/pZT8K0aP');
55+
56+
cy.setMode({ critical: true });
57+
58+
cy.findByTestId('ErrorIcon').should('exist');
59+
cy.findByTestId('ErrorIcon').trigger('mouseover');
60+
cy.findByText('This catalogue item is critical.').should('exist');
61+
cy.findAllByText('(Item Details)').should('exist');
62+
});
63+
5364
it('should be able to navigate back to the catalogue home', () => {
5465
cy.findByRole('button', { name: 'navigate to catalogue home' }).click();
5566
cy.findByText('Motion').should('be.visible');

src/App.tsx

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -27,6 +27,7 @@ import CatalogueLayout, {
2727
catalogueLayoutLoader,
2828
} from './catalogue/catalogueLayout.component';
2929
import CatalogueCardView from './catalogue/category/catalogueCardView.component';
30+
import CatalogueItemLayout from './catalogue/items/catalogueItemLayout.component';
3031
import CatalogueItemsLandingPage from './catalogue/items/catalogueItemsLandingPage.component';
3132
import CatalogueItemsPage from './catalogue/items/catalogueItemsPage.component';
3233
import SettingsMenuItems from './common/settingsMenuItems.component';
@@ -155,7 +156,7 @@ const routeObject: RouteObject[] = [
155156
},
156157
{
157158
path: paths.catalogueItem,
158-
Component: Outlet,
159+
Component: CatalogueItemLayout,
159160
children: [
160161
{
161162
index: true,

src/api/api.types.tsx

Lines changed: 20 additions & 16 deletions
Original file line numberDiff line numberDiff line change
@@ -26,6 +26,10 @@ export interface Rule {
2626
export interface SparesDefinition {
2727
system_types: SystemType[];
2828
}
29+
30+
// ------------------------------------- IN USE -----------------------------------------------------
31+
32+
export type InUseDefinition = SparesDefinition;
2933
// ------------------------------------ MANUFACTURERS -----------------------------------------------
3034

3135
interface AddressPost {
@@ -46,14 +50,14 @@ export interface ManufacturerPost {
4650
telephone?: string | null;
4751
}
4852

49-
export interface ManufacturerPatch
50-
extends Partial<Omit<ManufacturerPost, 'address'>> {
53+
export interface ManufacturerPatch extends Partial<
54+
Omit<ManufacturerPost, 'address'>
55+
> {
5156
address?: AddressPatch;
5257
}
5358

5459
export interface Manufacturer
55-
extends Required<Omit<ManufacturerPost, 'address'>>,
56-
CreatedModifiedMixin {
60+
extends Required<Omit<ManufacturerPost, 'address'>>, CreatedModifiedMixin {
5761
id: string;
5862
code: string;
5963
address: Address;
@@ -138,8 +142,7 @@ export interface CatalogueCategoryPostProperty {
138142
allowed_values?: AllowedValues | null;
139143
}
140144

141-
export interface CatalogueCategoryPropertyPost
142-
extends CatalogueCategoryPostProperty {
145+
export interface CatalogueCategoryPropertyPost extends CatalogueCategoryPostProperty {
143146
// eslint-disable-next-line @typescript-eslint/no-explicit-any
144147
default_value: any;
145148
}
@@ -150,8 +153,7 @@ export interface CatalogueCategoryPropertyPatch {
150153
unit_id?: string | null;
151154
}
152155

153-
export interface CatalogueCategoryProperty
154-
extends Required<CatalogueCategoryPostProperty> {
156+
export interface CatalogueCategoryProperty extends Required<CatalogueCategoryPostProperty> {
155157
id: string;
156158
unit: string | null;
157159
}
@@ -166,7 +168,8 @@ export interface CatalogueCategoryPost {
166168
export type CatalogueCategoryPatch = Partial<CatalogueCategoryPost>;
167169

168170
export interface CatalogueCategory
169-
extends Required<Omit<CatalogueCategoryPost, 'properties'>>,
171+
extends
172+
Required<Omit<CatalogueCategoryPost, 'properties'>>,
170173
CreatedModifiedMixin {
171174
id: string;
172175
code: string;
@@ -208,11 +211,15 @@ export interface CatalogueItemPost {
208211

209212
export type CatalogueItemPatch = Partial<CatalogueItemPost>;
210213
export interface CatalogueItem
211-
extends CreatedModifiedMixin,
214+
extends
215+
CreatedModifiedMixin,
212216
Required<Omit<CatalogueItemPost, 'properties'>> {
213217
id: string;
214218
properties: Property[];
215219
number_of_spares: number | null;
220+
number_of_spares_required: number | null;
221+
criticality: number | null;
222+
is_flagged: boolean | null;
216223
}
217224

218225
// ------------------------------------ ITEMS ------------------------------------------------
@@ -234,8 +241,7 @@ export interface ItemPost {
234241
export type ItemPatch = Partial<ItemPost>;
235242

236243
export interface Item
237-
extends CreatedModifiedMixin,
238-
Required<Omit<ItemPost, 'properties'>> {
244+
extends CreatedModifiedMixin, Required<Omit<ItemPost, 'properties'>> {
239245
id: string;
240246
usage_status: string;
241247
properties: Property[];
@@ -265,8 +271,7 @@ export interface AttachmentUploadInfo {
265271
}
266272

267273
export interface AttachmentMetadata
268-
extends Required<AttachmentPostMetadata>,
269-
CreatedModifiedMixin {
274+
extends Required<AttachmentPostMetadata>, CreatedModifiedMixin {
270275
id: string;
271276
}
272277

@@ -288,8 +293,7 @@ export interface ImagePost extends ObjectFileUploadMetadata {
288293
}
289294

290295
export interface APIImage
291-
extends Required<Omit<ImagePost, 'upload_file'>>,
292-
CreatedModifiedMixin {
296+
extends Required<Omit<ImagePost, 'upload_file'>>, CreatedModifiedMixin {
293297
id: string;
294298
primary: boolean;
295299
thumbnail_base64: string;

src/api/catalogueItems.test.tsx

Lines changed: 15 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -164,6 +164,9 @@ describe('catalogue items api functions', () => {
164164
obsolete_reason: null,
165165
properties: [],
166166
number_of_spares: 0,
167+
number_of_spares_required: null,
168+
criticality: null,
169+
is_flagged: null,
167170
...CREATED_MODIFIED_TIME_VALUES,
168171
};
169172
});
@@ -266,6 +269,9 @@ describe('catalogue items api functions', () => {
266269
obsolete_reason: null,
267270
obsolete_replacement_catalogue_item_id: null,
268271
number_of_spares: 0,
272+
number_of_spares_required: null,
273+
criticality: null,
274+
is_flagged: null,
269275
properties: [
270276
{
271277
id: '90',
@@ -294,6 +300,9 @@ describe('catalogue items api functions', () => {
294300
obsolete_reason: null,
295301
obsolete_replacement_catalogue_item_id: null,
296302
number_of_spares: 0,
303+
number_of_spares_required: null,
304+
criticality: null,
305+
is_flagged: null,
297306
properties: [
298307
{
299308
id: '90',
@@ -401,6 +410,9 @@ describe('catalogue items api functions', () => {
401410
obsolete_reason: null,
402411
obsolete_replacement_catalogue_item_id: null,
403412
number_of_spares: 0,
413+
number_of_spares_required: null,
414+
criticality: null,
415+
is_flagged: null,
404416
properties: [
405417
{
406418
id: '90',
@@ -429,6 +441,9 @@ describe('catalogue items api functions', () => {
429441
obsolete_reason: null,
430442
obsolete_replacement_catalogue_item_id: null,
431443
number_of_spares: 0,
444+
number_of_spares_required: null,
445+
criticality: null,
446+
is_flagged: null,
432447
properties: [
433448
{
434449
id: '90',

src/api/settings.test.tsx

Lines changed: 17 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -2,7 +2,7 @@ import { renderHook, waitFor } from '@testing-library/react';
22
import SystemTypesJSON from '../mocks/SystemTypes.json';
33
import { hooksWrapperWithProviders } from '../testUtils';
44

5-
import { useGetSparesDefinition } from './settings';
5+
import { useGetInUseDefinition, useGetSparesDefinition } from './settings';
66

77
describe('settings api functions', () => {
88
afterEach(() => {
@@ -24,4 +24,20 @@ describe('settings api functions', () => {
2424
});
2525
});
2626
});
27+
28+
describe('useGetInUseDefinition', () => {
29+
it('sends request to fetch the in use definition and returns successful response', async () => {
30+
const { result } = renderHook(() => useGetInUseDefinition(), {
31+
wrapper: hooksWrapperWithProviders(),
32+
});
33+
34+
await waitFor(() => {
35+
expect(result.current.isSuccess).toBeTruthy();
36+
});
37+
38+
expect(result.current.data).toEqual({
39+
system_types: [SystemTypesJSON[1]],
40+
});
41+
});
42+
});
2743
});

0 commit comments

Comments
 (0)