mirror of
https://github.com/NomaDamas/k-skill.git
synced 2026-06-24 02:04:11 +00:00
Reject impossible K League schedule dates before querying
The kleague-results API previously accepted regex-shaped but impossible calendar dates and treated them like empty-result queries. This change adds a regression test first, then rejects invalid YYYY-MM-DD strings during normalization so bad input never reaches the fetch layer. Constraint: Public API contract says date must be a valid Date or YYYY-MM-DD string Rejected: Let upstream return zero matches | hides invalid input as a valid no-results response Confidence: high Scope-risk: narrow Reversibility: clean Directive: Keep string-date validation in normalizeDateInput before any schedule fetch Tested: node --test packages/kleague-results/test/index.test.js; npm run ci; live smoke getKLeagueSummary(2026-03-22, K리그1, FC서울, standings); live smoke getMatchResults(2026-03-22, K리그2); invalid-date smoke getMatchResults(2026-13-40); LSP diagnostics on changed files; architect verification Not-tested: Additional leap-year and month-end invalid-date permutations
This commit is contained in:
parent
01915d8032
commit
c784a77454
2 changed files with 43 additions and 0 deletions
|
|
@ -65,6 +65,10 @@ function normalizeDateInput(value) {
|
|||
throw new Error("date must be a valid Date or YYYY-MM-DD string.");
|
||||
}
|
||||
|
||||
if (!isValidCalendarDate(match[1], match[2], match[3])) {
|
||||
throw new Error("date must be a valid Date or YYYY-MM-DD string.");
|
||||
}
|
||||
|
||||
return buildDateParts(match[1], match[2], match[3]);
|
||||
}
|
||||
|
||||
|
|
@ -85,6 +89,27 @@ function buildDateParts(year, month, day) {
|
|||
};
|
||||
}
|
||||
|
||||
function isValidCalendarDate(year, month, day) {
|
||||
const numericYear = Number(year);
|
||||
const numericMonth = Number(month);
|
||||
const numericDay = Number(day);
|
||||
|
||||
if (!Number.isInteger(numericYear) || !Number.isInteger(numericMonth) || !Number.isInteger(numericDay)) {
|
||||
return false;
|
||||
}
|
||||
|
||||
if (numericMonth < 1 || numericMonth > 12 || numericDay < 1) {
|
||||
return false;
|
||||
}
|
||||
|
||||
const maxDay = [31, isLeapYear(numericYear) ? 29 : 28, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31][numericMonth - 1];
|
||||
return numericDay <= maxDay;
|
||||
}
|
||||
|
||||
function isLeapYear(year) {
|
||||
return year % 4 === 0 && (year % 100 !== 0 || year % 400 === 0);
|
||||
}
|
||||
|
||||
function buildClubDirectory(clubList = []) {
|
||||
const directory = new Map();
|
||||
|
||||
|
|
|
|||
|
|
@ -126,6 +126,24 @@ test("public fetchers compose day results with current standings via mocked fetc
|
|||
}
|
||||
});
|
||||
|
||||
test("getMatchResults rejects impossible calendar dates before fetching", async () => {
|
||||
let fetchCalled = false;
|
||||
|
||||
await assert.rejects(
|
||||
() =>
|
||||
getMatchResults("2026-13-40", {
|
||||
leagueId: "K리그1",
|
||||
fetchImpl: async () => {
|
||||
fetchCalled = true;
|
||||
return makeResponse(schedulePayload);
|
||||
},
|
||||
}),
|
||||
/date must be a valid Date or YYYY-MM-DD string\./,
|
||||
);
|
||||
|
||||
assert.equal(fetchCalled, false);
|
||||
});
|
||||
|
||||
function makeResponse(body) {
|
||||
return new Response(JSON.stringify(body), {
|
||||
status: 200,
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue