tests/step3notes.test.js
- import { describe, it, expect, vi } from "vitest";
- import { timeGrid } from "../src/model/theory.js";
- import { FIXTURES, INSTANCES } from "./api.js";
- const { step3Params } = FIXTURES;
- const { step3 } = INSTANCES;
- describe("Step3Notes", () => {
-
- it("schema exposes top-level descriptors and format functions for pitch, seed, interval and rest; instrument groups carry running GM program numbers", () => {
- const params = step3.schema();
- expect(params.map((p) => p.name)).toEqual([
- "voices",
- "voice",
- "seed_pct",
- "dissonance",
- "max_interval",
- "rest_pct",
- "constraints",
- ]);
- const voiceTpl = params.find((p) => p.name === "voice").template;
- expect(voiceTpl.find((t) => t.name === "min_pitch").format(60)).toBe(
- "C<sub>4</sub>",
- );
- expect(voiceTpl.find((t) => t.name === "max_pitch").format(67)).toBe(
- "G<sub>4</sub>",
- );
- expect(params.find((p) => p.name === "seed_pct").format(25)).toBe("25%");
- expect(params.find((p) => p.name === "max_interval").format(6)).toContain(
- "Semitones",
- );
- expect(params.find((p) => p.name === "rest_pct").format(10)).toBe("10%");
- const instrument = voiceTpl.find((t) => t.name === "instrument");
- expect(instrument.groups).toHaveLength(16);
- expect(instrument.groups[0].label).toBe("Piano");
- expect(instrument.groups[0].options[0]).toEqual({
- value: 0,
- label: "Acoustic Grand Piano",
- });
- expect(instrument.groups[1].options[0]).toEqual({
- value: 8,
- label: "Celesta",
- });
- expect(instrument.groups[15].options[7]).toEqual({
- value: 127,
- label: "Gunshot",
- });
- });
-
- it("solve returns a 'No solution' message on null solver result; exposes solution + time-grid metadata for the composer cache on a real solution; derives bars from chords length when present", async () => {
- const noSol = await step3.solve(
- step3Params(),
- vi.fn().mockResolvedValue(null),
- );
- expect(noSol.textOutput).toContain("No solution");
- expect(noSol.solution).toBeUndefined();
- const params = step3Params();
- const { subdivision, numSubBeats } = timeGrid(
- params.voice,
- params.voices,
- params.numerator,
- params.bars,
- );
- const sol = { note_0_0: 60 };
- const out = await step3.solve(params, vi.fn().mockResolvedValue(sol));
- expect(out.textOutput).toContain("solution found");
- expect(out.solution).toBe(sol);
- expect(out.numSubBeats).toBe(numSubBeats);
- expect(out.subdivision).toBe(subdivision);
- const fromChords = await step3.solve(
- step3Params({ bars: 99, chords: ["I", "V"] }),
- vi.fn().mockResolvedValue(sol),
- );
- expect(fromChords.numSubBeats).toBe(8);
- });
- });