diff --git a/apps/desktop/src/features/workspace/GrooveMap.test.tsx b/apps/desktop/src/features/workspace/GrooveMap.test.tsx new file mode 100644 index 000000000..015d832b2 --- /dev/null +++ b/apps/desktop/src/features/workspace/GrooveMap.test.tsx @@ -0,0 +1,51 @@ +import { describe, it, expect } from "vitest"; +import { render, screen } from "@testing-library/react"; +import { GrooveMap } from "./GrooveMap"; + +describe("GrooveMap", () => { + it("renders the loading state", () => { + render(); + expect(screen.getByText(/Checking the bass line/)).toBeInTheDocument(); + }); + + it("renders the empty state when no notes are provided", () => { + render(); + expect(screen.getByText(/No bass line transcription yet/)).toBeInTheDocument(); + }); + + it("renders the empty state when notes array is empty", () => { + render(); + expect(screen.getByText(/No bass line transcription yet/)).toBeInTheDocument(); + }); + + it("renders the notes correctly and verifies width scaling for offsets > 10", () => { + // We intentionally include a note with an offset > 10s (here 20.00s) + // to verify that the timeline max scaling adapts correctly, rather than capping at 10. + const notes = [ + { onset: 0, offset: 1.5, pitch: "E1" }, + { onset: 2, offset: 2.5, pitch: "A1" }, + { onset: 10, offset: 20, pitch: "E1" }, // max offset is 20 + ]; + + render(); + + // Check main accessible region exists + expect(screen.getByRole("region", { name: "Bass transcription groove map" })).toBeInTheDocument(); + + // Check note blocks are rendered (title attributes match note descriptions) + expect(screen.getByTitle("E1 (0.00s - 1.50s)")).toBeInTheDocument(); + expect(screen.getByTitle("A1 (2.00s - 2.50s)")).toBeInTheDocument(); + + // Verify the large offset note is rendered with the expected left and width attributes. + // The maxTime should be 20. So onset 10 = 50% left. (20-10) = 10 duration = 50% width. + const largeNote = screen.getByTitle("E1 (10.00s - 20.00s)"); + expect(largeNote).toHaveStyle({ + left: "50%", + width: "50%" + }); + + // Check pitches (A1 and E1) are rendered as horizontal lanes + expect(screen.getByText("A1")).toBeInTheDocument(); + expect(screen.getByText("E1")).toBeInTheDocument(); + }); +});