From f407ab202317c188085cce4df90c3e24da3d4e31 Mon Sep 17 00:00:00 2001 From: Sebastian Date: Mon, 3 Jul 2023 12:44:20 -0300 Subject: fix #7741 add integration test --- packages/taler-harness/src/harness/harness.ts | 47 ++-- packages/taler-harness/src/harness/helpers.ts | 20 +- .../src/integrationtests/test-payment-share.ts | 239 +++++++++++++++++++++ .../src/integrationtests/testrunner.ts | 2 + 4 files changed, 265 insertions(+), 43 deletions(-) create mode 100644 packages/taler-harness/src/integrationtests/test-payment-share.ts (limited to 'packages/taler-harness/src') diff --git a/packages/taler-harness/src/harness/harness.ts b/packages/taler-harness/src/harness/harness.ts index 1120eae84..940e4258a 100644 --- a/packages/taler-harness/src/harness/harness.ts +++ b/packages/taler-harness/src/harness/harness.ts @@ -28,6 +28,8 @@ import { AmountJson, Amounts, AmountString, + codecForMerchantOrderPrivateStatusResponse, + codecForMerchantPostOrderResponse, codecForMerchantReserveCreateConfirmation, Configuration, CoreApiResponse, @@ -39,28 +41,42 @@ import { hash, j2s, Logger, + MerchantInstancesResponse, + MerchantOrderPrivateStatusResponse, + MerchantPostOrderRequest, + MerchantPostOrderResponse, MerchantReserveCreateConfirmation, MerchantTemplateAddDetails, - NotificationType, parsePaytoUri, stringToBytes, TalerError, TalerProtocolDuration, - TransactionMajorState, + TipCreateConfirmation, + TipCreateRequest, + TippingReserveStatus, WalletNotification, } from "@gnu-taler/taler-util"; +import { + createPlatformHttpLib, + readSuccessResponseJsonOrThrow, +} from "@gnu-taler/taler-util/http"; import { BankApi, BankServiceHandle, HarnessExchangeBankAccount, - OpenedPromise, openPromise, - WalletApiOperation, WalletCoreApiClient, WalletCoreRequestType, WalletCoreResponseType, WalletOperations, } from "@gnu-taler/taler-wallet-core"; +import { + createRemoteWallet, + getClientFromRemoteWallet, + makeNotificationWaiter, + RemoteWallet, + WalletNotificationWaiter, +} from "@gnu-taler/taler-wallet-core/remote"; import { deepStrictEqual } from "assert"; import axiosImp, { AxiosError } from "axios"; import { ChildProcess, spawn } from "child_process"; @@ -72,29 +88,6 @@ import * as readline from "readline"; import { URL } from "url"; import { CoinConfig } from "./denomStructures.js"; import { LibeufinNexusApi, LibeufinSandboxApi } from "./libeufin-apis.js"; -import { - codecForMerchantOrderPrivateStatusResponse, - codecForMerchantPostOrderResponse, - MerchantInstancesResponse, - MerchantOrderPrivateStatusResponse, - MerchantPostOrderRequest, - MerchantPostOrderResponse, - TipCreateConfirmation, - TipCreateRequest, - TippingReserveStatus, -} from "@gnu-taler/taler-util"; -import { - createRemoteWallet, - getClientFromRemoteWallet, - makeNotificationWaiter, - RemoteWallet, - WalletNotificationWaiter, -} from "@gnu-taler/taler-wallet-core/remote"; -import { - createPlatformHttpLib, - readSuccessResponseJsonOrErrorCode, - readSuccessResponseJsonOrThrow, -} from "@gnu-taler/taler-util/http"; const logger = new Logger("harness.ts"); diff --git a/packages/taler-harness/src/harness/helpers.ts b/packages/taler-harness/src/harness/helpers.ts index 8c62aef37..3e91c8bd9 100644 --- a/packages/taler-harness/src/harness/helpers.ts +++ b/packages/taler-harness/src/harness/helpers.ts @@ -298,22 +298,10 @@ export async function createSimpleTestkudosEnvironmentV2( ), }); - const walletService = new WalletService(t, { - name: "wallet", - }); - await walletService.start(); - await walletService.pingUntilAvailable(); - - const walletClient = new WalletClient({ - unixPath: walletService.socketPath, - onNotification(n) { - console.log("got notification", n); - }, - }); - await walletClient.connect(); - await walletClient.client.call(WalletApiOperation.InitWallet, { - skipDefaults: true, - }); + const { walletClient, walletService } = await createWalletDaemonWithClient( + t, + { name: "wallet" }, + ); console.log("setup done!"); 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..2f853b91b --- /dev/null +++ b/packages/taler-harness/src/integrationtests/test-payment-share.ts @@ -0,0 +1,239 @@ +/* + 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 + */ + +/** + * Imports. + */ +import { WalletApiOperation } from "@gnu-taler/taler-wallet-core"; +import { GlobalTestState, MerchantPrivateApi } from "../harness/harness.js"; +import { + createSimpleTestkudosEnvironmentV2, + withdrawViaBankV2, + makeTestPaymentV2, + createWalletDaemonWithClient, +} from "../harness/helpers.js"; +import { + ConfirmPayResultType, + PreparePayResultType, + j2s, + parsePayUri, + stringifyPayUri, +} from "@gnu-taler/taler-util"; + +/** + * 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); + + // 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, {}); + + //create two orders to pay + async function createOrder(amount: string) { + const order = { + summary: "Buy me!", + amount, + fulfillment_url: "taler://fulfillment-success/thx", + }; + + const instance = "default"; + const args = { order }; + const auth = {}; + + const orderResp = await MerchantPrivateApi.createOrder( + merchant, + instance, + { + order: args.order, + }, + auth, + ); + + const orderStatus = await MerchantPrivateApi.queryPrivateOrderStatus( + merchant, + { + orderId: orderResp.order_id, + }, + auth, + ); + + t.assertTrue(orderStatus.order_status === "unpaid"); + return { id: orderResp.order_id, uri: orderStatus.taler_pay_uri }; + } + + /** + * FIRST CASE, create in first wallet and pay in the second wallet + * first wallet should not be able to continue + */ + { + 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, + ); + + //share order from the first wallet + const { privatePayUri } = await firstWallet.call( + WalletApiOperation.SharePayment, + { + merchantBaseUrl: merchant.makeInstanceBaseUrl(), + orderId: order.id, + }, + ); + + //claim from the second wallet + const claimSecondWallet = await secondWallet.call( + WalletApiOperation.PreparePayForUri, + { talerPayUri: privatePayUri }, + ); + + t.assertTrue( + claimSecondWallet.status === PreparePayResultType.PaymentPossible, + ); + + //pay from the second wallet + const r2 = await secondWallet.call(WalletApiOperation.ConfirmPay, { + proposalId: claimSecondWallet.proposalId, + }); + + t.assertTrue(r2.type === ConfirmPayResultType.Done); + { + 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"); + } + + // Claim the order with the first wallet + const claimFirstWalletAgain = await firstWallet.call( + WalletApiOperation.PreparePayForUri, + { talerPayUri: order.uri }, + ); + + t.assertTrue( + claimFirstWalletAgain.status === PreparePayResultType.AlreadyConfirmed, + ); + + const r1 = await firstWallet.call(WalletApiOperation.ConfirmPay, { + proposalId: claimFirstWallet.proposalId, + }); + + t.assertTrue(r1.type === ConfirmPayResultType.Done); + { + 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"); + } + } + + /** + * SECOND CASE, create in first wallet and share to the second wallet + * pay with the first wallet, second wallet should not be able to continue + */ + { + 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, + ); + + //share order from the first wallet + const { privatePayUri } = await firstWallet.call( + WalletApiOperation.SharePayment, + { + merchantBaseUrl: merchant.makeInstanceBaseUrl(), + orderId: order.id, + }, + ); + + //claim from the second wallet + const claimSecondWallet = await secondWallet.call( + WalletApiOperation.PreparePayForUri, + { talerPayUri: privatePayUri }, + ); + + t.assertTrue( + claimSecondWallet.status === PreparePayResultType.PaymentPossible, + ); + + //pay from the second wallet + const r2 = await firstWallet.call(WalletApiOperation.ConfirmPay, { + proposalId: claimFirstWallet.proposalId, + }); + + t.assertTrue(r2.type === ConfirmPayResultType.Done); + + const bal1 = await firstWallet.call(WalletApiOperation.GetBalances, {}); + t.assertAmountEquals(bal1.balances[0].available, "TESTKUDOS:16.18"); + + const bal2 = await secondWallet.call(WalletApiOperation.GetBalances, {}); + t.assertAmountEquals(bal2.balances[0].available, "TESTKUDOS:14.23"); + + // Claim the order with the first wallet + const claimSecondWalletAgain = await secondWallet.call( + WalletApiOperation.PreparePayForUri, + { talerPayUri: order.uri }, + ); + + t.assertTrue( + claimSecondWalletAgain.status === PreparePayResultType.AlreadyConfirmed, + ); + } +} + +runPaymentShareTest.suites = ["wallet"]; diff --git a/packages/taler-harness/src/integrationtests/testrunner.ts b/packages/taler-harness/src/integrationtests/testrunner.ts index 0f64ae94f..e35264d13 100644 --- a/packages/taler-harness/src/integrationtests/testrunner.ts +++ b/packages/taler-harness/src/integrationtests/testrunner.ts @@ -102,6 +102,7 @@ import { runWalletBalanceTest } from "./test-wallet-balance.js"; import { runPaymentTemplateTest } from "./test-payment-template.js"; import { runExchangeDepositTest } from "./test-exchange-deposit.js"; import { runPeerRepairTest } from "./test-peer-repair.js"; +import { runPaymentShareTest } from "./test-payment-share.js"; /** * Test runner. @@ -166,6 +167,7 @@ const allTests: TestMainFunction[] = [ runPaymentIdempotencyTest, runPaymentMultipleTest, runPaymentTest, + runPaymentShareTest, runPaymentTemplateTest, runPaymentAbortTest, runPaymentTransientTest, -- cgit v1.2.3