Skip to content

Commit b0e0a69

Browse files
authored
test: add closing tests to context menu COMPASS-9386 (#7069)
Adds some tests to ensure context menu closes in different contexts. Also cleans up some tests by generalizing the items being passed.
1 parent bcd1cd6 commit b0e0a69

File tree

1 file changed

+77
-51
lines changed

1 file changed

+77
-51
lines changed

packages/compass-components/src/components/context-menu.spec.tsx

Lines changed: 77 additions & 51 deletions
Original file line numberDiff line numberDiff line change
@@ -1,12 +1,50 @@
11
import React from 'react';
2-
import { render, screen, userEvent } from '@mongodb-js/testing-library-compass';
2+
import {
3+
render,
4+
screen,
5+
userEvent,
6+
waitFor,
7+
} from '@mongodb-js/testing-library-compass';
38
import { expect } from 'chai';
49
import sinon from 'sinon';
510
import { ContextMenuProvider } from '@mongodb-js/compass-context-menu';
611
import { useContextMenuItems, ContextMenu } from './context-menu';
712
import type { ContextMenuItem } from '@mongodb-js/compass-context-menu';
813

914
describe('useContextMenuItems', function () {
15+
let items: ContextMenuItem[];
16+
let onAction: sinon.SinonSpy;
17+
18+
function assertMenuItemsExist(items: ContextMenuItem[]) {
19+
for (let i = 0; i < items.length; i++) {
20+
expect(screen.getByTestId(`menu-group-0-item-${i}`)).to.exist;
21+
}
22+
}
23+
24+
function assertMenuItemsDoNotExist(items: ContextMenuItem[]) {
25+
for (let i = 0; i < items.length; i++) {
26+
expect(screen.queryByTestId(`menu-group-0-item-${i}`)).not.to.exist;
27+
}
28+
}
29+
30+
beforeEach(function () {
31+
onAction = sinon.spy();
32+
items = [
33+
{
34+
label: 'Test Item 1',
35+
onAction: () => onAction(1),
36+
},
37+
{
38+
label: 'Test Item 2',
39+
onAction: () => onAction(2),
40+
},
41+
];
42+
});
43+
44+
afterEach(function () {
45+
sinon.restore();
46+
});
47+
1048
const menuTestTriggerId = 'test-trigger';
1149

1250
const TestComponent = ({
@@ -29,13 +67,6 @@ describe('useContextMenuItems', function () {
2967
};
3068

3169
it('works with nested providers, using the parent provider', function () {
32-
const items = [
33-
{
34-
label: 'Test Item',
35-
onAction: () => {},
36-
},
37-
];
38-
3970
const { container } = render(
4071
<ContextMenuProvider menuWrapper={ContextMenu}>
4172
<ContextMenuProvider menuWrapper={ContextMenu}>
@@ -53,53 +84,22 @@ describe('useContextMenuItems', function () {
5384
});
5485

5586
it('renders without error', function () {
56-
const items = [
57-
{
58-
label: 'Test Item',
59-
onAction: () => {},
60-
},
61-
];
62-
6387
render(<TestComponent items={items} />);
6488

6589
expect(screen.getByTestId(menuTestTriggerId)).to.exist;
6690
});
6791

6892
it('shows context menu with items on right click', function () {
69-
const items = [
70-
{
71-
label: 'Test Item 1',
72-
onAction: () => {},
73-
},
74-
{
75-
label: 'Test Item 2',
76-
onAction: () => {},
77-
},
78-
];
79-
8093
render(<TestComponent items={items} />);
8194

8295
const trigger = screen.getByTestId(menuTestTriggerId);
8396
userEvent.click(trigger, { button: 2 });
8497

8598
// The menu items should be rendered
86-
expect(screen.getByTestId('menu-group-0-item-0')).to.exist;
87-
expect(screen.getByTestId('menu-group-0-item-1')).to.exist;
99+
assertMenuItemsExist(items);
88100
});
89101

90102
it('triggers the correct action when menu item is clicked', function () {
91-
const onAction = sinon.spy();
92-
const items = [
93-
{
94-
label: 'Test Item 1',
95-
onAction: () => onAction(1),
96-
},
97-
{
98-
label: 'Test Item 2',
99-
onAction: () => onAction(2),
100-
},
101-
];
102-
103103
render(<TestComponent items={items} />);
104104

105105
const trigger = screen.getByTestId(menuTestTriggerId);
@@ -111,21 +111,47 @@ describe('useContextMenuItems', function () {
111111
expect(onAction).to.have.been.calledOnceWithExactly(2);
112112
});
113113

114+
it('closes the menu when an item is clicked', async function () {
115+
render(<TestComponent items={items} />);
116+
117+
const trigger = screen.getByTestId(menuTestTriggerId);
118+
119+
// Open the menu with right-click
120+
userEvent.click(trigger, { button: 2 });
121+
122+
// Verify the menu is open (items exist)
123+
assertMenuItemsExist(items);
124+
125+
// Click on a menu item
126+
const menuItem = screen.getByTestId('menu-group-0-item-0');
127+
userEvent.click(menuItem);
128+
129+
// Verify the menu is closed (items do not exist)
130+
await waitFor(() => assertMenuItemsDoNotExist(items));
131+
});
132+
133+
it('closes the menu when clicking outside the menu', async function () {
134+
render(<TestComponent items={items} />);
135+
136+
const trigger = screen.getByTestId(menuTestTriggerId);
137+
138+
// Open the menu with right-click
139+
userEvent.click(trigger, { button: 2 });
140+
141+
// Verify the menu is open (items exist)
142+
assertMenuItemsExist(items);
143+
144+
// Click outside the menu (on document body)
145+
userEvent.click(document.body);
146+
147+
// Verify the menu is closed (items do not exist)
148+
await waitFor(() => assertMenuItemsDoNotExist(items));
149+
});
150+
114151
describe('with nested components', function () {
115152
const childTriggerId = 'child-trigger';
116153

117154
beforeEach(function () {
118-
const items = [
119-
{
120-
label: 'Test Item 1',
121-
onAction: () => {},
122-
},
123-
{
124-
label: 'Test Item 2',
125-
onAction: () => {},
126-
},
127-
];
128-
129155
const childItems = [
130156
{
131157
label: 'Child Item 1',

0 commit comments

Comments
 (0)