using the test to fine tune the withdraw process

This commit is contained in:
Sebastian 2022-04-11 18:00:28 -03:00
parent 1ae4a44a3a
commit d34eeb5c8c
No known key found for this signature in database
GPG Key ID: BE4FF68352439FC1
3 changed files with 46 additions and 84 deletions

View File

@ -53,13 +53,6 @@ describe("Withdraw CTA states", () => {
await waitNextUpdate() await waitNextUpdate()
{
const { status, hook } = getLastResultOrThrow()
expect(status).equals('loading-uri')
expect(hook).deep.equals({ "hasError": true, "operational": false, "message": "ERROR_NO-URI-FOR-WITHDRAWAL" });
}
await waitNextUpdate()
{ {
const { status, hook } = getLastResultOrThrow() const { status, hook } = getLastResultOrThrow()
@ -89,25 +82,6 @@ describe("Withdraw CTA states", () => {
await waitNextUpdate() await waitNextUpdate()
{
const { status, hook } = getLastResultOrThrow()
expect(status).equals('loading-exchange')
expect(hook).undefined;
}
await waitNextUpdate()
{
const { status, hook } = getLastResultOrThrow()
expect(status).equals('loading-exchange')
expect(hook).deep.equals({ "hasError": true, "operational": false, "message": "ERROR_NO-DEFAULT-EXCHANGE" });
}
await waitNextUpdate()
{ {
const { status, hook } = getLastResultOrThrow() const { status, hook } = getLastResultOrThrow()

View File

@ -24,7 +24,7 @@
import { AmountJson, Amounts } from "@gnu-taler/taler-util"; import { AmountJson, Amounts } from "@gnu-taler/taler-util";
import { TalerError } from "@gnu-taler/taler-wallet-core"; import { TalerError } from "@gnu-taler/taler-wallet-core";
import { Fragment, h, VNode } from "preact"; import { Fragment, h, VNode } from "preact";
import { useState } from "preact/hooks"; import { useMemo, useState } from "preact/hooks";
import { Amount } from "../components/Amount.js"; import { Amount } from "../components/Amount.js";
import { ErrorTalerOperation } from "../components/ErrorTalerOperation.js"; import { ErrorTalerOperation } from "../components/ErrorTalerOperation.js";
import { Loading } from "../components/Loading.js"; import { Loading } from "../components/Loading.js";
@ -116,44 +116,44 @@ export function useComponentState(
/** /**
* Get the amount and select one exchange * Get the amount and select one exchange
*/ */
const exchangeAndAmount = useAsyncAsHook( const uriHookDep =
async () => { !uriInfoHook || uriInfoHook.hasError || !uriInfoHook.response
if (!uriInfoHook || uriInfoHook.hasError || !uriInfoHook.response) return; ? undefined
const { uriInfo, knownExchanges } = uriInfoHook.response; : uriInfoHook;
const amount = Amounts.parseOrThrow(uriInfo.amount); const { amount, thisExchange, thisCurrencyExchanges } = useMemo(() => {
if (!uriHookDep)
return {
amount: undefined,
thisExchange: undefined,
thisCurrencyExchanges: [],
};
const thisCurrencyExchanges = knownExchanges.filter( const { uriInfo, knownExchanges } = uriHookDep.response;
(ex) => ex.currency === amount.currency,
);
const thisExchange: string | undefined = const amount = uriInfo ? Amounts.parseOrThrow(uriInfo.amount) : undefined;
customExchange ?? const thisCurrencyExchanges =
uriInfo.defaultExchangeBaseUrl ?? !amount || !knownExchanges
(thisCurrencyExchanges[0] ? []
? thisCurrencyExchanges[0].exchangeBaseUrl : knownExchanges.filter((ex) => ex.currency === amount.currency);
: undefined);
if (!thisExchange) throw Error("ERROR_NO-DEFAULT-EXCHANGE"); const thisExchange: string | undefined =
customExchange ??
uriInfo?.defaultExchangeBaseUrl ??
(thisCurrencyExchanges && thisCurrencyExchanges[0]
? thisCurrencyExchanges[0].exchangeBaseUrl
: undefined);
return { amount, thisExchange, thisCurrencyExchanges }; return { amount, thisExchange, thisCurrencyExchanges };
}, }, [uriHookDep, customExchange]);
[],
[!uriInfoHook || uriInfoHook.hasError ? undefined : uriInfoHook],
);
/** /**
* For the exchange selected, bring the status of the terms of service * For the exchange selected, bring the status of the terms of service
*/ */
const terms = useAsyncAsHook( const terms = useAsyncAsHook(
async () => { async () => {
if ( if (!thisExchange) return false;
!exchangeAndAmount ||
exchangeAndAmount.hasError ||
!exchangeAndAmount.response
)
return;
const { thisExchange } = exchangeAndAmount.response;
const exchangeTos = await api.getExchangeTos(thisExchange, ["text/xml"]); const exchangeTos = await api.getExchangeTos(thisExchange, ["text/xml"]);
const state = buildTermsOfServiceState(exchangeTos); const state = buildTermsOfServiceState(exchangeTos);
@ -161,11 +161,7 @@ export function useComponentState(
return { state }; return { state };
}, },
[], [],
[ [thisExchange],
!exchangeAndAmount || exchangeAndAmount.hasError
? undefined
: exchangeAndAmount,
],
); );
/** /**
@ -174,13 +170,7 @@ export function useComponentState(
*/ */
const info = useAsyncAsHook( const info = useAsyncAsHook(
async () => { async () => {
if ( if (!thisExchange || !amount) return false;
!exchangeAndAmount ||
exchangeAndAmount.hasError ||
!exchangeAndAmount.response
)
return;
const { thisExchange, amount } = exchangeAndAmount.response;
const info = await api.getExchangeWithdrawalInfo({ const info = await api.getExchangeWithdrawalInfo({
exchangeBaseUrl: thisExchange, exchangeBaseUrl: thisExchange,
@ -196,11 +186,7 @@ export function useComponentState(
return { info, withdrawalFee }; return { info, withdrawalFee };
}, },
[], [],
[ [thisExchange, amount],
!exchangeAndAmount || exchangeAndAmount.hasError
? undefined
: exchangeAndAmount,
],
); );
const [reviewing, setReviewing] = useState<boolean>(false); const [reviewing, setReviewing] = useState<boolean>(false);
@ -221,26 +207,27 @@ export function useComponentState(
}; };
} }
if (!exchangeAndAmount || exchangeAndAmount.hasError) { if (!thisExchange || !amount) {
return { return {
status: "loading-exchange", status: "loading-exchange",
hook: exchangeAndAmount, hook: {
hasError: true,
operational: false,
message: "ERROR_NO-DEFAULT-EXCHANGE",
},
}; };
} }
if (!exchangeAndAmount.response) {
return { const selectedExchange = thisExchange;
status: "loading-exchange",
hook: undefined,
};
}
const { thisExchange, thisCurrencyExchanges, amount } =
exchangeAndAmount.response;
async function doWithdrawAndCheckError(): Promise<void> { async function doWithdrawAndCheckError(): Promise<void> {
try { try {
setConfirmDisabled(true); setConfirmDisabled(true);
if (!talerWithdrawUri) return; if (!talerWithdrawUri) return;
const res = await api.acceptWithdrawal(talerWithdrawUri, thisExchange); const res = await api.acceptWithdrawal(
talerWithdrawUri,
selectedExchange,
);
if (res.confirmTransferUrl) { if (res.confirmTransferUrl) {
document.location.href = res.confirmTransferUrl; document.location.href = res.confirmTransferUrl;
} }
@ -308,7 +295,7 @@ export function useComponentState(
try { try {
await api.setExchangeTosAccepted( await api.setExchangeTosAccepted(
thisExchange, selectedExchange,
accepted ? termsState.version : undefined, accepted ? termsState.version : undefined,
); );
setReviewed(accepted); setReviewed(accepted);

View File

@ -42,7 +42,7 @@ export interface HookOperationalError {
export type HookResponse<T> = HookOk<T> | HookError | undefined; export type HookResponse<T> = HookOk<T> | HookError | undefined;
export function useAsyncAsHook<T>( export function useAsyncAsHook<T>(
fn: () => Promise<T>, fn: () => Promise<T | false>,
updateOnNotification?: Array<NotificationType>, updateOnNotification?: Array<NotificationType>,
deps?: any[], deps?: any[],
): HookResponse<T> { ): HookResponse<T> {
@ -57,6 +57,7 @@ export function useAsyncAsHook<T>(
async function doAsync(): Promise<void> { async function doAsync(): Promise<void> {
try { try {
const response = await args.fn(); const response = await args.fn();
if (response === false) return;
setHookResponse({ hasError: false, response }); setHookResponse({ hasError: false, response });
} catch (e) { } catch (e) {
if (e instanceof TalerError) { if (e instanceof TalerError) {