
















@@ -42,6 +42,18 @@ function createRelayPushParams() {
4242};
4343}
444445+function expectRelayConfig(
46+resolved: ReturnType<typeof resolveApnsRelayConfigFromEnv>,
47+expected: { baseUrl: string; timeoutMs: number },
48+) {
49+expect(resolved.ok).toBe(true);
50+if (!resolved.ok) {
51+throw new Error("expected APNs relay config to resolve");
52+}
53+expect(resolved.value.baseUrl).toBe(expected.baseUrl);
54+expect(resolved.value.timeoutMs).toBe(expected.timeoutMs);
55+}
56+4557describe("push-apns.relay", () => {
4658describe("resolveApnsRelayConfigFromEnv", () => {
4759it("returns a missing-config error when no relay base URL is configured", () => {
@@ -70,12 +82,9 @@ describe("push-apns.relay", () => {
7082},
7183);
728473-expect(resolved).toMatchObject({
74-ok: true,
75-value: {
76-baseUrl: "https://relay-override.example.com/base",
77-timeoutMs: 1000,
78-},
85+expectRelayConfig(resolved, {
86+baseUrl: "https://relay-override.example.com/base",
87+timeoutMs: 1000,
7988});
8089});
8190@@ -86,12 +95,9 @@ describe("push-apns.relay", () => {
8695OPENCLAW_APNS_RELAY_TIMEOUT_MS: "nope",
8796} as NodeJS.ProcessEnv);
889789-expect(resolved).toMatchObject({
90-ok: true,
91-value: {
92-baseUrl: "http://[::1]:8787",
93-timeoutMs: 10_000,
94-},
98+expectRelayConfig(resolved, {
99+baseUrl: "http://[::1]:8787",
100+timeoutMs: 10_000,
95101});
96102});
97103@@ -154,20 +160,29 @@ describe("push-apns.relay", () => {
154160});
155161156162expect(sender).toHaveBeenCalledTimes(1);
157-const sent = sender.mock.calls[0]?.[0];
158-expect(sent).toMatchObject({
159-relayConfig: {
160-baseUrl: "https://relay.example.com",
161-timeoutMs: 1000,
162-},
163-sendGrant: "send-grant-123",
164-relayHandle: "relay-handle-123",
165-gatewayDeviceId: relayGatewayIdentity.deviceId,
166-signedAtMs: 123_456_789,
167-pushType: "alert",
168-priority: "10",
169-payload: { aps: { alert: { title: "Wake", body: "Ping" } } },
170-});
163+const sent = sender.mock.calls[0]?.[0] as
164+| {
165+relayConfig?: { baseUrl?: string; timeoutMs?: number };
166+sendGrant?: string;
167+relayHandle?: string;
168+gatewayDeviceId?: string;
169+signedAtMs?: number;
170+pushType?: string;
171+priority?: string;
172+payload?: unknown;
173+bodyJson?: string;
174+signature?: string;
175+}
176+| undefined;
177+expect(sent?.relayConfig?.baseUrl).toBe("https://relay.example.com");
178+expect(sent?.relayConfig?.timeoutMs).toBe(1000);
179+expect(sent?.sendGrant).toBe("send-grant-123");
180+expect(sent?.relayHandle).toBe("relay-handle-123");
181+expect(sent?.gatewayDeviceId).toBe(relayGatewayIdentity.deviceId);
182+expect(sent?.signedAtMs).toBe(123_456_789);
183+expect(sent?.pushType).toBe("alert");
184+expect(sent?.priority).toBe("10");
185+expect(sent?.payload).toEqual({ aps: { alert: { title: "Wake", body: "Ping" } } });
171186expect(sent?.bodyJson).toBe(
172187JSON.stringify({
173188relayHandle: "relay-handle-123",
@@ -188,13 +203,11 @@ describe("push-apns.relay", () => {
188203sent?.signature ?? "",
189204),
190205).toBe(true);
191-expect(result).toMatchObject({
192-ok: true,
193-status: 200,
194-apnsId: "relay-apns-id",
195-environment: "production",
196-tokenSuffix: "abcd1234",
197-});
206+expect(result.ok).toBe(true);
207+expect(result.status).toBe(200);
208+expect(result.apnsId).toBe("relay-apns-id");
209+expect(result.environment).toBe("production");
210+expect(result.tokenSuffix).toBe("abcd1234");
198211});
199212200213it("does not follow relay redirects", async () => {
@@ -208,13 +221,12 @@ describe("push-apns.relay", () => {
208221const result = await sendApnsRelayPush(createRelayPushParams());
209222210223expect(fetchMock).toHaveBeenCalledTimes(1);
211-expect(fetchMock.mock.calls[0]?.[1]).toMatchObject({ redirect: "manual" });
212-expect(result).toMatchObject({
213-ok: false,
214-status: 302,
215-reason: "RelayRedirectNotAllowed",
216-environment: "production",
217-});
224+const fetchOptions = fetchMock.mock.calls[0]?.[1] as { redirect?: unknown } | undefined;
225+expect(fetchOptions?.redirect).toBe("manual");
226+expect(result.ok).toBe(false);
227+expect(result.status).toBe(302);
228+expect(result.reason).toBe("RelayRedirectNotAllowed");
229+expect(result.environment).toBe("production");
218230});
219231220232it("falls back to fetch status when the relay body is not JSON", async () => {
此内容由惯性聚合(RSS阅读器)自动聚合整理,仅供阅读参考。 原文来自 — 版权归原作者所有。