diff --git a/Auto Run Docs/SpecKit-web-header-analyzer-Phase-04-Test-Selection.md b/Auto Run Docs/SpecKit-web-header-analyzer-Phase-04-Test-Selection.md index c1321bc..61140df 100644 --- a/Auto Run Docs/SpecKit-web-header-analyzer-Phase-04-Test-Selection.md +++ b/Auto Run Docs/SpecKit-web-header-analyzer-Phase-04-Test-Selection.md @@ -35,7 +35,7 @@ This phase implements the test selection panel and analysis configuration contro - [x] Select All / Deselect All buttons work correctly - [x] Search/filter narrows visible tests by name - [x] DNS resolution toggle defaults to off -- [ ] Decode-all toggle is functional +- [x] Decode-all toggle is functional - [ ] All controls are keyboard accessible (Tab, Enter, Space) - [ ] Linting passes (`ruff check backend/`, `npx eslint src/`) - [ ] Run `/speckit.analyze` to verify consistency diff --git a/frontend/src/__tests__/AnalysisControls.test.tsx b/frontend/src/__tests__/AnalysisControls.test.tsx index 54f364d..df75117 100644 --- a/frontend/src/__tests__/AnalysisControls.test.tsx +++ b/frontend/src/__tests__/AnalysisControls.test.tsx @@ -110,6 +110,27 @@ describe("AnalysisControls", () => { ); }); + it("updates toggles without a controlled config", async () => { + setupFetchMock(sampleTests); + const handleChange = vi.fn(); + + const { container } = render(); + + await act(async () => { + await flushPromises(); + }); + + const decodeToggle = getToggle(container, "toggle-decode-all"); + act(() => { + decodeToggle.dispatchEvent(new MouseEvent("click", { bubbles: true })); + }); + + expect(decodeToggle.getAttribute("aria-checked")).toBe("true"); + expect(handleChange).toHaveBeenLastCalledWith( + expect.objectContaining({ decodeAll: true }), + ); + }); + it("updates toggles on click and keyboard", async () => { setupFetchMock(sampleTests); const handleChange = vi.fn(); diff --git a/frontend/src/components/AnalysisControls.tsx b/frontend/src/components/AnalysisControls.tsx index ed4c2ab..563b2ec 100644 --- a/frontend/src/components/AnalysisControls.tsx +++ b/frontend/src/components/AnalysisControls.tsx @@ -1,6 +1,6 @@ "use client"; -import type { KeyboardEvent } from "react"; +import { useState, type KeyboardEvent } from "react"; import { FontAwesomeIcon } from "@fortawesome/react-fontawesome"; import { faToggleOff, @@ -34,19 +34,29 @@ const handleToggleKeyDown = ( }; export default function AnalysisControls({ - config = defaultConfig, + config, onChange, }: AnalysisControlsProps) { + const [internalConfig, setInternalConfig] = useState(defaultConfig); + const resolvedConfig = config ?? internalConfig; + + const commitConfig = (nextConfig: AnalysisConfig) => { + if (!config) { + setInternalConfig(nextConfig); + } + onChange(nextConfig); + }; + const updateTests = (nextTestIds: number[]) => { - onChange({ ...config, testIds: nextTestIds }); + commitConfig({ ...resolvedConfig, testIds: nextTestIds }); }; const toggleResolve = () => { - onChange({ ...config, resolve: !config.resolve }); + commitConfig({ ...resolvedConfig, resolve: !resolvedConfig.resolve }); }; const toggleDecodeAll = () => { - onChange({ ...config, decodeAll: !config.decodeAll }); + commitConfig({ ...resolvedConfig, decodeAll: !resolvedConfig.decodeAll }); }; return ( @@ -70,15 +80,15 @@ export default function AnalysisControls({
@@ -94,20 +104,20 @@ export default function AnalysisControls({
- + ); }