summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorSebastian <sebasjm@gmail.com>2022-12-15 17:11:24 -0300
committerSebastian <sebasjm@gmail.com>2022-12-15 17:11:24 -0300
commitf93bd51499ed34844b666bf6d333227adf4368bf (patch)
treeed3cf0c38b7db54276436d1743a6085c94f71977
parent8d8d71807df6b775e5b0335eb1b2526a56d42ac6 (diff)
downloadwallet-core-f93bd51499ed34844b666bf6d333227adf4368bf.tar.gz
wallet-core-f93bd51499ed34844b666bf6d333227adf4368bf.tar.bz2
wallet-core-f93bd51499ed34844b666bf6d333227adf4368bf.zip
wxApi from context and using the new testing sdk
-rw-r--r--packages/taler-wallet-webextension/package.json4
-rw-r--r--packages/taler-wallet-webextension/src/NavigationBar.tsx21
-rw-r--r--packages/taler-wallet-webextension/src/components/PendingTransactions.tsx7
-rw-r--r--packages/taler-wallet-webextension/src/components/ShowFullContractTermPopup.tsx7
-rw-r--r--packages/taler-wallet-webextension/src/components/TermsOfService/index.ts5
-rw-r--r--packages/taler-wallet-webextension/src/components/TermsOfService/state.ts4
-rw-r--r--packages/taler-wallet-webextension/src/context/backend.ts53
-rw-r--r--packages/taler-wallet-webextension/src/cta/Deposit/index.ts3
-rw-r--r--packages/taler-wallet-webextension/src/cta/Deposit/state.ts4
-rw-r--r--packages/taler-wallet-webextension/src/cta/Deposit/test.ts80
-rw-r--r--packages/taler-wallet-webextension/src/cta/InvoiceCreate/index.ts3
-rw-r--r--packages/taler-wallet-webextension/src/cta/InvoiceCreate/state.ts8
-rw-r--r--packages/taler-wallet-webextension/src/cta/InvoicePay/index.ts5
-rw-r--r--packages/taler-wallet-webextension/src/cta/InvoicePay/state.ts4
-rw-r--r--packages/taler-wallet-webextension/src/cta/Payment/index.ts5
-rw-r--r--packages/taler-wallet-webextension/src/cta/Payment/state.ts4
-rw-r--r--packages/taler-wallet-webextension/src/cta/Payment/test.ts404
-rw-r--r--packages/taler-wallet-webextension/src/cta/Recovery/index.ts3
-rw-r--r--packages/taler-wallet-webextension/src/cta/Recovery/state.ts6
-rw-r--r--packages/taler-wallet-webextension/src/cta/Refund/index.ts5
-rw-r--r--packages/taler-wallet-webextension/src/cta/Refund/state.ts4
-rw-r--r--packages/taler-wallet-webextension/src/cta/Refund/test.ts349
-rw-r--r--packages/taler-wallet-webextension/src/cta/Tip/index.ts5
-rw-r--r--packages/taler-wallet-webextension/src/cta/Tip/state.ts4
-rw-r--r--packages/taler-wallet-webextension/src/cta/Tip/test.ts271
-rw-r--r--packages/taler-wallet-webextension/src/cta/TransferCreate/index.ts3
-rw-r--r--packages/taler-wallet-webextension/src/cta/TransferCreate/state.ts12
-rw-r--r--packages/taler-wallet-webextension/src/cta/TransferPickup/index.ts5
-rw-r--r--packages/taler-wallet-webextension/src/cta/TransferPickup/state.ts6
-rw-r--r--packages/taler-wallet-webextension/src/cta/Withdraw/index.ts7
-rw-r--r--packages/taler-wallet-webextension/src/cta/Withdraw/state.ts20
-rw-r--r--packages/taler-wallet-webextension/src/cta/Withdraw/test.ts230
-rw-r--r--packages/taler-wallet-webextension/src/hooks/useAutoOpenPermissions.ts12
-rw-r--r--packages/taler-wallet-webextension/src/hooks/useBackupDeviceName.ts7
-rw-r--r--packages/taler-wallet-webextension/src/hooks/useClipboardPermissions.ts12
-rw-r--r--packages/taler-wallet-webextension/src/hooks/useDiagnostics.ts5
-rw-r--r--packages/taler-wallet-webextension/src/hooks/useProviderStatus.ts10
-rw-r--r--packages/taler-wallet-webextension/src/hooks/useWalletDevMode.ts11
-rw-r--r--packages/taler-wallet-webextension/src/popup/BalancePage.tsx14
-rw-r--r--packages/taler-wallet-webextension/src/test-utils.ts14
-rw-r--r--packages/taler-wallet-webextension/src/wallet/AddBackupProvider/index.ts14
-rw-r--r--packages/taler-wallet-webextension/src/wallet/AddBackupProvider/state.ts68
-rw-r--r--packages/taler-wallet-webextension/src/wallet/AddBackupProvider/test.ts57
-rw-r--r--packages/taler-wallet-webextension/src/wallet/BackupPage.tsx9
-rw-r--r--packages/taler-wallet-webextension/src/wallet/DepositPage/index.ts8
-rw-r--r--packages/taler-wallet-webextension/src/wallet/DepositPage/state.ts24
-rw-r--r--packages/taler-wallet-webextension/src/wallet/DepositPage/test.ts373
-rw-r--r--packages/taler-wallet-webextension/src/wallet/DestinationSelection/index.ts3
-rw-r--r--packages/taler-wallet-webextension/src/wallet/DestinationSelection/state.ts4
-rw-r--r--packages/taler-wallet-webextension/src/wallet/DestinationSelection/test.ts113
-rw-r--r--packages/taler-wallet-webextension/src/wallet/DeveloperPage.tsx24
-rw-r--r--packages/taler-wallet-webextension/src/wallet/EmptyComponentExample/index.ts3
-rw-r--r--packages/taler-wallet-webextension/src/wallet/EmptyComponentExample/state.ts3
-rw-r--r--packages/taler-wallet-webextension/src/wallet/ExchangeAddPage.tsx7
-rw-r--r--packages/taler-wallet-webextension/src/wallet/ExchangeSelection/index.ts7
-rw-r--r--packages/taler-wallet-webextension/src/wallet/ExchangeSelection/state.ts14
-rw-r--r--packages/taler-wallet-webextension/src/wallet/History.tsx9
-rw-r--r--packages/taler-wallet-webextension/src/wallet/ManageAccount/index.ts5
-rw-r--r--packages/taler-wallet-webextension/src/wallet/ManageAccount/state.ts6
-rw-r--r--packages/taler-wallet-webextension/src/wallet/Notifications/index.ts5
-rw-r--r--packages/taler-wallet-webextension/src/wallet/Notifications/state.ts5
-rw-r--r--packages/taler-wallet-webextension/src/wallet/ProviderAddPage.tsx6
-rw-r--r--packages/taler-wallet-webextension/src/wallet/ProviderDetailPage.tsx12
-rw-r--r--packages/taler-wallet-webextension/src/wallet/Settings.tsx7
-rw-r--r--packages/taler-wallet-webextension/src/wallet/Transaction.tsx14
-rw-r--r--packages/taler-wallet-webextension/src/wxApi.ts8
-rw-r--r--packages/web-util/src/tests/hook.ts2
67 files changed, 1002 insertions, 1444 deletions
diff --git a/packages/taler-wallet-webextension/package.json b/packages/taler-wallet-webextension/package.json
index 0deca26cc..5c6983bfc 100644
--- a/packages/taler-wallet-webextension/package.json
+++ b/packages/taler-wallet-webextension/package.json
@@ -9,7 +9,7 @@
"private": false,
"scripts": {
"clean": "rimraf dist lib tsconfig.tsbuildinfo",
- "test": "pnpm compile && mocha 'dist/**/*.test.js' 'dist/**/test.js'",
+ "test": "pnpm compile && mocha --require source-map-support/register 'dist/**/*.test.js' 'dist/**/test.js'",
"test:coverage": "nyc pnpm test",
"compile": "tsc && ./build-fast-with-linaria.mjs",
"prepare": "pnpm compile",
@@ -80,4 +80,4 @@
"pogen": {
"domain": "taler-wallet-webex"
}
-} \ No newline at end of file
+}
diff --git a/packages/taler-wallet-webextension/src/NavigationBar.tsx b/packages/taler-wallet-webextension/src/NavigationBar.tsx
index 8fb289aa6..ab36af376 100644
--- a/packages/taler-wallet-webextension/src/NavigationBar.tsx
+++ b/packages/taler-wallet-webextension/src/NavigationBar.tsx
@@ -24,20 +24,20 @@
/**
* Imports.
*/
+import { WalletApiOperation } from "@gnu-taler/taler-wallet-core";
import { Fragment, h, VNode } from "preact";
+import { JustInDevMode } from "./components/JustInDevMode.js";
import {
NavigationHeader,
NavigationHeaderHolder,
SvgIcon,
} from "./components/styled/index.js";
+import { useBackendContext } from "./context/backend.js";
import { useTranslationContext } from "./context/translation.js";
-import settingsIcon from "./svg/settings_black_24dp.svg";
+import { useAsyncAsHook } from "./hooks/useAsyncAsHook.js";
import qrIcon from "./svg/qr_code_24px.svg";
+import settingsIcon from "./svg/settings_black_24dp.svg";
import warningIcon from "./svg/warning_24px.svg";
-import { useAsyncAsHook } from "./hooks/useAsyncAsHook.js";
-import { wxApi } from "./wxApi.js";
-import { WalletApiOperation } from "@gnu-taler/taler-wallet-core";
-import { JustInDevMode } from "./components/JustInDevMode.js";
/**
* List of pages used by the wallet
@@ -133,13 +133,8 @@ export const Pages = {
),
};
-export function PopupNavBar({
- path = "",
-}: {
- path?: string;
-}): // api: typeof wxApi,
-VNode {
- const api = wxApi; //FIXME: as parameter
+export function PopupNavBar({ path = "" }: { path?: string }): VNode {
+ const api = useBackendContext();
const hook = useAsyncAsHook(async () => {
return await api.wallet.call(
WalletApiOperation.GetUserAttentionUnreadCount,
@@ -194,7 +189,7 @@ VNode {
export function WalletNavBar({ path = "" }: { path?: string }): VNode {
const { i18n } = useTranslationContext();
- const api = wxApi; //FIXME: as parameter
+ const api = useBackendContext();
const hook = useAsyncAsHook(async () => {
return await api.wallet.call(
WalletApiOperation.GetUserAttentionUnreadCount,
diff --git a/packages/taler-wallet-webextension/src/components/PendingTransactions.tsx b/packages/taler-wallet-webextension/src/components/PendingTransactions.tsx
index 5d5dae092..85b43fb4e 100644
--- a/packages/taler-wallet-webextension/src/components/PendingTransactions.tsx
+++ b/packages/taler-wallet-webextension/src/components/PendingTransactions.tsx
@@ -22,11 +22,11 @@ import {
import { WalletApiOperation } from "@gnu-taler/taler-wallet-core";
import { Fragment, h, JSX, VNode } from "preact";
import { useEffect } from "preact/hooks";
+import { useBackendContext } from "../context/backend.js";
import { useTranslationContext } from "../context/translation.js";
import { useAsyncAsHook } from "../hooks/useAsyncAsHook.js";
import { Avatar } from "../mui/Avatar.js";
import { Typography } from "../mui/Typography.js";
-import { wxApi } from "../wxApi.js";
import Banner from "./Banner.js";
import { Time } from "./Time.js";
@@ -35,12 +35,13 @@ interface Props extends JSX.HTMLAttributes {
}
export function PendingTransactions({ goToTransaction }: Props): VNode {
+ const api = useBackendContext();
const state = useAsyncAsHook(() =>
- wxApi.wallet.call(WalletApiOperation.GetTransactions, {}),
+ api.wallet.call(WalletApiOperation.GetTransactions, {}),
);
useEffect(() => {
- return wxApi.listener.onUpdateNotification(
+ return api.listener.onUpdateNotification(
[NotificationType.WithdrawGroupFinished],
state?.retry,
);
diff --git a/packages/taler-wallet-webextension/src/components/ShowFullContractTermPopup.tsx b/packages/taler-wallet-webextension/src/components/ShowFullContractTermPopup.tsx
index 6461f76e3..47c10347c 100644
--- a/packages/taler-wallet-webextension/src/components/ShowFullContractTermPopup.tsx
+++ b/packages/taler-wallet-webextension/src/components/ShowFullContractTermPopup.tsx
@@ -25,11 +25,11 @@ import { Loading } from "../components/Loading.js";
import { LoadingError } from "../components/LoadingError.js";
import { Modal } from "../components/Modal.js";
import { Time } from "../components/Time.js";
+import { useBackendContext } from "../context/backend.js";
import { useTranslationContext } from "../context/translation.js";
import { HookError, useAsyncAsHook } from "../hooks/useAsyncAsHook.js";
import { ButtonHandler } from "../mui/handlers.js";
import { compose, StateViewMap } from "../utils/index.js";
-import { wxApi } from "../wxApi.js";
import { Amount } from "./Amount.js";
import { Link } from "./styled/index.js";
@@ -98,7 +98,8 @@ interface Props {
proposalId: string;
}
-function useComponentState({ proposalId }: Props, api: typeof wxApi): State {
+function useComponentState({ proposalId }: Props): State {
+ const api = useBackendContext();
const [show, setShow] = useState(false);
const hook = useAsyncAsHook(async () => {
if (!show) return undefined;
@@ -139,7 +140,7 @@ const viewMapping: StateViewMap<State> = {
export const ShowFullContractTermPopup = compose(
"ShowFullContractTermPopup",
- (p: Props) => useComponentState(p, wxApi),
+ (p: Props) => useComponentState(p),
viewMapping,
);
diff --git a/packages/taler-wallet-webextension/src/components/TermsOfService/index.ts b/packages/taler-wallet-webextension/src/components/TermsOfService/index.ts
index 4d2c4346e..5d5ad3ba2 100644
--- a/packages/taler-wallet-webextension/src/components/TermsOfService/index.ts
+++ b/packages/taler-wallet-webextension/src/components/TermsOfService/index.ts
@@ -18,7 +18,6 @@ import { Loading } from "../../components/Loading.js";
import { HookError } from "../../hooks/useAsyncAsHook.js";
import { ToggleHandler } from "../../mui/handlers.js";
import { compose, StateViewMap } from "../../utils/index.js";
-import { wxApi } from "../../wxApi.js";
import { useComponentState } from "./state.js";
import { TermsState } from "./utils.js";
import {
@@ -26,7 +25,7 @@ import {
LoadingUriView,
ShowButtonsAcceptedTosView,
ShowButtonsNonAcceptedTosView,
- ShowTosContentView,
+ ShowTosContentView
} from "./views.js";
export interface Props {
@@ -89,6 +88,6 @@ const viewMapping: StateViewMap<State> = {
export const TermsOfService = compose(
"TermsOfService",
- (p: Props) => useComponentState(p, wxApi),
+ (p: Props) => useComponentState(p),
viewMapping,
);
diff --git a/packages/taler-wallet-webextension/src/components/TermsOfService/state.ts b/packages/taler-wallet-webextension/src/components/TermsOfService/state.ts
index c5be71ef0..5006cefce 100644
--- a/packages/taler-wallet-webextension/src/components/TermsOfService/state.ts
+++ b/packages/taler-wallet-webextension/src/components/TermsOfService/state.ts
@@ -16,15 +16,15 @@
import { WalletApiOperation } from "@gnu-taler/taler-wallet-core";
import { useState } from "preact/hooks";
+import { useBackendContext } from "../../context/backend.js";
import { useAsyncAsHook } from "../../hooks/useAsyncAsHook.js";
-import { wxApi } from "../../wxApi.js";
import { Props, State } from "./index.js";
import { buildTermsOfServiceState } from "./utils.js";
export function useComponentState(
{ exchangeUrl, onChange }: Props,
- api: typeof wxApi,
): State {
+ const api = useBackendContext()
const readOnly = !onChange;
const [showContent, setShowContent] = useState<boolean>(readOnly);
const [errorAccepting, setErrorAccepting] = useState<Error | undefined>(
diff --git a/packages/taler-wallet-webextension/src/context/backend.ts b/packages/taler-wallet-webextension/src/context/backend.ts
new file mode 100644
index 000000000..3e9e1f0ab
--- /dev/null
+++ b/packages/taler-wallet-webextension/src/context/backend.ts
@@ -0,0 +1,53 @@
+/*
+ This file is part of GNU Taler
+ (C) 2022 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/>
+ */
+
+/**
+ *
+ * @author Sebastian Javier Marchano (sebasjm)
+ */
+
+import { ComponentChildren, createContext, h, VNode } from "preact";
+import { useContext } from "preact/hooks";
+import { wxApi, WxApiType } from "../wxApi.js";
+
+type Type = WxApiType
+
+const initial = wxApi;
+
+const Context = createContext<Type>(initial);
+
+type Props = Partial<WxApiType> & {
+ children: ComponentChildren;
+}
+
+export const BackendProvider = ({
+ wallet,
+ background,
+ listener,
+ children,
+}: Props): VNode => {
+
+ return h(Context.Provider, {
+ value: {
+ wallet: wallet ?? initial.wallet,
+ background: background ?? initial.background,
+ listener: listener ?? initial.listener
+ },
+ children,
+ });
+};
+
+export const useBackendContext = (): Type => useContext(Context);
diff --git a/packages/taler-wallet-webextension/src/cta/Deposit/index.ts b/packages/taler-wallet-webextension/src/cta/Deposit/index.ts
index 539709821..9ff3ddd1d 100644
--- a/packages/taler-wallet-webextension/src/cta/Deposit/index.ts
+++ b/packages/taler-wallet-webextension/src/cta/Deposit/index.ts
@@ -19,7 +19,6 @@ import { Loading } from "../../components/Loading.js";
import { HookError } from "../../hooks/useAsyncAsHook.js";
import { ButtonHandler } from "../../mui/handlers.js";
import { compose, StateViewMap } from "../../utils/index.js";
-import { wxApi } from "../../wxApi.js";
import { useComponentState } from "./state.js";
import { LoadingUriView, ReadyView } from "./views.js";
@@ -64,6 +63,6 @@ const viewMapping: StateViewMap<State> = {
export const DepositPage = compose(
"Deposit",
- (p: Props) => useComponentState(p, wxApi),
+ (p: Props) => useComponentState(p),
viewMapping,
);
diff --git a/packages/taler-wallet-webextension/src/cta/Deposit/state.ts b/packages/taler-wallet-webextension/src/cta/Deposit/state.ts
index 77e918ca9..fbcd107ef 100644
--- a/packages/taler-wallet-webextension/src/cta/Deposit/state.ts
+++ b/packages/taler-wallet-webextension/src/cta/Deposit/state.ts
@@ -16,14 +16,14 @@
import { Amounts } from "@gnu-taler/taler-util";
import { WalletApiOperation } from "@gnu-taler/taler-wallet-core";
+import { useBackendContext } from "../../context/backend.js";
import { useAsyncAsHook } from "../../hooks/useAsyncAsHook.js";
-import { wxApi } from "../../wxApi.js";
import { Props, State } from "./index.js";
export function useComponentState(
{ talerDepositUri, amountStr, cancel, onSuccess }: Props,
- api: typeof wxApi,
): State {
+ const api = useBackendContext()
const info = useAsyncAsHook(async () => {
if (!talerDepositUri) throw Error("ERROR_NO-URI-FOR-DEPOSIT");
if (!amountStr) throw Error("ERROR_NO-AMOUNT-FOR-DEPOSIT");
diff --git a/packages/taler-wallet-webextension/src/cta/Deposit/test.ts b/packages/taler-wallet-webextension/src/cta/Deposit/test.ts
index a5bfed4a8..1c8d4708d 100644
--- a/packages/taler-wallet-webextension/src/cta/Deposit/test.ts
+++ b/packages/taler-wallet-webextension/src/cta/Deposit/test.ts
@@ -20,16 +20,18 @@
*/
import { Amounts } from "@gnu-taler/taler-util";
-import { WalletApiOperation } from "@gnu-taler/taler-wallet-core";
import { expect } from "chai";
-import { mountHook } from "../../test-utils.js";
import { createWalletApiMock } from "../../test-utils.js";
import { useComponentState } from "./state.js";
+import { tests } from "@gnu-taler/web-util/lib/index.browser";
+import { Props } from "./index.js";
+import { WalletApiOperation } from "@gnu-taler/taler-wallet-core";
describe("Deposit CTA states", () => {
it("should tell the user that the URI is missing", async () => {
- const { handler, mock } = createWalletApiMock();
- const props = {
+ const { handler, TestingContext } = createWalletApiMock();
+
+ const props: Props = {
talerDepositUri: undefined,
amountStr: undefined,
cancel: async () => {
@@ -39,32 +41,28 @@ describe("Deposit CTA states", () => {
null;
},
};
- const { pullLastResultOrThrow, waitForStateUpdate, assertNoPendingUpdate } =
- mountHook(() => useComponentState(props, mock));
- {
- const { status } = pullLastResultOrThrow();
- expect(status).equals("loading");
- }
-
- expect(await waitForStateUpdate()).true;
-
- {
- const { status, error } = pullLastResultOrThrow();
+ const hookBehavior = await tests.hookBehaveLikeThis(useComponentState, props, [
+ ({ status }) => {
+ expect(status).equals("loading");
+ },
+ ({ status, error }) => {
+ expect(status).equals("loading-uri");
- expect(status).equals("loading-uri");
+ if (!error) expect.fail();
+ if (!error.hasError) expect.fail();
+ if (error.operational) expect.fail();
+ expect(error.message).eq("ERROR_NO-URI-FOR-DEPOSIT");
+ },
+ ], TestingContext)
- if (!error) expect.fail();
- if (!error.hasError) expect.fail();
- if (error.operational) expect.fail();
- expect(error.message).eq("ERROR_NO-URI-FOR-DEPOSIT");
- }
- await assertNoPendingUpdate();
+ expect(hookBehavior).deep.equal({ result: "ok" })
expect(handler.getCallingQueueState()).eq("empty");
});
it("should be ready after loading", async () => {
- const { handler, mock } = createWalletApiMock();
+ const { handler, TestingContext } = createWalletApiMock();
+
handler.addWalletCallResponse(
WalletApiOperation.PrepareDeposit,
undefined,
@@ -73,6 +71,7 @@ describe("Deposit CTA states", () => {
totalDepositCost: "EUR:1.2",
},
);
+
const props = {
talerDepositUri: "payto://refund/asdasdas",
amountStr: "EUR:1",
@@ -84,28 +83,21 @@ describe("Deposit CTA states", () => {
},
};
- const { pullLastResultOrThrow, waitForStateUpdate, assertNoPendingUpdate } =
- mountHook(() => useComponentState(props, mock));
-
- {
- const { status } = pullLastResultOrThrow();
- expect(status).equals("loading");
- }
-
- expect(await waitForStateUpdate()).true;
-
- {
- const state = pullLastResultOrThrow();
-
- if (state.status !== "ready") expect.fail();
- if (state.error) expect.fail();
- expect(state.confirm.onClick).not.undefined;
- expect(state.cost).deep.eq(Amounts.parseOrThrow("EUR:1.2"));
- expect(state.fee).deep.eq(Amounts.parseOrThrow("EUR:0.2"));
- expect(state.effective).deep.eq(Amounts.parseOrThrow("EUR:1"));
- }
+ const hookBehavior = await tests.hookBehaveLikeThis(useComponentState, props, [
+ ({ status }) => {
+ expect(status).equals("loading");
+ },
+ (state) => {
+ if (state.status !== "ready") expect.fail();
+ if (state.error) expect.fail();
+ expect(state.confirm.onClick).not.undefined;
+ expect(state.cost).deep.eq(Amounts.parseOrThrow("EUR:1.2"));
+ expect(state.fee).deep.eq(Amounts.parseOrThrow("EUR:0.2"));
+ expect(state.effective).deep.eq(Amounts.parseOrThrow("EUR:1"));
+ },
+ ], TestingContext)
- await assertNoPendingUpdate();
+ expect(hookBehavior).deep.equal({ result: "ok" })
expect(handler.getCallingQueueState()).eq("empty");
});
});
diff --git a/packages/taler-wallet-webextension/src/cta/InvoiceCreate/index.ts b/packages/taler-wallet-webextension/src/cta/InvoiceCreate/index.ts
index 01dbb6d6d..0569e8e5f 100644
--- a/packages/taler-wallet-webextension/src/cta/InvoiceCreate/index.ts
+++ b/packages/taler-wallet-webextension/src/cta/InvoiceCreate/index.ts
@@ -22,7 +22,6 @@ import { ButtonHandler, TextFieldHandler } from "../../mui/handlers.js";
import { compose, StateViewMap } from "../../utils/index.js";
import { ExchangeSelectionPage } from "../../wallet/ExchangeSelection/index.js";
import { NoExchangesView } from "../../wallet/ExchangeSelection/views.js";
-import { wxApi } from "../../wxApi.js";
import { useComponentState } from "./state.js";
import { LoadingUriView, ReadyView } from "./views.js";
@@ -78,6 +77,6 @@ const viewMapping: StateViewMap<State> = {
export const InvoiceCreatePage = compose(
"InvoiceCreatePage",
- (p: Props) => useComponentState(p, wxApi),
+ (p: Props) => useComponentState(p),
viewMapping,
);
diff --git a/packages/taler-wallet-webextension/src/cta/InvoiceCreate/state.ts b/packages/taler-wallet-webextension/src/cta/InvoiceCreate/state.ts
index 6007b5193..a26167f8e 100644
--- a/packages/taler-wallet-webextension/src/cta/InvoiceCreate/state.ts
+++ b/packages/taler-wallet-webextension/src/cta/InvoiceCreate/state.ts
@@ -23,17 +23,17 @@ import {
import { TalerError, WalletApiOperation } from "@gnu-taler/taler-wallet-core";
import { isFuture, parse } from "date-fns";
import { useState } from "preact/hooks";
+import { useBackendContext } from "../../context/backend.js";
import { useAsyncAsHook } from "../../hooks/useAsyncAsHook.js";
import { useSelectedExchange } from "../../hooks/useSelectedExchange.js";
import { RecursiveState } from "../../utils/index.js";
-import { wxApi } from "../../wxApi.js";
import { Props, State } from "./index.js";
export function useComponentState(
{ amount: amountStr, onClose, onSuccess }: Props,
- api: typeof wxApi,
): RecursiveState<State> {
const amount = Amounts.parseOrThrow(amountStr);
+ const api = useBackendContext()
const hook = useAsyncAsHook(() =>
api.wallet.call(WalletApiOperation.ListExchanges, {}),
@@ -158,8 +158,8 @@ export function useComponentState(
subject === undefined
? undefined
: !subject
- ? "Can't be empty"
- : undefined,
+ ? "Can't be empty"
+ : undefined,
value: subject ?? "",
onInput: async (e) => setSubject(e),
},
diff --git a/packages/taler-wallet-webextension/src/cta/InvoicePay/index.ts b/packages/taler-wallet-webextension/src/cta/InvoicePay/index.ts
index 6e16b528c..78f244964 100644
--- a/packages/taler-wallet-webextension/src/cta/InvoicePay/index.ts
+++ b/packages/taler-wallet-webextension/src/cta/InvoicePay/index.ts
@@ -18,13 +18,12 @@ import {
AbsoluteTime,
AmountJson,
PreparePayResult,
- TalerErrorDetail,
+ TalerErrorDetail
} from "@gnu-taler/taler-util";
import { Loading } from "../../components/Loading.js";
import { HookError } from "../../hooks/useAsyncAsHook.js";
import { ButtonHandler } from "../../mui/handlers.js";
import { compose, StateViewMap } from "../../utils/index.js";
-import { wxApi } from "../../wxApi.js";
import { useComponentState } from "./state.js";
import { LoadingUriView, ReadyView } from "./views.js";
@@ -92,6 +91,6 @@ const viewMapping: StateViewMap<State> = {
export const InvoicePayPage = compose(
"InvoicePayPage",
- (p: Props) => useComponentState(p, wxApi),
+ (p: Props) => useComponentState(p),
viewMapping,
);
diff --git a/packages/taler-wallet-webextension/src/cta/InvoicePay/state.ts b/packages/taler-wallet-webextension/src/cta/InvoicePay/state.ts
index c7fb48958..eb50ba748 100644
--- a/packages/taler-wallet-webextension/src/cta/InvoicePay/state.ts
+++ b/packages/taler-wallet-webextension/src/cta/InvoicePay/state.ts
@@ -25,14 +25,14 @@ import {
} from "@gnu-taler/taler-util";
import { TalerError, WalletApiOperation } from "@gnu-taler/taler-wallet-core";
import { useEffect, useState } from "preact/hooks";
+import { useBackendContext } from "../../context/backend.js";
import { useAsyncAsHook } from "../../hooks/useAsyncAsHook.js";
-import { wxApi } from "../../wxApi.js";
import { Props, State } from "./index.js";
export function useComponentState(
{ talerPayPullUri, onClose, goToWalletManualWithdraw, onSuccess }: Props,
- api: typeof wxApi,
): State {
+ const api = useBackendContext()
const hook = useAsyncAsHook(async () => {
const p2p = await api.wallet.call(WalletApiOperation.CheckPeerPullPayment, {
talerUri: talerPayPullUri,
diff --git a/packages/taler-wallet-webextension/src/cta/Payment/index.ts b/packages/taler-wallet-webextension/src/cta/Payment/index.ts
index 9bca8f74f..45e4a5b88 100644
--- a/packages/taler-wallet-webextension/src/cta/Payment/index.ts
+++ b/packages/taler-wallet-webextension/src/cta/Payment/index.ts
@@ -19,13 +19,12 @@ import {
PreparePayResult,
PreparePayResultAlreadyConfirmed,
PreparePayResultInsufficientBalance,
- PreparePayResultPaymentPossible,
+ PreparePayResultPaymentPossible
} from "@gnu-taler/taler-util";
import { Loading } from "../../components/Loading.js";
import { HookError } from "../../hooks/useAsyncAsHook.js";
import { ButtonHandler } from "../../mui/handlers.js";
import { compose, StateViewMap } from "../../utils/index.js";
-import { wxApi } from "../../wxApi.js";
import { useComponentState } from "./state.js";
import { BaseView, LoadingUriView } from "./views.js";
@@ -96,6 +95,6 @@ const viewMapping: StateViewMap<State> = {
export const PaymentPage = compose(
"Payment",
- (p: Props) => useComponentState(p, wxApi),
+ (p: Props) => useComponentState(p),
viewMapping,
);
diff --git a/packages/taler-wallet-webextension/src/cta/Payment/state.ts b/packages/taler-wallet-webextension/src/cta/Payment/state.ts
index 970af5b81..7690910e6 100644
--- a/packages/taler-wallet-webextension/src/cta/Payment/state.ts
+++ b/packages/taler-wallet-webextension/src/cta/Payment/state.ts
@@ -23,16 +23,16 @@ import {
} from "@gnu-taler/taler-util";
import { TalerError, WalletApiOperation } from "@gnu-taler/taler-wallet-core";
import { useEffect, useState } from "preact/hooks";
+import { useBackendContext } from "../../context/backend.js";
import { useAsyncAsHook } from "../../hooks/useAsyncAsHook.js";
import { ButtonHandler } from "../../mui/handlers.js";
-import { wxApi } from "../../wxApi.js";
import { Props, State } from "./index.js";
export function useComponentState(
{ talerPayUri, cancel, goToWalletManualWithdraw, onSuccess }: Props,
- api: typeof wxApi,
): State {
const [payErrMsg, setPayErrMsg] = useState<TalerError | undefined>(undefined);
+ const api = useBackendContext()
const hook = useAsyncAsHook(async () => {
if (!talerPayUri) throw Error("ERROR_NO-URI-FOR-PAYMENT");
diff --git a/packages/taler-wallet-webextension/src/cta/Payment/test.ts b/packages/taler-wallet-webextension/src/cta/Payment/test.ts
index b02ac6274..aba76fcf4 100644
--- a/packages/taler-wallet-webextension/src/cta/Payment/test.ts
+++ b/packages/taler-wallet-webextension/src/cta/Payment/test.ts
@@ -30,54 +30,46 @@ import {
} from "@gnu-taler/taler-util";
import { WalletApiOperation } from "@gnu-taler/taler-wallet-core";
import { expect } from "chai";
+import { tests } from "../../../../web-util/src/index.browser.js";
import { mountHook, nullFunction } from "../../test-utils.js";
import { createWalletApiMock } from "../../test-utils.js";
import { useComponentState } from "./state.js";
describe("Payment CTA states", () => {
it("should tell the user that the URI is missing", async () => {
- const { handler, mock } = createWalletApiMock();
+ const { handler, TestingContext } = createWalletApiMock();
const props = {
talerPayUri: undefined,
cancel: nullFunction,
goToWalletManualWithdraw: nullFunction,
- onSuccess: async () => {
- null;
- },
+ onSuccess: nullFunction,
};
- const { pullLastResultOrThrow, waitForStateUpdate, assertNoPendingUpdate } =
- mountHook(() => useComponentState(props, mock));
-
- {
- const { status, error } = pullLastResultOrThrow();
- expect(status).equals("loading");
- expect(error).undefined;
- }
-
- expect(await waitForStateUpdate()).true;
- {
- const { status, error } = pullLastResultOrThrow();
-
- expect(status).equals("loading-uri");
- if (error === undefined) expect.fail();
- expect(error.hasError).true;
- expect(error.operational).false;
- }
+ const hookBehavior = await tests.hookBehaveLikeThis(useComponentState, props, [
+ ({ status, error }) => {
+ expect(status).equals("loading");
+ expect(error).undefined;
+ },
+ ({ status, error }) => {
+ expect(status).equals("loading-uri");
+ if (error === undefined) expect.fail();
+ expect(error.hasError).true;
+ expect(error.operational).false;
+ },
+ ], TestingContext)
- await assertNoPendingUpdate();
+ expect(hookBehavior).deep.equal({ result: "ok" })
expect(handler.getCallingQueueState()).eq("empty");
+
});
it("should response with no balance", async () => {
- const { handler, mock } = createWalletApiMock();
+ const { handler, TestingContext } = createWalletApiMock();
const props = {
talerPayUri: "taller://pay",
cancel: nullFunction,
goToWalletManualWithdraw: nullFunction,
- onSuccess: async () => {
- null;
- },
+ onSuccess: nullFunction,
};
handler.addWalletCallResponse(
@@ -94,41 +86,34 @@ describe("Payment CTA states", () => {
{ balances: [] },
);
- const { pullLastResultOrThrow, waitForStateUpdate, assertNoPendingUpdate } =
- mountHook(() => useComponentState(props, mock));
-
- {
- const { status, error } = pullLastResultOrThrow();
- expect(status).equals("loading");
- expect(error).undefined;
- }
-
- expect(await waitForStateUpdate()).true;
-
- {
- const r = pullLastResultOrThrow();
- if (r.status !== "no-balance-for-currency") {
- expect(r).eq({});
- return;
- }
- expect(r.balance).undefined;
- expect(r.amount).deep.equal(Amounts.parseOrThrow("USD:10"));
- }
+ const hookBehavior = await tests.hookBehaveLikeThis(useComponentState, props, [
+ ({ status, error }) => {
+ expect(status).equals("loading");
+ expect(error).undefined;
+ },
+ (state) => {
+ if (state.status !== "no-balance-for-currency") {
+ expect(state).eq({});
+ return;
+ }
+ expect(state.balance).undefined;
+ expect(state.amount).deep.equal(Amounts.parseOrThrow("USD:10"));
+ },
+ ], TestingContext)
- await assertNoPendingUpdate();
+ expect(hookBehavior).deep.equal({ result: "ok" })
expect(handler.getCallingQueueState()).eq("empty");
});
it("should not be able to pay if there is no enough balance", async () => {
- const { handler, mock } = createWalletApiMock();
+ const { handler, TestingContext } = createWalletApiMock();
const props = {
talerPayUri: "taller://pay",
cancel: nullFunction,
goToWalletManualWithdraw: nullFunction,
- onSuccess: async () => {
- null;
- },
+ onSuccess: nullFunction,
};
+
handler.addWalletCallResponse(
WalletApiOperation.PreparePayForUri,
undefined,
@@ -153,38 +138,31 @@ describe("Payment CTA states", () => {
},
);
- const { pullLastResultOrThrow, waitForStateUpdate, assertNoPendingUpdate } =
- mountHook(() => useComponentState(props, mock));
-
- {
- const { status, error } = pullLastResultOrThrow();
- expect(status).equals("loading");
- expect(error).undefined;
- }
-
- expect(await waitForStateUpdate()).true;
-
- {
- const r = pullLastResultOrThrow();
- if (r.status !== "no-enough-balance") expect.fail();
- expect(r.balance).deep.equal(Amounts.parseOrThrow("USD:5"));
- expect(r.amount).deep.equal(Amounts.parseOrThrow("USD:10"));
- }
+ const hookBehavior = await tests.hookBehaveLikeThis(useComponentState, props, [
+ ({ status, error }) => {
+ expect(status).equals("loading");
+ expect(error).undefined;
+ },
+ (state) => {
+ if (state.status !== "no-enough-balance") expect.fail();
+ expect(state.balance).deep.equal(Amounts.parseOrThrow("USD:5"));
+ expect(state.amount).deep.equal(Amounts.parseOrThrow("USD:10"));
+ },
+ ], TestingContext)
- await assertNoPendingUpdate();
+ expect(hookBehavior).deep.equal({ result: "ok" })
expect(handler.getCallingQueueState()).eq("empty");
});
it("should be able to pay (without fee)", async () => {
- const { handler, mock } = createWalletApiMock();
+ const { handler, TestingContext } = createWalletApiMock();
const props = {
talerPayUri: "taller://pay",
cancel: nullFunction,
goToWalletManualWithdraw: nullFunction,
- onSuccess: async () => {
- null;
- },
+ onSuccess: nullFunction,
};
+
handler.addWalletCallResponse(
WalletApiOperation.PreparePayForUri,
undefined,
@@ -209,42 +187,36 @@ describe("Payment CTA states", () => {
],
},
);
- const { pullLastResultOrThrow, waitForStateUpdate, assertNoPendingUpdate } =
- mountHook(() => useComponentState(props, mock));
-
- {
- const { status, error } = pullLastResultOrThrow();
- expect(status).equals("loading");
- expect(error).undefined;
- }
-
- expect(await waitForStateUpdate()).true;
-
- {
- const r = pullLastResultOrThrow();
- if (r.status !== "ready") {
- expect(r).eq({});
- return;
- }
- expect(r.balance).deep.equal(Amounts.parseOrThrow("USD:15"));
- expect(r.amount).deep.equal(Amounts.parseOrThrow("USD:10"));
- expect(r.payHandler.onClick).not.undefined;
- }
-
- await assertNoPendingUpdate();
+ const hookBehavior = await tests.hookBehaveLikeThis(useComponentState, props, [
+ ({ status, error }) => {
+ expect(status).equals("loading");
+ expect(error).undefined;
+ },
+ (state) => {
+ if (state.status !== "ready") {
+ expect(state).eq({});
+ return;
+ }
+ expect(state.balance).deep.equal(Amounts.parseOrThrow("USD:15"));
+ expect(state.amount).deep.equal(Amounts.parseOrThrow("USD:10"));
+ expect(state.payHandler.onClick).not.undefined;
+ },
+ ], TestingContext)
+
+ expect(hookBehavior).deep.equal({ result: "ok" })
expect(handler.getCallingQueueState()).eq("empty");
+
});
it("should be able to pay (with fee)", async () => {
- const { handler, mock } = createWalletApiMock();
+ const { handler, TestingContext } = createWalletApiMock();
const props = {
talerPayUri: "taller://pay",
cancel: nullFunction,
goToWalletManualWithdraw: nullFunction,
- onSuccess: async () => {
- null;
- },
+ onSuccess: nullFunction,
};
+
handler.addWalletCallResponse(
WalletApiOperation.PreparePayForUri,
undefined,
@@ -269,39 +241,32 @@ describe("Payment CTA states", () => {
],
},
);
- const { pullLastResultOrThrow, waitForStateUpdate, assertNoPendingUpdate } =
- mountHook(() => useComponentState(props, mock));
-
- {
- const { status, error } = pullLastResultOrThrow();
- expect(status).equals("loading");
- expect(error).undefined;
- }
-
- expect(await waitForStateUpdate()).true;
-
- {
- const r = pullLastResultOrThrow();
- if (r.status !== "ready") expect.fail();
- expect(r.balance).deep.equal(Amounts.parseOrThrow("USD:15"));
- expect(r.amount).deep.equal(Amounts.parseOrThrow("USD:9"));
- expect(r.payHandler.onClick).not.undefined;
- }
-
- await assertNoPendingUpdate();
+ const hookBehavior = await tests.hookBehaveLikeThis(useComponentState, props, [
+ ({ status, error }) => {
+ expect(status).equals("loading");
+ expect(error).undefined;
+ },
+ (state) => {
+ if (state.status !== "ready") expect.fail();
+ expect(state.balance).deep.equal(Amounts.parseOrThrow("USD:15"));
+ expect(state.amount).deep.equal(Amounts.parseOrThrow("USD:9"));
+ expect(state.payHandler.onClick).not.undefined;
+ },
+ ], TestingContext)
+
+ expect(hookBehavior).deep.equal({ result: "ok" })
expect(handler.getCallingQueueState()).eq("empty");
});
it("should get confirmation done after pay successfully", async () => {
- const { handler, mock } = createWalletApiMock();
+ const { handler, TestingContext } = createWalletApiMock();
const props = {
talerPayUri: "taller://pay",
cancel: nullFunction,
goToWalletManualWithdraw: nullFunction,
- onSuccess: async () => {
- null;
- },
+ onSuccess: nullFunction,
};
+
handler.addWalletCallResponse(
WalletApiOperation.PreparePayForUri,
undefined,
@@ -332,35 +297,30 @@ describe("Payment CTA states", () => {
contractTerms: {},
} as ConfirmPayResult);
- const { pullLastResultOrThrow, waitForStateUpdate, assertNoPendingUpdate } =
- mountHook(() => useComponentState(props, mock));
-
- {
- const { status, error } = pullLastResultOrThrow();
- expect(status).equals("loading");
- expect(error).undefined;
- }
-
- expect(await waitForStateUpdate()).true;
-
- {
- const r = pullLastResultOrThrow();
- if (r.status !== "ready") {
- expect(r).eq({});
- return;
- }
- expect(r.balance).deep.equal(Amounts.parseOrThrow("USD:15"));
- expect(r.amount).deep.equal(Amounts.parseOrThrow("USD:9"));
- if (r.payHandler.onClick === undefined) expect.fail();
- r.payHandler.onClick();
- }
-
- await assertNoPendingUpdate();
+ const hookBehavior = await tests.hookBehaveLikeThis(useComponentState, props, [
+ ({ status, error }) => {
+ expect(status).equals("loading");
+ expect(error).undefined;
+ },
+ (state) => {
+ if (state.status !== "ready") {
+ expect(state).eq({});
+ return;
+ }
+ expect(state.balance).deep.equal(Amounts.parseOrThrow("USD:15"));
+ expect(state.amount).deep.equal(Amounts.parseOrThrow("USD:9"));
+ if (state.payHandler.onClick === undefined) expect.fail();
+ state.payHandler.onClick();
+ },
+ ], TestingContext)
+
+ expect(hookBehavior).deep.equal({ result: "ok" })
expect(handler.getCallingQueueState()).eq("empty");
+
});
it("should not stay in ready state after pay with error", async () => {
- const { handler, mock } = createWalletApiMock();
+ const { handler, TestingContext } = createWalletApiMock();
const props = {
talerPayUri: "taller://pay",
cancel: nullFunction,
@@ -397,62 +357,50 @@ describe("Payment CTA states", () => {
lastError: { code: 1 },
} as ConfirmPayResult);
- const { pullLastResultOrThrow, waitForStateUpdate, assertNoPendingUpdate } =
- mountHook(() => useComponentState(props, mock));
-
- {
- const { status, error } = pullLastResultOrThrow();
- expect(status).equals("loading");
- expect(error).undefined;
- }
-
- expect(await waitForStateUpdate()).true;
-
- {
- const r = pullLastResultOrThrow();
- if (r.status !== "ready") expect.fail();
- expect(r.balance).deep.equal(Amounts.parseOrThrow("USD:15"));
- expect(r.amount).deep.equal(Amounts.parseOrThrow("USD:9"));
- // expect(r.totalFees).deep.equal(Amounts.parseOrThrow("USD:1"));
- if (r.payHandler.onClick === undefined) expect.fail();
- r.payHandler.onClick();
- }
-
- expect(await waitForStateUpdate()).true;
-
- {
- const r = pullLastResultOrThrow();
- if (r.status !== "ready") expect.fail();
- expect(r.balance).deep.equal(Amounts.parseOrThrow("USD:15"));
- expect(r.amount).deep.equal(Amounts.parseOrThrow("USD:9"));
- // expect(r.totalFees).deep.equal(Amounts.parseOrThrow("USD:1"));
- expect(r.payHandler.onClick).undefined;
- if (r.payHandler.error === undefined) expect.fail();
- //FIXME: error message here is bad
- expect(r.payHandler.error.errorDetail.hint).eq(
- "could not confirm payment",
- );
- expect(r.payHandler.error.errorDetail.payResult).deep.equal({
- type: ConfirmPayResultType.Pending,
- lastError: { code: 1 },
- });
- }
-
- await assertNoPendingUpdate();
+ const hookBehavior = await tests.hookBehaveLikeThis(useComponentState, props, [
+ ({ status, error }) => {
+ expect(status).equals("loading");
+ expect(error).undefined;
+ },
+ (state) => {
+ if (state.status !== "ready") expect.fail();
+ expect(state.balance).deep.equal(Amounts.parseOrThrow("USD:15"));
+ expect(state.amount).deep.equal(Amounts.parseOrThrow("USD:9"));
+ // expect(r.totalFees).deep.equal(Amounts.parseOrThrow("USD:1"));
+ if (state.payHandler.onClick === undefined) expect.fail();
+ state.payHandler.onClick();
+ },
+ (state) => {
+ if (state.status !== "ready") expect.fail();
+ expect(state.balance).deep.equal(Amounts.parseOrThrow("USD:15"));
+ expect(state.amount).deep.equal(Amounts.parseOrThrow("USD:9"));
+ // expect(r.totalFees).deep.equal(Amounts.parseOrThrow("USD:1"));
+ expect(state.payHandler.onClick).undefined;
+ if (state.payHandler.error === undefined) expect.fail();
+ //FIXME: error message here is bad
+ expect(state.payHandler.error.errorDetail.hint).eq(
+ "could not confirm payment",
+ );
+ expect(state.payHandler.error.errorDetail.payResult).deep.equal({
+ type: ConfirmPayResultType.Pending,
+ lastError: { code: 1 },
+ });
+ },
+ ], TestingContext)
+ expect(hookBehavior).deep.equal({ result: "ok" })
expect(handler.getCallingQueueState()).eq("empty");
+
});
it("should update balance if a coins is withdraw", async () => {
- const { handler, mock } = createWalletApiMock();
+ const { handler, TestingContext } = createWalletApiMock();
const props = {
talerPayUri: "taller://pay",
cancel: nullFunction,
goToWalletManualWithdraw: nullFunction,
- onSuccess: async () => {
- null;
- },
+ onSuccess: nullFunction,
};
handler.addWalletCallResponse(
@@ -507,46 +455,30 @@ describe("Payment CTA states", () => {
},
);
- const { pullLastResultOrThrow, waitForStateUpdate, assertNoPendingUpdate } =
- mountHook(() => useComponentState(props, mock));
-
- {
- const { status, error } = pullLastResultOrThrow();
- expect(status).equals("loading");
- expect(error).undefined;
- }
-
- expect(await waitForStateUpdate()).true;
-
- {
- const r = pullLastResultOrThrow();
- if (r.status !== "ready") {
- expect(r).eq({});
- return;
- }
- expect(r.balance).deep.equal(Amounts.parseOrThrow("USD:10"));
- expect(r.amount).deep.equal(Amounts.parseOrThrow("USD:9"));
- // expect(r.totalFees).deep.equal(Amounts.parseOrThrow("USD:1"));
- expect(r.payHandler.onClick).not.undefined;
-
- handler.notifyEventFromWallet(NotificationType.CoinWithdrawn);
- }
-
- expect(await waitForStateUpdate()).true;
-
- {
- const r = pullLastResultOrThrow();
- if (r.status !== "ready") {
- expect(r).eq({});
- return;
- }
- expect(r.balance).deep.equal(Amounts.parseOrThrow("USD:15"));
- expect(r.amount).deep.equal(Amounts.parseOrThrow("USD:9"));
- // expect(r.totalFees).deep.equal(Amounts.parseOrThrow("USD:1"));
- expect(r.payHandler.onClick).not.undefined;
- }
-
- await assertNoPendingUpdate();
+ const hookBehavior = await tests.hookBehaveLikeThis(useComponentState, props, [
+ ({ status, error }) => {
+ expect(status).equals("loading");
+ expect(error).undefined;
+ },
+ (state) => {
+ if (state.status !== "ready") expect.fail()
+ expect(state.balance).deep.equal(Amounts.parseOrThrow("USD:10"));
+ expect(state.amount).deep.equal(Amounts.parseOrThrow("USD:9"));
+ // expect(r.totalFees).deep.equal(Amounts.parseOrThrow("USD:1"));
+ expect(state.payHandler.onClick).not.undefined;
+
+ handler.notifyEventFromWallet(NotificationType.CoinWithdrawn);
+ },
+ (state) => {
+ if (state.status !== "ready") expect.fail()
+ expect(state.balance).deep.equal(Amounts.parseOrThrow("USD:15"));
+ expect(state.amount).deep.equal(Amounts.parseOrThrow("USD:9"));
+ // expect(r.totalFees).deep.equal(Amounts.parseOrThrow("USD:1"));
+ expect(state.payHandler.onClick).not.undefined;
+ },
+ ], TestingContext)
+
+ expect(hookBehavior).deep.equal({ result: "ok" })
expect(handler.getCallingQueueState()).eq("empty");
});
});
diff --git a/packages/taler-wallet-webextension/src/cta/Recovery/index.ts b/packages/taler-wallet-webextension/src/cta/Recovery/index.ts
index 4a65c571b..4a6fc79c9 100644
--- a/packages/taler-wallet-webextension/src/cta/Recovery/index.ts
+++ b/packages/taler-wallet-webextension/src/cta/Recovery/index.ts
@@ -18,7 +18,6 @@ import { Loading } from "../../components/Loading.js";
import { HookError } from "../../hooks/useAsyncAsHook.js";
import { ButtonHandler } from "../../mui/handlers.js";
import { compose, StateViewMap } from "../../utils/index.js";
-import { wxApi } from "../../wxApi.js";
import { useComponentState } from "./state.js";
import { LoadingUriView, ReadyView } from "./views.js";
@@ -60,6 +59,6 @@ const viewMapping: StateViewMap<State> = {
export const RecoveryPage = compose(
"Recovery",
- (p: Props) => useComponentState(p, wxApi),
+ (p: Props) => useComponentState(p),
viewMapping,
);
diff --git a/packages/taler-wallet-webextension/src/cta/Recovery/state.ts b/packages/taler-wallet-webextension/src/cta/Recovery/state.ts
index 3a5d94e2e..018d61c03 100644
--- a/packages/taler-wallet-webextension/src/cta/Recovery/state.ts
+++ b/packages/taler-wallet-webextension/src/cta/Recovery/state.ts
@@ -16,13 +16,13 @@
import { parseRecoveryUri } from "@gnu-taler/taler-util";
import { WalletApiOperation } from "@gnu-taler/taler-wallet-core";
-import { wxApi } from "../../wxApi.js";
+import { useBackendContext } from "../../context/backend.js";
import { Props, State } from "./index.js";
export function useComponentState(
{ talerRecoveryUri, onCancel, onSuccess }: Props,
- api: typeof wxApi,
): State {
+ const api = useBackendContext()
if (!talerRecoveryUri) {
return {
status: "loading-uri",
@@ -48,7 +48,7 @@ export function useComponentState(
const recovery = info;
async function recoverBackup(): Promise<void> {
- await wxApi.wallet.call(WalletApiOperation.ImportBackupRecovery, {
+ await api.wallet.call(WalletApiOperation.ImportBackupRecovery, {
recovery,
});
onSuccess();
diff --git a/packages/taler-wallet-webextension/src/cta/Refund/index.ts b/packages/taler-wallet-webextension/src/cta/Refund/index.ts
index 099f72919..158f5c179 100644
--- a/packages/taler-wallet-webextension/src/cta/Refund/index.ts
+++ b/packages/taler-wallet-webextension/src/cta/Refund/index.ts
@@ -19,13 +19,12 @@ import { Loading } from "../../components/Loading.js";
import { HookError } from "../../hooks/useAsyncAsHook.js";
import { ButtonHandler } from "../../mui/handlers.js";
import { compose, StateViewMap } from "../../utils/index.js";
-import { wxApi } from "../../wxApi.js";
import { useComponentState } from "./state.js";
import {
IgnoredView,
InProgressView,
LoadingUriView,
- ReadyView,
+ ReadyView
} from "./views.js";
export interface Props {
@@ -90,6 +89,6 @@ const viewMapping: StateViewMap<State> = {
export const RefundPage = compose(
"Refund",
- (p: Props) => useComponentState(p, wxApi),
+ (p: Props) => useComponentState(p),
viewMapping,
);
diff --git a/packages/taler-wallet-webextension/src/cta/Refund/state.ts b/packages/taler-wallet-webextension/src/cta/Refund/state.ts
index 94c5567d6..624ab2fb2 100644
--- a/packages/taler-wallet-webextension/src/cta/Refund/state.ts
+++ b/packages/taler-wallet-webextension/src/cta/Refund/state.ts
@@ -17,14 +17,14 @@
import { Amounts, NotificationType } from "@gnu-taler/taler-util";
import { WalletApiOperation } from "@gnu-taler/taler-wallet-core";
import { useEffect, useState } from "preact/hooks";
+import { useBackendContext } from "../../context/backend.js";
import { useAsyncAsHook } from "../../hooks/useAsyncAsHook.js";
-import { wxApi } from "../../wxApi.js";
import { Props, State } from "./index.js";
export function useComponentState(
{ talerRefundUri, cancel, onSuccess }: Props,
- api: typeof wxApi,
): State {
+ const api = useBackendContext()
const [ignored, setIgnored] = useState(false);
const info = useAsyncAsHook(async () => {
diff --git a/packages/taler-wallet-webextension/src/cta/Refund/test.ts b/packages/taler-wallet-webextension/src/cta/Refund/test.ts
index 927c45981..5fbf3743e 100644
--- a/packages/taler-wallet-webextension/src/cta/Refund/test.ts
+++ b/packages/taler-wallet-webextension/src/cta/Refund/test.ts
@@ -20,75 +20,50 @@
*/
import {
- AmountJson,
Amounts,
NotificationType,
- OrderShortInfo,
- PrepareRefundResult,
+ OrderShortInfo
} from "@gnu-taler/taler-util";
import { WalletApiOperation } from "@gnu-taler/taler-wallet-core";
import { expect } from "chai";
-import { mountHook } from "../../test-utils.js";
-import { createWalletApiMock } from "../../test-utils.js";
+import { tests } from "../../../../web-util/src/index.browser.js";
+import { createWalletApiMock, mountHook, nullFunction } from "../../test-utils.js";
import { useComponentState } from "./state.js";
describe("Refund CTA states", () => {
it("should tell the user that the URI is missing", async () => {
- const { handler, mock } = createWalletApiMock();
+ const { handler, TestingContext } = createWalletApiMock();
- const { pullLastResultOrThrow, waitForStateUpdate, assertNoPendingUpdate } =
- mountHook(() =>
- useComponentState(
- {
- talerRefundUri: undefined,
- cancel: async () => {
- null;
- },
- onSuccess: async () => {
- null;
- },
- },
- mock,
- // {
- // prepareRefund: async () => ({}),
- // applyRefund: async () => ({}),
- // onUpdateNotification: async () => ({}),
- // } as any,
- ),
- );
-
- {
- const { status, error } = pullLastResultOrThrow();
- expect(status).equals("loading");
- expect(error).undefined;
+ const props = {
+ talerRefundUri: undefined,
+ cancel: nullFunction,
+ onSuccess: nullFunction,
}
- expect(await waitForStateUpdate()).true;
-
- {
- const { status, error } = pullLastResultOrThrow();
-
- expect(status).equals("loading-uri");
- if (!error) expect.fail();
- if (!error.hasError) expect.fail();
- if (error.operational) expect.fail();
- expect(error.message).eq("ERROR_NO-URI-FOR-REFUND");
- }
+ const hookBehavior = await tests.hookBehaveLikeThis(useComponentState, props, [
+ ({ status, error }) => {
+ expect(status).equals("loading");
+ expect(error).undefined;
+ },
+ ({ status, error }) => {
+ expect(status).equals("loading-uri");
+ if (!error) expect.fail();
+ if (!error.hasError) expect.fail();
+ if (error.operational) expect.fail();
+ expect(error.message).eq("ERROR_NO-URI-FOR-REFUND");
+ },
+ ], TestingContext)
- await assertNoPendingUpdate();
+ expect(hookBehavior).deep.equal({ result: "ok" })
expect(handler.getCallingQueueState()).eq("empty");
});
it("should be ready after loading", async () => {
- const { handler, mock } = createWalletApiMock();
+ const { handler, TestingContext } = createWalletApiMock();
const props = {
talerRefundUri: "taler://refund/asdasdas",
- cancel: async () => {
- null;
- },
- onSuccess: async () => {
- null;
- },
+ cancel: nullFunction,
+ onSuccess: nullFunction,
};
handler.addWalletCallResponse(WalletApiOperation.PrepareRefund, undefined, {
@@ -108,61 +83,28 @@ describe("Refund CTA states", () => {
} as OrderShortInfo,
});
- const { pullLastResultOrThrow, waitForStateUpdate, assertNoPendingUpdate } =
- mountHook(() =>
- useComponentState(
- props,
- mock,
- // {
- // prepareRefund: async () =>
- // ({
- // effectivePaid: "EUR:2",
- // awaiting: "EUR:2",
- // gone: "EUR:0",
- // granted: "EUR:0",
- // pending: false,
- // proposalId: "1",
- // info: {
- // contractTermsHash: "123",
- // merchant: {
- // name: "the merchant name",
- // },
- // orderId: "orderId1",
- // summary: "the summary",
- // },
- // } as PrepareRefundResult as any),
- // applyRefund: async () => ({}),
- // onUpdateNotification: async () => ({}),
- // } as any,
- ),
- );
-
- {
- const { status, error } = pullLastResultOrThrow();
- expect(status).equals("loading");
- expect(error).undefined;
- }
-
- expect(await waitForStateUpdate()).true;
-
- {
- const state = pullLastResultOrThrow();
-
- if (state.status !== "ready") expect.fail();
- if (state.error) expect.fail();
- expect(state.accept.onClick).not.undefined;
- expect(state.ignore.onClick).not.undefined;
- expect(state.merchantName).eq("the merchant name");
- expect(state.orderId).eq("orderId1");
- expect(state.products).undefined;
- }
+ const hookBehavior = await tests.hookBehaveLikeThis(useComponentState, props, [
+ ({ status, error }) => {
+ expect(status).equals("loading");
+ expect(error).undefined;
+ },
+ (state) => {
+ if (state.status !== "ready") expect.fail();
+ if (state.error) expect.fail();
+ expect(state.accept.onClick).not.undefined;
+ expect(state.ignore.onClick).not.undefined;
+ expect(state.merchantName).eq("the merchant name");
+ expect(state.orderId).eq("orderId1");
+ expect(state.products).undefined;
+ },
+ ], TestingContext)
- await assertNoPendingUpdate();
+ expect(hookBehavior).deep.equal({ result: "ok" })
expect(handler.getCallingQueueState()).eq("empty");
});
it("should be ignored after clicking the ignore button", async () => {
- const { handler, mock } = createWalletApiMock();
+ const { handler, TestingContext } = createWalletApiMock();
const props = {
talerRefundUri: "taler://refund/asdasdas",
cancel: async () => {
@@ -189,102 +131,36 @@ describe("Refund CTA states", () => {
summary: "the summary",
} as OrderShortInfo,
});
- // handler.addWalletCall(WalletApiOperation.ApplyRefund)
- // handler.addWalletCall(WalletApiOperation.PrepareRefund, undefined, {
- // awaiting: "EUR:1",
- // effectivePaid: "EUR:2",
- // gone: "EUR:0",
- // granted: "EUR:1",
- // pending: true,
- // proposalId: "1",
- // info: {
- // contractTermsHash: "123",
- // merchant: {
- // name: "the merchant name",
- // },
- // orderId: "orderId1",
- // summary: "the summary",
- // } as OrderShortInfo,
- // })
- const { pullLastResultOrThrow, waitForStateUpdate, assertNoPendingUpdate } =
- mountHook(() =>
- useComponentState(
- props,
- mock,
- // {
- // prepareRefund: async () =>
- // ({
- // effectivePaid: "EUR:2",
- // awaiting: "EUR:2",
- // gone: "EUR:0",
- // granted: "EUR:0",
- // pending: false,
- // proposalId: "1",
- // info: {
- // contractTermsHash: "123",
- // merchant: {
- // name: "the merchant name",
- // },
- // orderId: "orderId1",
- // summary: "the summary",
- // },
- // } as PrepareRefundResult as any),
- // applyRefund: async () => ({}),
- // onUpdateNotification: async () => ({}),
- // } as any,
- ),
- );
- {
- const { status, error } = pullLastResultOrThrow();
- expect(status).equals("loading");
- expect(error).undefined;
- }
-
- expect(await waitForStateUpdate()).true;
-
- {
- const state = pullLastResultOrThrow();
-
- if (state.status !== "ready") {
- expect(state).eq({});
- return;
- }
- if (state.error) {
- expect(state).eq({});
- return;
- }
- expect(state.accept.onClick).not.undefined;
- expect(state.merchantName).eq("the merchant name");
- expect(state.orderId).eq("orderId1");
- expect(state.products).undefined;
-
- if (state.ignore.onClick === undefined) expect.fail();
- state.ignore.onClick();
- }
-
- expect(await waitForStateUpdate()).true;
-
- {
- const state = pullLastResultOrThrow();
-
- if (state.status !== "ignored") {
- expect(state).eq({});
- return;
- }
- if (state.error) {
- expect(state).eq({});
- return;
- }
- expect(state.merchantName).eq("the merchant name");
- }
+ const hookBehavior = await tests.hookBehaveLikeThis(useComponentState, props, [
+ ({ status, error }) => {
+ expect(status).equals("loading");
+ expect(error).undefined;
+ },
+ (state) => {
+ if (state.status !== "ready") expect.fail()
+ if (state.error) expect.fail()
+ expect(state.accept.onClick).not.undefined;
+ expect(state.merchantName).eq("the merchant name");
+ expect(state.orderId).eq("orderId1");
+ expect(state.products).undefined;
+
+ if (state.ignore.onClick === undefined) expect.fail();
+ state.ignore.onClick();
+ },
+ (state) => {
+ if (state.status !== "ignored") expect.fail()
+ if (state.error) expect.fail()
+ expect(state.merchantName).eq("the merchant name");
+ },
+ ], TestingContext)
- await assertNoPendingUpdate();
+ expect(hookBehavior).deep.equal({ result: "ok" })
expect(handler.getCallingQueueState()).eq("empty");
});
it("should be in progress when doing refresh", async () => {
- const { handler, mock } = createWalletApiMock();
+ const { handler, TestingContext } = createWalletApiMock();
const props = {
talerRefundUri: "taler://refund/asdasdas",
cancel: async () => {
@@ -344,67 +220,42 @@ describe("Refund CTA states", () => {
} as OrderShortInfo,
});
- const { pullLastResultOrThrow, waitForStateUpdate, assertNoPendingUpdate } =
- mountHook(() => useComponentState(props, mock));
-
- {
- const { status, error } = pullLastResultOrThrow();
- expect(status).equals("loading");
- expect(error).undefined;
- }
-
- expect(await waitForStateUpdate()).true;
-
- {
- const state = pullLastResultOrThrow();
-
- if (state.status !== "in-progress") {
- expect(state).eq({});
- return;
- }
- if (state.error) expect.fail();
- expect(state.merchantName).eq("the merchant name");
- expect(state.products).undefined;
- expect(state.amount).deep.eq(Amounts.parseOrThrow("EUR:2"));
- // expect(state.progress).closeTo(1 / 3, 0.01)
-
- handler.notifyEventFromWallet(NotificationType.RefreshMelted);
- }
-
- expect(await waitForStateUpdate()).true;
-
- {
- const state = pullLastResultOrThrow();
-
- if (state.status !== "in-progress") {
- expect(state).eq({});
- return;
- }
- if (state.error) expect.fail();
- expect(state.merchantName).eq("the merchant name");
- expect(state.products).undefined;
- expect(state.amount).deep.eq(Amounts.parseOrThrow("EUR:2"));
- // expect(state.progress).closeTo(2 / 3, 0.01)
-
- handler.notifyEventFromWallet(NotificationType.RefreshMelted);
- }
-
- expect(await waitForStateUpdate()).true;
-
- {
- const state = pullLastResultOrThrow();
+ const hookBehavior = await tests.hookBehaveLikeThis(useComponentState, props, [
+ ({ status, error }) => {
+ expect(status).equals("loading");
+ expect(error).undefined;
+ },
+ (state) => {
+ if (state.status !== "in-progress") expect.fail()
+ if (state.error) expect.fail();
+ expect(state.merchantName).eq("the merchant name");
+ expect(state.products).undefined;
+ expect(state.amount).deep.eq(Amounts.parseOrThrow("EUR:2"));
+ // expect(state.progress).closeTo(1 / 3, 0.01)
+
+ handler.notifyEventFromWallet(NotificationType.RefreshMelted);
+ },
+ (state) => {
+ if (state.status !== "in-progress") expect.fail()
+ if (state.error) expect.fail();
+ expect(state.merchantName).eq("the merchant name");
+ expect(state.products).undefined;
+ expect(state.amount).deep.eq(Amounts.parseOrThrow("EUR:2"));
+ // expect(state.progress).closeTo(2 / 3, 0.01)
+
+ handler.notifyEventFromWallet(NotificationType.RefreshMelted);
+ },
+ (state) => {
+ if (state.status !== "ready") expect.fail()
+ if (state.error) expect.fail();
+ expect(state.merchantName).eq("the merchant name");
+ expect(state.products).undefined;
+ expect(state.amount).deep.eq(Amounts.parseOrThrow("EUR:2"));
- if (state.status !== "ready") {
- expect(state).eq({});
- return;
- }
- if (state.error) expect.fail();
- expect(state.merchantName).eq("the merchant name");
- expect(state.products).undefined;
- expect(state.amount).deep.eq(Amounts.parseOrThrow("EUR:2"));
- }
+ },
+ ], TestingContext)
- await assertNoPendingUpdate();
+ expect(hookBehavior).deep.equal({ result: "ok" })
expect(handler.getCallingQueueState()).eq("empty");
});
});
diff --git a/packages/taler-wallet-webextension/src/cta/Tip/index.ts b/packages/taler-wallet-webextension/src/cta/Tip/index.ts
index ff917008f..a29a3eadb 100644
--- a/packages/taler-wallet-webextension/src/cta/Tip/index.ts
+++ b/packages/taler-wallet-webextension/src/cta/Tip/index.ts
@@ -19,13 +19,12 @@ import { Loading } from "../../components/Loading.js";
import { HookError } from "../../hooks/useAsyncAsHook.js";
import { ButtonHandler } from "../../mui/handlers.js";
import { compose, StateViewMap } from "../../utils/index.js";
-import { wxApi } from "../../wxApi.js";
import { useComponentState } from "./state.js";
import {
AcceptedView,
IgnoredView,
LoadingUriView,
- ReadyView,
+ ReadyView
} from "./views.js";
export interface Props {
@@ -84,6 +83,6 @@ const viewMapping: StateViewMap<State> = {
export const TipPage = compose(
"Tip",
- (p: Props) => useComponentState(p, wxApi),
+ (p: Props) => useComponentState(p),
viewMapping,
);
diff --git a/packages/taler-wallet-webextension/src/cta/Tip/state.ts b/packages/taler-wallet-webextension/src/cta/Tip/state.ts
index ea9ba1b37..0ca213b01 100644
--- a/packages/taler-wallet-webextension/src/cta/Tip/state.ts
+++ b/packages/taler-wallet-webextension/src/cta/Tip/state.ts
@@ -16,14 +16,14 @@
import { Amounts } from "@gnu-taler/taler-util";
import { WalletApiOperation } from "@gnu-taler/taler-wallet-core";
+import { useBackendContext } from "../../context/backend.js";
import { useAsyncAsHook } from "../../hooks/useAsyncAsHook.js";
-import { wxApi } from "../../wxApi.js";
import { Props, State } from "./index.js";
export function useComponentState(
{ talerTipUri, onCancel, onSuccess }: Props,
- api: typeof wxApi,
): State {
+ const api = useBackendContext()
const tipInfo = useAsyncAsHook(async () => {
if (!talerTipUri) throw Error("ERROR_NO-URI-FOR-TIP");
const tip = await api.wallet.call(WalletApiOperation.PrepareTip, {
diff --git a/packages/taler-wallet-webextension/src/cta/Tip/test.ts b/packages/taler-wallet-webextension/src/cta/Tip/test.ts
index e57b9ec4d..21ed95218 100644
--- a/packages/taler-wallet-webextension/src/cta/Tip/test.ts
+++ b/packages/taler-wallet-webextension/src/cta/Tip/test.ts
@@ -22,54 +22,42 @@
import { Amounts } from "@gnu-taler/taler-util";
import { WalletApiOperation } from "@gnu-taler/taler-wallet-core";
import { expect } from "chai";
-import { mountHook } from "../../test-utils.js";
+import { tests } from "../../../../web-util/src/index.browser.js";
+import { mountHook, nullFunction } from "../../test-utils.js";
import { createWalletApiMock } from "../../test-utils.js";
+import { Props } from "./index.js";
import { useComponentState } from "./state.js";
describe("Tip CTA states", () => {
it("should tell the user that the URI is missing", async () => {
- const { handler, mock } = createWalletApiMock();
+ const { handler, TestingContext } = createWalletApiMock();
- const { pullLastResultOrThrow, waitForStateUpdate, assertNoPendingUpdate } =
- mountHook(() =>
- useComponentState(
- {
- talerTipUri: undefined,
- onCancel: async () => {
- null;
- },
- onSuccess: async () => {
- null;
- },
- },
- mock,
- ),
- );
-
- {
- const { status, error } = pullLastResultOrThrow();
- expect(status).equals("loading");
- expect(error).undefined;
+ const props: Props = {
+ talerTipUri: undefined,
+ onCancel: nullFunction,
+ onSuccess: nullFunction,
}
- expect(await waitForStateUpdate()).true;
-
- {
- const { status, error } = pullLastResultOrThrow();
-
- expect(status).equals("loading-uri");
- if (!error) expect.fail();
- if (!error.hasError) expect.fail();
- if (error.operational) expect.fail();
- expect(error.message).eq("ERROR_NO-URI-FOR-TIP");
- }
+ const hookBehavior = await tests.hookBehaveLikeThis(useComponentState, props, [
+ ({ status, error }) => {
+ expect(status).equals("loading");
+ expect(error).undefined;
+ },
+ ({ status, error }) => {
+ expect(status).equals("loading-uri");
+ if (!error) expect.fail();
+ if (!error.hasError) expect.fail();
+ if (error.operational) expect.fail();
+ expect(error.message).eq("ERROR_NO-URI-FOR-TIP");
+ },
+ ], TestingContext)
- await assertNoPendingUpdate();
+ expect(hookBehavior).deep.equal({ result: "ok" })
expect(handler.getCallingQueueState()).eq("empty");
});
it("should be ready for accepting the tip", async () => {
- const { handler, mock } = createWalletApiMock();
+ const { handler, TestingContext } = createWalletApiMock();
handler.addWalletCallResponse(WalletApiOperation.PrepareTip, undefined, {
accepted: false,
@@ -83,78 +71,59 @@ describe("Tip CTA states", () => {
tipAmountRaw: "",
});
- const { pullLastResultOrThrow, waitForStateUpdate, assertNoPendingUpdate } =
- mountHook(() =>
- useComponentState(
- {
- talerTipUri: "taler://tip/asd",
- onCancel: async () => {
- null;
- },
- onSuccess: async () => {
- null;
- },
- },
- mock,
- ),
- );
-
- {
- const { status, error } = pullLastResultOrThrow();
- expect(status).equals("loading");
- expect(error).undefined;
+ const props: Props = {
+ talerTipUri: "taler://tip/asd",
+ onCancel: nullFunction,
+ onSuccess: nullFunction,
}
- expect(await waitForStateUpdate()).true;
-
- {
- const state = pullLastResultOrThrow();
-
- if (state.status !== "ready") {
- expect(state).eq({ status: "ready" });
- return;
- }
- if (state.error) expect.fail();
- expect(state.amount).deep.eq(Amounts.parseOrThrow("EUR:1"));
- expect(state.merchantBaseUrl).eq("merchant url");
- expect(state.exchangeBaseUrl).eq("exchange url");
- if (state.accept.onClick === undefined) expect.fail();
-
- handler.addWalletCallResponse(WalletApiOperation.AcceptTip);
- state.accept.onClick();
- }
-
- handler.addWalletCallResponse(WalletApiOperation.PrepareTip, undefined, {
- accepted: true,
- exchangeBaseUrl: "exchange url",
- merchantBaseUrl: "merchant url",
- tipAmountEffective: "EUR:1",
- walletTipId: "tip_id",
- expirationTimestamp: {
- t_s: 1,
+ const hookBehavior = await tests.hookBehaveLikeThis(useComponentState, props, [
+ ({ status, error }) => {
+ expect(status).equals("loading");
+ expect(error).undefined;
},
- tipAmountRaw: "",
- });
- expect(await waitForStateUpdate()).true;
+ (state) => {
+ if (state.status !== "ready") {
+ expect(state).eq({ status: "ready" });
+ return;
+ }
+ if (state.error) expect.fail();
+ expect(state.amount).deep.eq(Amounts.parseOrThrow("EUR:1"));
+ expect(state.merchantBaseUrl).eq("merchant url");
+ expect(state.exchangeBaseUrl).eq("exchange url");
+ if (state.accept.onClick === undefined) expect.fail();
+
+ handler.addWalletCallResponse(WalletApiOperation.AcceptTip);
+ state.accept.onClick();
+
+ handler.addWalletCallResponse(WalletApiOperation.PrepareTip, undefined, {
+ accepted: true,
+ exchangeBaseUrl: "exchange url",
+ merchantBaseUrl: "merchant url",
+ tipAmountEffective: "EUR:1",
+ walletTipId: "tip_id",
+ expirationTimestamp: {
+ t_s: 1,
+ },
+ tipAmountRaw: "",
+ });
- {
- const state = pullLastResultOrThrow();
+ },
+ (state) => {
+ if (state.status !== "accepted") expect.fail()
+ if (state.error) expect.fail();
+ expect(state.amount).deep.eq(Amounts.parseOrThrow("EUR:1"));
+ expect(state.merchantBaseUrl).eq("merchant url");
+ expect(state.exchangeBaseUrl).eq("exchange url");
+ },
+ ], TestingContext)
- if (state.status !== "accepted") {
- expect(state).eq({ status: "accepted" });
- return;
- }
- if (state.error) expect.fail();
- expect(state.amount).deep.eq(Amounts.parseOrThrow("EUR:1"));
- expect(state.merchantBaseUrl).eq("merchant url");
- expect(state.exchangeBaseUrl).eq("exchange url");
- }
- await assertNoPendingUpdate();
+ expect(hookBehavior).deep.equal({ result: "ok" })
expect(handler.getCallingQueueState()).eq("empty");
});
- it("should be ignored after clicking the ignore button", async () => {
- const { handler, mock } = createWalletApiMock();
+ it.skip("should be ignored after clicking the ignore button", async () => {
+ const { handler, TestingContext } = createWalletApiMock();
handler.addWalletCallResponse(WalletApiOperation.PrepareTip, undefined, {
exchangeBaseUrl: "exchange url",
merchantBaseUrl: "merchant url",
@@ -167,46 +136,34 @@ describe("Tip CTA states", () => {
tipAmountRaw: "",
});
- const { pullLastResultOrThrow, waitForStateUpdate, assertNoPendingUpdate } =
- mountHook(() =>
- useComponentState(
- {
- talerTipUri: "taler://tip/asd",
- onCancel: async () => {
- null;
- },
- onSuccess: async () => {
- null;
- },
- },
- mock,
- ),
- );
-
- {
- const { status, error } = pullLastResultOrThrow();
- expect(status).equals("loading");
- expect(error).undefined;
+ const props: Props = {
+ talerTipUri: "taler://tip/asd",
+ onCancel: nullFunction,
+ onSuccess: nullFunction,
}
- expect(await waitForStateUpdate()).true;
-
- {
- const state = pullLastResultOrThrow();
-
- if (state.status !== "ready") expect.fail();
- if (state.error) expect.fail();
- expect(state.amount).deep.eq(Amounts.parseOrThrow("EUR:1"));
- expect(state.merchantBaseUrl).eq("merchant url");
- expect(state.exchangeBaseUrl).eq("exchange url");
- }
+ const hookBehavior = await tests.hookBehaveLikeThis(useComponentState, props, [
+ ({ status, error }) => {
+ expect(status).equals("loading");
+ expect(error).undefined;
+ },
+ (state) => {
+ if (state.status !== "ready") expect.fail();
+ if (state.error) expect.fail();
+ expect(state.amount).deep.eq(Amounts.parseOrThrow("EUR:1"));
+ expect(state.merchantBaseUrl).eq("merchant url");
+ expect(state.exchangeBaseUrl).eq("exchange url");
+
+ //FIXME: add ignore button
+ },
+ ], TestingContext)
- await assertNoPendingUpdate();
+ expect(hookBehavior).deep.equal({ result: "ok" })
expect(handler.getCallingQueueState()).eq("empty");
});
it("should render accepted if the tip has been used previously", async () => {
- const { handler, mock } = createWalletApiMock();
+ const { handler, TestingContext } = createWalletApiMock();
handler.addWalletCallResponse(WalletApiOperation.PrepareTip, undefined, {
accepted: true,
@@ -220,40 +177,28 @@ describe("Tip CTA states", () => {
tipAmountRaw: "",
});
- const { pullLastResultOrThrow, waitForStateUpdate, assertNoPendingUpdate } =
- mountHook(() =>
- useComponentState(
- {
- talerTipUri: "taler://tip/asd",
- onCancel: async () => {
- null;
- },
- onSuccess: async () => {
- null;
- },
- },
- mock,
- ),
- );
-
- {
- const { status, error } = pullLastResultOrThrow();
- expect(status).equals("loading");
- expect(error).undefined;
+ const props: Props = {
+ talerTipUri: "taler://tip/asd",
+ onCancel: nullFunction,
+ onSuccess: nullFunction,
}
- expect(await waitForStateUpdate()).true;
-
- {
- const state = pullLastResultOrThrow();
+ const hookBehavior = await tests.hookBehaveLikeThis(useComponentState, props, [
+ ({ status, error }) => {
+ expect(status).equals("loading");
+ expect(error).undefined;
+ },
+ (state) => {
+ if (state.status !== "accepted") expect.fail();
+ if (state.error) expect.fail();
+ expect(state.amount).deep.eq(Amounts.parseOrThrow("EUR:1"));
+ expect(state.merchantBaseUrl).eq("merchant url");
+ expect(state.exchangeBaseUrl).eq("exchange url");
+ },
+ ], TestingContext)
- if (state.status !== "accepted") expect.fail();
- if (state.error) expect.fail();
- expect(state.amount).deep.eq(Amounts.parseOrThrow("EUR:1"));
- expect(state.merchantBaseUrl).eq("merchant url");
- expect(state.exchangeBaseUrl).eq("exchange url");
- }
- await assertNoPendingUpdate();
+ expect(hookBehavior).deep.equal({ result: "ok" })
expect(handler.getCallingQueueState()).eq("empty");
+
});
});
diff --git a/packages/taler-wallet-webextension/src/cta/TransferCreate/index.ts b/packages/taler-wallet-webextension/src/cta/TransferCreate/index.ts
index 8d51ff3e0..0715bb60e 100644
--- a/packages/taler-wallet-webextension/src/cta/TransferCreate/index.ts
+++ b/packages/taler-wallet-webextension/src/cta/TransferCreate/index.ts
@@ -19,7 +19,6 @@ import { Loading } from "../../components/Loading.js";
import { HookError } from "../../hooks/useAsyncAsHook.js";
import { ButtonHandler, TextFieldHandler } from "../../mui/handlers.js";
import { compose, StateViewMap } from "../../utils/index.js";
-import { wxApi } from "../../wxApi.js";
import { useComponentState } from "./state.js";
import { LoadingUriView, ReadyView } from "./views.js";
@@ -66,6 +65,6 @@ const viewMapping: StateViewMap<State> = {
export const TransferCreatePage = compose(
"TransferCreatePage",
- (p: Props) => useComponentState(p, wxApi),
+ (p: Props) => useComponentState(p),
viewMapping,
);
diff --git a/packages/taler-wallet-webextension/src/cta/TransferCreate/state.ts b/packages/taler-wallet-webextension/src/cta/TransferCreate/state.ts
index c5e143f42..3536014da 100644
--- a/packages/taler-wallet-webextension/src/cta/TransferCreate/state.ts
+++ b/packages/taler-wallet-webextension/src/cta/TransferCreate/state.ts
@@ -17,19 +17,19 @@
import {
Amounts,
TalerErrorDetail,
- TalerProtocolTimestamp,
+ TalerProtocolTimestamp
} from "@gnu-taler/taler-util";
import { TalerError, WalletApiOperation } from "@gnu-taler/taler-wallet-core";
-import { format, isFuture, parse } from "date-fns";
+import { isFuture, parse } from "date-fns";
import { useState } from "preact/hooks";
+import { useBackendContext } from "../../context/backend.js";
import { useAsyncAsHook } from "../../hooks/useAsyncAsHook.js";
-import { wxApi } from "../../wxApi.js";
import { Props, State } from "./index.js";
export function useComponentState(
{ amount: amountStr, onClose, onSuccess }: Props,
- api: typeof wxApi,
): State {
+ const api = useBackendContext()
const amount = Amounts.parseOrThrow(amountStr);
const [subject, setSubject] = useState<string | undefined>();
@@ -124,8 +124,8 @@ export function useComponentState(
subject === undefined
? undefined
: !subject
- ? "Can't be empty"
- : undefined,
+ ? "Can't be empty"
+ : undefined,
value: subject ?? "",
onInput: async (e) => setSubject(e),
},
diff --git a/packages/taler-wallet-webextension/src/cta/TransferPickup/index.ts b/packages/taler-wallet-webextension/src/cta/TransferPickup/index.ts
index 399f1e290..de6ad3b79 100644
--- a/packages/taler-wallet-webextension/src/cta/TransferPickup/index.ts
+++ b/packages/taler-wallet-webextension/src/cta/TransferPickup/index.ts
@@ -17,13 +17,12 @@
import {
AbsoluteTime,
AmountJson,
- TalerErrorDetail,
+ TalerErrorDetail
} from "@gnu-taler/taler-util";
import { Loading } from "../../components/Loading.js";
import { HookError } from "../../hooks/useAsyncAsHook.js";
import { ButtonHandler } from "../../mui/handlers.js";
import { compose, StateViewMap } from "../../utils/index.js";
-import { wxApi } from "../../wxApi.js";
import { useComponentState } from "./state.js";
import { LoadingUriView, ReadyView } from "./views.js";
@@ -69,6 +68,6 @@ const viewMapping: StateViewMap<State> = {
export const TransferPickupPage = compose(
"TransferPickupPage",
- (p: Props) => useComponentState(p, wxApi),
+ (p: Props) => useComponentState(p),
viewMapping,
);
diff --git a/packages/taler-wallet-webextension/src/cta/TransferPickup/state.ts b/packages/taler-wallet-webextension/src/cta/TransferPickup/state.ts
index e8fb99ab7..45bec28fb 100644
--- a/packages/taler-wallet-webextension/src/cta/TransferPickup/state.ts
+++ b/packages/taler-wallet-webextension/src/cta/TransferPickup/state.ts
@@ -18,18 +18,18 @@ import {
AbsoluteTime,
Amounts,
TalerErrorDetail,
- TalerProtocolTimestamp,
+ TalerProtocolTimestamp
} from "@gnu-taler/taler-util";
import { TalerError, WalletApiOperation } from "@gnu-taler/taler-wallet-core";
import { useState } from "preact/hooks";
+import { useBackendContext } from "../../context/backend.js";
import { useAsyncAsHook } from "../../hooks/useAsyncAsHook.js";
-import { wxApi } from "../../wxApi.js";
import { Props, State } from "./index.js";
export function useComponentState(
{ talerPayPushUri, onClose, onSuccess }: Props,
- api: typeof wxApi,
): State {
+ const api = useBackendContext()
const hook = useAsyncAsHook(async () => {
return await api.wallet.call(WalletApiOperation.CheckPeerPushPayment, {
talerUri: talerPayPushUri,
diff --git a/packages/taler-wallet-webextension/src/cta/Withdraw/index.ts b/packages/taler-wallet-webextension/src/cta/Withdraw/index.ts
index 68b314c07..9e5943161 100644
--- a/packages/taler-wallet-webextension/src/cta/Withdraw/index.ts
+++ b/packages/taler-wallet-webextension/src/cta/Withdraw/index.ts
@@ -20,10 +20,9 @@ import { HookError } from "../../hooks/useAsyncAsHook.js";
import { State as SelectExchangeState } from "../../hooks/useSelectedExchange.js";
import { ButtonHandler, SelectFieldHandler } from "../../mui/handlers.js";
import { compose, StateViewMap } from "../../utils/index.js";
-import { wxApi } from "../../wxApi.js";
import {
useComponentStateFromParams,
- useComponentStateFromURI,
+ useComponentStateFromURI
} from "./state.js";
import { ExchangeSelectionPage } from "../../wallet/ExchangeSelection/index.js";
@@ -96,11 +95,11 @@ const viewMapping: StateViewMap<State> = {
export const WithdrawPageFromURI = compose(
"WithdrawPageFromURI",
- (p: PropsFromURI) => useComponentStateFromURI(p, wxApi),
+ (p: PropsFromURI) => useComponentStateFromURI(p),
viewMapping,
);
export const WithdrawPageFromParams = compose(
"WithdrawPageFromParams",
- (p: PropsFromParams) => useComponentStateFromParams(p, wxApi),
+ (p: PropsFromParams) => useComponentStateFromParams(p),
viewMapping,
);
diff --git a/packages/taler-wallet-webextension/src/cta/Withdraw/state.ts b/packages/taler-wallet-webextension/src/cta/Withdraw/state.ts
index 9bb29fbd6..4420221fc 100644
--- a/packages/taler-wallet-webextension/src/cta/Withdraw/state.ts
+++ b/packages/taler-wallet-webextension/src/cta/Withdraw/state.ts
@@ -19,20 +19,20 @@ import {
AmountJson,
Amounts,
ExchangeListItem,
- ExchangeTosStatus,
+ ExchangeTosStatus
} from "@gnu-taler/taler-util";
import { TalerError, WalletApiOperation } from "@gnu-taler/taler-wallet-core";
import { useState } from "preact/hooks";
+import { useBackendContext } from "../../context/backend.js";
import { useAsyncAsHook } from "../../hooks/useAsyncAsHook.js";
import { useSelectedExchange } from "../../hooks/useSelectedExchange.js";
import { RecursiveState } from "../../utils/index.js";
-import { wxApi } from "../../wxApi.js";
import { PropsFromParams, PropsFromURI, State } from "./index.js";
export function useComponentStateFromParams(
{ amount, cancel, onSuccess }: PropsFromParams,
- api: typeof wxApi,
): RecursiveState<State> {
+ const api = useBackendContext()
const uriInfoHook = useAsyncAsHook(async () => {
const exchanges = await api.wallet.call(
WalletApiOperation.ListExchanges,
@@ -84,14 +84,13 @@ export function useComponentStateFromParams(
chosenAmount,
exchangeList,
undefined,
- api,
);
}
export function useComponentStateFromURI(
{ talerWithdrawUri, cancel, onSuccess }: PropsFromURI,
- api: typeof wxApi,
): RecursiveState<State> {
+ const api = useBackendContext()
/**
* Ask the wallet about the withdraw URI
*/
@@ -158,7 +157,6 @@ export function useComponentStateFromURI(
chosenAmount,
exchangeList,
defaultExchange,
- api,
);
}
@@ -176,8 +174,8 @@ function exchangeSelectionState(
chosenAmount: AmountJson,
exchangeList: ExchangeListItem[],
defaultExchange: string | undefined,
- api: typeof wxApi,
): RecursiveState<State> {
+ const api = useBackendContext()
const selectedExchange = useSelectedExchange({
currency: chosenAmount.currency,
defaultExchange,
@@ -278,10 +276,10 @@ function exchangeSelectionState(
//TODO: calculate based on exchange info
const ageRestriction = ageRestrictionEnabled
? {
- list: ageRestrictionOptions,
- value: String(ageRestricted),
- onChange: async (v: string) => setAgeRestricted(parseInt(v, 10)),
- }
+ list: ageRestrictionOptions,
+ value: String(ageRestricted),
+ onChange: async (v: string) => setAgeRestricted(parseInt(v, 10)),
+ }
: undefined;
return {
diff --git a/packages/taler-wallet-webextension/src/cta/Withdraw/test.ts b/packages/taler-wallet-webextension/src/cta/Withdraw/test.ts
index 7fd8188ce..084b4368c 100644
--- a/packages/taler-wallet-webextension/src/cta/Withdraw/test.ts
+++ b/packages/taler-wallet-webextension/src/cta/Withdraw/test.ts
@@ -27,6 +27,7 @@ import {
} from "@gnu-taler/taler-util";
import { WalletApiOperation } from "@gnu-taler/taler-wallet-core";
import { expect } from "chai";
+import { tests } from "../../../../web-util/src/index.browser.js";
import { mountHook } from "../../test-utils.js";
import { createWalletApiMock } from "../../test-utils.js";
import { useComponentStateFromURI } from "./state.js";
@@ -61,53 +62,45 @@ const exchanges: ExchangeListItem[] = [
} as Partial<ExchangeListItem> as ExchangeListItem,
];
+const nullFunction = async (): Promise<void> => {
+ null;
+}
+
describe("Withdraw CTA states", () => {
it("should tell the user that the URI is missing", async () => {
- const { handler, mock } = createWalletApiMock();
+ const { handler, TestingContext } = createWalletApiMock();
+
const props = {
talerWithdrawUri: undefined,
- cancel: async () => {
- null;
- },
- onSuccess: async () => {
- null;
- },
+ cancel: nullFunction,
+ onSuccess: nullFunction,
};
- const { pullLastResultOrThrow, waitForStateUpdate, assertNoPendingUpdate } =
- mountHook(() => useComponentStateFromURI(props, mock));
-
- {
- const { status } = pullLastResultOrThrow();
- expect(status).equals("loading");
- }
-
- expect(await waitForStateUpdate()).true;
- {
- const { status, error } = pullLastResultOrThrow();
-
- if (status != "uri-error") expect.fail();
- if (!error) expect.fail();
- if (!error.hasError) expect.fail();
- if (error.operational) expect.fail();
- expect(error.message).eq("ERROR_NO-URI-FOR-WITHDRAWAL");
- }
+ const hookBehavior = await tests.hookBehaveLikeThis(useComponentStateFromURI, props, [
+ ({ status }) => {
+ expect(status).equals("loading");
+ },
+ ({ status, error }) => {
+ if (status != "uri-error") expect.fail();
+ if (!error) expect.fail();
+ if (!error.hasError) expect.fail();
+ if (error.operational) expect.fail();
+ expect(error.message).eq("ERROR_NO-URI-FOR-WITHDRAWAL");
+ },
+ ], TestingContext)
- await assertNoPendingUpdate();
+ expect(hookBehavior).deep.equal({ result: "ok" })
expect(handler.getCallingQueueState()).eq("empty");
});
it("should tell the user that there is not known exchange", async () => {
- const { handler, mock } = createWalletApiMock();
+ const { handler, TestingContext } = createWalletApiMock();
const props = {
talerWithdrawUri: "taler-withdraw://",
- cancel: async () => {
- null;
- },
- onSuccess: async () => {
- null;
- },
+ cancel: nullFunction,
+ onSuccess: nullFunction,
};
+
handler.addWalletCallResponse(
WalletApiOperation.GetWithdrawalDetailsForUri,
undefined,
@@ -117,39 +110,28 @@ describe("Withdraw CTA states", () => {
},
);
- const { pullLastResultOrThrow, waitForStateUpdate, assertNoPendingUpdate } =
- mountHook(() => useComponentStateFromURI(props, mock));
-
- {
- const { status } = pullLastResultOrThrow();
- expect(status).equals("loading", "1");
- }
-
- expect(await waitForStateUpdate()).true;
-
- {
- const { status, error } = pullLastResultOrThrow();
-
- expect(status).equals("no-exchange", "3");
-
- expect(error).undefined;
- }
+ const hookBehavior = await tests.hookBehaveLikeThis(useComponentStateFromURI, props, [
+ ({ status }) => {
+ expect(status).equals("loading");
+ },
+ ({ status, error }) => {
+ expect(status).equals("no-exchange");
+ expect(error).undefined;
+ },
+ ], TestingContext)
- await assertNoPendingUpdate();
+ expect(hookBehavior).deep.equal({ result: "ok" })
expect(handler.getCallingQueueState()).eq("empty");
});
it("should be able to withdraw if tos are ok", async () => {
- const { handler, mock } = createWalletApiMock();
+ const { handler, TestingContext } = createWalletApiMock();
const props = {
talerWithdrawUri: "taler-withdraw://",
- cancel: async () => {
- null;
- },
- onSuccess: async () => {
- null;
- },
+ cancel: nullFunction,
+ onSuccess: nullFunction,
};
+
handler.addWalletCallResponse(
WalletApiOperation.GetWithdrawalDetailsForUri,
undefined,
@@ -171,54 +153,38 @@ describe("Withdraw CTA states", () => {
},
);
- const { pullLastResultOrThrow, waitForStateUpdate, assertNoPendingUpdate } =
- mountHook(() => useComponentStateFromURI(props, mock));
-
- {
- const { status, error } = pullLastResultOrThrow();
- expect(status).equals("loading");
- expect(error).undefined;
- }
-
- expect(await waitForStateUpdate()).true;
-
- {
- const { status, error } = pullLastResultOrThrow();
-
- expect(status).equals("loading");
-
- expect(error).undefined;
- }
-
- expect(await waitForStateUpdate()).true;
-
- {
- const state = pullLastResultOrThrow();
- expect(state.status).equals("success");
- if (state.status !== "success") return;
+ const hookBehavior = await tests.hookBehaveLikeThis(useComponentStateFromURI, props, [
+ ({ status }) => {
+ expect(status).equals("loading");
+ },
+ ({ status, error }) => {
+ expect(status).equals("loading");
+ expect(error).undefined;
+ },
+ (state) => {
+ expect(state.status).equals("success");
+ if (state.status !== "success") return;
- expect(state.toBeReceived).deep.equal(Amounts.parseOrThrow("ARS:2"));
- expect(state.withdrawalFee).deep.equal(Amounts.parseOrThrow("ARS:0"));
- expect(state.chosenAmount).deep.equal(Amounts.parseOrThrow("ARS:2"));
+ expect(state.toBeReceived).deep.equal(Amounts.parseOrThrow("ARS:2"));
+ expect(state.withdrawalFee).deep.equal(Amounts.parseOrThrow("ARS:0"));
+ expect(state.chosenAmount).deep.equal(Amounts.parseOrThrow("ARS:2"));
- expect(state.doWithdrawal.onClick).not.undefined;
- }
+ expect(state.doWithdrawal.onClick).not.undefined;
+ },
+ ], TestingContext)
- await assertNoPendingUpdate();
+ expect(hookBehavior).deep.equal({ result: "ok" })
expect(handler.getCallingQueueState()).eq("empty");
});
it("should accept the tos before withdraw", async () => {
- const { handler, mock } = createWalletApiMock();
+ const { handler, TestingContext } = createWalletApiMock();
const props = {
talerWithdrawUri: "taler-withdraw://",
- cancel: async () => {
- null;
- },
- onSuccess: async () => {
- null;
- },
+ cancel: nullFunction,
+ onSuccess: nullFunction,
};
+
const exchangeWithNewTos = exchanges.map((e) => ({
...e,
tosStatus: ExchangeTosStatus.New,
@@ -255,57 +221,39 @@ describe("Withdraw CTA states", () => {
},
);
- const { pullLastResultOrThrow, waitForStateUpdate, assertNoPendingUpdate } =
- mountHook(() => useComponentStateFromURI(props, mock));
-
- {
- const { status, error } = pullLastResultOrThrow();
- expect(status).equals("loading");
- expect(error).undefined;
- }
-
- expect(await waitForStateUpdate()).true;
-
- {
- const { status, error } = pullLastResultOrThrow();
-
- expect(status).equals("loading");
-
- expect(error).undefined;
- }
-
- expect(await waitForStateUpdate()).true;
-
- {
- const state = pullLastResultOrThrow();
- expect(state.status).equals("success");
- if (state.status !== "success") return;
-
- expect(state.toBeReceived).deep.equal(Amounts.parseOrThrow("ARS:2"));
- expect(state.withdrawalFee).deep.equal(Amounts.parseOrThrow("ARS:0"));
- expect(state.chosenAmount).deep.equal(Amounts.parseOrThrow("ARS:2"));
-
- expect(state.doWithdrawal.onClick).undefined;
+ const hookBehavior = await tests.hookBehaveLikeThis(useComponentStateFromURI, props, [
+ ({ status }) => {
+ expect(status).equals("loading");
+ },
+ ({ status, error }) => {
+ expect(status).equals("loading");
+ expect(error).undefined;
+ },
+ (state) => {
+ expect(state.status).equals("success");
+ if (state.status !== "success") return;
- // updateAcceptedVersionToCurrentVersion();
- state.onTosUpdate();
- }
+ expect(state.toBeReceived).deep.equal(Amounts.parseOrThrow("ARS:2"));
+ expect(state.withdrawalFee).deep.equal(Amounts.parseOrThrow("ARS:0"));
+ expect(state.chosenAmount).deep.equal(Amounts.parseOrThrow("ARS:2"));
- expect(await waitForStateUpdate()).true;
+ expect(state.doWithdrawal.onClick).undefined;
- {
- const state = pullLastResultOrThrow();
- expect(state.status).equals("success");
- if (state.status !== "success") return;
+ state.onTosUpdate();
+ },
+ (state) => {
+ expect(state.status).equals("success");
+ if (state.status !== "success") return;
- expect(state.toBeReceived).deep.equal(Amounts.parseOrThrow("ARS:2"));
- expect(state.withdrawalFee).deep.equal(Amounts.parseOrThrow("ARS:0"));
- expect(state.chosenAmount).deep.equal(Amounts.parseOrThrow("ARS:2"));
+ expect(state.toBeReceived).deep.equal(Amounts.parseOrThrow("ARS:2"));
+ expect(state.withdrawalFee).deep.equal(Amounts.parseOrThrow("ARS:0"));
+ expect(state.chosenAmount).deep.equal(Amounts.parseOrThrow("ARS:2"));
- expect(state.doWithdrawal.onClick).not.undefined;
- }
+ expect(state.doWithdrawal.onClick).not.undefined;
+ },
+ ], TestingContext)
- await assertNoPendingUpdate();
+ expect(hookBehavior).deep.equal({ result: "ok" })
expect(handler.getCallingQueueState()).eq("empty");
});
});
diff --git a/packages/taler-wallet-webextension/src/hooks/useAutoOpenPermissions.ts b/packages/taler-wallet-webextension/src/hooks/useAutoOpenPermissions.ts
index 3361394a4..1a48cdca7 100644
--- a/packages/taler-wallet-webextension/src/hooks/useAutoOpenPermissions.ts
+++ b/packages/taler-wallet-webextension/src/hooks/useAutoOpenPermissions.ts
@@ -16,22 +16,23 @@
import { TalerError } from "@gnu-taler/taler-wallet-core";
import { useEffect, useState } from "preact/hooks";
+import { useBackendContext } from "../context/backend.js";
import { ToggleHandler } from "../mui/handlers.js";
import { platform } from "../platform/api.js";
-import { wxApi } from "../wxApi.js";
export function useAutoOpenPermissions(): ToggleHandler {
+ const api = useBackendContext();
const [enabled, setEnabled] = useState(false);
const [error, setError] = useState<TalerError | undefined>();
const toggle = async (): Promise<void> => {
- return handleAutoOpenPerm(enabled, setEnabled).catch((e) => {
+ return handleAutoOpenPerm(enabled, setEnabled, api.background).catch((e) => {
setError(TalerError.fromException(e));
});
};
useEffect(() => {
async function getValue(): Promise<void> {
- const res = await wxApi.background.containsHeaderListener();
+ const res = await api.background.containsHeaderListener();
setEnabled(res.newValue);
}
getValue();
@@ -48,6 +49,7 @@ export function useAutoOpenPermissions(): ToggleHandler {
async function handleAutoOpenPerm(
isEnabled: boolean,
onChange: (value: boolean) => void,
+ background: ReturnType<typeof useBackendContext>["background"],
): Promise<void> {
if (!isEnabled) {
// We set permissions here, since apparently FF wants this to be done
@@ -59,11 +61,11 @@ async function handleAutoOpenPerm(
onChange(false);
throw lastError;
}
- const res = await wxApi.background.toggleHeaderListener(granted);
+ const res = await background.toggleHeaderListener(granted);
onChange(res.newValue);
} else {
try {
- await wxApi.background
+ await background
.toggleHeaderListener(false)
.then((r) => onChange(r.newValue));
} catch (e) {
diff --git a/packages/taler-wallet-webextension/src/hooks/useBackupDeviceName.ts b/packages/taler-wallet-webextension/src/hooks/useBackupDeviceName.ts
index be81b7d7d..585a643a9 100644
--- a/packages/taler-wallet-webextension/src/hooks/useBackupDeviceName.ts
+++ b/packages/taler-wallet-webextension/src/hooks/useBackupDeviceName.ts
@@ -16,7 +16,7 @@
import { WalletApiOperation } from "@gnu-taler/taler-wallet-core";
import { useEffect, useState } from "preact/hooks";
-import { wxApi } from "../wxApi.js";
+import { useBackendContext } from "../context/backend.js";
export interface BackupDeviceName {
name: string;
@@ -28,17 +28,18 @@ export function useBackupDeviceName(): BackupDeviceName {
name: "",
update: () => Promise.resolve(),
});
+ const api = useBackendContext()
useEffect(() => {
async function run(): Promise<void> {
//create a first list of backup info by currency
- const status = await wxApi.wallet.call(
+ const status = await api.wallet.call(
WalletApiOperation.GetBackupInfo,
{},
);
async function update(newName: string): Promise<void> {
- await wxApi.wallet.call(WalletApiOperation.SetWalletDeviceId, {
+ await api.wallet.call(WalletApiOperation.SetWalletDeviceId, {
walletDeviceId: newName,
});
setStatus((old) => ({ ...old, name: newName }));
diff --git a/packages/taler-wallet-webextension/src/hooks/useClipboardPermissions.ts b/packages/taler-wallet-webextension/src/hooks/useClipboardPermissions.ts
index 9b7d46ba7..649def599 100644
--- a/packages/taler-wallet-webextension/src/hooks/useClipboardPermissions.ts
+++ b/packages/taler-wallet-webextension/src/hooks/useClipboardPermissions.ts
@@ -16,22 +16,24 @@
import { TalerError } from "@gnu-taler/taler-wallet-core";
import { useEffect, useState } from "preact/hooks";
+import { useBackendContext } from "../context/backend.js";
import { ToggleHandler } from "../mui/handlers.js";
import { platform } from "../platform/api.js";
-import { wxApi } from "../wxApi.js";
export function useClipboardPermissions(): ToggleHandler {
const [enabled, setEnabled] = useState(false);
const [error, setError] = useState<TalerError | undefined>();
+ const api = useBackendContext()
+
const toggle = async (): Promise<void> => {
- return handleClipboardPerm(enabled, setEnabled).catch((e) => {
+ return handleClipboardPerm(enabled, setEnabled, api.background).catch((e) => {
setError(TalerError.fromException(e));
});
};
useEffect(() => {
async function getValue(): Promise<void> {
- const res = await wxApi.background.containsHeaderListener();
+ const res = await api.background.containsHeaderListener();
setEnabled(res.newValue);
}
getValue();
@@ -49,6 +51,7 @@ export function useClipboardPermissions(): ToggleHandler {
async function handleClipboardPerm(
isEnabled: boolean,
onChange: (value: boolean) => void,
+ background: ReturnType<typeof useBackendContext>["background"],
): Promise<void> {
if (!isEnabled) {
// We set permissions here, since apparently FF wants this to be done
@@ -62,11 +65,10 @@ async function handleClipboardPerm(
onChange(false);
throw lastError;
}
- // const res = await wxApi.toggleHeaderListener(granted);
onChange(granted);
} else {
try {
- await wxApi.background
+ await background
.toggleHeaderListener(false)
.then((r) => onChange(r.newValue));
} catch (e) {
diff --git a/packages/taler-wallet-webextension/src/hooks/useDiagnostics.ts b/packages/taler-wallet-webextension/src/hooks/useDiagnostics.ts
index a8564fddb..1f36ca6c0 100644
--- a/packages/taler-wallet-webextension/src/hooks/useDiagnostics.ts
+++ b/packages/taler-wallet-webextension/src/hooks/useDiagnostics.ts
@@ -16,10 +16,11 @@
import { WalletDiagnostics } from "@gnu-taler/taler-util";
import { useEffect, useState } from "preact/hooks";
-import { wxApi } from "../wxApi.js";
+import { useBackendContext } from "../context/backend.js";
export function useDiagnostics(): [WalletDiagnostics | undefined, boolean] {
const [timedOut, setTimedOut] = useState(false);
+ const api = useBackendContext();
const [diagnostics, setDiagnostics] = useState<WalletDiagnostics | undefined>(
undefined,
);
@@ -33,7 +34,7 @@ export function useDiagnostics(): [WalletDiagnostics | undefined, boolean] {
}
}, 1000);
const doFetch = async (): Promise<void> => {
- const d = await wxApi.background.getDiagnostics();
+ const d = await api.background.getDiagnostics();
gotDiagnostics = true;
setDiagnostics(d);
};
diff --git a/packages/taler-wallet-webextension/src/hooks/useProviderStatus.ts b/packages/taler-wallet-webextension/src/hooks/useProviderStatus.ts
index e6473d1ec..ca2054931 100644
--- a/packages/taler-wallet-webextension/src/hooks/useProviderStatus.ts
+++ b/packages/taler-wallet-webextension/src/hooks/useProviderStatus.ts
@@ -16,7 +16,7 @@
import { ProviderInfo, WalletApiOperation } from "@gnu-taler/taler-wallet-core";
import { useEffect, useState } from "preact/hooks";
-import { wxApi } from "../wxApi.js";
+import { useBackendContext } from "../context/backend.js";
export interface ProviderStatus {
info?: ProviderInfo;
@@ -26,11 +26,11 @@ export interface ProviderStatus {
export function useProviderStatus(url: string): ProviderStatus | undefined {
const [status, setStatus] = useState<ProviderStatus | undefined>(undefined);
-
+ const api = useBackendContext();
useEffect(() => {
async function run(): Promise<void> {
//create a first list of backup info by currency
- const status = await wxApi.wallet.call(
+ const status = await api.wallet.call(
WalletApiOperation.GetBackupInfo,
{},
);
@@ -42,7 +42,7 @@ export function useProviderStatus(url: string): ProviderStatus | undefined {
async function sync(): Promise<void> {
if (info) {
- await wxApi.wallet.call(WalletApiOperation.RunBackupCycle, {
+ await api.wallet.call(WalletApiOperation.RunBackupCycle, {
providers: [info.syncProviderBaseUrl],
});
}
@@ -50,7 +50,7 @@ export function useProviderStatus(url: string): ProviderStatus | undefined {
async function remove(): Promise<void> {
if (info) {
- await wxApi.wallet.call(WalletApiOperation.RemoveBackupProvider, {
+ await api.wallet.call(WalletApiOperation.RemoveBackupProvider, {
provider: info.syncProviderBaseUrl,
});
}
diff --git a/packages/taler-wallet-webextension/src/hooks/useWalletDevMode.ts b/packages/taler-wallet-webextension/src/hooks/useWalletDevMode.ts
index d5743eb2e..6ae55da61 100644
--- a/packages/taler-wallet-webextension/src/hooks/useWalletDevMode.ts
+++ b/packages/taler-wallet-webextension/src/hooks/useWalletDevMode.ts
@@ -15,22 +15,24 @@
*/
import { useState, useEffect } from "preact/hooks";
-import { wxApi } from "../wxApi.js";
import { ToggleHandler } from "../mui/handlers.js";
import { TalerError, WalletApiOperation } from "@gnu-taler/taler-wallet-core";
+import { useBackendContext } from "../context/backend.js";
export function useWalletDevMode(): ToggleHandler {
const [enabled, setEnabled] = useState<undefined | boolean>(undefined);
const [error, setError] = useState<TalerError | undefined>();
+ const api = useBackendContext();
+
const toggle = async (): Promise<void> => {
- return handleOpen(enabled, setEnabled).catch((e) => {
+ return handleOpen(enabled, setEnabled, api).catch((e) => {
setError(TalerError.fromException(e));
});
};
useEffect(() => {
async function getValue(): Promise<void> {
- const res = await wxApi.wallet.call(WalletApiOperation.GetVersion, {});
+ const res = await api.wallet.call(WalletApiOperation.GetVersion, {});
setEnabled(res.devMode);
}
getValue();
@@ -47,9 +49,10 @@ export function useWalletDevMode(): ToggleHandler {
async function handleOpen(
currentValue: undefined | boolean,
onChange: (value: boolean) => void,
+ api: ReturnType<typeof useBackendContext>,
): Promise<void> {
const nextValue = !currentValue;
- await wxApi.wallet.call(WalletApiOperation.SetDevMode, {
+ await api.wallet.call(WalletApiOperation.SetDevMode, {
devModeEnabled: nextValue,
});
onChange(nextValue);
diff --git a/packages/taler-wallet-webextension/src/popup/BalancePage.tsx b/packages/taler-wallet-webextension/src/popup/BalancePage.tsx
index 98c6d166c..8786b2ff7 100644
--- a/packages/taler-wallet-webextension/src/popup/BalancePage.tsx
+++ b/packages/taler-wallet-webextension/src/popup/BalancePage.tsx
@@ -22,13 +22,13 @@ import { BalanceTable } from "../components/BalanceTable.js";
import { Loading } from "../components/Loading.js";
import { LoadingError } from "../components/LoadingError.js";
import { MultiActionButton } from "../components/MultiActionButton.js";
+import { useBackendContext } from "../context/backend.js";
import { useTranslationContext } from "../context/translation.js";
import { HookError, useAsyncAsHook } from "../hooks/useAsyncAsHook.js";
import { Button } from "../mui/Button.js";
import { ButtonHandler } from "../mui/handlers.js";
import { compose, StateViewMap } from "../utils/index.js";
import { AddNewActionView } from "../wallet/AddNewActionView.js";
-import { wxApi } from "../wxApi.js";
import { NoBalanceHelp } from "./NoBalanceHelp.js";
export interface Props {
@@ -67,10 +67,12 @@ export namespace State {
}
}
-function useComponentState(
- { goToWalletDeposit, goToWalletHistory, goToWalletManualWithdraw }: Props,
- api: typeof wxApi,
-): State {
+function useComponentState({
+ goToWalletDeposit,
+ goToWalletHistory,
+ goToWalletManualWithdraw,
+}: Props): State {
+ const api = useBackendContext();
const [addingAction, setAddingAction] = useState(false);
const state = useAsyncAsHook(() =>
api.wallet.call(WalletApiOperation.GetBalances, {}),
@@ -128,7 +130,7 @@ const viewMapping: StateViewMap<State> = {
export const BalancePage = compose(
"BalancePage",
- (p: Props) => useComponentState(p, wxApi),
+ (p: Props) => useComponentState(p),
viewMapping,
);
diff --git a/packages/taler-wallet-webextension/src/test-utils.ts b/packages/taler-wallet-webextension/src/test-utils.ts
index b4983b4c2..791773c42 100644
--- a/packages/taler-wallet-webextension/src/test-utils.ts
+++ b/packages/taler-wallet-webextension/src/test-utils.ts
@@ -31,6 +31,7 @@ import {
VNode,
} from "preact";
import { render as renderToString } from "preact-render-to-string";
+import { BackendProvider } from "./context/backend.js";
import { BackgroundApiClient, wxApi } from "./wxApi.js";
// When doing tests we want the requestAnimationFrame to be as fast as possible.
@@ -252,7 +253,7 @@ type Subscriptions = {
export function createWalletApiMock(): {
handler: MockHandler;
- mock: typeof wxApi;
+ TestingContext: FunctionalComponent<{ children: ComponentChildren }>
} {
const calls = new Array<CallRecord>();
const subscriptions: Subscriptions = {};
@@ -357,5 +358,14 @@ export function createWalletApiMock(): {
},
};
- return { handler, mock };
+ function TestingContext({ children }: { children: ComponentChildren }): VNode {
+ return create(BackendProvider, {
+ wallet: mock.wallet,
+ background: mock.background,
+ listener: mock.listener,
+ children,
+ }, children)
+ }
+
+ return { handler, TestingContext };
}
diff --git a/packages/taler-wallet-webextension/src/wallet/AddBackupProvider/index.ts b/packages/taler-wallet-webextension/src/wallet/AddBackupProvider/index.ts
index 3205588af..2adcc9f74 100644
--- a/packages/taler-wallet-webextension/src/wallet/AddBackupProvider/index.ts
+++ b/packages/taler-wallet-webextension/src/wallet/AddBackupProvider/index.ts
@@ -15,9 +15,7 @@
*/
import {
- AmountJson,
- BackupBackupProviderTerms,
- TalerErrorDetail,
+ TalerErrorDetail
} from "@gnu-taler/taler-util";
import { SyncTermsOfServiceResponse } from "@gnu-taler/taler-wallet-core";
import { Loading } from "../../components/Loading.js";
@@ -25,15 +23,13 @@ import { HookError } from "../../hooks/useAsyncAsHook.js";
import {
ButtonHandler,
TextFieldHandler,
- ToggleHandler,
+ ToggleHandler
} from "../../mui/handlers.js";
import { compose, StateViewMap } from "../../utils/index.js";
-import { wxApi } from "../../wxApi.js";
import { useComponentState } from "./state.js";
import {
- LoadingUriView,
- SelectProviderView,
- ConfirmProviderView,
+ ConfirmProviderView, LoadingUriView,
+ SelectProviderView
} from "./views.js";
export interface Props {
@@ -90,6 +86,6 @@ const viewMapping: StateViewMap<State> = {
export const AddBackupProviderPage = compose(
"AddBackupProvider",
- (p: Props) => useComponentState(p, wxApi),
+ (p: Props) => useComponentState(p),
viewMapping,
);
diff --git a/packages/taler-wallet-webextension/src/wallet/AddBackupProvider/state.ts b/packages/taler-wallet-webextension/src/wallet/AddBackupProvider/state.ts
index 504ee4678..271a1bf98 100644
--- a/packages/taler-wallet-webextension/src/wallet/AddBackupProvider/state.ts
+++ b/packages/taler-wallet-webextension/src/wallet/AddBackupProvider/state.ts
@@ -17,15 +17,15 @@
import {
canonicalizeBaseUrl,
Codec,
- TalerErrorDetail,
+ TalerErrorDetail
} from "@gnu-taler/taler-util";
import {
codecForSyncTermsOfServiceResponse,
- WalletApiOperation,
+ WalletApiOperation
} from "@gnu-taler/taler-wallet-core";
import { useEffect, useState } from "preact/hooks";
+import { useBackendContext } from "../../context/backend.js";
import { assertUnreachable } from "../../utils/index.js";
-import { wxApi } from "../../wxApi.js";
import { Props, State } from "./index.js";
type UrlState<T> = UrlOk<T> | UrlError;
@@ -106,37 +106,37 @@ function useUrlState<T>(
constHref == undefined
? undefined
: async () => {
- const req = await fetch(constHref).catch((e) => {
- return setState({
- status: "network-error",
- href: constHref,
- });
+ const req = await fetch(constHref).catch((e) => {
+ return setState({
+ status: "network-error",
+ href: constHref,
});
- if (!req) return;
+ });
+ if (!req) return;
- if (req.status >= 400 && req.status < 500) {
- setState({
- status: "client-error",
- code: req.status,
- });
- return;
- }
- if (req.status > 500) {
- setState({
- status: "server-error",
- code: req.status,
- });
- return;
- }
+ if (req.status >= 400 && req.status < 500) {
+ setState({
+ status: "client-error",
+ code: req.status,
+ });
+ return;
+ }
+ if (req.status > 500) {
+ setState({
+ status: "server-error",
+ code: req.status,
+ });
+ return;
+ }
- const json = await req.json();
- try {
- const result = codec.decode(json);
- setState({ status: "ok", result });
- } catch (e: any) {
- setState({ status: "parsing-error", json });
- }
- },
+ const json = await req.json();
+ try {
+ const result = codec.decode(json);
+ setState({ status: "ok", result });
+ } catch (e: any) {
+ setState({ status: "parsing-error", json });
+ }
+ },
[host, path],
);
@@ -145,8 +145,8 @@ function useUrlState<T>(
export function useComponentState(
{ currency, onBack, onComplete, onPaymentRequired }: Props,
- api: typeof wxApi,
): State {
+ const api = useBackendContext()
const [url, setHost] = useState<string | undefined>();
const [name, setName] = useState<string | undefined>();
const [tos, setTos] = useState(false);
@@ -223,8 +223,8 @@ export function useComponentState(
!urlState || urlState.status !== "ok" || !name
? undefined
: async () => {
- setShowConfirm(true);
- },
+ setShowConfirm(true);
+ },
},
urlOk: urlState?.status === "ok",
url: {
diff --git a/packages/taler-wallet-webextension/src/wallet/AddBackupProvider/test.ts b/packages/taler-wallet-webextension/src/wallet/AddBackupProvider/test.ts
index 1143853f8..929e051cb 100644
--- a/packages/taler-wallet-webextension/src/wallet/AddBackupProvider/test.ts
+++ b/packages/taler-wallet-webextension/src/wallet/AddBackupProvider/test.ts
@@ -19,12 +19,10 @@
* @author Sebastian Javier Marchano (sebasjm)
*/
-import { WalletApiOperation } from "@gnu-taler/taler-wallet-core";
import { expect } from "chai";
+import { tests } from "../../../../web-util/src/index.browser.js";
import {
- createWalletApiMock,
- mountHook,
- nullFunction,
+ createWalletApiMock, nullFunction
} from "../../test-utils.js";
import { Props } from "./index.js";
import { useComponentState } from "./state.js";
@@ -36,44 +34,21 @@ const props: Props = {
onPaymentRequired: nullFunction,
};
describe("AddBackupProvider states", () => {
- it("should start in 'select-provider' state", async () => {
- const { handler, mock } = createWalletApiMock();
-
- // handler.addWalletCallResponse(
- // WalletApiOperation.ListKnownBankAccounts,
- // undefined,
- // {
- // accounts: [],
- // },
- // );
-
- const { pullLastResultOrThrow, waitForStateUpdate, assertNoPendingUpdate } =
- mountHook(() => useComponentState(props, mock));
-
- {
- const state = pullLastResultOrThrow();
- expect(state.status).equal("select-provider");
- if (state.status !== "select-provider") return;
- expect(state.name.value).eq("");
- expect(state.url.value).eq("");
- }
- //FIXME: this should not make an extra update
- /**
- * this may be due to useUrlState because is using an effect over
- * a dependency with a timeout
- */
- // NOTE: do not remove this comment, keeping as an example
- // await waitForStateUpdate()
- // {
- // const state = pullLastResultOrThrow();
- // expect(state.status).equal("select-provider");
- // if (state.status !== "select-provider") return;
- // expect(state.name.value).eq("")
- // expect(state.url.value).eq("")
- // }
-
- await assertNoPendingUpdate();
+ it("should start in 'select-provider' state", async () => {
+ const { handler, TestingContext } = createWalletApiMock();
+
+ const hookBehavior = await tests.hookBehaveLikeThis(useComponentState, props, [
+ (state) => {
+ expect(state.status).equal("select-provider");
+ if (state.status !== "select-provider") return;
+ expect(state.name.value).eq("");
+ expect(state.url.value).eq("");
+ },
+ ], TestingContext)
+
+ expect(hookBehavior).deep.equal({ result: "ok" })
expect(handler.getCallingQueueState()).eq("empty");
+
});
});
diff --git a/packages/taler-wallet-webextension/src/wallet/BackupPage.tsx b/packages/taler-wallet-webextension/src/wallet/BackupPage.tsx
index c9dbfb64d..6e987f965 100644
--- a/packages/taler-wallet-webextension/src/wallet/BackupPage.tsx
+++ b/packages/taler-wallet-webextension/src/wallet/BackupPage.tsx
@@ -42,11 +42,11 @@ import {
SmallText,
WarningBox,
} from "../components/styled/index.js";
+import { useBackendContext } from "../context/backend.js";
import { useTranslationContext } from "../context/translation.js";
import { useAsyncAsHook } from "../hooks/useAsyncAsHook.js";
import { Button } from "../mui/Button.js";
import { Pages } from "../NavigationBar.js";
-import { wxApi } from "../wxApi.js";
interface Props {
onAddProvider: () => Promise<void>;
@@ -107,8 +107,9 @@ export function ShowRecoveryInfo({
export function BackupPage({ onAddProvider }: Props): VNode {
const { i18n } = useTranslationContext();
+ const api = useBackendContext();
const status = useAsyncAsHook(() =>
- wxApi.wallet.call(WalletApiOperation.GetBackupInfo, {}),
+ api.wallet.call(WalletApiOperation.GetBackupInfo, {}),
);
const [recoveryInfo, setRecoveryInfo] = useState<string>("");
if (!status) {
@@ -124,7 +125,7 @@ export function BackupPage({ onAddProvider }: Props): VNode {
}
async function getRecoveryInfo(): Promise<void> {
- const r = await wxApi.wallet.call(
+ const r = await api.wallet.call(
WalletApiOperation.ExportBackupRecovery,
{},
);
@@ -158,7 +159,7 @@ export function BackupPage({ onAddProvider }: Props): VNode {
providers={providers}
onAddProvider={onAddProvider}
onSyncAll={async () =>
- wxApi.wallet.call(WalletApiOperation.RunBackupCycle, {}).then()
+ api.wallet.call(WalletApiOperation.RunBackupCycle, {}).then()
}
onShowInfo={getRecoveryInfo}
/>
diff --git a/packages/taler-wallet-webextension/src/wallet/DepositPage/index.ts b/packages/taler-wallet-webextension/src/wallet/DepositPage/index.ts
index 3f23515b2..ad4c759bf 100644
--- a/packages/taler-wallet-webextension/src/wallet/DepositPage/index.ts
+++ b/packages/taler-wallet-webextension/src/wallet/DepositPage/index.ts
@@ -20,11 +20,9 @@ import { HookError } from "../../hooks/useAsyncAsHook.js";
import {
AmountFieldHandler,
ButtonHandler,
- SelectFieldHandler,
- TextFieldHandler,
+ SelectFieldHandler
} from "../../mui/handlers.js";
import { compose, StateViewMap } from "../../utils/index.js";
-import { wxApi } from "../../wxApi.js";
import { ManageAccountPage } from "../ManageAccount/index.js";
import { useComponentState } from "./state.js";
import {
@@ -32,7 +30,7 @@ import {
LoadingErrorView,
NoAccountToDepositView,
NoEnoughBalanceView,
- ReadyView,
+ ReadyView
} from "./views.js";
export interface Props {
@@ -119,6 +117,6 @@ const viewMapping: StateViewMap<State> = {
export const DepositPage = compose(
"DepositPage",
- (p: Props) => useComponentState(p, wxApi),
+ (p: Props) => useComponentState(p),
viewMapping,
);
diff --git a/packages/taler-wallet-webextension/src/wallet/DepositPage/state.ts b/packages/taler-wallet-webextension/src/wallet/DepositPage/state.ts
index bbf2c2771..5ad0841dc 100644
--- a/packages/taler-wallet-webextension/src/wallet/DepositPage/state.ts
+++ b/packages/taler-wallet-webextension/src/wallet/DepositPage/state.ts
@@ -21,18 +21,18 @@ import {
KnownBankAccountsInfo,
parsePaytoUri,
PaytoUri,
- stringifyPaytoUri,
+ stringifyPaytoUri
} from "@gnu-taler/taler-util";
import { WalletApiOperation } from "@gnu-taler/taler-wallet-core";
import { useState } from "preact/hooks";
+import { useBackendContext } from "../../context/backend.js";
import { useAsyncAsHook } from "../../hooks/useAsyncAsHook.js";
-import { wxApi } from "../../wxApi.js";
import { Props, State } from "./index.js";
export function useComponentState(
{ amount: amountStr, currency: currencyStr, onCancel, onSuccess }: Props,
- api: typeof wxApi,
): State {
+ const api = useBackendContext()
const parsed = amountStr === undefined ? undefined : Amounts.parse(amountStr);
const currency = parsed !== undefined ? parsed.currency : currencyStr;
@@ -55,8 +55,8 @@ export function useComponentState(
parsed !== undefined
? parsed
: currency !== undefined
- ? Amounts.zeroOfCurrency(currency)
- : undefined;
+ ? Amounts.zeroOfCurrency(currency)
+ : undefined;
// const [accountIdx, setAccountIdx] = useState<number>(0);
const [amount, setAmount] = useState<AmountJson>(initialValue ?? ({} as any));
const [selectedAccount, setSelectedAccount] = useState<PaytoUri>();
@@ -134,7 +134,7 @@ export function useComponentState(
const currentAccount = !selectedAccount ? firstAccount : selectedAccount;
if (fee === undefined) {
- getFeeForAmount(currentAccount, amount, api).then((initialFee) => {
+ getFeeForAmount(currentAccount, amount, api.wallet).then((initialFee) => {
setFee(initialFee);
});
return {
@@ -149,7 +149,7 @@ export function useComponentState(
const uri = !accountStr ? undefined : parsePaytoUri(accountStr);
if (uri) {
try {
- const result = await getFeeForAmount(uri, amount, api);
+ const result = await getFeeForAmount(uri, amount, api.wallet);
setSelectedAccount(uri);
setFee(result);
} catch (e) {
@@ -162,7 +162,7 @@ export function useComponentState(
async function updateAmount(newAmount: AmountJson): Promise<void> {
// const parsed = Amounts.parse(`${currency}:${numStr}`);
try {
- const result = await getFeeForAmount(currentAccount, newAmount, api);
+ const result = await getFeeForAmount(currentAccount, newAmount, api.wallet);
setAmount(newAmount);
setFee(result);
} catch (e) {
@@ -185,8 +185,8 @@ export function useComponentState(
const amountError = !isDirty
? undefined
: Amounts.cmp(balance, amount) === -1
- ? `Too much, your current balance is ${Amounts.stringifyValue(balance)}`
- : undefined;
+ ? `Too much, your current balance is ${Amounts.stringifyValue(balance)}`
+ : undefined;
const unableToDeposit =
Amounts.isZero(totalToDeposit) || //deposit may be zero because of fee
@@ -243,11 +243,11 @@ export function useComponentState(
async function getFeeForAmount(
p: PaytoUri,
a: AmountJson,
- api: typeof wxApi,
+ wallet: ReturnType<typeof useBackendContext>["wallet"],
): Promise<DepositGroupFees> {
const depositPaytoUri = `payto://${p.targetType}/${p.targetPath}`;
const amount = Amounts.stringify(a);
- return await api.wallet.call(WalletApiOperation.GetFeeForDeposit, {
+ return await wallet.call(WalletApiOperation.GetFeeForDeposit, {
amount,
depositPaytoUri,
});
diff --git a/packages/taler-wallet-webextension/src/wallet/DepositPage/test.ts b/packages/taler-wallet-webextension/src/wallet/DepositPage/test.ts
index 3f08c678c..90ac020b7 100644
--- a/packages/taler-wallet-webextension/src/wallet/DepositPage/test.ts
+++ b/packages/taler-wallet-webextension/src/wallet/DepositPage/test.ts
@@ -23,14 +23,13 @@ import {
Amounts,
DepositGroupFees,
parsePaytoUri,
- stringifyPaytoUri,
+ stringifyPaytoUri
} from "@gnu-taler/taler-util";
import { WalletApiOperation } from "@gnu-taler/taler-wallet-core";
import { expect } from "chai";
+import { tests } from "../../../../web-util/src/index.browser.js";
import {
- createWalletApiMock,
- mountHook,
- nullFunction,
+ createWalletApiMock, nullFunction
} from "../../test-utils.js";
import { useComponentState } from "./state.js";
@@ -50,7 +49,7 @@ const withSomeFee = (): DepositGroupFees => ({
describe("DepositPage states", () => {
it("should have status 'no-enough-balance' when balance is empty", async () => {
- const { handler, mock } = createWalletApiMock();
+ const { handler, TestingContext } = createWalletApiMock();
const props = { currency, onCancel: nullFunction, onSuccess: nullFunction };
handler.addWalletCallResponse(WalletApiOperation.GetBalances, undefined, {
@@ -72,27 +71,21 @@ describe("DepositPage states", () => {
},
);
- const { pullLastResultOrThrow, waitForStateUpdate, assertNoPendingUpdate } =
- mountHook(() => useComponentState(props, mock));
-
- {
- const { status } = pullLastResultOrThrow();
- expect(status).equal("loading");
- }
-
- expect(await waitForStateUpdate()).true;
-
- {
- const { status } = pullLastResultOrThrow();
- expect(status).equal("no-enough-balance");
- }
+ const hookBehavior = await tests.hookBehaveLikeThis(useComponentState, props, [
+ ({ status }) => {
+ expect(status).equal("loading");
+ },
+ ({ status }) => {
+ expect(status).equal("no-enough-balance");
+ },
+ ], TestingContext)
- await assertNoPendingUpdate();
+ expect(hookBehavior).deep.equal({ result: "ok" })
expect(handler.getCallingQueueState()).eq("empty");
});
it("should have status 'no-accounts' when balance is not empty and accounts is empty", async () => {
- const { handler, mock } = createWalletApiMock();
+ const { handler, TestingContext } = createWalletApiMock();
const props = { currency, onCancel: nullFunction, onSuccess: nullFunction };
handler.addWalletCallResponse(WalletApiOperation.GetBalances, undefined, {
@@ -113,22 +106,17 @@ describe("DepositPage states", () => {
accounts: [],
},
);
- const { pullLastResultOrThrow, waitForStateUpdate, assertNoPendingUpdate } =
- mountHook(() => useComponentState(props, mock));
-
- {
- const { status } = pullLastResultOrThrow();
- expect(status).equal("loading");
- }
-
- expect(await waitForStateUpdate()).true;
- {
- const r = pullLastResultOrThrow();
- if (r.status !== "no-accounts") expect.fail();
- // expect(r.cancelHandler.onClick).not.undefined;
- }
-
- await assertNoPendingUpdate();
+
+ const hookBehavior = await tests.hookBehaveLikeThis(useComponentState, props, [
+ ({ status }) => {
+ expect(status).equal("loading");
+ },
+ ({ status }) => {
+ expect(status).equal("no-accounts");
+ },
+ ], TestingContext)
+
+ expect(hookBehavior).deep.equal({ result: "ok" })
expect(handler.getCallingQueueState()).eq("empty");
});
@@ -146,7 +134,7 @@ describe("DepositPage states", () => {
};
it("should have status 'ready' but unable to deposit ", async () => {
- const { handler, mock } = createWalletApiMock();
+ const { handler, TestingContext } = createWalletApiMock();
const props = { currency, onCancel: nullFunction, onSuccess: nullFunction };
handler.addWalletCallResponse(WalletApiOperation.GetBalances, undefined, {
@@ -173,37 +161,29 @@ describe("DepositPage states", () => {
withoutFee(),
);
- const { pullLastResultOrThrow, waitForStateUpdate, assertNoPendingUpdate } =
- mountHook(() => useComponentState(props, mock));
-
- {
- const { status } = pullLastResultOrThrow();
- expect(status).equal("loading");
- }
-
- expect(await waitForStateUpdate()).true;
- {
- const { status } = pullLastResultOrThrow();
- expect(status).equal("loading");
- }
- expect(await waitForStateUpdate()).true;
-
- {
- const r = pullLastResultOrThrow();
- if (r.status !== "ready") expect.fail();
- expect(r.cancelHandler.onClick).not.undefined;
- expect(r.currency).eq(currency);
- expect(r.account.value).eq(stringifyPaytoUri(ibanPayto.uri));
- expect(r.amount.value).deep.eq(Amounts.parseOrThrow("EUR:0"));
- expect(r.depositHandler.onClick).undefined;
- }
-
- await assertNoPendingUpdate();
+ const hookBehavior = await tests.hookBehaveLikeThis(useComponentState, props, [
+ ({ status }) => {
+ expect(status).equal("loading");
+ },
+ ({ status }) => {
+ expect(status).equal("loading");
+ },
+ (state) => {
+ if (state.status !== "ready") expect.fail();
+ expect(state.cancelHandler.onClick).not.undefined;
+ expect(state.currency).eq(currency);
+ expect(state.account.value).eq(stringifyPaytoUri(ibanPayto.uri));
+ expect(state.amount.value).deep.eq(Amounts.parseOrThrow("EUR:0"));
+ expect(state.depositHandler.onClick).undefined;
+ },
+ ], TestingContext)
+
+ expect(hookBehavior).deep.equal({ result: "ok" })
expect(handler.getCallingQueueState()).eq("empty");
});
it("should not be able to deposit more than the balance ", async () => {
- const { handler, mock } = createWalletApiMock();
+ const { handler, TestingContext } = createWalletApiMock();
const props = { currency, onCancel: nullFunction, onSuccess: nullFunction };
handler.addWalletCallResponse(WalletApiOperation.GetBalances, undefined, {
@@ -235,134 +215,45 @@ describe("DepositPage states", () => {
undefined,
withoutFee(),
);
- handler.addWalletCallResponse(
- WalletApiOperation.GetFeeForDeposit,
- undefined,
- withoutFee(),
- );
- handler.addWalletCallResponse(
- WalletApiOperation.GetFeeForDeposit,
- undefined,
- withoutFee(),
- );
-
- const { pullLastResultOrThrow, waitForStateUpdate, assertNoPendingUpdate } =
- mountHook(() => useComponentState(props, mock));
-
- {
- const { status } = pullLastResultOrThrow();
- expect(status).equal("loading");
- }
- expect(await waitForStateUpdate()).true;
- {
- const { status } = pullLastResultOrThrow();
- expect(status).equal("loading");
- }
-
- expect(await waitForStateUpdate()).true;
const accountSelected = stringifyPaytoUri(ibanPayto.uri);
- {
- const r = pullLastResultOrThrow();
- if (r.status !== "ready") expect.fail();
- expect(r.cancelHandler.onClick).not.undefined;
- expect(r.currency).eq(currency);
- expect(r.account.value).eq(stringifyPaytoUri(talerBankPayto.uri));
- expect(r.amount.value).deep.eq(Amounts.parseOrThrow("EUR:0"));
- expect(r.depositHandler.onClick).undefined;
- expect(r.totalFee).deep.eq(Amounts.parseOrThrow(`${currency}:0`));
- expect(r.account.onChange).not.undefined;
-
- r.account.onChange!(accountSelected);
- }
-
- expect(await waitForStateUpdate()).true;
-
- {
- const r = pullLastResultOrThrow();
- if (r.status !== "ready") expect.fail();
- expect(r.cancelHandler.onClick).not.undefined;
- expect(r.currency).eq(currency);
- expect(r.account.value).eq(accountSelected);
- expect(r.amount.value).deep.eq(Amounts.parseOrThrow("EUR:0"));
- expect(r.totalFee).deep.eq(Amounts.parseOrThrow(`${currency}:0`));
- expect(r.depositHandler.onClick).undefined;
- }
-
- await assertNoPendingUpdate();
- });
+ const hookBehavior = await tests.hookBehaveLikeThis(useComponentState, props, [
+ ({ status }) => {
+ expect(status).equal("loading");
+ },
+ ({ status }) => {
+ expect(status).equal("loading");
+ },
+ (state) => {
+ if (state.status !== "ready") expect.fail();
+ expect(state.cancelHandler.onClick).not.undefined;
+ expect(state.currency).eq(currency);
+ expect(state.account.value).eq(stringifyPaytoUri(talerBankPayto.uri));
+ expect(state.amount.value).deep.eq(Amounts.parseOrThrow("EUR:0"));
+ expect(state.depositHandler.onClick).undefined;
+ expect(state.totalFee).deep.eq(Amounts.parseOrThrow(`${currency}:0`));
+ expect(state.account.onChange).not.undefined;
+
+ state.account.onChange!(accountSelected);
+ },
+ (state) => {
+ if (state.status !== "ready") expect.fail();
+ expect(state.cancelHandler.onClick).not.undefined;
+ expect(state.currency).eq(currency);
+ expect(state.account.value).eq(accountSelected);
+ expect(state.amount.value).deep.eq(Amounts.parseOrThrow("EUR:0"));
+ expect(state.totalFee).deep.eq(Amounts.parseOrThrow(`${currency}:0`));
+ expect(state.depositHandler.onClick).undefined;
+ },
+ ], TestingContext)
- // it("should calculate the fee upon entering amount ", async () => {
- // const { pullLastResultOrThrow, waitForStateUpdate, assertNoPendingUpdate } =
- // mountHook(() =>
- // useComponentState(
- // { currency, onCancel: nullFunction, onSuccess: nullFunction },
- // {
- // getBalance: async () =>
- // ({
- // balances: [{ available: `${currency}:1` }],
- // } as Partial<BalancesResponse>),
- // listKnownBankAccounts: async () => ({ accounts: [ibanPayto] }),
- // getFeeForDeposit: withSomeFee,
- // } as Partial<typeof wxApi> as any,
- // ),
- // );
-
- // {
- // const { status } = getLastResultOrThrow();
- // expect(status).equal("loading");
- // }
-
- // await waitNextUpdate();
-
- // {
- // const r = getLastResultOrThrow();
- // if (r.status !== "ready") expect.fail();
- // expect(r.cancelHandler.onClick).not.undefined;
- // expect(r.currency).eq(currency);
- // expect(r.account.value).eq(accountSelected);
- // expect(r.amount.value).eq("0");
- // expect(r.depositHandler.onClick).undefined;
- // expect(r.totalFee).deep.eq(Amounts.parseOrThrow(`${currency}:0`));
-
- // r.amount.onInput("10");
- // }
-
- // expect(await waitForStateUpdate()).true;
-
- // {
- // const r = pullLastResultOrThrow();
- // if (r.status !== "ready") expect.fail();
- // expect(r.cancelHandler.onClick).not.undefined;
- // expect(r.currency).eq(currency);
- // expect(r.account.value).eq(accountSelected);
- // expect(r.amount.value).eq("10");
- // expect(r.totalFee).deep.eq(Amounts.parseOrThrow(`${currency}:0`));
- // expect(r.depositHandler.onClick).undefined;
-
- // r.amount.onInput("3");
- // }
-
- // expect(await waitForStateUpdate()).true;
-
- // {
- // const r = pullLastResultOrThrow();
- // if (r.status !== "ready") expect.fail();
- // expect(r.cancelHandler.onClick).not.undefined;
- // expect(r.currency).eq(currency);
- // expect(r.account.value).eq(accountSelected);
- // expect(r.amount.value).eq("3");
- // expect(r.totalFee).deep.eq(Amounts.parseOrThrow(`${currency}:0`));
- // expect(r.depositHandler.onClick).not.undefined;
- // }
-
- // await assertNoPendingUpdate();
- // expect(handler.getCallingQueueState()).eq("empty")
- // });
+ expect(hookBehavior).deep.equal({ result: "ok" })
+ expect(handler.getCallingQueueState()).eq("empty");
+ });
it("should calculate the fee upon entering amount ", async () => {
- const { handler, mock } = createWalletApiMock();
+ const { handler, TestingContext } = createWalletApiMock();
const props = { currency, onCancel: nullFunction, onSuccess: nullFunction };
handler.addWalletCallResponse(WalletApiOperation.GetBalances, undefined, {
@@ -399,70 +290,54 @@ describe("DepositPage states", () => {
withSomeFee(),
);
- const { pullLastResultOrThrow, waitForStateUpdate, assertNoPendingUpdate } =
- mountHook(() => useComponentState(props, mock));
-
- {
- const { status } = pullLastResultOrThrow();
- expect(status).equal("loading");
- }
-
- expect(await waitForStateUpdate()).true;
-
- {
- const { status } = pullLastResultOrThrow();
- expect(status).equal("loading");
- }
-
- expect(await waitForStateUpdate()).true;
const accountSelected = stringifyPaytoUri(ibanPayto.uri);
- {
- const r = pullLastResultOrThrow();
- if (r.status !== "ready") expect.fail();
- expect(r.cancelHandler.onClick).not.undefined;
- expect(r.currency).eq(currency);
- expect(r.account.value).eq(stringifyPaytoUri(talerBankPayto.uri));
- expect(r.amount.value).deep.eq(Amounts.parseOrThrow("EUR:0"));
- expect(r.depositHandler.onClick).undefined;
- expect(r.totalFee).deep.eq(Amounts.parseOrThrow(`${currency}:0`));
- expect(r.account.onChange).not.undefined;
-
- r.account.onChange!(accountSelected);
- }
-
- expect(await waitForStateUpdate()).true;
-
- {
- const r = pullLastResultOrThrow();
- if (r.status !== "ready") expect.fail();
- expect(r.cancelHandler.onClick).not.undefined;
- expect(r.currency).eq(currency);
- expect(r.account.value).eq(accountSelected);
- expect(r.amount.value).deep.eq(Amounts.parseOrThrow("EUR:0"));
- expect(r.depositHandler.onClick).undefined;
- expect(r.totalFee).deep.eq(Amounts.parseOrThrow(`${currency}:3`));
-
- expect(r.amount.onInput).not.undefined;
- if (!r.amount.onInput) return;
- r.amount.onInput(Amounts.parseOrThrow("EUR:10"));
- }
-
- expect(await waitForStateUpdate()).true;
-
- {
- const r = pullLastResultOrThrow();
- if (r.status !== "ready") expect.fail();
- expect(r.cancelHandler.onClick).not.undefined;
- expect(r.currency).eq(currency);
- expect(r.account.value).eq(accountSelected);
- expect(r.amount.value).deep.eq(Amounts.parseOrThrow("EUR:10"));
- expect(r.totalFee).deep.eq(Amounts.parseOrThrow(`${currency}:3`));
- expect(r.totalToDeposit).deep.eq(Amounts.parseOrThrow(`${currency}:7`));
- expect(r.depositHandler.onClick).not.undefined;
- }
-
- await assertNoPendingUpdate();
+ const hookBehavior = await tests.hookBehaveLikeThis(useComponentState, props, [
+ ({ status }) => {
+ expect(status).equal("loading");
+ },
+ ({ status }) => {
+ expect(status).equal("loading");
+ },
+ (state) => {
+ if (state.status !== "ready") expect.fail();
+ expect(state.cancelHandler.onClick).not.undefined;
+ expect(state.currency).eq(currency);
+ expect(state.account.value).eq(stringifyPaytoUri(talerBankPayto.uri));
+ expect(state.amount.value).deep.eq(Amounts.parseOrThrow("EUR:0"));
+ expect(state.depositHandler.onClick).undefined;
+ expect(state.totalFee).deep.eq(Amounts.parseOrThrow(`${currency}:0`));
+ expect(state.account.onChange).not.undefined;
+
+ state.account.onChange!(accountSelected);
+ },
+ (state) => {
+ if (state.status !== "ready") expect.fail();
+ expect(state.cancelHandler.onClick).not.undefined;
+ expect(state.currency).eq(currency);
+ expect(state.account.value).eq(accountSelected);
+ expect(state.amount.value).deep.eq(Amounts.parseOrThrow("EUR:0"));
+ expect(state.depositHandler.onClick).undefined;
+ expect(state.totalFee).deep.eq(Amounts.parseOrThrow(`${currency}:3`));
+
+ expect(state.amount.onInput).not.undefined;
+ if (!state.amount.onInput) return;
+ state.amount.onInput(Amounts.parseOrThrow("EUR:10"));
+ },
+ (state) => {
+ if (state.status !== "ready") expect.fail();
+ expect(state.cancelHandler.onClick).not.undefined;
+ expect(state.currency).eq(currency);
+ expect(state.account.value).eq(accountSelected);
+ expect(state.amount.value).deep.eq(Amounts.parseOrThrow("EUR:10"));
+ expect(state.totalFee).deep.eq(Amounts.parseOrThrow(`${currency}:3`));
+ expect(state.totalToDeposit).deep.eq(Amounts.parseOrThrow(`${currency}:7`));
+ expect(state.depositHandler.onClick).not.undefined;
+ },
+ ], TestingContext)
+
+ expect(hookBehavior).deep.equal({ result: "ok" })
expect(handler.getCallingQueueState()).eq("empty");
+
});
});
diff --git a/packages/taler-wallet-webextension/src/wallet/DestinationSelection/index.ts b/packages/taler-wallet-webextension/src/wallet/DestinationSelection/index.ts
index 2f066d744..f1e766a18 100644
--- a/packages/taler-wallet-webextension/src/wallet/DestinationSelection/index.ts
+++ b/packages/taler-wallet-webextension/src/wallet/DestinationSelection/index.ts
@@ -18,7 +18,6 @@ import { Loading } from "../../components/Loading.js";
import { HookError } from "../../hooks/useAsyncAsHook.js";
import { AmountFieldHandler, ButtonHandler } from "../../mui/handlers.js";
import { compose, StateViewMap } from "../../utils/index.js";
-import { wxApi } from "../../wxApi.js";
import { useComponentState } from "./state.js";
import { LoadingUriView, ReadyView, SelectCurrencyView } from "./views.js";
@@ -88,6 +87,6 @@ const viewMapping: StateViewMap<State> = {
export const DestinationSelectionPage = compose(
"DestinationSelectionPage",
- (p: Props) => useComponentState(p, wxApi),
+ (p: Props) => useComponentState(p),
viewMapping,
);
diff --git a/packages/taler-wallet-webextension/src/wallet/DestinationSelection/state.ts b/packages/taler-wallet-webextension/src/wallet/DestinationSelection/state.ts
index a67f926bc..0621d3304 100644
--- a/packages/taler-wallet-webextension/src/wallet/DestinationSelection/state.ts
+++ b/packages/taler-wallet-webextension/src/wallet/DestinationSelection/state.ts
@@ -17,15 +17,15 @@
import { Amounts } from "@gnu-taler/taler-util";
import { WalletApiOperation } from "@gnu-taler/taler-wallet-core";
import { useState } from "preact/hooks";
+import { useBackendContext } from "../../context/backend.js";
import { useAsyncAsHook } from "../../hooks/useAsyncAsHook.js";
import { assertUnreachable, RecursiveState } from "../../utils/index.js";
-import { wxApi } from "../../wxApi.js";
import { Contact, Props, State } from "./index.js";
export function useComponentState(
props: Props,
- api: typeof wxApi,
): RecursiveState<State> {
+ const api = useBackendContext()
const parsedInitialAmount = !props.amount
? undefined
: Amounts.parse(props.amount);
diff --git a/packages/taler-wallet-webextension/src/wallet/DestinationSelection/test.ts b/packages/taler-wallet-webextension/src/wallet/DestinationSelection/test.ts
index c2aa04849..afba5db35 100644
--- a/packages/taler-wallet-webextension/src/wallet/DestinationSelection/test.ts
+++ b/packages/taler-wallet-webextension/src/wallet/DestinationSelection/test.ts
@@ -23,11 +23,12 @@ import {
Amounts,
ExchangeEntryStatus,
ExchangeListItem,
- ExchangeTosStatus,
+ ExchangeTosStatus
} from "@gnu-taler/taler-util";
import { WalletApiOperation } from "@gnu-taler/taler-wallet-core";
import { expect } from "chai";
-import { createWalletApiMock, mountHook } from "../../test-utils.js";
+import { tests } from "../../../../web-util/src/index.browser.js";
+import { createWalletApiMock, nullFunction } from "../../test-utils.js";
import { useComponentState } from "./state.js";
const exchangeArs: ExchangeListItem = {
@@ -42,7 +43,7 @@ const exchangeArs: ExchangeListItem = {
describe("Destination selection states", () => {
it("should select currency if no amount specified", async () => {
- const { handler, mock } = createWalletApiMock();
+ const { handler, TestingContext } = createWalletApiMock();
handler.addWalletCallResponse(
WalletApiOperation.ListExchanges,
@@ -54,83 +55,65 @@ describe("Destination selection states", () => {
const props = {
type: "get" as const,
- goToWalletManualWithdraw: () => {
- return null;
- },
- goToWalletWalletInvoice: () => {
- null;
- },
+ goToWalletManualWithdraw: nullFunction,
+ goToWalletWalletInvoice: nullFunction,
};
- const { pullLastResultOrThrow, waitForStateUpdate, assertNoPendingUpdate } =
- mountHook(() => useComponentState(props, mock));
-
- {
- const state = pullLastResultOrThrow();
-
- if (state.status !== "loading") expect.fail();
- if (state.error) expect.fail();
- }
-
- expect(await waitForStateUpdate()).true;
-
- {
- const state = pullLastResultOrThrow();
-
- if (state.status !== "select-currency") expect.fail();
- if (state.error) expect.fail();
- expect(state.currencies).deep.eq({
- ARS: "ARS",
- "": "Select a currency",
- });
-
- state.onCurrencySelected(exchangeArs.currency!);
- }
-
- expect(await waitForStateUpdate()).true;
-
- {
- const state = pullLastResultOrThrow();
- if (state.status !== "ready") expect.fail();
- if (state.error) expect.fail();
- expect(state.goToBank.onClick).eq(undefined);
- expect(state.goToWallet.onClick).eq(undefined);
+ const hookBehavior = await tests.hookBehaveLikeThis(useComponentState, props, [
+ ({ status }) => {
+ expect(status).equal("loading");
+ },
+ (state) => {
+ if (state.status !== "select-currency") expect.fail();
+ if (state.error) expect.fail();
+ expect(state.currencies).deep.eq({
+ ARS: "ARS",
+ "": "Select a currency",
+ });
+
+ state.onCurrencySelected(exchangeArs.currency!);
+ },
+ (state) => {
+ if (state.status !== "ready") expect.fail();
+ if (state.error) expect.fail();
+ expect(state.goToBank.onClick).eq(undefined);
+ expect(state.goToWallet.onClick).eq(undefined);
- expect(state.amountHandler.value).deep.eq(Amounts.parseOrThrow("ARS:0"));
- }
+ expect(state.amountHandler.value).deep.eq(Amounts.parseOrThrow("ARS:0"));
+ },
+ ], TestingContext)
- await assertNoPendingUpdate();
+ expect(hookBehavior).deep.equal({ result: "ok" })
expect(handler.getCallingQueueState()).eq("empty");
+
});
it("should be possible to start with an amount specified in request params", async () => {
- const { handler, mock } = createWalletApiMock();
+ const { handler, TestingContext } = createWalletApiMock();
const props = {
type: "get" as const,
- goToWalletManualWithdraw: () => {
- return null;
- },
- goToWalletWalletInvoice: () => {
- null;
- },
+ goToWalletManualWithdraw: nullFunction,
+ goToWalletWalletInvoice: nullFunction,
amount: "ARS:2",
};
- const { pullLastResultOrThrow, waitForStateUpdate, assertNoPendingUpdate } =
- mountHook(() => useComponentState(props, mock));
-
- {
- const state = pullLastResultOrThrow();
-
- if (state.status !== "ready") expect.fail();
- if (state.error) expect.fail();
- expect(state.goToBank.onClick).not.eq(undefined);
- expect(state.goToWallet.onClick).not.eq(undefined);
- expect(state.amountHandler.value).deep.eq(Amounts.parseOrThrow("ARS:2"));
- }
+ const hookBehavior = await tests.hookBehaveLikeThis(useComponentState, props, [
+ // ({ status }) => {
+ // expect(status).equal("loading");
+ // },
+ (state) => {
+ if (state.status !== "ready") expect.fail();
+ if (state.error) expect.fail();
+ expect(state.goToBank.onClick).not.eq(undefined);
+ expect(state.goToWallet.onClick).not.eq(undefined);
+
+ expect(state.amountHandler.value).deep.eq(Amounts.parseOrThrow("ARS:2"));
+ },
+ ], TestingContext)
- await assertNoPendingUpdate();
+ expect(hookBehavior).deep.equal({ result: "ok" })
expect(handler.getCallingQueueState()).eq("empty");
+
});
});
diff --git a/packages/taler-wallet-webextension/src/wallet/DeveloperPage.tsx b/packages/taler-wallet-webextension/src/wallet/DeveloperPage.tsx
index 2333fd3c1..c42798c8f 100644
--- a/packages/taler-wallet-webextension/src/wallet/DeveloperPage.tsx
+++ b/packages/taler-wallet-webextension/src/wallet/DeveloperPage.tsx
@@ -31,12 +31,12 @@ import { useEffect, useRef, useState } from "preact/hooks";
import { Diagnostics } from "../components/Diagnostics.js";
import { NotifyUpdateFadeOut } from "../components/styled/index.js";
import { Time } from "../components/Time.js";
+import { useBackendContext } from "../context/backend.js";
import { useTranslationContext } from "../context/translation.js";
import { useAsyncAsHook } from "../hooks/useAsyncAsHook.js";
import { useDiagnostics } from "../hooks/useDiagnostics.js";
import { Button } from "../mui/Button.js";
import { Grid } from "../mui/Grid.js";
-import { wxApi } from "../wxApi.js";
export function DeveloperPage(): VNode {
const [status, timedOut] = useDiagnostics();
@@ -45,13 +45,15 @@ export function DeveloperPage(): VNode {
//FIXME: waiting for retry notification make a always increasing loop of notifications
listenAllEvents.includes = (e) => e !== "waiting-for-retry"; // includes every event
+ const api = useBackendContext();
+
const response = useAsyncAsHook(async () => {
- const op = await wxApi.wallet.call(
+ const op = await api.wallet.call(
WalletApiOperation.GetPendingOperations,
{},
);
- const c = await wxApi.wallet.call(WalletApiOperation.DumpCoins, {});
- const ex = await wxApi.wallet.call(WalletApiOperation.ListExchanges, {});
+ const c = await api.wallet.call(WalletApiOperation.DumpCoins, {});
+ const ex = await api.wallet.call(WalletApiOperation.ListExchanges, {});
return {
operations: op.pendingOperations,
coins: c.coins,
@@ -60,10 +62,7 @@ export function DeveloperPage(): VNode {
});
useEffect(() => {
- return wxApi.listener.onUpdateNotification(
- listenAllEvents,
- response?.retry,
- );
+ return api.listener.onUpdateNotification(listenAllEvents, response?.retry);
});
const nonResponse = { operations: [], coins: [], exchanges: [] };
@@ -82,7 +81,7 @@ export function DeveloperPage(): VNode {
coins={coins}
exchanges={exchanges}
onDownloadDatabase={async () => {
- const db = await wxApi.wallet.call(WalletApiOperation.ExportDb, {});
+ const db = await api.wallet.call(WalletApiOperation.ExportDb, {});
return JSON.stringify(db);
}}
/>
@@ -135,9 +134,10 @@ export function View({
content,
});
}
+ const api = useBackendContext();
const fileRef = useRef<HTMLInputElement>(null);
async function onImportDatabase(str: string): Promise<void> {
- return wxApi.wallet.call(WalletApiOperation.ImportDb, {
+ return api.wallet.call(WalletApiOperation.ImportDb, {
dump: JSON.parse(str),
});
}
@@ -177,7 +177,7 @@ export function View({
onClick={() =>
confirmReset(
i18n.str`Do you want to IRREVOCABLY DESTROY everything inside your wallet and LOSE ALL YOUR COINS?`,
- () => wxApi.background.resetDb(),
+ () => api.background.resetDb(),
)
}
>
@@ -190,7 +190,7 @@ export function View({
onClick={() =>
confirmReset(
i18n.str`TESTING: This may delete all your coin, proceed with caution`,
- () => wxApi.background.runGarbageCollector(),
+ () => api.background.runGarbageCollector(),
)
}
>
diff --git a/packages/taler-wallet-webextension/src/wallet/EmptyComponentExample/index.ts b/packages/taler-wallet-webextension/src/wallet/EmptyComponentExample/index.ts
index 4b7725264..95badb218 100644
--- a/packages/taler-wallet-webextension/src/wallet/EmptyComponentExample/index.ts
+++ b/packages/taler-wallet-webextension/src/wallet/EmptyComponentExample/index.ts
@@ -17,7 +17,6 @@
import { Loading } from "../../components/Loading.js";
import { HookError } from "../../hooks/useAsyncAsHook.js";
import { compose, StateViewMap } from "../../utils/index.js";
-import { wxApi } from "../../wxApi.js";
import { useComponentState } from "./state.js";
import { LoadingUriView, ReadyView } from "./views.js";
@@ -55,6 +54,6 @@ const viewMapping: StateViewMap<State> = {
export const ComponentName = compose(
"ComponentName",
- (p: Props) => useComponentState(p, wxApi),
+ (p: Props) => useComponentState(p),
viewMapping,
);
diff --git a/packages/taler-wallet-webextension/src/wallet/EmptyComponentExample/state.ts b/packages/taler-wallet-webextension/src/wallet/EmptyComponentExample/state.ts
index d194b3f97..31a351579 100644
--- a/packages/taler-wallet-webextension/src/wallet/EmptyComponentExample/state.ts
+++ b/packages/taler-wallet-webextension/src/wallet/EmptyComponentExample/state.ts
@@ -14,10 +14,9 @@
GNU Taler; see the file COPYING. If not, see <http://www.gnu.org/licenses/>
*/
-import { wxApi } from "../../wxApi.js";
import { Props, State } from "./index.js";
-export function useComponentState({ p }: Props, api: typeof wxApi): State {
+export function useComponentState({ p }: Props): State {
return {
status: "ready",
error: undefined,
diff --git a/packages/taler-wallet-webextension/src/wallet/ExchangeAddPage.tsx b/packages/taler-wallet-webextension/src/wallet/ExchangeAddPage.tsx
index a0c62787a..d8a7c6090 100644
--- a/packages/taler-wallet-webextension/src/wallet/ExchangeAddPage.tsx
+++ b/packages/taler-wallet-webextension/src/wallet/ExchangeAddPage.tsx
@@ -21,9 +21,9 @@ import {
import { WalletApiOperation } from "@gnu-taler/taler-wallet-core";
import { h, VNode } from "preact";
import { useState } from "preact/hooks";
+import { useBackendContext } from "../context/backend.js";
import { useAsyncAsHook } from "../hooks/useAsyncAsHook.js";
import { queryToSlashKeys } from "../utils/index.js";
-import { wxApi } from "../wxApi.js";
import { ExchangeAddConfirmPage } from "./ExchangeAddConfirm.js";
import { ExchangeSetUrlPage } from "./ExchangeSetUrl.js";
@@ -37,8 +37,9 @@ export function ExchangeAddPage({ currency, onBack }: Props): VNode {
{ url: string; config: TalerConfigResponse } | undefined
>(undefined);
+ const api = useBackendContext();
const knownExchangesResponse = useAsyncAsHook(() =>
- wxApi.wallet.call(WalletApiOperation.ListExchanges, {}),
+ api.wallet.call(WalletApiOperation.ListExchanges, {}),
);
const knownExchanges = !knownExchangesResponse
? []
@@ -75,7 +76,7 @@ export function ExchangeAddPage({ currency, onBack }: Props): VNode {
url={verifying.url}
onCancel={onBack}
onConfirm={async () => {
- await wxApi.wallet.call(WalletApiOperation.AddExchange, {
+ await api.wallet.call(WalletApiOperation.AddExchange, {
exchangeBaseUrl: canonicalizeBaseUrl(verifying.url),
forceUpdate: true,
});
diff --git a/packages/taler-wallet-webextension/src/wallet/ExchangeSelection/index.ts b/packages/taler-wallet-webextension/src/wallet/ExchangeSelection/index.ts
index a95830f8e..661fa5286 100644
--- a/packages/taler-wallet-webextension/src/wallet/ExchangeSelection/index.ts
+++ b/packages/taler-wallet-webextension/src/wallet/ExchangeSelection/index.ts
@@ -18,14 +18,13 @@ import {
DenomOperationMap,
ExchangeFullDetails,
ExchangeListItem,
- FeeDescriptionPair,
+ FeeDescriptionPair
} from "@gnu-taler/taler-util";
import { Loading } from "../../components/Loading.js";
import { HookError } from "../../hooks/useAsyncAsHook.js";
import { State as SelectExchangeState } from "../../hooks/useSelectedExchange.js";
import { ButtonHandler, SelectFieldHandler } from "../../mui/handlers.js";
import { compose, StateViewMap } from "../../utils/index.js";
-import { wxApi } from "../../wxApi.js";
import { useComponentState } from "./state.js";
import {
ComparingView,
@@ -33,7 +32,7 @@ import {
NoExchangesView,
PrivacyContentView,
ReadyView,
- TosContentView,
+ TosContentView
} from "./views.js";
export interface Props {
@@ -106,6 +105,6 @@ const viewMapping: StateViewMap<State> = {
export const ExchangeSelectionPage = compose(
"ExchangeSelectionPage",
- (p: Props) => useComponentState(p, wxApi),
+ (p: Props) => useComponentState(p),
viewMapping,
);
diff --git a/packages/taler-wallet-webextension/src/wallet/ExchangeSelection/state.ts b/packages/taler-wallet-webextension/src/wallet/ExchangeSelection/state.ts
index 63d545b97..585050413 100644
--- a/packages/taler-wallet-webextension/src/wallet/ExchangeSelection/state.ts
+++ b/packages/taler-wallet-webextension/src/wallet/ExchangeSelection/state.ts
@@ -17,17 +17,17 @@
import { DenomOperationMap, FeeDescription } from "@gnu-taler/taler-util";
import {
createPairTimeline,
- WalletApiOperation,
+ WalletApiOperation
} from "@gnu-taler/taler-wallet-core";
import { useState } from "preact/hooks";
+import { useBackendContext } from "../../context/backend.js";
import { useAsyncAsHook } from "../../hooks/useAsyncAsHook.js";
-import { wxApi } from "../../wxApi.js";
import { Props, State } from "./index.js";
export function useComponentState(
{ onCancel, onSelection, list: exchanges, currentExchange }: Props,
- api: typeof wxApi,
): State {
+ const api = useBackendContext()
const initialValue = exchanges.findIndex(
(e) => e.exchangeBaseUrl === currentExchange,
);
@@ -52,14 +52,14 @@ export function useComponentState(
const selected = !selectedExchange
? undefined
: await api.wallet.call(WalletApiOperation.GetExchangeDetailedInfo, {
- exchangeBaseUrl: selectedExchange.exchangeBaseUrl,
- });
+ exchangeBaseUrl: selectedExchange.exchangeBaseUrl,
+ });
const original = !initialExchange
? undefined
: await api.wallet.call(WalletApiOperation.GetExchangeDetailedInfo, {
- exchangeBaseUrl: initialExchange.exchangeBaseUrl,
- });
+ exchangeBaseUrl: initialExchange.exchangeBaseUrl,
+ });
return {
exchanges,
diff --git a/packages/taler-wallet-webextension/src/wallet/History.tsx b/packages/taler-wallet-webextension/src/wallet/History.tsx
index 4b9c5c711..50f634f52 100644
--- a/packages/taler-wallet-webextension/src/wallet/History.tsx
+++ b/packages/taler-wallet-webextension/src/wallet/History.tsx
@@ -33,13 +33,13 @@ import {
} from "../components/styled/index.js";
import { Time } from "../components/Time.js";
import { TransactionItem } from "../components/TransactionItem.js";
+import { useBackendContext } from "../context/backend.js";
import { useTranslationContext } from "../context/translation.js";
import { useAsyncAsHook } from "../hooks/useAsyncAsHook.js";
import { Button } from "../mui/Button.js";
import { NoBalanceHelp } from "../popup/NoBalanceHelp.js";
import DownloadIcon from "../svg/download_24px.svg";
import UploadIcon from "../svg/upload_24px.svg";
-import { wxApi } from "../wxApi.js";
interface Props {
currency?: string;
@@ -52,13 +52,14 @@ export function HistoryPage({
goToWalletDeposit,
}: Props): VNode {
const { i18n } = useTranslationContext();
+ const api = useBackendContext();
const state = useAsyncAsHook(async () => ({
- b: await wxApi.wallet.call(WalletApiOperation.GetBalances, {}),
- tx: await wxApi.wallet.call(WalletApiOperation.GetTransactions, {}),
+ b: await api.wallet.call(WalletApiOperation.GetBalances, {}),
+ tx: await api.wallet.call(WalletApiOperation.GetTransactions, {}),
}));
useEffect(() => {
- return wxApi.listener.onUpdateNotification(
+ return api.listener.onUpdateNotification(
[NotificationType.WithdrawGroupFinished],
state?.retry,
);
diff --git a/packages/taler-wallet-webextension/src/wallet/ManageAccount/index.ts b/packages/taler-wallet-webextension/src/wallet/ManageAccount/index.ts
index df4e7586f..0ee6472d6 100644
--- a/packages/taler-wallet-webextension/src/wallet/ManageAccount/index.ts
+++ b/packages/taler-wallet-webextension/src/wallet/ManageAccount/index.ts
@@ -20,10 +20,9 @@ import { HookError } from "../../hooks/useAsyncAsHook.js";
import {
ButtonHandler,
SelectFieldHandler,
- TextFieldHandler,
+ TextFieldHandler
} from "../../mui/handlers.js";
import { compose, StateViewMap } from "../../utils/index.js";
-import { wxApi } from "../../wxApi.js";
import { useComponentState } from "./state.js";
import { LoadingUriView, ReadyView } from "./views.js";
@@ -75,6 +74,6 @@ const viewMapping: StateViewMap<State> = {
export const ManageAccountPage = compose(
"ManageAccountPage",
- (p: Props) => useComponentState(p, wxApi),
+ (p: Props) => useComponentState(p),
viewMapping,
);
diff --git a/packages/taler-wallet-webextension/src/wallet/ManageAccount/state.ts b/packages/taler-wallet-webextension/src/wallet/ManageAccount/state.ts
index 1f920f05f..d60ef962b 100644
--- a/packages/taler-wallet-webextension/src/wallet/ManageAccount/state.ts
+++ b/packages/taler-wallet-webextension/src/wallet/ManageAccount/state.ts
@@ -17,18 +17,18 @@
import {
KnownBankAccountsInfo,
parsePaytoUri,
- stringifyPaytoUri,
+ stringifyPaytoUri
} from "@gnu-taler/taler-util";
import { WalletApiOperation } from "@gnu-taler/taler-wallet-core";
import { useState } from "preact/hooks";
+import { useBackendContext } from "../../context/backend.js";
import { useAsyncAsHook } from "../../hooks/useAsyncAsHook.js";
-import { wxApi } from "../../wxApi.js";
import { AccountByType, Props, State } from "./index.js";
export function useComponentState(
{ currency, onAccountAdded, onCancel }: Props,
- api: typeof wxApi,
): State {
+ const api = useBackendContext()
const hook = useAsyncAsHook(() =>
api.wallet.call(WalletApiOperation.ListKnownBankAccounts, { currency }),
);
diff --git a/packages/taler-wallet-webextension/src/wallet/Notifications/index.ts b/packages/taler-wallet-webextension/src/wallet/Notifications/index.ts
index 253a0e629..3791b8967 100644
--- a/packages/taler-wallet-webextension/src/wallet/Notifications/index.ts
+++ b/packages/taler-wallet-webextension/src/wallet/Notifications/index.ts
@@ -18,11 +18,10 @@ import { UserAttentionUnreadList } from "@gnu-taler/taler-util";
import { Loading } from "../../components/Loading.js";
import { HookError } from "../../hooks/useAsyncAsHook.js";
import { compose, StateViewMap } from "../../utils/index.js";
-import { wxApi } from "../../wxApi.js";
import { useComponentState } from "./state.js";
import { LoadingUriView, ReadyView } from "./views.js";
-export interface Props {}
+export type Props = object
export type State = State.Loading | State.LoadingUriError | State.Ready;
@@ -56,6 +55,6 @@ const viewMapping: StateViewMap<State> = {
export const NotificationsPage = compose(
"NotificationsPage",
- (p: Props) => useComponentState(p, wxApi),
+ (p: Props) => useComponentState(p),
viewMapping,
);
diff --git a/packages/taler-wallet-webextension/src/wallet/Notifications/state.ts b/packages/taler-wallet-webextension/src/wallet/Notifications/state.ts
index 093722cf0..1042dea9f 100644
--- a/packages/taler-wallet-webextension/src/wallet/Notifications/state.ts
+++ b/packages/taler-wallet-webextension/src/wallet/Notifications/state.ts
@@ -15,11 +15,12 @@
*/
import { WalletApiOperation } from "@gnu-taler/taler-wallet-core";
+import { useBackendContext } from "../../context/backend.js";
import { useAsyncAsHook } from "../../hooks/useAsyncAsHook.js";
-import { wxApi } from "../../wxApi.js";
import { Props, State } from "./index.js";
-export function useComponentState({}: Props, api: typeof wxApi): State {
+export function useComponentState(p: Props): State {
+ const api = useBackendContext()
const hook = useAsyncAsHook(async () => {
return await api.wallet.call(
WalletApiOperation.GetUserAttentionRequests,
diff --git a/packages/taler-wallet-webextension/src/wallet/ProviderAddPage.tsx b/packages/taler-wallet-webextension/src/wallet/ProviderAddPage.tsx
index d5f072828..eb86c9a3f 100644
--- a/packages/taler-wallet-webextension/src/wallet/ProviderAddPage.tsx
+++ b/packages/taler-wallet-webextension/src/wallet/ProviderAddPage.tsx
@@ -31,10 +31,10 @@ import {
SubTitle,
Title,
} from "../components/styled/index.js";
+import { useBackendContext } from "../context/backend.js";
import { useTranslationContext } from "../context/translation.js";
import { Button } from "../mui/Button.js";
import { queryToSlashConfig } from "../utils/index.js";
-import { wxApi } from "../wxApi.js";
interface Props {
currency: string;
@@ -46,7 +46,7 @@ export function ProviderAddPage({ onBack }: Props): VNode {
| { url: string; name: string; provider: BackupBackupProviderTerms }
| undefined
>(undefined);
-
+ const api = useBackendContext();
if (!verifying) {
return (
<SetUrlView
@@ -70,7 +70,7 @@ export function ProviderAddPage({ onBack }: Props): VNode {
setVerifying(undefined);
}}
onConfirm={() => {
- return wxApi.wallet
+ return api.wallet
.call(WalletApiOperation.AddBackupProvider, {
backupProviderBaseUrl: verifying.url,
name: verifying.name,
diff --git a/packages/taler-wallet-webextension/src/wallet/ProviderDetailPage.tsx b/packages/taler-wallet-webextension/src/wallet/ProviderDetailPage.tsx
index 6dde30b39..46d54e871 100644
--- a/packages/taler-wallet-webextension/src/wallet/ProviderDetailPage.tsx
+++ b/packages/taler-wallet-webextension/src/wallet/ProviderDetailPage.tsx
@@ -28,10 +28,10 @@ import { Loading } from "../components/Loading.js";
import { LoadingError } from "../components/LoadingError.js";
import { PaymentStatus, SmallLightText } from "../components/styled/index.js";
import { Time } from "../components/Time.js";
+import { useBackendContext } from "../context/backend.js";
import { useTranslationContext } from "../context/translation.js";
import { useAsyncAsHook } from "../hooks/useAsyncAsHook.js";
import { Button } from "../mui/Button.js";
-import { wxApi } from "../wxApi.js";
interface Props {
pid: string;
@@ -47,12 +47,10 @@ export function ProviderDetailPage({
onWithdraw,
}: Props): VNode {
const { i18n } = useTranslationContext();
+ const api = useBackendContext();
async function getProviderInfo(): Promise<ProviderInfo | null> {
//create a first list of backup info by currency
- const status = await wxApi.wallet.call(
- WalletApiOperation.GetBackupInfo,
- {},
- );
+ const status = await api.wallet.call(WalletApiOperation.GetBackupInfo, {});
const providers = status.providers.filter(
(p) => p.syncProviderBaseUrl === providerURL,
@@ -103,7 +101,7 @@ export function ProviderDetailPage({
<ProviderView
info={info}
onSync={async () =>
- wxApi.wallet
+ api.wallet
.call(WalletApiOperation.RunBackupCycle, {
providers: [providerURL],
})
@@ -120,7 +118,7 @@ export function ProviderDetailPage({
onWithdraw(info.paymentStatus.amount);
}}
onDelete={() =>
- wxApi.wallet
+ api.wallet
.call(WalletApiOperation.RemoveBackupProvider, {
provider: providerURL,
})
diff --git a/packages/taler-wallet-webextension/src/wallet/Settings.tsx b/packages/taler-wallet-webextension/src/wallet/Settings.tsx
index c0268a1ae..f00b242d6 100644
--- a/packages/taler-wallet-webextension/src/wallet/Settings.tsx
+++ b/packages/taler-wallet-webextension/src/wallet/Settings.tsx
@@ -34,6 +34,7 @@ import {
SuccessText,
WarningText,
} from "../components/styled/index.js";
+import { useBackendContext } from "../context/backend.js";
import { useDevContext } from "../context/devContext.js";
import { useTranslationContext } from "../context/translation.js";
import { useAsyncAsHook } from "../hooks/useAsyncAsHook.js";
@@ -43,7 +44,6 @@ import { useClipboardPermissions } from "../hooks/useClipboardPermissions.js";
import { ToggleHandler } from "../mui/handlers.js";
import { Pages } from "../NavigationBar.js";
import { platform } from "../platform/api.js";
-import { wxApi } from "../wxApi.js";
const GIT_HASH = typeof __GIT_HASH__ !== "undefined" ? __GIT_HASH__ : undefined;
@@ -53,10 +53,11 @@ export function SettingsPage(): VNode {
const { devModeToggle } = useDevContext();
const { name, update } = useBackupDeviceName();
const webex = platform.getWalletWebExVersion();
+ const api = useBackendContext();
const exchangesHook = useAsyncAsHook(async () => {
- const list = await wxApi.wallet.call(WalletApiOperation.ListExchanges, {});
- const version = await wxApi.wallet.call(WalletApiOperation.GetVersion, {});
+ const list = await api.wallet.call(WalletApiOperation.ListExchanges, {});
+ const version = await api.wallet.call(WalletApiOperation.GetVersion, {});
return { exchanges: list.exchanges, version };
});
const { exchanges, version } =
diff --git a/packages/taler-wallet-webextension/src/wallet/Transaction.tsx b/packages/taler-wallet-webextension/src/wallet/Transaction.tsx
index e70f5fbd1..b7eb4a947 100644
--- a/packages/taler-wallet-webextension/src/wallet/Transaction.tsx
+++ b/packages/taler-wallet-webextension/src/wallet/Transaction.tsx
@@ -60,11 +60,11 @@ import {
WarningBox,
} from "../components/styled/index.js";
import { Time } from "../components/Time.js";
+import { useBackendContext } from "../context/backend.js";
import { useTranslationContext } from "../context/translation.js";
import { useAsyncAsHook } from "../hooks/useAsyncAsHook.js";
import { Button } from "../mui/Button.js";
import { Pages } from "../NavigationBar.js";
-import { wxApi } from "../wxApi.js";
interface Props {
tid: string;
@@ -76,17 +76,17 @@ export function TransactionPage({
goToWalletHistory,
}: Props): VNode {
const { i18n } = useTranslationContext();
-
+ const api = useBackendContext();
const state = useAsyncAsHook(
() =>
- wxApi.wallet.call(WalletApiOperation.GetTransactionById, {
+ api.wallet.call(WalletApiOperation.GetTransactionById, {
transactionId,
}),
[transactionId],
);
useEffect(() =>
- wxApi.listener.onUpdateNotification(
+ api.listener.onUpdateNotification(
[NotificationType.WithdrawGroupFinished],
state?.retry,
),
@@ -118,19 +118,19 @@ export function TransactionPage({
null;
}}
onDelete={async () => {
- await wxApi.wallet.call(WalletApiOperation.DeleteTransaction, {
+ await api.wallet.call(WalletApiOperation.DeleteTransaction, {
transactionId,
});
goToWalletHistory(currency);
}}
onRetry={async () => {
- await wxApi.wallet.call(WalletApiOperation.RetryTransaction, {
+ await api.wallet.call(WalletApiOperation.RetryTransaction, {
transactionId,
});
goToWalletHistory(currency);
}}
onRefund={async (purchaseId) => {
- await wxApi.wallet.call(WalletApiOperation.ApplyRefundFromPurchaseId, {
+ await api.wallet.call(WalletApiOperation.ApplyRefundFromPurchaseId, {
purchaseId,
});
}}
diff --git a/packages/taler-wallet-webextension/src/wxApi.ts b/packages/taler-wallet-webextension/src/wxApi.ts
index 524eed990..d304a42a5 100644
--- a/packages/taler-wallet-webextension/src/wxApi.ts
+++ b/packages/taler-wallet-webextension/src/wxApi.ts
@@ -151,6 +151,14 @@ function onUpdateNotification(
return platform.listenToWalletBackground(onNewMessage);
}
+export type WxApiType = {
+ wallet: WalletCoreApiClient;
+ background: BackgroundApiClient;
+ listener: {
+ onUpdateNotification: typeof onUpdateNotification;
+ }
+}
+
export const wxApi = {
wallet: new WxWalletCoreApiClient(),
background: new BackgroundApiClient(),
diff --git a/packages/web-util/src/tests/hook.ts b/packages/web-util/src/tests/hook.ts
index f5bebbd6d..a4938f3f9 100644
--- a/packages/web-util/src/tests/hook.ts
+++ b/packages/web-util/src/tests/hook.ts
@@ -246,7 +246,7 @@ interface HookTestResultError {
export async function hookBehaveLikeThis<T extends object, PropsType>(
hookFunction: (p: PropsType) => RecursiveState<T>,
props: PropsType,
- checks: Array<(state: T) => void>,
+ checks: Array<(state: Exclude<T, VoidFunction>) => void>,
Context?: ({ children }: { children: any }) => VNode | null,
): Promise<HookTestResult> {
const { pullLastResultOrThrow, waitForStateUpdate, assertNoPendingUpdate } =