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:
@@ -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);
|
||||
});
|
||||
});
|
||||
Reference in New Issue
Block a user