Skip to content

Commit 403d166

Browse files
committed
Self-review, cleanup
1 parent 4c735d8 commit 403d166

5 files changed

Lines changed: 386 additions & 8 deletions

File tree

packages/dashboard-core-plugins/src/WidgetLoaderPlugin.test.tsx

Lines changed: 97 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -7,6 +7,7 @@ import {
77
type WidgetMiddlewarePlugin,
88
type WidgetComponentProps,
99
type WidgetMiddlewareComponentProps,
10+
type WidgetMiddlewarePanelProps,
1011
} from '@deephaven/plugin';
1112
import { Provider } from 'react-redux';
1213
import { Dashboard, PanelEvent } from '@deephaven/dashboard';
@@ -433,4 +434,100 @@ describe('middleware plugin chaining', () => {
433434
const wrapper = screen.getByTestId('middleware-wrapper');
434435
expect(wrapper).toContainElement(screen.getByText('TestWidgetTwo'));
435436
});
437+
438+
it('middleware for one type does not affect a different type', async () => {
439+
const otherPlugin: WidgetPlugin = {
440+
name: 'other-widget',
441+
type: PluginType.WIDGET_PLUGIN,
442+
component: TestWidgetTwo,
443+
supportedTypes: 'other-type',
444+
};
445+
446+
const layoutManager = createAndMountDashboard([
447+
['test-widget-plugin', testWidgetPlugin],
448+
['other-widget', otherPlugin],
449+
['test-middleware-plugin', testMiddlewarePlugin], // targets 'test-widget' only
450+
]);
451+
452+
// Open the other type — middleware should NOT apply
453+
act(
454+
() =>
455+
layoutManager?.eventHub.emit(PanelEvent.OPEN, {
456+
widget: { type: 'other-type' },
457+
})
458+
);
459+
460+
expect(screen.queryAllByText('TestWidgetTwo').length).toBe(1);
461+
expect(screen.queryAllByText('MiddlewareWrapper').length).toBe(0);
462+
});
463+
464+
it('chains panel middleware around base panelComponent', async () => {
465+
function TestPanelMiddleware({
466+
Component,
467+
...props
468+
}: WidgetMiddlewarePanelProps) {
469+
return (
470+
<div data-testid="panel-middleware">
471+
<span>PanelMiddleware</span>
472+
{/* eslint-disable-next-line react/jsx-props-no-spreading */}
473+
<Component {...props} />
474+
</div>
475+
);
476+
}
477+
478+
const panelMiddleware: WidgetMiddlewarePlugin = {
479+
name: 'panel-middleware',
480+
type: PluginType.WIDGET_PLUGIN,
481+
component: TestMiddlewareWrapper,
482+
panelComponent: TestPanelMiddleware,
483+
supportedTypes: 'test-widget-panel',
484+
isMiddleware: true,
485+
};
486+
487+
const layoutManager = createAndMountDashboard([
488+
['test-widget-plugin-with-panel', testWidgetPluginWithPanel],
489+
['panel-middleware', panelMiddleware],
490+
]);
491+
492+
act(
493+
() =>
494+
layoutManager?.eventHub.emit(PanelEvent.OPEN, {
495+
widget: { type: 'test-widget-panel' },
496+
})
497+
);
498+
499+
// Panel middleware should wrap the base panel
500+
expect(screen.queryAllByText('PanelMiddleware').length).toBe(1);
501+
expect(screen.queryAllByText('TestPanel').length).toBe(1);
502+
const wrapper = screen.getByTestId('panel-middleware');
503+
expect(wrapper).toContainElement(screen.getByText('TestPanel'));
504+
});
505+
506+
it('skips component-only middleware when base has panelComponent', async () => {
507+
// Middleware that only defines component (no panelComponent)
508+
const componentOnlyMiddleware: WidgetMiddlewarePlugin = {
509+
name: 'component-only-middleware',
510+
type: PluginType.WIDGET_PLUGIN,
511+
component: TestMiddlewareWrapper,
512+
supportedTypes: 'test-widget-panel',
513+
isMiddleware: true,
514+
};
515+
516+
const layoutManager = createAndMountDashboard([
517+
['test-widget-plugin-with-panel', testWidgetPluginWithPanel],
518+
['component-only-middleware', componentOnlyMiddleware],
519+
]);
520+
521+
act(
522+
() =>
523+
layoutManager?.eventHub.emit(PanelEvent.OPEN, {
524+
widget: { type: 'test-widget-panel' },
525+
})
526+
);
527+
528+
// The base panel should render, but middleware wrapper should NOT appear
529+
// because the middleware lacks panelComponent and the base has panelComponent
530+
expect(screen.queryAllByText('TestPanel').length).toBe(1);
531+
expect(screen.queryAllByText('MiddlewareWrapper').length).toBe(0);
532+
});
436533
});

packages/dashboard-core-plugins/src/WidgetLoaderPlugin.tsx

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -283,8 +283,8 @@ export function WidgetLoaderPlugin(
283283
}
284284

285285
// Has panel component - chain middleware around the panel.
286-
// Middleware with panelComponent wraps at the panel level directly.
287-
// Middleware with only component is auto-promoted to a panel wrapper.
286+
// Only middleware that defines panelComponent is applied here.
287+
// Middleware with only component is skipped in this path.
288288
log.debug(
289289
`Chaining panel components for ${basePlugin.name} (has custom panel component)`
290290
);

packages/plugin/src/PluginTypes.ts

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -206,7 +206,7 @@ export interface WidgetMiddlewarePlugin<T = unknown>
206206
* Type guard to check if a plugin is a middleware plugin.
207207
*/
208208
export function isWidgetMiddlewarePlugin(
209-
plugin: PluginModule
209+
plugin: PluginModuleExport
210210
): plugin is WidgetMiddlewarePlugin {
211211
return (
212212
isWidgetPlugin(plugin) &&

0 commit comments

Comments
 (0)