import { fireEvent, render, screen } from "@testing-library/react" import { describe, expect, it, vi } from "vitest" import { Compressor } from "../compressor" // Mock useTranslation vi.mock("react-i18next", () => ({ useTranslation: () => ({ t: (key: string) => key, }), })) describe("Compressor", () => { it("renders with default settings", () => { render() expect(screen.getByText("fairlightAudio.effects.compressor.title")).toBeInTheDocument() expect(screen.getByText("fairlightAudio.effects.compressor.reset")).toBeInTheDocument() // Check all control labels expect(screen.getByText("fairlightAudio.effects.compressor.threshold")).toBeInTheDocument() expect(screen.getByText("fairlightAudio.effects.compressor.ratio")).toBeInTheDocument() expect(screen.getByText("fairlightAudio.effects.compressor.attack")).toBeInTheDocument() expect(screen.getByText("fairlightAudio.effects.compressor.release")).toBeInTheDocument() expect(screen.getByText("fairlightAudio.effects.compressor.knee")).toBeInTheDocument() expect(screen.getByText("fairlightAudio.effects.compressor.makeup")).toBeInTheDocument() }) it("displays default values", () => { render() expect(screen.getByText("-24.0 dB")).toBeInTheDocument() // threshold expect(screen.getByText("4:1")).toBeInTheDocument() // ratio expect(screen.getByText("10.0 ms")).toBeInTheDocument() // attack expect(screen.getByText("100 ms")).toBeInTheDocument() // release expect(screen.getByText("2.5 dB")).toBeInTheDocument() // knee expect(screen.getByText("0.0 dB")).toBeInTheDocument() // makeup }) it("renders preset buttons", () => { render() expect(screen.getByText("fairlightAudio.effects.compressor.presets.gentle")).toBeInTheDocument() expect(screen.getByText("fairlightAudio.effects.compressor.presets.vocal")).toBeInTheDocument() expect(screen.getByText("fairlightAudio.effects.compressor.presets.drums")).toBeInTheDocument() expect(screen.getByText("fairlightAudio.effects.compressor.presets.master")).toBeInTheDocument() }) it("calls onParameterChange when parameters are adjusted", () => { const onParameterChange = vi.fn() render() // Sliders are not easily testable with testing-library // We'll test the preset buttons instead const gentleButton = screen.getByText("fairlightAudio.effects.compressor.presets.gentle") fireEvent.click(gentleButton) expect(onParameterChange).toHaveBeenCalledWith("threshold", -20) expect(onParameterChange).toHaveBeenCalledWith("ratio", 2) expect(onParameterChange).toHaveBeenCalledWith("attack", 10) expect(onParameterChange).toHaveBeenCalledWith("release", 100) expect(onParameterChange).toHaveBeenCalledWith("knee", 10) expect(onParameterChange).toHaveBeenCalledWith("makeup", 2) }) it("applies vocal preset correctly", () => { const onParameterChange = vi.fn() render() const vocalButton = screen.getByText("fairlightAudio.effects.compressor.presets.vocal") fireEvent.click(vocalButton) expect(onParameterChange).toHaveBeenCalledWith("threshold", -15) expect(onParameterChange).toHaveBeenCalledWith("ratio", 3) expect(onParameterChange).toHaveBeenCalledWith("attack", 5) expect(onParameterChange).toHaveBeenCalledWith("release", 50) expect(onParameterChange).toHaveBeenCalledWith("knee", 5) expect(onParameterChange).toHaveBeenCalledWith("makeup", 3) }) it("applies drums preset correctly", () => { const onParameterChange = vi.fn() render() const drumsButton = screen.getByText("fairlightAudio.effects.compressor.presets.drums") fireEvent.click(drumsButton) expect(onParameterChange).toHaveBeenCalledWith("threshold", -10) expect(onParameterChange).toHaveBeenCalledWith("ratio", 6) expect(onParameterChange).toHaveBeenCalledWith("attack", 1) expect(onParameterChange).toHaveBeenCalledWith("release", 100) expect(onParameterChange).toHaveBeenCalledWith("knee", 0) expect(onParameterChange).toHaveBeenCalledWith("makeup", 5) }) it("applies master preset correctly", () => { const onParameterChange = vi.fn() render() const masterButton = screen.getByText("fairlightAudio.effects.compressor.presets.master") fireEvent.click(masterButton) expect(onParameterChange).toHaveBeenCalledWith("threshold", -12) expect(onParameterChange).toHaveBeenCalledWith("ratio", 2.5) expect(onParameterChange).toHaveBeenCalledWith("attack", 30) expect(onParameterChange).toHaveBeenCalledWith("release", 300) expect(onParameterChange).toHaveBeenCalledWith("knee", 20) expect(onParameterChange).toHaveBeenCalledWith("makeup", 1) }) it("resets to default settings", () => { const onParameterChange = vi.fn() render() // Apply a preset first const drumsButton = screen.getByText("fairlightAudio.effects.compressor.presets.drums") fireEvent.click(drumsButton) // Clear the mock onParameterChange.mockClear() // Click reset const resetButton = screen.getByText("fairlightAudio.effects.compressor.reset") fireEvent.click(resetButton) expect(onParameterChange).toHaveBeenCalledWith("threshold", -24) expect(onParameterChange).toHaveBeenCalledWith("ratio", 4) expect(onParameterChange).toHaveBeenCalledWith("attack", 10) expect(onParameterChange).toHaveBeenCalledWith("release", 100) expect(onParameterChange).toHaveBeenCalledWith("knee", 2.5) expect(onParameterChange).toHaveBeenCalledWith("makeup", 0) }) it("displays gain reduction meter", () => { render() // Check that gain reduction label is rendered expect(screen.getByText("fairlightAudio.effects.compressor.gainReduction")).toBeInTheDocument() // The meter should have a height based on gainReduction value const meter = screen .getByText("fairlightAudio.effects.compressor.gainReduction") .previousElementSibling?.querySelector(".bg-orange-500") expect(meter).toHaveStyle({ height: "20%" }) // 6/30 * 100 = 20% }) it("handles zero gain reduction", () => { render() const meter = screen .getByText("fairlightAudio.effects.compressor.gainReduction") .previousElementSibling?.querySelector(".bg-orange-500") expect(meter).toHaveStyle({ height: "0%" }) }) it("handles maximum gain reduction", () => { render() const meter = screen .getByText("fairlightAudio.effects.compressor.gainReduction") .previousElementSibling?.querySelector(".bg-orange-500") expect(meter).toHaveStyle({ height: "100%" }) }) it("formats high ratio as infinity", () => { render() // Can't easily test slider changes, but we can verify the formatRatio function // by checking the initial state expect(screen.getByText("4:1")).toBeInTheDocument() }) it("applies custom className", () => { const { container } = render() const compressorDiv = container.firstChild expect(compressorDiv).toHaveClass("custom-class") expect(compressorDiv).toHaveClass("bg-zinc-900") }) it("renders SVG visualization", () => { const { container } = render() const svg = container.querySelector("svg") expect(svg).toBeInTheDocument() expect(svg).toHaveAttribute("viewBox", "0 0 100 100") // Check for grid lines const lines = svg.querySelectorAll("line") expect(lines.length).toBeGreaterThan(0) // Check for compression curve path const path = svg.querySelector("path") expect(path).toBeInTheDocument() expect(path).toHaveAttribute("stroke", "#3b82f6") }) it("does not call onParameterChange when not provided", () => { // This should not throw render() const gentleButton = screen.getByText("fairlightAudio.effects.compressor.presets.gentle") expect(() => fireEvent.click(gentleButton)).not.toThrow() }) })