gloomberb 0.6.1 → 0.7.1
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/package.json +1 -1
- package/patches/@opentui%2Fcore@0.1.90.patch +48 -24
- package/src/app.tsx +158 -57
- package/src/capabilities/factories.ts +3 -0
- package/src/cli/registry.test.ts +0 -1
- package/src/components/chart/chart-controller.ts +0 -1
- package/src/components/chart/chart-data.ts +1 -31
- package/src/components/chart/chart-renderer.ts +94 -12
- package/src/components/chart/chart-resolution.test.ts +0 -36
- package/src/components/chart/chart-resolution.ts +0 -27
- package/src/components/chart/chart.test.ts +60 -45
- package/src/components/chart/comparison-chart-data.test.ts +1 -5
- package/src/components/chart/comparison-chart-data.ts +1 -4
- package/src/components/chart/comparison-chart-renderer.test.ts +26 -0
- package/src/components/chart/comparison-chart-renderer.ts +13 -6
- package/src/components/chart/comparison-stock-chart.tsx +63 -39
- package/src/components/chart/price-axis-labels.tsx +114 -0
- package/src/components/chart/static-chart-surface.tsx +30 -4
- package/src/components/chart/stock-chart.test.ts +0 -16
- package/src/components/chart/stock-chart.tsx +69 -41
- package/src/components/chart/time-axis-label.tsx +120 -0
- package/src/components/command-bar/__snapshots__/command-bar.test.tsx.snap +0 -28
- package/src/components/command-bar/command-bar.test.tsx +182 -36
- package/src/components/command-bar/command-bar.tsx +943 -1016
- package/src/components/command-bar/command-registry.ts +0 -10
- package/src/components/command-bar/confirm-body.tsx +51 -0
- package/src/components/command-bar/helpers.ts +2 -5
- package/src/components/command-bar/list-model.ts +76 -0
- package/src/components/command-bar/theme-picker.tsx +254 -0
- package/src/components/command-bar/view-model.test.ts +4 -4
- package/src/components/command-bar/view-model.ts +1 -20
- package/src/components/command-bar/workflow-ops.ts +4 -0
- package/src/components/command-bar/workflow-types.ts +1 -2
- package/src/components/data-table-stack-view.test.tsx +39 -4
- package/src/components/data-table-stack-view.tsx +11 -104
- package/src/components/data-table-view.tsx +43 -79
- package/src/components/feed-data-table-stack-view.tsx +10 -17
- package/src/components/feed-stack-controller.ts +39 -0
- package/src/components/index.ts +5 -1
- package/src/components/layout/detached-pane-shell.tsx +29 -10
- package/src/components/layout/floating-pane.tsx +35 -4
- package/src/components/layout/header.tsx +12 -7
- package/src/components/layout/pane-content.test.tsx +64 -0
- package/src/components/layout/pane-content.tsx +2 -0
- package/src/components/layout/pane-cycle-order.test.ts +30 -0
- package/src/components/layout/pane-cycle-order.ts +32 -0
- package/src/components/layout/pane-footer.tsx +11 -4
- package/src/components/layout/pane-header.tsx +5 -5
- package/src/components/layout/pane-sizing.ts +9 -2
- package/src/components/layout/pane-title.ts +4 -1
- package/src/components/layout/pane.tsx +11 -5
- package/src/components/layout/shell.test.tsx +264 -22
- package/src/components/layout/shell.tsx +46 -8
- package/src/components/layout/status-bar.tsx +2 -0
- package/src/components/onboarding/onboarding-wizard.tsx +1 -2
- package/src/components/pane-settings-dialog.tsx +12 -4
- package/src/components/pane-template-wizard.test.tsx +3 -4
- package/src/components/speedometer-gauge.test.tsx +45 -0
- package/src/components/speedometer-gauge.tsx +562 -0
- package/src/components/table-view-shared.tsx +218 -0
- package/src/components/ticker-list-table-view.tsx +57 -73
- package/src/components/ticker-list-table.test.tsx +82 -1
- package/src/components/ticker-list-table.tsx +22 -9
- package/src/components/ui/confirm-dialog.tsx +66 -0
- package/src/components/ui/data-table.tsx +30 -19
- package/src/components/ui/frame.tsx +2 -0
- package/src/components/ui/index.ts +0 -1
- package/src/components/ui/page-stack-view.tsx +39 -10
- package/src/components/ui/table-layout.test.ts +42 -0
- package/src/components/ui/table-layout.ts +49 -4
- package/src/components/ui/tabs.tsx +34 -1
- package/src/components/ui/ui.test.tsx +168 -21
- package/src/core/state/app-state.ts +10 -17
- package/src/market-data/coordinator.test.ts +76 -1
- package/src/market-data/coordinator.ts +218 -49
- package/src/news/aggregator.test.ts +49 -1
- package/src/news/aggregator.ts +48 -3
- package/src/news/hooks.ts +6 -2
- package/src/plugins/builtin/ai/ask-ai-detail-tab.tsx +46 -16
- package/src/plugins/builtin/ai/providers.ts +0 -17
- package/src/plugins/builtin/ai/screener-pane.test.tsx +3 -4
- package/src/plugins/builtin/ai/screener-pane.tsx +3 -5
- package/src/plugins/builtin/analytics/index.tsx +1 -18
- package/src/plugins/builtin/ask-ai.test.tsx +89 -2
- package/src/plugins/builtin/broker-manager/index.test.tsx +2 -2
- package/src/plugins/builtin/broker-manager/index.tsx +19 -36
- package/src/plugins/builtin/chat-controller.test.ts +188 -1
- package/src/plugins/builtin/chat-controller.ts +537 -220
- package/src/plugins/builtin/chat.test.tsx +431 -13
- package/src/plugins/builtin/chat.tsx +1134 -227
- package/src/plugins/builtin/cloud-tweets.tsx +1 -1
- package/src/plugins/builtin/comparison-chart.test.tsx +53 -2
- package/src/plugins/builtin/comparison-chart.tsx +11 -5
- package/src/plugins/builtin/correlation/index.tsx +1 -6
- package/src/plugins/builtin/debug.tsx +1 -3
- package/src/plugins/builtin/econ/index.tsx +1 -2
- package/src/plugins/builtin/fear-greed/fear-greed-data.test.ts +72 -0
- package/src/plugins/builtin/fear-greed/fear-greed-data.ts +366 -0
- package/src/plugins/builtin/fear-greed/index.tsx +587 -0
- package/src/plugins/builtin/fx-matrix/index.tsx +2 -2
- package/src/plugins/builtin/help.test.tsx +2 -2
- package/src/plugins/builtin/help.tsx +2 -2
- package/src/plugins/builtin/holders/index.test.ts +13 -1
- package/src/plugins/builtin/holders/index.tsx +64 -29
- package/src/plugins/builtin/insider/index.tsx +22 -89
- package/src/plugins/builtin/market-movers/index.tsx +13 -19
- package/src/plugins/builtin/market-movers/screener.test.ts +39 -1
- package/src/plugins/builtin/market-movers/screener.ts +70 -17
- package/src/plugins/builtin/news-wire/breaking-pane.tsx +3 -2
- package/src/plugins/builtin/news-wire/index.tsx +41 -2
- package/src/plugins/builtin/news-wire/industry-pane.tsx +4 -18
- package/src/plugins/builtin/news-wire/news-detail-view.tsx +46 -4
- package/src/plugins/builtin/news-wire/news-preset-pane.tsx +3 -2
- package/src/plugins/builtin/news-wire/news-table.tsx +11 -11
- package/src/plugins/builtin/news.tsx +4 -16
- package/src/plugins/builtin/notes.tsx +19 -55
- package/src/plugins/builtin/options.test.tsx +58 -2
- package/src/plugins/builtin/options.tsx +110 -65
- package/src/plugins/builtin/plugin-groups.ts +2 -0
- package/src/plugins/builtin/portfolio-list/cli/commands.ts +1 -1
- package/src/plugins/builtin/portfolio-list/pane.tsx +16 -39
- package/src/plugins/builtin/research/index.test.ts +94 -0
- package/src/plugins/builtin/research/index.tsx +164 -33
- package/src/plugins/builtin/sec-filing-display.tsx +84 -0
- package/src/plugins/builtin/sec.tsx +13 -66
- package/src/plugins/builtin/sectors/index.tsx +1 -1
- package/src/plugins/builtin/ticker-detail/chart-tab.tsx +0 -1
- package/src/plugins/builtin/ticker-detail/index.tsx +0 -1
- package/src/plugins/builtin/ticker-detail/overview-tab.tsx +0 -1
- package/src/plugins/builtin/ticker-detail/pane.tsx +28 -22
- package/src/plugins/builtin/ticker-detail-chart-tab-switch.test.tsx +3 -4
- package/src/plugins/builtin/ticker-detail.test.tsx +38 -0
- package/src/plugins/builtin/world-indices/index.tsx +1 -1
- package/src/plugins/builtin/yield-curve/index.tsx +1 -1
- package/src/plugins/ibkr/broker-adapter.ts +1 -3
- package/src/plugins/ibkr/gateway-service-native.ts +1 -5
- package/src/plugins/ibkr/gateway-service.ts +1 -1
- package/src/plugins/ibkr/index.test.tsx +0 -2
- package/src/plugins/ibkr/trade-tab.test.tsx +3 -4
- package/src/plugins/pane-manager.ts +0 -13
- package/src/plugins/plugin-runtime.test.tsx +40 -6
- package/src/plugins/plugin-runtime.tsx +20 -10
- package/src/plugins/prediction-markets/cli.ts +0 -1
- package/src/plugins/prediction-markets/controller-data.ts +0 -2
- package/src/plugins/prediction-markets/controller.ts +0 -15
- package/src/plugins/prediction-markets/detail/pane.tsx +1 -0
- package/src/plugins/prediction-markets/pane.test.tsx +3 -11
- package/src/plugins/prediction-markets/test-helpers.tsx +1 -1
- package/src/plugins/registry.ts +13 -42
- package/src/plugins/ticker-navigation.test.ts +66 -0
- package/src/plugins/ticker-navigation.ts +44 -0
- package/src/react/input.ts +2 -1
- package/src/renderers/electrobun/bun/index.ts +32 -11
- package/src/renderers/electrobun/bun/window-focus.ts +37 -0
- package/src/renderers/electrobun/shared/protocol.ts +7 -1
- package/src/renderers/electrobun/view/app-services.ts +88 -31
- package/src/renderers/electrobun/view/backend-rpc.ts +15 -0
- package/src/renderers/electrobun/view/data-table.tsx +138 -101
- package/src/renderers/electrobun/view/desktop-controls.tsx +42 -20
- package/src/renderers/electrobun/view/desktop-window-bridge.ts +12 -1
- package/src/renderers/electrobun/view/dialog-host.tsx +13 -1
- package/src/renderers/electrobun/view/input-host.tsx +74 -10
- package/src/renderers/electrobun/view/key-event.ts +1 -1
- package/src/renderers/electrobun/view/main.tsx +18 -1
- package/src/renderers/electrobun/view/styles.css +329 -0
- package/src/renderers/electrobun/view/toast-host.tsx +29 -3
- package/src/renderers/electrobun/view/ui-host.tsx +42 -0
- package/src/renderers/opentui/chart-surface.tsx +179 -0
- package/src/renderers/opentui/input-host.tsx +1 -1
- package/src/renderers/opentui/start.tsx +48 -30
- package/src/renderers/opentui/test-utils.tsx +17 -0
- package/src/renderers/opentui/ui-host.tsx +5 -2
- package/src/sources/gloomberb-cloud.test.ts +86 -1
- package/src/sources/gloomberb-cloud.ts +117 -21
- package/src/sources/provider-router.test.ts +122 -0
- package/src/sources/provider-router.ts +198 -15
- package/src/sources/yahoo-finance.test.ts +44 -0
- package/src/sources/yahoo-finance.ts +6 -0
- package/src/state/app-bootstrap.ts +20 -7
- package/src/state/app-context-selector.test.tsx +189 -4
- package/src/state/app-context.test.ts +65 -0
- package/src/state/app-context.tsx +48 -16
- package/src/state/use-inline-tickers.test.tsx +73 -0
- package/src/state/use-inline-tickers.ts +19 -10
- package/src/test-support/plugin-runtime.ts +3 -2
- package/src/theme/colors.test.ts +75 -0
- package/src/theme/colors.ts +76 -6
- package/src/theme/theme-context.tsx +26 -0
- package/src/theme/themes.test.ts +23 -1
- package/src/theme/themes.ts +115 -0
- package/src/types/broker.ts +1 -1
- package/src/types/capability-route-source.ts +1 -0
- package/src/types/data-provider.ts +15 -2
- package/src/types/desktop-window.ts +6 -0
- package/src/types/financials.ts +2 -0
- package/src/types/plugin.ts +1 -3
- package/src/ui/host.tsx +7 -0
- package/src/utils/api-client.test.ts +32 -0
- package/src/utils/api-client.ts +119 -18
- package/src/utils/back-navigation.ts +24 -1
- package/src/utils/double-escape-close.test.ts +33 -0
- package/src/utils/double-escape-close.ts +40 -0
- package/src/utils/throttled-fetch.test.ts +22 -0
- package/src/utils/throttled-fetch.ts +3 -1
- package/src/utils/ticker-search.ts +53 -9
- package/src/version.ts +1 -1
- package/src/plugins/builtin/news-wire/feed-pane.tsx +0 -21
- package/src/plugins/builtin/news-wire/top-pane.tsx +0 -21
|
@@ -1,14 +1,15 @@
|
|
|
1
1
|
import { afterEach, describe, expect, test } from "bun:test";
|
|
2
2
|
import { act, useReducer } from "react";
|
|
3
|
-
import { testRender } from "../../renderers/opentui/test-utils";
|
|
4
|
-
import { DialogProvider } from "@opentui-ui/dialog/react";
|
|
3
|
+
import { TestDialogProvider, testRender } from "../../renderers/opentui/test-utils";
|
|
5
4
|
import { CommandBar } from "./command-bar";
|
|
6
|
-
import { AppContext, type AppState, appReducer, createInitialState, getEffectiveThemeId } from "../../state/app-context";
|
|
5
|
+
import { AppContext, type AppAction, type AppState, appReducer, createInitialState, getEffectiveThemeId } from "../../state/app-context";
|
|
7
6
|
import { createTestDataProvider } from "../../test-support/data-provider";
|
|
7
|
+
import { ThemeProvider, useThemeId } from "../../theme/theme-context";
|
|
8
8
|
import { cloneLayout, createDefaultConfig, type AppConfig } from "../../types/config";
|
|
9
9
|
import type { DataProvider } from "../../types/data-provider";
|
|
10
10
|
import type { TickerRecord } from "../../types/ticker";
|
|
11
11
|
import type { PluginRegistry } from "../../plugins/registry";
|
|
12
|
+
import type { PaneTemplateCreateOptions } from "../../types/plugin";
|
|
12
13
|
|
|
13
14
|
let testSetup: Awaited<ReturnType<typeof testRender>> | undefined;
|
|
14
15
|
|
|
@@ -162,7 +163,7 @@ function makePluginRegistry(hasPaneSettings: (paneId: string) => boolean = () =>
|
|
|
162
163
|
paneId: "chat",
|
|
163
164
|
label: "New Chat Pane",
|
|
164
165
|
description: "Open another floating chat window",
|
|
165
|
-
shortcut: { prefix: "CHAT" },
|
|
166
|
+
shortcut: { prefix: "CHAT", argPlaceholder: "channel", argKind: "text" },
|
|
166
167
|
}],
|
|
167
168
|
["quote-monitor-pane", {
|
|
168
169
|
id: "quote-monitor-pane",
|
|
@@ -213,9 +214,9 @@ function makePluginRegistry(hasPaneSettings: (paneId: string) => boolean = () =>
|
|
|
213
214
|
getPluginPaneTemplateIds: () => [],
|
|
214
215
|
hasPaneSettings,
|
|
215
216
|
events: { emit: () => {} },
|
|
216
|
-
|
|
217
|
+
hidePane: () => {},
|
|
217
218
|
pinTicker: () => {},
|
|
218
|
-
|
|
219
|
+
showPane: () => {},
|
|
219
220
|
updateLayoutFn: () => {},
|
|
220
221
|
getTermSizeFn: () => ({ width: 80, height: 24 }),
|
|
221
222
|
notify: () => {},
|
|
@@ -231,6 +232,10 @@ function makePluginRegistry(hasPaneSettings: (paneId: string) => boolean = () =>
|
|
|
231
232
|
} as unknown as PluginRegistry;
|
|
232
233
|
}
|
|
233
234
|
|
|
235
|
+
function ThemeProbe() {
|
|
236
|
+
return <text>{`theme:${useThemeId()}`}</text>;
|
|
237
|
+
}
|
|
238
|
+
|
|
234
239
|
function CommandBarHarness({
|
|
235
240
|
query,
|
|
236
241
|
disabledPlugins = [],
|
|
@@ -245,6 +250,7 @@ function CommandBarHarness({
|
|
|
245
250
|
dataProvider = makeDataProvider(),
|
|
246
251
|
hasPaneSettings,
|
|
247
252
|
onCheckForUpdates,
|
|
253
|
+
onAction,
|
|
248
254
|
}: {
|
|
249
255
|
query: string;
|
|
250
256
|
disabledPlugins?: string[];
|
|
@@ -259,6 +265,7 @@ function CommandBarHarness({
|
|
|
259
265
|
dataProvider?: DataProvider;
|
|
260
266
|
hasPaneSettings?: (paneId: string) => boolean;
|
|
261
267
|
onCheckForUpdates?: () => void | Promise<void>;
|
|
268
|
+
onAction?: (action: AppAction) => void;
|
|
262
269
|
}) {
|
|
263
270
|
let config = {
|
|
264
271
|
...createDefaultConfig("/tmp/gloomberb-test"),
|
|
@@ -273,6 +280,7 @@ function CommandBarHarness({
|
|
|
273
280
|
...createInitialState(config),
|
|
274
281
|
commandBarOpen: true,
|
|
275
282
|
commandBarQuery: query,
|
|
283
|
+
focusedPaneId: "portfolio-list:main",
|
|
276
284
|
tickers: new Map(tickers.map((ticker) => [ticker.metadata.ticker, ticker])),
|
|
277
285
|
config: { ...config, disabledPlugins },
|
|
278
286
|
paneState: selectedTicker
|
|
@@ -300,24 +308,31 @@ function CommandBarHarness({
|
|
|
300
308
|
configurePluginRegistry?.(pluginRegistry);
|
|
301
309
|
const [liveState, dispatch] = useReducer(appReducer, state);
|
|
302
310
|
const currentState = live ? liveState : state;
|
|
303
|
-
const currentDispatch = live
|
|
311
|
+
const currentDispatch = live
|
|
312
|
+
? (action: AppAction) => {
|
|
313
|
+
onAction?.(action);
|
|
314
|
+
dispatch(action);
|
|
315
|
+
}
|
|
316
|
+
: (_action: AppAction) => {};
|
|
304
317
|
|
|
305
318
|
return (
|
|
306
|
-
<
|
|
307
|
-
<
|
|
308
|
-
|
|
309
|
-
|
|
310
|
-
|
|
311
|
-
|
|
312
|
-
|
|
313
|
-
|
|
314
|
-
|
|
315
|
-
|
|
316
|
-
|
|
317
|
-
|
|
318
|
-
|
|
319
|
-
|
|
320
|
-
|
|
319
|
+
<ThemeProvider themeId={getEffectiveThemeId(currentState)}>
|
|
320
|
+
<AppContext value={{ state: currentState, dispatch: currentDispatch }}>
|
|
321
|
+
<TestDialogProvider>
|
|
322
|
+
{live && <ThemeProbe />}
|
|
323
|
+
{showQueryState && <text>{`query:${currentState.commandBarQuery}`}</text>}
|
|
324
|
+
{currentState.commandBarOpen && (
|
|
325
|
+
<CommandBar
|
|
326
|
+
dataProvider={dataProvider}
|
|
327
|
+
tickerRepository={tickerRepository as any}
|
|
328
|
+
pluginRegistry={pluginRegistry}
|
|
329
|
+
quitApp={() => {}}
|
|
330
|
+
onCheckForUpdates={onCheckForUpdates}
|
|
331
|
+
/>
|
|
332
|
+
)}
|
|
333
|
+
</TestDialogProvider>
|
|
334
|
+
</AppContext>
|
|
335
|
+
</ThemeProvider>
|
|
321
336
|
);
|
|
322
337
|
}
|
|
323
338
|
|
|
@@ -334,7 +349,7 @@ describe("CommandBar", () => {
|
|
|
334
349
|
});
|
|
335
350
|
|
|
336
351
|
test("runs check for updates from the command bar", async () => {
|
|
337
|
-
const calls = [];
|
|
352
|
+
const calls: number[] = [];
|
|
338
353
|
|
|
339
354
|
testSetup = await testRender(<CommandBarHarness query="check for updates" live onCheckForUpdates={() => { calls.push(Date.now()); }} />, {
|
|
340
355
|
width: 80,
|
|
@@ -739,8 +754,12 @@ describe("CommandBar", () => {
|
|
|
739
754
|
const frame = testSetup.captureCharFrame();
|
|
740
755
|
expect(frame).toContain("Commands");
|
|
741
756
|
expect(frame).toContain("TH");
|
|
742
|
-
expect(frame).toContain("
|
|
743
|
-
expect(frame).
|
|
757
|
+
expect(frame).toContain("Amber");
|
|
758
|
+
expect(frame).toContain("Paper");
|
|
759
|
+
expect(frame).toContain("GitHub Light");
|
|
760
|
+
expect(frame).toContain("Solarized Light");
|
|
761
|
+
expect(frame).toContain("Gruvbox Light");
|
|
762
|
+
expect(frame).toContain("Nord Light");
|
|
744
763
|
});
|
|
745
764
|
|
|
746
765
|
test("renders plugin toggle state", async () => {
|
|
@@ -793,6 +812,7 @@ describe("CommandBar", () => {
|
|
|
793
812
|
await testSetup.renderOnce();
|
|
794
813
|
await act(async () => {
|
|
795
814
|
testSetup!.mockInput.pressArrow("down");
|
|
815
|
+
await Bun.sleep(220);
|
|
796
816
|
await testSetup!.renderOnce();
|
|
797
817
|
});
|
|
798
818
|
await testSetup.renderOnce();
|
|
@@ -801,6 +821,38 @@ describe("CommandBar", () => {
|
|
|
801
821
|
expect(frame).toContain("theme:green");
|
|
802
822
|
});
|
|
803
823
|
|
|
824
|
+
test("debounces rapid keyboard theme previews", async () => {
|
|
825
|
+
const actions: AppAction[] = [];
|
|
826
|
+
testSetup = await testRender(
|
|
827
|
+
<CommandBarHarness query="TH " live onAction={(action) => actions.push(action)} />,
|
|
828
|
+
{ width: 80, height: 24 },
|
|
829
|
+
);
|
|
830
|
+
|
|
831
|
+
await testSetup.renderOnce();
|
|
832
|
+
await act(async () => {
|
|
833
|
+
for (let index = 0; index < 6; index++) {
|
|
834
|
+
testSetup!.mockInput.pressArrow("down");
|
|
835
|
+
}
|
|
836
|
+
await testSetup!.renderOnce();
|
|
837
|
+
});
|
|
838
|
+
|
|
839
|
+
expect(actions.filter((action) => action.type === "PREVIEW_THEME")).toHaveLength(0);
|
|
840
|
+
|
|
841
|
+
await act(async () => {
|
|
842
|
+
await Bun.sleep(100);
|
|
843
|
+
await testSetup!.renderOnce();
|
|
844
|
+
});
|
|
845
|
+
|
|
846
|
+
expect(actions.filter((action) => action.type === "PREVIEW_THEME")).toHaveLength(0);
|
|
847
|
+
|
|
848
|
+
await act(async () => {
|
|
849
|
+
await Bun.sleep(150);
|
|
850
|
+
await testSetup!.renderOnce();
|
|
851
|
+
});
|
|
852
|
+
|
|
853
|
+
expect(actions.filter((action) => action.type === "PREVIEW_THEME")).toHaveLength(1);
|
|
854
|
+
});
|
|
855
|
+
|
|
804
856
|
test("does not preview a theme from mouse hover alone", async () => {
|
|
805
857
|
testSetup = await testRender(<CommandBarHarness query="TH " live />, {
|
|
806
858
|
width: 80,
|
|
@@ -836,6 +888,7 @@ describe("CommandBar", () => {
|
|
|
836
888
|
await testSetup.renderOnce();
|
|
837
889
|
await act(async () => {
|
|
838
890
|
testSetup!.mockInput.pressArrow("down");
|
|
891
|
+
await Bun.sleep(220);
|
|
839
892
|
await testSetup!.renderOnce();
|
|
840
893
|
});
|
|
841
894
|
await testSetup.renderOnce();
|
|
@@ -883,8 +936,10 @@ describe("CommandBar", () => {
|
|
|
883
936
|
await testSetup.renderOnce();
|
|
884
937
|
await act(async () => {
|
|
885
938
|
testSetup!.mockInput.pressArrow("down");
|
|
939
|
+
await Bun.sleep(220);
|
|
886
940
|
await testSetup!.renderOnce();
|
|
887
941
|
});
|
|
942
|
+
await testSetup.renderOnce();
|
|
888
943
|
expect(testSetup.captureCharFrame()).toContain("theme:green");
|
|
889
944
|
|
|
890
945
|
await emitKeypress(testSetup, { name: "u", ctrl: true });
|
|
@@ -952,7 +1007,7 @@ describe("CommandBar", () => {
|
|
|
952
1007
|
});
|
|
953
1008
|
|
|
954
1009
|
test("typing a shorthand and pressing enter executes the inferred quote monitor shortcut", async () => {
|
|
955
|
-
const created: Array<{ templateId: string; options?:
|
|
1010
|
+
const created: Array<{ templateId: string; options?: PaneTemplateCreateOptions }> = [];
|
|
956
1011
|
|
|
957
1012
|
testSetup = await testRender(<CommandBarHarness
|
|
958
1013
|
query=""
|
|
@@ -987,6 +1042,39 @@ describe("CommandBar", () => {
|
|
|
987
1042
|
}]);
|
|
988
1043
|
});
|
|
989
1044
|
|
|
1045
|
+
test("typing a chat channel shortcut opens that channel directly", async () => {
|
|
1046
|
+
const created: Array<{ templateId: string; options?: PaneTemplateCreateOptions }> = [];
|
|
1047
|
+
|
|
1048
|
+
testSetup = await testRender(<CommandBarHarness
|
|
1049
|
+
query=""
|
|
1050
|
+
live
|
|
1051
|
+
configurePluginRegistry={(pluginRegistry) => {
|
|
1052
|
+
pluginRegistry.createPaneFromTemplateAsyncFn = async (templateId, options) => {
|
|
1053
|
+
created.push({ templateId, options });
|
|
1054
|
+
};
|
|
1055
|
+
}}
|
|
1056
|
+
/>, {
|
|
1057
|
+
width: 100,
|
|
1058
|
+
height: 20,
|
|
1059
|
+
});
|
|
1060
|
+
|
|
1061
|
+
await testSetup.renderOnce();
|
|
1062
|
+
|
|
1063
|
+
await act(async () => {
|
|
1064
|
+
await testSetup!.mockInput.typeText("CHAT help");
|
|
1065
|
+
testSetup!.mockInput.pressEnter();
|
|
1066
|
+
await Bun.sleep(0);
|
|
1067
|
+
await testSetup!.renderOnce();
|
|
1068
|
+
});
|
|
1069
|
+
|
|
1070
|
+
expect(created).toEqual([{
|
|
1071
|
+
templateId: "new-chat-pane",
|
|
1072
|
+
options: {
|
|
1073
|
+
arg: "help",
|
|
1074
|
+
},
|
|
1075
|
+
}]);
|
|
1076
|
+
});
|
|
1077
|
+
|
|
990
1078
|
test("clears the root query with cmd-backspace", async () => {
|
|
991
1079
|
testSetup = await testRender(<CommandBarHarness query="DES AMD" />, {
|
|
992
1080
|
width: 80,
|
|
@@ -1649,7 +1737,6 @@ describe("CommandBar", () => {
|
|
|
1649
1737
|
await testSetup.renderOnce();
|
|
1650
1738
|
const initialFrame = testSetup.captureCharFrame();
|
|
1651
1739
|
expect(initialFrame).toContain("Delete Layout");
|
|
1652
|
-
expect(initialFrame).toContain("Danger");
|
|
1653
1740
|
|
|
1654
1741
|
await act(async () => {
|
|
1655
1742
|
testSetup!.mockInput.pressEnter();
|
|
@@ -1900,7 +1987,7 @@ describe("CommandBar", () => {
|
|
|
1900
1987
|
});
|
|
1901
1988
|
|
|
1902
1989
|
test("does not treat no-argument shortcut prefixes as typed pane names", async () => {
|
|
1903
|
-
const created: Array<{ templateId: string; options?:
|
|
1990
|
+
const created: Array<{ templateId: string; options?: PaneTemplateCreateOptions }> = [];
|
|
1904
1991
|
|
|
1905
1992
|
testSetup = await testRender(<CommandBarHarness
|
|
1906
1993
|
query="Top News"
|
|
@@ -2086,7 +2173,7 @@ describe("CommandBar", () => {
|
|
|
2086
2173
|
});
|
|
2087
2174
|
|
|
2088
2175
|
test("QQ MSFT executes directly without opening a secondary workflow", async () => {
|
|
2089
|
-
const created: Array<{ templateId: string; options?:
|
|
2176
|
+
const created: Array<{ templateId: string; options?: PaneTemplateCreateOptions }> = [];
|
|
2090
2177
|
|
|
2091
2178
|
testSetup = await testRender(<CommandBarHarness
|
|
2092
2179
|
query="QQ MSFT"
|
|
@@ -2119,7 +2206,7 @@ describe("CommandBar", () => {
|
|
|
2119
2206
|
});
|
|
2120
2207
|
|
|
2121
2208
|
test("CMP AAPL,MSFT creates the comparison chart directly", async () => {
|
|
2122
|
-
const created: Array<{ templateId: string; options?:
|
|
2209
|
+
const created: Array<{ templateId: string; options?: PaneTemplateCreateOptions }> = [];
|
|
2123
2210
|
|
|
2124
2211
|
testSetup = await testRender(<CommandBarHarness
|
|
2125
2212
|
query="CMP AAPL,MSFT"
|
|
@@ -2197,8 +2284,52 @@ describe("CommandBar", () => {
|
|
|
2197
2284
|
expect(frame).toContain("AAPL,");
|
|
2198
2285
|
});
|
|
2199
2286
|
|
|
2287
|
+
test("CMP with one resolved ticker opens inline completion instead of creating a one-symbol chart", async () => {
|
|
2288
|
+
const created: Array<{ templateId: string; options?: PaneTemplateCreateOptions }> = [];
|
|
2289
|
+
|
|
2290
|
+
testSetup = await testRender(<CommandBarHarness
|
|
2291
|
+
query="CMP AMD"
|
|
2292
|
+
extraTickers={[makeTicker("AMD", "Advanced Micro Devices")]}
|
|
2293
|
+
configurePluginRegistry={(pluginRegistry) => {
|
|
2294
|
+
(pluginRegistry.panes as Map<string, any>).set("comparison-chart", {
|
|
2295
|
+
id: "comparison-chart",
|
|
2296
|
+
name: "Comparison Chart",
|
|
2297
|
+
component: () => null,
|
|
2298
|
+
defaultPosition: "right",
|
|
2299
|
+
});
|
|
2300
|
+
(pluginRegistry.paneTemplates as Map<string, any>).set("comparison-chart-pane", {
|
|
2301
|
+
id: "comparison-chart-pane",
|
|
2302
|
+
paneId: "comparison-chart",
|
|
2303
|
+
label: "Comparison Chart",
|
|
2304
|
+
description: "Compare multiple symbols in one pane",
|
|
2305
|
+
shortcut: { prefix: "CMP", argPlaceholder: "tickers", argKind: "ticker-list" },
|
|
2306
|
+
wizard: [{ key: "tickers", label: "Tickers", type: "text" }],
|
|
2307
|
+
canCreate: (_context: unknown, options?: { symbols?: string[] | null }) => !options?.symbols || options.symbols.length >= 2,
|
|
2308
|
+
});
|
|
2309
|
+
pluginRegistry.createPaneFromTemplateAsyncFn = async (templateId, options) => {
|
|
2310
|
+
created.push({ templateId, options });
|
|
2311
|
+
};
|
|
2312
|
+
}}
|
|
2313
|
+
/>, {
|
|
2314
|
+
width: 100,
|
|
2315
|
+
height: 20,
|
|
2316
|
+
});
|
|
2317
|
+
|
|
2318
|
+
await testSetup.renderOnce();
|
|
2319
|
+
await act(async () => {
|
|
2320
|
+
testSetup!.mockInput.pressEnter();
|
|
2321
|
+
await Bun.sleep(0);
|
|
2322
|
+
await testSetup!.renderOnce();
|
|
2323
|
+
});
|
|
2324
|
+
|
|
2325
|
+
const frame = await waitForFrameToContain("Tickers");
|
|
2326
|
+
expect(created).toEqual([]);
|
|
2327
|
+
expect(frame).toContain("Comparison Chart");
|
|
2328
|
+
expect(frame).toContain("AMD");
|
|
2329
|
+
});
|
|
2330
|
+
|
|
2200
2331
|
test("AI <prompt> opens the inline workflow and prefills the textarea prompt", async () => {
|
|
2201
|
-
const created: Array<{ templateId: string; options?:
|
|
2332
|
+
const created: Array<{ templateId: string; options?: PaneTemplateCreateOptions }> = [];
|
|
2202
2333
|
|
|
2203
2334
|
testSetup = await testRender(<CommandBarHarness
|
|
2204
2335
|
query="AI quality compounders"
|
|
@@ -2254,7 +2385,7 @@ describe("CommandBar", () => {
|
|
|
2254
2385
|
});
|
|
2255
2386
|
|
|
2256
2387
|
test("submits typed AI screener prompts from the textarea field", async () => {
|
|
2257
|
-
const created: Array<{ templateId: string; options?:
|
|
2388
|
+
const created: Array<{ templateId: string; options?: PaneTemplateCreateOptions }> = [];
|
|
2258
2389
|
|
|
2259
2390
|
testSetup = await testRender(<CommandBarHarness
|
|
2260
2391
|
query="AI"
|
|
@@ -2608,7 +2739,15 @@ describe("CommandBar", () => {
|
|
|
2608
2739
|
});
|
|
2609
2740
|
|
|
2610
2741
|
test("matches the direct help command", async () => {
|
|
2611
|
-
|
|
2742
|
+
const openedPanes: string[] = [];
|
|
2743
|
+
testSetup = await testRender(<CommandBarHarness
|
|
2744
|
+
query="help"
|
|
2745
|
+
configurePluginRegistry={(pluginRegistry) => {
|
|
2746
|
+
pluginRegistry.showPane = (paneId: string) => {
|
|
2747
|
+
openedPanes.push(paneId);
|
|
2748
|
+
};
|
|
2749
|
+
}}
|
|
2750
|
+
/>, {
|
|
2612
2751
|
width: 80,
|
|
2613
2752
|
height: 18,
|
|
2614
2753
|
});
|
|
@@ -2618,6 +2757,13 @@ describe("CommandBar", () => {
|
|
|
2618
2757
|
const frame = testSetup.captureCharFrame();
|
|
2619
2758
|
expect(frame).toContain("Help");
|
|
2620
2759
|
expect(frame).toContain("Navigation");
|
|
2760
|
+
|
|
2761
|
+
await act(async () => {
|
|
2762
|
+
testSetup!.mockInput.pressEnter();
|
|
2763
|
+
await testSetup!.renderOnce();
|
|
2764
|
+
});
|
|
2765
|
+
|
|
2766
|
+
expect(openedPanes).toEqual(["help"]);
|
|
2621
2767
|
});
|
|
2622
2768
|
|
|
2623
2769
|
test("skips pane templates whose canCreate throws", async () => {
|
|
@@ -2686,7 +2832,7 @@ describe("CommandBar", () => {
|
|
|
2686
2832
|
query="auth login"
|
|
2687
2833
|
live
|
|
2688
2834
|
configurePluginRegistry={(pluginRegistry) => {
|
|
2689
|
-
pluginRegistry.commands.set("auth-login", {
|
|
2835
|
+
(pluginRegistry.commands as Map<string, any>).set("auth-login", {
|
|
2690
2836
|
id: "auth-login",
|
|
2691
2837
|
label: "Auth Login",
|
|
2692
2838
|
description: "Log in to your account",
|
|
@@ -2726,7 +2872,7 @@ describe("CommandBar", () => {
|
|
|
2726
2872
|
query="workspace"
|
|
2727
2873
|
live
|
|
2728
2874
|
configurePluginRegistry={(pluginRegistry) => {
|
|
2729
|
-
pluginRegistry.commands.set("new-workspace", {
|
|
2875
|
+
(pluginRegistry.commands as Map<string, any>).set("new-workspace", {
|
|
2730
2876
|
id: "new-workspace",
|
|
2731
2877
|
label: "Workspace",
|
|
2732
2878
|
description: "Create a workspace",
|
|
@@ -2736,7 +2882,7 @@ describe("CommandBar", () => {
|
|
|
2736
2882
|
wizard: [
|
|
2737
2883
|
{ key: "name", label: "Name", type: "text", placeholder: "Research" },
|
|
2738
2884
|
],
|
|
2739
|
-
execute: async (values) => {
|
|
2885
|
+
execute: async (values?: Record<string, string>) => {
|
|
2740
2886
|
submitted.push(values);
|
|
2741
2887
|
},
|
|
2742
2888
|
} as any);
|