Add getNearestStations to Reference client, along with types, validators and tests
All checks were successful
Testing / run-tests (push) Successful in 6m18s
All checks were successful
Testing / run-tests (push) Successful in 6m18s
This commit is contained in:
parent
a600d1f91d
commit
ca85bbd6be
@ -1,5 +1,5 @@
|
||||
import { validateCrs, validateNlc, validateReasonCode, validateStanox, validateTiploc, validateStation } from "../inputValidation/inputValidation";
|
||||
import { ReferenceV2_LocationReferenceCodes, ReferenceV2_LocationReferenceCodeType, ReferenceV2_ReasonCode } from "../types/reference/ReferenceTypesV2";
|
||||
import { validateCrs, validateNlc, validateReasonCode, validateStanox, validateTiploc, validateStation, validateLatLon } from "../inputValidation/inputValidation";
|
||||
import { ReferenceV2_LocationReferenceCodes, ReferenceV2_LocationReferenceCodeType, ReferenceV2_NearestStations, ReferenceV2_ReasonCode } from "../types/reference/ReferenceTypesV2";
|
||||
import { BaseOwlBoardClient } from "./client";
|
||||
|
||||
export class ReferenceClientV2 {
|
||||
@ -15,6 +15,12 @@ export class ReferenceClientV2 {
|
||||
return this.client.makeRequest("GET", path);
|
||||
}
|
||||
|
||||
async getNearestStations(latitude: number, longitude: number): Promise<ReferenceV2_NearestStations> {
|
||||
validateLatLon(latitude, longitude);
|
||||
const path = `/api/v2/live/station/nearest/${latitude}/${longitude}`
|
||||
return this.client.makeRequest("GET", path);
|
||||
}
|
||||
|
||||
async lookupLocationReference(type: ReferenceV2_LocationReferenceCodeType, referenceCode: string): Promise<ReferenceV2_LocationReferenceCodes> {
|
||||
const validators: Record<ReferenceV2_LocationReferenceCodeType, (code: string) => boolean> = {
|
||||
crs: validateCrs,
|
||||
|
||||
@ -7,7 +7,8 @@ import { validateCrs,
|
||||
validateHeadcode,
|
||||
validateNlc,
|
||||
validateStanox,
|
||||
validateStation} from "./inputValidation";
|
||||
validateStation,
|
||||
validateLatLon} from "./inputValidation";
|
||||
import { ValidationError } from "../errors";
|
||||
|
||||
describe("PIS Validation Tests", () => {
|
||||
@ -228,3 +229,36 @@ describe("Headcode Validation Tests", () => {
|
||||
expect(() => validateHeadcode(true)).toThrow(ValidationError);
|
||||
})
|
||||
})
|
||||
|
||||
describe("Latitude/Logitude Validation Tests", () => {
|
||||
test("Valid Latitude/Logitude values should return true", () => {
|
||||
expect(validateLatLon(51.5074, "-0.1278")).toBe(true);
|
||||
expect(validateLatLon("51.5074", "-0.1278")).toBe(true);
|
||||
expect(validateLatLon(0, 0)).toBe(true);
|
||||
expect(validateLatLon("0", "0")).toBe(true);
|
||||
expect(validateLatLon(90, 180)).toBe(true);
|
||||
expect(validateLatLon(-90, -180)).toBe(true);
|
||||
expect(validateLatLon(" 51.5074 ", " -0.1278 ")).toBe(true);
|
||||
expect(validateLatLon(45.123456, -73.987654)).toBe(true);
|
||||
expect(validateLatLon("89.9999999999", "179.9999999999")).toBe(true);
|
||||
})
|
||||
|
||||
test("Invalid types should throw Validation Error", () => {
|
||||
expect(() => validateLatLon(true, false)).toThrow(ValidationError);
|
||||
expect(() => validateLatLon([], [])).toThrow(ValidationError);
|
||||
expect(() => validateLatLon(null, null)).toThrow(ValidationError);
|
||||
expect(() => validateLatLon("str", "ing")).toThrow(ValidationError);
|
||||
expect(() => validateLatLon({}, {})).toThrow(ValidationError);
|
||||
expect(() => validateLatLon(14.235, "whale")).toThrow(ValidationError);
|
||||
expect(() => validateLatLon("", "")).toThrow(ValidationError);
|
||||
})
|
||||
|
||||
test("Out of bound inputs should throw Validation Error", () => {
|
||||
expect(() => validateLatLon(91, 0)).toThrow(ValidationError);
|
||||
expect(() => validateLatLon(-91, 47)).toThrow(ValidationError);
|
||||
expect(() => validateLatLon(12, 181)).toThrow(ValidationError);
|
||||
expect(() => validateLatLon(78, -181)).toThrow(ValidationError);
|
||||
expect(() => validateLatLon("90.0000001", "0")).toThrow(ValidationError);
|
||||
expect(() => validateLatLon("0", "180.0000001")).toThrow(ValidationError);
|
||||
})
|
||||
})
|
||||
@ -126,3 +126,26 @@ export function validateHeadcode(headcode: unknown): boolean {
|
||||
return true;
|
||||
}
|
||||
|
||||
export function validateLatLon(lat: unknown, lon: unknown): boolean {
|
||||
const toNumber = (val: unknown, label: string): number => {
|
||||
if (typeof val === "number") return val;
|
||||
if (typeof val === "string" && val.trim() !== "") {
|
||||
const num = Number(val);
|
||||
if (Number.isFinite(num)) return num;
|
||||
}
|
||||
throw new ValidationError(`Invalid input: ${label} must be a valid number`)
|
||||
};
|
||||
|
||||
const latNum = toNumber(lat, "latitude");
|
||||
const lonNum = toNumber(lon, "longitude");
|
||||
|
||||
if (latNum < -90 || latNum > 90) {
|
||||
throw new ValidationError("Latitude must be between -90 and 90");
|
||||
}
|
||||
if (lonNum < -180 || lonNum > 180) {
|
||||
throw new ValidationError("Longitude must be between -180 and 180");
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
|
||||
@ -19,4 +19,12 @@ interface ReferenceV2_ReasonCodeObject {
|
||||
|
||||
export type ReferenceV2_ReasonCode = ReferenceV2_ReasonCodeObject[]
|
||||
|
||||
export type ReferenceV2_LocationReferenceCodeType = "tiploc" | "crs" | "stanox" | "nlc" | "station"
|
||||
export type ReferenceV2_LocationReferenceCodeType = "tiploc" | "crs" | "stanox" | "nlc" | "station"
|
||||
|
||||
interface ReferenceV2_NearestStationItem {
|
||||
"3ALPHA": string;
|
||||
NLCDESC: string;
|
||||
miles: number; // Float
|
||||
}
|
||||
|
||||
export type ReferenceV2_NearestStations = ReferenceV2_NearestStationItem[]
|
||||
Loading…
x
Reference in New Issue
Block a user