From b5c358099543e22a3f02c2ac908678ee643446ba Mon Sep 17 00:00:00 2001 From: tombogle Date: Thu, 22 Feb 2024 17:11:49 -0500 Subject: [PATCH] 707: Broke unit tests into two files. All tests pass now. --- .../src/components/grid-menu.component.tsx | 3 + .../gridMenu.component.onClick.test.tsx | 40 ++++++ .../gridMenu.component.render.test.tsx | 100 +++++++++++++ .../components/gridMenu.component.test.tsx | 133 ------------------ 4 files changed, 143 insertions(+), 133 deletions(-) create mode 100644 lib/platform-bible-react/src/components/gridMenu.component.onClick.test.tsx create mode 100644 lib/platform-bible-react/src/components/gridMenu.component.render.test.tsx delete mode 100644 lib/platform-bible-react/src/components/gridMenu.component.test.tsx diff --git a/lib/platform-bible-react/src/components/grid-menu.component.tsx b/lib/platform-bible-react/src/components/grid-menu.component.tsx index 1566733ec0..9de2f249f7 100644 --- a/lib/platform-bible-react/src/components/grid-menu.component.tsx +++ b/lib/platform-bible-react/src/components/grid-menu.component.tsx @@ -47,6 +47,9 @@ function MenuColumn( return (

{metadata.label}

+ {/* It would seem as though this List component were unnecessary, since it only contains one + thing, but the "dense" property does affect the layout of the items (in a way I don't fully + understand). There might be a better way. */} { + const topMenuCombiner = new NonValidatingDocumentCombiner(jsonMenu, { + copyDocuments: false, + ignoreDuplicateProperties: true, + }); + + // Assert the type that schema validation should have already sorted out + // eslint-disable-next-line no-type-assertion/no-type-assertion + const menuData = topMenuCombiner.output as PlatformMenus; + + it('handles click event correctly', () => { + render( + , + ); + + const sendReceiveProjectsItem = screen.queryByText('%sendReceiveProjects%'); + expect(sendReceiveProjectsItem).toBeDefined(); + + sendReceiveProjectsItem && fireEvent.click(sendReceiveProjectsItem); + + expect(numberOfCommandsHandled).toBe(1); + expect(lastCommandHandled).toBe('paratext.sendReceiveProjects'); + }); +}); diff --git a/lib/platform-bible-react/src/components/gridMenu.component.render.test.tsx b/lib/platform-bible-react/src/components/gridMenu.component.render.test.tsx new file mode 100644 index 0000000000..800e0e64b1 --- /dev/null +++ b/lib/platform-bible-react/src/components/gridMenu.component.render.test.tsx @@ -0,0 +1,100 @@ +import { PlatformMenus } from 'platform-bible-utils'; +import { render, screen } from '@testing-library/react'; +import '@testing-library/jest-dom'; +import GridMenu from './grid-menu.component'; +import { MouseEventHandler, PropsWithChildren } from 'react'; +import NonValidatingDocumentCombiner from '../test-utils/non-validating-document-combiner'; +import * as jsonMenu from './sample.composed.full.menu.json'; + +jest.mock('@mui/material', () => { + const mui = jest.requireActual('@mui/material'); // Import the actual MUI components + + return { + ...mui, // Spread the actual MUI exports + + // Mocked components + MenuItem: ({ + divider, + className, + children, + }: { + divider: boolean | undefined; + className: string | undefined; + onClick?: MouseEventHandler | undefined; + } & PropsWithChildren) => { + const dividerStyle = divider ? ' hasDivider' : ''; + return ( +
  • + {children} +
  • + ); + }, + }; +}); + +function HandleMenuCommandNoOp() { +} + +describe('GridMenu renders', () => { + const topMenuCombiner = new NonValidatingDocumentCombiner(jsonMenu, { + copyDocuments: false, + ignoreDuplicateProperties: true, + }); + + // Assert the type that schema validation should have already sorted out + // eslint-disable-next-line no-type-assertion/no-type-assertion + const menuData = topMenuCombiner.output as PlatformMenus; + render( + , + ); + + it('column label correctly', () => { + const expectedColumns = [ + screen.queryByText('%mainMenu_Paratext%'), + screen.queryByText('%mainMenu_Window%'), + screen.queryByText('%mainMenu_Layout%'), + screen.queryByText('%mainMenu_Help%'), + ]; + + expectedColumns.forEach((column) => { + expect(column).toBeInTheDocument(); + expect(column).toHaveAttribute( + 'class', + expect.stringMatching(/\bpapi-menu-column-header\b/), + ); + }); + }); + + const allMenuItems = screen.queryAllByRole('menuitem'); + + // We expect all the top-level menu items to be laid out in the grid, but not the ones which + // belong to a submenu. + // (Note: In our test data, groups that are in submenus have the text "Sub" in them.) + const expectedMenuItems = jsonMenu.mainMenu.items.filter( + (i) => 'group' in i && !/sub/i.test(i.group), + ); + + it('the correct total number of items', () => { + expect(allMenuItems.length).toBe(expectedMenuItems.length); + }); + + it('the correct total number of groups with dividers', () => { + let cGroupsWithDividers = 0; + allMenuItems.forEach((m) => { + if (m.outerHTML?.match('hasDivider')) cGroupsWithDividers += 1; + }); + + // In the test data, only 4 of the column-level groups contain menu items. They are in two + // columns and there should be no divider for the final group in each column. + expect(cGroupsWithDividers).toBe(2); + }); + + it('the last group in a column without a final separator', () => { + const htmlForAddParatextVideoItem = allMenuItems.map((i) => i.outerHTML).find((html) => html && + /%video_AddParatextVideo%/.test(html), + ); + + expect(htmlForAddParatextVideoItem).toBeDefined(); + expect(htmlForAddParatextVideoItem).not.toMatch('hasDivider'); + }); +}); diff --git a/lib/platform-bible-react/src/components/gridMenu.component.test.tsx b/lib/platform-bible-react/src/components/gridMenu.component.test.tsx deleted file mode 100644 index fb1ec05282..0000000000 --- a/lib/platform-bible-react/src/components/gridMenu.component.test.tsx +++ /dev/null @@ -1,133 +0,0 @@ -import { PlatformMenus } from 'platform-bible-utils'; -import { fireEvent, render } from '@testing-library/react'; -import '@testing-library/jest-dom'; -import GridMenu from './grid-menu.component'; -import { Command } from './menu-item.component'; -import { PropsWithChildren } from 'react'; -import NonValidatingDocumentCombiner from '../test-utils/non-validating-document-combiner'; -import * as jsonMenu from './sample.composed.full.menu.json'; - -// jest.mock('@mui/material', () => ({ -// __esModule: true, -// // Grid: ({ children }: PropsWithChildren) =>
    {children}
    , -// List: ({ children }: PropsWithChildren) =>
      {children}
    , -// MenuItem: ({ divider, className, children }: { divider: boolean | undefined, className: string | undefined } & PropsWithChildren) => { -// const hasDividerStyle = divider ? ' hasDivider' : ''; -// return
  • {children}
  • ; -// }, -// // Menu: ({ children }: PropsWithChildren) =>
      {children}
    , -// // ListItemText: ({ primary }: {primary: string} & PropsWithChildren) => {primary}, -// // ListItemIcon: ({ className, children }: {className: string} & PropsWithChildren) => {children}, -// })); - -jest.mock('@mui/material', () => { - const mui = jest.requireActual('@mui/material'); // Import the actual MUI components - - return { - ...mui, // Spread the actual MUI exports - - // Mocked components - MenuItem: ({ - divider, - className, - children, - }: { divider: boolean | undefined; className: string | undefined } & PropsWithChildren) => { - const dividerStyle = divider ? ' hasDivider' : ''; - return ( -
  • - {children} -
  • - ); - }, - - // Add more mocked components as needed - }; -}); - -/* -jest.spyOn(console, 'error').mockImplementation(() => {}); -*/ - -let lastCommandHandled: string; -let numberOfCommandsHandled: number = 0; - -function HandleMenuCommandNoOp(command: Command) { - lastCommandHandled = command.command; - numberOfCommandsHandled += 1; -} - -describe('GridMenu', () => { - const topMenuCombiner = new NonValidatingDocumentCombiner(jsonMenu, { - copyDocuments: false, - ignoreDuplicateProperties: true, - }); - - // Assert the type that schema validation should have already sorted out - // eslint-disable-next-line no-type-assertion/no-type-assertion - const menuData = topMenuCombiner.output as PlatformMenus; - const { getByText, getAllByRole, container } = render( - , - ); - describe('renders', () => { - it('column label correctly', () => { - const expectedColumns = [ - getByText('%mainMenu_Paratext%'), - getByText('%mainMenu_Window%'), - getByText('%mainMenu_Layout%'), - getByText('%mainMenu_Help%'), - ]; - - expectedColumns.forEach((column) => { - expect(column).toBeInTheDocument(); - expect(column).toHaveAttribute( - 'class', - expect.stringMatching(/\bpapi-menu-column-header\b/), - ); - }); - }); - - it('some HTML', () => { - expect(container.innerHTML).toBeDefined(); - }); - - const allMenuItems = getAllByRole('menuitem'); - // We expect all the top-level menu items to be laid out in the grid, but not the ones which - // belong to a submenu. - // (Note: In our test data, groups that are in submenus have the text "Sub" in them.) - const expectedMenuItems = jsonMenu.mainMenu.items.filter( - (i) => 'group' in i && !/sub/i.test(i.group), - ); - - it('the correct total number of items', () => { - expect(allMenuItems.length).toBe(expectedMenuItems.length); - }); - - it('the correct total number of groups with dividers', () => { - let cGroupsWithDividers = 0; - allMenuItems.forEach((m) => { - if (m.outerHTML?.match('hasDivider')) cGroupsWithDividers += 1; - }); - - // In the test data, only 4 of the column-level groups contain menu items. They are in two - // columns and there should be no divider for the final group in each column. - expect(cGroupsWithDividers).toBe(2); - }); - - it('the last group in a column without a final separator', () => { - const htmlForAddParatextVideoItem = allMenuItems.map((i) => i.outerHTML).find((html) => html && - /%video_AddParatextVideo%/.test(html), - ); - - expect(htmlForAddParatextVideoItem).toBeDefined();expect(htmlForAddParatextVideoItem).not.toMatch('hasDivider'); - - }); - }); - describe('handles', () => { - it('click event correctly', () => { - fireEvent.click(getByText('%sendReceiveProjects%')); - - expect(lastCommandHandled).toBe('paratext.sendReceiveProjects'); - expect(numberOfCommandsHandled).toBe(1); - }); - }); -});