refactor!: simplify query and session ownership
Use Query cancellation and native mutation results instead of HTTP registries, access epochs and copied scope state. Keep local auth ordering and mutation identity fences. Allow staged generated files to remain excluded from ESLint. Backend contract: WealthLedger/backend@d698ed9 BREAKING CHANGE: drop investment stateVersion/progress/resources from the client contract and use data/metadata readiness instead of rewritten query status. Cross-tab auth may require re-login.
This commit is contained in:
@@ -44,71 +44,6 @@ function summary(currency: string, coupon: string, dividend: string) {
|
||||
};
|
||||
}
|
||||
|
||||
describe("income membership validation", () => {
|
||||
const entry: IncomeAnalytics["entries"][number] = {
|
||||
accruedInterest: null,
|
||||
category: "income",
|
||||
commission: null,
|
||||
description: "Купон",
|
||||
figi: "FIGI",
|
||||
id: "coupon-1",
|
||||
instrumentKey: "income-group",
|
||||
instrumentType: "bond",
|
||||
instrumentUid: null,
|
||||
logoName: null,
|
||||
occurredAt: "2026-08-01T12:00:00Z",
|
||||
payment: money("RUB", "10"),
|
||||
price: null,
|
||||
quantity: null,
|
||||
ticker: "BOND",
|
||||
type: "OPERATION_TYPE_COUPON",
|
||||
};
|
||||
|
||||
const instrument: IncomeAnalytics["instruments"][number] = {
|
||||
...summary("RUB", "10", "0"),
|
||||
displayName: "BOND",
|
||||
figi: "FIGI",
|
||||
instrumentType: "bond",
|
||||
instrumentUid: null,
|
||||
key: entry.instrumentKey,
|
||||
receiptCount: 1,
|
||||
ticker: "BOND",
|
||||
};
|
||||
|
||||
const valid: IncomeAnalytics = {
|
||||
...analytics,
|
||||
entries: [entry],
|
||||
instruments: [instrument],
|
||||
totalsByCurrency: [summary("RUB", "10", "0")],
|
||||
};
|
||||
|
||||
it.each([
|
||||
["missing key", undefined],
|
||||
["empty key", ""],
|
||||
["whitespace key", " "],
|
||||
["non-string key", 12],
|
||||
["unknown key", "not-in-breakdown"],
|
||||
])("rejects an entry with %s", (_name, instrumentKey) => {
|
||||
// Deliberately malformed API data exercises the runtime validation boundary.
|
||||
const response = {
|
||||
...valid,
|
||||
entries: [{ ...entry, instrumentKey }],
|
||||
} as unknown as IncomeAnalytics;
|
||||
|
||||
expect(toIncomeDisplayModel(response)).toBeNull();
|
||||
});
|
||||
|
||||
it.each([
|
||||
["duplicate instrument keys", { instruments: [instrument, instrument] }],
|
||||
["currency mismatch", { entries: [{ ...entry, payment: money("USD", "10") }] }],
|
||||
["receipt count mismatch", { instruments: [{ ...instrument, receiptCount: 2 }] }],
|
||||
["missing entries", { entries: [] }],
|
||||
["empty instrument key", { instruments: [{ ...instrument, key: "" }] }],
|
||||
])("rejects %s", (_name, invalid) => {
|
||||
expect(toIncomeDisplayModel({ ...valid, ...invalid })).toBeNull();
|
||||
});
|
||||
});
|
||||
|
||||
describe("income comparison display", () => {
|
||||
it.each([
|
||||
["25", "100", "+25 %"],
|
||||
|
||||
Reference in New Issue
Block a user