commit f56bb45bf9e85586c121a8c020166d6340b51eae
parent 990479c9818c9650a869f0e8123b220df40bc43d
Author: Florian Dold <florian@dold.me>
Date: Thu, 25 Sep 2025 17:47:09 +0200
harness: add donau-multi test
Diffstat:
2 files changed, 279 insertions(+), 0 deletions(-)
diff --git a/packages/taler-harness/src/integrationtests/test-donau-multi.ts b/packages/taler-harness/src/integrationtests/test-donau-multi.ts
@@ -0,0 +1,277 @@
+/*
+ This file is part of GNU Taler
+ (C) 2020-2025 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/>
+ */
+
+/**
+ * Imports.
+ */
+import {
+ AccessToken,
+ ConfirmPayResultType,
+ DonauHttpClient,
+ Duration,
+ j2s,
+ MerchantContractOutputType,
+ MerchantContractVersion,
+ OrderOutputType,
+ OrderVersion,
+ PreparePayResultType,
+ succeedOrThrow,
+ TalerMerchantInstanceHttpClient,
+} from "@gnu-taler/taler-util";
+import { WalletApiOperation } from "@gnu-taler/taler-wallet-core";
+import { defaultCoinConfig } from "../harness/denomStructures.js";
+import {
+ createSimpleTestkudosEnvironmentV3,
+ withdrawViaBankV3,
+} from "../harness/environments.js";
+import { DonauService } from "../harness/harness-donau.js";
+import {
+ delayMs,
+ getTestHarnessPaytoForLabel,
+ GlobalTestState,
+} from "../harness/harness.js";
+
+export async function runDonauMultiTest(t: GlobalTestState) {
+ // Set up test environment
+
+ const {
+ walletClient,
+ bankClient,
+ exchange,
+ merchant,
+ merchantAdminAccessToken,
+ commonDb,
+ } = await createSimpleTestkudosEnvironmentV3(t, undefined, {
+ merchantUseDonau: true,
+ walletConfig: {
+ features: {
+ enableV1Contracts: true,
+ },
+ },
+ });
+
+ const wres = await withdrawViaBankV3(t, {
+ walletClient,
+ bankClient,
+ amount: "TESTKUDOS:100",
+ exchange,
+ });
+ await wres.withdrawalFinishedCond;
+
+ const donau = DonauService.create(t, {
+ currency: "TESTKUDOS",
+ database: commonDb.connStr,
+ httpPort: 8084,
+ name: "donau",
+ domain: "Bern",
+ });
+
+ donau.addCoinConfigList(defaultCoinConfig.map((x) => x("TESTKUDOS")));
+
+ await donau.start();
+
+ const merchantClient1 = new TalerMerchantInstanceHttpClient(
+ merchant.makeInstanceBaseUrl(),
+ );
+
+ const inst1 = succeedOrThrow(
+ await merchantClient1.getCurrentInstanceDetails(merchantAdminAccessToken),
+ );
+ const merchantPub1 = inst1.merchant_pub;
+
+ const donauClient = new DonauHttpClient(donau.baseUrl);
+
+ const currentYear = new Date().getFullYear();
+
+ const charityResp1 = succeedOrThrow(
+ await donauClient.createCharity("" as AccessToken, {
+ charity_pub: merchantPub1,
+ current_year: currentYear,
+ max_per_year: "TESTKUDOS:1000",
+ charity_name: "42",
+ receipts_to_date: "TESTKUDOS:0",
+ charity_url: merchant.makeInstanceBaseUrl(),
+ }),
+ );
+
+ const charityId1 = charityResp1["charity_id"];
+
+ succeedOrThrow(
+ await merchantClient1.postDonau({
+ body: {
+ charity_id: charityId1,
+ donau_url: donau.baseUrl,
+ },
+ token: merchantAdminAccessToken,
+ }),
+ );
+
+ // Second merchant instance with donau
+
+ const { accessToken: tok2 } = await merchant.addInstanceWithWireAccount(
+ {
+ id: "minst2",
+ name: "minst2",
+ paytoUris: [getTestHarnessPaytoForLabel("minst2")],
+ defaultWireTransferDelay: Duration.toTalerProtocolDuration(
+ Duration.fromSpec({ minutes: 1 }),
+ ),
+ },
+ { adminAccessToken: merchantAdminAccessToken },
+ );
+
+ const merchantClient2 = new TalerMerchantInstanceHttpClient(
+ merchant.makeInstanceBaseUrl("minst2"),
+ );
+
+ const inst2 = succeedOrThrow(
+ await merchantClient2.getCurrentInstanceDetails(tok2),
+ );
+ const merchantPub2 = inst2.merchant_pub;
+
+ console.log(`pub1: ${merchantPub1}`);
+ console.log(`pub2: ${merchantPub2}`);
+
+ const charityResp2 = succeedOrThrow(
+ await donauClient.createCharity("" as AccessToken, {
+ charity_pub: merchantPub2,
+ current_year: currentYear,
+ max_per_year: "TESTKUDOS:1000",
+ charity_name: "43",
+ receipts_to_date: "TESTKUDOS:0",
+ charity_url: merchant.makeInstanceBaseUrl("minst2"),
+ }),
+ );
+
+ const charityId2 = charityResp2["charity_id"];
+
+ succeedOrThrow(
+ await merchantClient2.postDonau({
+ body: {
+ charity_id: charityId2,
+ donau_url: donau.baseUrl,
+ },
+ token: tok2,
+ }),
+ );
+
+ // Wait for donaukeysupdate
+ // We don't use -t since it doesn't seem to work at the moment.
+ await delayMs(2000);
+
+ {
+ // Just test the GetDonau request (initial)
+ const getRes = await walletClient.call(WalletApiOperation.GetDonau, {});
+ t.assertDeepEqual(getRes.currentDonauInfo, undefined);
+ }
+
+ await walletClient.call(WalletApiOperation.SetDonau, {
+ donauBaseUrl: donau.baseUrl,
+ taxPayerId: "test-tax-payer",
+ });
+
+ {
+ // Just test the GetDonau request (after setting)
+ const getRes = await walletClient.call(WalletApiOperation.GetDonau, {});
+ t.assertTrue(getRes.currentDonauInfo != null);
+ t.assertDeepEqual(getRes.currentDonauInfo.donauBaseUrl, donau.baseUrl);
+ }
+
+ for (let i = 0; i < 3; i++) {
+ const orderResp = succeedOrThrow(
+ await merchantClient1.createOrder(merchantAdminAccessToken, {
+ order: {
+ version: OrderVersion.V1,
+ summary: "Test Donation",
+ choices: [
+ {
+ amount: "TESTKUDOS:9",
+ outputs: [
+ {
+ type: OrderOutputType.TaxReceipt,
+ amount: "TESTKUDOS:9",
+ donau_urls: [donau.baseUrl],
+ },
+ ],
+ },
+ ],
+ },
+ }),
+ );
+
+ console.log(`order resp: ${j2s(orderResp)}`);
+
+ let orderStatus = succeedOrThrow(
+ await merchantClient1.getOrderDetails(
+ merchantAdminAccessToken,
+ orderResp.order_id,
+ ),
+ );
+
+ t.assertTrue(orderStatus.order_status === "unpaid");
+
+ const preparePayResult = await walletClient.call(
+ WalletApiOperation.PreparePayForUri,
+ {
+ talerPayUri: orderStatus.taler_pay_uri,
+ },
+ );
+
+ console.log(`preparePayResult: ${j2s(preparePayResult)}`);
+
+ t.assertTrue(
+ preparePayResult.status === PreparePayResultType.ChoiceSelection,
+ );
+
+ t.assertDeepEqual(
+ preparePayResult.contractTerms.version,
+ MerchantContractVersion.V1,
+ );
+ const outTok = preparePayResult.contractTerms.choices[0].outputs[0];
+ t.assertDeepEqual(outTok.type, MerchantContractOutputType.TaxReceipt);
+
+ // t.assertTrue(!!outTok.amount);
+
+ // t.assertAmountEquals(outTok.amount, "TESTKUDOS:5");
+
+ const r2 = await walletClient.call(WalletApiOperation.ConfirmPay, {
+ transactionId: preparePayResult.transactionId,
+ choiceIndex: 0,
+ useDonau: true,
+ });
+
+ t.assertDeepEqual(r2.type, ConfirmPayResultType.Done);
+
+ // Check if payment was successful.
+
+ orderStatus = succeedOrThrow(
+ await merchantClient1.getOrderDetails(
+ merchantAdminAccessToken,
+ orderResp.order_id,
+ ),
+ );
+
+ t.assertDeepEqual(orderStatus.order_status, "paid");
+ }
+
+ const statements = await walletClient.call(
+ WalletApiOperation.GetDonauStatements,
+ {},
+ );
+ console.log(j2s(statements));
+}
+
+runDonauMultiTest.suites = ["donau"];
diff --git a/packages/taler-harness/src/integrationtests/testrunner.ts b/packages/taler-harness/src/integrationtests/testrunner.ts
@@ -54,6 +54,7 @@ import { runDepositTest } from "./test-deposit.js";
import { runDonauCharityManagementTest } from "./test-donau-charity-management.js";
import { runDonauCompatTest } from "./test-donau-compat.js";
import { runDonauMinusTTest } from "./test-donau-minus-t.js";
+import { runDonauMultiTest } from "./test-donau-multi.js";
import { runDonauTest } from "./test-donau.js";
import { runExchangeDepositTest } from "./test-exchange-deposit.js";
import { runExchangeKycAuthTest } from "./test-exchange-kyc-auth.js";
@@ -385,6 +386,7 @@ const allTests: TestMainFunction[] = [
runDonauTest,
runDonauMinusTTest,
runDonauCharityManagementTest,
+ runDonauMultiTest,
];
export interface TestRunSpec {