94 lines
3.5 KiB
TypeScript
94 lines
3.5 KiB
TypeScript
import { describe, expect, it, vi } from "vitest";
|
|
import { isPublicIp, ProxyCheckProvider, shouldBlockIpClassification } from "../src/index";
|
|
|
|
const ipAddress = "8.8.8.8";
|
|
|
|
function response(details: Record<string, unknown>) {
|
|
return new Response(JSON.stringify({ status: "ok", [ipAddress]: details }), {
|
|
status: 200,
|
|
headers: { "content-type": "application/json" },
|
|
});
|
|
}
|
|
|
|
describe("ProxyCheck.io intelligence", () => {
|
|
it("maps geolocation and a clear network response", async () => {
|
|
const request = vi.fn<typeof fetch>().mockResolvedValue(response({
|
|
proxy: "no",
|
|
type: "Business",
|
|
risk: 2,
|
|
city: "Mountain View",
|
|
region: "California",
|
|
country: "United States",
|
|
isocode: "US",
|
|
latitude: 37.4056,
|
|
longitude: -122.0775,
|
|
timezone: "America/Los_Angeles",
|
|
asn: "AS15169",
|
|
provider: "Google LLC",
|
|
}));
|
|
|
|
const result = await new ProxyCheckProvider({ apiKey: "secret", request }).classify(ipAddress);
|
|
|
|
expect(result).toMatchObject({
|
|
classification: "clear",
|
|
provider: "proxycheck",
|
|
riskScore: 2,
|
|
location: {
|
|
city: "Mountain View",
|
|
region: "California",
|
|
country: "United States",
|
|
countryCode: "US",
|
|
latitude: 37.4056,
|
|
longitude: -122.0775,
|
|
timezone: "America/Los_Angeles",
|
|
},
|
|
network: { asn: "AS15169", provider: "Google LLC" },
|
|
});
|
|
expect(request).toHaveBeenCalledWith(
|
|
expect.stringContaining("https://proxycheck.io/v2/8.8.8.8"),
|
|
expect.objectContaining({ signal: expect.any(AbortSignal) }),
|
|
);
|
|
});
|
|
|
|
it("maps VPN and Tor responses to explicit classifications", async () => {
|
|
const vpnRequest = vi.fn<typeof fetch>().mockResolvedValue(response({ proxy: "yes", type: "VPN" }));
|
|
const torRequest = vi.fn<typeof fetch>().mockResolvedValue(response({ proxy: "yes", type: "TOR" }));
|
|
|
|
await expect(new ProxyCheckProvider({ apiKey: "secret", request: vpnRequest }).classify(ipAddress))
|
|
.resolves.toMatchObject({ classification: "vpn" });
|
|
await expect(new ProxyCheckProvider({ apiKey: "secret", request: torRequest }).classify(ipAddress))
|
|
.resolves.toMatchObject({ classification: "tor" });
|
|
});
|
|
|
|
it("fails explicitly when ProxyCheck does not return usable data", async () => {
|
|
const request = vi.fn<typeof fetch>().mockResolvedValue(
|
|
new Response(JSON.stringify({ status: "denied", message: "Invalid API key" }), { status: 200 }),
|
|
);
|
|
|
|
await expect(new ProxyCheckProvider({ apiKey: "secret", request }).classify(ipAddress))
|
|
.rejects.toThrow("ProxyCheck lookup failed");
|
|
});
|
|
});
|
|
|
|
describe("account-addition policy", () => {
|
|
it("fails closed and blocks anonymizing networks", () => {
|
|
expect(shouldBlockIpClassification("unknown", false)).toBe(true);
|
|
expect(shouldBlockIpClassification("vpn", false)).toBe(true);
|
|
expect(shouldBlockIpClassification("proxy", false)).toBe(true);
|
|
expect(shouldBlockIpClassification("tor", false)).toBe(true);
|
|
expect(shouldBlockIpClassification("clear", true)).toBe(false);
|
|
expect(shouldBlockIpClassification("hosting", false)).toBe(false);
|
|
expect(shouldBlockIpClassification("hosting", true)).toBe(true);
|
|
});
|
|
});
|
|
|
|
describe("public IP filtering", () => {
|
|
it("does not send private, loopback, documentation, or mapped-private addresses", () => {
|
|
expect(isPublicIp("8.8.8.8")).toBe(true);
|
|
expect(isPublicIp("10.0.0.1")).toBe(false);
|
|
expect(isPublicIp("127.0.0.1")).toBe(false);
|
|
expect(isPublicIp("203.0.113.10")).toBe(false);
|
|
expect(isPublicIp("::ffff:192.168.1.1")).toBe(false);
|
|
});
|
|
});
|