import assert from "node:assert/strict"; // Training stats "Based on": practice by default; "Races" replaces the stint table with one // row per race session, marked ๐Ÿ with race, session and series - race laps never form stints. export async function runTrainingSourceSmoke({ evaluate, navigate, savedState, waitFor, base }) { const patchState = async (patch) => { const current = await savedState(); Object.assign(current, patch); const response = await fetch(base + "/api/state", { method: "POST", headers: { "Content-Type": "application/json" }, body: JSON.stringify(current) }); assert.equal(response.ok, true); }; const seeded = await savedState(); const t0 = Date.now() - 3600000; const lap = (sessionId, offset, lapMs) => ({ driverId: "ts_driver", competitorKey: "driver_ts_driver", sessionId, lapMs, timestamp: t0 + offset, validLap: true }); await patchState({ classes: [...seeded.classes, { id: "ts_class", name: "TS 2WD" }], drivers: [...seeded.drivers, { id: "ts_driver", profileId: "ts_profile", name: "TS Driver", classId: "ts_class", transponder: "8770001" }], events: [...seeded.events, { id: "ts_practice_event", name: "TS Practice", classId: "ts_class", mode: "race", raceConfig: { practiceOnly: true } }, { id: "ts_race_event", name: "TS Winter #3 TS 2WD", classId: "ts_class", mode: "race", date: "2026-11-29" }], sessions: [...seeded.sessions, { id: "ts_op", eventId: "ts_practice_event", name: "TS Open Practice", type: "open_practice", status: "finished" }, { id: "ts_q2", eventId: "ts_race_event", name: "Kval 2", type: "qualification", status: "finished" }], series: [...(seeded.series || []), { id: "ts_series", name: "TS Winter Cup", eventIds: ["ts_race_event"], classIds: ["ts_class"] }], resultsBySession: { ...seeded.resultsBySession, ts_op: { passings: [lap("ts_op", 20000, 20000), lap("ts_op", 40000, 20000), lap("ts_op", 59500, 19500), lap("ts_op", 79000, 19500)], competitors: {} }, ts_q2: { passings: [lap("ts_q2", 900000, 18000), lap("ts_q2", 918000, 18200), lap("ts_q2", 936400, 18400)], competitors: {} }, }, }); try { await navigate("training", "view"); // The overview has its own driver picker; the driver page has another one. await waitFor(async () => Boolean(await evaluate(`[...document.querySelectorAll("#training-overview-driver option, #training-driver option")].some((option) => option.value === "ts_profile")`)), "driver listed"); await evaluate(`(() => { const select = document.getElementById("training-overview-driver") || document.getElementById("training-driver"); select.value = "ts_profile"; select.dispatchEvent(new Event("change")); })()`); await waitFor(async () => (await evaluate(`document.getElementById("training-driver")?.value`)) === "ts_profile" && Boolean(await evaluate(`document.getElementById("training-source")`)), "training stats for the driver"); assert.equal(await evaluate(`document.getElementById("training-source").value`), "practice", "practice is the default"); assert.equal(await evaluate(`Boolean(document.querySelector('[data-sort-id="training-stints-featured"]'))`), true, "stints for practice"); assert.equal(await evaluate(`document.querySelectorAll(".training-race-origin").length`), 0, "no race laps mixed into practice"); await evaluate(`(() => { const select = document.getElementById("training-source"); select.value = "race"; select.dispatchEvent(new Event("change")); })()`); await waitFor(async () => Boolean(await evaluate(`document.querySelector('[data-sort-id="training-race-sessions"]')`)), "race sessions table"); assert.equal(await evaluate(`Boolean(document.querySelector('[data-sort-id="training-stints-featured"]'))`), false, "no stints for races"); const row = await evaluate(`[...document.querySelectorAll('[data-sort-id="training-race-sessions"] tbody tr')].map((tr) => [...tr.children].map((td) => td.textContent.trim()))[0]`); assert.equal(row[1], "๐Ÿ TS Winter #3 TS 2WD ยท Kval 2 ยท TS Winter Cup", "race, session and series"); assert.equal(row[2], "3"); console.log("PASS training stats: practice by default; races shown per race session with ๐Ÿ race ยท session ยท series, never as stints"); } finally { const current = await savedState(); const results = { ...current.resultsBySession }; delete results.ts_op; delete results.ts_q2; await patchState({ resultsBySession: results, sessions: current.sessions.filter((session) => !session.id.startsWith("ts_")), events: current.events.filter((event) => !event.id.startsWith("ts_")), series: (current.series || []).filter((series) => series.id !== "ts_series"), drivers: current.drivers.filter((driver) => driver.id !== "ts_driver"), classes: current.classes.filter((item) => item.id !== "ts_class"), training: { ...current.training, ledger: (current.training?.ledger || []).filter((entry) => !String(entry.sessionId).startsWith("ts_")) }, }); } }