diff options
Diffstat (limited to 'packages/taler-harness/src/integrationtests/test-payment-abort.ts')
-rw-r--r-- | packages/taler-harness/src/integrationtests/test-payment-abort.ts | 164 |
1 files changed, 164 insertions, 0 deletions
diff --git a/packages/taler-harness/src/integrationtests/test-payment-abort.ts b/packages/taler-harness/src/integrationtests/test-payment-abort.ts new file mode 100644 index 000000000..ca8384411 --- /dev/null +++ b/packages/taler-harness/src/integrationtests/test-payment-abort.ts @@ -0,0 +1,164 @@ +/* + 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, + PreparePayResultType, + TalerErrorCode, + TalerErrorDetail, + URL, + codecForMerchantOrderStatusUnpaid, + j2s, +} from "@gnu-taler/taler-util"; +import { WalletApiOperation } from "@gnu-taler/taler-wallet-core"; +import { FaultInjectionRequestContext } from "../harness/faultInjection.js"; +import { GlobalTestState, harnessHttpLib } from "../harness/harness.js"; +import { + createFaultInjectedMerchantTestkudosEnvironment, + withdrawViaBankV2, +} from "../harness/helpers.js"; + +export async function runPaymentAbortTest(t: GlobalTestState) { + // Set up test environment + + const { walletClient, bank, exchange, faultyMerchant, faultyExchange } = + await createFaultInjectedMerchantTestkudosEnvironment(t); + + // Withdraw digital cash into the wallet. + + const wres = await withdrawViaBankV2(t, { + walletClient, + bank, + exchange: faultyExchange, + amount: "TESTKUDOS:20", + }); + + await wres.withdrawalFinishedCond; + + const merchantClient = new MerchantApiClient( + faultyMerchant.makeInstanceBaseUrl(), + ); + + let orderResp = await merchantClient.createOrder({ + order: { + summary: "Buy me!", + amount: "TESTKUDOS:5", + fulfillment_url: "https://example.com/article42", + public_reorder_url: "https://example.com/article42-share", + }, + }); + + let orderStatus = await merchantClient.queryPrivateOrderStatus({ + orderId: orderResp.order_id, + sessionId: "mysession-one", + }); + + t.assertTrue(orderStatus.order_status === "unpaid"); + + t.assertTrue(orderStatus.already_paid_order_id === undefined); + let publicOrderStatusUrl = orderStatus.order_status_url; + + let publicOrderStatusResp = await harnessHttpLib.fetch(publicOrderStatusUrl); + + if (publicOrderStatusResp.status != 402) { + throw Error( + `expected status 402 (before claiming), but got ${publicOrderStatusResp.status}`, + ); + } + + let pubUnpaidStatus = codecForMerchantOrderStatusUnpaid().decode( + publicOrderStatusResp.json(), + ); + + console.log(pubUnpaidStatus); + + let preparePayResp = await walletClient.call( + WalletApiOperation.PreparePayForUri, + { + talerPayUri: pubUnpaidStatus.taler_pay_uri, + }, + ); + + t.assertTrue(preparePayResp.status === PreparePayResultType.PaymentPossible); + + publicOrderStatusResp = await harnessHttpLib.fetch(publicOrderStatusUrl); + + if (publicOrderStatusResp.status != 402) { + throw Error( + `expected status 402 (after claiming), but got ${publicOrderStatusResp.status}`, + ); + } + + pubUnpaidStatus = codecForMerchantOrderStatusUnpaid().decode( + publicOrderStatusResp.json(), + ); + + faultyMerchant.faultProxy.addFault({ + async modifyRequest(ctx: FaultInjectionRequestContext) { + const url = new URL(ctx.requestUrl); + if (!url.pathname.endsWith("/pay")) { + return; + } + ctx.dropRequest = true; + const err: TalerErrorDetail = { + code: TalerErrorCode.GENERIC_CONFIGURATION_INVALID, + hint: "something went wrong", + }; + ctx.substituteResponseStatusCode = 404; + ctx.substituteResponseBody = Buffer.from(JSON.stringify(err)); + console.log("injecting pay fault"); + }, + }); + + const confirmPayResp = await walletClient.call( + WalletApiOperation.ConfirmPay, + { + transactionId: preparePayResp.transactionId, + }, + ); + + // Can't have succeeded yet, but network error results in "pending" state. + t.assertDeepEqual(confirmPayResp.type, ConfirmPayResultType.Pending); + + const txns = await walletClient.call(WalletApiOperation.GetTransactions, { + sort: "stable-ascending", + }); + console.log(j2s(txns)); + + await walletClient.call(WalletApiOperation.AbortTransaction, { + transactionId: txns.transactions[1].transactionId, + }); + + await walletClient.call(WalletApiOperation.TestingWaitTransactionsFinal, {}); + + const txns2 = await walletClient.call(WalletApiOperation.GetTransactions, { + sort: "stable-ascending", + }); + console.log(j2s(txns2)); + + const txTypes = txns2.transactions.map((x) => x.type); + console.log(txTypes); + t.assertDeepEqual(txTypes, ["withdrawal", "payment", "refund"]); + + // FIXME: also check extended transaction list for refresh. + // FIXME: also check balance +} + +runPaymentAbortTest.suites = ["wallet"]; |