commit 62888395efbf15bf74b16f5ad63def7bf1688f13
parent 4ea71a9400d39fa7f6aadd0c9ba7f2116a8b2990
Author: Florian Dold <dold@taler.net>
Date: Mon, 10 Aug 2026 11:22:22 +0200
harness: test withdrawal without exchange terms
Diffstat:
2 files changed, 92 insertions(+), 0 deletions(-)
diff --git a/packages/taler-harness/src/integrationtests/test-wallet-missing-tos.ts b/packages/taler-harness/src/integrationtests/test-wallet-missing-tos.ts
@@ -0,0 +1,90 @@
+/*
+ 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 {
+ ExchangeTosStatus,
+ TalerCorebankApiClient,
+ TransactionIdStr,
+ TransactionMajorState,
+ TransactionMinorState,
+} from "@gnu-taler/taler-util";
+import { WalletApiOperation } from "@gnu-taler/taler-wallet-core";
+import { createSimpleTestkudosEnvironmentV3 } from "../harness/environments.js";
+import { GlobalTestState } from "../harness/harness.js";
+
+/**
+ * Verify that an exchange without configured terms does not block the wallet.
+ */
+export async function runWalletMissingTosTest(t: GlobalTestState) {
+ const { walletClient, bankClient, exchange } =
+ await createSimpleTestkudosEnvironmentV3(t);
+
+ const user = await bankClient.createRandomBankUser();
+ const userBankClient = new TalerCorebankApiClient(bankClient.baseUrl);
+ userBankClient.setAuth(user);
+ const amount = "TESTKUDOS:10";
+ const wop = await userBankClient.createWithdrawalOperation(
+ user.username,
+ amount,
+ );
+
+ await walletClient.call(WalletApiOperation.GetWithdrawalDetailsForUri, {
+ talerWithdrawUri: wop.taler_withdraw_uri,
+ });
+ const prepareResp = await walletClient.call(
+ WalletApiOperation.PrepareBankIntegratedWithdrawal,
+ { talerWithdrawUri: wop.taler_withdraw_uri },
+ );
+
+ const tos = await walletClient.call(WalletApiOperation.GetExchangeTos, {
+ exchangeBaseUrl: exchange.baseUrl,
+ });
+ t.assertDeepEqual(tos.tosStatus, ExchangeTosStatus.MissingTos);
+
+ // A stale UI might still ask wallet-core to accept. The request must
+ // return without changing the missing-ToS state or blocking the operation.
+ await walletClient.call(WalletApiOperation.SetExchangeTosAccepted, {
+ exchangeBaseUrl: exchange.baseUrl,
+ });
+ const exchangeEntry = await walletClient.call(
+ WalletApiOperation.GetExchangeEntryByUrl,
+ { exchangeBaseUrl: exchange.baseUrl },
+ );
+ t.assertDeepEqual(exchangeEntry.tosStatus, ExchangeTosStatus.MissingTos);
+
+ await walletClient.call(WalletApiOperation.ConfirmWithdrawal, {
+ transactionId: prepareResp.transactionId,
+ amount,
+ exchangeBaseUrl: exchange.baseUrl,
+ });
+ await walletClient.call(WalletApiOperation.TestingWaitTransactionState, {
+ transactionId: prepareResp.transactionId as TransactionIdStr,
+ txState: {
+ major: TransactionMajorState.Pending,
+ minor: TransactionMinorState.BankConfirmTransfer,
+ },
+ });
+
+ await userBankClient.confirmWithdrawalOperation(user.username, {
+ withdrawalOperationId: wop.withdrawal_id,
+ });
+ await walletClient.call(WalletApiOperation.TestingWaitTransactionState, {
+ transactionId: prepareResp.transactionId as TransactionIdStr,
+ txState: { major: TransactionMajorState.Done },
+ });
+}
+
+runWalletMissingTosTest.suites = ["wallet"];
diff --git a/packages/taler-harness/src/integrationtests/testrunner.ts b/packages/taler-harness/src/integrationtests/testrunner.ts
@@ -225,6 +225,7 @@ import { runWalletExchangeUpdateTest } from "./test-wallet-exchange-update.js";
import { runWalletGenDbTest } from "./test-wallet-gendb.js";
import { runWalletInsufficientBalanceTest } from "./test-wallet-insufficient-balance.js";
import { runWalletMailboxBasicTest } from "./test-wallet-mailbox-basic.js";
+import { runWalletMissingTosTest } from "./test-wallet-missing-tos.js";
import { runWalletNetworkAvailabilityTest } from "./test-wallet-network-availability.js";
import { runWalletNotificationsTest } from "./test-wallet-notifications.js";
import { runWalletObservabilityTest } from "./test-wallet-observability.js";
@@ -347,6 +348,7 @@ const allTests: TestMainFunction[] = [
runWalletMailboxBasicTest,
runWalletDblessTest,
runWallettestingTest,
+ runWalletMissingTosTest,
runWithdrawalAbortBankTest,
runWithdrawalBadSuggestedExchangeTest,
runWithdrawalBankIntegratedTest,