Skip to content

Commit

Permalink
Extract common components out #1022
Browse files Browse the repository at this point in the history
  • Loading branch information
joshuadkitenge committed Oct 16, 2024
1 parent ddfe52a commit afeb65f
Show file tree
Hide file tree
Showing 8 changed files with 1,219 additions and 946 deletions.
824 changes: 364 additions & 460 deletions src/catalogue/items/catalogueItemsLandingPage.component.tsx

Large diffs are not rendered by default.

93 changes: 93 additions & 0 deletions src/common/actionMenu.component.test.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,93 @@
import '@testing-library/jest-dom';
import { screen } from '@testing-library/react';
import userEvent, { UserEvent } from '@testing-library/user-event';
import { vi } from 'vitest';
import { renderComponentWithRouterProvider } from '../testUtils';
import ActionMenu, { ActionMenuProps } from './actionMenu.component';

describe('ActionMenu Component', () => {
let props: ActionMenuProps;
let user: UserEvent;
const mockEditMenuItem = {
onClick: vi.fn(),
dialog: <div data-testid="edit-dialog">Edit Dialog</div>,
};

const createView = () => {
renderComponentWithRouterProvider(<ActionMenu {...props} />);
};

beforeEach(() => {
props = {
ariaLabelPrefix: 'catalogue items landing page',
editMenuItem: mockEditMenuItem,
printMenuItem: true,
};
user = userEvent.setup();
// Mock the window.print function
vi.spyOn(window, 'print').mockImplementation(() => {});
});

afterEach(() => {
vi.clearAllMocks();
});

it('renders the ActionMenu and allows menu interaction', async () => {
createView();

// Verify that "Actions" text is displayed
expect(screen.getByText('Actions')).toBeInTheDocument();

// Verify the menu button is rendered
const actionButton = screen.getByLabelText(
'catalogue items landing page actions menu'
);
expect(actionButton).toBeInTheDocument();

// Open the menu
await user.click(actionButton);

// Check if the "Edit" option is visible
expect(screen.getByText('Edit')).toBeVisible();

// Check if the "Print" option is visible
expect(screen.getByText('Print')).toBeVisible();
});

it('triggers edit action and closes menu on clicking Edit', async () => {
createView();

// Open the menu
const actionButton = screen.getByLabelText(
'catalogue items landing page actions menu'
);
await user.click(actionButton);

// Click on the "Edit" option
const editButton = screen.getByText('Edit');
await user.click(editButton);

// Verify that the mock edit function was called
expect(mockEditMenuItem.onClick).toHaveBeenCalled();

// Check if the dialog is displayed
expect(screen.getByTestId('edit-dialog')).toBeInTheDocument();
});

it('triggers window print and closes menu on clicking Print', async () => {
createView();

// Open the menu
const actionButton = screen.getByLabelText(
'catalogue items landing page actions menu'
);
await user.click(actionButton);

// Click on the "Print" option
const printButton = screen.getByText('Print');
await user.click(printButton);

// Verify that window.print was called
expect(window.print).toHaveBeenCalled();
});
});
101 changes: 101 additions & 0 deletions src/common/actionMenu.component.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,101 @@
import EditIcon from '@mui/icons-material/Edit';
import ExpandMoreIcon from '@mui/icons-material/ExpandMore';
import PrintIcon from '@mui/icons-material/Print';
import { IconButton, Menu, MenuItem } from '@mui/material';
import Grid from '@mui/material/Grid';
import Typography from '@mui/material/Typography';
import React from 'react';

export interface ActionMenuProps {
ariaLabelPrefix: string;
editMenuItem: { onClick: () => void; dialog: React.ReactNode };
printMenuItem: boolean;
}
function ActionMenu(props: ActionMenuProps) {
// Navigation

const { editMenuItem, printMenuItem, ariaLabelPrefix } = props;

const [anchorEl, setAnchorEl] = React.useState<null | HTMLElement>(null);
const menuOpen = Boolean(anchorEl);

const handleMenuClick = (event: React.MouseEvent<HTMLButtonElement>) => {
setAnchorEl(event.currentTarget);
};

const handleMenuClose = () => {
setAnchorEl(null);
};

return (
<Grid
item
xs={12}
sm
container
sx={{
textAlign: 'right',
justifyContent: 'flex-end',
alignItems: 'top',
'@media print': {
display: 'none',
},
}}
>
<Grid item>
<Typography variant="body1" sx={{ display: 'inline-block', mr: 1 }}>
Actions
</Typography>
<IconButton
onClick={handleMenuClick}
sx={{
border: '1px solid',
borderRadius: 1,
padding: '6px',
}}
aria-label={`${ariaLabelPrefix} actions menu`}
>
<ExpandMoreIcon />
</IconButton>

{/* Menu Component */}
<Menu
anchorEl={anchorEl}
open={menuOpen}
onClose={handleMenuClose}
transformOrigin={{ vertical: 'top', horizontal: 'right' }}
anchorOrigin={{ vertical: 'bottom', horizontal: 'right' }}
sx={{
'@media print': {
display: 'none',
},
}}
>
<MenuItem
onClick={() => {
editMenuItem.onClick();
handleMenuClose();
}}
>
<EditIcon fontSize="small" sx={{ mr: 1 }} />
Edit
</MenuItem>
{printMenuItem && (
<MenuItem
onClick={() => {
window.print();
handleMenuClose();
}}
>
<PrintIcon fontSize="small" sx={{ mr: 1 }} />
Print
</MenuItem>
)}
</Menu>
</Grid>
{editMenuItem.dialog}
</Grid>
);
}

export default ActionMenu;
124 changes: 124 additions & 0 deletions src/common/tab/__snapshots__/tabView.component.test.tsx.snap
Original file line number Diff line number Diff line change
@@ -0,0 +1,124 @@
// Vitest Snapshot v1, https://vitest.dev/guide/snapshot.html

exports[`TabView Component > renders correctly 1`] = `
<body>
<div>
<div
class="MuiGrid-root MuiGrid-container css-k6wrnl-MuiGrid-root"
>
<div
class="MuiGrid-root MuiGrid-item MuiGrid-grid-xs-12 css-1idn90j-MuiGrid-root"
>
<div
class="MuiTabs-root css-1ujnqem-MuiTabs-root"
>
<div
class="MuiTabs-scroller MuiTabs-fixed css-jpln7h-MuiTabs-scroller"
style="overflow: hidden; margin-bottom: 0px;"
>
<div
aria-label="test view tabs"
class="MuiTabs-flexContainer css-heg063-MuiTabs-flexContainer"
role="tablist"
>
<button
aria-controls="tab1-tabpanel"
aria-selected="true"
class="MuiButtonBase-root MuiTab-root MuiTab-labelIcon MuiTab-textColorPrimary Mui-selected css-12xzlyc-MuiButtonBase-root-MuiTab-root"
id="tab1-tab"
role="tab"
tabindex="0"
type="button"
>
<div
class="MuiTab-iconWrapper"
>
icon 1
</div>
tab1
<span
class="MuiTouchRipple-root css-8je8zh-MuiTouchRipple-root"
/>
</button>
<button
aria-controls="tab2-tabpanel"
aria-selected="false"
class="MuiButtonBase-root MuiTab-root MuiTab-labelIcon MuiTab-textColorPrimary css-12xzlyc-MuiButtonBase-root-MuiTab-root"
id="tab2-tab"
role="tab"
tabindex="-1"
type="button"
>
<div
class="MuiTab-iconWrapper"
>
icon 2
</div>
tab2
<span
class="MuiTouchRipple-root css-8je8zh-MuiTouchRipple-root"
/>
</button>
<button
aria-controls="tab3-tabpanel"
aria-selected="false"
class="MuiButtonBase-root MuiTab-root MuiTab-labelIcon MuiTab-textColorPrimary css-12xzlyc-MuiButtonBase-root-MuiTab-root"
id="tab3-tab"
role="tab"
tabindex="-1"
type="button"
>
<div
class="MuiTab-iconWrapper"
>
icon 3
</div>
tab3
<span
class="MuiTouchRipple-root css-8je8zh-MuiTouchRipple-root"
/>
</button>
</div>
<span
class="MuiTabs-indicator css-1aquho2-MuiTabs-indicator"
style="left: 0px; width: 0px;"
/>
</div>
</div>
</div>
<div
class="MuiGrid-root MuiGrid-item MuiGrid-grid-xs-12 css-1idn90j-MuiGrid-root"
>
<div
aria-labelledby="tab1-tab"
id="tab1-tabpanel"
role="tabpanel"
style="height: 100%;"
>
<div
class="MuiBox-root css-10klw3m"
>
<div>
Content for Tab 1
</div>
</div>
</div>
<div
aria-labelledby="tab2-tab"
hidden=""
id="tab2-tabpanel"
role="tabpanel"
style="height: 100%;"
/>
<div
aria-labelledby="tab3-tab"
hidden=""
id="tab3-tabpanel"
role="tabpanel"
style="height: 100%;"
/>
</div>
</div>
</div>
</body>
`;
15 changes: 0 additions & 15 deletions src/common/tab/tab.utils.tsx
Original file line number Diff line number Diff line change
@@ -1,7 +1,3 @@
import AttachmentOutlinedIcon from '@mui/icons-material/AttachmentOutlined';
import CollectionsOutlinedIcon from '@mui/icons-material/CollectionsOutlined';
import InfoOutlinedIcon from '@mui/icons-material/InfoOutlined';
import NotesIcon from '@mui/icons-material/Notes';
import { styled } from '@mui/material';
import Tab from '@mui/material/Tab';

Expand All @@ -17,17 +13,6 @@ export const CATALOGUE_LANDING_PAGE_TAB_VALUES = [
export type CatalogueLandingPageTabValue =
(typeof CATALOGUE_LANDING_PAGE_TAB_VALUES)[number];

// Default icons for the base values
export const defaultCatalogueLandingPageIconMapping: Record<
CatalogueLandingPageTabValue,
React.ReactElement
> = {
Information: <InfoOutlinedIcon />,
Gallery: <CollectionsOutlinedIcon />,
Attachments: <AttachmentOutlinedIcon />,
Notes: <NotesIcon />,
};

export function a11yProps<T>(label: T) {
return {
id: `${label}-tab`,
Expand Down
Loading

0 comments on commit afeb65f

Please sign in to comment.