taler-typescript-core

Wallet core logic and WebUIs for various components
Log | Files | Refs | Submodules | README | LICENSE

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:
Apackages/taler-util/src/http-client/status-handling.test.ts | 98+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
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); +});