diff --git a/packages/compass-components/src/components/context-menu.spec.tsx b/packages/compass-components/src/components/context-menu.spec.tsx index 13fd851ec0c..f6e37265e21 100644 --- a/packages/compass-components/src/components/context-menu.spec.tsx +++ b/packages/compass-components/src/components/context-menu.spec.tsx @@ -1,5 +1,10 @@ import React from 'react'; -import { render, screen, userEvent } from '@mongodb-js/testing-library-compass'; +import { + render, + screen, + userEvent, + waitFor, +} from '@mongodb-js/testing-library-compass'; import { expect } from 'chai'; import sinon from 'sinon'; import { ContextMenuProvider } from '@mongodb-js/compass-context-menu'; @@ -7,6 +12,39 @@ import { useContextMenuItems, ContextMenu } from './context-menu'; import type { ContextMenuItem } from '@mongodb-js/compass-context-menu'; describe('useContextMenuItems', function () { + let items: ContextMenuItem[]; + let onAction: sinon.SinonSpy; + + function assertMenuItemsExist(items: ContextMenuItem[]) { + for (let i = 0; i < items.length; i++) { + expect(screen.getByTestId(`menu-group-0-item-${i}`)).to.exist; + } + } + + function assertMenuItemsDoNotExist(items: ContextMenuItem[]) { + for (let i = 0; i < items.length; i++) { + expect(screen.queryByTestId(`menu-group-0-item-${i}`)).not.to.exist; + } + } + + beforeEach(function () { + onAction = sinon.spy(); + items = [ + { + label: 'Test Item 1', + onAction: () => onAction(1), + }, + { + label: 'Test Item 2', + onAction: () => onAction(2), + }, + ]; + }); + + afterEach(function () { + sinon.restore(); + }); + const menuTestTriggerId = 'test-trigger'; const TestComponent = ({ @@ -29,13 +67,6 @@ describe('useContextMenuItems', function () { }; it('works with nested providers, using the parent provider', function () { - const items = [ - { - label: 'Test Item', - onAction: () => {}, - }, - ]; - const { container } = render( @@ -53,53 +84,22 @@ describe('useContextMenuItems', function () { }); it('renders without error', function () { - const items = [ - { - label: 'Test Item', - onAction: () => {}, - }, - ]; - render(); expect(screen.getByTestId(menuTestTriggerId)).to.exist; }); it('shows context menu with items on right click', function () { - const items = [ - { - label: 'Test Item 1', - onAction: () => {}, - }, - { - label: 'Test Item 2', - onAction: () => {}, - }, - ]; - render(); const trigger = screen.getByTestId(menuTestTriggerId); userEvent.click(trigger, { button: 2 }); // The menu items should be rendered - expect(screen.getByTestId('menu-group-0-item-0')).to.exist; - expect(screen.getByTestId('menu-group-0-item-1')).to.exist; + assertMenuItemsExist(items); }); it('triggers the correct action when menu item is clicked', function () { - const onAction = sinon.spy(); - const items = [ - { - label: 'Test Item 1', - onAction: () => onAction(1), - }, - { - label: 'Test Item 2', - onAction: () => onAction(2), - }, - ]; - render(); const trigger = screen.getByTestId(menuTestTriggerId); @@ -111,21 +111,47 @@ describe('useContextMenuItems', function () { expect(onAction).to.have.been.calledOnceWithExactly(2); }); + it('closes the menu when an item is clicked', async function () { + render(); + + const trigger = screen.getByTestId(menuTestTriggerId); + + // Open the menu with right-click + userEvent.click(trigger, { button: 2 }); + + // Verify the menu is open (items exist) + assertMenuItemsExist(items); + + // Click on a menu item + const menuItem = screen.getByTestId('menu-group-0-item-0'); + userEvent.click(menuItem); + + // Verify the menu is closed (items do not exist) + await waitFor(() => assertMenuItemsDoNotExist(items)); + }); + + it('closes the menu when clicking outside the menu', async function () { + render(); + + const trigger = screen.getByTestId(menuTestTriggerId); + + // Open the menu with right-click + userEvent.click(trigger, { button: 2 }); + + // Verify the menu is open (items exist) + assertMenuItemsExist(items); + + // Click outside the menu (on document body) + userEvent.click(document.body); + + // Verify the menu is closed (items do not exist) + await waitFor(() => assertMenuItemsDoNotExist(items)); + }); + describe('with nested components', function () { const childTriggerId = 'child-trigger'; beforeEach(function () { - const items = [ - { - label: 'Test Item 1', - onAction: () => {}, - }, - { - label: 'Test Item 2', - onAction: () => {}, - }, - ]; - const childItems = [ { label: 'Child Item 1',