From ff733b97745d2dda0ab8d36e1316bfff77179c2a Mon Sep 17 00:00:00 2001 From: Daniel Bulant Date: Mon, 25 May 2026 18:10:22 +0200 Subject: [PATCH] tests --- .../__tests__/question-generation.test.ts | 45 +++++++++++++++++++ api/src/party/question-utils.ts | 18 ++++++-- 2 files changed, 59 insertions(+), 4 deletions(-) diff --git a/api/src/party/__tests__/question-generation.test.ts b/api/src/party/__tests__/question-generation.test.ts index 24713f7..60691e5 100644 --- a/api/src/party/__tests__/question-generation.test.ts +++ b/api/src/party/__tests__/question-generation.test.ts @@ -1,5 +1,6 @@ import { describe, expect, it, vi } from "vitest"; import type { Question, QuizRound } from "../../party-types"; +import { buildAudioMetadataQuestion } from "../audio-question-generator"; import { buildNumericQuestion } from "../numeric-question-generator"; import { buildMemberOptions, @@ -266,6 +267,50 @@ describe("question generation", () => { expect(question).toBeNull(); }); + it("builds audio questions with fewer than four real options", async () => { + const randomSpy = vi.spyOn(Math, "random").mockReturnValue(0.99); + const db = createFakeDb(null); + const analytics = { + storyClusters: [ + { + tracks: [ + { + name: "Shared Track One", + artists: [{ name: "Shared Artist One" }], + albumName: "Shared Album One", + }, + { + name: "Shared Track Two", + artists: [{ name: "Shared Artist Two" }], + albumName: "Shared Album Two", + }, + ], + artists: [ + { name: "Shared Artist One" }, + { name: "Shared Artist Two" }, + ], + genres: [], + }, + ], + groupSummary: { + mostSharedGenres: [], + }, + } as PartyAnalytics; + + try { + const question = await buildAudioMetadataQuestion(db, analytics, 0, []); + + expect(question).not.toBeNull(); + expect(question?.type).toBe("choice"); + if (question?.type === "choice") { + expect(question.options).toHaveLength(2); + expect(question.text).toContain("Shared Track Two"); + } + } finally { + randomSpy.mockRestore(); + } + }); + it("selects a fresh party song when the current one was already used", async () => { const db = createSongFallbackDb([ makeSong("track-1", "spotify:track:one", "One"), diff --git a/api/src/party/question-utils.ts b/api/src/party/question-utils.ts index f0cbdb3..5f8f74d 100644 --- a/api/src/party/question-utils.ts +++ b/api/src/party/question-utils.ts @@ -135,7 +135,7 @@ export function getMostSharedGenreNames(analytics: PartyAnalytics): string[] { export function pickQuestionCandidate( candidates: QuestionCandidate[], history: QuizRound[], - index: number, + _index: number, ): T | null { const seenKeys = new Set(); const seenSubjects = new Set(); @@ -165,7 +165,7 @@ export function pickQuestionCandidate( if (fresh.length === 0) return null; const pool = fresh; - const candidate = pool[index % pool.length]; + const candidate = pickRandom(pool); if (!candidate) return null; return { ...candidate.question, @@ -510,7 +510,8 @@ export function buildOrderedOptions( const options = uniqueStrings( values.filter((value): value is string => isUsableText(value)), ); - return options.length >= desiredCount ? options.slice(0, desiredCount) : null; + const optionCount = getAvailableOptionCount(options.length, desiredCount); + return optionCount ? options.slice(0, optionCount) : null; } export function buildOptionsWithCorrect( @@ -523,7 +524,8 @@ export function buildOptionsWithCorrect( correct, ...candidates.filter((c) => isUsableText(c) && c !== correct), ]); - return options.length >= desiredCount ? options.slice(0, desiredCount) : null; + const optionCount = getAvailableOptionCount(options.length, desiredCount); + return optionCount ? options.slice(0, optionCount) : null; } export function pickRandom(items: T[]): T | null { @@ -532,6 +534,14 @@ export function pickRandom(items: T[]): T | null { return items[index] ?? null; } +function getAvailableOptionCount( + availableCount: number, + desiredCount: number, +): number | null { + if (availableCount < 2) return null; + return Math.min(availableCount, desiredCount); +} + export function getCurrentLeader( quizState: { scores: Record }, members: PartyQuestionMember[],