tests/step2chords.test.js
- import { describe, it, expect, vi, afterEach } from "vitest";
- import { chordGraph } from "../src/model/theory.js";
- import { FIXTURES, INSTANCES, STUBS } from "./api.js";
- const { step2Params } = FIXTURES;
- const { step2 } = INSTANCES;
- describe("Step2Chords", () => {
- afterEach(() => vi.unstubAllGlobals());
-
- it("schema appends the preset list from index.json; falls back to manual-only on fetch failure", async () => {
- STUBS.fetchJson([{ id: "bach", name: "Bach", works: 412 }]);
- const okParams = await step2.schema();
- const okStyle = okParams
- .find((p) => p.name === "part")
- .template.find((t) => t.name === "style");
- expect(okStyle.options).toEqual(["manual", "bach"]);
- expect(okStyle.labels).toEqual(["Manual", "Bach (412)"]);
- STUBS.fetchReject("nope");
- STUBS.silenceConsole("warn");
- const failParams = await step2.schema();
- const failStyle = failParams
- .find((p) => p.name === "part")
- .template.find((t) => t.name === "style");
- expect(failStyle.options).toEqual(["manual"]);
- });
-
- it("solve emits an NC-filled progression with chord-graph data and an empty concreteProgression in disabled mode without invoking the solver", async () => {
- const solver = vi.fn();
- const out = await step2.solve(
- { enable: false, mode: "major", key: 0, bars: 3, preset: null },
- solver,
- );
- expect(solver).not.toHaveBeenCalled();
- expect(out.chords).toEqual(["NC", "NC", "NC"]);
- expect(out.chordGraph.path).toBeNull();
- expect(out.chordGraph.graph.nodes).toContain("I");
- expect(out.textOutput).toContain("disabled");
- expect(out.concreteProgression).toBe("");
- });
-
- it("solve returns progression, cost and path on solver success; reports 'No chord progression found' when path is null", async () => {
- const params = { ...step2Params({ bars: 3 }), key: 0 };
- const { nodes } = chordGraph(params.mode, params.preset);
- const intOf = Object.fromEntries(nodes.map((node, i) => [node, i + 1]));
- const okSolver = vi.fn().mockResolvedValue({
- path: [intOf["I"], intOf["V"], intOf["I"]],
- total_cost: 4,
- });
- const ok = await step2.solve(params, okSolver);
- expect(ok.chords).toEqual(["I", "V", "I"]);
- expect(ok.concreteProgression).toBe("C -> G -> C");
- expect(ok.textOutput).toContain("Chord Progression Found");
- expect(ok.textOutput).toContain("Total cost: 4");
- expect(ok.chordGraph.path.nodes).toEqual(["I", "V", "I"]);
- expect(ok.chordGraph.path.edges).toBeInstanceOf(Set);
- const fail = await step2.solve(params, vi.fn().mockResolvedValue(null));
- expect(fail.textOutput).toBe("No chord progression found.");
- expect(fail.chordGraph.path).toBeNull();
- expect(fail.chords).toEqual([]);
- expect(fail.concreteProgression).toBe("");
- });
- });