You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

165 lines
4.8 KiB

This file contains ambiguous Unicode characters!

This file contains ambiguous Unicode characters that may be confused with others in your current locale. If your use case is intentional and legitimate, you can safely ignore this warning. Use the Escape button to highlight these characters.

import { beforeEach, describe, expect, it, vi } from "vitest";
import {
axelSearchRowToCandidate,
resolveAxelMothershipCandidates,
resolveAxelMothershipSuggest,
} from "@/lib/axel/candidates";
import { AxelHttpClient } from "@/lib/axel/client";
describe("axelSearchRowToCandidate", () => {
it("display_label 与 axel description 一致option_id 保留原始 placeId", () => {
const row = {
placeId: "ChIJ4cLf10jGwoARBQWdZHer2OQ",
description: "123 Main Street, Los Angeles, CA, USA",
mainText: "123 Main Street",
secondaryText: "Los Angeles, CA, USA",
};
const candidate = axelSearchRowToCandidate(row, {
street: "123 Main St",
city: "Los Angeles",
state: "CA",
zip: "90001",
});
expect(candidate?.option_id).toBe("ChIJ4cLf10jGwoARBQWdZHer2OQ");
expect(candidate?.display_label).toBe(
"123 Main Street, Los Angeles, CA, USA",
);
expect(candidate?.street).toContain("123");
});
});
describe("resolveAxelMothershipCandidates", () => {
beforeEach(() => {
vi.restoreAllMocks();
vi.stubEnv("AXEL_CANDIDATE_VERIFY_TOP_K", "3");
});
function makeSearchRow(suffix: string) {
return {
placeId: `ChIJ-${suffix}`,
description: `${suffix} Main Street, Dallas, TX, USA`,
mainText: `${suffix} Main Street`,
secondaryText: "Dallas, TX, USA",
};
}
it("仅对前 3 条候选 fetchPlace 校验,其余默认可选", async () => {
const fetchPlace = vi.fn().mockResolvedValue({ placeId: "ok" });
const searchLocation = vi
.fn()
.mockResolvedValueOnce([
makeSearchRow("1"),
makeSearchRow("2"),
makeSearchRow("3"),
makeSearchRow("4"),
makeSearchRow("5"),
])
.mockResolvedValueOnce([makeSearchRow("d1")]);
vi.spyOn(AxelHttpClient, "create").mockResolvedValue({
searchLocation,
fetchPlace,
} as unknown as AxelHttpClient);
const result = await resolveAxelMothershipCandidates({
pickup: {
street: "1 Main St",
city: "Dallas",
state: "TX",
zip: "75201",
},
delivery: {
street: "2 Oak Ave",
city: "Los Angeles",
state: "CA",
zip: "90001",
},
});
expect(result.pickup_candidates).toHaveLength(5);
expect(result.delivery_candidates).toHaveLength(1);
expect(fetchPlace).toHaveBeenCalledTimes(4);
expect(result.pickup_candidates[0]?.selectable).toBe(true);
expect(result.pickup_candidates[3]?.selectable).toBe(true);
expect(result.pickup_candidates[4]?.selectable).toBe(true);
});
it("前 K 条均失败时,未校验候选仍可使 assert 通过", async () => {
const fetchPlace = vi
.fn()
.mockRejectedValueOnce(new Error("place 404"))
.mockRejectedValueOnce(new Error("place 404"))
.mockRejectedValueOnce(new Error("place 404"))
.mockResolvedValueOnce({ placeId: "ChIJ-d1" });
const searchLocation = vi
.fn()
.mockResolvedValueOnce([
makeSearchRow("bad1"),
makeSearchRow("bad2"),
makeSearchRow("bad3"),
makeSearchRow("good-tail"),
])
.mockResolvedValueOnce([makeSearchRow("d1")]);
vi.spyOn(AxelHttpClient, "create").mockResolvedValue({
searchLocation,
fetchPlace,
} as unknown as AxelHttpClient);
const result = await resolveAxelMothershipCandidates({
pickup: {
street: "99 Main St",
city: "Dallas",
state: "TX",
zip: "75201",
},
delivery: {
street: "1 Oak",
city: "LA",
state: "CA",
zip: "90001",
},
});
expect(result.pickup_candidates[0]?.selectable).toBe(false);
expect(result.pickup_candidates[3]?.selectable).toBe(true);
expect(fetchPlace).toHaveBeenCalledTimes(4);
});
});
describe("resolveAxelMothershipSuggest", () => {
beforeEach(() => {
vi.restoreAllMocks();
vi.stubEnv("AXEL_CANDIDATE_VERIFY_TOP_K", "3");
});
it("仅映射 Axel googlePlacesResults无 placeId 丢弃,并对 TopK fetchPlace", async () => {
const fetchPlace = vi.fn().mockResolvedValue({ placeId: "ok" });
const searchLocation = vi.fn().mockResolvedValue([
{
placeId: "ChIJ-a",
description: "100 A St, LA, CA, USA",
mainText: "100 A St",
secondaryText: "LA, CA, USA",
},
{
placeId: "",
description: "本系统不应出现的假地址",
mainText: "fake",
secondaryText: "Nowhere",
},
]);
vi.spyOn(AxelHttpClient, "create").mockResolvedValue({
searchLocation,
fetchPlace,
} as unknown as AxelHttpClient);
const list = await resolveAxelMothershipSuggest("100 A St");
expect(searchLocation).toHaveBeenCalledWith("100 A St");
expect(list).toHaveLength(1);
expect(list[0]?.option_id).toBe("ChIJ-a");
expect(fetchPlace).toHaveBeenCalledTimes(1);
});
});