import { describe, expect, it } from "vite-plus/test"; import { extractAgentNotificationDeepLink, routeAgentNotificationResponseOnce,} from "./notificationPayload"; function responseWithData(data: Record<string, unknown>, identifier = "notification-1") { return { notification: { request: { identifier, content: { data, }, }, }, };} describe("extractAgentNotificationDeepLink", () => { it("uses explicit deep links from APNs payload data", () => { expect( extractAgentNotificationDeepLink( responseWithData({ deepLink: "/threads/env/thread", environmentId: "ignored", threadId: "ignored", }), ), ).toBe("/threads/env/thread"); }); it("normalizes explicit thread deep links from APNs payload data", () => { expect( extractAgentNotificationDeepLink( responseWithData({ deepLink: "/threads/env%201/thread%2F2", }), ), ).toBe("/threads/env%201/thread%2F2"); }); it("falls back to the thread route from environment and thread ids", () => { expect( extractAgentNotificationDeepLink( responseWithData({ environmentId: "env 1", threadId: "thread/2", }), ), ).toBe("/threads/env%201/thread%2F2"); }); it("falls back to ids when explicit deep link is not an agent thread route", () => { expect( extractAgentNotificationDeepLink( responseWithData({ deepLink: "/", environmentId: "env", threadId: "thread", }), ), ).toBe("/threads/env/thread"); }); it("ignores malformed or external links", () => { expect( extractAgentNotificationDeepLink(responseWithData({ deepLink: "https://example.com" })), ).toBeNull(); expect( extractAgentNotificationDeepLink(responseWithData({ deepLink: "/settings" })), ).toBeNull(); expect( extractAgentNotificationDeepLink(responseWithData({ deepLink: "//example.com" })), ).toBeNull(); expect( extractAgentNotificationDeepLink(responseWithData({ deepLink: "/threads/env/thread?x=1" })), ).toBeNull(); expect(extractAgentNotificationDeepLink({})).toBeNull(); });}); describe("routeAgentNotificationResponseOnce", () => { it("does not navigate twice when the initial and listener responses refer to one notification", () => { const handledResponseIds = new Set<string>(); const navigations: Array<string> = []; const response = responseWithData({ environmentId: "env", threadId: "thread", }); routeAgentNotificationResponseOnce({ handledResponseIds, response, navigate: (deepLink) => navigations.push(deepLink), }); routeAgentNotificationResponseOnce({ handledResponseIds, response, navigate: (deepLink) => navigations.push(deepLink), }); expect(navigations).toEqual(["/threads/env/thread"]); });});
import { describe, expect, it } from "vite-plus/test";
import {
extractAgentNotificationDeepLink,
routeAgentNotificationResponseOnce,
} from "./notificationPayload";
function responseWithData(data: Record<string, unknown>, identifier = "notification-1") {
return {
notification: {
request: {
identifier,
content: {
data,
},
},
},
};
}
describe("extractAgentNotificationDeepLink", () => {
it("uses explicit deep links from APNs payload data", () => {
expect(
extractAgentNotificationDeepLink(
responseWithData({
deepLink: "/threads/env/thread",
environmentId: "ignored",
threadId: "ignored",
}),
),
).toBe("/threads/env/thread");
});
it("normalizes explicit thread deep links from APNs payload data", () => {
expect(
extractAgentNotificationDeepLink(
responseWithData({
deepLink: "/threads/env%201/thread%2F2",
}),
),
).toBe("/threads/env%201/thread%2F2");
});
it("falls back to the thread route from environment and thread ids", () => {
expect(
extractAgentNotificationDeepLink(
responseWithData({
environmentId: "env 1",
threadId: "thread/2",
}),
),
).toBe("/threads/env%201/thread%2F2");
});
it("falls back to ids when explicit deep link is not an agent thread route", () => {
expect(
extractAgentNotificationDeepLink(
responseWithData({
deepLink: "/",
environmentId: "env",
threadId: "thread",
}),
),
).toBe("/threads/env/thread");
});
it("ignores malformed or external links", () => {
expect(
extractAgentNotificationDeepLink(responseWithData({ deepLink: "https://example.com" })),
).toBeNull();
expect(
extractAgentNotificationDeepLink(responseWithData({ deepLink: "/settings" })),
).toBeNull();
expect(
extractAgentNotificationDeepLink(responseWithData({ deepLink: "//example.com" })),
).toBeNull();
expect(
extractAgentNotificationDeepLink(responseWithData({ deepLink: "/threads/env/thread?x=1" })),
).toBeNull();
expect(extractAgentNotificationDeepLink({})).toBeNull();
});
});
describe("routeAgentNotificationResponseOnce", () => {
it("does not navigate twice when the initial and listener responses refer to one notification", () => {
const handledResponseIds = new Set<string>();
const navigations: Array<string> = [];
const response = responseWithData({
environmentId: "env",
threadId: "thread",
});
routeAgentNotificationResponseOnce({
handledResponseIds,
response,
navigate: (deepLink) => navigations.push(deepLink),
});
routeAgentNotificationResponseOnce({
handledResponseIds,
response,
navigate: (deepLink) => navigations.push(deepLink),
});
expect(navigations).toEqual(["/threads/env/thread"]);
});
});