gnunet-svn
[Top][All Lists]
Advanced

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

[taler-wallet-core] 05/07: test for every error code in the spec


From: gnunet
Subject: [taler-wallet-core] 05/07: test for every error code in the spec
Date: Fri, 03 Nov 2023 23:13:55 +0100

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

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

commit 11b99b9256d13e16aff460db6f014390ded4670b
Author: Sebastian <sebasjm@gmail.com>
AuthorDate: Fri Nov 3 19:00:47 2023 -0300

    test for every error code in the spec
---
 .../taler-harness/src/http-client/bank-core.ts     | 1375 ++++++++++++--------
 packages/taler-harness/src/index.ts                |  111 +-
 2 files changed, 893 insertions(+), 593 deletions(-)

diff --git a/packages/taler-harness/src/http-client/bank-core.ts 
b/packages/taler-harness/src/http-client/bank-core.ts
index 6f9641dc9..ccefd2bfe 100644
--- a/packages/taler-harness/src/http-client/bank-core.ts
+++ b/packages/taler-harness/src/http-client/bank-core.ts
@@ -1,542 +1,841 @@
-import { AccessToken, Amounts, TalerCoreBankHttpClient, TalerCorebankApi, 
buildPayto, encodeCrock, failOrThrow, getRandomBytes, parsePaytoUri, 
stringifyPaytoUri, succeedOrThrow } from "@gnu-taler/taler-util"
-
-export class BankCoreSmokeTest {
-  constructor(readonly api: TalerCoreBankHttpClient) {
-
-  }
-
-  async testConfig() {
-    const config = await this.api.getConfig()
-    if (!this.api.isCompatible(config.body.version)) {
-      throw Error(`not compatible with server ${config.body.version}`)
-    }
-    return config.body
-  }
-
-  async testCashouts(adminPassword: string) {
-  }
-  async testMonitor(adminPassword: string) {
-    const { access_token: adminToken } = await succeedOrThrow(() =>
-      this.api.getAuthenticationAPI("admin").createAccessToken(adminPassword, {
-        scope: "readwrite"
-      })
-    )
-
-    await succeedOrThrow(() => (
-      this.api.getMonitor()
-    ))
-
-    await succeedOrThrow(() => (
-      this.api.getMonitor({
-        timeframe: TalerCorebankApi.MonitorTimeframeParam.day,
-        which: (new Date()).getDate() - 1
-      })
-    ))
-  }
-
-  async testAccountManagement(adminPassword: string) {
-
-    const { access_token: adminToken } = await succeedOrThrow(() =>
-      this.api.getAuthenticationAPI("admin").createAccessToken(adminPassword, {
-        scope: "readwrite"
-      })
-    )
-
-    /**
-     * Create account
-    */
-    {
-      const username = "harness-" + 
encodeCrock(getRandomBytes(10)).toLowerCase();
-
-      // await failOrThrow("invalid-input",() =>
-      //   this.api.createAccount(adminToken, {
-      //     name: username,
-      //     username, password: "123",
-      //     challenge_contact_data: {
-      //       email: "invalid email",
-      //       phone: "invalid phone",
-      //     }
-      //   })
-      // )
-
-      // await failOrThrow("unable-to-create",() =>
-      //   this.api.createAccount(adminToken, {
-      //     name: "admin",
-      //     username, password: "123"
-      //   })
-      // )
-
-      // await failOrThrow("unable-to-create",() =>
-      //   this.api.createAccount(adminToken, {
-      //     name: "bank",
-      //     username, password: "123"
-      //   })
-      // )
-
-      await succeedOrThrow(() =>
-        this.api.createAccount(adminToken, {
-          name: username,
-          username, password: "123"
-        })
-      )
-
-      await failOrThrow("already-exist", () =>
-        this.api.createAccount(adminToken, {
-          name: username,
-          username, password: "123"
-        })
-      );
-    }
-
-    /**
-     * Delete account
-     */
-    {
-      const { username, token } = await createRandomTestUser(this.api, 
adminToken)
-
-      await failOrThrow("not-found", () =>
-        this.api.deleteAccount({ username: "not-found", token: adminToken })
-      )
-      await failOrThrow("unable-to-delete", () =>
-        this.api.deleteAccount({ username: "admin", token: adminToken })
-      )
-      await failOrThrow("unable-to-delete", () =>
-        this.api.deleteAccount({ username: "bank", token: adminToken })
-      )
-
-      await failOrThrow("balance-not-zero", () =>
-        this.api.deleteAccount({ username, token: adminToken })
-      )
-
-      const userInfo = await succeedOrThrow(() =>
-        this.api.getAccount({ username, token })
-      )
-
-      const adminInfo = await succeedOrThrow(() =>
-        this.api.getAccount({ username: "admin", token: adminToken })
-      )
-
-      const adminAccount = parsePaytoUri(adminInfo.payto_uri)!
-      adminAccount.params["message"] = "all my money"
-      const withSubject = stringifyPaytoUri(adminAccount)
-
-      await succeedOrThrow(() =>
-        this.api.createTransaction({ username, token }, {
-          payto_uri: withSubject,
-          amount: userInfo.balance.amount
-        })
-      )
-
-
-      const otherUsername = "harness-" + 
encodeCrock(getRandomBytes(10)).toLowerCase();
-
-      await succeedOrThrow(() =>
-        this.api.createAccount(adminToken, {
-          name: otherUsername,
-          username: otherUsername, password: "123"
-        })
-      )
-
-      await failOrThrow("unauthorized", () =>
-        this.api.deleteAccount({ username: otherUsername, token })
-      )
-
-      await succeedOrThrow(() =>
-        this.api.deleteAccount({ username, token: adminToken })
-      )
-    }
-
-    /**
-     * Update account
-     */
-    {
-      const { username, token } = await createRandomTestUser(this.api, 
adminToken)
-
-      await failOrThrow("cant-change-legal-name-or-admin", () =>
-        this.api.updateAccount({ username, token }, {
-          name: "something else",
-        })
-      )
-
-      // await failOrThrow("not-found", () =>
-      //   this.api.updateAccount({ username: "notfound", token }, {
-      //     challenge_contact_data: {
-      //       email: "asd@Aasd.com"
-      //     }
-      //   })
-      // )
-
-      await failOrThrow("unauthorized", () =>
-        this.api.updateAccount({ username: "notfound", token: "wrongtoken" as 
AccessToken }, {
-          challenge_contact_data: {
-            email: "asd@Aasd.com"
-          }
-        })
-      )
-
-      await succeedOrThrow(() =>
-        this.api.updateAccount({ username, token }, {
-          challenge_contact_data: {
-            email: "asd@Aasd.com"
-          }
-        })
-      )
-    }
-
-    /**
-     * Update password
-     */
-    {
-      const { username, token } = await createRandomTestUser(this.api, 
adminToken)
-
-      await succeedOrThrow(() =>
-        this.api.updatePassword({ username, token }, {
-          old_password: "123",
-          new_password: "234"
-        })
-      )
-      // await failOrThrow("not-found",() =>
-      //   this.api.updatePassword({ username:"notfound", token: userTempToken 
}, {
-      //     old_password: "123",
-      //     new_password: "234"
-      //   })
-      // )
-      await failOrThrow("unauthorized", () =>
-        this.api.updatePassword({ username: "admin", token }, {
-          old_password: "123",
-          new_password: "234"
-        })
-      )
-      // await failOrThrow("old-password-invalid-or-not-allowed",() =>
-      //   this.api.updatePassword({ username, token: userTempToken }, {
-      //     old_password: "123",
-      //     new_password: "234"
-      //   })
-      // )
-
-    }
-
-    /**
-     * public accounts
-     */
-    {
-      const acs = await succeedOrThrow(() => this.api.getPublicAccounts())
-
-    }
-    /**
-     * get accounts
-     */
-    {
-      const { username, token } = await createRandomTestUser(this.api, 
adminToken)
-      // await failOrThrow("no-rights",() => 
-      //   this.api.getAccounts(token)
-      // )
-      await failOrThrow("unauthorized", () =>
-        this.api.getAccounts("ASDASD" as AccessToken)
-      )
-
-      const acs = await succeedOrThrow(() =>
-        this.api.getAccounts(adminToken)
-      )
-    }
-
-  }
-
-  async testWithdrawals(adminPassword: string) {
-    const { access_token: adminToken } = await succeedOrThrow(() =>
-      this.api.getAuthenticationAPI("admin").createAccessToken(adminPassword, {
-        scope: "readwrite"
-      })
-    )
-    /**
-     * create withdrawals
-     */
-    {
-      const { username, token } = await createRandomTestUser(this.api, 
adminToken)
-
-      const userInfo = await succeedOrThrow(() =>
-        this.api.getAccount({ username, token })
-      )
-
-      const balance = Amounts.parseOrThrow(userInfo.balance.amount)
-      const moreThanBalance = Amounts.stringify(Amounts.mult(balance, 
5).amount)
-      await failOrThrow("insufficient-funds", () =>
-        this.api.createWithdrawal({ username, token }, {
-          amount: moreThanBalance
-        })
-      )
-
-      await failOrThrow("unauthorized", () =>
-        this.api.createWithdrawal({ username, token: "wrongtoken" as 
AccessToken }, {
-          amount: userInfo.balance.amount
-        })
-      )
-
-      await succeedOrThrow(() =>
-        this.api.createWithdrawal({ username, token }, {
-          amount: userInfo.balance.amount
-        })
-      )
-    }
-
-    /**
-     * get withdrawal
-     */
-    {
-      const { username, token } = await createRandomTestUser(this.api, 
adminToken)
-
-      const userInfo = await succeedOrThrow(() =>
-        this.api.getAccount({ username, token })
-      )
-
-      const { withdrawal_id } = await succeedOrThrow(() =>
-        this.api.createWithdrawal({ username, token }, {
-          amount: userInfo.balance.amount
-        })
-      )
-
-      await succeedOrThrow(() =>
-        this.api.getWithdrawalById(withdrawal_id)
-      )
-
-      await failOrThrow("invalid-id", () =>
-        this.api.getWithdrawalById("invalid")
-      )
-      await failOrThrow("not-found", () =>
-        this.api.getWithdrawalById("11111111-1111-1111-1111-111111111111")
-      )
-    }
-
-    /**
-     * abort withdrawal
-     */
-    {
-      const { username: exchangeUser, token: exchangeToken } = await 
createRandomTestUser(this.api, adminToken, { is_taler_exchange: true })
-      const { username, token } = await createRandomTestUser(this.api, 
adminToken)
-
-      const userInfo = await succeedOrThrow(() =>
-        this.api.getAccount({ username, token })
-      )
-      const exchangeInfo = await succeedOrThrow(() =>
-        this.api.getAccount({ username: exchangeUser, token: exchangeToken })
-      )
-
-      await failOrThrow("invalid-id", () =>
-        this.api.abortWithdrawalById("invalid")
-      )
-      await failOrThrow("not-found", () =>
-        this.api.abortWithdrawalById("11111111-1111-1111-1111-111111111111")
-      )
-
-      const { withdrawal_id: firstWithdrawal } = await succeedOrThrow(() =>
-        this.api.createWithdrawal({ username, token }, {
-          amount: userInfo.balance.amount
-        })
-      )
-
-      await succeedOrThrow(() =>
-        this.api.abortWithdrawalById(firstWithdrawal)
-      )
-
-      const { taler_withdraw_uri: uri, withdrawal_id: secondWithdrawal } = 
await succeedOrThrow(() =>
-        this.api.createWithdrawal({ username, token }, {
-          amount: userInfo.balance.amount
-        })
-      )
-
-      await succeedOrThrow(() =>
-        
this.api.getIntegrationAPI().completeWithdrawalOperationById(secondWithdrawal, {
-          reserve_pub: encodeCrock(getRandomBytes(32)),
-          selected_exchange: exchangeInfo.payto_uri,
-        })
-      )
-      await succeedOrThrow(() =>
-        this.api.confirmWithdrawalById(secondWithdrawal)
-      )
-      await failOrThrow("previously-confirmed", () =>
-        this.api.abortWithdrawalById(secondWithdrawal)
-      )
-    }
-
-    /**
-     * confirm withdrawal
-     */
-    {
-      const { username: exchangeUser, token: exchangeToken } = await 
createRandomTestUser(this.api, adminToken, { is_taler_exchange: true })
-      const { username, token } = await createRandomTestUser(this.api, 
adminToken)
-
-      const userInfo = await succeedOrThrow(() =>
-        this.api.getAccount({ username, token })
-      )
-      const exchangeInfo = await succeedOrThrow(() =>
-        this.api.getAccount({ username: exchangeUser, token: exchangeToken })
-      )
-
-      await failOrThrow("invalid-id", () =>
-        this.api.confirmWithdrawalById("invalid")
-      )
-      await failOrThrow("not-found", () =>
-        this.api.confirmWithdrawalById("11111111-1111-1111-1111-111111111111")
-      )
-
-      const { withdrawal_id: firstWithdrawal } = await succeedOrThrow(() =>
-        this.api.createWithdrawal({ username, token }, {
-          amount: userInfo.balance.amount
-        })
-      )
-
-      await failOrThrow("no-exchange-or-reserve-selected", () =>
-        this.api.confirmWithdrawalById(firstWithdrawal)
-      )
-
-      await succeedOrThrow(() =>
-        
this.api.getIntegrationAPI().completeWithdrawalOperationById(firstWithdrawal, {
-          reserve_pub: encodeCrock(getRandomBytes(32)),
-          selected_exchange: exchangeInfo.payto_uri,
-        })
-      )
-
-      await succeedOrThrow(() =>
-        this.api.confirmWithdrawalById(firstWithdrawal)
-      )
-
-      const { withdrawal_id: secondWithdrawal } = await succeedOrThrow(() =>
-        this.api.createWithdrawal({ username, token }, {
-          amount: userInfo.balance.amount
-        })
-      )
-
-      await succeedOrThrow(() =>
-        this.api.abortWithdrawalById(secondWithdrawal)
-      )
-      //FIXME: skip
-      // await failOrThrow("previously-aborted", () =>
-      //   this.api.confirmWithdrawalById(secondWithdrawal)
-      // )
-    }
+import { AccessToken, Amounts, TalerCoreBankHttpClient, TalerCorebankApi, 
TestForApi, buildPayto, encodeCrock, failOrThrow, getRandomBytes, 
parsePaytoUri, stringifyPaytoUri, succeedOrThrow } from "@gnu-taler/taler-util"
+
+
+
+export function createTestForBankCore(adminToken: AccessToken): 
TestForApi<TalerCoreBankHttpClient> {
+  return {
+    test_abortCashoutById: {
+      success: undefined,
+      "already-confirmed": undefined,
+      "cashout-not-supported": undefined,
+      "not-found": undefined,
+    },
+    test_createCashout: {
+      "account-not-found": undefined,
+      "incorrect-exchange-rate": undefined,
+      "no-contact-info": undefined,
+      "no-enough-balance": undefined,
+      "cashout-not-supported": undefined,
+      success: undefined,
+    },
+    test_confirmCashoutById: {
+      "cashout-address-changed": undefined,
+      "cashout-not-supported": undefined,
+      "not-found": undefined,
+      "wrong-tan-or-credential": undefined,
+      success: undefined,
+    },
+    test_getAccountCashouts: {
+      "cashout-not-supported": undefined,
+      "account-not-found": undefined,
+      success: undefined,
+    },
+    test_getCashoutById: {
+      "cashout-not-supported": undefined,
+      success: undefined,
+      "not-found": undefined,
+    },
+    test_getCashoutRate: {
+      "cashout-not-supported": undefined,
+      "not-supported": undefined,
+      "wrong-calculation": undefined,
+      success: undefined,
+    },
+    test_getGlobalCashouts: {
+      "cashout-not-supported": undefined,
+      success: undefined,
+    },
+    test_abortWithdrawalById: {
+      "invalid-id": async (api) => {
+        await failOrThrow("invalid-id", () =>
+          api.abortWithdrawalById("invalid")
+        )
+      },
+      "not-found": async (api) => {
+        await failOrThrow("not-found", () =>
+          api.abortWithdrawalById("11111111-1111-1111-1111-111111111111")
+        )
+      },
+      "previously-confirmed": async (api) => {
+        const { username: exchangeUser, token: exchangeToken } = await 
createRandomTestUser(api, adminToken, { is_taler_exchange: true })
+        const { username, token } = await createRandomTestUser(api, adminToken)
+
+        const userInfo = await succeedOrThrow(() =>
+          api.getAccount({ username, token })
+        )
+        const exchangeInfo = await succeedOrThrow(() =>
+          api.getAccount({ username: exchangeUser, token: exchangeToken })
+        )
+
+        const { withdrawal_id } = await succeedOrThrow(() =>
+          api.createWithdrawal({ username, token }, {
+            amount: userInfo.balance.amount
+          })
+        )
+
+        await succeedOrThrow(() =>
+          
api.getIntegrationAPI().completeWithdrawalOperationById(withdrawal_id, {
+            reserve_pub: encodeCrock(getRandomBytes(32)),
+            selected_exchange: exchangeInfo.payto_uri,
+          })
+        )
+        await succeedOrThrow(() =>
+          api.confirmWithdrawalById(withdrawal_id)
+        )
+        await failOrThrow("previously-confirmed", () =>
+          api.abortWithdrawalById(withdrawal_id)
+        )
+      },
+      success: async (api) => {
+        const { username, token } = await createRandomTestUser(api, adminToken)
+
+        const userInfo = await succeedOrThrow(() =>
+          api.getAccount({ username, token })
+        )
+
+        const { withdrawal_id: firstWithdrawal } = await succeedOrThrow(() =>
+          api.createWithdrawal({ username, token }, {
+            amount: userInfo.balance.amount
+          })
+        )
+
+        await succeedOrThrow(() =>
+          api.abortWithdrawalById(firstWithdrawal)
+        )
+      },
+    },
+    test_confirmWithdrawalById: {
+      "insufficient-funds": async (api) => {
+
+      },
+      "invalid-id": async (api) => {
+        await failOrThrow("invalid-id", () =>
+          api.confirmWithdrawalById("invalid")
+        )
+      },
+      "no-exchange-or-reserve-selected": async (api) => {
+        const { username, token } = await createRandomTestUser(api, adminToken)
+
+        const userInfo = await succeedOrThrow(() =>
+          api.getAccount({ username, token })
+        )
+
+        const { withdrawal_id } = await succeedOrThrow(() =>
+          api.createWithdrawal({ username, token }, {
+            amount: userInfo.balance.amount
+          })
+        )
+
+        await failOrThrow("no-exchange-or-reserve-selected", () =>
+          api.confirmWithdrawalById(withdrawal_id)
+        )
+      },
+      "not-found": async (api) => {
+        await failOrThrow("not-found", () =>
+          api.confirmWithdrawalById("11111111-1111-1111-1111-111111111111")
+        )
+      },
+      "previously-aborted": async (api) => {
+        const { username, token } = await createRandomTestUser(api, adminToken)
+        const userInfo = await succeedOrThrow(() =>
+          api.getAccount({ username, token })
+        )
+        const { withdrawal_id } = await succeedOrThrow(() =>
+          api.createWithdrawal({ username, token }, {
+            amount: userInfo.balance.amount
+          })
+        )
+
+        await succeedOrThrow(() =>
+          api.abortWithdrawalById(withdrawal_id)
+        )
+        await failOrThrow("previously-aborted", () =>
+          api.confirmWithdrawalById(withdrawal_id)
+        )
+      },
+      success: async (api) => {
+        const { username: exchangeUser, token: exchangeToken } = await 
createRandomTestUser(api, adminToken, { is_taler_exchange: true })
+        const { username, token } = await createRandomTestUser(api, adminToken)
+
+        const userInfo = await succeedOrThrow(() =>
+          api.getAccount({ username, token })
+        )
+        const exchangeInfo = await succeedOrThrow(() =>
+          api.getAccount({ username: exchangeUser, token: exchangeToken })
+        )
+
+        const { withdrawal_id } = await succeedOrThrow(() =>
+          api.createWithdrawal({ username, token }, {
+            amount: userInfo.balance.amount
+          })
+        )
+
+        await succeedOrThrow(() =>
+          
api.getIntegrationAPI().completeWithdrawalOperationById(withdrawal_id, {
+            reserve_pub: encodeCrock(getRandomBytes(32)),
+            selected_exchange: exchangeInfo.payto_uri,
+          })
+        )
+
+        await succeedOrThrow(() =>
+          api.confirmWithdrawalById(withdrawal_id)
+        )
+
+      },
+    },
+    test_createAccount: {
+      "insufficient-funds": undefined,
+      "payto-already-exists": async (api) => {
+        const { username, token } = await createRandomTestUser(api, adminToken)
+
+        const userInfo = await succeedOrThrow(() =>
+          api.getAccount({ username, token })
+        )
+
+        const anotherUsername = "harness-" + 
encodeCrock(getRandomBytes(10)).toLowerCase();
+        await failOrThrow("payto-already-exists", () =>
+          api.createAccount(adminToken, {
+            name: anotherUsername,
+            username: anotherUsername,
+            password: "123",
+            internal_payto_uri: userInfo.payto_uri,
+          })
+        );
+
+      },
+      "username-reserved": async (api) => {
+        await failOrThrow("username-reserved", () =>
+          api.createAccount(adminToken, {
+            name: "admin",
+            username: "admin", password: "123"
+          })
+        )
+      },
+      "username-already-exists": async (api) => {
+        const username = "harness-" + 
encodeCrock(getRandomBytes(10)).toLowerCase();
+        await succeedOrThrow(() =>
+          api.createAccount(adminToken, {
+            name: username,
+            username, password: "123"
+          })
+        )
+
+        await failOrThrow("username-already-exists", () =>
+          api.createAccount(adminToken, {
+            name: username,
+            username, password: "123"
+          })
+        );
+      },
+      "invalid-phone-or-email": async (api) => {
+        const username = "harness-" + 
encodeCrock(getRandomBytes(10)).toLowerCase();
+        await failOrThrow("invalid-input", () =>
+          api.createAccount(adminToken, {
+            name: username,
+            username, password: "123",
+            challenge_contact_data: {
+              email: "invalid email",
+              phone: "invalid phone",
+            }
+          })
+        )
+      },
+      success: async (api) => {
+        const username = "harness-" + 
encodeCrock(getRandomBytes(10)).toLowerCase();
+
+        await succeedOrThrow(() =>
+          api.createAccount(adminToken, {
+            name: username,
+            username, password: "123"
+          })
+        )
+      },
+      unauthorized: async (api) => {
+        const username = "harness-" + 
encodeCrock(getRandomBytes(10)).toLowerCase();
+
+        await succeedOrThrow(() =>
+          api.createAccount(adminToken, {
+            name: username,
+            username, password: "123"
+          })
+        )
+
+        const { access_token } = await succeedOrThrow(() =>
+          api.getAuthenticationAPI(username).createAccessToken("123", {
+            scope: "readwrite"
+          })
+        )
+
+        const anotherUser = "harness-" + 
encodeCrock(getRandomBytes(10)).toLowerCase();
+        await failOrThrow("unauthorized", () =>
+          api.createAccount(access_token, {
+            name: anotherUser,
+            username: anotherUser, password: "123"
+          })
+        )
+
+      },
+
+    },
+    test_createTransaction: {
+      "creditor-not-found": async (api) => {
+        const { username, token } = await createRandomTestUser(api, adminToken)
+
+        const userInfo = await succeedOrThrow(() =>
+          api.getAccount({ username, token })
+        )
+
+        const notFoundAccount = buildPayto("iban", "DE1231231231", undefined)
+        notFoundAccount.params["message"] = "not-found"
+        await failOrThrow("creditor-not-found", () =>
+          api.createTransaction({ username, token }, {
+            payto_uri: stringifyPaytoUri(notFoundAccount),
+            amount: userInfo.balance.amount
+          })
+        )
+      },
+      "creditor-same": async (api) => {
+        const { username, token } = await createRandomTestUser(api, adminToken)
+
+        const userInfo = await succeedOrThrow(() =>
+          api.getAccount({ username, token })
+        )
+        const account = parsePaytoUri(userInfo.payto_uri)!
+        account.params["message"] = "myaccount"
+
+        await failOrThrow("creditor-same", () =>
+          api.createTransaction({ username, token }, {
+            payto_uri: stringifyPaytoUri(account),
+            amount: userInfo.balance.amount
+          })
+        )
+
+      },
+      "insufficient-funds": async (api) => {
+        const { username, token } = await createRandomTestUser(api, adminToken)
+        const { username: otherUser, token: otherToken } = await 
createRandomTestUser(api, adminToken)
+
+        const userInfo = await succeedOrThrow(() =>
+          api.getAccount({ username, token })
+        )
+        const otherInfo = await succeedOrThrow(() =>
+          api.getAccount({ username: otherUser, token: otherToken })
+        )
+        const otherAccount = parsePaytoUri(otherInfo.payto_uri)!
+        otherAccount.params["message"] = "all"
+
+        await failOrThrow("insufficient-funds", () =>
+          api.createTransaction({ username, token }, {
+            payto_uri: stringifyPaytoUri(otherAccount),
+            amount: Amounts.stringify(Amounts.mult(userInfo.balance.amount, 
20).amount)
+          })
+        )
+      },
+      "not-found": async (api) => {
+        const { username, token } = await createRandomTestUser(api, adminToken)
+        const { username: otherUser, token: otherToken } = await 
createRandomTestUser(api, adminToken)
+
+        const userInfo = await succeedOrThrow(() =>
+          api.getAccount({ username, token })
+        )
+        const otherInfo = await succeedOrThrow(() =>
+          api.getAccount({ username: otherUser, token: otherToken })
+        )
+        const otherAccount = parsePaytoUri(otherInfo.payto_uri)!
+        otherAccount.params["message"] = "all"
+
+        await succeedOrThrow(() =>
+          api.createTransaction({ username: "notfound", token }, {
+            payto_uri: stringifyPaytoUri(otherAccount),
+            amount: userInfo.balance.amount
+          })
+        )
+      },
+      "invalid-input": async (api) => {
+        const { username, token } = await createRandomTestUser(api, adminToken)
+        const { username: otherUser, token: otherToken } = await 
createRandomTestUser(api, adminToken)
+
+        const userInfo = await succeedOrThrow(() =>
+          api.getAccount({ username, token })
+        )
+        const otherInfo = await succeedOrThrow(() =>
+          api.getAccount({ username: otherUser, token: otherToken })
+        )
+        const otherAccount = parsePaytoUri(otherInfo.payto_uri)!
+        otherAccount.params["message"] = "all"
+
+        //missing amount
+        await failOrThrow("invalid-input", () =>
+          api.createTransaction({ username, token }, {
+            payto_uri: stringifyPaytoUri(otherAccount),
+            // amount: userInfo.balance.amount
+          })
+        )
+        //missing subject
+        await failOrThrow("invalid-input", () =>
+          api.createTransaction({ username, token }, {
+            payto_uri: otherInfo.payto_uri,
+            amount: userInfo.balance.amount
+          })
+        )
+
+      },
+      success: async (api) => {
+        const { username, token } = await createRandomTestUser(api, adminToken)
+        const { username: otherUser, token: otherToken } = await 
createRandomTestUser(api, adminToken)
+
+        const userInfo = await succeedOrThrow(() =>
+          api.getAccount({ username, token })
+        )
+        const otherInfo = await succeedOrThrow(() =>
+          api.getAccount({ username: otherUser, token: otherToken })
+        )
+        const otherAccount = parsePaytoUri(otherInfo.payto_uri)!
+        otherAccount.params["message"] = "all"
+
+        await succeedOrThrow(() =>
+          api.createTransaction({ username, token }, {
+            payto_uri: stringifyPaytoUri(otherAccount),
+            amount: userInfo.balance.amount
+          })
+        )
+
+      },
+      unauthorized: async (api) => {
+        const { username, token } = await createRandomTestUser(api, adminToken)
+        const { username: otherUser, token: otherToken } = await 
createRandomTestUser(api, adminToken)
+
+        const userInfo = await succeedOrThrow(() =>
+          api.getAccount({ username, token })
+        )
+        const otherInfo = await succeedOrThrow(() =>
+          api.getAccount({ username: otherUser, token: otherToken })
+        )
+        const otherAccount = parsePaytoUri(otherInfo.payto_uri)!
+        otherAccount.params["message"] = "all"
+
+        await failOrThrow("unauthorized", () =>
+          api.createTransaction({ username, token: "wrongtoken" as AccessToken 
}, {
+            payto_uri: stringifyPaytoUri(otherAccount),
+            amount: userInfo.balance.amount
+          })
+        )
+      },
+    },
+    test_createWithdrawal: {
+      "account-not-found": async (api) => {
+        const userInfo = await succeedOrThrow(() =>
+          api.getAccount({ username: "admin", token: adminToken })
+        )
+        await succeedOrThrow(() =>
+          api.createWithdrawal({ username: "notfound", token: adminToken }, {
+            amount: userInfo.balance.amount
+          })
+        )
+
+      },
+      "insufficient-funds": async (api) => {
+        const { username, token } = await createRandomTestUser(api, adminToken)
+        const userInfo = await succeedOrThrow(() =>
+          api.getAccount({ username, token })
+        )
+
+        const balance = Amounts.parseOrThrow(userInfo.balance.amount)
+        const moreThanBalance = Amounts.stringify(Amounts.mult(balance, 
5).amount)
+        await failOrThrow("insufficient-funds", () =>
+          api.createWithdrawal({ username, token }, {
+            amount: moreThanBalance
+          })
+        )
+      },
+      success: async (api) => {
+        const { username, token } = await createRandomTestUser(api, adminToken)
+        const userInfo = await succeedOrThrow(() =>
+          api.getAccount({ username, token })
+        )
+        await succeedOrThrow(() =>
+          api.createWithdrawal({ username, token }, {
+            amount: userInfo.balance.amount
+          })
+        )
+
+      },
+      unauthorized: async (api) => {
+        const { username, token } = await createRandomTestUser(api, adminToken)
+        const userInfo = await succeedOrThrow(() =>
+          api.getAccount({ username, token })
+        )
+        await failOrThrow("unauthorized", () =>
+          api.createWithdrawal({ username, token: "wrongtoken" as AccessToken 
}, {
+            amount: userInfo.balance.amount
+          })
+        )
+
+      },
+    },
+    test_deleteAccount: {
+      "balance-not-zero": async (api) => {
+        const { username, token } = await createRandomTestUser(api, adminToken)
+
+        await failOrThrow("balance-not-zero", () =>
+          api.deleteAccount({ username, token: adminToken })
+        )
+
+      },
+      "not-found": async (api) => {
+        await failOrThrow("not-found", () =>
+          api.deleteAccount({ username: "not-found", token: adminToken })
+        )
+      },
+      "username-reserved": async (api) => {
+        await failOrThrow("username-reserved", () =>
+          api.deleteAccount({ username: "admin", token: adminToken })
+        )
+        await failOrThrow("username-reserved", () =>
+          api.deleteAccount({ username: "bank", token: adminToken })
+        )
+      },
+      success: async (api) => {
+        const { username, token } = await createRandomTestUser(api, adminToken)
+
+        const userInfo = await succeedOrThrow(() =>
+          api.getAccount({ username, token })
+        )
+
+        const adminInfo = await succeedOrThrow(() =>
+          api.getAccount({ username: "admin", token: adminToken })
+        )
+
+        const adminAccount = parsePaytoUri(adminInfo.payto_uri)!
+        adminAccount.params["message"] = "all my money"
+        const withSubject = stringifyPaytoUri(adminAccount)
+
+        await succeedOrThrow(() =>
+          api.createTransaction({ username, token }, {
+            payto_uri: withSubject,
+            amount: userInfo.balance.amount
+          })
+        )
+
+      },
+      unauthorized: async (api) => {
+        const username = "harness-" + 
encodeCrock(getRandomBytes(10)).toLowerCase();
+
+        await succeedOrThrow(() =>
+          api.createAccount(adminToken, {
+            name: username,
+            username, password: "123"
+          })
+        )
+
+        const { token } = await createRandomTestUser(api, adminToken)
+        await failOrThrow("unauthorized", () =>
+          api.deleteAccount({ username: username, token })
+        )
+
+      },
+    },
+    test_getAccount: {
+      "not-found": async (api) => {
+        await failOrThrow("not-found", () =>
+          api.getAccount({ username: "not-found", token: adminToken })
+        )
+
+      },
+      success: async (api) => {
+        const { username, token } = await createRandomTestUser(api, adminToken)
+        await succeedOrThrow(() =>
+          api.getAccount({ username, token })
+        )
+      },
+      unauthorized: async (api) => {
+        const { username, token } = await createRandomTestUser(api, adminToken)
+        await failOrThrow("unauthorized", () =>
+          api.getAccount({ username, token: "wrongtoken" as AccessToken })
+        )
+      },
+    },
+    test_getAccounts: {
+      success: async (api) => {
+        await succeedOrThrow(() =>
+          api.getAccounts(adminToken)
+        )
+        await succeedOrThrow(() =>
+          api.getAccounts(adminToken, {
+            account: "admin"
+          })
+        )
+        await succeedOrThrow(() =>
+          api.getAccounts(adminToken, undefined, {
+            order: "dec",
+            limit: 10,
+            offset: "1"
+          })
+        )
+      },
+      unauthorized: async (api) => {
+        await failOrThrow("unauthorized", () =>
+          api.getAccounts("ASDASD" as AccessToken)
+        )
+      },
+    },
+    test_getConfig: {
+      success: async (api) => {
+        const config = await succeedOrThrow(() => api.getConfig())
+
+        if (!api.isCompatible(config.version)) {
+          throw Error(`not compatible with server ${config.version}`)
+        }
+
+      },
+    },
+    test_getMonitor: {
+      "unauthorized": async (api) => {
+        await failOrThrow("unauthorized", () => (
+          api.getMonitor("wrongtoken" as AccessToken)
+        ))
+
+      },
+      "invalid-input": async (api) => {
+
+        await failOrThrow("invalid-input", () => (
+          api.getMonitor(adminToken, {
+            timeframe: TalerCorebankApi.MonitorTimeframeParam.day,
+            which: 100
+          })
+        ))
+
+      },
+      "monitor-not-supported": undefined,
+      success: async (api) => {
+
+        await succeedOrThrow(() => (
+          api.getMonitor(adminToken)
+        ))
+
+        await succeedOrThrow(() => (
+          api.getMonitor(adminToken, {
+            timeframe: TalerCorebankApi.MonitorTimeframeParam.day,
+            which: (new Date()).getDate() - 1
+          })
+        ))
+
+      },
+    },
+    test_getPublicAccounts: {
+      success: async (api) => {
+        await succeedOrThrow(() => (
+          api.getPublicAccounts()
+        ))
+
+        await succeedOrThrow(() => (
+          api.getPublicAccounts({
+            order: "asc"
+          })
+        ))
+        await succeedOrThrow(() => (
+          api.getPublicAccounts({
+            order: "dec"
+          })
+        ))
+        await succeedOrThrow(() => (
+          api.getPublicAccounts({
+            order: "dec", limit: 10, offset: String(1)
+          })
+        ))
+      },
+    },
+    test_getTransactionById: {
+      "not-found": async (api) => {
+        const { username, token } = await createRandomTestUser(api, adminToken)
+        await failOrThrow("not-found", () =>
+          api.getTransactionById({ username, token }, 123123123)
+        )
+      },
+      success: async (api) => {
+        const { username, token } = await createRandomTestUser(api, adminToken)
+        const { username: otherUser, token: otherToken } = await 
createRandomTestUser(api, adminToken)
+
+        const userInfo = await succeedOrThrow(() =>
+          api.getAccount({ username, token })
+        )
+        const otherInfo = await succeedOrThrow(() =>
+          api.getAccount({ username: otherUser, token: otherToken })
+        )
+        const otherAccount = parsePaytoUri(otherInfo.payto_uri)!
+        otherAccount.params["message"] = "all"
+
+        await succeedOrThrow(() =>
+          api.createTransaction({ username, token }, {
+            payto_uri: stringifyPaytoUri(otherAccount),
+            amount: userInfo.balance.amount
+          })
+        )
+
+        const txs = await succeedOrThrow(() => api.getTransactions({ username, 
token }, {
+          limit: 5,
+          order: "asc"
+        }))
+        const rowId = txs.transactions[0].row_id
+
+        await succeedOrThrow(() =>
+          api.getTransactionById({ username, token }, rowId)
+        )
+
+      },
+      unauthorized: async (api) => {
+        const { username, token } = await createRandomTestUser(api, adminToken)
+        await failOrThrow("unauthorized", () =>
+          api.getTransactionById({ username, token: "wrongtoken" as 
AccessToken }, 123123123)
+        )
+      },
+    },
+    test_getTransactions: {
+      "not-found": async (api) => {
+        await failOrThrow("not-found", () => api.getTransactions({
+          username: "not-found",
+          token: adminToken,
+        }))
+      },
+      success: async (api) => {
+        const { username, token } = await createRandomTestUser(api, adminToken)
+        // await succeedOrThrow(() => api.getTransactions(creds))
+        const txs = await succeedOrThrow(() => api.getTransactions({ username, 
token }, {
+          limit: 5,
+          order: "asc"
+        }))
+      },
+      unauthorized: async (api) => {
+        const { username, token } = await createRandomTestUser(api, adminToken)
+
+        await failOrThrow("unauthorized", () => api.getTransactions({
+          username: username,
+          token: "wrongtoken" as AccessToken,
+        }))
+
+      },
+    },
+    test_getWithdrawalById: {
+      "invalid-id": async (api) => {
+
+        await failOrThrow("invalid-id", () =>
+          api.getWithdrawalById("invalid")
+        )
+
+      },
+      "not-found": async (api) => {
+        await failOrThrow("not-found", () =>
+          api.getWithdrawalById("11111111-1111-1111-1111-111111111111")
+        )
+
+      },
+      success: async (api) => {
+        const { username, token } = await createRandomTestUser(api, adminToken)
+        const userInfo = await succeedOrThrow(() =>
+          api.getAccount({ username, token })
+        )
+        const { withdrawal_id } = await succeedOrThrow(() =>
+          api.createWithdrawal({ username, token }, {
+            amount: userInfo.balance.amount
+          })
+        )
+        await succeedOrThrow(() =>
+          api.getWithdrawalById(withdrawal_id)
+        )
+      },
+    },
+    test_updateAccount: {
+      "cant-change-legal-name-or-admin": async (api) => {
+        const { username, token } = await createRandomTestUser(api, adminToken)
+
+        await failOrThrow("cant-change-legal-name-or-admin", () =>
+          api.updateAccount({ username, token }, {
+            name: "something else",
+          })
+        )
+
+      },
+      "not-found": async (api) => {
+        const { username, token } = await createRandomTestUser(api, adminToken)
+        await failOrThrow("not-found", () =>
+          api.updateAccount({ username: "notfound", token }, {
+            challenge_contact_data: {
+              email: "asd@Aasd.com"
+            }
+          })
+        )
+      },
+      success: async (api) => {
+        const { username, token } = await createRandomTestUser(api, adminToken)
+
+        await succeedOrThrow(() =>
+          api.updateAccount({ username, token }, {
+            challenge_contact_data: {
+              email: "asd@Aasd.com"
+            }
+          })
+        )
+
+      },
+      unauthorized: async (api) => {
+
+        await failOrThrow("unauthorized", () =>
+          api.updateAccount({ username: "notfound", token: "wrongtoken" as 
AccessToken }, {
+            challenge_contact_data: {
+              email: "asd@Aasd.com"
+            }
+          })
+        )
+      },
+    },
+    test_updatePassword: {
+      "not-found": async (api) => {
+
+        await failOrThrow("not-found", () =>
+          api.updatePassword({ username: "notfound", token: adminToken }, {
+            old_password: "123",
+            new_password: "234"
+          })
+        )
+
+
+      },
+      "old-password-invalid-or-not-allowed": async (api) => {
+        const { username, token } = await createRandomTestUser(api, adminToken)
+
+        await failOrThrow("old-password-invalid-or-not-allowed", () =>
+          api.updatePassword({ username, token }, {
+            old_password: "1233",
+            new_password: "234"
+          })
+        )
+
+      },
+      success: async (api) => {
+        const { username, token } = await createRandomTestUser(api, adminToken)
+
+        await succeedOrThrow(() =>
+          api.updatePassword({ username, token }, {
+            old_password: "123",
+            new_password: "234"
+          })
+        )
+
+
+      },
+      unauthorized: async (api) => {
+        const { username, token } = await createRandomTestUser(api, adminToken)
+        await failOrThrow("unauthorized", () =>
+          api.updatePassword({ username: "admin", token }, {
+            old_password: "123",
+            new_password: "234"
+          })
+        )
+
+
+      },
+    },
   }
-
-  async testTransactions(adminPassword: string) {
-    const { access_token: adminToken } = await succeedOrThrow(() =>
-      this.api.getAuthenticationAPI("admin").createAccessToken(adminPassword, {
-        scope: "readwrite"
-      })
-    )
-    // get transactions
-    {
-      const { username, token } = await createRandomTestUser(this.api, 
adminToken)
-      // await succeedOrThrow(() => this.api.getTransactions(creds))
-      const txs = await succeedOrThrow(() => this.api.getTransactions({ 
username, token }, {
-        limit: 5,
-        order: "asc"
-      }))
-      // await failOrThrow("not-found",() => this.api.getTransactions({
-      //   username:"not-found",
-      //   token: creds.token,
-      // }))
-      await failOrThrow("unauthorized", () => this.api.getTransactions({
-        username: username,
-        token: "wrongtoken" as AccessToken,
-      }))
-    }
-
-    /**
-     * getTxby id
-     */
-    {
-      const { username, token } = await createRandomTestUser(this.api, 
adminToken)
-      const { username: otherUser, token: otherToken } = await 
createRandomTestUser(this.api, adminToken)
-
-      const userInfo = await succeedOrThrow(() =>
-        this.api.getAccount({ username, token })
-      )
-      const otherInfo = await succeedOrThrow(() =>
-        this.api.getAccount({ username: otherUser, token: otherToken })
-      )
-      const otherAccount = parsePaytoUri(otherInfo.payto_uri)!
-      otherAccount.params["message"] = "all"
-
-      await succeedOrThrow(() =>
-        this.api.createTransaction({ username, token }, {
-          payto_uri: stringifyPaytoUri(otherAccount),
-          amount: userInfo.balance.amount
-        })
-      )
-
-      const txs = await succeedOrThrow(() => this.api.getTransactions({ 
username, token }, {
-        limit: 5,
-        order: "asc"
-      }))
-      const rowId = txs.transactions[0].row_id
-
-      await succeedOrThrow(() =>
-        this.api.getTransactionById({ username, token }, rowId)
-      )
-
-      await failOrThrow("not-found", () =>
-        this.api.getTransactionById({ username, token }, 123123123)
-      )
-
-      await failOrThrow("unauthorized", () =>
-        this.api.getTransactionById({ username, token: "wrongtoken" as 
AccessToken }, 123123123)
-      )
-    }
-
-    /**
-     * create transactions
-     */
-    {
-      const { username, token } = await createRandomTestUser(this.api, 
adminToken)
-      const { username: otherUser, token: otherToken } = await 
createRandomTestUser(this.api, adminToken)
-
-      const userInfo = await succeedOrThrow(() =>
-        this.api.getAccount({ username, token })
-      )
-      const otherInfo = await succeedOrThrow(() =>
-        this.api.getAccount({ username: otherUser, token: otherToken })
-      )
-      const otherAccount = parsePaytoUri(otherInfo.payto_uri)!
-      otherAccount.params["message"] = "all"
-
-      await succeedOrThrow(() =>
-        this.api.createTransaction({ username, token }, {
-          payto_uri: stringifyPaytoUri(otherAccount),
-          amount: userInfo.balance.amount
-        })
-      )
-      //missing amount
-      await failOrThrow("invalid-input", () =>
-        this.api.createTransaction({ username, token }, {
-          payto_uri: stringifyPaytoUri(otherAccount),
-          // amount: userInfo.balance.amount
-        })
-      )
-      //missing subject
-      await failOrThrow("invalid-input", () =>
-        this.api.createTransaction({ username, token }, {
-          payto_uri: otherInfo.payto_uri,
-          amount: userInfo.balance.amount
-        })
-      )
-      await failOrThrow("unauthorized", () =>
-        this.api.createTransaction({ username, token: "wrongtoken" as 
AccessToken }, {
-          payto_uri: otherInfo.payto_uri,
-          amount: userInfo.balance.amount
-        })
-      )
-
-      const notFoundAccount = buildPayto("iban", "DE1231231231", undefined)
-      notFoundAccount.params["message"] = "not-found"
-      await failOrThrow("account-not-found", () =>
-        this.api.createTransaction({ username, token }, {
-          payto_uri: stringifyPaytoUri(notFoundAccount),
-          amount: userInfo.balance.amount
-        })
-      )
-    }
-  }
-
-
 }
 
 export async function createRandomTestUser(api: TalerCoreBankHttpClient, 
adminToken: AccessToken, options: 
Partial<TalerCorebankApi.RegisterAccountRequest> = {}) {
diff --git a/packages/taler-harness/src/index.ts 
b/packages/taler-harness/src/index.ts
index 717aee57d..af4e5c788 100644
--- a/packages/taler-harness/src/index.ts
+++ b/packages/taler-harness/src/index.ts
@@ -51,7 +51,7 @@ import {
 } from "@gnu-taler/taler-wallet-core";
 import { deepStrictEqual } from "assert";
 import fs from "fs";
-import { BankCoreSmokeTest } from "http-client/bank-core.js";
+import { createRandomTestUser, createTestForBankCore } from 
"http-client/bank-core.js";
 import os from "os";
 import path from "path";
 import { runBench1 } from "./bench1.js";
@@ -667,68 +667,69 @@ deploymentCli
     const httpLib = createPlatformHttpLib();
     const api = new 
TalerCoreBankHttpClient(args.testBankAPI.corebankApiBaseUrl, httpLib);
 
-    const tester = new BankCoreSmokeTest(api)
+    process.stdout.write("config: ");
+    const config = await api.getConfig()
+    if (!api.isCompatible(config.body.version)) {
+      console.log("fail")
+      return;
+    } else {
+      console.log("ok")
+    }
+
+    if (!args.testBankAPI.adminPwd) {
+      console.log("no admin password, exit")
+      return;
+    }
+
+    const resp = await 
api.getAuthenticationAPI("admin").createAccessToken(args.testBankAPI.adminPwd, {
+      scope: "readwrite"
+    })
+
+    if (resp.type === "fail") {
+      console.log("wrong admin password")
+      return;
+    }
+    const tester = createTestForBankCore(resp.body.access_token)
+
     if (args.testBankAPI.showCurl) {
       setPrintHttpRequestAsCurl(true)
     }
-    try {
-      process.stdout.write("config: ");
-      const config = await tester.testConfig()
-      console.log("ok")
-      const admin = args.testBankAPI.adminPwd
-      process.stdout.write("account management: ");
-      const withAdmin = !!admin && admin !== "-"
-      if (withAdmin) {
-        await tester.testAccountManagement(admin)
-        console.log("ok")
-      } else {
-        console.log("skipped")
-      }
-
-      process.stdout.write("transactions: ");
-      if (withAdmin) {
-        await tester.testTransactions(admin)
-        console.log("ok")
-      } else {
-        console.log("skipped")
-      }
 
-      process.stdout.write("withdrawals: ");
-      if (withAdmin) {
-        await tester.testWithdrawals(admin)
-        console.log("ok")
-      } else {
-        console.log("skipped")
+    const apiState = await 
Promise.all(Object.entries(tester).flatMap(([testName, casesMap]) => {
+      return Object.entries(casesMap).map(([caseName, caseFunc]) => {
+        if (!caseFunc) {
+          return { testName, caseName, result: "skiped" as const }
+        }
+        return caseFunc(api)
+          .then(r => ({ testName, caseName, result: "ok" as const }))
+          .catch(error => ({ testName, caseName, result: "fail" as const, 
error }))
+      })
+    }))
+
+    const total = apiState.reduce((prev, testResult) => {
+      if (testResult.result === "ok") {
+        prev.ok += 1
       }
-
-      process.stdout.write("monitor: ");
-      if (withAdmin && config.have_cashout) {
-        await tester.testMonitor(admin)
-        console.log("ok")
-      } else {
-        console.log("skipped")
+      if (testResult.result === "skiped") {
+        prev.skiped += 1
       }
-
-      process.stdout.write("cashout: ");
-      if (withAdmin && config.have_cashout) {
-        await tester.testCashouts(admin)
-        console.log("ok")
-      } else {
-        console.log("skipped")
+      if (testResult.result === "fail") {
+        prev.fail += 1
       }
-
-    } catch (e: any) {
-      console.log("")
-      if (e instanceof TalerError) {
-        console.error("FAILED", JSON.stringify(e.errorDetail, undefined, 2))
-        console.error(e.stack)
-      } else if (e instanceof Error) {
-        console.error(`FAILED: ${e.message}`)
-        console.error(e.stack)
-      } else {
-        console.error(`FAILED: ${e}`)
+      return prev
+    }, { "ok": 0, "skiped": 0, "fail": 0 })
+
+    console.log("successful tests:", total.ok)
+    console.log("uncompleted tests:", total.skiped)
+    apiState.forEach((testResult) => {
+      if (testResult.result === "skiped") {
+        console.log("    ", testResult.testName, testResult.caseName)
       }
-    }
+    })
+    console.log("failed tests:", total.fail)
+    apiState.filter(t => t.result === "fail").forEach((testResult, i) => {
+      console.log(i, ")", testResult)
+    })
   });
 
 

-- 
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]