import { describe, expect, it } from "vitest"; import { DIAGNOSTIC_RULES, evaluateDiagnostics } from "./diagnostics"; const okMeta: Record = { status: "ok", errors: [] }; const baseDns: Record = { mx: [], spf: [], dmarc: [], _meta: okMeta }; const baseTls: Record = { authorized: true, hostnameValid: true, daysRemaining: 90, _meta: okMeta }; const secureHeaders: Record = { "strict-transport-security": "max-age=31536000; includeSubDomains", "content-security-policy": "default-src 'self'; object-src 'none'; base-uri 'self'", "x-content-type-options": "nosniff", "referrer-policy": "strict-origin-when-cross-origin", "x-frame-options": "DENY", }; const baseHttp: Record = { http: { status: 301 }, httpRedirectsToHttps: true, httpsChain: [{ status: 200, headers: secureHeaders }], _meta: okMeta }; function ids(dns: Record = baseDns, tls: Record = baseTls, http: Record = baseHttp) { return evaluateDiagnostics(dns, tls, http).map((finding) => finding.id); } describe("diagnostics", () => { it("has unique stable rule identifiers", () => { const ids = DIAGNOSTIC_RULES.map((rule) => rule.id); expect(new Set(ids).size).toBe(ids.length); }); it("finds mail and HTTP posture gaps deterministically", () => { const found = ids( { mx: [{ exchange: "mail.example.com" }], spf: [], dmarc: [], _meta: okMeta }, baseTls, { http: { status: 200 }, httpRedirectsToHttps: false, httpsChain: [{ status: 200, headers: { "strict-transport-security": null, "content-security-policy": null, "x-content-type-options": null } }], _meta: okMeta }, ); expect(found).toEqual([ "http.hsts_missing", "http.csp_missing", "http.redirect", "dns.dmarc_missing", "dns.spf_missing", "http.frame_protection", "http.nosniff_missing", "http.referrer_policy_missing", ]); }); it("keeps partial collectors informational and does not deduct missing evidence", () => { const findings = evaluateDiagnostics( { mx: [{ exchange: "mail.example.com" }], spf: [], dmarc: [], _meta: { status: "partial", errors: [{ probe: "TXT", message: "timeout" }, { probe: "DMARC", message: "timeout" }] } }, { authorized: true, hostnameValid: true, daysRemaining: 90, _meta: okMeta }, { http: { error: "timeout" }, httpRedirectsToHttps: false, httpsChain: [{ error: "timeout" }], _meta: { status: "partial", errors: [{ probe: "HTTPS", message: "timeout" }] } }, ); expect(findings.map((finding) => finding.id)).toEqual(["collector.dns_partial", "collector.http_partial"]); expect(findings.every((finding) => finding.scoreImpact === 0)).toBe(true); }); it("does not score headers when the HTTPS chain has no terminal response", () => { expect(ids(baseDns, baseTls, { http: { status: 301 }, httpRedirectsToHttps: true, httpsChain: [{ status: 302, location: "/next", headers: {} }, { url: "/next", error: "redirect failed" }], _meta: { status: "partial", errors: [{ probe: "HTTPS", message: "redirect failed" }] } })).toEqual(["collector.http_partial"]); }); it("deduplicates the generic TLS verification penalty when specific causes exist", () => { const found = ids(baseDns, { authorized: false, authorizationError: "CERT_HAS_EXPIRED", hostnameValid: false, hostnameError: "hostname mismatch", daysRemaining: -2, _meta: okMeta }, baseHttp); expect(found).toContain("tls.expired"); expect(found).toContain("tls.hostname"); expect(found).not.toContain("tls.verification"); }); it("reports an untrusted issuer when no more specific TLS cause is present", () => { expect(ids(baseDns, { authorized: false, authorizationError: "UNABLE_TO_VERIFY_LEAF_SIGNATURE", hostnameValid: true, daysRemaining: 90, _meta: okMeta }, baseHttp)).toContain("tls.verification"); }); it("reports malformed certificate validity dates without adding generic trust noise", () => { const found = ids(baseDns, { authorized: false, authorizationError: "CERT_INVALID", hostnameValid: true, validityDatesValid: false, _meta: okMeta }, baseHttp); expect(found).toContain("tls.validity_dates"); expect(found).not.toContain("tls.verification"); }); it("does not score expiry states from an incoherent certificate window", () => { const found = ids(baseDns, { authorized: true, hostnameValid: true, validFrom: "Jul 02 00:00:00 2026 GMT", validTo: "Jul 01 00:00:00 2026 GMT", validityDatesValid: false, notYetValid: true, daysRemaining: -1, _meta: okMeta, }, baseHttp); expect(found).toContain("tls.validity_dates"); expect(found).not.toContain("tls.expired"); expect(found).not.toContain("tls.not_yet_valid"); expect(found).not.toContain("tls.expiry_critical"); expect(found).not.toContain("tls.expiry_warning"); }); it("reports HTTPS downgrades and loops as findings", () => { const downgrade = ids(baseDns, baseTls, { ...baseHttp, httpsDowngrade: true, httpsChain: [{ status: 302, location: "http://example.com/", headers: secureHeaders }, { error: "HTTPS redirect downgrade is not allowed.", code: "HTTPS_DOWNGRADE" }], _meta: { status: "partial", errors: [{ probe: "HTTPS", message: "downgrade" }] } }); expect(downgrade).toContain("http.https_downgrade"); const loop = ids(baseDns, baseTls, { ...baseHttp, httpsChain: [{ status: 302, location: "/", headers: secureHeaders }, { error: "Redirect loop detected.", code: "REDIRECT_LOOP" }], _meta: { status: "partial", errors: [{ probe: "HTTPS", message: "loop" }] } }); expect(loop).toContain("http.redirect_loop"); }); it("surfaces redirects rejected by the target policy", () => { expect(ids(baseDns, baseTls, { ...baseHttp, httpsChain: [{ status: 302, location: "http://127.0.0.1/", headers: secureHeaders }, { code: "REDIRECT_TARGET_BLOCKED", error: "Target rejected" }], _meta: { status: "partial", errors: [{ probe: "HTTPS", message: "target blocked" }] }, })).toContain("http.redirect_blocked"); }); it("classifies terminal HTTP status without using a green status", () => { expect(ids(baseDns, baseTls, { ...baseHttp, httpsChain: [{ status: 404, headers: secureHeaders }] })).toContain("http.terminal_client_error"); expect(ids(baseDns, baseTls, { ...baseHttp, httpsChain: [{ status: 503, headers: secureHeaders }] })).toContain("http.terminal_server_error"); }); it("evaluates HSTS, CSP and nosniff values rather than presence alone", () => { const findings = ids(baseDns, baseTls, { ...baseHttp, httpsChain: [{ status: 200, headers: { ...secureHeaders, "strict-transport-security": "max-age=0", "content-security-policy": "default-src * 'unsafe-eval'", "x-content-type-options": "text/plain" } }] }); expect(findings).toContain("http.hsts_disabled"); expect(findings).toContain("http.csp_weak"); expect(findings).toContain("http.nosniff_invalid"); }); it("does not require mail authentication for an explicit null MX", () => { const findings = ids({ mx: [{ exchange: ".", priority: 0 }], spf: [], dmarc: [], _meta: okMeta }, baseTls, baseHttp); expect(findings).not.toContain("dns.spf_missing"); expect(findings).not.toContain("dns.dmarc_missing"); }); it("reports multiple SPF records as a distinct configuration error", () => { expect(ids({ mx: [{ exchange: "mail.example.com" }], spf: ["v=spf1 -all", "v=spf1 ~all"], dmarc: [], _meta: okMeta }, baseTls, baseHttp)).toContain("dns.spf_multiple"); }); it("reports malformed MX answers while preserving null-MX semantics", () => { expect(ids({ mx: [{ exchange: "", priority: 10 }], spf: [], dmarc: [], _meta: okMeta }, baseTls, baseHttp)).toContain("dns.mx_invalid"); expect(ids({ mx: [{ exchange: "", priority: 0 }], spf: [], dmarc: [], _meta: okMeta }, baseTls, baseHttp)).not.toContain("dns.mx_invalid"); expect(ids({ mx: [{ exchange: ".", priority: 0 }], spf: [], dmarc: [], _meta: okMeta }, baseTls, baseHttp)).not.toContain("dns.mx_invalid"); }); it("recognizes DMARC pct=0 as non-enforcing without mislabeling the record invalid", () => { const findings = ids({ mx: [{ exchange: "mail.example.com" }], spf: ["v=spf1 -all"], dmarc: ["v=DMARC1; p=reject; pct=0"], _meta: okMeta }, baseTls, baseHttp); expect(findings).toContain("dns.dmarc_monitor"); expect(findings).not.toContain("dns.dmarc_invalid"); }); });