95 lines
3.1 KiB
TypeScript
95 lines
3.1 KiB
TypeScript
import { describe, expect, it } from "vitest";
|
|
|
|
import type { BrokerageOperation } from "../api/useBrokerageOperations";
|
|
|
|
import { brokerageOperationGroupKey, operationLabelKey } from "./display";
|
|
|
|
it.each([
|
|
["OPERATION_TYPE_BUY", "buy"],
|
|
["OPERATION_TYPE_COUPON", "other"],
|
|
["OPERATION_TYPE_BUY_CARD", "buy"],
|
|
["OPERATION_TYPE_BUY_MARGIN", "buy"],
|
|
["OPERATION_TYPE_SELL", "sell"],
|
|
["OPERATION_TYPE_SELL_CARD", "sell"],
|
|
["OPERATION_TYPE_SELL_MARGIN", "sell"],
|
|
["OPERATION_TYPE_DIV_EXT", "dividend"],
|
|
["OPERATION_TYPE_DIVIDEND", "dividend"],
|
|
["OPERATION_TYPE_DIVIDEND_TRANSFER", "dividend"],
|
|
["OPERATION_TYPE_INPUT_SECURITIES", "input"],
|
|
["OPERATION_TYPE_OUTPUT_SECURITIES", "output"],
|
|
["OPERATION_TYPE_FUTURE_TAX", "tax"],
|
|
["OPERATION_TYPE_FUTURE_FEE", "fee"],
|
|
["OPERATION_TYPE_TRANS_FUTURE", "transfer"],
|
|
["FUTURE_UNKNOWN_OPERATION", "other"],
|
|
])("preserves the wire operation label for %s", (type, label) => {
|
|
expect(operationLabelKey(type)).toBe(`ledger.operationType.${label}`);
|
|
});
|
|
|
|
describe("brokerageOperationGroupKey", () => {
|
|
const base: BrokerageOperation = {
|
|
account: { id: "account-1", name: "Брокерский" },
|
|
accruedInterest: null,
|
|
category: "income",
|
|
commission: null,
|
|
description: "Купон",
|
|
figi: "FIGI",
|
|
id: "operation",
|
|
instrumentType: "bond",
|
|
instrumentUid: "UID",
|
|
logoName: null,
|
|
occurredAt: "2026-08-14T10:00:00Z",
|
|
payment: null,
|
|
price: null,
|
|
quantity: null,
|
|
ticker: "BOND",
|
|
type: "OPERATION_TYPE_COUPON",
|
|
};
|
|
|
|
it("uses screen day, preferred identity and exact type, not account", () => {
|
|
const first = brokerageOperationGroupKey(base);
|
|
|
|
const same = brokerageOperationGroupKey({
|
|
...base,
|
|
account: { id: "account-2", name: "ИИС" },
|
|
figi: "OTHER-FIGI",
|
|
occurredAt: "2026-08-14T11:00:00Z",
|
|
});
|
|
|
|
expect(same).toBe(first);
|
|
expect(brokerageOperationGroupKey({
|
|
...base,
|
|
type: "OPERATION_TYPE_DIVIDEND",
|
|
})).not.toBe(first);
|
|
});
|
|
|
|
it("keeps buy and sell of one instrument in different groups", () => {
|
|
expect(brokerageOperationGroupKey({ ...base, type: "OPERATION_TYPE_BUY" }))
|
|
.not.toBe(brokerageOperationGroupKey({
|
|
...base,
|
|
type: "OPERATION_TYPE_SELL",
|
|
}));
|
|
});
|
|
|
|
it("separates local midnight and joins one local day across UTC dates", () => {
|
|
const before = new Date(2026, 7, 14, 23, 59).toISOString();
|
|
const after = new Date(2026, 7, 15, 0, 1).toISOString();
|
|
const morning = new Date(2026, 7, 14, 1).toISOString();
|
|
const evening = new Date(2026, 7, 14, 23).toISOString();
|
|
|
|
expect(brokerageOperationGroupKey({ ...base, occurredAt: before }))
|
|
.not.toBe(brokerageOperationGroupKey({ ...base, occurredAt: after }));
|
|
expect(brokerageOperationGroupKey({ ...base, occurredAt: morning }))
|
|
.toBe(brokerageOperationGroupKey({ ...base, occurredAt: evening }));
|
|
});
|
|
|
|
it("falls back to FIGI and leaves missing identity ungrouped", () => {
|
|
expect(brokerageOperationGroupKey({ ...base, instrumentUid: null }))
|
|
.toBe(brokerageOperationGroupKey({ ...base, instrumentUid: "" }));
|
|
expect(brokerageOperationGroupKey({
|
|
...base,
|
|
figi: null,
|
|
instrumentUid: null,
|
|
})).toBeNull();
|
|
});
|
|
});
|