claude/sweet-carson-46j5k6 #100

Merged
chrisp merged 2 commits from claude/sweet-carson-46j5k6 into main 2026-06-19 06:15:32 +00:00
3 changed files with 41 additions and 19 deletions
Showing only changes of commit 45c7950805 - Show all commits

View file

@ -3,6 +3,13 @@ import { Link } from "react-router";
import { ArrowUp, ArrowDown, ArrowUpDown } from "lucide-react"; import { ArrowUp, ArrowDown, ArrowUpDown } from "lucide-react";
import { Button } from "~/components/ui/button"; import { Button } from "~/components/ui/button";
import { Card, CardContent } from "~/components/ui/card"; import { Card, CardContent } from "~/components/ui/card";
import {
Select,
SelectContent,
SelectItem,
SelectTrigger,
SelectValue,
} from "~/components/ui/select";
import { Table, TableHeader, TableRow, TableHead, TableBody, TableCell } from "~/components/ui/table"; import { Table, TableHeader, TableRow, TableHead, TableBody, TableCell } from "~/components/ui/table";
import { Badge } from "~/components/ui/badge"; import { Badge } from "~/components/ui/badge";
@ -271,9 +278,7 @@ export function TeamScoreBreakdown({
<PositionCell pick={pick} /> <PositionCell pick={pick} />
</TableCell> </TableCell>
<TableCell className="text-right"> <TableCell className="text-right">
<div className="flex flex-col items-end"> <PointsValue pick={pick} />
<PointsValue pick={pick} />
</div>
</TableCell> </TableCell>
</TableRow> </TableRow>
))} ))}
@ -286,26 +291,29 @@ export function TeamScoreBreakdown({
<div className="md:hidden space-y-3" data-testid="picks-mobile"> <div className="md:hidden space-y-3" data-testid="picks-mobile">
{/* Sort control */} {/* Sort control */}
<div className="flex items-center gap-2"> <div className="flex items-center gap-2">
<label htmlFor="picks-sort" className="text-sm text-muted-foreground shrink-0"> <span id="picks-sort-label" className="text-sm text-muted-foreground shrink-0">
Sort by Sort by
</label> </span>
<select <Select
id="picks-sort"
value={sortColumn} value={sortColumn}
onChange={(e) => handleSortColumn(e.target.value as SortColumn)} onValueChange={(v) => handleSortColumn(v as SortColumn)}
className="flex-1 rounded-md border border-input bg-transparent px-3 py-2 text-sm shadow-xs outline-none focus-visible:ring-[3px] focus-visible:ring-ring/50"
> >
{SORT_OPTIONS.map((opt) => ( <SelectTrigger className="flex-1" aria-labelledby="picks-sort-label">
<option key={opt.value} value={opt.value}> <SelectValue />
{opt.label} </SelectTrigger>
</option> <SelectContent>
))} {SORT_OPTIONS.map((opt) => (
</select> <SelectItem key={opt.value} value={opt.value}>
{opt.label}
</SelectItem>
))}
</SelectContent>
</Select>
<Button <Button
variant="outline" variant="outline"
size="icon" size="icon"
onClick={() => setSortDirection(sortDirection === "asc" ? "desc" : "asc")} onClick={() => setSortDirection(sortDirection === "asc" ? "desc" : "asc")}
aria-label={`Sort ${sortDirection === "asc" ? "ascending" : "descending"}`} aria-label={`Sort ${sortDirection === "asc" ? "descending" : "ascending"}`}
> >
{sortDirection === "asc" ? ( {sortDirection === "asc" ? (
<ArrowUp className="h-4 w-4" /> <ArrowUp className="h-4 w-4" />

View file

@ -519,6 +519,11 @@ describe("TeamScoreBreakdown", () => {
); );
} }
async function selectSortColumn(user: ReturnType<typeof userEvent.setup>, label: string) {
await user.click(screen.getByRole("combobox", { name: /sort by/i }));
await user.click(screen.getByRole("option", { name: label }));
}
it("renders a card per pick with all fields visible", () => { it("renders a card per pick with all fields visible", () => {
renderWithRouter( renderWithRouter(
<TeamScoreBreakdown <TeamScoreBreakdown
@ -571,7 +576,7 @@ describe("TeamScoreBreakdown", () => {
); );
// picks: Team A=100, Driver B=50, Team C=0; points defaults to descending // picks: Team A=100, Driver B=50, Team C=0; points defaults to descending
await user.selectOptions(screen.getByLabelText(/sort by/i), "points"); await selectSortColumn(user, "Points");
expect(getCardOrder()).toEqual(["Team A", "Driver B", "Team C"]); expect(getCardOrder()).toEqual(["Team A", "Driver B", "Team C"]);
}); });
@ -587,8 +592,9 @@ describe("TeamScoreBreakdown", () => {
/> />
); );
await user.selectOptions(screen.getByLabelText(/sort by/i), "points"); // desc await selectSortColumn(user, "Points"); // desc
await user.click(screen.getByRole("button", { name: /sort descending/i })); // While descending, the toggle's action is to sort ascending.
await user.click(screen.getByRole("button", { name: /sort ascending/i }));
// now ascending: Team C (0), Driver B (50), Team A (100) // now ascending: Team C (0), Driver B (50), Team A (100)
expect(getCardOrder()).toEqual(["Team C", "Driver B", "Team A"]); expect(getCardOrder()).toEqual(["Team C", "Driver B", "Team A"]);
}); });

View file

@ -29,6 +29,14 @@ process.env.NODE_ENV = 'test';
// jsdom does not implement scrollTo on elements // jsdom does not implement scrollTo on elements
HTMLElement.prototype.scrollTo = vi.fn(); HTMLElement.prototype.scrollTo = vi.fn();
// jsdom does not implement these APIs that Radix UI relies on for pointer
// interactions and option positioning (Select, DropdownMenu, etc.). Without
// them, opening a Radix Select in a test throws.
HTMLElement.prototype.scrollIntoView = vi.fn();
HTMLElement.prototype.hasPointerCapture = vi.fn(() => false);
HTMLElement.prototype.setPointerCapture = vi.fn();
HTMLElement.prototype.releasePointerCapture = vi.fn();
// Mock BetterAuth // Mock BetterAuth
vi.mock('~/lib/auth.server', () => ({ vi.mock('~/lib/auth.server', () => ({
auth: { auth: {