summaryrefslogtreecommitdiff
path: root/packages/taler-wallet-webextension/src/wallet
diff options
context:
space:
mode:
authorSebastian <sebasjm@gmail.com>2022-03-23 16:20:39 -0300
committerSebastian <sebasjm@gmail.com>2022-03-23 16:20:39 -0300
commite21c1b31928cd6bfe90150ea2de19799b6359c40 (patch)
tree10558ee2b86d5ac01de0995bfe12bdb7da44edde /packages/taler-wallet-webextension/src/wallet
parent136c39ba9fb86080beaa27cd9e0c4d5086a2d691 (diff)
downloadwallet-core-e21c1b31928cd6bfe90150ea2de19799b6359c40.tar.gz
wallet-core-e21c1b31928cd6bfe90150ea2de19799b6359c40.tar.bz2
wallet-core-e21c1b31928cd6bfe90150ea2de19799b6359c40.zip
splitted rollup config for testing and first component state unit test
Diffstat (limited to 'packages/taler-wallet-webextension/src/wallet')
-rw-r--r--packages/taler-wallet-webextension/src/wallet/CreateManualWithdraw.stories.tsx12
-rw-r--r--packages/taler-wallet-webextension/src/wallet/CreateManualWithdraw.test.ts212
-rw-r--r--packages/taler-wallet-webextension/src/wallet/CreateManualWithdraw.tsx57
-rw-r--r--packages/taler-wallet-webextension/src/wallet/ManualWithdrawPage.tsx2
4 files changed, 260 insertions, 23 deletions
diff --git a/packages/taler-wallet-webextension/src/wallet/CreateManualWithdraw.stories.tsx b/packages/taler-wallet-webextension/src/wallet/CreateManualWithdraw.stories.tsx
index e4955e376..407d4ef34 100644
--- a/packages/taler-wallet-webextension/src/wallet/CreateManualWithdraw.stories.tsx
+++ b/packages/taler-wallet-webextension/src/wallet/CreateManualWithdraw.stories.tsx
@@ -29,30 +29,30 @@ export default {
};
// ,
-const exchangeList = {
+const exchangeUrlWithCurrency = {
"http://exchange.taler:8081": "COL",
"http://exchange.tal": "EUR",
};
export const WithoutAnyExchangeKnown = createExample(TestedComponent, {
- exchangeList: {},
+ exchangeUrlWithCurrency: {},
});
export const InitialState = createExample(TestedComponent, {
- exchangeList,
+ exchangeUrlWithCurrency,
});
export const WithAmountInitialized = createExample(TestedComponent, {
initialAmount: "10",
- exchangeList,
+ exchangeUrlWithCurrency,
});
export const WithExchangeError = createExample(TestedComponent, {
error: "The exchange url seems invalid",
- exchangeList,
+ exchangeUrlWithCurrency,
});
export const WithAmountError = createExample(TestedComponent, {
initialAmount: "e",
- exchangeList,
+ exchangeUrlWithCurrency,
});
diff --git a/packages/taler-wallet-webextension/src/wallet/CreateManualWithdraw.test.ts b/packages/taler-wallet-webextension/src/wallet/CreateManualWithdraw.test.ts
new file mode 100644
index 000000000..a5174bef9
--- /dev/null
+++ b/packages/taler-wallet-webextension/src/wallet/CreateManualWithdraw.test.ts
@@ -0,0 +1,212 @@
+/*
+ This file is part of GNU Taler
+ (C) 2021 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 { SelectFieldHandler, TextFieldHandler, useComponentState } from "./CreateManualWithdraw";
+import { expect } from "chai";
+import { mountHook } from "../test-utils";
+
+
+const exchangeListWithARSandUSD = {
+ "url1": "USD",
+ "url2": "ARS",
+ "url3": "ARS",
+};
+
+const exchangeListEmpty = {
+};
+
+describe("CreateManualWithdraw states", () => {
+ it("should set noExchangeFound when exchange list is empty", () => {
+ const { result } = mountHook(() =>
+ useComponentState(exchangeListEmpty, undefined, undefined),
+ );
+
+ if (!result.current) {
+ expect(result.current).not.to.be.undefined;
+ return;
+ }
+
+ expect(result.current.noExchangeFound).equal(true)
+ });
+
+ it("should set noExchangeFound when exchange list doesn't include selected currency", () => {
+ const { result } = mountHook(() =>
+ useComponentState(exchangeListWithARSandUSD, undefined, "COL"),
+ );
+
+ if (!result.current) {
+ expect(result.current).not.to.be.undefined;
+ return;
+ }
+
+ expect(result.current.noExchangeFound).equal(true)
+ });
+
+
+ it("should select the first exchange from the list", () => {
+ const { result } = mountHook(() =>
+ useComponentState(exchangeListWithARSandUSD, undefined, undefined),
+ );
+
+ if (!result.current) {
+ expect(result.current).not.to.be.undefined;
+ return;
+ }
+
+ expect(result.current.exchange.value).equal("url1")
+ });
+
+ it("should select the first exchange with the selected currency", () => {
+ const { result } = mountHook(() =>
+ useComponentState(exchangeListWithARSandUSD, undefined, "ARS"),
+ );
+
+ if (!result.current) {
+ expect(result.current).not.to.be.undefined;
+ return;
+ }
+
+ expect(result.current.exchange.value).equal("url2")
+ });
+
+ it("should change the exchange when currency change", async () => {
+ const { result, waitNextUpdate } = mountHook(() =>
+ useComponentState(exchangeListWithARSandUSD, undefined, "ARS"),
+ );
+
+ if (!result.current) {
+ expect.fail("hook didn't render");
+ }
+
+ expect(result.current.exchange.value).equal("url2")
+
+ result.current.currency.onChange("USD")
+
+ await waitNextUpdate()
+
+ expect(result.current.exchange.value).equal("url1")
+
+ });
+
+ it("should change the currency when exchange change", async () => {
+ const { result, waitNextUpdate } = mountHook(() =>
+ useComponentState(exchangeListWithARSandUSD, undefined, "ARS"),
+ );
+
+ if (!result.current) {
+ expect.fail("hook didn't render");
+ }
+
+ expect(result.current.exchange.value).equal("url2")
+ expect(result.current.currency.value).equal("ARS")
+
+ result.current.exchange.onChange("url1")
+
+ await waitNextUpdate()
+
+ expect(result.current.exchange.value).equal("url1")
+ expect(result.current.currency.value).equal("USD")
+ });
+
+ it("should update parsed amount when amount change", async () => {
+ const { result, waitNextUpdate } = mountHook(() =>
+ useComponentState(exchangeListWithARSandUSD, undefined, "ARS"),
+ );
+
+ if (!result.current) {
+ expect.fail("hook didn't render");
+ }
+
+ expect(result.current.parsedAmount).equal(undefined)
+
+ result.current.amount.onInput("12")
+
+ await waitNextUpdate()
+
+ expect(result.current.parsedAmount).deep.equals({
+ value: 12, fraction: 0, currency: "ARS"
+ })
+ });
+
+ it("should have an amount field", async () => {
+ const { result, waitNextUpdate } = mountHook(() =>
+ useComponentState(exchangeListWithARSandUSD, undefined, "ARS"),
+ );
+
+ if (!result.current) {
+ expect.fail("hook didn't render");
+ }
+
+ await defaultTestForInputText(waitNextUpdate, () => result.current!.amount)
+ })
+
+ it("should have an exchange selector ", async () => {
+ const { result, waitNextUpdate } = mountHook(() =>
+ useComponentState(exchangeListWithARSandUSD, undefined, "ARS"),
+ );
+
+ if (!result.current) {
+ expect.fail("hook didn't render");
+ }
+
+ await defaultTestForInputSelect(waitNextUpdate, () => result.current!.exchange)
+ })
+
+ it("should have a currency selector ", async () => {
+ const { result, waitNextUpdate } = mountHook(() =>
+ useComponentState(exchangeListWithARSandUSD, undefined, "ARS"),
+ );
+
+ if (!result.current) {
+ expect.fail("hook didn't render");
+ }
+
+ await defaultTestForInputSelect(waitNextUpdate, () => result.current!.currency)
+ })
+
+});
+
+
+async function defaultTestForInputText(awaiter: () => Promise<void>, getField: () => TextFieldHandler) {
+ const initialValue = getField().value;
+ const otherValue = `${initialValue} something else`
+ getField().onInput(otherValue)
+
+ await awaiter()
+
+ expect(getField().value).equal(otherValue)
+}
+
+
+async function defaultTestForInputSelect(awaiter: () => Promise<void>, getField: () => SelectFieldHandler) {
+ const initialValue = getField().value;
+ const keys = Object.keys(getField().list)
+ const nextIdx = keys.indexOf(initialValue) + 1
+ if (keys.length < nextIdx) {
+ throw new Error('no enough values')
+ }
+ const nextValue = keys[nextIdx]
+ getField().onChange(nextValue)
+
+ await awaiter()
+
+ expect(getField().value).equal(nextValue)
+}
diff --git a/packages/taler-wallet-webextension/src/wallet/CreateManualWithdraw.tsx b/packages/taler-wallet-webextension/src/wallet/CreateManualWithdraw.tsx
index 068135ae0..2d5129a3d 100644
--- a/packages/taler-wallet-webextension/src/wallet/CreateManualWithdraw.tsx
+++ b/packages/taler-wallet-webextension/src/wallet/CreateManualWithdraw.tsx
@@ -39,20 +39,39 @@ import { Pages } from "../NavigationBar";
export interface Props {
error: string | undefined;
initialAmount?: string;
- exchangeList: Record<string, string>;
+ exchangeUrlWithCurrency: Record<string, string>;
onCreate: (exchangeBaseUrl: string, amount: AmountJson) => Promise<void>;
initialCurrency?: string;
}
+export interface State {
+ noExchangeFound: boolean;
+ parsedAmount: AmountJson | undefined;
+ amount: TextFieldHandler;
+ currency: SelectFieldHandler;
+ exchange: SelectFieldHandler;
+}
+
+export interface TextFieldHandler {
+ onInput: (value: string) => void;
+ value: string;
+}
+
+export interface SelectFieldHandler {
+ onChange: (value: string) => void;
+ value: string;
+ list: Record<string, string>;
+}
+
export function useComponentState(
- exchangeList: Record<string, string>,
+ exchangeUrlWithCurrency: Record<string, string>,
initialAmount: string | undefined,
initialCurrency: string | undefined,
-) {
- const exchangeSelectList = Object.keys(exchangeList);
- const currencySelectList = Object.values(exchangeList);
+): State {
+ const exchangeSelectList = Object.keys(exchangeUrlWithCurrency);
+ const currencySelectList = Object.values(exchangeUrlWithCurrency);
const exchangeMap = exchangeSelectList.reduce(
- (p, c) => ({ ...p, [c]: `${c} (${exchangeList[c]})` }),
+ (p, c) => ({ ...p, [c]: `${c} (${exchangeUrlWithCurrency[c]})` }),
{} as Record<string, string>,
);
const currencyMap = currencySelectList.reduce(
@@ -61,7 +80,7 @@ export function useComponentState(
);
const foundExchangeForCurrency = exchangeSelectList.findIndex(
- (e) => exchangeList[e] === initialCurrency,
+ (e) => exchangeUrlWithCurrency[e] === initialCurrency,
);
const initialExchange =
@@ -73,7 +92,7 @@ export function useComponentState(
const [exchange, setExchange] = useState(initialExchange || "");
const [currency, setCurrency] = useState(
- initialExchange ? exchangeList[initialExchange] : "",
+ initialExchange ? exchangeUrlWithCurrency[initialExchange] : "",
);
const [amount, setAmount] = useState(initialAmount || "");
@@ -81,12 +100,14 @@ export function useComponentState(
function changeExchange(exchange: string): void {
setExchange(exchange);
- setCurrency(exchangeList[exchange]);
+ setCurrency(exchangeUrlWithCurrency[exchange]);
}
function changeCurrency(currency: string): void {
setCurrency(currency);
- const found = Object.entries(exchangeList).find((e) => e[1] === currency);
+ const found = Object.entries(exchangeUrlWithCurrency).find(
+ (e) => e[1] === currency,
+ );
if (found) {
setExchange(found[0]);
@@ -95,7 +116,7 @@ export function useComponentState(
}
}
return {
- initialExchange,
+ noExchangeFound: initialExchange === undefined,
currency: {
list: currencyMap,
value: currency,
@@ -114,12 +135,12 @@ export function useComponentState(
};
}
-interface InputHandler {
+export interface InputHandler {
value: string;
onInput: (s: string) => void;
}
-interface SelectInputHandler {
+export interface SelectInputHandler {
list: Record<string, string>;
value: string;
onChange: (s: string) => void;
@@ -127,16 +148,20 @@ interface SelectInputHandler {
export function CreateManualWithdraw({
initialAmount,
- exchangeList,
+ exchangeUrlWithCurrency,
error,
initialCurrency,
onCreate,
}: Props): VNode {
const { i18n } = useTranslationContext();
- const state = useComponentState(exchangeList, initialAmount, initialCurrency);
+ const state = useComponentState(
+ exchangeUrlWithCurrency,
+ initialAmount,
+ initialCurrency,
+ );
- if (!state.initialExchange) {
+ if (state.noExchangeFound) {
if (initialCurrency !== undefined) {
return (
<section>
diff --git a/packages/taler-wallet-webextension/src/wallet/ManualWithdrawPage.tsx b/packages/taler-wallet-webextension/src/wallet/ManualWithdrawPage.tsx
index b7e63bbf8..05c518508 100644
--- a/packages/taler-wallet-webextension/src/wallet/ManualWithdrawPage.tsx
+++ b/packages/taler-wallet-webextension/src/wallet/ManualWithdrawPage.tsx
@@ -110,7 +110,7 @@ export function ManualWithdrawPage({ currency, onCancel }: Props): VNode {
return (
<CreateManualWithdraw
error={error}
- exchangeList={exchangeList}
+ exchangeUrlWithCurrency={exchangeList}
onCreate={doCreate}
initialCurrency={currency}
/>