summaryrefslogtreecommitdiff
path: root/packages/taler-harness/src/integrationtests/test-payment-share.ts
diff options
context:
space:
mode:
Diffstat (limited to 'packages/taler-harness/src/integrationtests/test-payment-share.ts')
-rw-r--r--packages/taler-harness/src/integrationtests/test-payment-share.ts308
1 files changed, 308 insertions, 0 deletions
diff --git a/packages/taler-harness/src/integrationtests/test-payment-share.ts b/packages/taler-harness/src/integrationtests/test-payment-share.ts
new file mode 100644
index 000000000..141faa81e
--- /dev/null
+++ b/packages/taler-harness/src/integrationtests/test-payment-share.ts
@@ -0,0 +1,308 @@
+/*
+ This file is part of GNU Taler
+ (C) 2020 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 {
+ ConfirmPayResultType,
+ MerchantApiClient,
+ NotificationType,
+ PreparePayResultType,
+ j2s,
+} from "@gnu-taler/taler-util";
+import { WalletApiOperation } from "@gnu-taler/taler-wallet-core";
+import { GlobalTestState } from "../harness/harness.js";
+import {
+ createSimpleTestkudosEnvironmentV2,
+ createWalletDaemonWithClient,
+ withdrawViaBankV2,
+} from "../harness/helpers.js";
+
+/**
+ * Run test for basic, bank-integrated withdrawal and payment.
+ */
+export async function runPaymentShareTest(t: GlobalTestState) {
+ // Set up test environment
+ const {
+ walletClient: firstWallet,
+ bank,
+ exchange,
+ merchant,
+ } = await createSimpleTestkudosEnvironmentV2(t);
+
+ const merchantClient = new MerchantApiClient(merchant.makeInstanceBaseUrl());
+
+ // Withdraw digital cash into the wallet.
+ await withdrawViaBankV2(t, {
+ walletClient: firstWallet,
+ bank,
+ exchange,
+ amount: "TESTKUDOS:20",
+ });
+ await firstWallet.call(WalletApiOperation.TestingWaitTransactionsFinal, {});
+
+ const { walletClient: secondWallet } = await createWalletDaemonWithClient(t, {
+ name: "wallet2",
+ });
+
+ await withdrawViaBankV2(t, {
+ walletClient: secondWallet,
+ bank,
+ exchange,
+ amount: "TESTKUDOS:20",
+ });
+ await secondWallet.call(WalletApiOperation.TestingWaitTransactionsFinal, {});
+
+ {
+ const first = await firstWallet.call(WalletApiOperation.GetBalances, {});
+ const second = await secondWallet.call(WalletApiOperation.GetBalances, {});
+ t.assertAmountEquals(first.balances[0].available, "TESTKUDOS:19.53");
+ t.assertAmountEquals(second.balances[0].available, "TESTKUDOS:19.53");
+ }
+
+ t.logStep("setup-done");
+
+ // create two orders to pay
+ async function createOrder(amount: string) {
+ const order = {
+ summary: "Buy me!",
+ amount,
+ fulfillment_url: "taler://fulfillment-success/thx",
+ };
+
+ const args = { order };
+
+ const orderResp = await merchantClient.createOrder({
+ order: args.order,
+ });
+
+ const orderStatus = await merchantClient.queryPrivateOrderStatus({
+ orderId: orderResp.order_id,
+ });
+
+ t.assertTrue(orderStatus.order_status === "unpaid");
+ return { id: orderResp.order_id, uri: orderStatus.taler_pay_uri };
+ }
+
+ t.logStep("orders-created");
+
+ /**
+ * Case 1:
+ * - Claim with first wallet and pay in the second wallet.
+ * - First wallet should be notified.
+ */
+ {
+ const order = await createOrder("TESTKUDOS:5");
+ // Claim the order with the first wallet
+ const claimFirstWallet = await firstWallet.call(
+ WalletApiOperation.PreparePayForUri,
+ { talerPayUri: order.uri },
+ );
+
+ t.assertTrue(
+ claimFirstWallet.status === PreparePayResultType.PaymentPossible,
+ );
+
+ t.logStep("w1-payment-possible");
+
+ // share order from the first wallet
+ const { privatePayUri } = await firstWallet.call(
+ WalletApiOperation.SharePayment,
+ {
+ merchantBaseUrl: merchant.makeInstanceBaseUrl(),
+ orderId: order.id,
+ },
+ );
+
+ t.logStep("w1-payment-shared");
+
+ // claim from the second wallet
+ const claimSecondWallet = await secondWallet.call(
+ WalletApiOperation.PreparePayForUri,
+ { talerPayUri: privatePayUri },
+ );
+
+ t.assertTrue(
+ claimSecondWallet.status === PreparePayResultType.PaymentPossible,
+ );
+
+ t.logStep("w2-claimed");
+
+ // pay from the second wallet
+ const r2 = await secondWallet.call(WalletApiOperation.ConfirmPay, {
+ transactionId: claimSecondWallet.transactionId,
+ });
+
+ t.assertTrue(r2.type === ConfirmPayResultType.Done);
+
+ t.logStep("w2-confirmed");
+
+ // Wait for refresh to settle before we do checks
+ await secondWallet.call(
+ WalletApiOperation.TestingWaitTransactionsFinal,
+ {},
+ );
+
+ t.logStep("w2-refresh-settled");
+
+ {
+ const first = await firstWallet.call(WalletApiOperation.GetBalances, {});
+ const second = await secondWallet.call(
+ WalletApiOperation.GetBalances,
+ {},
+ );
+ t.assertAmountEquals(first.balances[0].available, "TESTKUDOS:19.53");
+ t.assertAmountEquals(second.balances[0].available, "TESTKUDOS:14.23");
+ }
+
+ t.logStep("wait-for-payment");
+ // firstWallet.waitForNotificationCond(n =>
+ // n.type === NotificationType.TransactionStateTransition &&
+ // n.transactionId === claimFirstWallet.transactionId
+ // )
+ // Claim the order with the first wallet
+ const claimFirstWalletAgain = await firstWallet.call(
+ WalletApiOperation.PreparePayForUri,
+ { talerPayUri: order.uri },
+ );
+
+ t.assertTrue(
+ claimFirstWalletAgain.status === PreparePayResultType.AlreadyConfirmed,
+ );
+ t.assertTrue( claimFirstWalletAgain.paid );
+
+ t.logStep("w1-prepared-again");
+
+ const r1 = await firstWallet.call(WalletApiOperation.ConfirmPay, {
+ transactionId: claimFirstWallet.transactionId,
+ });
+
+ //t.assertTrue(r1.type === ConfirmPayResultType.Pending);
+
+ t.logStep("w1-confirmed-shared");
+
+ await firstWallet.call(
+ WalletApiOperation.TestingWaitTransactionsFinal,
+ {},
+ );
+
+ await secondWallet.call(
+ WalletApiOperation.TestingWaitTransactionsFinal,
+ {},
+ );
+
+ /**
+ * only the second wallet balance was affected
+ */
+ {
+ const first = await firstWallet.call(WalletApiOperation.GetBalances, {});
+ const second = await secondWallet.call(
+ WalletApiOperation.GetBalances,
+ {},
+ );
+ t.assertAmountEquals(first.balances[0].available, "TESTKUDOS:19.53");
+ t.assertAmountEquals(second.balances[0].available, "TESTKUDOS:14.23");
+ }
+ }
+
+ t.logStep("first-case-done");
+
+ /**
+ * Case 2:
+ * - Claim with first wallet and share with the second wallet
+ * - Pay with the first wallet, second wallet should be notified
+ */
+ {
+ const order = await createOrder("TESTKUDOS:3");
+ // Claim the order with the first wallet
+ const claimFirstWallet = await firstWallet.call(
+ WalletApiOperation.PreparePayForUri,
+ { talerPayUri: order.uri },
+ );
+
+ t.assertTrue(
+ claimFirstWallet.status === PreparePayResultType.PaymentPossible,
+ );
+
+ t.logStep("case2-w1-claimed");
+
+ // share order from the first wallet
+ const { privatePayUri } = await firstWallet.call(
+ WalletApiOperation.SharePayment,
+ {
+ merchantBaseUrl: merchant.makeInstanceBaseUrl(),
+ orderId: order.id,
+ },
+ );
+
+ t.logStep("case2-w1-shared");
+
+ // claim from the second wallet
+ const claimSecondWallet = await secondWallet.call(
+ WalletApiOperation.PreparePayForUri,
+ { talerPayUri: privatePayUri },
+ );
+
+ t.logStep("case2-w2-prepared");
+
+ t.assertTrue(
+ claimSecondWallet.status === PreparePayResultType.PaymentPossible,
+ );
+
+ // pay from the first wallet
+ const r2 = await firstWallet.call(WalletApiOperation.ConfirmPay, {
+ transactionId: claimFirstWallet.transactionId,
+ });
+
+ t.assertTrue(r2.type === ConfirmPayResultType.Done);
+
+ // Wait for refreshes to settle before doing checks
+ await firstWallet.call(WalletApiOperation.TestingWaitTransactionsFinal, {});
+
+ /**
+ * only the first wallet balance was affected
+ */
+ const bal1 = await firstWallet.call(WalletApiOperation.GetBalances, {});
+ const bal2 = await secondWallet.call(WalletApiOperation.GetBalances, {});
+ t.assertAmountEquals(bal1.balances[0].available, "TESTKUDOS:16.18");
+ t.assertAmountEquals(bal2.balances[0].available, "TESTKUDOS:14.23");
+
+ t.logStep("wait-for-payment");
+ // secondWallet.waitForNotificationCond(n =>
+ // n.type === NotificationType.TransactionStateTransition &&
+ // n.transactionId === claimSecondWallet.transactionId
+ // )
+
+ // Claim the order with the first wallet
+ const claimSecondWalletAgain = await secondWallet.call(
+ WalletApiOperation.PreparePayForUri,
+ { talerPayUri: order.uri },
+ );
+
+ t.assertTrue(
+ claimSecondWalletAgain.status === PreparePayResultType.AlreadyConfirmed,
+ );
+ t.assertTrue(
+ claimSecondWalletAgain.paid,
+ );
+
+ }
+
+ t.logStep("second-case-done");
+}
+
+runPaymentShareTest.suites = ["wallet"];