Add CSV imports and granular competition data cleanup

This commit is contained in:
larssand
2026-08-27 17:56:50 +02:00
parent a87c64a47c
commit e5af42ce2d
9 changed files with 504 additions and 8 deletions

50
tests/csv_import.test.js Normal file
View File

@@ -0,0 +1,50 @@
import test from "node:test";
import assert from "node:assert/strict";
import { parseCsvRows, importDriversCsv, importCarsCsv } from "../src/csv_import.js";
function makeUid() {
let next = 0;
return (prefix) => `${prefix}_${++next}`;
}
test("CSV parser supports quoted commas, semicolons, tabs, and BOM headers", () => {
assert.deepEqual(parseCsvRows('\uFEFFname,brand\n"Driver, One","Team ""A"""')[0].values, {
name: "Driver, One",
brand: 'Team "A"',
});
assert.equal(parseCsvRows("name;transponder\nDriver One;123")[0].values.transponder, "123");
assert.equal(parseCsvRows("name\ttransponder\nCar One\t456")[0].values.transponder, "456");
});
test("driver CSV import creates classes and merges exported or external rows safely", () => {
const result = importDriversCsv(
"id;namn;klass;märke;transponder;klubb;land\n;New Driver;2WD;Associated;222;JMK;SE\ndriver_1;Existing Driver;4WD;;111;;",
{
classes: [{ id: "class_4wd", name: "4WD" }],
drivers: [{ id: "driver_1", name: "Old Name", classId: "class_4wd", brand: "Xray", transponder: "111", profileId: "profile_1", club: "JMK", country: "SE" }],
uid: makeUid(),
}
);
assert.equal(result.added, 1);
assert.equal(result.updated, 1);
assert.equal(result.skipped, 0);
assert.equal(result.classes.find((item) => item.name === "2WD")?.id, "class_1");
assert.equal(result.drivers.find((item) => item.id === "driver_1")?.name, "Existing Driver");
assert.equal(result.drivers.find((item) => item.id === "driver_1")?.brand, "Xray");
assert.equal(result.drivers.find((item) => item.transponder === "222")?.classId, "class_1");
});
test("car CSV import matches transponders and skips nameless rows", () => {
const result = importCarsCsv(
"name,brand,transponder\nUpdated Car,,123\nNew Car,Schumacher,456\n,Missing,789",
{
cars: [{ id: "car_1", name: "Old Car", brand: "Associated", transponder: "123" }],
uid: makeUid(),
}
);
assert.equal(result.added, 1);
assert.equal(result.updated, 1);
assert.equal(result.skipped, 1);
assert.equal(result.cars.find((item) => item.id === "car_1")?.name, "Updated Car");
assert.equal(result.cars.find((item) => item.id === "car_1")?.brand, "Associated");
});

View File

@@ -5,4 +5,5 @@ import "./judging_logic.test.js";
import "./runtime_persistence.test.js";
import "./audio_runtime.test.js";
import "./decoder_runtime.test.js";
import "./csv_import.test.js";
import "./server_persistence.integration.test.js";