111 lines
3.5 KiB
TypeScript
111 lines
3.5 KiB
TypeScript
import { describe, it } from "node:test";
|
|||
|
|
import * as assert from "node:assert/strict";
|
||
|
|
|
||
|
|
import {
|
||
|
|
STARTER_WATCHLIST,
|
||
|
|
ONBOARDING_DISCLAIMER,
|
||
|
|
defaultDrawdownTolerancePct,
|
||
|
|
defaultRiskTolerance,
|
||
|
|
type StarterSymbol,
|
||
|
|
} from "../starter.ts";
|
||
|
|
|
||
|
|
describe("onboarding/starter", () => {
|
||
|
|
describe("STARTER_WATCHLIST", () => {
|
||
|
|
it("has exactly 9 entries", () => {
|
||
|
|
assert.equal(STARTER_WATCHLIST.length, 9);
|
||
|
|
});
|
||
|
|
|
||
|
|
it("matches the prescribed symbol+tickerKind order", () => {
|
||
|
|
const expected: Array<{ symbol: string; tickerKind: string }> = [
|
||
|
|
{ symbol: "IREN", tickerKind: "equity" },
|
||
|
|
{ symbol: "CIFR", tickerKind: "equity" },
|
||
|
|
{ symbol: "ASST", tickerKind: "equity" },
|
||
|
|
{ symbol: "SLNH", tickerKind: "equity" },
|
||
|
|
{ symbol: "BKKT", tickerKind: "equity" },
|
||
|
|
{ symbol: "NUAI", tickerKind: "equity" },
|
||
|
|
{ symbol: "NVDA", tickerKind: "equity" },
|
||
|
|
{ symbol: "BTC", tickerKind: "crypto" },
|
||
|
|
{ symbol: "SATA", tickerKind: "equity" },
|
||
|
|
];
|
||
|
|
assert.equal(STARTER_WATCHLIST.length, expected.length);
|
||
|
|
for (let i = 0; i < expected.length; i++) {
|
||
|
|
const got: StarterSymbol = STARTER_WATCHLIST[i];
|
||
|
|
assert.equal(got.symbol, expected[i].symbol, `item #${i} symbol`);
|
||
|
|
assert.equal(got.tickerKind, expected[i].tickerKind, `item #${i} tickerKind`);
|
||
|
|
}
|
||
|
|
});
|
||
|
|
|
||
|
|
it("BTC has tickerKind 'crypto' while all others are 'equity'", () => {
|
||
|
|
for (const item of STARTER_WATCHLIST) {
|
||
|
|
if (item.symbol === "BTC") {
|
||
|
|
assert.equal(item.tickerKind, "crypto");
|
||
|
|
} else {
|
||
|
|
assert.equal(item.tickerKind, "equity");
|
||
|
|
}
|
||
|
|
}
|
||
|
|
});
|
||
|
|
|
||
|
|
it("every entry has a non-empty reason string", () => {
|
||
|
|
for (const item of STARTER_WATCHLIST) {
|
||
|
|
assert.ok(item.reason.length > 0, `reason for ${item.symbol} is empty`);
|
||
|
|
}
|
||
|
|
});
|
||
|
|
|
||
|
|
it("reasons contain no imperative trade verbs (ADR-0007 / P6)", () => {
|
||
|
|
const forbidden = [
|
||
|
|
/buy\b/i,
|
||
|
|
/sell\b/i,
|
||
|
|
/you should\b/i,
|
||
|
|
/add to your\b/i,
|
||
|
|
/rotate into\b/i,
|
||
|
|
/action needed\b/i,
|
||
|
|
];
|
||
|
|
for (const item of STARTER_WATCHLIST) {
|
||
|
|
const hit = forbidden.find((rx) => rx.test(item.reason));
|
||
|
|
assert.equal(hit, undefined, `forbidden verb in reason for ${item.symbol}`);
|
||
|
|
}
|
||
|
|
});
|
||
|
|
});
|
||
|
|
|
||
|
|
describe("defaultDrawdownTolerancePct", () => {
|
||
|
|
it("returns -20 for beginner", () => {
|
||
|
|
assert.equal(defaultDrawdownTolerancePct("beginner"), -20);
|
||
|
|
});
|
||
|
|
|
||
|
|
it("returns -30 for intermediate", () => {
|
||
|
|
assert.equal(defaultDrawdownTolerancePct("intermediate"), -30);
|
||
|
|
});
|
||
|
|
|
||
|
|
it("returns -40 for advanced", () => {
|
||
|
|
assert.equal(defaultDrawdownTolerancePct("advanced"), -40);
|
||
|
|
});
|
||
|
|
});
|
||
|
|
|
||
|
|
describe("defaultRiskTolerance", () => {
|
||
|
|
it("returns 'moderate' for beginner", () => {
|
||
|
|
assert.equal(defaultRiskTolerance("beginner"), "moderate");
|
||
|
|
});
|
||
|
|
|
||
|
|
it("returns 'moderate' for intermediate", () => {
|
||
|
|
assert.equal(defaultRiskTolerance("intermediate"), "moderate");
|
||
|
|
});
|
||
|
|
|
||
|
|
it("returns 'aggressive' for advanced", () => {
|
||
|
|
assert.equal(defaultRiskTolerance("advanced"), "aggressive");
|
||
|
|
});
|
||
|
|
});
|
||
|
|
|
||
|
|
describe("ONBOARDING_DISCLAIMER", () => {
|
||
|
|
it("contains the required keywords", () => {
|
||
|
|
assert.ok(
|
||
|
|
ONBOARDING_DISCLAIMER.toLowerCase().includes("educational"),
|
||
|
|
"missing 'educational'",
|
||
|
|
);
|
||
|
|
assert.ok(
|
||
|
|
ONBOARDING_DISCLAIMER.toLowerCase().includes("not financial advice"),
|
||
|
|
"missing 'not financial advice'",
|
||
|
|
);
|
||
|
|
});
|
||
|
|
});
|
||
|
|
});
|