feat(flight-finder): implement milestone M1 - domain model and skill contract
This commit is contained in:
98
skills/flight-finder/tests/request-normalizer.test.ts
Normal file
98
skills/flight-finder/tests/request-normalizer.test.ts
Normal file
@@ -0,0 +1,98 @@
|
||||
import test from "node:test";
|
||||
import assert from "node:assert/strict";
|
||||
|
||||
import {
|
||||
DFW_BLQ_2026_PROMPT_DRAFT,
|
||||
normalizeFlightReportRequest
|
||||
} from "../src/request-normalizer.js";
|
||||
|
||||
test("normalizeFlightReportRequest preserves the legacy DFW-BLQ split-return structure", () => {
|
||||
const result = normalizeFlightReportRequest(DFW_BLQ_2026_PROMPT_DRAFT);
|
||||
|
||||
assert.equal(result.readyToSearch, true);
|
||||
assert.deepEqual(result.missingSearchInputs, []);
|
||||
assert.deepEqual(result.missingDeliveryInputs, []);
|
||||
assert.equal(result.request.preferences.marketCountry, "TH");
|
||||
assert.equal(result.request.preferences.normalizeCurrencyTo, "USD");
|
||||
assert.equal(result.request.legs.length, 3);
|
||||
assert.equal(result.request.passengerGroups.length, 2);
|
||||
assert.deepEqual(
|
||||
result.request.legAssignments.find((entry) => entry.legId === "outbound")?.passengerGroupIds,
|
||||
["pair", "solo"]
|
||||
);
|
||||
assert.equal(
|
||||
result.request.preferences.requireAirlineDirectCrossCheck,
|
||||
true
|
||||
);
|
||||
});
|
||||
|
||||
test("normalizeFlightReportRequest keeps email missing as a delivery gate, not a search blocker", () => {
|
||||
const result = normalizeFlightReportRequest({
|
||||
...DFW_BLQ_2026_PROMPT_DRAFT,
|
||||
recipientEmail: null
|
||||
});
|
||||
|
||||
assert.equal(result.readyToSearch, true);
|
||||
assert.deepEqual(result.missingSearchInputs, []);
|
||||
assert.deepEqual(result.missingDeliveryInputs, ["recipient email"]);
|
||||
assert.match(result.warnings.join(" "), /recipient email/i);
|
||||
});
|
||||
|
||||
test("normalizeFlightReportRequest reports missing search-critical inputs explicitly", () => {
|
||||
const result = normalizeFlightReportRequest({
|
||||
tripName: "Incomplete flight request",
|
||||
legs: [
|
||||
{
|
||||
id: "outbound",
|
||||
origin: "DFW",
|
||||
destination: "",
|
||||
label: "Outbound"
|
||||
}
|
||||
],
|
||||
passengerGroups: [],
|
||||
legAssignments: []
|
||||
});
|
||||
|
||||
assert.equal(result.readyToSearch, false);
|
||||
assert.match(result.missingSearchInputs.join(" | "), /origin and destination/i);
|
||||
assert.match(result.missingSearchInputs.join(" | "), /date window/i);
|
||||
assert.match(result.missingSearchInputs.join(" | "), /passenger groups/i);
|
||||
assert.match(result.missingSearchInputs.join(" | "), /assignments/i);
|
||||
});
|
||||
|
||||
test("normalizeFlightReportRequest validates marketCountry as an ISO alpha-2 code", () => {
|
||||
assert.throws(
|
||||
() =>
|
||||
normalizeFlightReportRequest({
|
||||
...DFW_BLQ_2026_PROMPT_DRAFT,
|
||||
preferences: {
|
||||
...DFW_BLQ_2026_PROMPT_DRAFT.preferences,
|
||||
marketCountry: "Germany"
|
||||
}
|
||||
}),
|
||||
/ISO 3166-1 alpha-2/i
|
||||
);
|
||||
});
|
||||
|
||||
test("normalizeFlightReportRequest uppercases a lowercase marketCountry code", () => {
|
||||
const result = normalizeFlightReportRequest({
|
||||
...DFW_BLQ_2026_PROMPT_DRAFT,
|
||||
preferences: {
|
||||
...DFW_BLQ_2026_PROMPT_DRAFT.preferences,
|
||||
marketCountry: "th"
|
||||
}
|
||||
});
|
||||
|
||||
assert.equal(result.request.preferences.marketCountry, "TH");
|
||||
});
|
||||
|
||||
test("normalizeFlightReportRequest flags a malformed recipient email without blocking search readiness", () => {
|
||||
const result = normalizeFlightReportRequest({
|
||||
...DFW_BLQ_2026_PROMPT_DRAFT,
|
||||
recipientEmail: "stefano-at-example"
|
||||
});
|
||||
|
||||
assert.equal(result.readyToSearch, true);
|
||||
assert.deepEqual(result.missingDeliveryInputs, ["valid recipient email"]);
|
||||
assert.match(result.warnings.join(" "), /malformed/i);
|
||||
});
|
||||
Reference in New Issue
Block a user