forked from phenom/healer-man
Guard source gear namespaces and retain recoverable legacy records (#9)
This commit is contained in:
1 parent
ab37006932
commit
e567910c04
23 files changed
+1203
-66
No files matched your search
@@ -1,5 +1,5 @@
|
||||
import { describe, expect, it } from "vitest";
|
||||
import type { ClassId } from "../app/characterCatalog";
|
||||
import { contentCategoryForClass, type ClassId } from "../app/characterCatalog";
|
||||
import { classCanEquipItem, equipmentSlotForItem } from "./equipment";
|
||||
import {
|
||||
compareEquipmentUpgrade,
|
||||
@@ -7,6 +7,7 @@ import {
|
||||
resolvedAverageItemLevel,
|
||||
resolvedEquipmentItems,
|
||||
resolvedEquipmentLoadout,
|
||||
resolvedEquipmentStats,
|
||||
type HeirloomContext,
|
||||
} from "./heirloomEquipment";
|
||||
import { EMPTY_ITEM_STATS, itemStatsFor } from "./itemStats";
|
||||
@@ -33,8 +34,14 @@ function context(profile: SpecializationDefinition, level: number, ownerKind: "p
|
||||
};
|
||||
}
|
||||
|
||||
function catalogItem(template: LootCatalogItem, itemLevel: number, suffix = "test"): InventoryItem {
|
||||
function catalogItem(
|
||||
template: LootCatalogItem,
|
||||
itemLevel: number,
|
||||
suffix = "test",
|
||||
overrides: Partial<InventoryItem> = {},
|
||||
): InventoryItem {
|
||||
return {
|
||||
contentCategory: "wow",
|
||||
instanceId: `${template.itemId}:${itemLevel}:${suffix}`,
|
||||
itemId: template.itemId,
|
||||
itemKey: template.itemKey,
|
||||
@@ -50,6 +57,7 @@ function catalogItem(template: LootCatalogItem, itemLevel: number, suffix = "tes
|
||||
sourceBossKey: "test-boss",
|
||||
sourceBossName: "Test Boss",
|
||||
acquiredAt: 1,
|
||||
...overrides,
|
||||
};
|
||||
}
|
||||
|
||||
@@ -77,6 +85,59 @@ describe("specialization-aware heirlooms", () => {
|
||||
expect(loadout["off-hand"]?.armorType).toBe("shield");
|
||||
});
|
||||
|
||||
it("keeps RoM training defaults when foreign, unresolved, or non-native assigned items are present", () => {
|
||||
const romContext: HeirloomContext = {
|
||||
ownerId: "rom-owner",
|
||||
ownerKind: "player",
|
||||
classId: "rom-priest",
|
||||
specializationId: null,
|
||||
role: "healer",
|
||||
level: 40,
|
||||
};
|
||||
const chestTemplate = templates.find((template) => template.inventorySlot === "chest" && template.armorType === "cloth")!;
|
||||
const training = resolvedEquipmentLoadout({}, [], romContext).chest!;
|
||||
expect(training).toMatchObject({
|
||||
contentCategory: "rom",
|
||||
quality: "heirloom",
|
||||
sourceBossKey: "heirloom",
|
||||
sourceBossName: "Training Armory",
|
||||
});
|
||||
expect(training.stats.romNative).toBeDefined();
|
||||
|
||||
const trainingSlotWithoutReference = resolvedEquipmentLoadout({}, [], romContext)["off-hand"]!;
|
||||
expect(trainingSlotWithoutReference.stats.romNative).toBeUndefined();
|
||||
expect(equipmentStatsForItems([trainingSlotWithoutReference]).romNative).toBeDefined();
|
||||
const copiedTraining = JSON.parse(JSON.stringify(trainingSlotWithoutReference)) as InventoryItem;
|
||||
expect(copiedTraining).toMatchObject({
|
||||
contentCategory: "rom",
|
||||
instanceId: trainingSlotWithoutReference.instanceId,
|
||||
sourceBossName: "Training Armory",
|
||||
});
|
||||
expect(equipmentStatsForItems([copiedTraining]).romNative).toBeUndefined();
|
||||
expect(classCanEquipItem("rom-priest", copiedTraining)).toBe(false);
|
||||
|
||||
const badAssignedItems = [
|
||||
catalogItem(chestTemplate, 40, "foreign-wow"),
|
||||
catalogItem(chestTemplate, 40, "unresolved", { contentCategory: null }),
|
||||
catalogItem(chestTemplate, 40, "rom-without-native", { contentCategory: "rom" }),
|
||||
];
|
||||
for (const item of badAssignedItems) {
|
||||
expect(classCanEquipItem("rom-priest", item)).toBe(false);
|
||||
const loadout = resolvedEquipmentLoadout({ [romContext.ownerId]: { chest: item.instanceId } }, [item], romContext);
|
||||
expect(loadout.chest).toMatchObject({ sourceBossName: "Training Armory", contentCategory: "rom" });
|
||||
expect(resolvedEquipmentStats({ [romContext.ownerId]: { chest: item.instanceId } }, [item], romContext))
|
||||
.toEqual(resolvedEquipmentStats({}, [], romContext));
|
||||
}
|
||||
|
||||
const nativeItem = catalogItem(chestTemplate, 40, "rom-native", {
|
||||
contentCategory: "rom",
|
||||
stats: itemStatsFor({ ...chestTemplate, itemLevel: 40, romNative: { stamina: 3 } }),
|
||||
});
|
||||
expect(classCanEquipItem("rom-priest", nativeItem)).toBe(true);
|
||||
expect(resolvedEquipmentLoadout({ [romContext.ownerId]: { chest: nativeItem.instanceId } }, [nativeItem], romContext).chest)
|
||||
.toBe(nativeItem);
|
||||
});
|
||||
|
||||
it("allocates only useful archetype stats", () => {
|
||||
const protection = SPECIALIZATION_DEFINITIONS.find((definition) => definition.id === "warrior:protection")!;
|
||||
const holy = SPECIALIZATION_DEFINITIONS.find((definition) => definition.id === "priest:holy")!;
|
||||
@@ -118,10 +179,10 @@ describe("specialization-aware heirlooms", () => {
|
||||
}
|
||||
});
|
||||
|
||||
it("opens a real item-level-85 upgrade path for every gear profile at level 80", () => {
|
||||
it("opens an item-level-85 catalog upgrade path for every WoW gear profile at level 80", () => {
|
||||
expect(scaledLootItemLevel(79)).toBe(79);
|
||||
expect(scaledLootItemLevel(80)).toBe(85);
|
||||
for (const profile of SPECIALIZATION_DEFINITIONS) {
|
||||
for (const profile of SPECIALIZATION_DEFINITIONS.filter((candidate) => contentCategoryForClass(candidate.classId) === "wow")) {
|
||||
const loadout = resolvedEquipmentLoadout({}, [], context(profile, 80));
|
||||
const upgrades = compatibleItems(profile.classId, 85)
|
||||
.filter((item) => compareEquipmentUpgrade(item, loadout, profile, context(profile, 80)).isUpgrade);
|
||||
|
||||
Reference in new issue
Block a user