Skip to content

Commit 4730c18

Browse files
committed
fix: add tests and fix bug with menu auto-closing
1 parent a173aae commit 4730c18

File tree

3 files changed

+63
-2
lines changed

3 files changed

+63
-2
lines changed

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

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -28,7 +28,7 @@ export function ContextMenu({ menu }: ContextMenuWrapperProps) {
2828
if (!menu.isOpen) {
2929
menu.close();
3030
}
31-
}, [menu, menu.isOpen]);
31+
}, [menu.isOpen]);
3232

3333
return (
3434
<div
Lines changed: 45 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,45 @@
1+
import React from 'react';
2+
import { render } from '@mongodb-js/testing-library-compass';
3+
import { expect } from 'chai';
4+
import { ContextMenuProvider } from './context-menu-provider';
5+
import type { ContextMenuWrapperProps } from './types';
6+
7+
describe('ContextMenuProvider', function () {
8+
const TestMenu: React.FC<ContextMenuWrapperProps> = () => (
9+
<div data-testid="test-menu">Test Menu</div>
10+
);
11+
12+
const TestComponent = () => (
13+
<div data-testid="test-content">Test Content</div>
14+
);
15+
16+
describe('when nested', function () {
17+
it('throws an error when providers are nested', function () {
18+
expect(() => {
19+
render(
20+
<ContextMenuProvider wrapper={TestMenu}>
21+
<div>
22+
<ContextMenuProvider wrapper={TestMenu}>
23+
<TestComponent />
24+
</ContextMenuProvider>
25+
</div>
26+
</ContextMenuProvider>
27+
);
28+
}).to.throw(
29+
'Duplicated ContextMenuProvider found. Please remove the nested provider.'
30+
);
31+
});
32+
});
33+
34+
describe('when not nested', function () {
35+
it('renders without error', function () {
36+
render(
37+
<ContextMenuProvider wrapper={TestMenu}>
38+
<TestComponent />
39+
</ContextMenuProvider>
40+
);
41+
42+
expect(document.querySelector('[data-testid="test-content"]')).to.exist;
43+
});
44+
});
45+
});

packages/compass-context-menu/src/context-menu-provider.tsx

Lines changed: 17 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -4,6 +4,7 @@ import React, {
44
useState,
55
useMemo,
66
createContext,
7+
useContext,
78
} from 'react';
89
import type { ContextMenuContext, ContextMenuState } from './types';
910
import type { EnhancedMouseEvent } from './context-menu-content';
@@ -20,6 +21,9 @@ export function ContextMenuProvider({
2021
menu: ContextMenuState & { close: () => void };
2122
}>;
2223
}) {
24+
// Check if there's already a parent context menu provider
25+
const parentContext = useContext(Context);
26+
2327
const [menu, setMenu] = useState<ContextMenuState>({
2428
isOpen: false,
2529
itemGroups: [],
@@ -37,6 +41,11 @@ export function ContextMenuProvider({
3741
);
3842

3943
useEffect(() => {
44+
// If there's a parent provider, don't add event listeners
45+
if (parentContext) {
46+
return;
47+
}
48+
4049
function handleContextMenu(event: MouseEvent) {
4150
event.preventDefault();
4251

@@ -64,7 +73,7 @@ export function ContextMenuProvider({
6473
document.removeEventListener('contextmenu', handleContextMenu);
6574
window.removeEventListener('resize', handleClosingEvent);
6675
};
67-
}, [handleClosingEvent]);
76+
}, [handleClosingEvent, parentContext]);
6877

6978
const value = useMemo(
7079
() => ({
@@ -73,6 +82,13 @@ export function ContextMenuProvider({
7382
[close]
7483
);
7584

85+
// Prevent accidental nested providers
86+
if (parentContext) {
87+
throw new Error(
88+
'Duplicated ContextMenuProvider found. Please remove the nested provider.'
89+
);
90+
}
91+
7692
const Wrapper = wrapper ?? React.Fragment;
7793

7894
return (

0 commit comments

Comments
 (0)