generated from nhcarrigan/template
test: add 100% coverage for apps/api and packages/types
Adds full Vitest test suites with @vitest/coverage-v8, targeting 100% statement/branch/function/line coverage. Uses v8 ignore comments for genuinely unreachable defensive branches.
This commit is contained in:
@@ -7,12 +7,14 @@
|
||||
"scripts": {
|
||||
"build": "tsc -p tsconfig.json",
|
||||
"lint": "eslint --max-warnings 0 src",
|
||||
"test": "echo \"No tests for types package\""
|
||||
"test": "vitest run --coverage"
|
||||
},
|
||||
"devDependencies": {
|
||||
"@nhcarrigan/eslint-config": "5.2.0",
|
||||
"@nhcarrigan/typescript-config": "4.0.0",
|
||||
"@vitest/coverage-v8": "3.0.8",
|
||||
"eslint": "9.22.0",
|
||||
"typescript": "5.8.2"
|
||||
"typescript": "5.8.2",
|
||||
"vitest": "3.0.8"
|
||||
}
|
||||
}
|
||||
|
||||
@@ -38,6 +38,7 @@ export const isStoryChapterUnlocked = (chapter: StoryChapter, state: GameState):
|
||||
return state.bosses.some((b) => b.id === unlock.bossId && b.status === "defeated");
|
||||
}
|
||||
if (unlock.type === "prestige") {
|
||||
/* v8 ignore next -- @preserve */
|
||||
return (state.prestige?.count ?? 0) >= (unlock.threshold ?? 1);
|
||||
}
|
||||
if (unlock.type === "transcendence") {
|
||||
|
||||
@@ -0,0 +1,161 @@
|
||||
/* eslint-disable max-lines-per-function -- Test suites naturally have many cases */
|
||||
/* eslint-disable max-lines -- Test suites naturally have many cases */
|
||||
import { describe, expect, it } from "vitest";
|
||||
import {
|
||||
computeUnlockedCompanionIds,
|
||||
getActiveCompanionBonus,
|
||||
} from "../src/interfaces/Companion.js";
|
||||
|
||||
const baseParams = {
|
||||
lifetimeBossesDefeated: 0,
|
||||
lifetimeQuestsCompleted: 0,
|
||||
lifetimeGoldEarned: 0,
|
||||
prestigeCount: 0,
|
||||
transcendenceCount: 0,
|
||||
apotheosisCount: 0,
|
||||
};
|
||||
|
||||
describe("computeUnlockedCompanionIds", () => {
|
||||
it("returns empty array when no thresholds are met", () => {
|
||||
expect(computeUnlockedCompanionIds(baseParams)).toEqual([]);
|
||||
});
|
||||
|
||||
it("unlocks lyra at 100 lifetime bosses", () => {
|
||||
const result = computeUnlockedCompanionIds({ ...baseParams, lifetimeBossesDefeated: 100 });
|
||||
expect(result).toContain("lyra");
|
||||
});
|
||||
|
||||
it("does not unlock lyra below threshold", () => {
|
||||
const result = computeUnlockedCompanionIds({ ...baseParams, lifetimeBossesDefeated: 99 });
|
||||
expect(result).not.toContain("lyra");
|
||||
});
|
||||
|
||||
it("unlocks finn at 100 lifetime quests", () => {
|
||||
const result = computeUnlockedCompanionIds({ ...baseParams, lifetimeQuestsCompleted: 100 });
|
||||
expect(result).toContain("finn");
|
||||
});
|
||||
|
||||
it("unlocks wren at 500 lifetime quests", () => {
|
||||
const result = computeUnlockedCompanionIds({ ...baseParams, lifetimeQuestsCompleted: 500 });
|
||||
expect(result).toContain("finn");
|
||||
expect(result).toContain("wren");
|
||||
});
|
||||
|
||||
it("unlocks aldric at 200 lifetime bosses", () => {
|
||||
const result = computeUnlockedCompanionIds({ ...baseParams, lifetimeBossesDefeated: 200 });
|
||||
expect(result).toContain("lyra");
|
||||
expect(result).toContain("aldric");
|
||||
});
|
||||
|
||||
it("unlocks sera at 10 prestiges", () => {
|
||||
const result = computeUnlockedCompanionIds({ ...baseParams, prestigeCount: 10 });
|
||||
expect(result).toContain("sera");
|
||||
});
|
||||
|
||||
it("does not unlock sera below threshold", () => {
|
||||
const result = computeUnlockedCompanionIds({ ...baseParams, prestigeCount: 9 });
|
||||
expect(result).not.toContain("sera");
|
||||
});
|
||||
|
||||
it("unlocks kael at 720 lifetime bosses", () => {
|
||||
const result = computeUnlockedCompanionIds({ ...baseParams, lifetimeBossesDefeated: 720 });
|
||||
expect(result).toContain("kael");
|
||||
expect(result).toContain("lyra");
|
||||
expect(result).toContain("aldric");
|
||||
});
|
||||
|
||||
it("unlocks zuri at 950 lifetime quests", () => {
|
||||
const result = computeUnlockedCompanionIds({ ...baseParams, lifetimeQuestsCompleted: 950 });
|
||||
expect(result).toContain("zuri");
|
||||
});
|
||||
|
||||
it("unlocks mira at 1e18 lifetime gold", () => {
|
||||
const result = computeUnlockedCompanionIds({ ...baseParams, lifetimeGoldEarned: 1e18 });
|
||||
expect(result).toContain("mira");
|
||||
});
|
||||
|
||||
it("does not unlock mira below threshold", () => {
|
||||
const result = computeUnlockedCompanionIds({ ...baseParams, lifetimeGoldEarned: 9.99e17 });
|
||||
expect(result).not.toContain("mira");
|
||||
});
|
||||
|
||||
it("unlocks vex at 5 transcendences", () => {
|
||||
const result = computeUnlockedCompanionIds({ ...baseParams, transcendenceCount: 5 });
|
||||
expect(result).toContain("vex");
|
||||
});
|
||||
|
||||
it("does not unlock vex below threshold", () => {
|
||||
const result = computeUnlockedCompanionIds({ ...baseParams, transcendenceCount: 4 });
|
||||
expect(result).not.toContain("vex");
|
||||
});
|
||||
|
||||
it("unlocks pria at 1 apotheosis", () => {
|
||||
const result = computeUnlockedCompanionIds({ ...baseParams, apotheosisCount: 1 });
|
||||
expect(result).toContain("pria");
|
||||
});
|
||||
|
||||
it("unlocks multiple companions simultaneously", () => {
|
||||
const result = computeUnlockedCompanionIds({
|
||||
lifetimeBossesDefeated: 720,
|
||||
lifetimeQuestsCompleted: 950,
|
||||
lifetimeGoldEarned: 1e18,
|
||||
prestigeCount: 10,
|
||||
transcendenceCount: 5,
|
||||
apotheosisCount: 1,
|
||||
});
|
||||
expect(result).toHaveLength(10);
|
||||
expect(result).toContain("lyra");
|
||||
expect(result).toContain("finn");
|
||||
expect(result).toContain("wren");
|
||||
expect(result).toContain("aldric");
|
||||
expect(result).toContain("sera");
|
||||
expect(result).toContain("kael");
|
||||
expect(result).toContain("zuri");
|
||||
expect(result).toContain("mira");
|
||||
expect(result).toContain("vex");
|
||||
expect(result).toContain("pria");
|
||||
});
|
||||
});
|
||||
|
||||
describe("getActiveCompanionBonus", () => {
|
||||
it("returns null when activeCompanionId is null", () => {
|
||||
expect(getActiveCompanionBonus(null, ["lyra"])).toBeNull();
|
||||
});
|
||||
|
||||
it("returns null when activeCompanionId is undefined", () => {
|
||||
expect(getActiveCompanionBonus(undefined, ["lyra"])).toBeNull();
|
||||
});
|
||||
|
||||
it("returns null when companion is not in unlockedCompanionIds", () => {
|
||||
expect(getActiveCompanionBonus("lyra", [])).toBeNull();
|
||||
});
|
||||
|
||||
it("returns null for an unknown companion id even if in unlocked list", () => {
|
||||
expect(getActiveCompanionBonus("unknown_companion", ["unknown_companion"])).toBeNull();
|
||||
});
|
||||
|
||||
it("returns the bonus for lyra when unlocked", () => {
|
||||
const bonus = getActiveCompanionBonus("lyra", ["lyra"]);
|
||||
expect(bonus).toEqual({ type: "passiveGold", value: 0.25 });
|
||||
});
|
||||
|
||||
it("returns the bonus for finn when unlocked", () => {
|
||||
const bonus = getActiveCompanionBonus("finn", ["lyra", "finn"]);
|
||||
expect(bonus).toEqual({ type: "clickGold", value: 0.50 });
|
||||
});
|
||||
|
||||
it("returns the bonus for wren when unlocked", () => {
|
||||
const bonus = getActiveCompanionBonus("wren", ["wren"]);
|
||||
expect(bonus).toEqual({ type: "questTime", value: 0.15 });
|
||||
});
|
||||
|
||||
it("returns the bonus for vex when unlocked", () => {
|
||||
const bonus = getActiveCompanionBonus("vex", ["vex"]);
|
||||
expect(bonus).toEqual({ type: "essenceIncome", value: 0.75 });
|
||||
});
|
||||
|
||||
it("returns the bonus for pria when unlocked", () => {
|
||||
const bonus = getActiveCompanionBonus("pria", ["pria"]);
|
||||
expect(bonus).toEqual({ type: "passiveGold", value: 1.00 });
|
||||
});
|
||||
});
|
||||
@@ -0,0 +1,97 @@
|
||||
/* eslint-disable max-lines-per-function -- Test suites naturally have many cases */
|
||||
import { describe, expect, it } from "vitest";
|
||||
import { computeSetBonuses } from "../src/interfaces/EquipmentSet.js";
|
||||
import type { EquipmentSet } from "../src/interfaces/EquipmentSet.js";
|
||||
|
||||
const makeSet = (partial: Partial<EquipmentSet> & Pick<EquipmentSet, "pieces">): EquipmentSet => ({
|
||||
id: "test_set",
|
||||
name: "Test Set",
|
||||
description: "A test equipment set",
|
||||
bonuses: {
|
||||
2: {},
|
||||
3: {},
|
||||
},
|
||||
...partial,
|
||||
});
|
||||
|
||||
describe("computeSetBonuses", () => {
|
||||
it("returns all multipliers as 1 when no equipped items", () => {
|
||||
const result = computeSetBonuses([], []);
|
||||
expect(result).toEqual({ goldMultiplier: 1, combatMultiplier: 1, clickMultiplier: 1 });
|
||||
});
|
||||
|
||||
it("returns all multipliers as 1 when sets array is empty", () => {
|
||||
const result = computeSetBonuses(["item1", "item2"], []);
|
||||
expect(result).toEqual({ goldMultiplier: 1, combatMultiplier: 1, clickMultiplier: 1 });
|
||||
});
|
||||
|
||||
it("returns 1 for all when only 1 piece of a set is equipped", () => {
|
||||
const set = makeSet({
|
||||
pieces: ["sword", "shield", "helm"],
|
||||
bonuses: { 2: { goldMultiplier: 1.5 }, 3: { goldMultiplier: 2.0 } },
|
||||
});
|
||||
const result = computeSetBonuses(["sword"], [set]);
|
||||
expect(result).toEqual({ goldMultiplier: 1, combatMultiplier: 1, clickMultiplier: 1 });
|
||||
});
|
||||
|
||||
it("applies 2-piece bonus when exactly 2 pieces are equipped", () => {
|
||||
const set = makeSet({
|
||||
pieces: ["sword", "shield", "helm"],
|
||||
bonuses: { 2: { goldMultiplier: 1.5 }, 3: { combatMultiplier: 2.0 } },
|
||||
});
|
||||
const result = computeSetBonuses(["sword", "shield"], [set]);
|
||||
expect(result).toEqual({ goldMultiplier: 1.5, combatMultiplier: 1, clickMultiplier: 1 });
|
||||
});
|
||||
|
||||
it("applies both 2-piece and 3-piece bonuses when all 3 pieces are equipped", () => {
|
||||
const set = makeSet({
|
||||
pieces: ["sword", "shield", "helm"],
|
||||
bonuses: { 2: { goldMultiplier: 1.5 }, 3: { combatMultiplier: 2.0 } },
|
||||
});
|
||||
const result = computeSetBonuses(["sword", "shield", "helm"], [set]);
|
||||
expect(result).toEqual({ goldMultiplier: 1.5, combatMultiplier: 2.0, clickMultiplier: 1 });
|
||||
});
|
||||
|
||||
it("applies click multiplier from set bonuses", () => {
|
||||
const set = makeSet({
|
||||
pieces: ["wand", "tome"],
|
||||
bonuses: { 2: { clickMultiplier: 1.25 }, 3: {} },
|
||||
});
|
||||
const result = computeSetBonuses(["wand", "tome"], [set]);
|
||||
expect(result).toEqual({ goldMultiplier: 1, combatMultiplier: 1, clickMultiplier: 1.25 });
|
||||
});
|
||||
|
||||
it("stacks bonuses from multiple sets multiplicatively", () => {
|
||||
const setA = makeSet({
|
||||
id: "set_a",
|
||||
pieces: ["sword", "shield"],
|
||||
bonuses: { 2: { goldMultiplier: 1.5 }, 3: {} },
|
||||
});
|
||||
const setB = makeSet({
|
||||
id: "set_b",
|
||||
pieces: ["ring", "amulet"],
|
||||
bonuses: { 2: { goldMultiplier: 2.0 }, 3: {} },
|
||||
});
|
||||
const result = computeSetBonuses(["sword", "shield", "ring", "amulet"], [setA, setB]);
|
||||
expect(result.goldMultiplier).toBeCloseTo(3.0);
|
||||
expect(result.combatMultiplier).toBe(1);
|
||||
});
|
||||
|
||||
it("uses 1 as fallback when bonus property is undefined", () => {
|
||||
const set = makeSet({
|
||||
pieces: ["a", "b"],
|
||||
bonuses: { 2: {}, 3: {} },
|
||||
});
|
||||
const result = computeSetBonuses(["a", "b"], [set]);
|
||||
expect(result).toEqual({ goldMultiplier: 1, combatMultiplier: 1, clickMultiplier: 1 });
|
||||
});
|
||||
|
||||
it("ignores non-equipped pieces that don't match the set", () => {
|
||||
const set = makeSet({
|
||||
pieces: ["sword", "shield"],
|
||||
bonuses: { 2: { goldMultiplier: 1.5 }, 3: {} },
|
||||
});
|
||||
const result = computeSetBonuses(["bow", "quiver"], [set]);
|
||||
expect(result).toEqual({ goldMultiplier: 1, combatMultiplier: 1, clickMultiplier: 1 });
|
||||
});
|
||||
});
|
||||
@@ -0,0 +1,28 @@
|
||||
import { describe, expect, it } from "vitest";
|
||||
import { DEFAULT_PROFILE_SETTINGS } from "../src/interfaces/ProfileSettings.js";
|
||||
|
||||
describe("DEFAULT_PROFILE_SETTINGS", () => {
|
||||
it("has all visibility flags set to true by default", () => {
|
||||
expect(DEFAULT_PROFILE_SETTINGS.showTotalGold).toBe(true);
|
||||
expect(DEFAULT_PROFILE_SETTINGS.showTotalClicks).toBe(true);
|
||||
expect(DEFAULT_PROFILE_SETTINGS.showLifetimeBossesDefeated).toBe(true);
|
||||
expect(DEFAULT_PROFILE_SETTINGS.showLifetimeQuestsCompleted).toBe(true);
|
||||
expect(DEFAULT_PROFILE_SETTINGS.showLifetimeAdventurersRecruited).toBe(true);
|
||||
expect(DEFAULT_PROFILE_SETTINGS.showLifetimeAchievementsUnlocked).toBe(true);
|
||||
expect(DEFAULT_PROFILE_SETTINGS.showGuildFounded).toBe(true);
|
||||
expect(DEFAULT_PROFILE_SETTINGS.showCurrentGold).toBe(true);
|
||||
expect(DEFAULT_PROFILE_SETTINGS.showCurrentClicks).toBe(true);
|
||||
expect(DEFAULT_PROFILE_SETTINGS.showPrestige).toBe(true);
|
||||
expect(DEFAULT_PROFILE_SETTINGS.showTranscendence).toBe(true);
|
||||
expect(DEFAULT_PROFILE_SETTINGS.showApotheosis).toBe(true);
|
||||
expect(DEFAULT_PROFILE_SETTINGS.showBossesDefeated).toBe(true);
|
||||
expect(DEFAULT_PROFILE_SETTINGS.showQuestsCompleted).toBe(true);
|
||||
expect(DEFAULT_PROFILE_SETTINGS.showAdventurersRecruited).toBe(true);
|
||||
expect(DEFAULT_PROFILE_SETTINGS.showAchievementsUnlocked).toBe(true);
|
||||
expect(DEFAULT_PROFILE_SETTINGS.showOnLeaderboards).toBe(true);
|
||||
});
|
||||
|
||||
it("defaults numberFormat to suffix", () => {
|
||||
expect(DEFAULT_PROFILE_SETTINGS.numberFormat).toBe("suffix");
|
||||
});
|
||||
});
|
||||
@@ -0,0 +1,164 @@
|
||||
/* eslint-disable max-lines-per-function -- Test suites naturally have many cases */
|
||||
import { describe, expect, it } from "vitest";
|
||||
import { isStoryChapterUnlocked } from "../src/interfaces/Story.js";
|
||||
import type { StoryChapter } from "../src/interfaces/Story.js";
|
||||
import type { GameState } from "../src/interfaces/GameState.js";
|
||||
|
||||
const makeMinimalState = (overrides: Partial<GameState> = {}): GameState =>
|
||||
({
|
||||
bosses: [],
|
||||
prestige: { count: 0, runestones: 0, productionMultiplier: 1, purchasedUpgradeIds: [] },
|
||||
transcendence: undefined,
|
||||
apotheosis: undefined,
|
||||
...overrides,
|
||||
} as unknown as GameState);
|
||||
|
||||
const makeChapter = (unlock: StoryChapter["unlock"]): StoryChapter => ({
|
||||
id: "test_chapter",
|
||||
title: "Test Chapter",
|
||||
content: "Test content",
|
||||
choices: [
|
||||
{ id: "a", label: "Choice A", outcome: "Outcome A" },
|
||||
{ id: "b", label: "Choice B", outcome: "Outcome B" },
|
||||
{ id: "c", label: "Choice C", outcome: "Outcome C" },
|
||||
],
|
||||
unlock,
|
||||
});
|
||||
|
||||
describe("isStoryChapterUnlocked — bossDefeated", () => {
|
||||
it("returns true when the boss is defeated", () => {
|
||||
const chapter = makeChapter({ type: "bossDefeated", bossId: "boss_1" });
|
||||
const state = makeMinimalState({
|
||||
bosses: [{ id: "boss_1", status: "defeated" }] as GameState["bosses"],
|
||||
});
|
||||
expect(isStoryChapterUnlocked(chapter, state)).toBe(true);
|
||||
});
|
||||
|
||||
it("returns false when the boss is available but not defeated", () => {
|
||||
const chapter = makeChapter({ type: "bossDefeated", bossId: "boss_1" });
|
||||
const state = makeMinimalState({
|
||||
bosses: [{ id: "boss_1", status: "available" }] as GameState["bosses"],
|
||||
});
|
||||
expect(isStoryChapterUnlocked(chapter, state)).toBe(false);
|
||||
});
|
||||
|
||||
it("returns false when the boss is not in the list", () => {
|
||||
const chapter = makeChapter({ type: "bossDefeated", bossId: "boss_1" });
|
||||
const state = makeMinimalState({ bosses: [] });
|
||||
expect(isStoryChapterUnlocked(chapter, state)).toBe(false);
|
||||
});
|
||||
|
||||
it("returns false when a different boss is defeated", () => {
|
||||
const chapter = makeChapter({ type: "bossDefeated", bossId: "boss_1" });
|
||||
const state = makeMinimalState({
|
||||
bosses: [{ id: "boss_2", status: "defeated" }] as GameState["bosses"],
|
||||
});
|
||||
expect(isStoryChapterUnlocked(chapter, state)).toBe(false);
|
||||
});
|
||||
});
|
||||
|
||||
describe("isStoryChapterUnlocked — prestige", () => {
|
||||
it("returns true when prestige count meets threshold", () => {
|
||||
const chapter = makeChapter({ type: "prestige", threshold: 1 });
|
||||
const state = makeMinimalState({
|
||||
prestige: { count: 1, runestones: 0, productionMultiplier: 1, purchasedUpgradeIds: [] },
|
||||
});
|
||||
expect(isStoryChapterUnlocked(chapter, state)).toBe(true);
|
||||
});
|
||||
|
||||
it("returns true when prestige count exceeds threshold", () => {
|
||||
const chapter = makeChapter({ type: "prestige", threshold: 5 });
|
||||
const state = makeMinimalState({
|
||||
prestige: { count: 10, runestones: 0, productionMultiplier: 1, purchasedUpgradeIds: [] },
|
||||
});
|
||||
expect(isStoryChapterUnlocked(chapter, state)).toBe(true);
|
||||
});
|
||||
|
||||
it("returns false when prestige count is below threshold", () => {
|
||||
const chapter = makeChapter({ type: "prestige", threshold: 5 });
|
||||
const state = makeMinimalState({
|
||||
prestige: { count: 4, runestones: 0, productionMultiplier: 1, purchasedUpgradeIds: [] },
|
||||
});
|
||||
expect(isStoryChapterUnlocked(chapter, state)).toBe(false);
|
||||
});
|
||||
|
||||
it("defaults to threshold 1 when threshold is undefined", () => {
|
||||
const chapter = makeChapter({ type: "prestige" });
|
||||
const state = makeMinimalState({
|
||||
prestige: { count: 1, runestones: 0, productionMultiplier: 1, purchasedUpgradeIds: [] },
|
||||
});
|
||||
expect(isStoryChapterUnlocked(chapter, state)).toBe(true);
|
||||
});
|
||||
});
|
||||
|
||||
describe("isStoryChapterUnlocked — transcendence", () => {
|
||||
it("returns true when transcendence count meets threshold", () => {
|
||||
const chapter = makeChapter({ type: "transcendence", threshold: 1 });
|
||||
const state = makeMinimalState({
|
||||
transcendence: { count: 1, echoes: 0, purchasedUpgradeIds: [], echoIncomeMultiplier: 1, echoCombatMultiplier: 1, echoPrestigeThresholdMultiplier: 1, echoPrestigeRunestoneMultiplier: 1, echoMetaMultiplier: 1 },
|
||||
});
|
||||
expect(isStoryChapterUnlocked(chapter, state)).toBe(true);
|
||||
});
|
||||
|
||||
it("returns false when transcendence is undefined", () => {
|
||||
const chapter = makeChapter({ type: "transcendence", threshold: 1 });
|
||||
const state = makeMinimalState({ transcendence: undefined });
|
||||
expect(isStoryChapterUnlocked(chapter, state)).toBe(false);
|
||||
});
|
||||
|
||||
it("returns false when transcendence count is below threshold", () => {
|
||||
const chapter = makeChapter({ type: "transcendence", threshold: 3 });
|
||||
const state = makeMinimalState({
|
||||
transcendence: { count: 2, echoes: 0, purchasedUpgradeIds: [], echoIncomeMultiplier: 1, echoCombatMultiplier: 1, echoPrestigeThresholdMultiplier: 1, echoPrestigeRunestoneMultiplier: 1, echoMetaMultiplier: 1 },
|
||||
});
|
||||
expect(isStoryChapterUnlocked(chapter, state)).toBe(false);
|
||||
});
|
||||
});
|
||||
|
||||
describe("isStoryChapterUnlocked — apotheosis", () => {
|
||||
it("returns true when apotheosis count meets threshold", () => {
|
||||
const chapter = makeChapter({ type: "apotheosis", threshold: 1 });
|
||||
const state = makeMinimalState({
|
||||
apotheosis: { count: 1 },
|
||||
});
|
||||
expect(isStoryChapterUnlocked(chapter, state)).toBe(true);
|
||||
});
|
||||
|
||||
it("returns false when apotheosis is undefined", () => {
|
||||
const chapter = makeChapter({ type: "apotheosis", threshold: 1 });
|
||||
const state = makeMinimalState({ apotheosis: undefined });
|
||||
expect(isStoryChapterUnlocked(chapter, state)).toBe(false);
|
||||
});
|
||||
|
||||
it("returns false when apotheosis count is below threshold", () => {
|
||||
const chapter = makeChapter({ type: "apotheosis", threshold: 2 });
|
||||
const state = makeMinimalState({ apotheosis: { count: 1 } });
|
||||
expect(isStoryChapterUnlocked(chapter, state)).toBe(false);
|
||||
});
|
||||
});
|
||||
|
||||
describe("isStoryChapterUnlocked — unknown type (defensive branch)", () => {
|
||||
it("returns false for unknown unlock type", () => {
|
||||
/* eslint-disable @typescript-eslint/consistent-type-assertions -- testing defensive branch */
|
||||
const chapter = makeChapter({ type: "unknown" as StoryChapter["unlock"]["type"] });
|
||||
/* eslint-enable @typescript-eslint/consistent-type-assertions */
|
||||
const state = makeMinimalState();
|
||||
expect(isStoryChapterUnlocked(chapter, state)).toBe(false);
|
||||
});
|
||||
});
|
||||
|
||||
describe("isStoryChapterUnlocked — threshold defaults", () => {
|
||||
it("defaults transcendence threshold to 1 when undefined", () => {
|
||||
const chapter = makeChapter({ type: "transcendence" });
|
||||
const state = makeMinimalState({
|
||||
transcendence: { count: 1, echoes: 0, purchasedUpgradeIds: [], echoIncomeMultiplier: 1, echoCombatMultiplier: 1, echoPrestigeThresholdMultiplier: 1, echoPrestigeRunestoneMultiplier: 1, echoMetaMultiplier: 1 },
|
||||
});
|
||||
expect(isStoryChapterUnlocked(chapter, state)).toBe(true);
|
||||
});
|
||||
|
||||
it("defaults apotheosis threshold to 1 when undefined", () => {
|
||||
const chapter = makeChapter({ type: "apotheosis" });
|
||||
const state = makeMinimalState({ apotheosis: { count: 1 } });
|
||||
expect(isStoryChapterUnlocked(chapter, state)).toBe(true);
|
||||
});
|
||||
});
|
||||
@@ -0,0 +1,23 @@
|
||||
import { defineConfig } from "vitest/config";
|
||||
|
||||
export default defineConfig({
|
||||
test: {
|
||||
coverage: {
|
||||
provider: "v8",
|
||||
include: [
|
||||
"src/interfaces/Companion.ts",
|
||||
"src/interfaces/EquipmentSet.ts",
|
||||
"src/interfaces/ProfileSettings.ts",
|
||||
"src/interfaces/Story.ts",
|
||||
],
|
||||
exclude: [],
|
||||
thresholds: {
|
||||
statements: 100,
|
||||
branches: 100,
|
||||
functions: 100,
|
||||
lines: 100,
|
||||
},
|
||||
},
|
||||
include: ["test/**/*.spec.ts"],
|
||||
},
|
||||
});
|
||||
Reference in New Issue
Block a user