gnunet-svn
[Top][All Lists]
Advanced

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

[taler-wallet-core] 02/02: add bank API tests


From: gnunet
Subject: [taler-wallet-core] 02/02: add bank API tests
Date: Thu, 20 Aug 2020 10:25:18 +0200

This is an automated email from the git hooks/post-receive script.

dold pushed a commit to branch master
in repository wallet-core.

commit 786976e5a8e10f6a3eab50cacbefe98d8b2364f5
Author: Florian Dold <florian.dold@gmail.com>
AuthorDate: Thu Aug 20 13:55:03 2020 +0530

    add bank API tests
---
 packages/taler-integrationtests/src/harness.ts     | 235 ++++++++++++++-------
 packages/taler-integrationtests/src/helpers.ts     |   9 +-
 .../taler-integrationtests/src/test-bank-api.ts    | 122 +++++++++++
 .../src/test-exchange-management.ts                |   6 +-
 .../src/test-payment-fault.ts                      |   8 +-
 .../src/test-withdrawal-bank-integrated.ts         |   8 +-
 .../src/test-withdrawal-manual.ts                  |   6 +-
 7 files changed, 299 insertions(+), 95 deletions(-)

diff --git a/packages/taler-integrationtests/src/harness.ts 
b/packages/taler-integrationtests/src/harness.ts
index 77914af6..6897b4b5 100644
--- a/packages/taler-integrationtests/src/harness.ts
+++ b/packages/taler-integrationtests/src/harness.ts
@@ -66,9 +66,10 @@ import {
   TransactionsResponse,
   codecForTransactionsResponse,
   WithdrawTestBalanceRequest,
+  AmountString,
 } from "taler-wallet-core";
 import { URL } from "url";
-import axios from "axios";
+import axios, { AxiosError } from "axios";
 import {
   codecForMerchantOrderPrivateStatusResponse,
   codecForPostOrderResponse,
@@ -276,6 +277,21 @@ export class GlobalTestState {
     );
   }
 
+  async assertThrowsAsync(block: () => Promise<void>): Promise<any> {
+    try {
+      await block();
+    } catch (e) {
+      return e;
+    }
+    throw Error(
+      `expected exception to be thrown, but block finished without throwing`,
+    );
+  }
+
+  assertAxiosError(e: any): asserts e is AxiosError {
+    return e.isAxiosError;
+  }
+
   assertTrue(b: boolean): asserts b {
     if (!b) {
       throw Error("test assertion failed");
@@ -412,6 +428,7 @@ export interface BankConfig {
   httpPort: number;
   database: string;
   allowRegistrations: boolean;
+  maxDebt?: string;
 }
 
 function setPaths(config: Configuration, home: string) {
@@ -474,7 +491,136 @@ export interface ExchangeBankAccount {
   wireGatewayApiBaseUrl: string;
 }
 
-export class BankService {
+export interface BankServiceInterface {
+  readonly baseUrl: string;
+  readonly port: number;
+}
+
+export enum CreditDebitIndicator {
+  Credit = "credit",
+  Debit = "debit",
+}
+
+export interface BankAccountBalanceResponse {
+  balance_amount: AmountString;
+  credit_debit_indicator: CreditDebitIndicator;
+}
+
+export namespace BankAccessApi {
+  export async function getAccountBalance(
+    bank: BankServiceInterface,
+    bankUser: BankUser,
+  ): Promise<BankAccountBalanceResponse> {
+    const url = new URL(
+      `accounts/${bankUser.username}/balance`,
+      bank.baseUrl,
+    );
+    const resp = await axios.get(
+      url.href,
+      {
+        auth: bankUser,
+      },
+    );
+    return resp.data;
+  }
+
+  export async function createWithdrawalOperation(
+    bank: BankServiceInterface,
+    bankUser: BankUser,
+    amount: string,
+  ): Promise<WithdrawalOperationInfo> {
+    const url = new URL(
+      `accounts/${bankUser.username}/withdrawals`,
+      bank.baseUrl,
+    );
+    const resp = await axios.post(
+      url.href,
+      {
+        amount,
+      },
+      {
+        auth: bankUser,
+      },
+    );
+    return codecForWithdrawalOperationInfo().decode(resp.data);
+  }
+}
+
+export namespace BankApi {
+  export async function registerAccount(
+    bank: BankServiceInterface,
+    username: string,
+    password: string,
+  ): Promise<BankUser> {
+    const url = new URL("testing/register", bank.baseUrl);
+    await axios.post(url.href, {
+      username,
+      password,
+    });
+    return {
+      password,
+      username,
+      accountPaytoUri: `payto://x-taler-bank/localhost/${username}`,
+    };
+  }
+
+  export async function createRandomBankUser(
+    bank: BankServiceInterface,
+  ): Promise<BankUser> {
+    const username = "user-" + encodeCrock(getRandomBytes(10));
+    const password = "pw-" + encodeCrock(getRandomBytes(10));
+    return await registerAccount(bank, username, password);
+  }
+
+  export async function adminAddIncoming(
+    bank: BankServiceInterface,
+    params: {
+      exchangeBankAccount: ExchangeBankAccount;
+      amount: string;
+      reservePub: string;
+      debitAccountPayto: string;
+    },
+  ) {
+    const url = new URL(
+      
`taler-wire-gateway/${params.exchangeBankAccount.accountName}/admin/add-incoming`,
+      bank.baseUrl,
+    );
+    await axios.post(
+      url.href,
+      {
+        amount: params.amount,
+        reserve_pub: params.reservePub,
+        debit_account: params.debitAccountPayto,
+      },
+      {
+        auth: {
+          username: params.exchangeBankAccount.accountName,
+          password: params.exchangeBankAccount.accountPassword,
+        },
+      },
+    );
+  }
+
+  export async function confirmWithdrawalOperation(
+    bank: BankServiceInterface,
+    bankUser: BankUser,
+    wopi: WithdrawalOperationInfo,
+  ): Promise<void> {
+    const url = new URL(
+      
`accounts/${bankUser.username}/withdrawals/${wopi.withdrawal_id}/confirm`,
+      bank.baseUrl,
+    );
+    await axios.post(
+      url.href,
+      {},
+      {
+        auth: bankUser,
+      },
+    );
+  }
+}
+
+export class BankService implements BankServiceInterface {
   proc: ProcessWrapper | undefined;
 
   static fromExistingConfig(gc: GlobalTestState): BankService {
@@ -502,6 +648,7 @@ export class BankService {
     config.setString("bank", "database", bc.database);
     config.setString("bank", "http_port", `${bc.httpPort}`);
     config.setString("bank", "max_debt_bank", `${bc.currency}:999999`);
+    config.setString("bank", "max_debt", bc.maxDebt ?? `${bc.currency}:100`);
     config.setString(
       "bank",
       "allow_registrations",
@@ -583,79 +730,6 @@ export class BankService {
     const url = `http://localhost:${this.bankConfig.httpPort}/config`;
     await pingProc(this.proc, url, "bank");
   }
-
-  async createAccount(username: string, password: string): Promise<void> {
-    const url = 
`http://localhost:${this.bankConfig.httpPort}/testing/register`;
-    await axios.post(url, {
-      username,
-      password,
-    });
-  }
-
-  async createRandomBankUser(): Promise<BankUser> {
-    const username = "user-" + encodeCrock(getRandomBytes(10));
-    const bankUser: BankUser = {
-      username,
-      password: "pw-" + encodeCrock(getRandomBytes(10)),
-      accountPaytoUri: `payto://x-taler-bank/localhost/${username}`,
-    };
-    await this.createAccount(bankUser.username, bankUser.password);
-    return bankUser;
-  }
-
-  async createWithdrawalOperation(
-    bankUser: BankUser,
-    amount: string,
-  ): Promise<WithdrawalOperationInfo> {
-    const url = 
`http://localhost:${this.bankConfig.httpPort}/accounts/${bankUser.username}/withdrawals`;
-    const resp = await axios.post(
-      url,
-      {
-        amount,
-      },
-      {
-        auth: bankUser,
-      },
-    );
-    return codecForWithdrawalOperationInfo().decode(resp.data);
-  }
-
-  async adminAddIncoming(params: {
-    exchangeBankAccount: ExchangeBankAccount;
-    amount: string;
-    reservePub: string;
-    debitAccountPayto: string;
-  }) {
-    const url = 
`http://localhost:${this.bankConfig.httpPort}/taler-wire-gateway/${params.exchangeBankAccount.accountName}/admin/add-incoming`;
-    await axios.post(
-      url,
-      {
-        amount: params.amount,
-        reserve_pub: params.reservePub,
-        debit_account: params.debitAccountPayto,
-      },
-      {
-        auth: {
-          username: params.exchangeBankAccount.accountName,
-          password: params.exchangeBankAccount.accountPassword,
-        },
-      },
-    );
-  }
-
-  async confirmWithdrawalOperation(
-    bankUser: BankUser,
-    wopi: WithdrawalOperationInfo,
-  ): Promise<void> {
-    const url = 
`http://localhost:${this.bankConfig.httpPort}/accounts/${bankUser.username}/withdrawals/${wopi.withdrawal_id}/confirm`;
-    await axios.post(
-      url,
-      {},
-      {
-        auth: bankUser,
-      },
-    );
-  }
 }
 
 export interface BankUser {
@@ -945,11 +1019,12 @@ export namespace MerchantPrivateApi {
   export async function giveRefund(
     merchantService: MerchantServiceInterface,
     r: {
-    instance: string;
-    orderId: string;
-    amount: string;
-    justification: string;
-  }): Promise<{ talerRefundUri: string }> {
+      instance: string;
+      orderId: string;
+      amount: string;
+      justification: string;
+    },
+  ): Promise<{ talerRefundUri: string }> {
     const reqUrl = new URL(
       `private/orders/${r.orderId}/refund`,
       merchantService.makeInstanceBaseUrl(r.instance),
diff --git a/packages/taler-integrationtests/src/helpers.ts 
b/packages/taler-integrationtests/src/helpers.ts
index 86f530e0..d33aaff4 100644
--- a/packages/taler-integrationtests/src/helpers.ts
+++ b/packages/taler-integrationtests/src/helpers.ts
@@ -34,6 +34,8 @@ import {
   defaultCoinConfig,
   ExchangeBankAccount,
   MerchantServiceInterface,
+  BankApi,
+  BankAccessApi,
 } from "./harness";
 import { AmountString } from "taler-wallet-core/lib/types/talerTypes";
 import { FaultInjectedMerchantService } from "./faultInjection";
@@ -230,8 +232,8 @@ export async function withdrawViaBank(
 ): Promise<void> {
   const { wallet, bank, exchange, amount } = p;
 
-  const user = await bank.createRandomBankUser();
-  const wop = await bank.createWithdrawalOperation(user, amount);
+  const user = await BankApi.createRandomBankUser(bank);
+  const wop = await BankAccessApi.createWithdrawalOperation(bank, user, 
amount);
 
   // Hand it to the wallet
 
@@ -244,7 +246,7 @@ export async function withdrawViaBank(
 
   // Confirm it
 
-  await bank.confirmWithdrawalOperation(user, wop);
+  await BankApi.confirmWithdrawalOperation(bank, user, wop);
 
   // Withdraw
 
@@ -260,3 +262,4 @@ export async function withdrawViaBank(
   const balApiResp = await wallet.apiRequest("getBalances", {});
   t.assertTrue(balApiResp.type === "response");
 }
+
diff --git a/packages/taler-integrationtests/src/test-bank-api.ts 
b/packages/taler-integrationtests/src/test-bank-api.ts
new file mode 100644
index 00000000..1c233a55
--- /dev/null
+++ b/packages/taler-integrationtests/src/test-bank-api.ts
@@ -0,0 +1,122 @@
+/*
+ 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 { runTest, GlobalTestState, MerchantPrivateApi, WalletCli, 
defaultCoinConfig, ExchangeService, setupDb, BankService, MerchantService, 
BankApi, BankUser, BankAccessApi, CreditDebitIndicator } from "./harness";
+import { createSimpleTestkudosEnvironment, withdrawViaBank } from "./helpers";
+import { createEddsaKeyPair, encodeCrock } from "taler-wallet-core";
+
+/**
+ * Run test for basic, bank-integrated withdrawal.
+ */
+runTest(async (t: GlobalTestState) => {
+  // Set up test environment
+
+  const db = await setupDb(t);
+
+  const bank = await BankService.create(t, {
+    allowRegistrations: true,
+    currency: "TESTKUDOS",
+    database: db.connStr,
+    httpPort: 8082,
+  });
+
+  const exchange = ExchangeService.create(t, {
+    name: "testexchange-1",
+    currency: "TESTKUDOS",
+    httpPort: 8081,
+    database: db.connStr,
+  });
+
+  const merchant = await MerchantService.create(t, {
+    name: "testmerchant-1",
+    currency: "TESTKUDOS",
+    httpPort: 8083,
+    database: db.connStr,
+  });
+
+  const exchangeBankAccount = await bank.createExchangeAccount(
+    "MyExchange",
+    "x",
+  );
+  exchange.addBankAccount("1", exchangeBankAccount);
+
+  bank.setSuggestedExchange(exchange, exchangeBankAccount.accountPaytoUri);
+
+  await bank.start();
+
+  await bank.pingUntilAvailable();
+
+  exchange.addOfferedCoins(defaultCoinConfig);
+
+  await exchange.start();
+  await exchange.pingUntilAvailable();
+
+  merchant.addExchange(exchange);
+
+  await merchant.start();
+  await merchant.pingUntilAvailable();
+
+  await merchant.addInstance({
+    id: "minst1",
+    name: "minst1",
+    paytoUris: ["payto://x-taler-bank/minst1"],
+  });
+
+  await merchant.addInstance({
+    id: "default",
+    name: "Default Instance",
+    paytoUris: [`payto://x-taler-bank/merchant-default`],
+  });
+
+  console.log("setup done!");
+
+  const wallet = new WalletCli(t);
+
+  const bankUser = await BankApi.registerAccount(bank, "user1", "pw1");
+
+  // Make sure that registering twice results in a 409 Conflict
+  {
+    const e = await t.assertThrowsAsync(async () => {
+      await BankApi.registerAccount(bank, "user1", "pw1");
+    });
+    t.assertAxiosError(e);
+    t.assertTrue(e.response?.status === 409);
+  }
+
+  let bal = await BankAccessApi.getAccountBalance(bank, bankUser);
+
+  console.log(bal);
+
+  // Check that we got the sign-up bonus.
+  t.assertAmountEquals(bal.balance_amount, "TESTKUDOS:100");
+  t.assertTrue(bal.credit_debit_indicator === CreditDebitIndicator.Credit);
+
+  const res = createEddsaKeyPair();
+
+  await BankApi.adminAddIncoming(bank, {
+    amount: "TESTKUDOS:115",
+    debitAccountPayto: bankUser.accountPaytoUri,
+    exchangeBankAccount: exchangeBankAccount,
+    reservePub: encodeCrock(res.eddsaPub),
+  });
+
+  bal = await BankAccessApi.getAccountBalance(bank, bankUser);
+  t.assertAmountEquals(bal.balance_amount, "TESTKUDOS:15");
+  t.assertTrue(bal.credit_debit_indicator === CreditDebitIndicator.Debit);
+});
diff --git a/packages/taler-integrationtests/src/test-exchange-management.ts 
b/packages/taler-integrationtests/src/test-exchange-management.ts
index 9199c183..4ca86b34 100644
--- a/packages/taler-integrationtests/src/test-exchange-management.ts
+++ b/packages/taler-integrationtests/src/test-exchange-management.ts
@@ -26,6 +26,8 @@ import {
   ExchangeService,
   MerchantService,
   defaultCoinConfig,
+  BankApi,
+  BankAccessApi,
 } from "./harness";
 import { createSimpleTestkudosEnvironment, withdrawViaBank } from "./helpers";
 import {
@@ -231,8 +233,8 @@ runTest(async (t: GlobalTestState) => {
 
   // Create withdrawal operation
 
-  const user = await bank.createRandomBankUser();
-  const wop = await bank.createWithdrawalOperation(user, "TESTKUDOS:10");
+  const user = await BankApi.createRandomBankUser(bank);
+  const wop = await BankAccessApi.createWithdrawalOperation(bank, user, 
"TESTKUDOS:10");
 
   // Hand it to the wallet
 
diff --git a/packages/taler-integrationtests/src/test-payment-fault.ts 
b/packages/taler-integrationtests/src/test-payment-fault.ts
index 8065b430..a7f44706 100644
--- a/packages/taler-integrationtests/src/test-payment-fault.ts
+++ b/packages/taler-integrationtests/src/test-payment-fault.ts
@@ -31,6 +31,8 @@ import {
   WalletCli,
   defaultCoinConfig,
   MerchantPrivateApi,
+  BankApi,
+  BankAccessApi,
 } from "./harness";
 import {
   FaultInjectedExchangeService,
@@ -114,8 +116,8 @@ runTest(async (t: GlobalTestState) => {
 
   // Create withdrawal operation
 
-  const user = await bank.createRandomBankUser();
-  const wop = await bank.createWithdrawalOperation(user, "TESTKUDOS:20");
+  const user = await BankApi.createRandomBankUser(bank);
+  const wop = await BankAccessApi.createWithdrawalOperation(bank, user, 
"TESTKUDOS:20");
 
   // Hand it to the wallet
 
@@ -128,7 +130,7 @@ runTest(async (t: GlobalTestState) => {
 
   // Confirm it
 
-  await bank.confirmWithdrawalOperation(user, wop);
+  await BankApi.confirmWithdrawalOperation(bank, user, wop);
 
   // Withdraw
 
diff --git 
a/packages/taler-integrationtests/src/test-withdrawal-bank-integrated.ts 
b/packages/taler-integrationtests/src/test-withdrawal-bank-integrated.ts
index 46ccdaae..f2593c80 100644
--- a/packages/taler-integrationtests/src/test-withdrawal-bank-integrated.ts
+++ b/packages/taler-integrationtests/src/test-withdrawal-bank-integrated.ts
@@ -17,7 +17,7 @@
 /**
  * Imports.
  */
-import { runTest, GlobalTestState } from "./harness";
+import { runTest, GlobalTestState, BankApi, BankAccessApi } from "./harness";
 import { createSimpleTestkudosEnvironment } from "./helpers";
 import { codecForBalancesResponse } from "taler-wallet-core";
 
@@ -31,8 +31,8 @@ runTest(async (t: GlobalTestState) => {
 
   // Create a withdrawal operation
 
-  const user = await bank.createRandomBankUser();
-  const wop = await bank.createWithdrawalOperation(user, "TESTKUDOS:10");
+  const user = await BankApi.createRandomBankUser(bank);
+  const wop = await BankAccessApi.createWithdrawalOperation(bank, user, 
"TESTKUDOS:10");
 
   // Hand it to the wallet
 
@@ -45,7 +45,7 @@ runTest(async (t: GlobalTestState) => {
 
   // Confirm it
 
-  await bank.confirmWithdrawalOperation(user, wop);
+  await BankApi.confirmWithdrawalOperation(bank, user, wop);
 
   // Withdraw
 
diff --git a/packages/taler-integrationtests/src/test-withdrawal-manual.ts 
b/packages/taler-integrationtests/src/test-withdrawal-manual.ts
index 0d09c3e5..ee844d9f 100644
--- a/packages/taler-integrationtests/src/test-withdrawal-manual.ts
+++ b/packages/taler-integrationtests/src/test-withdrawal-manual.ts
@@ -17,7 +17,7 @@
 /**
  * Imports.
  */
-import { runTest, GlobalTestState } from "./harness";
+import { runTest, GlobalTestState, BankApi } from "./harness";
 import { createSimpleTestkudosEnvironment } from "./helpers";
 import { CoreApiResponse } from "taler-wallet-core/lib/walletCoreApiHandler";
 import { codecForBalancesResponse } from "taler-wallet-core";
@@ -37,7 +37,7 @@ runTest(async (t: GlobalTestState) => {
 
   // Create a withdrawal operation
 
-  const user = await bank.createRandomBankUser();
+  const user = await BankApi.createRandomBankUser(bank);
 
   let wresp: CoreApiResponse;
 
@@ -56,7 +56,7 @@ runTest(async (t: GlobalTestState) => {
 
   const reservePub: string = (wresp.result as any).reservePub;
 
-  await bank.adminAddIncoming({
+  await BankApi.adminAddIncoming(bank, {
     exchangeBankAccount,
     amount: "TESTKUDOS:10",
     debitAccountPayto: user.accountPaytoUri,

-- 
To stop receiving notification emails like this one, please contact
gnunet@gnunet.org.



reply via email to

[Prev in Thread] Current Thread [Next in Thread]