From 89c9140d01f141a196e7f26e90eaae59d280ee3a Mon Sep 17 00:00:00 2001 From: Emmanuel Date: Fri, 10 Jan 2025 09:40:02 +0100 Subject: [PATCH] feat: improve some typescript for codeslist --- src/packages/model/CodesList.ts | 2 + .../code-sliding-panel-menu.spec.tsx | 143 ++++++++++++++++++ ...l-menu.jsx => code-sliding-panel-menu.tsx} | 16 +- .../codes-panel-add-button.spec.tsx | 38 +++-- .../codes-panel-add-button.tsx | 4 +- .../{codes-panel.scss => codes-panel.css} | 0 .../codelist-detail/codes-panel.jsx | 2 +- 7 files changed, 185 insertions(+), 20 deletions(-) create mode 100644 src/packages/modules-codelists/components/codelist-detail/code-sliding-panel-menu.spec.tsx rename src/packages/modules-codelists/components/codelist-detail/{code-sliding-panel-menu.jsx => code-sliding-panel-menu.tsx} (65%) rename src/packages/modules-codelists/components/codelist-detail/{codes-panel.scss => codes-panel.css} (100%) diff --git a/src/packages/model/CodesList.ts b/src/packages/model/CodesList.ts index 9a2998c75..7a9b20779 100644 --- a/src/packages/model/CodesList.ts +++ b/src/packages/model/CodesList.ts @@ -13,6 +13,8 @@ export interface CodesList { id?: string; codes: Code[]; notation: string; + lastCodeUriSegment: string; + contributor: string; } export type CodesLists = { diff --git a/src/packages/modules-codelists/components/codelist-detail/code-sliding-panel-menu.spec.tsx b/src/packages/modules-codelists/components/codelist-detail/code-sliding-panel-menu.spec.tsx new file mode 100644 index 000000000..43e59458f --- /dev/null +++ b/src/packages/modules-codelists/components/codelist-detail/code-sliding-panel-menu.spec.tsx @@ -0,0 +1,143 @@ +import { CodesList } from '@model/CodesList'; +import { render, screen, fireEvent } from '@testing-library/react'; +import { Mock, vi } from 'vitest'; + +import { ADMIN, CODELIST_CONTRIBUTOR } from '../../../auth/roles'; +import { usePermission } from '../../../redux/hooks/usePermission'; +import { CodeSlidingPanelMenu } from './code-sliding-panel-menu'; + +vi.mock('../../../redux/hooks/usePermission'); + +describe('CodeSlidingPanelMenu', () => { + const mockHandleSubmit = vi.fn(); + const mockHandleBack = vi.fn(); + const codelist = { contributor: 'test-contributor' }; + + beforeEach(() => { + vi.clearAllMocks(); + }); + + it('renders the ReturnButton', () => { + (usePermission as Mock).mockReturnValue({ roles: [], stamp: '' }); + render( + , + ); + + screen.getByRole('button', { name: /back/i }); + }); + + it('renders the UpdateButton when not in creation mode and has permission', () => { + (usePermission as Mock).mockReturnValue({ + roles: [CODELIST_CONTRIBUTOR], + stamp: 'test-contributor', + }); + + render( + , + ); + + screen.getByRole('button', { name: /update/i }); + }); + + it('renders the SaveButton when in creation mode and has permission', () => { + (usePermission as Mock).mockReturnValue({ + roles: [CODELIST_CONTRIBUTOR], + stamp: 'test-contributor', + }); + + render( + , + ); + + screen.getByRole('button', { name: /save/i }); + }); + + it('does not render UpdateButton or SaveButton when user lacks permissions', () => { + (usePermission as Mock).mockReturnValue({ + roles: [], + stamp: 'other-contributor', + }); + + render( + , + ); + + expect(screen.queryByRole('button', { name: /update/i })).toBeNull(); + + render( + , + ); + + expect(screen.queryByRole('button', { name: /save/i })).toBeNull(); + }); + + it('renders the UpdateButton and SaveButton for admin users', () => { + (usePermission as Mock).mockReturnValue({ roles: [ADMIN], stamp: '' }); + + render( + , + ); + + screen.getByRole('button', { name: /update/i }); + + render( + , + ); + + screen.getByRole('button', { name: /save/i }); + }); + + it('triggers the appropriate actions on button clicks', () => { + (usePermission as Mock).mockReturnValue({ roles: [ADMIN], stamp: '' }); + + render( + , + ); + + fireEvent.click(screen.getByRole('button', { name: /back/i })); + expect(mockHandleBack).toHaveBeenCalled(); + + fireEvent.click(screen.getByRole('button', { name: /update/i })); + expect(mockHandleSubmit).toHaveBeenCalled(); + }); +}); diff --git a/src/packages/modules-codelists/components/codelist-detail/code-sliding-panel-menu.jsx b/src/packages/modules-codelists/components/codelist-detail/code-sliding-panel-menu.tsx similarity index 65% rename from src/packages/modules-codelists/components/codelist-detail/code-sliding-panel-menu.jsx rename to src/packages/modules-codelists/components/codelist-detail/code-sliding-panel-menu.tsx index 0ddccf23b..7ce8a67fd 100644 --- a/src/packages/modules-codelists/components/codelist-detail/code-sliding-panel-menu.jsx +++ b/src/packages/modules-codelists/components/codelist-detail/code-sliding-panel-menu.tsx @@ -1,3 +1,5 @@ +import { CodesList } from '@model/CodesList'; + import { ActionToolbar } from '@components/action-toolbar'; import { ReturnButton, @@ -8,12 +10,18 @@ import { import { ADMIN, CODELIST_CONTRIBUTOR } from '../../../auth/roles'; import { usePermission } from '../../../redux/hooks/usePermission'; +interface CodeSlidingPanelMenuTypes { + codelist: CodesList; + handleSubmit: () => void; + handleBack: () => void; + creation: boolean; +} export const CodeSlidingPanelMenu = ({ codelist, handleSubmit, handleBack, creation, -}) => { +}: Readonly) => { const permission = usePermission(); const hasRightsBasedOnStamp = @@ -23,11 +31,11 @@ export const CodeSlidingPanelMenu = ({ return ( - + {(isAdmin || hasRightsBasedOnStamp) && ( <> - {!creation && } - {creation && } + {!creation && } + {creation && } )} diff --git a/src/packages/modules-codelists/components/codelist-detail/codes-panel-add-button.spec.tsx b/src/packages/modules-codelists/components/codelist-detail/codes-panel-add-button.spec.tsx index faca3d6dd..2017ed249 100644 --- a/src/packages/modules-codelists/components/codelist-detail/codes-panel-add-button.spec.tsx +++ b/src/packages/modules-codelists/components/codelist-detail/codes-panel-add-button.spec.tsx @@ -1,3 +1,4 @@ +import { CodesList } from '@model/CodesList'; import { render, screen, fireEvent } from '@testing-library/react'; import { Mock, vi } from 'vitest'; @@ -23,7 +24,10 @@ describe('CodesPanelAddButton', () => { }); render( - , + , ); expect(screen.queryByRole('button', { name: /add/i })).toBeNull(); @@ -37,7 +41,7 @@ describe('CodesPanelAddButton', () => { render( , ); @@ -53,10 +57,12 @@ describe('CodesPanelAddButton', () => { render( , ); @@ -72,10 +78,12 @@ describe('CodesPanelAddButton', () => { render( , ); @@ -91,10 +99,12 @@ describe('CodesPanelAddButton', () => { render( , ); diff --git a/src/packages/modules-codelists/components/codelist-detail/codes-panel-add-button.tsx b/src/packages/modules-codelists/components/codelist-detail/codes-panel-add-button.tsx index 0c1501eec..cee336b65 100644 --- a/src/packages/modules-codelists/components/codelist-detail/codes-panel-add-button.tsx +++ b/src/packages/modules-codelists/components/codelist-detail/codes-panel-add-button.tsx @@ -1,10 +1,12 @@ +import { CodesList } from '@model/CodesList'; + import { AddButton } from '@components/buttons/add'; import { ADMIN, CODELIST_CONTRIBUTOR } from '../../../auth/roles'; import { usePermission } from '../../../redux/hooks/usePermission'; interface CodesPanelAddButtonTypes { - codelist: any; + codelist: CodesList; onHandlePanel: () => void; } export const CodesPanelAddButton = ({ diff --git a/src/packages/modules-codelists/components/codelist-detail/codes-panel.scss b/src/packages/modules-codelists/components/codelist-detail/codes-panel.css similarity index 100% rename from src/packages/modules-codelists/components/codelist-detail/codes-panel.scss rename to src/packages/modules-codelists/components/codelist-detail/codes-panel.css diff --git a/src/packages/modules-codelists/components/codelist-detail/codes-panel.jsx b/src/packages/modules-codelists/components/codelist-detail/codes-panel.jsx index 989168288..b2d0ec18d 100644 --- a/src/packages/modules-codelists/components/codelist-detail/codes-panel.jsx +++ b/src/packages/modules-codelists/components/codelist-detail/codes-panel.jsx @@ -16,7 +16,7 @@ import { validateCode } from '../../utils'; import { CollapsiblePanel } from '../collapsible-panel'; import { CodeSlidingPanelMenu } from './code-sliding-panel-menu'; import { CodesPanelAddButton } from './codes-panel-add-button'; -import './codes-panel.scss'; +import './codes-panel.css'; import { Table } from './codes/table'; const CodeSlidingPanel = ({