commit 221f3e6b2da1f491fc15a88f324fb155227efca6
parent 84976f692f0a6df7b302d69c872ac2d60b09ae2d
Author: Florian Dold <dold@taler.net>
Date: Tue, 21 Jul 2026 10:56:11 +0200
util: test error responses whose JSON body is null
Diffstat:
1 file changed, 77 insertions(+), 0 deletions(-)
diff --git a/packages/taler-util/src/http-common.test.ts b/packages/taler-util/src/http-common.test.ts
@@ -0,0 +1,77 @@
+/*
+ This file is part of GNU Taler
+ (C) 2026 Taler Systems S.A.
+
+ GNU Taler is free software; you can redistribute it and/or modify it under the
+ terms of the GNU General Public License as published by the Free Software
+ Foundation; either version 3, or (at your option) any later version.
+
+ GNU Taler is distributed in the hope that it will be useful, but WITHOUT ANY
+ WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR
+ A PARTICULAR PURPOSE. See the GNU General Public License for more details.
+
+ You should have received a copy of the GNU General Public License along with
+ GNU Taler; see the file COPYING. If not, see <http://www.gnu.org/licenses/>
+ */
+
+import assert from "node:assert";
+import { test } from "node:test";
+import { TalerError } from "./errors.js";
+import {
+ Headers,
+ HeadersImpl,
+ HttpResponse,
+ readTalerErrorResponse,
+ readUnexpectedResponseDetails,
+} from "./http-common.js";
+import { TalerErrorCode } from "./taler-error-codes.js";
+
+function jsonResponse(body: string, status = 400): HttpResponse {
+ const headers = new HeadersImpl();
+ headers.set("content-type", "application/json");
+ return {
+ requestUrl: "https://exchange.example/keys",
+ requestMethod: "GET",
+ status,
+ headers: headers as Headers,
+ async json() {
+ return JSON.parse(body);
+ },
+ async text() {
+ return body;
+ },
+ async bytes() {
+ return new TextEncoder().encode(body);
+ },
+ };
+}
+
+test("a JSON null error body is reported as a malformed response", async (t) => {
+ // "null" is valid JSON, so the parse succeeds and the code then reads a
+ // property off it. That must not escape as a bare TypeError, which carries
+ // none of the request context.
+ await assert.rejects(
+ () => readTalerErrorResponse(jsonResponse("null")),
+ (e: unknown) => {
+ assert.ok(e instanceof TalerError, `${e}`);
+ assert.strictEqual(
+ e.errorDetail.code,
+ TalerErrorCode.WALLET_RECEIVED_MALFORMED_RESPONSE,
+ );
+ return true;
+ },
+ );
+ const detail = await readUnexpectedResponseDetails(jsonResponse("null"));
+ assert.strictEqual(
+ detail.code,
+ TalerErrorCode.WALLET_RECEIVED_MALFORMED_RESPONSE,
+ );
+});
+
+test("a well-formed error body is returned unchanged", async (t) => {
+ const detail = await readTalerErrorResponse(
+ jsonResponse(JSON.stringify({ code: 1234, hint: "nope" })),
+ );
+ assert.strictEqual(detail.code, 1234);
+ assert.strictEqual(detail.hint, "nope");
+});