diff --git a/apps/web/src/components/filters/FilterBar.test.tsx b/apps/web/src/components/filters/FilterBar.test.tsx index 53a659b..8b077c4 100644 --- a/apps/web/src/components/filters/FilterBar.test.tsx +++ b/apps/web/src/components/filters/FilterBar.test.tsx @@ -132,4 +132,70 @@ describe("FilterBar", (): void => { // Should show 3 active filters (2 statuses + 1 priority) expect(screen.getByText(/3/)).toBeInTheDocument(); }); + + describe("accessibility (CQ-WEB-11)", (): void => { + it("should have aria-label on search input", (): void => { + render(); + const searchInput = screen.getByRole("textbox", { name: /search tasks/i }); + expect(searchInput).toBeInTheDocument(); + }); + + it("should have aria-label on date inputs", (): void => { + render(); + expect(screen.getByLabelText(/filter from date/i)).toBeInTheDocument(); + expect(screen.getByLabelText(/filter to date/i)).toBeInTheDocument(); + }); + + it("should have aria-labels on status filter buttons", (): void => { + render(); + expect(screen.getByRole("button", { name: /status filter/i })).toBeInTheDocument(); + }); + + it("should have aria-labels on priority filter buttons", (): void => { + render(); + expect(screen.getByRole("button", { name: /priority filter/i })).toBeInTheDocument(); + }); + + it("should have id and htmlFor associations on status checkboxes", async (): Promise => { + const user = userEvent.setup(); + render(); + + // Open status dropdown + await user.click(screen.getByRole("button", { name: /status filter/i })); + + // Verify specific status checkboxes have proper id attributes + const notStartedCheckbox = screen.getByLabelText(/filter by status: not started/i); + expect(notStartedCheckbox).toHaveAttribute("id", "status-filter-NOT_STARTED"); + + const inProgressCheckbox = screen.getByLabelText(/filter by status: in progress/i); + expect(inProgressCheckbox).toHaveAttribute("id", "status-filter-IN_PROGRESS"); + + const completedCheckbox = screen.getByLabelText(/filter by status: completed/i); + expect(completedCheckbox).toHaveAttribute("id", "status-filter-COMPLETED"); + }); + + it("should have id and htmlFor associations on priority checkboxes", async (): Promise => { + const user = userEvent.setup(); + render(); + + // Open priority dropdown + await user.click(screen.getByRole("button", { name: /priority filter/i })); + + // Verify specific priority checkboxes have proper id attributes + const lowCheckbox = screen.getByLabelText(/filter by priority: low/i); + expect(lowCheckbox).toHaveAttribute("id", "priority-filter-LOW"); + + const mediumCheckbox = screen.getByLabelText(/filter by priority: medium/i); + expect(mediumCheckbox).toHaveAttribute("id", "priority-filter-MEDIUM"); + + const highCheckbox = screen.getByLabelText(/filter by priority: high/i); + expect(highCheckbox).toHaveAttribute("id", "priority-filter-HIGH"); + }); + + it("should have aria-label on clear filters button", (): void => { + const filtersWithSearch = { search: "test" }; + render(); + expect(screen.getByRole("button", { name: /clear filters/i })).toBeInTheDocument(); + }); + }); }); diff --git a/apps/web/src/components/filters/FilterBar.tsx b/apps/web/src/components/filters/FilterBar.tsx index 981060d..ccb541c 100644 --- a/apps/web/src/components/filters/FilterBar.tsx +++ b/apps/web/src/components/filters/FilterBar.tsx @@ -112,6 +112,7 @@ export function FilterBar({ { setSearchValue(e.target.value); @@ -141,14 +142,17 @@ export function FilterBar({ {Object.values(TaskStatus).map((status) => (