Files
HiveGrid-Wireframes/hivegrid-cloud/apps/web/app/modules/ipAddress/services/geoip.server.test.ts
T

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();
});
});