claude/sweet-carson-46j5k6 #100
3 changed files with 41 additions and 19 deletions
|
|
@ -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" />
|
||||||
|
|
|
||||||
|
|
@ -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"]);
|
||||||
});
|
});
|
||||||
|
|
|
||||||
|
|
@ -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: {
|
||||||
|
|
|
||||||
Loading…
Add table
Reference in a new issue