97 lines
3.6 KiB
JavaScript
97 lines
3.6 KiB
JavaScript
import { expect, test } from "vitest";
|
|
import { createDashboardModel } from "./createDashboardModel.js";
|
|
|
|
test("uses lucky gift pool breakdown to aggregate business metrics", () => {
|
|
const model = createDashboardModel({
|
|
lucky_gift_pools: [
|
|
{ payout_coin: 300, pool_id: "lucky_100", turnover_coin: 1_000 },
|
|
{ payout_coin: 50, pool_id: "super_lucky", turnover_coin: 500 }
|
|
],
|
|
lucky_gift_payout: 1,
|
|
lucky_gift_profit: 1,
|
|
lucky_gift_turnover: 1
|
|
}, { appCode: "lalu", countryId: 0, range: { end: "2026-06-04", start: "2026-06-04" } });
|
|
|
|
expect(model.luckyGiftPools).toEqual([
|
|
expect.objectContaining({ payout: 300, pool_id: "lucky_100", profit: 700, turnover: 1_000 }),
|
|
expect.objectContaining({ payout: 50, pool_id: "super_lucky", profit: 450, turnover: 500 })
|
|
]);
|
|
expect(metricValue(model, "幸运礼物流水")).toBe("1,500");
|
|
expect(metricValue(model, "幸运礼物返奖")).toBe("350");
|
|
expect(metricValue(model, "幸运礼物利润")).toBe("1,150");
|
|
expect(model.businessKpis.filter((item) => item.detailKey === "luckyGiftPools")).toHaveLength(3);
|
|
});
|
|
|
|
test("includes coin seller stock recharge in USD total and keeps seller transfer as coin metric", () => {
|
|
const model = createDashboardModel({
|
|
coin_seller_recharge_usd_minor: 200,
|
|
coin_seller_transfer_coin: 160_000,
|
|
country_breakdown: [
|
|
{
|
|
coin_seller_recharge_usd_minor: 200,
|
|
coin_seller_transfer_coin: 160_000,
|
|
country: "阿富汗",
|
|
google_recharge_usd_minor: 150,
|
|
recharge_usd_minor: 150
|
|
}
|
|
],
|
|
daily_series: [
|
|
{
|
|
coin_seller: 200,
|
|
google: 150,
|
|
label: "当前",
|
|
recharge_usd_minor: 150
|
|
}
|
|
],
|
|
google_recharge_usd_minor: 150,
|
|
recharge_usd_minor: 150
|
|
}, { appCode: "lalu", countryId: 0, range: { end: "2026-06-04", start: "2026-06-04" } });
|
|
|
|
expect(metricValue(model, "总充值")).toBe("$4");
|
|
expect(metricValue(model, "币商转账金币")).toBe("160,000");
|
|
expect(model.revenueSeries[0]).toEqual(expect.objectContaining({ coin_seller: 200, google: 150, lineTotal: 350, total: 350 }));
|
|
expect(model.countryBreakdown[0]).toEqual(expect.objectContaining({ coin_seller_transfer_coin: 160_000, recharge_usd_minor: 350 }));
|
|
});
|
|
|
|
test("exposes new user KPI and removes visitor stage from funnel", () => {
|
|
const model = createDashboardModel({
|
|
active_users: 80,
|
|
new_users: 12,
|
|
new_users_delta_rate: 0.24,
|
|
paid_users: 8,
|
|
recharge_users: 7
|
|
}, { appCode: "lalu", countryId: 0, range: { end: "2026-06-04", start: "2026-06-04" } });
|
|
|
|
expect(metricValue(model, "新增用户数")).toBe("12");
|
|
expect(model.kpis.map((item) => item.label)).toContain("新增用户数");
|
|
expect(model.funnel.map((item) => item.name)).toEqual(["活跃用户", "付费用户", "充值用户"]);
|
|
});
|
|
|
|
test("uses active users as payer and recharge conversion denominator", () => {
|
|
const model = createDashboardModel({
|
|
active_users: 80,
|
|
country_breakdown: [
|
|
{
|
|
active_users: 20,
|
|
country: "巴西",
|
|
paid_users: 8,
|
|
recharge_users: 6,
|
|
recharge_usd_minor: 500
|
|
}
|
|
],
|
|
new_users: 4,
|
|
paid_users: 8,
|
|
recharge_users: 6
|
|
}, { appCode: "lalu", countryId: 0, range: { end: "2026-06-04", start: "2026-06-04" } });
|
|
|
|
expect(model.sideMetrics.find((item) => item.label === "付费转化率")?.value).toBe("10.00%");
|
|
expect(model.countryBreakdown[0]).toEqual(expect.objectContaining({
|
|
payer_rate: 0.4,
|
|
recharge_conversion_rate: 0.3
|
|
}));
|
|
});
|
|
|
|
function metricValue(model, label) {
|
|
return [...model.kpis, ...model.businessKpis].find((item) => item.label === label)?.value;
|
|
}
|