Fixes #289 * docs: add batch qualifying results entry design spec Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com> * docs: add batch qualifying results entry implementation plan Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com> * chore: ignore .worktrees directory * feat: add qualifying results text parser with tests * fix: handle no-space after dot separator, tighten T-prefix to uppercase only * feat: add batch-add-results server intent with duplicate filtering Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com> * feat: add create-participant intent for inline participant creation * fix: trim sportsSeasonId validation in create-participant intent * feat: fill 0-QP rows for unplaced participants on qualifying event finalize Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com> * perf: use bulk insert for 0-QP rows on qualifying event finalize * feat: add BatchResultEntry component for paste-and-parse batch result import Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com> * fix: disable add participant button while create request is in flight * feat: render BatchResultEntry on qualifying event pages Add BatchResultEntry component import and render it on event pages when the event is a qualifying event, not a final_standings/playoff_game type, and not yet complete. Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com> * fix: address final review issues (sportsSeasonId authority, participant validation, CRLF, unused prop) Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com> --------- Co-authored-by: Claude Sonnet 4.6 <noreply@anthropic.com>
48 lines
1.7 KiB
TypeScript
48 lines
1.7 KiB
TypeScript
import { describe, it, expect } from "vitest";
|
|
import { filterNewResults, findParticipantsWithoutResults } from "../admin.sports-seasons.$id.events.$eventId.helpers";
|
|
|
|
describe("filterNewResults", () => {
|
|
it("returns all rows when no existing results", () => {
|
|
const incoming = [
|
|
{ participantId: "p1", placement: 1 },
|
|
{ participantId: "p2", placement: 2 },
|
|
];
|
|
expect(filterNewResults(incoming, new Set())).toEqual(incoming);
|
|
});
|
|
|
|
it("skips participantIds already in existingIds", () => {
|
|
const incoming = [
|
|
{ participantId: "p1", placement: 1 },
|
|
{ participantId: "p2", placement: 2 },
|
|
];
|
|
const existing = new Set(["p1"]);
|
|
expect(filterNewResults(incoming, existing)).toEqual([
|
|
{ participantId: "p2", placement: 2 },
|
|
]);
|
|
});
|
|
|
|
it("returns empty array when all are duplicates", () => {
|
|
const incoming = [{ participantId: "p1", placement: 1 }];
|
|
const existing = new Set(["p1"]);
|
|
expect(filterNewResults(incoming, existing)).toEqual([]);
|
|
});
|
|
});
|
|
|
|
describe("findParticipantsWithoutResults", () => {
|
|
it("returns participantIds not in existingResultIds", () => {
|
|
const allIds = ["p1", "p2", "p3"];
|
|
const existingIds = new Set(["p1"]);
|
|
expect(findParticipantsWithoutResults(allIds, existingIds)).toEqual(["p2", "p3"]);
|
|
});
|
|
|
|
it("returns empty array when all participants have results", () => {
|
|
const allIds = ["p1", "p2"];
|
|
const existingIds = new Set(["p1", "p2"]);
|
|
expect(findParticipantsWithoutResults(allIds, existingIds)).toEqual([]);
|
|
});
|
|
|
|
it("returns all when none have results", () => {
|
|
const allIds = ["p1", "p2"];
|
|
expect(findParticipantsWithoutResults(allIds, new Set())).toEqual(["p1", "p2"]);
|
|
});
|
|
});
|