const https = await import("node:https");
let fakeNowMs = 1_700_000_000_000;
let sendMessage: typeofimport("./client.js").sendMessage;
let sendFileUrl: typeofimport("./client.js").sendFileUrl;
let fetchChatUsers: typeofimport("./client.js").fetchChatUsers;
let resolveLegacyWebhookNameToChatUserId: typeofimport("./client.js").resolveLegacyWebhookNameToChatUserId;
function createMockResponseEmitter(statusCode: number): IncomingMessage { const res = new EventEmitter() as Partial<IncomingMessage>;
res.statusCode = statusCode; return res as unknown as IncomingMessage;
}
function createMockRequestEmitter(): ClientRequest { const req = new EventEmitter() as Partial<ClientRequest>;
req.write = vi.fn() as ClientRequest["write"];
req.end = vi.fn() as ClientRequest["end"];
req.destroy = vi.fn() as ClientRequest["destroy"]; return req as unknown as ClientRequest;
}
it("returns true on successful send", async () => {
mockSuccessResponse(); const result = await settleTimers(sendMessage("https://nas.example.com/incoming", "Hello"));
expect(result).toBe(true);
});
it("returns false on server error after retries", async () => {
mockFailureResponse(500); const result = await settleTimers(sendMessage("https://nas.example.com/incoming", "Hello"));
expect(result).toBe(false);
});
it("rejects malformed file URLs before making a request", async () => { const result = await settleTimers(sendFileUrl("https://nas.example.com/incoming", "not-a-url"));
expect(result).toBe(false);
expect(ssrfMocks.resolvePinnedHostnameWithPolicy).not.toHaveBeenCalled();
expect(vi.mocked(https.request)).not.toHaveBeenCalled();
});
it("rejects non-http file URLs before making a request", async () => { const result = await settleTimers(
sendFileUrl("https://nas.example.com/incoming", "file:///tmp/secret.txt"),
);
expect(result).toBe(false);
expect(ssrfMocks.resolvePinnedHostnameWithPolicy).not.toHaveBeenCalled();
expect(vi.mocked(https.request)).not.toHaveBeenCalled();
});
it("rejects SSRF-blocked hosts before making a request", async () => {
ssrfMocks.resolvePinnedHostnameWithPolicy.mockRejectedValueOnce( new Error("Blocked private network target"),
); const result = await settleTimers(
sendFileUrl("https://nas.example.com/incoming", "http://169.254.169.254/latest/meta-data"),
);
expect(result).toBe(false);
expect(ssrfMocks.resolvePinnedHostnameWithPolicy).toHaveBeenCalledWith("169.254.169.254");
expect(vi.mocked(https.request)).not.toHaveBeenCalled();
});
});
// Helper to mock the user_list API response for fetchChatUsers / resolveLegacyWebhookNameToChatUserId function mockUserListResponse(users: Array<Record<string, unknown>>) {
mockUserListResponseImpl(users, false);
}
function mockUserListResponseOnce(users: Array<Record<string, unknown>>) {
mockUserListResponseImpl(users, true);
}
beforeEach(() => {
vi.clearAllMocks();
vi.useFakeTimers(); // Advance time to invalidate any cached user list from previous tests
fakeNowMs += 10 * 60 * 1000;
vi.setSystemTime(fakeNowMs);
});
Die Informationen auf dieser Webseite wurden
nach bestem Wissen sorgfältig zusammengestellt. Es wird jedoch weder Vollständigkeit, noch Richtigkeit,
noch Qualität der bereit gestellten Informationen zugesichert.
Bemerkung:
Die farbliche Syntaxdarstellung und die Messung sind noch experimentell.