84 lines
4.6 KiB
TypeScript
84 lines
4.6 KiB
TypeScript
import { describe, expect, it } from "vitest";
|
|
|
|
import { rankAnalyticsItems, selectAnalytics, type AnalyticsItem, type PublicAnalytics } from "./model";
|
|
|
|
const item = (key: string, guideCount: number, stygianCount: number, name = key): AnalyticsItem => ({
|
|
key, name, imageUrl: null, rarity: null, guideCount, stygianCount,
|
|
contributions: [{ guideId: "g0", teamSignature: "guide-team", count: guideCount }, { guideId: "s0", teamSignature: "stygian-team", count: stygianCount }],
|
|
});
|
|
|
|
describe("analytics source selection", () => {
|
|
it("merges sources, changes order, and removes Stygian-only items when excluded", () => {
|
|
const items = [item("shared", 2, 5), item("guide", 4, 0), item("stygian", 0, 3)];
|
|
expect(rankAnalyticsItems(items, true).map(({ key, count }) => [key, count])).toEqual([
|
|
["shared", 7], ["guide", 4], ["stygian", 3],
|
|
]);
|
|
expect(rankAnalyticsItems(items, false).map(({ key, count }) => [key, count])).toEqual([
|
|
["guide", 4], ["shared", 2],
|
|
]);
|
|
expect(items[0].guideCount).toBe(2);
|
|
});
|
|
|
|
it("breaks ties by name and then key", () => {
|
|
expect(rankAnalyticsItems([item("z", 1, 0, "Alpha"), item("b", 1, 0, "Beta"), item("a", 1, 0, "Alpha")], true)
|
|
.map(({ key }) => key)).toEqual(["a", "z", "b"]);
|
|
});
|
|
|
|
it("updates every ranking and summary and handles empty sources", () => {
|
|
const entries = [item("shared", 2, 1), item("stygian", 0, 1)];
|
|
const data: PublicAnalytics = {
|
|
guides: [
|
|
...Array.from({ length: 5 }, (_, index) => ({ id: `g${index}`, source: "guide" as const, name: `Guide ${index}` })),
|
|
...Array.from({ length: 3 }, (_, index) => ({ id: `s${index}`, source: "stygian" as const, name: `Stygian ${index}` })),
|
|
],
|
|
teamGroups: [{ guideId: "g0", signature: "guide-team", count: 6 }, { guideId: "s0", signature: "stygian-team", count: 9 }],
|
|
guideCount: 5, stygianScheduleCount: 3, guideTeamCount: 6, stygianTeamCount: 9,
|
|
team: { character: entries, weapon: entries, artifact: entries },
|
|
recommendation: { weapon: entries, artifact: entries },
|
|
};
|
|
const included = selectAnalytics(data, true);
|
|
const excluded = selectAnalytics(data, false);
|
|
expect(included.teamCount).toBe(15);
|
|
expect(excluded.teamCount).toBe(6);
|
|
expect(excluded.stygianScheduleCount).toBe(0);
|
|
expect(excluded.guideCount).toBe(5);
|
|
for (const list of [...Object.values(excluded.team), ...Object.values(excluded.recommendation)]) {
|
|
expect(list.map(({ key, count }) => [key, count])).toEqual([["shared", 2]]);
|
|
}
|
|
expect(rankAnalyticsItems([], true)).toEqual([]);
|
|
expect(rankAnalyticsItems([item("unused", 0, 0)], false)).toEqual([]);
|
|
});
|
|
|
|
it("excludes guides before deduplicating and preserves per-member equipment counts", () => {
|
|
const entry: AnalyticsItem = {
|
|
...item("weapon", 7, 2),
|
|
contributions: [
|
|
{ guideId: "g1", teamSignature: "shared", count: 4 },
|
|
{ guideId: "g2", teamSignature: "shared", count: 2 },
|
|
{ guideId: "g2", teamSignature: "different-build", count: 1 },
|
|
{ guideId: "s1", teamSignature: "shared", count: 2 },
|
|
],
|
|
};
|
|
const recommendation = { ...entry, contributions: [{ guideId: "g1", teamSignature: null, count: 3 }, { guideId: "g2", teamSignature: null, count: 4 }] };
|
|
const data: PublicAnalytics = {
|
|
guides: [{ id: "g1", source: "guide", name: "One" }, { id: "g2", source: "guide", name: "Two" }, { id: "s1", source: "stygian", name: "Stygian" }],
|
|
teamGroups: [{ guideId: "g1", signature: "shared", count: 2 }, { guideId: "g2", signature: "shared", count: 1 }, { guideId: "g2", signature: "different-build", count: 1 }, { guideId: "s1", signature: "shared", count: 1 }],
|
|
guideCount: 2, stygianScheduleCount: 1, guideTeamCount: 4, stygianTeamCount: 1,
|
|
team: { character: [], weapon: [entry], artifact: [] }, recommendation: { weapon: [recommendation], artifact: [] },
|
|
};
|
|
expect(selectAnalytics(data, true).team.weapon[0].count).toBe(9);
|
|
const unique = selectAnalytics(data, true, new Set(), true);
|
|
expect(unique.teamCount).toBe(2);
|
|
expect(unique.team.weapon[0].count).toBe(3);
|
|
expect(unique.recommendation.weapon[0].count).toBe(7);
|
|
const excluded = selectAnalytics(data, true, new Set(["g1"]), true);
|
|
expect(excluded.guideCount).toBe(1);
|
|
expect(excluded.team.weapon[0].count).toBe(3);
|
|
expect(excluded.recommendation.weapon[0].count).toBe(4);
|
|
expect(selectAnalytics(data, true, new Set(["g1", "g2"]), true).team.weapon[0].count).toBe(2);
|
|
const empty = selectAnalytics(data, false, new Set(["g1", "g2"]), true);
|
|
expect(empty.teamCount).toBe(0);
|
|
expect(empty.team.weapon).toEqual([]);
|
|
});
|
|
});
|