Skip to content

Commit

Permalink
Add some more unit tests for ReactPanel
Browse files Browse the repository at this point in the history
  • Loading branch information
mofojed committed Oct 30, 2023
1 parent 2dbe1e3 commit a621178
Show file tree
Hide file tree
Showing 2 changed files with 96 additions and 4 deletions.
94 changes: 92 additions & 2 deletions plugins/ui/src/js/src/ReactPanel.test.tsx
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
import React from 'react';
import { render } from '@testing-library/react';
import { LayoutUtils } from '@deephaven/dashboard';
import { LayoutUtils, useListener } from '@deephaven/dashboard';
import ReactPanel, { ReactPanelProps } from './ReactPanel';

// Mock LayoutUtils, useListener, and PanelEvent from @deephaven/dashboard package
Expand All @@ -18,7 +18,12 @@ jest.mock('@deephaven/dashboard', () => {
default: jest.fn(),
};
});
jest.mock('./useLayout', () => jest.fn(() => ({ root: {}, eventHub: {} })));

const mockLayout = { root: {}, eventHub: {} };
jest.mock('./useLayout', () => jest.fn(() => mockLayout));

const mockPanelId = 'test-panel-id';
jest.mock('shortid', () => jest.fn(() => mockPanelId));

beforeEach(() => {
jest.clearAllMocks();
Expand All @@ -43,6 +48,13 @@ function makeReactPanel({
);
}

/**
* Simulate the panel CLOSED event. Assumes the `useListener` has only been called with that event listener.
*/
function simulatePanelClosed() {
(useListener as jest.Mock).mock.calls[0][2](mockPanelId);
}

it('opens panel on mount, and closes panel on unmount', async () => {
const onOpen = jest.fn();
const onClose = jest.fn();
Expand All @@ -59,3 +71,81 @@ it('opens panel on mount, and closes panel on unmount', async () => {
expect(onOpen).toHaveBeenCalledTimes(1);
expect(onClose).toHaveBeenCalledTimes(1);
});

it('only calls open once if the panel has not closed and only children change', async () => {
const onOpen = jest.fn();
const onClose = jest.fn();
const metadata = { foo: 'bar' };
const children = 'hello';
const { rerender } = render(
makeReactPanel({ children, onOpen, onClose, metadata })
);
expect(LayoutUtils.openComponent).toHaveBeenCalledTimes(1);
expect(LayoutUtils.closeComponent).not.toHaveBeenCalled();
expect(onOpen).toHaveBeenCalledTimes(1);
expect(onClose).not.toHaveBeenCalled();

rerender(makeReactPanel({ children: 'world', onOpen, onClose, metadata }));

expect(LayoutUtils.openComponent).toHaveBeenCalledTimes(1);
expect(LayoutUtils.closeComponent).not.toHaveBeenCalled();
expect(onOpen).toHaveBeenCalledTimes(1);
expect(onClose).not.toHaveBeenCalled();
});

it('calls openComponent again after panel is closed only if the metadata changes', async () => {
const onOpen = jest.fn();
const onClose = jest.fn();
const metadata = { foo: 'bar' };
const children = 'hello';
const { rerender } = render(
makeReactPanel({
children,
onOpen,
onClose,
metadata,
})
);
expect(LayoutUtils.openComponent).toHaveBeenCalledTimes(1);
expect(LayoutUtils.closeComponent).not.toHaveBeenCalled();
expect(onOpen).toHaveBeenCalledTimes(1);
expect(onClose).not.toHaveBeenCalled();
expect(useListener).toHaveBeenCalledTimes(1);

simulatePanelClosed();

expect(LayoutUtils.openComponent).toHaveBeenCalledTimes(1);
expect(LayoutUtils.closeComponent).toHaveBeenCalledTimes(0);
expect(onOpen).toHaveBeenCalledTimes(1);
expect(onClose).toHaveBeenCalledTimes(1);

// Should not re-open if just the children change but the metadata stays the same
rerender(
makeReactPanel({
children: 'world',
onOpen,
onClose,
metadata,
})
);

expect(LayoutUtils.openComponent).toHaveBeenCalledTimes(1);
expect(LayoutUtils.closeComponent).toHaveBeenCalledTimes(0);
expect(onOpen).toHaveBeenCalledTimes(1);
expect(onClose).toHaveBeenCalledTimes(1);

// Should re-open after the metadata change
rerender(
makeReactPanel({
children,
onOpen,
onClose,
metadata: { fiz: 'baz' },
})
);

expect(LayoutUtils.openComponent).toHaveBeenCalledTimes(2);
expect(LayoutUtils.closeComponent).toHaveBeenCalledTimes(0);
expect(onOpen).toHaveBeenCalledTimes(2);
expect(onClose).toHaveBeenCalledTimes(1);
});
6 changes: 4 additions & 2 deletions plugins/ui/src/js/src/ReactPanel.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -43,7 +43,7 @@ function ReactPanel({
const panelId = useMemo(() => shortid(), []);
const [element, setElement] = useState<HTMLElement>();
const isPanelOpenRef = useRef(false);
const openedMetadataRef = useRef();
const openedMetadataRef = useRef<Record<string, unknown>>();

log.debug2('Rendering panel', panelId);

Expand All @@ -63,6 +63,7 @@ function ReactPanel({
closedPanelId => {
if (closedPanelId === panelId) {
log.debug('Panel closed', panelId);
isPanelOpenRef.current = false;
onClose?.();
}
},
Expand Down Expand Up @@ -96,10 +97,11 @@ function ReactPanel({
LayoutUtils.openComponent({ root, config });
log.debug('Opened panel', panelId, config);
isPanelOpenRef.current = true;
openedMetadataRef.current = metadata;

onOpen?.();
}
}, [children, layout, metadata, onOpen, panelId, title]);
}, [layout, metadata, onOpen, panelId, title]);

return element ? ReactDOM.createPortal(children, element) : null;
}
Expand Down

0 comments on commit a621178

Please sign in to comment.