commit cb1beccfe021351323ce032257941972638820e3
parent f3aa21b26baf2d0e4aa463f0886012eb1031cec7
Author: Sebastian <sebasjm@gmail.com>
Date: Wed, 22 Oct 2025 13:49:19 -0300
add missing payto helper unit test
Diffstat:
3 files changed, 125 insertions(+), 14 deletions(-)
diff --git a/packages/taler-util/src/payto.test.ts b/packages/taler-util/src/payto.test.ts
@@ -18,6 +18,7 @@ import test from "ava";
import {
PaytoString,
+ Paytos,
addPaytoQueryParams,
parsePaytoUri,
stringifyPaytoUri,
diff --git a/packages/taler-util/src/payto.ts b/packages/taler-util/src/payto.ts
@@ -150,7 +150,12 @@ export namespace Paytos {
export interface PaytoTalerBank extends PaytoGeneric {
targetType: PaytoType.TalerBank;
- host: HostPortPath;
+ /**
+ * this is kept to keep compatiblity with old parser
+ * @deprecated use URL
+ */
+ host: string;
+ url: HostPortPath;
account: string;
}
@@ -250,7 +255,7 @@ export namespace Paytos {
try {
// https://url.spec.whatwg.org/#concept-basic-url-parser
if (path === undefined) {
- path = ""
+ path = "";
}
if (!path.endsWith("/")) {
path = path + "/";
@@ -262,15 +267,24 @@ export namespace Paytos {
url.hash = "";
return url.href as HostPortPath;
} catch (e) {
- console.log(e)
+ console.log(e);
return undefined;
}
}
+ function withoutScheme(h: HostPortPath): HostPortPath {
+ return (
+ h.startsWith("http://")
+ ? h.substring(7)
+ : h.startsWith("https://")
+ ? h.substring(8)
+ : h
+ ) as HostPortPath;
+ }
/**
* Same as `parseHostPortPath2` but only takes one string.
* This should be the definitive signature.
* https://bugs.gnunet.org/view.php?id=10467
- *
+ *
* @param hostnameAndPath
* @returns
*/
@@ -374,15 +388,16 @@ export namespace Paytos {
reservePub: Uint8Array,
params: Record<string, string> = {},
): PaytoTalerReserve {
+ const path = withoutScheme(exchange);
const pub = encodeCrock(reservePub);
return {
targetType: PaytoType.TalerReserve,
exchange,
reservePub,
params,
- normalizedPath: `${exchange.toLocaleLowerCase()}/${pub}`,
- fullPath: `${exchange}/${pub}`,
- displayName: `${exchange}@${pub}`,
+ normalizedPath: `${path.toLocaleLowerCase()}${pub}`,
+ fullPath: `${path}${pub}`,
+ displayName: `${path}@${pub}`,
};
}
export function createTalerReserveHttp(
@@ -390,30 +405,34 @@ export namespace Paytos {
reservePub: Uint8Array,
params: Record<string, string> = {},
): PaytoTalerReserveHttp {
+ const path = withoutScheme(exchange);
const pub = encodeCrock(reservePub);
return {
targetType: PaytoType.TalerReserveHttp,
exchange,
reservePub,
params,
- normalizedPath: `${exchange.toLocaleLowerCase()}/${pub}`,
- fullPath: `${exchange}/${pub}`,
- displayName: `${exchange}@${pub}`,
+ normalizedPath: `${path.toLocaleLowerCase()}${pub}`,
+ fullPath: `${path}${pub}`,
+ displayName: `${path}@${pub}`,
};
}
export function createTalerBank(
- host: HostPortPath,
+ url: HostPortPath,
account: string,
params: Record<string, string> = {},
): PaytoTalerBank {
+ const path = withoutScheme(url);
+ const host = path.endsWith("/") ? path.substring(0, path.length - 1) : path;
return {
targetType: PaytoType.TalerBank,
host,
+ url,
account,
params,
- normalizedPath: `${host.toLocaleLowerCase()}/${account}`,
- fullPath: `${host}/${account}`,
- displayName: `${account}@${host}`,
+ normalizedPath: `${path.toLocaleLowerCase()}${account}`,
+ fullPath: `${path}${account}`,
+ displayName: `${account}@${url}`,
};
}
diff --git a/packages/taler-util/src/paytos.test.ts b/packages/taler-util/src/paytos.test.ts
@@ -0,0 +1,91 @@
+/*
+ This file is part of GNU Taler
+ (C) 2019 GNUnet e.V.
+
+ 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 test from "ava";
+
+import { HostPortPath, PaytoType, Paytos } from "./payto.js";
+import { succeedOrThrow } from "./index.js";
+
+test("basic payto parsing", (t) => {
+ const r1 = Paytos.fromString("https://example.com/");
+ t.is(r1.type, "fail");
+
+ const r2 = Paytos.fromString("payto:blabla");
+ t.is(r2.type, "fail");
+
+ // this doesn't work because x-taler-bank requires host and account
+ const r3 = Paytos.fromString("payto:://x-taler-bank/12");
+ t.is(r3.type, "fail");
+
+ const r4 = Paytos.fromString("payto://x-taler-bank/host/account");
+ if (r4.type === "fail") {
+ t.fail();
+ throw Error();
+ }
+ if (r4.body.targetType !== PaytoType.TalerBank) {
+ t.fail(r4.body.targetType);
+ throw Error();
+ }
+ t.is(r4.body.normalizedPath, "host/account");
+});
+
+test("basic x-taler-bank payto string", (t) => {
+ const result = succeedOrThrow(
+ Paytos.fromString("payto://x-taler-bank/bank.demo.taler.net/accountName"),
+ );
+
+ if (result.targetType !== PaytoType.TalerBank) {
+ t.fail();
+ throw Error();
+ }
+ t.is(result.normalizedPath, "bank.demo.taler.net/accountName");
+ t.is(result.host, "bank.demo.taler.net");
+ t.is(result.url, "https://bank.demo.taler.net/" as HostPortPath);
+ t.is(result.account, "accountName");
+});
+
+test("parsing payto and stringify again", (t) => {
+ const payto1 = "payto://iban/DE1231231231?reciever-name=John%20Doe";
+ t.is(
+ Paytos.toFullString(succeedOrThrow(Paytos.fromString(payto1))),
+ payto1 as Paytos.FullPaytoString,
+ );
+
+ const normalized = "payto://iban/de1231231231";
+ t.is(
+ Paytos.toNormalizedString(succeedOrThrow(Paytos.fromString(payto1))),
+ normalized as Paytos.NormalizedPaytoString,
+ );
+});
+test("parsing payto with % carh", (t) => {
+ const payto1 =
+ "payto://iban/DE7763544441436?receiver-name=Test%20123%2B-%24%25%5E%3Cem%3Ehi%3C%2Fem%3E" as Paytos.FullPaytoString;
+
+ t.is(Paytos.toFullString(succeedOrThrow(Paytos.fromString(payto1))), payto1);
+});
+
+test("adding payto query params", (t) => {
+ const payto1 =
+ "payto://iban/DE1231231231?receiver-name=John%20Doe" as Paytos.FullPaytoString;
+ const p = succeedOrThrow(Paytos.fromString(payto1));
+
+ p.params["foo"] = "42";
+
+ t.deepEqual(
+ Paytos.toFullString(p),
+ "payto://iban/DE1231231231?receiver-name=John%20Doe&foo=42",
+ );
+});