main
mjs 49 lines 4.03 KB
Raw
1 import assert from "node:assert/strict";
2 import { readFileSync } from "node:fs";
3 import test from "node:test";
4
5 const workspace = readFileSync(new URL("../app/components/investment-workspace.tsx", import.meta.url), "utf8");
6
7 test("immediate connected IBKR authentication bootstraps its broker portfolio exactly once", () => {
8 assert.match(workspace, /ibkrBootstrapSyncsRef = useRef\(new Map<string, Promise<boolean>>\(\)\)/);
9 assert.match(workspace, /if \(brokerType === "IBKR" && action\.status === "CONNECTED"\)[\s\S]*?ibkrBootstrapSyncsRef\.current\.delete\(action\.connectionId\);[\s\S]*?await bootstrapIbkrPortfolio\(action\.connectionId\)/);
10 assert.match(workspace, /const existing = ibkrBootstrapSyncsRef\.current\.get\(connectionId\);[\s\S]*?if \(existing\) return existing;/);
11 assert.match(workspace, /portfolioApi\.syncBrokerConnection\(connectionId\)/);
12 });
13
14 test("IBKR polling bootstraps once on authenticated CONNECTED and never on page load", () => {
15 const refresh = workspace.match(/async function refreshAuthenticatedBroker[\s\S]*?\n }\n\n async function bootstrapIbkrPortfolio/)?.[0] ?? "";
16 assert.match(refresh, /if \(!authStatus\.authenticated \|\| authStatus\.state !== "CONNECTED"\) return false/);
17 assert.match(refresh, /pendingBrokerAuthRef\.current\?\.provider === "IBKR"[\s\S]*?await bootstrapIbkrPortfolio\(connectionId\)/);
18 assert.match(workspace, /if \(provider === "IBKR"\)[\s\S]*?ibkrBootstrapSyncsRef\.current\.delete\(connectionId\);[\s\S]*?pendingBrokerAuthRef\.current = \{ connectionId, provider \}/);
19 const initialLoad = workspace.match(/async function loadPortfolios[\s\S]*?\n }\n\n void loadPortfolios/)?.[0] ?? "";
20 assert.doesNotMatch(initialLoad, /syncBrokerConnection|bootstrapIbkrPortfolio/);
21 });
22
23 test("bootstrap refreshes portfolios and selects only a returned or connection-linked portfolio", () => {
24 const bootstrap = workspace.match(/async function bootstrapIbkrPortfolio[\s\S]*?\n }\n\n async function finishBrokerAuthentication/)?.[0] ?? "";
25 assert.match(bootstrap, /const dashboard = await portfolioApi\.getDashboard\(\)/);
26 assert.match(bootstrap, /setPortfolios\(dashboard\.portfolios\)/);
27 assert.match(bootstrap, /result\.portfolios\.find\(\(portfolio\) =>[\s\S]*?portfolio\.brokerConnectionId === connectionId/);
28 assert.match(bootstrap, /dashboard\.portfolios\.find\(\(portfolio\) =>[\s\S]*?portfolio\.brokerConnectionId === connectionId/);
29 assert.doesNotMatch(bootstrap, /portfolio\.name ===|find\(\(portfolio\) => portfolio\.name/);
30 assert.match(bootstrap, /if \(current\) return current;/);
31 });
32
33 test("bootstrap failure is sanitized, leaves authentication state untouched, and does not sync non-IBKR auth outcomes", () => {
34 const bootstrap = workspace.match(/async function bootstrapIbkrPortfolio[\s\S]*?\n }\n\n async function finishBrokerAuthentication/)?.[0] ?? "";
35 assert.match(bootstrap, /Interactive Brokers connected, but portfolio sync failed\. Try syncing again\./);
36 assert.doesNotMatch(bootstrap, /setBrokerConnections\(\[\]|DISCONNECTED|authenticationAction/);
37 const completion = workspace.match(/async function completeBrokerAuthentication[\s\S]*?\n }\n\n async function login/)?.[0] ?? "";
38 assert.match(completion, /action\.action === "NONE"/);
39 const redirectBranch = completion.match(/if \(action\.action === "REDIRECT_REQUIRED"[\s\S]*?authWindow\.close\(\);/)?.[0] ?? "";
40 assert.doesNotMatch(redirectBranch, /bootstrapIbkrPortfolio/);
41 assert.match(completion, /if \(action\.action === "NONE"\)[\s\S]*?else \{[\s\S]*?setBrokerCardError\(brokerType, action\.message\)/);
42 });
43
44 test("manual selected-portfolio sync and non-IBKR authentication flows stay separate", () => {
45 assert.match(workspace, /async function syncSelectedPortfolio\(\)[\s\S]*?portfolioApi\.syncBrokerConnection\(connectionId\)/);
46 assert.match(workspace, /brokerType === "IBKR" && action\.status === "CONNECTED"/);
47 assert.doesNotMatch(workspace, /brokerType === "ICICI_DIRECT"[\s\S]{0,100}bootstrapIbkrPortfolio/);
48 assert.doesNotMatch(workspace, /brokerType === "HDFC_SECURITIES"[\s\S]{0,100}bootstrapIbkrPortfolio/);
49 });