mirror of
https://github.com/openclaw/openclaw.git
synced 2026-08-26 04:15:48 -06:00
14b59a06f5
* fix(line): deliver a location LINE cannot render instead of dropping it A location whose title or address is blank makes LINE reject the whole request, so every delivery path filtered it out before sending. The reply then arrived without the pin, and nothing told the user or the operator that a part of the message had been removed: the coordinates the sender supplied were discarded silently. The location builder now answers with the values the sender wrote — the non-blank label plus the coordinates — as a text message, so an unrenderable pin degrades into something the chat can show instead of disappearing. Both delivery paths inherit that from the single builder, and the three call sites that used to skip a null result no longer have a branch to take. Live validation against the Messaging API confirms the shape: the authored location is rejected with "May not be empty" on messages[0].address, the same rejection kills an entire batch that also carries valid text, and both degraded forms validate cleanly. * fix(line): bound the location fallback to LINE's text limit Nothing caps the location labels at the schema, so a long title with a blank address produced one raw text message past LINE's 5,000-character limit — the provider rejected it and the location was lost exactly as silently as before. The pin path already caps each label at 100 characters. Name that limit and apply it in the fallback too, so both forms carry the same bound instead of one of them re-deriving the provider's rules. * test(line): merge the duplicate send.js imports
69 lines
2.2 KiB
TypeScript
69 lines
2.2 KiB
TypeScript
// Line tests cover how an unrenderable location reaches the chat.
|
|
import { describe, expect, it } from "vitest";
|
|
import { createLocationMessage } from "./send.js";
|
|
|
|
describe("createLocationMessage", () => {
|
|
it("keeps a renderable location as a pin", () => {
|
|
const message = createLocationMessage({
|
|
title: "Blue Bottle",
|
|
address: "1 Main Street",
|
|
latitude: 35.6895,
|
|
longitude: 139.6917,
|
|
});
|
|
|
|
expect(message).toEqual({
|
|
type: "location",
|
|
title: "Blue Bottle",
|
|
address: "1 Main Street",
|
|
latitude: 35.6895,
|
|
longitude: 139.6917,
|
|
});
|
|
});
|
|
|
|
it.each([
|
|
{ name: "title", title: " ", address: "1 Main Street", kept: "1 Main Street" },
|
|
{ name: "address", title: "Blue Bottle", address: " ", kept: "Blue Bottle" },
|
|
])(
|
|
"delivers a blank-$name location as the values the sender wrote",
|
|
({ title, address, kept }) => {
|
|
// LINE rejects the pin, but the sender's label and coordinates are still
|
|
// deliverable, so they must reach the chat instead of being dropped.
|
|
const message = createLocationMessage({
|
|
title,
|
|
address,
|
|
latitude: 35.6895,
|
|
longitude: 139.6917,
|
|
});
|
|
|
|
expect(message).toEqual({ type: "text", text: `${kept}\n35.6895, 139.6917` });
|
|
},
|
|
);
|
|
|
|
it("caps an oversized label so the fallback stays inside LINE's text limit", () => {
|
|
// Nothing bounds the label at the schema, so an unbounded fallback would be
|
|
// rejected for length and lose the location exactly as before.
|
|
const message = createLocationMessage({
|
|
title: "A".repeat(6000),
|
|
address: " ",
|
|
latitude: 35.6895,
|
|
longitude: 139.6917,
|
|
});
|
|
|
|
expect(message.type).toBe("text");
|
|
const text = (message as { text: string }).text;
|
|
expect(text).toBe("A".repeat(100) + String.fromCharCode(10) + "35.6895, 139.6917");
|
|
expect(text.length).toBeLessThanOrEqual(5000);
|
|
});
|
|
|
|
it("still delivers the coordinates when the sender left both labels blank", () => {
|
|
const message = createLocationMessage({
|
|
title: " ",
|
|
address: "",
|
|
latitude: 35.6895,
|
|
longitude: 139.6917,
|
|
});
|
|
|
|
expect(message).toEqual({ type: "text", text: "35.6895, 139.6917" });
|
|
});
|
|
});
|