mirror of
https://github.com/Kvan7/Exiled-Exchange-2.git
synced 2026-10-11 21:51:36 +00:00
524 lines
15 KiB
TypeScript
524 lines
15 KiB
TypeScript
import { init } from "@/assets/data";
|
|
import { ItemCategory } from "@/parser";
|
|
import { ParsedModifier } from "@/parser/advanced-mod-desc";
|
|
import { ModifierType, StatCalculated } from "@/parser/modifiers";
|
|
import { __testExports } from "@/parser/Parser";
|
|
import { createTestItem, makeCalcStat } from "@specs/helper";
|
|
import { setupTests } from "@specs/vitest.setup";
|
|
import { beforeEach, describe, expect, it } from "vitest";
|
|
|
|
describe("determineAugments", () => {
|
|
beforeEach(async () => {
|
|
setupTests();
|
|
await init("en");
|
|
});
|
|
|
|
it("should return correct baseTypes", () => {
|
|
const expectedRef = ["Greater Iron Rune", "Greater Iron Rune"];
|
|
|
|
const result = __testExports.determineAugments(
|
|
{
|
|
info: {
|
|
type: ModifierType.Augment,
|
|
},
|
|
} as unknown as ParsedModifier,
|
|
[makeCalcStat("#% increased Physical Damage", 36, ModifierType.Augment)],
|
|
);
|
|
|
|
expect(result.map((augment) => augment.refName)).toEqual(expectedRef);
|
|
});
|
|
|
|
it("Works for one item", () => {
|
|
const expectedRef = ["Lesser Storm Rune"];
|
|
|
|
const result = __testExports.determineAugments(
|
|
{
|
|
info: {
|
|
type: ModifierType.Augment,
|
|
},
|
|
} as unknown as ParsedModifier,
|
|
[makeCalcStat("#% to Lightning Resistance", 10, ModifierType.Augment)],
|
|
);
|
|
|
|
expect(result.map((augment) => augment.refName)).toEqual(expectedRef);
|
|
});
|
|
|
|
it("handles range mods correctly", () => {
|
|
const mod = {
|
|
info: {
|
|
type: "rune",
|
|
tags: [],
|
|
},
|
|
stats: [
|
|
{
|
|
stat: {
|
|
ref: "Adds # to # Lightning Damage",
|
|
better: 1,
|
|
matchers: [
|
|
{
|
|
string: "Adds # to # Lightning Damage",
|
|
},
|
|
],
|
|
trade: {
|
|
ids: {
|
|
explicit: ["explicit.stat_3336890334"],
|
|
fractured: ["fractured.stat_3336890334"],
|
|
enchant: ["enchant.stat_3336890334"],
|
|
rune: ["rune.stat_3336890334"],
|
|
desecrated: ["desecrated.stat_3336890334"],
|
|
crafted: ["crafted.stat_3336890334"],
|
|
},
|
|
},
|
|
id: "local_minimum_added_lightning_damage",
|
|
},
|
|
translation: {
|
|
string: "Adds # to # Lightning Damage",
|
|
},
|
|
roll: {
|
|
unscalable: false,
|
|
dp: false,
|
|
value: 15.5,
|
|
min: 15.5,
|
|
max: 15.5,
|
|
},
|
|
},
|
|
],
|
|
} as unknown as ParsedModifier;
|
|
|
|
const statCalcs = [
|
|
{
|
|
stat: {
|
|
ref: "Adds # to # Lightning Damage",
|
|
better: 1,
|
|
matchers: [
|
|
{
|
|
string: "Adds # to # Lightning Damage",
|
|
},
|
|
],
|
|
trade: {
|
|
ids: {
|
|
explicit: ["explicit.stat_3336890334"],
|
|
fractured: ["fractured.stat_3336890334"],
|
|
enchant: ["enchant.stat_3336890334"],
|
|
rune: ["rune.stat_3336890334"],
|
|
desecrated: ["desecrated.stat_3336890334"],
|
|
crafted: ["crafted.stat_3336890334"],
|
|
},
|
|
},
|
|
id: "local_minimum_added_lightning_damage",
|
|
},
|
|
type: "rune",
|
|
sources: [
|
|
{
|
|
modifier: {
|
|
info: {
|
|
type: "rune",
|
|
tags: [],
|
|
},
|
|
stats: [
|
|
{
|
|
stat: {
|
|
ref: "Adds # to # Lightning Damage",
|
|
better: 1,
|
|
matchers: [
|
|
{
|
|
string: "Adds # to # Lightning Damage",
|
|
},
|
|
],
|
|
trade: {
|
|
ids: {
|
|
explicit: ["explicit.stat_3336890334"],
|
|
fractured: ["fractured.stat_3336890334"],
|
|
enchant: ["enchant.stat_3336890334"],
|
|
rune: ["rune.stat_3336890334"],
|
|
desecrated: ["desecrated.stat_3336890334"],
|
|
crafted: ["crafted.stat_3336890334"],
|
|
},
|
|
},
|
|
id: "local_minimum_added_lightning_damage",
|
|
},
|
|
translation: {
|
|
string: "Adds # to # Lightning Damage",
|
|
},
|
|
roll: {
|
|
unscalable: false,
|
|
dp: false,
|
|
value: 15.5,
|
|
min: 15.5,
|
|
max: 15.5,
|
|
},
|
|
},
|
|
],
|
|
},
|
|
stat: {
|
|
stat: {
|
|
ref: "Adds # to # Lightning Damage",
|
|
better: 1,
|
|
matchers: [
|
|
{
|
|
string: "Adds # to # Lightning Damage",
|
|
},
|
|
],
|
|
trade: {
|
|
ids: {
|
|
explicit: ["explicit.stat_3336890334"],
|
|
fractured: ["fractured.stat_3336890334"],
|
|
enchant: ["enchant.stat_3336890334"],
|
|
rune: ["rune.stat_3336890334"],
|
|
desecrated: ["desecrated.stat_3336890334"],
|
|
crafted: ["crafted.stat_3336890334"],
|
|
},
|
|
},
|
|
id: "local_minimum_added_lightning_damage",
|
|
},
|
|
translation: {
|
|
string: "Adds # to # Lightning Damage",
|
|
},
|
|
roll: {
|
|
unscalable: false,
|
|
dp: false,
|
|
value: 15.5,
|
|
min: 15.5,
|
|
max: 15.5,
|
|
},
|
|
},
|
|
contributes: {
|
|
value: 15.5,
|
|
min: 15.5,
|
|
max: 15.5,
|
|
},
|
|
},
|
|
],
|
|
},
|
|
] as unknown as StatCalculated[];
|
|
const result = __testExports.determineAugments(mod, statCalcs);
|
|
|
|
expect(result).toHaveLength(1);
|
|
expect(result[0].refName).toEqual("Greater Storm Rune");
|
|
});
|
|
|
|
it("works for bonded augments", () => {
|
|
const expectedRef = ["Fox Idol"];
|
|
|
|
const result = __testExports.determineAugments(
|
|
{
|
|
info: {
|
|
type: ModifierType.Augment,
|
|
},
|
|
} as unknown as ParsedModifier,
|
|
[
|
|
makeCalcStat(
|
|
"Idols socketed in this item gain the benefits of their Bonded modifiers",
|
|
1,
|
|
ModifierType.Augment,
|
|
),
|
|
],
|
|
);
|
|
expect(result.map((augment) => augment.refName)).toEqual(expectedRef);
|
|
});
|
|
});
|
|
|
|
describe("BFS", () => {
|
|
beforeEach(async () => {
|
|
setupTests();
|
|
await init("en");
|
|
});
|
|
|
|
it("should return valid combination", () => {
|
|
const result = __testExports.modifiedBfs(36, [], [14, 16, 18, 20]);
|
|
|
|
expect(result).toEqual([18, 18]);
|
|
});
|
|
|
|
it.each([
|
|
[40, [14, 16, 18, 20], [20, 20]],
|
|
[20, [14, 16, 18, 20], [20]],
|
|
[19, [14, 16, 18, 20], null],
|
|
[15, [5, 7.5, 10], [7.5, 7.5]],
|
|
[34, [14, 16, 18], [18, 16]],
|
|
[10, [10], [10]],
|
|
[10, [], null],
|
|
[40, [10, 20, 30], [20, 20]],
|
|
])(
|
|
"%#. should return valid combination for %o and %o",
|
|
(target, options, expected) => {
|
|
const result = __testExports.modifiedBfs(target, [], options);
|
|
|
|
expect(result).toEqual(expected);
|
|
},
|
|
);
|
|
|
|
it("should not infinite loop", () => {
|
|
const result = __testExports.modifiedBfs(100, [], Array(100).fill(0));
|
|
|
|
expect(result).toHaveLength(0);
|
|
}, 50);
|
|
|
|
it("should not infinite loop2", () => {
|
|
const result = __testExports.modifiedBfs(15.5, [], Array(4).fill(1));
|
|
|
|
expect(result).toHaveLength(0);
|
|
}, 50);
|
|
});
|
|
|
|
describe("parseAugmentSockets", () => {
|
|
beforeEach(async () => {
|
|
setupTests();
|
|
await init("en");
|
|
});
|
|
|
|
it("should skip for items without sockets", () => {
|
|
const item = createTestItem();
|
|
|
|
const result = __testExports.parseAugmentSockets([], item);
|
|
expect(result).toEqual("PARSER_SKIPPED");
|
|
});
|
|
|
|
it.each([
|
|
[["Sockets: S"], 1],
|
|
[["Sockets: S S"], 2],
|
|
[["Sockets: S S S"], 3],
|
|
[["Sockets: S S S S"], 4],
|
|
[["Sockets: S S S S S"], 5],
|
|
])(
|
|
"%#. should add correct augment socket count(%o -> %o)",
|
|
(lines, expected) => {
|
|
const item = createTestItem();
|
|
item.category = ItemCategory.Gloves;
|
|
|
|
const result = __testExports.parseAugmentSockets(lines, item);
|
|
expect(result).toEqual("SECTION_PARSED");
|
|
expect(item.augmentSockets?.normal).toEqual(1);
|
|
expect(item.augmentSockets?.empty).toEqual(0);
|
|
expect(item.augmentSockets?.current).toEqual(expected);
|
|
expect(
|
|
item.augmentSockets?.augments.every((v) => v === null),
|
|
).toBeTruthy();
|
|
expect(item.augmentSockets?.augments.length).toEqual(expected);
|
|
},
|
|
);
|
|
|
|
it("should add sockets on non-socket section", () => {
|
|
const item = createTestItem();
|
|
item.category = ItemCategory.Gloves;
|
|
|
|
const result = __testExports.parseAugmentSockets(["text"], item);
|
|
expect(result).toEqual("SECTION_SKIPPED");
|
|
expect(item.augmentSockets?.normal).toEqual(1);
|
|
expect(item.augmentSockets?.empty).toEqual(1);
|
|
expect(item.augmentSockets?.current).toEqual(0);
|
|
expect(item.augmentSockets?.augments.every((v) => v === null)).toBeTruthy();
|
|
expect(item.augmentSockets?.augments.length).toEqual(1);
|
|
});
|
|
});
|
|
|
|
describe("applyAugmentSockets", () => {
|
|
beforeEach(async () => {
|
|
setupTests();
|
|
await init("en");
|
|
});
|
|
|
|
it("should do nothing on item without sockets", () => {
|
|
const item = createTestItem();
|
|
|
|
__testExports.applyAugmentSockets(item);
|
|
expect(item).toEqual(createTestItem());
|
|
});
|
|
|
|
it("should set empty on item with no augment stats", () => {
|
|
const item = createTestItem();
|
|
item.category = ItemCategory.Gloves;
|
|
item.augmentSockets = {
|
|
empty: 0,
|
|
current: 2,
|
|
normal: 2,
|
|
augments: [null, null],
|
|
};
|
|
|
|
__testExports.applyAugmentSockets(item);
|
|
expect(item.augmentSockets.empty).toEqual(2);
|
|
expect(item.augmentSockets.current).toEqual(2);
|
|
expect(item.augmentSockets.normal).toEqual(2);
|
|
expect(item.augmentSockets.augments.every((v) => v === null)).toBeTruthy();
|
|
});
|
|
|
|
it("should apply correct augment to item", () => {
|
|
const item = createTestItem();
|
|
item.category = ItemCategory.Bow;
|
|
item.augmentSockets = {
|
|
empty: 0,
|
|
current: 2,
|
|
normal: 2,
|
|
augments: [null, null],
|
|
};
|
|
|
|
const stat = makeCalcStat(
|
|
"#% increased Physical Damage",
|
|
18,
|
|
ModifierType.Augment,
|
|
);
|
|
item.statsByType = [stat];
|
|
item.newMods = [
|
|
{
|
|
info: {
|
|
type: ModifierType.Augment,
|
|
tags: [],
|
|
},
|
|
stats: [stat.sources[0].stat],
|
|
},
|
|
];
|
|
|
|
__testExports.applyAugmentSockets(item);
|
|
expect(item.augmentSockets.empty).toEqual(1);
|
|
expect(item.augmentSockets.current).toEqual(2);
|
|
expect(item.augmentSockets.normal).toEqual(2);
|
|
expect(item.augmentSockets.augments[0]?.refName).toEqual(
|
|
"Greater Iron Rune",
|
|
);
|
|
expect(item.augmentSockets.augments[1]).toBeNull();
|
|
});
|
|
|
|
it("should apply multiple different augments to item", () => {
|
|
const item = createTestItem();
|
|
item.category = ItemCategory.Bow;
|
|
item.augmentSockets = {
|
|
empty: 0,
|
|
current: 2,
|
|
normal: 2,
|
|
augments: [null, null],
|
|
};
|
|
|
|
const stat1 = makeCalcStat(
|
|
"#% increased Physical Damage",
|
|
18,
|
|
ModifierType.Augment,
|
|
);
|
|
const stat2 = makeCalcStat(
|
|
"Bow Attacks fire # additional Arrows",
|
|
1,
|
|
ModifierType.Augment,
|
|
);
|
|
item.statsByType = [stat1, stat2];
|
|
item.newMods = [
|
|
{
|
|
info: {
|
|
type: ModifierType.Augment,
|
|
tags: [],
|
|
},
|
|
stats: [stat1.sources[0].stat, stat2.sources[0].stat],
|
|
},
|
|
];
|
|
|
|
__testExports.applyAugmentSockets(item);
|
|
expect(item.augmentSockets.empty).toEqual(0);
|
|
expect(item.augmentSockets.current).toEqual(2);
|
|
expect(item.augmentSockets.normal).toEqual(2);
|
|
expect(
|
|
item.augmentSockets.augments.some(
|
|
(i) => i?.refName === "Greater Iron Rune",
|
|
),
|
|
).toBeTruthy();
|
|
expect(
|
|
item.augmentSockets.augments.some(
|
|
(i) => i?.refName === "Countess Seske's Rune of Archery",
|
|
),
|
|
).toBeTruthy();
|
|
});
|
|
|
|
it("should join multiline augments", () => {
|
|
const item = createTestItem();
|
|
item.category = ItemCategory.Staff;
|
|
item.augmentSockets = {
|
|
empty: 0,
|
|
current: 2,
|
|
normal: 2,
|
|
augments: [null, null],
|
|
};
|
|
|
|
const stat1 = makeCalcStat(
|
|
"Meta Skills gain #% increased Energy",
|
|
40,
|
|
ModifierType.Augment,
|
|
);
|
|
const stat2 = makeCalcStat(
|
|
"#% increased Spirit",
|
|
-25,
|
|
ModifierType.Augment,
|
|
);
|
|
const stat3 = makeCalcStat(
|
|
"#% increased Mana Regeneration Rate",
|
|
20,
|
|
ModifierType.Augment,
|
|
);
|
|
item.statsByType = [stat1, stat2, stat3];
|
|
item.newMods = [
|
|
{
|
|
info: {
|
|
type: ModifierType.Augment,
|
|
tags: [],
|
|
},
|
|
stats: [
|
|
stat1.sources[0].stat,
|
|
stat2.sources[0].stat,
|
|
stat3.sources[0].stat,
|
|
],
|
|
},
|
|
];
|
|
|
|
__testExports.applyAugmentSockets(item);
|
|
expect(item.augmentSockets.empty).toEqual(0);
|
|
expect(item.augmentSockets.current).toEqual(2);
|
|
expect(item.augmentSockets.normal).toEqual(2);
|
|
expect(
|
|
item.augmentSockets.augments.some(
|
|
(i) => i?.refName === "Idol of the Martyr",
|
|
),
|
|
).toBeTruthy();
|
|
expect(
|
|
item.augmentSockets.augments.some(
|
|
(i) => i?.refName === "Lesser Inspiration Rune",
|
|
),
|
|
).toBeTruthy();
|
|
});
|
|
|
|
it("should handle bonded mods", () => {
|
|
const item = createTestItem();
|
|
item.category = ItemCategory.BodyArmour;
|
|
item.augmentSockets = {
|
|
empty: 1,
|
|
current: 1,
|
|
normal: 2,
|
|
augments: [null, null],
|
|
};
|
|
|
|
const Bonded = makeCalcStat(
|
|
"Bonded: #% to Quality of all Skills",
|
|
5,
|
|
ModifierType.Augment,
|
|
);
|
|
const nonBonded = makeCalcStat(
|
|
"Idols socketed in this item gain the benefits of their Bonded modifiers",
|
|
1,
|
|
ModifierType.Augment,
|
|
);
|
|
item.statsByType = [Bonded, nonBonded];
|
|
item.newMods = [
|
|
{
|
|
info: {
|
|
type: ModifierType.Augment,
|
|
tags: [],
|
|
},
|
|
stats: [Bonded.sources[0].stat, nonBonded.sources[0].stat],
|
|
},
|
|
];
|
|
|
|
__testExports.applyAugmentSockets(item);
|
|
expect(item.augmentSockets.empty).toEqual(1);
|
|
expect(item.augmentSockets.current).toEqual(1);
|
|
expect(item.augmentSockets.normal).toEqual(2);
|
|
expect(item.augmentSockets.augments).toHaveLength(2);
|
|
expect(item.augmentSockets.augments[0]?.refName).toBe("Fox Idol");
|
|
expect(item.augmentSockets.augments[1]).toBeNull();
|
|
});
|
|
});
|