commit c05b51ff10c8ef4b82f6f22b7b1a1c7a79407d56
parent 0053ed49ae9f61d097a6d835345cd185603e1f03
Author: Florian Dold <dold@taler.net>
Date: Tue, 21 Jul 2026 11:12:10 +0200
util: test corebank status and parameter handling against the spec
Diffstat:
1 file changed, 98 insertions(+), 0 deletions(-)
diff --git a/packages/taler-util/src/http-client/status-handling.test.ts b/packages/taler-util/src/http-client/status-handling.test.ts
@@ -0,0 +1,98 @@
+/*
+ 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 {
+ HeadersImpl,
+ HttpRequestLibrary,
+ HttpRequestOptions,
+ HttpResponse,
+} from "../http-common.js";
+import { Amounts } from "../amounts.js";
+import { TalerErrorCode } from "../taler-error-codes.js";
+import { MonitorTimeframeParam } from "../types-taler-corebank.js";
+import { TalerBankConversionHttpClient } from "./bank-conversion.js";
+import { TalerCoreBankHttpClient } from "./bank-core.js";
+
+/**
+ * Answers every request with a canned status and body, recording the URL.
+ */
+class StubHttpLib implements HttpRequestLibrary {
+ lastUrl: string | undefined;
+ constructor(
+ private status: number,
+ private body: unknown = {},
+ ) {}
+ async fetch(url: string, opt?: HttpRequestOptions): Promise<HttpResponse> {
+ this.lastUrl ??= url;
+ const headers = new HeadersImpl();
+ headers.set("content-type", "application/json");
+ const body = this.body;
+ const status = this.status;
+ return {
+ requestUrl: url,
+ requestMethod: opt?.method ?? "GET",
+ status,
+ headers: headers as any,
+ async json() {
+ return body;
+ },
+ async text() {
+ return JSON.stringify(body);
+ },
+ async bytes() {
+ return new TextEncoder().encode(JSON.stringify(body));
+ },
+ };
+ }
+}
+
+test("an unknown corebank account is not an empty token list", async (t) => {
+ // 404 means the base URL is wrong or the account is gone. Reporting it as
+ // a successful empty list makes a misconfigured bank indistinguishable from
+ // an account that simply has no tokens.
+ const lib = new StubHttpLib(404, { code: 5108, hint: "unknown account" });
+ const client = new TalerCoreBankHttpClient("https://bank.example/api/", lib);
+ const res = await client.getAccessTokenList("alice", "tok" as any);
+ assert.notStrictEqual(res.type, "ok");
+});
+
+test("the monitor timeframe is sent even for the first enum member", async (t) => {
+ const lib = new StubHttpLib(200, {});
+ const client = new TalerCoreBankHttpClient("https://bank.example/api/", lib);
+ await client
+ .getMonitor("tok" as any, { timeframe: MonitorTimeframeParam.hour })
+ .catch(() => undefined);
+ assert.ok(lib.lastUrl !== undefined);
+ assert.ok(
+ lib.lastUrl!.includes("timeframe=hour"),
+ `timeframe dropped: ${lib.lastUrl}`,
+ );
+});
+
+test("the cash-out rate reports the Taler error code, like the cash-in rate", async (t) => {
+ const body = { code: TalerErrorCode.GENERIC_PARAMETER_MALFORMED, hint: "x" };
+ const cashout = new TalerBankConversionHttpClient(
+ "https://bank.example/conversion-info/",
+ new StubHttpLib(400, body),
+ );
+ const res = await cashout.getCashoutRate(undefined, {
+ debit: Amounts.parseOrThrow("KUDOS:1"),
+ });
+ assert.strictEqual(res.type, "fail");
+ assert.strictEqual(res.case, TalerErrorCode.GENERIC_PARAMETER_MALFORMED);
+});