Add buildBuyTicketUrl + escapeHtml helpers for popup content
This commit is contained in:
@@ -0,0 +1,34 @@
|
||||
import { describe, it, expect } from "vitest";
|
||||
import { buildBuyTicketUrl, escapeHtml } from "./buyTicketUrl.js";
|
||||
|
||||
describe("buildBuyTicketUrl", () => {
|
||||
it("builds a URL with the correct base", () => {
|
||||
const url = buildBuyTicketUrl("MOW", "LED", "20260501");
|
||||
expect(url.startsWith("https://www.aeroflot.ru/sb/app/ru-ru#/search?")).toBe(true);
|
||||
});
|
||||
|
||||
it("includes the routes triple dep.date.arr", () => {
|
||||
const url = buildBuyTicketUrl("MOW", "LED", "20260501");
|
||||
expect(url).toContain("routes=MOW.20260501.LED");
|
||||
});
|
||||
|
||||
it("includes the stable UTM and adults/cabin params", () => {
|
||||
const url = buildBuyTicketUrl("MOW", "LED", "20260501");
|
||||
expect(url).toContain("adults=1");
|
||||
expect(url).toContain("cabin=economy");
|
||||
expect(url).toContain("autosearch=Y");
|
||||
expect(url).toContain("utm_source=aflwebbot");
|
||||
});
|
||||
});
|
||||
|
||||
describe("escapeHtml", () => {
|
||||
it("escapes &, <, >, and double-quote", () => {
|
||||
expect(escapeHtml("A & B < C > D \"E\"")).toBe(
|
||||
"A & B < C > D "E"",
|
||||
);
|
||||
});
|
||||
|
||||
it("returns the input unchanged when no special chars", () => {
|
||||
expect(escapeHtml("Москва")).toBe("Москва");
|
||||
});
|
||||
});
|
||||
@@ -0,0 +1,38 @@
|
||||
/**
|
||||
* Buy-ticket URL for the arrival popup (Angular parity: `getLink`).
|
||||
*
|
||||
* Base path + fixed params are hardcoded to the Russian-locale Aeroflot
|
||||
* search page. The routes triple `{dep}.{date}.{arr}` is the only variable
|
||||
* part of the URL.
|
||||
*/
|
||||
|
||||
const BASE = "https://www.aeroflot.ru/sb/app/ru-ru#/search";
|
||||
const FIXED_PARAMS =
|
||||
"adults=1&cabin=economy&children=0&infants=0&autosearch=Y" +
|
||||
"&utm_source=aflwebbot&utm_medium=referral" +
|
||||
"&utm_campaign=ref_3015_general_rf_button.index__all_flight.map";
|
||||
|
||||
/**
|
||||
* @param departure 3-letter city code (e.g. "MOW").
|
||||
* @param arrival 3-letter city code (e.g. "LED").
|
||||
* @param date YYYYMMDD — typically filter.date or today.
|
||||
*/
|
||||
export function buildBuyTicketUrl(
|
||||
departure: string,
|
||||
arrival: string,
|
||||
date: string,
|
||||
): string {
|
||||
return `${BASE}?${FIXED_PARAMS}&routes=${departure}.${date}.${arrival}`;
|
||||
}
|
||||
|
||||
/**
|
||||
* Minimal HTML escape for popup content — prevents injection via
|
||||
* city names containing `& < > "`.
|
||||
*/
|
||||
export function escapeHtml(s: string): string {
|
||||
return s
|
||||
.replace(/&/g, "&")
|
||||
.replace(/</g, "<")
|
||||
.replace(/>/g, ">")
|
||||
.replace(/"/g, """);
|
||||
}
|
||||
Reference in New Issue
Block a user