63 lines
2.5 KiB
TypeScript
63 lines
2.5 KiB
TypeScript
import { beforeEach, describe, expect, it, vi } from "vitest";
|
|
|
|
vi.mock("@toolctrl/config", () => ({
|
|
loadWebConfig: vi.fn(() => ({ config: { ipGeo: { hashPepper: "test-pepper", dbPath: undefined } } })),
|
|
}));
|
|
vi.mock("~/utils/logger.server", () => ({
|
|
createScopedLogger: () => ({ warn: vi.fn(), error: vi.fn(), debug: vi.fn(), info: vi.fn() }),
|
|
}));
|
|
|
|
import { createHmac } from "node:crypto";
|
|
import { hashIp, lookupCountry, __resetGeoipReaderForTests } from "./geoip.server";
|
|
import { loadWebConfig } from "@toolctrl/config";
|
|
|
|
describe("geoip.hashIp", () => {
|
|
beforeEach(() => {
|
|
__resetGeoipReaderForTests();
|
|
vi.mocked(loadWebConfig).mockReturnValue({ config: { ipGeo: { hashPepper: "test-pepper" } } } as never);
|
|
});
|
|
|
|
it("pseudonymisiert die IP per HMAC-SHA256 mit Pepper (kein Klartext)", () => {
|
|
const hashed = hashIp("203.0.113.10");
|
|
expect(hashed).toBe(createHmac("sha256", "test-pepper").update("203.0.113.10").digest("hex"));
|
|
expect(hashed).not.toContain("203.0.113.10");
|
|
expect(hashed).toMatch(/^[0-9a-f]{64}$/);
|
|
});
|
|
|
|
it("ist deterministisch und trennt verschiedene IPs", () => {
|
|
expect(hashIp("1.1.1.1")).toBe(hashIp("1.1.1.1"));
|
|
expect(hashIp("1.1.1.1")).not.toBe(hashIp("1.1.1.2"));
|
|
});
|
|
|
|
it("fällt ohne Pepper auf ungepepperten SHA-256 zurück (immer noch kein Klartext)", () => {
|
|
vi.mocked(loadWebConfig).mockReturnValue({ config: { ipGeo: {} } } as never);
|
|
const hashed = hashIp("203.0.113.10");
|
|
expect(hashed).toMatch(/^[0-9a-f]{64}$/);
|
|
expect(hashed).not.toContain("203.0.113.10");
|
|
});
|
|
});
|
|
|
|
describe("geoip.lookupCountry", () => {
|
|
beforeEach(() => __resetGeoipReaderForTests());
|
|
|
|
it("löst das Land auf und bevorzugt den deutschen Namen", async () => {
|
|
const reader = { get: () => ({ country: { iso_code: "DE", names: { de: "Deutschland", en: "Germany" } } }) };
|
|
await expect(lookupCountry("203.0.113.10", reader)).resolves.toEqual({
|
|
countryCode: "DE",
|
|
countryName: "Deutschland",
|
|
});
|
|
});
|
|
|
|
it("fällt auf den englischen Namen zurück, wenn kein deutscher vorhanden ist", async () => {
|
|
const reader = { get: () => ({ country: { iso_code: "US", names: { en: "United States" } } }) };
|
|
await expect(lookupCountry("203.0.113.10", reader)).resolves.toEqual({
|
|
countryCode: "US",
|
|
countryName: "United States",
|
|
});
|
|
});
|
|
|
|
it("liefert null, wenn kein Land gefunden wird (Stub)", async () => {
|
|
await expect(lookupCountry("203.0.113.10", { get: () => null })).resolves.toBeNull();
|
|
});
|
|
});
|