import { test } from "node:test"; import assert from "node:assert/strict"; import { fatalBrokerReason, PinMismatchError } from "../src/broker-nats.ts"; // novox/hq issue 058 (and its review): serve mode retries a broker that is not up yet, but must // give up at once on a failure waiting cannot fix — otherwise a permanent fault loops for ever // disguised as "not reachable". This is the classifier that draws the line; the bed cannot test it // (it starts the consumer only after the broker is up), so it is proven here. test("a broker that is not up yet is retryable, not fatal", () => { for (const err of [ Object.assign(new Error("connect ECONNREFUSED 10.42.0.1:5671"), { code: "ECONNREFUSED" }), Object.assign(new Error("connect ETIMEDOUT"), { code: "ETIMEDOUT" }), Object.assign(new Error("getaddrinfo EAI_AGAIN anchor.internal"), { code: "EAI_AGAIN" }), new Error("timed out fetching the broker's certificate"), ]) { assert.equal(fatalBrokerReason(err), null, `should retry: ${(err as Error).message}`); } }); test("a certificate that does not match the pin is fatal, by type not by message", () => { // Typed, so rewording the message cannot turn an impostor back into an infinite retry. assert.notEqual(fatalBrokerReason(new PinMismatchError("anything at all")), null); // A plain Error with pin-ish words is NOT treated as the pin case — only the type is. assert.equal(fatalBrokerReason(new Error("the pinned value was fine")), null); }); test("a malformed broker URL is fatal — it never parses on the next try", () => { assert.notEqual(fatalBrokerReason(Object.assign(new Error("Invalid URL"), { code: "ERR_INVALID_URL" })), null); assert.notEqual(fatalBrokerReason(new Error("Invalid URL: not-a-url")), null); }); test("a refused login is fatal — a wrong or revoked credential, not an absent broker", () => { // The bus refuses a login in its own words; each is final, because the next try says the same. for (const msg of ["Authorization Violation", "nats: user authentication expired", "Permissions Violation for Subscription to \"x\""]) { assert.notEqual(fatalBrokerReason(new Error(msg)), null, `should be fatal: ${msg}`); } }); test("a non-Error value does not crash the classifier", () => { assert.equal(fatalBrokerReason("just a string"), null); assert.equal(fatalBrokerReason(undefined), null); });