fix #7153: more error handling
if handler do not trap error then fail at compile time, all safe handlers push alert on error errors are typed so they render good information
This commit is contained in:
parent
8a70edb2f8
commit
4a781bd0dd
@ -20,12 +20,10 @@
|
||||
*/
|
||||
|
||||
import { AmountJson, Amounts } from "@gnu-taler/taler-util";
|
||||
import { styled } from "@linaria/react";
|
||||
import { Fragment, h, VNode } from "preact";
|
||||
import { useState } from "preact/hooks";
|
||||
import { useTranslationContext } from "../context/translation.js";
|
||||
import { Grid } from "../mui/Grid.js";
|
||||
import { AmountFieldHandler, TextFieldHandler } from "../mui/handlers.js";
|
||||
import { AmountFieldHandler, nullFunction, withSafe } from "../mui/handlers.js";
|
||||
import { AmountField } from "./AmountField.js";
|
||||
|
||||
export default {
|
||||
@ -39,9 +37,9 @@ function RenderAmount(): VNode {
|
||||
|
||||
const handler: AmountFieldHandler = {
|
||||
value: value ?? Amounts.zeroOfCurrency("USD"),
|
||||
onInput: async (e) => {
|
||||
onInput: withSafe(async (e) => {
|
||||
setValue(e);
|
||||
},
|
||||
}, nullFunction),
|
||||
error,
|
||||
};
|
||||
const { i18n } = useTranslationContext();
|
||||
|
@ -18,7 +18,6 @@ import { ComponentChildren, Fragment, h, VNode } from "preact";
|
||||
import { useState } from "preact/hooks";
|
||||
import { useTranslationContext } from "../../../web-util/src/index.browser.js";
|
||||
import {
|
||||
ErrorAlert,
|
||||
Alert as AlertNotification,
|
||||
useAlertContext,
|
||||
} from "../context/alert.js";
|
||||
@ -37,41 +36,78 @@ function AlertContext({
|
||||
context: undefined | object;
|
||||
}): VNode {
|
||||
const [more, setMore] = useState(false);
|
||||
const [wrap, setWrap] = useState(false);
|
||||
const { i18n } = useTranslationContext();
|
||||
if (!more) {
|
||||
return (
|
||||
<div style={{ display: "flex", justifyContent: "right" }}>
|
||||
<a onClick={() => setMore(true)}>
|
||||
<a
|
||||
onClick={() => setMore(true)}
|
||||
style={{ cursor: "pointer", textDecoration: "underline" }}
|
||||
>
|
||||
<i18n.Translate>more info</i18n.Translate>
|
||||
</a>
|
||||
</div>
|
||||
);
|
||||
}
|
||||
return (
|
||||
<pre style={{ overflow: "overlay" }}>
|
||||
{JSON.stringify(
|
||||
const errorInfo = JSON.stringify(
|
||||
context === undefined ? { cause } : { context, cause },
|
||||
undefined,
|
||||
2,
|
||||
)}
|
||||
);
|
||||
return (
|
||||
<Fragment>
|
||||
<div style={{ display: "flex", justifyContent: "right" }}>
|
||||
<a
|
||||
onClick={() => setWrap(!wrap)}
|
||||
style={{ cursor: "pointer", textDecoration: "underline" }}
|
||||
>
|
||||
<i18n.Translate>wrap text</i18n.Translate>
|
||||
</a>
|
||||
|
||||
<a
|
||||
onClick={() => navigator.clipboard.writeText(errorInfo)}
|
||||
style={{ cursor: "pointer", textDecoration: "underline" }}
|
||||
>
|
||||
<i18n.Translate>copy content</i18n.Translate>
|
||||
</a>
|
||||
|
||||
<a
|
||||
onClick={() => setMore(false)}
|
||||
style={{ cursor: "pointer", textDecoration: "underline" }}
|
||||
>
|
||||
<i18n.Translate>less info</i18n.Translate>
|
||||
</a>
|
||||
</div>
|
||||
<pre
|
||||
style={
|
||||
wrap
|
||||
? {
|
||||
whiteSpace: "pre-wrap",
|
||||
overflowWrap: "anywhere",
|
||||
}
|
||||
: {
|
||||
overflow: "overlay",
|
||||
}
|
||||
}
|
||||
>
|
||||
{errorInfo}
|
||||
</pre>
|
||||
</Fragment>
|
||||
);
|
||||
}
|
||||
|
||||
export function ErrorAlertView({
|
||||
error: alert,
|
||||
error,
|
||||
onClose,
|
||||
}: {
|
||||
error: ErrorAlert;
|
||||
error: AlertNotification;
|
||||
onClose?: () => Promise<void>;
|
||||
}): VNode {
|
||||
return (
|
||||
<Alert title={alert.message} severity={alert.type} onClose={onClose}>
|
||||
<div style={{ display: "flex", flexDirection: "column" }}>
|
||||
<div>{alert.description}</div>
|
||||
<AlertContext context={alert.context} cause={alert.cause} />
|
||||
</div>
|
||||
</Alert>
|
||||
<Wrapper>
|
||||
<AlertView alert={error} onClose={onClose} />
|
||||
</Wrapper>
|
||||
);
|
||||
}
|
||||
|
||||
@ -86,6 +122,9 @@ export function AlertView({
|
||||
<Alert title={alert.message} severity={alert.type} onClose={onClose}>
|
||||
<div style={{ display: "flex", flexDirection: "column" }}>
|
||||
<div>{alert.description}</div>
|
||||
{alert.type === "error" ? (
|
||||
<AlertContext context={alert.context} cause={alert.cause} />
|
||||
) : undefined}
|
||||
</div>
|
||||
</Alert>
|
||||
);
|
||||
@ -104,5 +143,5 @@ export function CurrentAlerts(): VNode {
|
||||
}
|
||||
|
||||
function Wrapper({ children }: { children: ComponentChildren }): VNode {
|
||||
return <div style={{ margin: "2em" }}>{children}</div>;
|
||||
return <div style={{ margin: "1em" }}>{children}</div>;
|
||||
}
|
||||
|
@ -24,7 +24,7 @@ import {
|
||||
Transaction,
|
||||
TransactionType,
|
||||
} from "@gnu-taler/taler-util";
|
||||
import { createExample } from "../test-utils.js";
|
||||
import { tests } from "@gnu-taler/web-util/lib/index.browser";
|
||||
import { PendingTransactionsView as TestedComponent } from "./PendingTransactions.js";
|
||||
|
||||
export default {
|
||||
@ -32,7 +32,7 @@ export default {
|
||||
component: TestedComponent,
|
||||
};
|
||||
|
||||
export const OnePendingTransaction = createExample(TestedComponent, {
|
||||
export const OnePendingTransaction = tests.createExample(TestedComponent, {
|
||||
transactions: [
|
||||
{
|
||||
amountEffective: "USD:10",
|
||||
@ -42,7 +42,7 @@ export const OnePendingTransaction = createExample(TestedComponent, {
|
||||
],
|
||||
});
|
||||
|
||||
export const ThreePendingTransactions = createExample(TestedComponent, {
|
||||
export const ThreePendingTransactions = tests.createExample(TestedComponent, {
|
||||
transactions: [
|
||||
{
|
||||
amountEffective: "USD:10",
|
||||
@ -62,7 +62,7 @@ export const ThreePendingTransactions = createExample(TestedComponent, {
|
||||
],
|
||||
});
|
||||
|
||||
export const TenPendingTransactions = createExample(TestedComponent, {
|
||||
export const TenPendingTransactions = tests.createExample(TestedComponent, {
|
||||
transactions: [
|
||||
{
|
||||
amountEffective: "USD:10",
|
||||
|
@ -19,13 +19,13 @@
|
||||
* @author Sebastian Javier Marchano (sebasjm)
|
||||
*/
|
||||
|
||||
import { createExample } from "../test-utils.js";
|
||||
import { tests } from "@gnu-taler/web-util/lib/index.browser";
|
||||
import { QR } from "./QR.js";
|
||||
|
||||
export default {
|
||||
title: "qr",
|
||||
};
|
||||
|
||||
export const Restore = createExample(QR, {
|
||||
export const Restore = tests.createExample(QR, {
|
||||
text: "taler://restore/6J0RZTJC6AV21WXK87BTE67WTHE9P2QSHF2BZXTP7PDZY2ARYBPG@sync1.demo.taler.net,sync2.demo.taler.net,sync1.demo.taler.net,sync3.demo.taler.net",
|
||||
});
|
||||
|
@ -20,7 +20,7 @@
|
||||
*/
|
||||
|
||||
import { WalletContractData } from "@gnu-taler/taler-wallet-core";
|
||||
import { createExample } from "../test-utils.js";
|
||||
import { tests } from "@gnu-taler/web-util/lib/index.browser";
|
||||
import {
|
||||
ErrorView,
|
||||
HiddenView,
|
||||
@ -86,10 +86,10 @@ const cd: WalletContractData = {
|
||||
deliveryLocation: undefined,
|
||||
};
|
||||
|
||||
export const ShowingSimpleOrder = createExample(ShowView, {
|
||||
export const ShowingSimpleOrder = tests.createExample(ShowView, {
|
||||
contractTerms: cd,
|
||||
});
|
||||
export const Error = createExample(ErrorView, {
|
||||
export const Error = tests.createExample(ErrorView, {
|
||||
proposalId: "asd",
|
||||
error: {
|
||||
hasError: true,
|
||||
@ -103,5 +103,5 @@ export const Error = createExample(ErrorView, {
|
||||
// },
|
||||
},
|
||||
});
|
||||
export const Loading = createExample(LoadingView, {});
|
||||
export const Hidden = createExample(HiddenView, {});
|
||||
export const Loading = tests.createExample(LoadingView, {});
|
||||
export const Hidden = tests.createExample(HiddenView, {});
|
||||
|
@ -24,14 +24,14 @@ import { useState } from "preact/hooks";
|
||||
import { Loading } from "../components/Loading.js";
|
||||
import { Modal } from "../components/Modal.js";
|
||||
import { Time } from "../components/Time.js";
|
||||
import { alertFromError } from "../context/alert.js";
|
||||
import { alertFromError, useAlertContext } from "../context/alert.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 { Amount } from "./Amount.js";
|
||||
import { AlertView } from "./CurrentAlerts.js";
|
||||
import { ErrorAlertView } from "./CurrentAlerts.js";
|
||||
import { Link } from "./styled/index.js";
|
||||
|
||||
const ContractTermsTable = styled.table`
|
||||
@ -102,6 +102,7 @@ interface Props {
|
||||
function useComponentState({ proposalId }: Props): State {
|
||||
const api = useBackendContext();
|
||||
const [show, setShow] = useState(false);
|
||||
const { pushAlertOnError } = useAlertContext();
|
||||
const hook = useAsyncAsHook(async () => {
|
||||
if (!show) return undefined;
|
||||
return await api.wallet.call(WalletApiOperation.GetContractTermsDetails, {
|
||||
@ -110,10 +111,10 @@ function useComponentState({ proposalId }: Props): State {
|
||||
}, [show]);
|
||||
|
||||
const hideHandler = {
|
||||
onClick: async () => setShow(false),
|
||||
onClick: pushAlertOnError(async () => setShow(false)),
|
||||
};
|
||||
const showHandler = {
|
||||
onClick: async () => setShow(true),
|
||||
onClick: pushAlertOnError(async () => setShow(true)),
|
||||
};
|
||||
if (!show) {
|
||||
return {
|
||||
@ -161,8 +162,8 @@ export function ErrorView({
|
||||
const { i18n } = useTranslationContext();
|
||||
return (
|
||||
<Modal title="Full detail" onClose={hideHandler}>
|
||||
<AlertView
|
||||
alert={alertFromError(
|
||||
<ErrorAlertView
|
||||
error={alertFromError(
|
||||
i18n.str`Could not load purchase proposal details`,
|
||||
error,
|
||||
{ proposalId },
|
||||
|
@ -28,7 +28,7 @@ export function useComponentState({ exchangeUrl, onChange }: Props): State {
|
||||
const readOnly = !onChange;
|
||||
const [showContent, setShowContent] = useState<boolean>(readOnly);
|
||||
const { i18n } = useTranslationContext();
|
||||
const { pushAlert } = useAlertContext();
|
||||
const { pushAlertOnError } = useAlertContext();
|
||||
|
||||
/**
|
||||
* For the exchange selected, bring the status of the terms of service
|
||||
@ -67,7 +67,6 @@ export function useComponentState({ exchangeUrl, onChange }: Props): State {
|
||||
async function onUpdate(accepted: boolean): Promise<void> {
|
||||
if (!state) return;
|
||||
|
||||
try {
|
||||
if (accepted) {
|
||||
await api.wallet.call(WalletApiOperation.SetExchangeTosAccepted, {
|
||||
exchangeBaseUrl: exchangeUrl,
|
||||
@ -82,9 +81,6 @@ export function useComponentState({ exchangeUrl, onChange }: Props): State {
|
||||
}
|
||||
// setAccepted(accepted);
|
||||
if (!readOnly) onChange(accepted); //external update
|
||||
} catch (e) {
|
||||
pushAlert(alertFromError(i18n.str`Could not accept terms of service`, e));
|
||||
}
|
||||
}
|
||||
|
||||
const accepted = state.status === "accepted";
|
||||
@ -94,20 +90,20 @@ export function useComponentState({ exchangeUrl, onChange }: Props): State {
|
||||
showingTermsOfService: {
|
||||
value: showContent,
|
||||
button: {
|
||||
onClick: async () => {
|
||||
onClick: pushAlertOnError(async () => {
|
||||
setShowContent(!showContent);
|
||||
},
|
||||
}),
|
||||
},
|
||||
},
|
||||
terms: state,
|
||||
termsAccepted: {
|
||||
value: accepted,
|
||||
button: {
|
||||
onClick: async () => {
|
||||
onClick: pushAlertOnError(async () => {
|
||||
const newValue = !accepted; //toggle
|
||||
onUpdate(newValue);
|
||||
await onUpdate(newValue);
|
||||
setShowContent(false);
|
||||
},
|
||||
}),
|
||||
},
|
||||
},
|
||||
};
|
||||
|
@ -19,11 +19,11 @@
|
||||
* @author Sebastian Javier Marchano (sebasjm)
|
||||
*/
|
||||
|
||||
import { createExample } from "../../test-utils.js";
|
||||
import { tests } from "@gnu-taler/web-util/lib/index.browser";
|
||||
// import { ReadyView } from "./views.js";
|
||||
|
||||
export default {
|
||||
title: "TermsOfService",
|
||||
};
|
||||
|
||||
// export const Ready = createExample(ReadyView, {});
|
||||
// export const Ready = tests.createExample(ReadyView, {});
|
||||
|
@ -19,19 +19,26 @@
|
||||
* @author Sebastian Javier Marchano (sebasjm)
|
||||
*/
|
||||
|
||||
import { TranslatedString } from "@gnu-taler/taler-util";
|
||||
import { TalerErrorDetail, TranslatedString } from "@gnu-taler/taler-util";
|
||||
import { ComponentChildren, createContext, h, VNode } from "preact";
|
||||
import { useContext, useState } from "preact/hooks";
|
||||
import { HookError } from "../hooks/useAsyncAsHook.js";
|
||||
import { SafeHandler, withSafe } from "../mui/handlers.js";
|
||||
import { BackgroundError } from "../wxApi.js";
|
||||
|
||||
export type AlertType = "info" | "warning" | "error" | "success";
|
||||
|
||||
export interface Alert {
|
||||
export interface InfoAlert {
|
||||
message: TranslatedString;
|
||||
description: TranslatedString | VNode;
|
||||
type: AlertType;
|
||||
type: "info" | "warning" | "success";
|
||||
}
|
||||
|
||||
export interface ErrorAlert extends Alert {
|
||||
export type Alert = InfoAlert | ErrorAlert;
|
||||
|
||||
export interface ErrorAlert {
|
||||
message: TranslatedString;
|
||||
description: TranslatedString | VNode;
|
||||
type: "error";
|
||||
context: object;
|
||||
cause: any;
|
||||
@ -41,10 +48,14 @@ type Type = {
|
||||
alerts: Alert[];
|
||||
pushAlert: (n: Alert) => void;
|
||||
removeAlert: (n: Alert) => void;
|
||||
pushAlertOnError: <T>(h: (p: T) => Promise<void>) => SafeHandler<T>;
|
||||
};
|
||||
|
||||
const initial: Type = {
|
||||
alerts: [],
|
||||
pushAlertOnError: () => {
|
||||
throw Error("alert context not initialized");
|
||||
},
|
||||
pushAlert: () => {
|
||||
null;
|
||||
},
|
||||
@ -80,8 +91,17 @@ export const AlertProvider = ({ children }: Props): VNode => {
|
||||
setAlerts((ns: AlertWithDate[]) => ns.filter((n) => n !== alert));
|
||||
};
|
||||
|
||||
function pushAlertOnError<T>(
|
||||
handler: (p: T) => Promise<void>,
|
||||
): SafeHandler<T> {
|
||||
return withSafe(handler, (e) => {
|
||||
const a = alertFromError(e.message as TranslatedString, e);
|
||||
pushAlert(a);
|
||||
});
|
||||
}
|
||||
|
||||
return h(Context.Provider, {
|
||||
value: { alerts, pushAlert, removeAlert },
|
||||
value: { alerts, pushAlert, removeAlert, pushAlertOnError },
|
||||
children,
|
||||
});
|
||||
};
|
||||
@ -90,29 +110,71 @@ export const useAlertContext = (): Type => useContext(Context);
|
||||
|
||||
export function alertFromError(
|
||||
message: TranslatedString,
|
||||
error: unknown,
|
||||
error: HookError,
|
||||
...context: any[]
|
||||
): ErrorAlert;
|
||||
|
||||
export function alertFromError(
|
||||
message: TranslatedString,
|
||||
error: Error,
|
||||
...context: any[]
|
||||
): ErrorAlert;
|
||||
|
||||
export function alertFromError(
|
||||
message: TranslatedString,
|
||||
error: TalerErrorDetail,
|
||||
...context: any[]
|
||||
): ErrorAlert;
|
||||
|
||||
export function alertFromError(
|
||||
message: TranslatedString,
|
||||
error: HookError | TalerErrorDetail | Error,
|
||||
...context: any[]
|
||||
): ErrorAlert {
|
||||
let description = "" as TranslatedString;
|
||||
let description: TranslatedString;
|
||||
let cause: any;
|
||||
|
||||
const isObject = typeof error === "object" &&
|
||||
error !== null;
|
||||
const hasMessage =
|
||||
isObject &&
|
||||
"message" in error &&
|
||||
typeof error.message === "string";
|
||||
|
||||
if (hasMessage) {
|
||||
if (typeof error === "object" && error !== null) {
|
||||
if ("code" in error) {
|
||||
//TalerErrorDetail
|
||||
description = (error.hint ??
|
||||
`Error code: ${error.code}`) as TranslatedString;
|
||||
cause = {
|
||||
details: error,
|
||||
};
|
||||
} else if ("hasError" in error) {
|
||||
//HookError
|
||||
description = error.message as TranslatedString;
|
||||
if (error.type === "taler") {
|
||||
cause = {
|
||||
details: error.details,
|
||||
};
|
||||
}
|
||||
} else {
|
||||
description = `Unknown error: ${String(error)}` as TranslatedString;
|
||||
if (error instanceof BackgroundError) {
|
||||
description = (error.errorDetail.hint ??
|
||||
`Error code: ${error.errorDetail.code}`) as TranslatedString;
|
||||
cause = {
|
||||
details: error.errorDetail,
|
||||
stack: error.stack,
|
||||
};
|
||||
} else {
|
||||
description = error.message as TranslatedString;
|
||||
cause = {
|
||||
stack: error.stack,
|
||||
};
|
||||
}
|
||||
}
|
||||
} else {
|
||||
description = "" as TranslatedString;
|
||||
cause = error;
|
||||
}
|
||||
|
||||
return {
|
||||
type: "error",
|
||||
message,
|
||||
description,
|
||||
cause: error,
|
||||
cause,
|
||||
context,
|
||||
};
|
||||
}
|
||||
|
@ -22,16 +22,15 @@
|
||||
import { createContext, h, VNode } from "preact";
|
||||
import { useContext } from "preact/hooks";
|
||||
import { useWalletDevMode } from "../hooks/useWalletDevMode.js";
|
||||
import { ToggleHandler } from "../mui/handlers.js";
|
||||
|
||||
interface Type {
|
||||
devMode: boolean;
|
||||
devModeToggle: ToggleHandler;
|
||||
toggle: () => Promise<void>;
|
||||
}
|
||||
const Context = createContext<Type>({
|
||||
devMode: false,
|
||||
devModeToggle: {
|
||||
button: {},
|
||||
toggle: async () => {
|
||||
null;
|
||||
},
|
||||
});
|
||||
|
||||
@ -47,9 +46,8 @@ export const DevContextProviderForTesting = ({
|
||||
return h(Context.Provider, {
|
||||
value: {
|
||||
devMode: !!value,
|
||||
devModeToggle: {
|
||||
value,
|
||||
button: {},
|
||||
toggle: async () => {
|
||||
null;
|
||||
},
|
||||
},
|
||||
children,
|
||||
@ -58,7 +56,10 @@ export const DevContextProviderForTesting = ({
|
||||
|
||||
export const DevContextProvider = ({ children }: { children: any }): VNode => {
|
||||
const devModeToggle = useWalletDevMode();
|
||||
const value: Type = { devMode: !!devModeToggle.value, devModeToggle };
|
||||
const value: Type = {
|
||||
devMode: !!devModeToggle.value,
|
||||
toggle: devModeToggle.toggle,
|
||||
};
|
||||
//support for function as children, useful for getting the value right away
|
||||
children =
|
||||
children.length === 1 && typeof children === "function"
|
||||
|
@ -16,7 +16,7 @@
|
||||
|
||||
import { Amounts } from "@gnu-taler/taler-util";
|
||||
import { WalletApiOperation } from "@gnu-taler/taler-wallet-core";
|
||||
import { alertFromError } from "../../context/alert.js";
|
||||
import { alertFromError, useAlertContext } from "../../context/alert.js";
|
||||
import { useBackendContext } from "../../context/backend.js";
|
||||
import { useTranslationContext } from "../../context/translation.js";
|
||||
import { useAsyncAsHook } from "../../hooks/useAsyncAsHook.js";
|
||||
@ -29,6 +29,7 @@ export function useComponentState({
|
||||
onSuccess,
|
||||
}: Props): State {
|
||||
const api = useBackendContext();
|
||||
const { pushAlertOnError } = useAlertContext();
|
||||
const info = useAsyncAsHook(async () => {
|
||||
if (!talerDepositUri) throw Error("ERROR_NO-URI-FOR-DEPOSIT");
|
||||
if (!amountStr) throw Error("ERROR_NO-AMOUNT-FOR-DEPOSIT");
|
||||
@ -66,7 +67,7 @@ export function useComponentState({
|
||||
status: "ready",
|
||||
error: undefined,
|
||||
confirm: {
|
||||
onClick: doDeposit,
|
||||
onClick: pushAlertOnError(doDeposit),
|
||||
},
|
||||
fee: Amounts.sub(deposit.totalDepositCost, deposit.effectiveDepositAmount)
|
||||
.amount,
|
||||
|
@ -20,14 +20,14 @@
|
||||
*/
|
||||
|
||||
import { Amounts } from "@gnu-taler/taler-util";
|
||||
import { createExample } from "../../test-utils.js";
|
||||
import { tests } from "@gnu-taler/web-util/lib/index.browser";
|
||||
import { ReadyView } from "./views.js";
|
||||
|
||||
export default {
|
||||
title: "deposit",
|
||||
};
|
||||
|
||||
export const Ready = createExample(ReadyView, {
|
||||
export const Ready = tests.createExample(ReadyView, {
|
||||
status: "ready",
|
||||
confirm: {},
|
||||
cost: Amounts.parseOrThrow("EUR:1.2"),
|
||||
|
@ -55,7 +55,7 @@ describe("Deposit CTA states", () => {
|
||||
if (!error) expect.fail();
|
||||
// if (!error.hasError) expect.fail();
|
||||
// if (error.operational) expect.fail();
|
||||
expect(error.cause?.message).eq("ERROR_NO-URI-FOR-DEPOSIT");
|
||||
expect(error.description).eq("ERROR_NO-URI-FOR-DEPOSIT");
|
||||
},
|
||||
],
|
||||
TestingContext,
|
||||
|
@ -15,15 +15,11 @@
|
||||
*/
|
||||
|
||||
/* eslint-disable react-hooks/rules-of-hooks */
|
||||
import {
|
||||
Amounts,
|
||||
TalerErrorDetail,
|
||||
TalerProtocolTimestamp,
|
||||
} from "@gnu-taler/taler-util";
|
||||
import { Amounts, TalerProtocolTimestamp } from "@gnu-taler/taler-util";
|
||||
import { TalerError, WalletApiOperation } from "@gnu-taler/taler-wallet-core";
|
||||
import { isFuture, parse } from "date-fns";
|
||||
import { useState } from "preact/hooks";
|
||||
import { alertFromError } from "../../context/alert.js";
|
||||
import { alertFromError, useAlertContext } from "../../context/alert.js";
|
||||
import { useBackendContext } from "../../context/backend.js";
|
||||
import { useTranslationContext } from "../../context/translation.js";
|
||||
import { useAsyncAsHook } from "../../hooks/useAsyncAsHook.js";
|
||||
@ -71,6 +67,7 @@ export function useComponentState({
|
||||
return () => {
|
||||
const [subject, setSubject] = useState<string | undefined>();
|
||||
const [timestamp, setTimestamp] = useState<string | undefined>();
|
||||
const { pushAlertOnError } = useAlertContext();
|
||||
|
||||
const selectedExchange = useSelectedExchange({
|
||||
currency: amount.currency,
|
||||
@ -144,7 +141,7 @@ export function useComponentState({
|
||||
|
||||
async function accept(): Promise<void> {
|
||||
if (!subject || !purse_expiration) return;
|
||||
try {
|
||||
|
||||
const resp = await api.wallet.call(
|
||||
WalletApiOperation.InitiatePeerPullPayment,
|
||||
{
|
||||
@ -158,13 +155,6 @@ export function useComponentState({
|
||||
);
|
||||
|
||||
onSuccess(resp.transactionId);
|
||||
} catch (e) {
|
||||
if (e instanceof TalerError) {
|
||||
// setOperationError(e.errorDetail);
|
||||
}
|
||||
console.error(e);
|
||||
throw Error("error trying to accept");
|
||||
}
|
||||
}
|
||||
const unableToCreate =
|
||||
!subject || Amounts.isZero(amount) || !purse_expiration;
|
||||
@ -179,22 +169,22 @@ export function useComponentState({
|
||||
? "Can't be empty"
|
||||
: undefined,
|
||||
value: subject ?? "",
|
||||
onInput: async (e) => setSubject(e),
|
||||
onInput: pushAlertOnError(async (e) => setSubject(e)),
|
||||
},
|
||||
expiration: {
|
||||
error: timestampError,
|
||||
value: timestamp === undefined ? "" : timestamp,
|
||||
onInput: async (e) => {
|
||||
onInput: pushAlertOnError(async (e) => {
|
||||
setTimestamp(e);
|
||||
},
|
||||
}),
|
||||
},
|
||||
doSelectExchange: selectedExchange.doSelect,
|
||||
exchangeUrl: exchange.exchangeBaseUrl,
|
||||
create: {
|
||||
onClick: unableToCreate ? undefined : accept,
|
||||
onClick: unableToCreate ? undefined : pushAlertOnError(accept),
|
||||
},
|
||||
cancel: {
|
||||
onClick: onClose,
|
||||
onClick: pushAlertOnError(onClose),
|
||||
},
|
||||
requestAmount,
|
||||
toBeReceived,
|
||||
|
@ -19,14 +19,15 @@
|
||||
* @author Sebastian Javier Marchano (sebasjm)
|
||||
*/
|
||||
|
||||
import { createExample } from "../../test-utils.js";
|
||||
import { tests } from "@gnu-taler/web-util/lib/index.browser";
|
||||
import { nullFunction } from "../../mui/handlers.js";
|
||||
import { ReadyView } from "./views.js";
|
||||
|
||||
export default {
|
||||
title: "invoice create",
|
||||
};
|
||||
|
||||
export const Ready = createExample(ReadyView, {
|
||||
export const Ready = tests.createExample(ReadyView, {
|
||||
requestAmount: {
|
||||
currency: "ARS",
|
||||
value: 1,
|
||||
@ -45,9 +46,7 @@ export const Ready = createExample(ReadyView, {
|
||||
exchangeUrl: "https://exchange.taler.ar",
|
||||
subject: {
|
||||
value: "some subject",
|
||||
onInput: async () => {
|
||||
null;
|
||||
},
|
||||
onInput: nullFunction,
|
||||
},
|
||||
create: {},
|
||||
});
|
||||
|
@ -61,7 +61,6 @@ export namespace State {
|
||||
goToWalletManualWithdraw: (currency: string) => Promise<void>;
|
||||
summary: string | undefined;
|
||||
expiration: AbsoluteTime | undefined;
|
||||
operationError?: TalerErrorDetail;
|
||||
payStatus: PreparePayResult;
|
||||
}
|
||||
|
||||
|
@ -25,10 +25,11 @@ import {
|
||||
} from "@gnu-taler/taler-util";
|
||||
import { TalerError, WalletApiOperation } from "@gnu-taler/taler-wallet-core";
|
||||
import { useEffect, useState } from "preact/hooks";
|
||||
import { alertFromError } from "../../context/alert.js";
|
||||
import { alertFromError, useAlertContext } from "../../context/alert.js";
|
||||
import { useBackendContext } from "../../context/backend.js";
|
||||
import { useTranslationContext } from "../../context/translation.js";
|
||||
import { useAsyncAsHook } from "../../hooks/useAsyncAsHook.js";
|
||||
import { withSafe } from "../../mui/handlers.js";
|
||||
import { Props, State } from "./index.js";
|
||||
|
||||
export function useComponentState({
|
||||
@ -39,6 +40,7 @@ export function useComponentState({
|
||||
}: Props): State {
|
||||
const api = useBackendContext();
|
||||
const { i18n } = useTranslationContext();
|
||||
const { pushAlertOnError } = useAlertContext();
|
||||
const hook = useAsyncAsHook(async () => {
|
||||
const p2p = await api.wallet.call(WalletApiOperation.CheckPeerPullPayment, {
|
||||
talerUri: talerPayPullUri,
|
||||
@ -54,10 +56,6 @@ export function useComponentState({
|
||||
),
|
||||
);
|
||||
|
||||
const [operationError, setOperationError] = useState<
|
||||
TalerErrorDetail | undefined
|
||||
>(undefined);
|
||||
|
||||
if (!hook) {
|
||||
return {
|
||||
status: "loading",
|
||||
@ -109,18 +107,17 @@ export function useComponentState({
|
||||
contractTerms: {} as any,
|
||||
amountRaw: hook.response.p2p.amount,
|
||||
noncePriv: "",
|
||||
};
|
||||
} as any; //FIXME: check this interface with new values
|
||||
|
||||
const baseResult = {
|
||||
uri: talerPayPullUri,
|
||||
cancel: {
|
||||
onClick: onClose,
|
||||
onClick: pushAlertOnError(onClose),
|
||||
},
|
||||
amount,
|
||||
goToWalletManualWithdraw,
|
||||
summary,
|
||||
expiration: expiration ? AbsoluteTime.fromTimestamp(expiration) : undefined,
|
||||
operationError,
|
||||
};
|
||||
|
||||
if (!foundBalance) {
|
||||
@ -148,7 +145,6 @@ export function useComponentState({
|
||||
}
|
||||
|
||||
async function accept(): Promise<void> {
|
||||
try {
|
||||
const resp = await api.wallet.call(
|
||||
WalletApiOperation.AcceptPeerPullPayment,
|
||||
{
|
||||
@ -156,13 +152,6 @@ export function useComponentState({
|
||||
},
|
||||
);
|
||||
onSuccess(resp.transactionId);
|
||||
} catch (e) {
|
||||
if (e instanceof TalerError) {
|
||||
setOperationError(e.errorDetail);
|
||||
}
|
||||
console.error(e);
|
||||
throw Error("error trying to accept");
|
||||
}
|
||||
}
|
||||
|
||||
return {
|
||||
@ -172,7 +161,7 @@ export function useComponentState({
|
||||
payStatus: paymentPossible,
|
||||
balance: foundAmount,
|
||||
accept: {
|
||||
onClick: accept,
|
||||
onClick: pushAlertOnError(accept),
|
||||
},
|
||||
};
|
||||
}
|
||||
|
@ -20,14 +20,14 @@
|
||||
*/
|
||||
|
||||
import { PreparePayResult, PreparePayResultType } from "@gnu-taler/taler-util";
|
||||
import { createExample } from "../../test-utils.js";
|
||||
import { tests } from "@gnu-taler/web-util/lib/index.browser";
|
||||
import { ReadyView } from "./views.js";
|
||||
|
||||
export default {
|
||||
title: "invoice payment",
|
||||
};
|
||||
|
||||
export const Ready = createExample(ReadyView, {
|
||||
export const Ready = tests.createExample(ReadyView, {
|
||||
amount: {
|
||||
currency: "ARS",
|
||||
value: 1,
|
||||
|
@ -16,11 +16,10 @@
|
||||
|
||||
import { Fragment, h, VNode } from "preact";
|
||||
import { Amount } from "../../components/Amount.js";
|
||||
import { ErrorTalerOperation } from "../../components/ErrorTalerOperation.js";
|
||||
import { LogoHeader } from "../../components/LogoHeader.js";
|
||||
import { Part } from "../../components/Part.js";
|
||||
import { PaymentButtons } from "../../components/PaymentButtons.js";
|
||||
import { Link, SubTitle, WalletAction } from "../../components/styled/index.js";
|
||||
import { SubTitle, WalletAction } from "../../components/styled/index.js";
|
||||
import { Time } from "../../components/Time.js";
|
||||
import { useTranslationContext } from "../../context/translation.js";
|
||||
import { State } from "./index.js";
|
||||
@ -29,29 +28,14 @@ export function ReadyView(
|
||||
state: State.Ready | State.NoBalanceForCurrency | State.NoEnoughBalance,
|
||||
): VNode {
|
||||
const { i18n } = useTranslationContext();
|
||||
const {
|
||||
operationError,
|
||||
summary,
|
||||
amount,
|
||||
expiration,
|
||||
uri,
|
||||
status,
|
||||
balance,
|
||||
payStatus,
|
||||
cancel,
|
||||
} = state;
|
||||
const { summary, amount, expiration, uri, status, balance, payStatus } =
|
||||
state;
|
||||
return (
|
||||
<WalletAction>
|
||||
<LogoHeader />
|
||||
<SubTitle>
|
||||
<i18n.Translate>Digital invoice</i18n.Translate>
|
||||
</SubTitle>
|
||||
{operationError && (
|
||||
<ErrorTalerOperation
|
||||
title={i18n.str`Could not finish the payment operation`}
|
||||
error={operationError}
|
||||
/>
|
||||
)}
|
||||
<section style={{ textAlign: "left" }}>
|
||||
<Part title={i18n.str`Subject`} text={<div>{summary}</div>} />
|
||||
<Part title={i18n.str`Amount`} text={<Amount value={amount} />} />
|
||||
|
@ -19,11 +19,10 @@ import {
|
||||
ConfirmPayResultType,
|
||||
NotificationType,
|
||||
PreparePayResultType,
|
||||
TalerErrorCode,
|
||||
} from "@gnu-taler/taler-util";
|
||||
import { TalerError, WalletApiOperation } from "@gnu-taler/taler-wallet-core";
|
||||
import { useEffect, useState } from "preact/hooks";
|
||||
import { alertFromError } from "../../context/alert.js";
|
||||
import { WalletApiOperation } from "@gnu-taler/taler-wallet-core";
|
||||
import { useEffect } from "preact/hooks";
|
||||
import { alertFromError, useAlertContext } from "../../context/alert.js";
|
||||
import { useBackendContext } from "../../context/backend.js";
|
||||
import { useTranslationContext } from "../../context/translation.js";
|
||||
import { useAsyncAsHook } from "../../hooks/useAsyncAsHook.js";
|
||||
@ -36,7 +35,7 @@ export function useComponentState({
|
||||
goToWalletManualWithdraw,
|
||||
onSuccess,
|
||||
}: Props): State {
|
||||
const [payErrMsg, setPayErrMsg] = useState<TalerError | undefined>(undefined);
|
||||
const { pushAlertOnError } = useAlertContext();
|
||||
const api = useBackendContext();
|
||||
const { i18n } = useTranslationContext();
|
||||
|
||||
@ -142,23 +141,27 @@ export function useComponentState({
|
||||
}
|
||||
|
||||
async function doPayment(): Promise<void> {
|
||||
try {
|
||||
if (payStatus.status !== "payment-possible") {
|
||||
throw TalerError.fromUncheckedDetail({
|
||||
code: TalerErrorCode.GENERIC_CLIENT_INTERNAL_ERROR,
|
||||
hint: `payment is not possible: ${payStatus.status}`,
|
||||
});
|
||||
}
|
||||
// if (payStatus.status !== "payment-possible") {
|
||||
// throw TalerError.fromUncheckedDetail({
|
||||
// code: TalerErrorCode.GENERIC_CLIENT_INTERNAL_ERROR,
|
||||
// when: new Date().toISOString(),
|
||||
// hint: `payment is not possible: ${payStatus.status}`,
|
||||
// });
|
||||
// }
|
||||
const res = await api.wallet.call(WalletApiOperation.ConfirmPay, {
|
||||
proposalId: payStatus.proposalId,
|
||||
});
|
||||
// handle confirm pay
|
||||
if (res.type !== ConfirmPayResultType.Done) {
|
||||
throw TalerError.fromUncheckedDetail({
|
||||
code: TalerErrorCode.GENERIC_CLIENT_INTERNAL_ERROR,
|
||||
hint: `could not confirm payment`,
|
||||
payResult: res,
|
||||
});
|
||||
// throw new BackgroundError("Could not confirm payment", res.lastError)
|
||||
// // throw TalerError.fromUncheckedDetail({
|
||||
// // code: TalerErrorCode.GENERIC_CLIENT_INTERNAL_ERROR,
|
||||
// // when: new Date().toISOString(),
|
||||
// // hint: `could not confirm payment`,
|
||||
// // payResult: res,
|
||||
// // });
|
||||
onSuccess(res.transactionId);
|
||||
return;
|
||||
}
|
||||
const fu = res.contractTerms.fulfillment_url;
|
||||
if (fu) {
|
||||
@ -169,16 +172,10 @@ export function useComponentState({
|
||||
}
|
||||
}
|
||||
onSuccess(res.transactionId);
|
||||
} catch (e) {
|
||||
if (e instanceof TalerError) {
|
||||
setPayErrMsg(e);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
const payHandler: ButtonHandler = {
|
||||
onClick: payErrMsg ? undefined : doPayment,
|
||||
error: payErrMsg,
|
||||
onClick: pushAlertOnError(doPayment),
|
||||
};
|
||||
|
||||
// (payStatus.status === PreparePayResultType.PaymentPossible)
|
||||
|
@ -24,10 +24,11 @@ import {
|
||||
MerchantContractTerms as ContractTerms,
|
||||
PreparePayResultType,
|
||||
} from "@gnu-taler/taler-util";
|
||||
import merchantIcon from "../../../static-dev/merchant-icon.jpeg";
|
||||
import { createExample } from "../../test-utils.js";
|
||||
import { BaseView } from "./views.js";
|
||||
import { tests } from "@gnu-taler/web-util/lib/index.browser";
|
||||
import beer from "../../../static-dev/beer.png";
|
||||
import merchantIcon from "../../../static-dev/merchant-icon.jpeg";
|
||||
import { nullFunction } from "../../mui/handlers.js";
|
||||
import { BaseView } from "./views.js";
|
||||
|
||||
export default {
|
||||
title: "payment",
|
||||
@ -35,7 +36,7 @@ export default {
|
||||
argTypes: {},
|
||||
};
|
||||
|
||||
export const NoBalance = createExample(BaseView, {
|
||||
export const NoBalance = tests.createExample(BaseView, {
|
||||
status: "no-balance-for-currency",
|
||||
error: undefined,
|
||||
amount: Amounts.parseOrThrow("USD:10"),
|
||||
@ -44,6 +45,7 @@ export const NoBalance = createExample(BaseView, {
|
||||
uri: "",
|
||||
payStatus: {
|
||||
status: PreparePayResultType.InsufficientBalance,
|
||||
balanceDetails: {} as any,
|
||||
talerUri: "taler://pay/..",
|
||||
noncePriv: "",
|
||||
proposalId: "96YY92RQZGF3V7TJSPN4SF9549QX7BRF88Q5PYFCSBNQ0YK4RPK0",
|
||||
@ -61,7 +63,7 @@ export const NoBalance = createExample(BaseView, {
|
||||
},
|
||||
});
|
||||
|
||||
export const NoEnoughBalance = createExample(BaseView, {
|
||||
export const NoEnoughBalance = tests.createExample(BaseView, {
|
||||
status: "no-enough-balance",
|
||||
error: undefined,
|
||||
amount: Amounts.parseOrThrow("USD:10"),
|
||||
@ -74,6 +76,7 @@ export const NoEnoughBalance = createExample(BaseView, {
|
||||
uri: "",
|
||||
payStatus: {
|
||||
status: PreparePayResultType.InsufficientBalance,
|
||||
balanceDetails: {} as any,
|
||||
talerUri: "taler://pay/..",
|
||||
noncePriv: "",
|
||||
proposalId: "96YY92RQZGF3V7TJSPN4SF9549QX7BRF88Q5PYFCSBNQ0YK4RPK0",
|
||||
@ -91,7 +94,7 @@ export const NoEnoughBalance = createExample(BaseView, {
|
||||
},
|
||||
});
|
||||
|
||||
export const EnoughBalanceButRestricted = createExample(BaseView, {
|
||||
export const EnoughBalanceButRestricted = tests.createExample(BaseView, {
|
||||
status: "no-enough-balance",
|
||||
error: undefined,
|
||||
amount: Amounts.parseOrThrow("USD:10"),
|
||||
@ -104,6 +107,7 @@ export const EnoughBalanceButRestricted = createExample(BaseView, {
|
||||
uri: "",
|
||||
payStatus: {
|
||||
status: PreparePayResultType.InsufficientBalance,
|
||||
balanceDetails: {} as any,
|
||||
talerUri: "taler://pay/..",
|
||||
noncePriv: "",
|
||||
proposalId: "96YY92RQZGF3V7TJSPN4SF9549QX7BRF88Q5PYFCSBNQ0YK4RPK0",
|
||||
@ -121,7 +125,7 @@ export const EnoughBalanceButRestricted = createExample(BaseView, {
|
||||
},
|
||||
});
|
||||
|
||||
export const PaymentPossible = createExample(BaseView, {
|
||||
export const PaymentPossible = tests.createExample(BaseView, {
|
||||
status: "ready",
|
||||
error: undefined,
|
||||
amount: Amounts.parseOrThrow("USD:10"),
|
||||
@ -131,9 +135,7 @@ export const PaymentPossible = createExample(BaseView, {
|
||||
value: 11,
|
||||
},
|
||||
payHandler: {
|
||||
onClick: async () => {
|
||||
null;
|
||||
},
|
||||
onClick: nullFunction,
|
||||
},
|
||||
|
||||
uri: "taler://pay/merchant-backend.taler/2021.242-01G2X4275RBWG/?c=66BE594PDZR24744J6EQK52XM0",
|
||||
@ -162,7 +164,7 @@ export const PaymentPossible = createExample(BaseView, {
|
||||
},
|
||||
});
|
||||
|
||||
export const PaymentPossibleWithFee = createExample(BaseView, {
|
||||
export const PaymentPossibleWithFee = tests.createExample(BaseView, {
|
||||
status: "ready",
|
||||
error: undefined,
|
||||
amount: Amounts.parseOrThrow("USD:10"),
|
||||
@ -172,9 +174,7 @@ export const PaymentPossibleWithFee = createExample(BaseView, {
|
||||
value: 11,
|
||||
},
|
||||
payHandler: {
|
||||
onClick: async () => {
|
||||
null;
|
||||
},
|
||||
onClick: nullFunction,
|
||||
},
|
||||
|
||||
uri: "taler://pay/merchant-backend.taler/2021.242-01G2X4275RBWG/?c=66BE594PDZR24744J6EQK52XM0",
|
||||
@ -200,7 +200,7 @@ export const PaymentPossibleWithFee = createExample(BaseView, {
|
||||
},
|
||||
});
|
||||
|
||||
export const TicketWithAProductList = createExample(BaseView, {
|
||||
export const TicketWithAProductList = tests.createExample(BaseView, {
|
||||
status: "ready",
|
||||
error: undefined,
|
||||
amount: Amounts.parseOrThrow("USD:10"),
|
||||
@ -210,9 +210,7 @@ export const TicketWithAProductList = createExample(BaseView, {
|
||||
value: 11,
|
||||
},
|
||||
payHandler: {
|
||||
onClick: async () => {
|
||||
null;
|
||||
},
|
||||
onClick: nullFunction,
|
||||
},
|
||||
|
||||
uri: "taler://pay/merchant-backend.taler/2021.242-01G2X4275RBWG/?c=66BE594PDZR24744J6EQK52XM0",
|
||||
@ -257,7 +255,7 @@ export const TicketWithAProductList = createExample(BaseView, {
|
||||
},
|
||||
});
|
||||
|
||||
export const TicketWithShipping = createExample(BaseView, {
|
||||
export const TicketWithShipping = tests.createExample(BaseView, {
|
||||
status: "ready",
|
||||
error: undefined,
|
||||
amount: Amounts.parseOrThrow("USD:10"),
|
||||
@ -267,9 +265,7 @@ export const TicketWithShipping = createExample(BaseView, {
|
||||
value: 11,
|
||||
},
|
||||
payHandler: {
|
||||
onClick: async () => {
|
||||
null;
|
||||
},
|
||||
onClick: nullFunction,
|
||||
},
|
||||
|
||||
uri: "taler://pay/merchant-backend.taler/2021.242-01G2X4275RBWG/?c=66BE594PDZR24744J6EQK52XM0",
|
||||
@ -309,7 +305,7 @@ export const TicketWithShipping = createExample(BaseView, {
|
||||
},
|
||||
});
|
||||
|
||||
export const AlreadyConfirmedByOther = createExample(BaseView, {
|
||||
export const AlreadyConfirmedByOther = tests.createExample(BaseView, {
|
||||
status: "confirmed",
|
||||
error: undefined,
|
||||
amount: Amounts.parseOrThrow("USD:10"),
|
||||
|
@ -31,7 +31,8 @@ import {
|
||||
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 { ErrorAlert, useAlertContext } from "../../context/alert.js";
|
||||
import { nullFunction } from "../../mui/handlers.js";
|
||||
import { createWalletApiMock } from "../../test-utils.js";
|
||||
import { useComponentState } from "./state.js";
|
||||
|
||||
@ -385,8 +386,12 @@ describe("Payment CTA states", () => {
|
||||
} as ConfirmPayResult);
|
||||
|
||||
const hookBehavior = await tests.hookBehaveLikeThis(
|
||||
useComponentState,
|
||||
props,
|
||||
() => {
|
||||
const state = useComponentState(props);
|
||||
// const { alerts } = useAlertContext();
|
||||
return { ...state, alerts: {} };
|
||||
},
|
||||
{},
|
||||
[
|
||||
({ status, error }) => {
|
||||
expect(status).equals("loading");
|
||||
@ -400,22 +405,21 @@ describe("Payment CTA states", () => {
|
||||
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 },
|
||||
});
|
||||
},
|
||||
// (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"));
|
||||
|
||||
// // FIXME: check that the error is pushed to the alertContext
|
||||
// // expect(state.alerts.length).eq(1);
|
||||
// // const alert = state.alerts[0]
|
||||
// // if (alert.type !== "error") expect.fail();
|
||||
|
||||
// // expect(alert.cause.errorDetail.payResult).deep.equal({
|
||||
// // type: ConfirmPayResultType.Pending,
|
||||
// // lastError: { code: 1 },
|
||||
// // });
|
||||
// },
|
||||
],
|
||||
TestingContext,
|
||||
);
|
||||
|
@ -16,7 +16,7 @@
|
||||
|
||||
import { parseRecoveryUri } from "@gnu-taler/taler-util";
|
||||
import { WalletApiOperation } from "@gnu-taler/taler-wallet-core";
|
||||
import { Alert } from "../../context/alert.js";
|
||||
import { useAlertContext } from "../../context/alert.js";
|
||||
import { useBackendContext } from "../../context/backend.js";
|
||||
import { useTranslationContext } from "../../context/translation.js";
|
||||
import { Props, State } from "./index.js";
|
||||
@ -27,6 +27,7 @@ export function useComponentState({
|
||||
onSuccess,
|
||||
}: Props): State {
|
||||
const api = useBackendContext();
|
||||
const { pushAlertOnError } = useAlertContext();
|
||||
const { i18n } = useTranslationContext();
|
||||
if (!talerRecoveryUri) {
|
||||
return {
|
||||
@ -67,10 +68,10 @@ export function useComponentState({
|
||||
status: "ready",
|
||||
|
||||
accept: {
|
||||
onClick: recoverBackup,
|
||||
onClick: pushAlertOnError(recoverBackup),
|
||||
},
|
||||
cancel: {
|
||||
onClick: onCancel,
|
||||
onClick: pushAlertOnError(onCancel),
|
||||
},
|
||||
error: undefined,
|
||||
};
|
||||
|
@ -20,7 +20,7 @@
|
||||
*/
|
||||
|
||||
import { Amounts } from "@gnu-taler/taler-util";
|
||||
import { createExample } from "../../test-utils.js";
|
||||
import { tests } from "@gnu-taler/web-util/lib/index.browser";
|
||||
import { ReadyView } from "./views.js";
|
||||
|
||||
export default {
|
||||
|
@ -17,7 +17,7 @@
|
||||
import { Amounts, NotificationType } from "@gnu-taler/taler-util";
|
||||
import { WalletApiOperation } from "@gnu-taler/taler-wallet-core";
|
||||
import { useEffect, useState } from "preact/hooks";
|
||||
import { alertFromError } from "../../context/alert.js";
|
||||
import { alertFromError, useAlertContext } from "../../context/alert.js";
|
||||
import { useBackendContext } from "../../context/backend.js";
|
||||
import { useTranslationContext } from "../../context/translation.js";
|
||||
import { useAsyncAsHook } from "../../hooks/useAsyncAsHook.js";
|
||||
@ -31,6 +31,7 @@ export function useComponentState({
|
||||
const api = useBackendContext();
|
||||
const { i18n } = useTranslationContext();
|
||||
const [ignored, setIgnored] = useState(false);
|
||||
const { pushAlertOnError } = useAlertContext();
|
||||
|
||||
const info = useAsyncAsHook(async () => {
|
||||
if (!talerRefundUri) throw Error("ERROR_NO-URI-FOR-REFUND");
|
||||
@ -108,10 +109,10 @@ export function useComponentState({
|
||||
...baseInfo,
|
||||
orderId: info.response.refund.info.orderId,
|
||||
accept: {
|
||||
onClick: doAccept,
|
||||
onClick: pushAlertOnError(doAccept),
|
||||
},
|
||||
ignore: {
|
||||
onClick: doIgnore,
|
||||
onClick: pushAlertOnError(doIgnore),
|
||||
},
|
||||
cancel,
|
||||
};
|
||||
|
@ -21,13 +21,13 @@
|
||||
|
||||
import { Amounts } from "@gnu-taler/taler-util";
|
||||
import beer from "../../../static-dev/beer.png";
|
||||
import { createExample } from "../../test-utils.js";
|
||||
import { tests } from "@gnu-taler/web-util/lib/index.browser";
|
||||
import { IgnoredView, InProgressView, ReadyView } from "./views.js";
|
||||
export default {
|
||||
title: "refund",
|
||||
};
|
||||
|
||||
export const InProgress = createExample(InProgressView, {
|
||||
export const InProgress = tests.createExample(InProgressView, {
|
||||
status: "in-progress",
|
||||
error: undefined,
|
||||
amount: Amounts.parseOrThrow("USD:1"),
|
||||
@ -37,7 +37,7 @@ export const InProgress = createExample(InProgressView, {
|
||||
products: undefined,
|
||||
});
|
||||
|
||||
export const Ready = createExample(ReadyView, {
|
||||
export const Ready = tests.createExample(ReadyView, {
|
||||
status: "ready",
|
||||
error: undefined,
|
||||
accept: {},
|
||||
@ -51,7 +51,7 @@ export const Ready = createExample(ReadyView, {
|
||||
orderId: "abcdef",
|
||||
});
|
||||
|
||||
export const WithAProductList = createExample(ReadyView, {
|
||||
export const WithAProductList = tests.createExample(ReadyView, {
|
||||
status: "ready",
|
||||
error: undefined,
|
||||
accept: {},
|
||||
@ -75,7 +75,7 @@ export const WithAProductList = createExample(ReadyView, {
|
||||
orderId: "abcdef",
|
||||
});
|
||||
|
||||
export const Ignored = createExample(IgnoredView, {
|
||||
export const Ignored = tests.createExample(IgnoredView, {
|
||||
status: "ignored",
|
||||
error: undefined,
|
||||
merchantName: "the merchant",
|
||||
|
@ -27,11 +27,8 @@ import {
|
||||
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,
|
||||
} from "../../test-utils.js";
|
||||
import { nullFunction } from "../../mui/handlers.js";
|
||||
import { createWalletApiMock } from "../../test-utils.js";
|
||||
import { useComponentState } from "./state.js";
|
||||
|
||||
describe("Refund CTA states", () => {
|
||||
@ -57,7 +54,7 @@ describe("Refund CTA states", () => {
|
||||
if (!error) expect.fail();
|
||||
// if (!error.hasError) expect.fail();
|
||||
// if (error.operational) expect.fail();
|
||||
expect(error.cause?.message).eq("ERROR_NO-URI-FOR-REFUND");
|
||||
expect(error.description).eq("ERROR_NO-URI-FOR-REFUND");
|
||||
},
|
||||
],
|
||||
TestingContext,
|
||||
|
@ -16,7 +16,7 @@
|
||||
|
||||
import { Amounts } from "@gnu-taler/taler-util";
|
||||
import { WalletApiOperation } from "@gnu-taler/taler-wallet-core";
|
||||
import { alertFromError } from "../../context/alert.js";
|
||||
import { alertFromError, useAlertContext } from "../../context/alert.js";
|
||||
import { useBackendContext } from "../../context/backend.js";
|
||||
import { useTranslationContext } from "../../context/translation.js";
|
||||
import { useAsyncAsHook } from "../../hooks/useAsyncAsHook.js";
|
||||
@ -29,6 +29,7 @@ export function useComponentState({
|
||||
}: Props): State {
|
||||
const api = useBackendContext();
|
||||
const { i18n } = useTranslationContext();
|
||||
const { pushAlertOnError } = useAlertContext();
|
||||
const tipInfo = useAsyncAsHook(async () => {
|
||||
if (!talerTipUri) throw Error("ERROR_NO-URI-FOR-TIP");
|
||||
const tip = await api.wallet.call(WalletApiOperation.PrepareTip, {
|
||||
@ -77,7 +78,7 @@ export function useComponentState({
|
||||
amount: Amounts.parseOrThrow(tip.tipAmountEffective),
|
||||
error: undefined,
|
||||
cancel: {
|
||||
onClick: onCancel,
|
||||
onClick: pushAlertOnError(onCancel),
|
||||
},
|
||||
};
|
||||
|
||||
@ -92,7 +93,7 @@ export function useComponentState({
|
||||
status: "ready",
|
||||
...baseInfo,
|
||||
accept: {
|
||||
onClick: doAccept,
|
||||
onClick: pushAlertOnError(doAccept),
|
||||
},
|
||||
};
|
||||
}
|
||||
|
@ -20,14 +20,14 @@
|
||||
*/
|
||||
|
||||
import { Amounts } from "@gnu-taler/taler-util";
|
||||
import { createExample } from "../../test-utils.js";
|
||||
import { tests } from "@gnu-taler/web-util/lib/index.browser";
|
||||
import { AcceptedView, ReadyView } from "./views.js";
|
||||
|
||||
export default {
|
||||
title: "tip",
|
||||
};
|
||||
|
||||
export const Accepted = createExample(AcceptedView, {
|
||||
export const Accepted = tests.createExample(AcceptedView, {
|
||||
status: "accepted",
|
||||
error: undefined,
|
||||
amount: Amounts.parseOrThrow("EUR:1"),
|
||||
@ -35,7 +35,7 @@ export const Accepted = createExample(AcceptedView, {
|
||||
merchantBaseUrl: "",
|
||||
});
|
||||
|
||||
export const Ready = createExample(ReadyView, {
|
||||
export const Ready = tests.createExample(ReadyView, {
|
||||
status: "ready",
|
||||
error: undefined,
|
||||
amount: Amounts.parseOrThrow("EUR:1"),
|
||||
|
@ -23,7 +23,8 @@ import { Amounts } 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, nullFunction } from "../../test-utils.js";
|
||||
import { nullFunction } from "../../mui/handlers.js";
|
||||
import { createWalletApiMock } from "../../test-utils.js";
|
||||
import { Props } from "./index.js";
|
||||
import { useComponentState } from "./state.js";
|
||||
|
||||
@ -48,7 +49,7 @@ describe("Tip CTA states", () => {
|
||||
({ status, error }) => {
|
||||
expect(status).equals("error");
|
||||
if (!error) expect.fail();
|
||||
expect(error.cause?.message).eq("ERROR_NO-URI-FOR-TIP");
|
||||
expect(error.description).eq("ERROR_NO-URI-FOR-TIP");
|
||||
},
|
||||
],
|
||||
TestingContext,
|
||||
|
@ -54,7 +54,6 @@ export namespace State {
|
||||
subject: TextFieldHandler;
|
||||
expiration: TextFieldHandler;
|
||||
error: undefined;
|
||||
operationError?: TalerErrorDetail;
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -22,7 +22,7 @@ import {
|
||||
import { TalerError, WalletApiOperation } from "@gnu-taler/taler-wallet-core";
|
||||
import { isFuture, parse } from "date-fns";
|
||||
import { useState } from "preact/hooks";
|
||||
import { alertFromError } from "../../context/alert.js";
|
||||
import { alertFromError, useAlertContext } from "../../context/alert.js";
|
||||
import { useBackendContext } from "../../context/backend.js";
|
||||
import { useTranslationContext } from "../../context/translation.js";
|
||||
import { useAsyncAsHook } from "../../hooks/useAsyncAsHook.js";
|
||||
@ -34,16 +34,13 @@ export function useComponentState({
|
||||
onSuccess,
|
||||
}: Props): State {
|
||||
const api = useBackendContext();
|
||||
const { pushAlertOnError } = useAlertContext();
|
||||
const amount = Amounts.parseOrThrow(amountStr);
|
||||
const { i18n } = useTranslationContext();
|
||||
|
||||
const [subject, setSubject] = useState<string | undefined>();
|
||||
const [timestamp, setTimestamp] = useState<string | undefined>();
|
||||
|
||||
const [operationError, setOperationError] = useState<
|
||||
TalerErrorDetail | undefined
|
||||
>(undefined);
|
||||
|
||||
const hook = useAsyncAsHook(async () => {
|
||||
const resp = await api.wallet.call(
|
||||
WalletApiOperation.PreparePeerPushPayment,
|
||||
@ -104,7 +101,6 @@ export function useComponentState({
|
||||
|
||||
async function accept(): Promise<void> {
|
||||
if (!subject || !purse_expiration) return;
|
||||
try {
|
||||
const resp = await api.wallet.call(
|
||||
WalletApiOperation.InitiatePeerPushPayment,
|
||||
{
|
||||
@ -116,13 +112,6 @@ export function useComponentState({
|
||||
},
|
||||
);
|
||||
onSuccess(resp.transactionId);
|
||||
} catch (e) {
|
||||
if (e instanceof TalerError) {
|
||||
setOperationError(e.errorDetail);
|
||||
}
|
||||
console.error(e);
|
||||
throw Error("error trying to accept");
|
||||
}
|
||||
}
|
||||
|
||||
const unableToCreate =
|
||||
@ -131,7 +120,7 @@ export function useComponentState({
|
||||
return {
|
||||
status: "ready",
|
||||
cancel: {
|
||||
onClick: onClose,
|
||||
onClick: pushAlertOnError(onClose),
|
||||
},
|
||||
subject: {
|
||||
error:
|
||||
@ -141,21 +130,20 @@ export function useComponentState({
|
||||
? "Can't be empty"
|
||||
: undefined,
|
||||
value: subject ?? "",
|
||||
onInput: async (e) => setSubject(e),
|
||||
onInput: pushAlertOnError(async (e) => setSubject(e)),
|
||||
},
|
||||
expiration: {
|
||||
error: timestampError,
|
||||
value: timestamp === undefined ? "" : timestamp,
|
||||
onInput: async (e) => {
|
||||
onInput: pushAlertOnError(async (e) => {
|
||||
setTimestamp(e);
|
||||
},
|
||||
}),
|
||||
},
|
||||
create: {
|
||||
onClick: unableToCreate ? undefined : accept,
|
||||
onClick: unableToCreate ? undefined : pushAlertOnError(accept),
|
||||
},
|
||||
debitAmount,
|
||||
toBeReceived,
|
||||
error: undefined,
|
||||
operationError,
|
||||
};
|
||||
}
|
||||
|
@ -19,14 +19,15 @@
|
||||
* @author Sebastian Javier Marchano (sebasjm)
|
||||
*/
|
||||
|
||||
import { createExample } from "../../test-utils.js";
|
||||
import { tests } from "@gnu-taler/web-util/lib/index.browser";
|
||||
import { nullFunction } from "../../mui/handlers.js";
|
||||
import { ReadyView } from "./views.js";
|
||||
|
||||
export default {
|
||||
title: "transfer create",
|
||||
};
|
||||
|
||||
export const Ready = createExample(ReadyView, {
|
||||
export const Ready = tests.createExample(ReadyView, {
|
||||
debitAmount: {
|
||||
currency: "ARS",
|
||||
value: 1,
|
||||
@ -44,8 +45,6 @@ export const Ready = createExample(ReadyView, {
|
||||
},
|
||||
subject: {
|
||||
value: "the subject",
|
||||
onInput: async () => {
|
||||
null;
|
||||
},
|
||||
onInput: nullFunction,
|
||||
},
|
||||
});
|
||||
|
@ -32,8 +32,6 @@ export function ReadyView({
|
||||
toBeReceived,
|
||||
debitAmount,
|
||||
create,
|
||||
operationError,
|
||||
cancel,
|
||||
}: State.Ready): VNode {
|
||||
const { i18n } = useTranslationContext();
|
||||
|
||||
@ -65,12 +63,6 @@ export function ReadyView({
|
||||
<SubTitle>
|
||||
<i18n.Translate>Digital cash transfer</i18n.Translate>
|
||||
</SubTitle>
|
||||
{operationError && (
|
||||
<ErrorTalerOperation
|
||||
title={i18n.str`Could not finish the transfer creation`}
|
||||
error={operationError}
|
||||
/>
|
||||
)}
|
||||
<section style={{ textAlign: "left" }}>
|
||||
<p>
|
||||
<TextField
|
||||
|
@ -57,7 +57,6 @@ export namespace State {
|
||||
expiration: AbsoluteTime | undefined;
|
||||
error: undefined;
|
||||
accept: ButtonHandler;
|
||||
operationError?: TalerErrorDetail;
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -22,7 +22,7 @@ import {
|
||||
} from "@gnu-taler/taler-util";
|
||||
import { TalerError, WalletApiOperation } from "@gnu-taler/taler-wallet-core";
|
||||
import { useState } from "preact/hooks";
|
||||
import { alertFromError } from "../../context/alert.js";
|
||||
import { alertFromError, useAlertContext } from "../../context/alert.js";
|
||||
import { useBackendContext } from "../../context/backend.js";
|
||||
import { useTranslationContext } from "../../context/translation.js";
|
||||
import { useAsyncAsHook } from "../../hooks/useAsyncAsHook.js";
|
||||
@ -34,15 +34,13 @@ export function useComponentState({
|
||||
onSuccess,
|
||||
}: Props): State {
|
||||
const api = useBackendContext();
|
||||
const { pushAlertOnError } = useAlertContext();
|
||||
const { i18n } = useTranslationContext();
|
||||
const hook = useAsyncAsHook(async () => {
|
||||
return await api.wallet.call(WalletApiOperation.CheckPeerPushPayment, {
|
||||
talerUri: talerPayPushUri,
|
||||
});
|
||||
}, []);
|
||||
const [operationError, setOperationError] = useState<
|
||||
TalerErrorDetail | undefined
|
||||
>(undefined);
|
||||
|
||||
if (!hook) {
|
||||
return {
|
||||
@ -74,7 +72,6 @@ export function useComponentState({
|
||||
contractTerms?.purse_expiration;
|
||||
|
||||
async function accept(): Promise<void> {
|
||||
try {
|
||||
const resp = await api.wallet.call(
|
||||
WalletApiOperation.AcceptPeerPushPayment,
|
||||
{
|
||||
@ -82,26 +79,18 @@ export function useComponentState({
|
||||
},
|
||||
);
|
||||
onSuccess(resp.transactionId);
|
||||
} catch (e) {
|
||||
if (e instanceof TalerError) {
|
||||
setOperationError(e.errorDetail);
|
||||
}
|
||||
console.error(e);
|
||||
throw Error("error trying to accept");
|
||||
}
|
||||
}
|
||||
return {
|
||||
status: "ready",
|
||||
amount: Amounts.parseOrThrow(amount),
|
||||
error: undefined,
|
||||
accept: {
|
||||
onClick: accept,
|
||||
onClick: pushAlertOnError(accept),
|
||||
},
|
||||
summary,
|
||||
expiration: expiration ? AbsoluteTime.fromTimestamp(expiration) : undefined,
|
||||
cancel: {
|
||||
onClick: onClose,
|
||||
onClick: pushAlertOnError(onClose),
|
||||
},
|
||||
operationError,
|
||||
};
|
||||
}
|
||||
|
@ -19,14 +19,14 @@
|
||||
* @author Sebastian Javier Marchano (sebasjm)
|
||||
*/
|
||||
|
||||
import { createExample } from "../../test-utils.js";
|
||||
import { tests } from "@gnu-taler/web-util/lib/index.browser";
|
||||
import { ReadyView } from "./views.js";
|
||||
|
||||
export default {
|
||||
title: "transfer pickup",
|
||||
};
|
||||
|
||||
export const Ready = createExample(ReadyView, {
|
||||
export const Ready = tests.createExample(ReadyView, {
|
||||
amount: {
|
||||
currency: "ARS",
|
||||
value: 1,
|
||||
|
@ -30,8 +30,6 @@ export function ReadyView({
|
||||
summary,
|
||||
expiration,
|
||||
amount,
|
||||
cancel,
|
||||
operationError,
|
||||
}: State.Ready): VNode {
|
||||
const { i18n } = useTranslationContext();
|
||||
return (
|
||||
@ -40,12 +38,6 @@ export function ReadyView({
|
||||
<SubTitle>
|
||||
<i18n.Translate>Digital cash transfer</i18n.Translate>
|
||||
</SubTitle>
|
||||
{operationError && (
|
||||
<ErrorTalerOperation
|
||||
title={i18n.str`Could not finish the pickup operation`}
|
||||
error={operationError}
|
||||
/>
|
||||
)}
|
||||
<section style={{ textAlign: "left" }}>
|
||||
<Part title={i18n.str`Subject`} text={<div>{summary}</div>} />
|
||||
<Part title={i18n.str`Amount`} text={<Amount value={amount} />} />
|
||||
|
@ -23,7 +23,7 @@ import {
|
||||
} from "@gnu-taler/taler-util";
|
||||
import { TalerError, WalletApiOperation } from "@gnu-taler/taler-wallet-core";
|
||||
import { useState } from "preact/hooks";
|
||||
import { alertFromError } from "../../context/alert.js";
|
||||
import { alertFromError, useAlertContext } from "../../context/alert.js";
|
||||
import { useBackendContext } from "../../context/backend.js";
|
||||
import { useTranslationContext } from "../../context/translation.js";
|
||||
import { useAsyncAsHook } from "../../hooks/useAsyncAsHook.js";
|
||||
@ -205,6 +205,7 @@ function exchangeSelectionState(
|
||||
|
||||
return () => {
|
||||
const { i18n } = useTranslationContext();
|
||||
const { pushAlertOnError } = useAlertContext();
|
||||
const [ageRestricted, setAgeRestricted] = useState(0);
|
||||
const currentExchange = selectedExchange.selected;
|
||||
const tosNeedToBeAccepted =
|
||||
@ -299,7 +300,9 @@ function exchangeSelectionState(
|
||||
? {
|
||||
list: ageRestrictionOptions,
|
||||
value: String(ageRestricted),
|
||||
onChange: async (v: string) => setAgeRestricted(parseInt(v, 10)),
|
||||
onChange: pushAlertOnError(async (v: string) =>
|
||||
setAgeRestricted(parseInt(v, 10)),
|
||||
),
|
||||
}
|
||||
: undefined;
|
||||
|
||||
@ -317,7 +320,7 @@ function exchangeSelectionState(
|
||||
onClick:
|
||||
doingWithdraw || tosNeedToBeAccepted
|
||||
? undefined
|
||||
: doWithdrawAndCheckError,
|
||||
: pushAlertOnError(doWithdrawAndCheckError),
|
||||
error: withdrawError,
|
||||
},
|
||||
onTosUpdate,
|
||||
|
@ -20,7 +20,8 @@
|
||||
*/
|
||||
|
||||
import { ExchangeListItem } from "@gnu-taler/taler-util";
|
||||
import { createExample } from "../../test-utils.js";
|
||||
import { tests } from "@gnu-taler/web-util/lib/index.browser";
|
||||
import { nullFunction } from "../../mui/handlers.js";
|
||||
// import { TermsState } from "../../utils/index.js";
|
||||
import { SuccessView } from "./views.js";
|
||||
|
||||
@ -28,28 +29,6 @@ export default {
|
||||
title: "withdraw",
|
||||
};
|
||||
|
||||
const exchangeList = {
|
||||
"exchange.demo.taler.net": "http://exchange.demo.taler.net (USD)",
|
||||
"exchange.test.taler.net": "http://exchange.test.taler.net (KUDOS)",
|
||||
};
|
||||
|
||||
const nullHandler = {
|
||||
onClick: async (): Promise<void> => {
|
||||
null;
|
||||
},
|
||||
};
|
||||
|
||||
// const normalTosState = {
|
||||
// terms: {
|
||||
// status: "accepted",
|
||||
// version: "",
|
||||
// } as TermsState,
|
||||
// onAccept: () => null,
|
||||
// onReview: () => null,
|
||||
// reviewed: false,
|
||||
// reviewing: false,
|
||||
// };
|
||||
|
||||
const ageRestrictionOptions: Record<string, string> = "6:12:18"
|
||||
.split(":")
|
||||
.reduce((p, c) => ({ ...p, [c]: `under ${c}` }), {});
|
||||
@ -61,7 +40,7 @@ const ageRestrictionSelectField = {
|
||||
value: "0",
|
||||
};
|
||||
|
||||
export const TermsOfServiceNotYetLoaded = createExample(SuccessView, {
|
||||
export const TermsOfServiceNotYetLoaded = tests.createExample(SuccessView, {
|
||||
error: undefined,
|
||||
status: "success",
|
||||
chosenAmount: {
|
||||
@ -69,7 +48,7 @@ export const TermsOfServiceNotYetLoaded = createExample(SuccessView, {
|
||||
value: 2,
|
||||
fraction: 10000000,
|
||||
},
|
||||
doWithdrawal: nullHandler,
|
||||
doWithdrawal: { onClick: nullFunction },
|
||||
currentExchange: {
|
||||
exchangeBaseUrl: "https://exchange.demo.taler.net",
|
||||
tos: {},
|
||||
@ -87,7 +66,7 @@ export const TermsOfServiceNotYetLoaded = createExample(SuccessView, {
|
||||
},
|
||||
});
|
||||
|
||||
export const WithSomeFee = createExample(SuccessView, {
|
||||
export const WithSomeFee = tests.createExample(SuccessView, {
|
||||
error: undefined,
|
||||
status: "success",
|
||||
chosenAmount: {
|
||||
@ -95,7 +74,7 @@ export const WithSomeFee = createExample(SuccessView, {
|
||||
value: 2,
|
||||
fraction: 10000000,
|
||||
},
|
||||
doWithdrawal: nullHandler,
|
||||
doWithdrawal: { onClick: nullFunction },
|
||||
currentExchange: {
|
||||
exchangeBaseUrl: "https://exchange.demo.taler.net",
|
||||
tos: {},
|
||||
@ -113,7 +92,7 @@ export const WithSomeFee = createExample(SuccessView, {
|
||||
doSelectExchange: {},
|
||||
});
|
||||
|
||||
export const WithoutFee = createExample(SuccessView, {
|
||||
export const WithoutFee = tests.createExample(SuccessView, {
|
||||
error: undefined,
|
||||
status: "success",
|
||||
chosenAmount: {
|
||||
@ -121,7 +100,7 @@ export const WithoutFee = createExample(SuccessView, {
|
||||
value: 2,
|
||||
fraction: 0,
|
||||
},
|
||||
doWithdrawal: nullHandler,
|
||||
doWithdrawal: { onClick: nullFunction },
|
||||
currentExchange: {
|
||||
exchangeBaseUrl: "https://exchange.demo.taler.net",
|
||||
tos: {},
|
||||
@ -139,7 +118,7 @@ export const WithoutFee = createExample(SuccessView, {
|
||||
},
|
||||
});
|
||||
|
||||
export const EditExchangeUntouched = createExample(SuccessView, {
|
||||
export const EditExchangeUntouched = tests.createExample(SuccessView, {
|
||||
error: undefined,
|
||||
status: "success",
|
||||
chosenAmount: {
|
||||
@ -147,7 +126,7 @@ export const EditExchangeUntouched = createExample(SuccessView, {
|
||||
value: 2,
|
||||
fraction: 10000000,
|
||||
},
|
||||
doWithdrawal: nullHandler,
|
||||
doWithdrawal: { onClick: nullFunction },
|
||||
currentExchange: {
|
||||
exchangeBaseUrl: "https://exchange.demo.taler.net",
|
||||
tos: {},
|
||||
@ -165,7 +144,7 @@ export const EditExchangeUntouched = createExample(SuccessView, {
|
||||
},
|
||||
});
|
||||
|
||||
export const EditExchangeModified = createExample(SuccessView, {
|
||||
export const EditExchangeModified = tests.createExample(SuccessView, {
|
||||
error: undefined,
|
||||
status: "success",
|
||||
chosenAmount: {
|
||||
@ -173,7 +152,7 @@ export const EditExchangeModified = createExample(SuccessView, {
|
||||
value: 2,
|
||||
fraction: 10000000,
|
||||
},
|
||||
doWithdrawal: nullHandler,
|
||||
doWithdrawal: { onClick: nullFunction },
|
||||
currentExchange: {
|
||||
exchangeBaseUrl: "https://exchange.demo.taler.net",
|
||||
tos: {},
|
||||
@ -191,7 +170,7 @@ export const EditExchangeModified = createExample(SuccessView, {
|
||||
},
|
||||
});
|
||||
|
||||
export const WithAgeRestriction = createExample(SuccessView, {
|
||||
export const WithAgeRestriction = tests.createExample(SuccessView, {
|
||||
error: undefined,
|
||||
status: "success",
|
||||
ageRestriction: ageRestrictionSelectField,
|
||||
@ -201,7 +180,7 @@ export const WithAgeRestriction = createExample(SuccessView, {
|
||||
fraction: 10000000,
|
||||
},
|
||||
doSelectExchange: {},
|
||||
doWithdrawal: nullHandler,
|
||||
doWithdrawal: { onClick: nullFunction },
|
||||
currentExchange: {
|
||||
exchangeBaseUrl: "https://exchange.demo.taler.net",
|
||||
tos: {},
|
||||
|
@ -28,7 +28,6 @@ import {
|
||||
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";
|
||||
|
||||
@ -88,7 +87,7 @@ describe("Withdraw CTA states", () => {
|
||||
if (!error) expect.fail();
|
||||
// if (!error.hasError) expect.fail();
|
||||
// if (error.operational) expect.fail();
|
||||
expect(error.cause?.message).eq("ERROR_NO-URI-FOR-WITHDRAWAL");
|
||||
expect(error.description).eq("ERROR_NO-URI-FOR-WITHDRAWAL");
|
||||
},
|
||||
],
|
||||
TestingContext,
|
||||
|
@ -18,7 +18,6 @@ import { ExchangeTosStatus } from "@gnu-taler/taler-util";
|
||||
import { Fragment, h, VNode } from "preact";
|
||||
import { useState } from "preact/hooks";
|
||||
import { Amount } from "../../components/Amount.js";
|
||||
import { ErrorTalerOperation } from "../../components/ErrorTalerOperation.js";
|
||||
import { Part } from "../../components/Part.js";
|
||||
import { QR } from "../../components/QR.js";
|
||||
import { SelectList } from "../../components/SelectList.js";
|
||||
@ -36,13 +35,6 @@ export function SuccessView(state: State.Success): VNode {
|
||||
state.currentExchange.tosStatus === ExchangeTosStatus.Accepted;
|
||||
return (
|
||||
<Fragment>
|
||||
{state.doWithdrawal.error && (
|
||||
<ErrorTalerOperation
|
||||
title={i18n.str`Could not finish the withdrawal operation`}
|
||||
error={state.doWithdrawal.error.errorDetail}
|
||||
/>
|
||||
)}
|
||||
|
||||
<section style={{ textAlign: "left" }}>
|
||||
<Part
|
||||
title={
|
||||
|
@ -16,7 +16,7 @@
|
||||
import { TalerErrorDetail } from "@gnu-taler/taler-util";
|
||||
import { TalerError } from "@gnu-taler/taler-wallet-core";
|
||||
import { useEffect, useMemo, useState } from "preact/hooks";
|
||||
import { WalletError } from "../wxApi.js";
|
||||
import { BackgroundError } from "../wxApi.js";
|
||||
|
||||
export interface HookOk<T> {
|
||||
hasError: false;
|
||||
@ -74,12 +74,12 @@ export function useAsyncAsHook<T>(
|
||||
message: e.message,
|
||||
details: e.errorDetail,
|
||||
});
|
||||
} else if (e instanceof WalletError) {
|
||||
} else if (e instanceof BackgroundError) {
|
||||
setHookResponse({
|
||||
hasError: true,
|
||||
type: "taler",
|
||||
message: e.message,
|
||||
details: e.errorDetail.errorDetail,
|
||||
details: e.errorDetail,
|
||||
});
|
||||
} else if (e instanceof Error) {
|
||||
setHookResponse({
|
||||
|
@ -14,23 +14,41 @@
|
||||
GNU Taler; see the file COPYING. If not, see <http://www.gnu.org/licenses/>
|
||||
*/
|
||||
|
||||
import { TalerError } from "@gnu-taler/taler-wallet-core";
|
||||
import { useEffect, useState } from "preact/hooks";
|
||||
import { useAlertContext } from "../context/alert.js";
|
||||
import { useBackendContext } from "../context/backend.js";
|
||||
import { ToggleHandler } from "../mui/handlers.js";
|
||||
import { platform } from "../platform/foreground.js";
|
||||
|
||||
export function useAutoOpenPermissions(): ToggleHandler {
|
||||
const api = useBackendContext();
|
||||
const { pushAlertOnError } = useAlertContext();
|
||||
const [enabled, setEnabled] = useState(false);
|
||||
const [error, setError] = useState<TalerError | undefined>();
|
||||
const toggle = async (): Promise<void> => {
|
||||
return handleAutoOpenPerm(enabled, setEnabled, api.background).catch(
|
||||
(e) => {
|
||||
setError(TalerError.fromException(e));
|
||||
},
|
||||
);
|
||||
};
|
||||
|
||||
async function handleAutoOpenPerm(): Promise<void> {
|
||||
if (!enabled) {
|
||||
// We set permissions here, since apparently FF wants this to be done
|
||||
// as the result of an input event ...
|
||||
let granted: boolean;
|
||||
try {
|
||||
granted = await platform.getPermissionsApi().requestHostPermissions();
|
||||
} catch (lastError) {
|
||||
setEnabled(false);
|
||||
throw lastError;
|
||||
}
|
||||
const res = await api.background.call("toggleHeaderListener", granted);
|
||||
setEnabled(res.newValue);
|
||||
} else {
|
||||
try {
|
||||
await api.background
|
||||
.call("toggleHeaderListener", false)
|
||||
.then((r) => setEnabled(r.newValue));
|
||||
} catch (e) {
|
||||
console.log(e);
|
||||
}
|
||||
}
|
||||
return;
|
||||
}
|
||||
|
||||
useEffect(() => {
|
||||
async function getValue(): Promise<void> {
|
||||
@ -42,40 +60,11 @@ export function useAutoOpenPermissions(): ToggleHandler {
|
||||
}
|
||||
getValue();
|
||||
}, []);
|
||||
|
||||
return {
|
||||
value: enabled,
|
||||
button: {
|
||||
onClick: toggle,
|
||||
error,
|
||||
onClick: pushAlertOnError(handleAutoOpenPerm),
|
||||
},
|
||||
};
|
||||
}
|
||||
|
||||
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
|
||||
// as the result of an input event ...
|
||||
let granted: boolean;
|
||||
try {
|
||||
granted = await platform.getPermissionsApi().requestHostPermissions();
|
||||
} catch (lastError) {
|
||||
onChange(false);
|
||||
throw lastError;
|
||||
}
|
||||
const res = await background.call("toggleHeaderListener", granted);
|
||||
onChange(res.newValue);
|
||||
} else {
|
||||
try {
|
||||
await background
|
||||
.call("toggleHeaderListener", false)
|
||||
.then((r) => onChange(r.newValue));
|
||||
} catch (e) {
|
||||
console.log(e);
|
||||
}
|
||||
}
|
||||
return;
|
||||
}
|
||||
|
@ -14,24 +14,42 @@
|
||||
GNU Taler; see the file COPYING. If not, see <http://www.gnu.org/licenses/>
|
||||
*/
|
||||
|
||||
import { TalerError } from "@gnu-taler/taler-wallet-core";
|
||||
import { useEffect, useState } from "preact/hooks";
|
||||
import { useAlertContext } from "../context/alert.js";
|
||||
import { useBackendContext } from "../context/backend.js";
|
||||
import { ToggleHandler } from "../mui/handlers.js";
|
||||
import { platform } from "../platform/foreground.js";
|
||||
|
||||
export function useClipboardPermissions(): ToggleHandler {
|
||||
const [enabled, setEnabled] = useState(false);
|
||||
const [error, setError] = useState<TalerError | undefined>();
|
||||
const api = useBackendContext();
|
||||
const { pushAlertOnError } = useAlertContext();
|
||||
|
||||
const toggle = async (): Promise<void> => {
|
||||
return handleClipboardPerm(enabled, setEnabled, api.background).catch(
|
||||
(e) => {
|
||||
setError(TalerError.fromException(e));
|
||||
},
|
||||
);
|
||||
};
|
||||
async function handleClipboardPerm(): Promise<void> {
|
||||
if (!enabled) {
|
||||
// We set permissions here, since apparently FF wants this to be done
|
||||
// as the result of an input event ...
|
||||
let granted: boolean;
|
||||
try {
|
||||
granted = await platform
|
||||
.getPermissionsApi()
|
||||
.requestClipboardPermissions();
|
||||
} catch (lastError) {
|
||||
setEnabled(false);
|
||||
throw lastError;
|
||||
}
|
||||
setEnabled(granted);
|
||||
} else {
|
||||
try {
|
||||
await api.background
|
||||
.call("toggleHeaderListener", false)
|
||||
.then((r) => setEnabled(r.newValue));
|
||||
} catch (e) {
|
||||
console.log(e);
|
||||
}
|
||||
}
|
||||
return;
|
||||
}
|
||||
|
||||
useEffect(() => {
|
||||
async function getValue(): Promise<void> {
|
||||
@ -47,38 +65,7 @@ export function useClipboardPermissions(): ToggleHandler {
|
||||
return {
|
||||
value: enabled,
|
||||
button: {
|
||||
onClick: toggle,
|
||||
error,
|
||||
onClick: pushAlertOnError(handleClipboardPerm),
|
||||
},
|
||||
};
|
||||
}
|
||||
|
||||
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
|
||||
// as the result of an input event ...
|
||||
let granted: boolean;
|
||||
try {
|
||||
granted = await platform
|
||||
.getPermissionsApi()
|
||||
.requestClipboardPermissions();
|
||||
} catch (lastError) {
|
||||
onChange(false);
|
||||
throw lastError;
|
||||
}
|
||||
onChange(granted);
|
||||
} else {
|
||||
try {
|
||||
await background
|
||||
.call("toggleHeaderListener", false)
|
||||
.then((r) => onChange(r.newValue));
|
||||
} catch (e) {
|
||||
console.log(e);
|
||||
}
|
||||
}
|
||||
return;
|
||||
}
|
||||
|
@ -16,6 +16,7 @@
|
||||
|
||||
import { ExchangeListItem } from "@gnu-taler/taler-util";
|
||||
import { useState } from "preact/hooks";
|
||||
import { useAlertContext } from "../context/alert.js";
|
||||
import { ButtonHandler } from "../mui/handlers.js";
|
||||
|
||||
type State = State.Ready | State.NoExchange | State.Selecting;
|
||||
@ -59,6 +60,7 @@ export function useSelectedExchange({
|
||||
const [selectedExchange, setSelectedExchange] = useState<string | undefined>(
|
||||
undefined,
|
||||
);
|
||||
const { pushAlertOnError } = useAlertContext();
|
||||
|
||||
if (!list.length) {
|
||||
return {
|
||||
@ -105,7 +107,7 @@ export function useSelectedExchange({
|
||||
return {
|
||||
status: "ready",
|
||||
doSelect: {
|
||||
onClick: async () => setIsSelecting(true),
|
||||
onClick: pushAlertOnError(async () => setIsSelecting(true)),
|
||||
},
|
||||
selected: found,
|
||||
};
|
||||
@ -118,7 +120,7 @@ export function useSelectedExchange({
|
||||
return {
|
||||
status: "ready",
|
||||
doSelect: {
|
||||
onClick: async () => setIsSelecting(true),
|
||||
onClick: pushAlertOnError(async () => setIsSelecting(true)),
|
||||
},
|
||||
selected: found,
|
||||
};
|
||||
@ -127,7 +129,7 @@ export function useSelectedExchange({
|
||||
return {
|
||||
status: "ready",
|
||||
doSelect: {
|
||||
onClick: async () => setIsSelecting(true),
|
||||
onClick: pushAlertOnError(async () => setIsSelecting(true)),
|
||||
},
|
||||
selected: listCurrency[0],
|
||||
};
|
||||
|
@ -13,11 +13,11 @@
|
||||
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/>
|
||||
*/
|
||||
import { useTalerActionURL } from "./useTalerActionURL.js";
|
||||
import { mountHook } from "../test-utils.js";
|
||||
import { IoCProviderForTesting } from "../context/iocContext.js";
|
||||
import { h, VNode } from "preact";
|
||||
import { expect } from "chai";
|
||||
import { h, VNode } from "preact";
|
||||
import { IoCProviderForTesting } from "../context/iocContext.js";
|
||||
import { useTalerActionURL } from "./useTalerActionURL.js";
|
||||
import { tests } from "@gnu-taler/web-util/lib/index.browser";
|
||||
|
||||
describe("useTalerActionURL hook", () => {
|
||||
it("should be set url to undefined when dismiss", async () => {
|
||||
@ -31,32 +31,28 @@ describe("useTalerActionURL hook", () => {
|
||||
});
|
||||
};
|
||||
|
||||
const { pullLastResultOrThrow, waitForStateUpdate, assertNoPendingUpdate } =
|
||||
mountHook(useTalerActionURL, ctx);
|
||||
|
||||
{
|
||||
const [url] = pullLastResultOrThrow();
|
||||
const hookBehavior = await tests.hookBehaveLikeThis(
|
||||
useTalerActionURL,
|
||||
{},
|
||||
[
|
||||
([url]) => {
|
||||
expect(url).undefined;
|
||||
}
|
||||
|
||||
expect(await waitForStateUpdate()).true;
|
||||
|
||||
{
|
||||
const [url, setDismissed] = pullLastResultOrThrow();
|
||||
},
|
||||
([url, setDismissed]) => {
|
||||
expect(url).deep.equals({
|
||||
location: "clipboard",
|
||||
uri: "qwe",
|
||||
});
|
||||
setDismissed(true);
|
||||
}
|
||||
|
||||
expect(await waitForStateUpdate()).true;
|
||||
|
||||
{
|
||||
const [url] = pullLastResultOrThrow();
|
||||
},
|
||||
([url]) => {
|
||||
if (url !== undefined) throw Error("invalid");
|
||||
expect(url).undefined;
|
||||
}
|
||||
await assertNoPendingUpdate();
|
||||
},
|
||||
],
|
||||
ctx,
|
||||
);
|
||||
|
||||
expect(hookBehavior).deep.equal({ result: "ok" });
|
||||
});
|
||||
});
|
||||
|
@ -14,22 +14,29 @@
|
||||
GNU Taler; see the file COPYING. If not, see <http://www.gnu.org/licenses/>
|
||||
*/
|
||||
|
||||
import { useState, useEffect } from "preact/hooks";
|
||||
import { ToggleHandler } from "../mui/handlers.js";
|
||||
import { TalerError, WalletApiOperation } from "@gnu-taler/taler-wallet-core";
|
||||
import { WalletApiOperation } from "@gnu-taler/taler-wallet-core";
|
||||
import { useEffect, useState } from "preact/hooks";
|
||||
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, api).catch((e) => {
|
||||
setError(TalerError.fromException(e));
|
||||
});
|
||||
type Result = {
|
||||
value: boolean | undefined;
|
||||
toggle: () => Promise<void>;
|
||||
};
|
||||
|
||||
export function useWalletDevMode(): Result {
|
||||
const [enabled, setEnabled] = useState<undefined | boolean>(undefined);
|
||||
const api = useBackendContext();
|
||||
// const { pushAlertOnError } = useAlertContext();
|
||||
|
||||
async function handleOpen(): Promise<void> {
|
||||
const nextValue = !enabled;
|
||||
await api.wallet.call(WalletApiOperation.SetDevMode, {
|
||||
devModeEnabled: nextValue,
|
||||
});
|
||||
setEnabled(nextValue);
|
||||
return;
|
||||
}
|
||||
|
||||
useEffect(() => {
|
||||
async function getValue(): Promise<void> {
|
||||
const res = await api.wallet.call(WalletApiOperation.GetVersion, {});
|
||||
@ -37,24 +44,9 @@ export function useWalletDevMode(): ToggleHandler {
|
||||
}
|
||||
getValue();
|
||||
}, []);
|
||||
|
||||
return {
|
||||
value: enabled,
|
||||
button: {
|
||||
onClick: enabled === undefined ? undefined : toggle,
|
||||
error,
|
||||
},
|
||||
toggle: handleOpen,
|
||||
};
|
||||
}
|
||||
|
||||
async function handleOpen(
|
||||
currentValue: undefined | boolean,
|
||||
onChange: (value: boolean) => void,
|
||||
api: ReturnType<typeof useBackendContext>,
|
||||
): Promise<void> {
|
||||
const nextValue = !currentValue;
|
||||
await api.wallet.call(WalletApiOperation.SetDevMode, {
|
||||
devModeEnabled: nextValue,
|
||||
});
|
||||
onChange(nextValue);
|
||||
return;
|
||||
}
|
||||
|
@ -14,23 +14,51 @@
|
||||
GNU Taler; see the file COPYING. If not, see <http://www.gnu.org/licenses/>
|
||||
*/
|
||||
import { AmountJson } from "@gnu-taler/taler-util";
|
||||
import { TalerError } from "@gnu-taler/taler-wallet-core";
|
||||
|
||||
export interface TextFieldHandler {
|
||||
onInput?: (value: string) => Promise<void>;
|
||||
onInput?: SafeHandler<string>;
|
||||
value: string;
|
||||
error?: string;
|
||||
}
|
||||
|
||||
export interface AmountFieldHandler {
|
||||
onInput?: (value: AmountJson) => Promise<void>;
|
||||
onInput?: SafeHandler<AmountJson>;
|
||||
value: AmountJson;
|
||||
error?: string;
|
||||
}
|
||||
|
||||
declare const __safe_handler: unique symbol;
|
||||
export type SafeHandler<T> = {
|
||||
<Req extends T>(req: Req): Promise<void>;
|
||||
(): Promise<void>;
|
||||
[__safe_handler]: true;
|
||||
};
|
||||
|
||||
export function withSafe<T>(
|
||||
handler: (p: T) => Promise<void>,
|
||||
onError: (e: Error) => void,
|
||||
): SafeHandler<T> {
|
||||
const sh = async function (p: T): Promise<void> {
|
||||
try {
|
||||
await handler(p);
|
||||
} catch (e) {
|
||||
if (e instanceof Error) {
|
||||
onError(e);
|
||||
} else {
|
||||
onError(new Error(String(e)));
|
||||
}
|
||||
}
|
||||
};
|
||||
return sh as SafeHandler<T>;
|
||||
}
|
||||
|
||||
export const nullFunction = async function (): Promise<void> {
|
||||
//do nothing
|
||||
} as SafeHandler<void>;
|
||||
|
||||
export interface ButtonHandler {
|
||||
onClick?: () => Promise<void>;
|
||||
error?: TalerError;
|
||||
onClick?: SafeHandler<void>;
|
||||
// error?: TalerError;
|
||||
}
|
||||
|
||||
export interface ToggleHandler {
|
||||
@ -39,7 +67,7 @@ export interface ToggleHandler {
|
||||
}
|
||||
|
||||
export interface SelectFieldHandler {
|
||||
onChange?: (value: string) => Promise<void>;
|
||||
onChange?: SafeHandler<string>;
|
||||
error?: string;
|
||||
value: string;
|
||||
isDirty?: boolean;
|
||||
|
@ -23,10 +23,10 @@
|
||||
import { createHashHistory } from "history";
|
||||
import { ComponentChildren, Fragment, h, VNode } from "preact";
|
||||
import Router, { route, Route } from "preact-router";
|
||||
import { Match } from "preact-router/match";
|
||||
import { useEffect, useState } from "preact/hooks";
|
||||
import PendingTransactions from "../components/PendingTransactions.js";
|
||||
import { PopupBox } from "../components/styled/index.js";
|
||||
import { AlertProvider } from "../context/alert.js";
|
||||
import { DevContextProvider } from "../context/devContext.js";
|
||||
import { IoCProviderForRuntime } from "../context/iocContext.js";
|
||||
import {
|
||||
@ -34,7 +34,7 @@ import {
|
||||
useTranslationContext,
|
||||
} from "../context/translation.js";
|
||||
import { useTalerActionURL } from "../hooks/useTalerActionURL.js";
|
||||
import { PopupNavBarOptions, Pages, PopupNavBar } from "../NavigationBar.js";
|
||||
import { Pages, PopupNavBar, PopupNavBarOptions } from "../NavigationBar.js";
|
||||
import { platform } from "../platform/foreground.js";
|
||||
import { BackupPage } from "../wallet/BackupPage.js";
|
||||
import { ProviderDetailPage } from "../wallet/ProviderDetailPage.js";
|
||||
@ -219,7 +219,9 @@ function PopupTemplate({
|
||||
<PendingTransactions goToTransaction={goToTransaction} />
|
||||
) : undefined}
|
||||
<PopupNavBar path={path} />
|
||||
<PopupBox>{children}</PopupBox>
|
||||
<PopupBox>
|
||||
<AlertProvider>{children}</AlertProvider>
|
||||
</PopupBox>
|
||||
</Fragment>
|
||||
);
|
||||
}
|
||||
|
@ -19,19 +19,19 @@
|
||||
* @author Sebastian Javier Marchano (sebasjm)
|
||||
*/
|
||||
|
||||
import { createExample } from "../test-utils.js";
|
||||
import { tests } from "@gnu-taler/web-util/lib/index.browser";
|
||||
import { BalanceView as TestedComponent } from "./BalancePage.js";
|
||||
|
||||
export default {
|
||||
title: "balance",
|
||||
};
|
||||
|
||||
export const EmptyBalance = createExample(TestedComponent, {
|
||||
export const EmptyBalance = tests.createExample(TestedComponent, {
|
||||
balances: [],
|
||||
goToWalletManualWithdraw: {},
|
||||
});
|
||||
|
||||
export const SomeCoins = createExample(TestedComponent, {
|
||||
export const SomeCoins = tests.createExample(TestedComponent, {
|
||||
balances: [
|
||||
{
|
||||
available: "USD:10.5",
|
||||
@ -45,7 +45,7 @@ export const SomeCoins = createExample(TestedComponent, {
|
||||
goToWalletManualWithdraw: {},
|
||||
});
|
||||
|
||||
export const SomeCoinsInTreeCurrencies = createExample(TestedComponent, {
|
||||
export const SomeCoinsInTreeCurrencies = tests.createExample(TestedComponent, {
|
||||
balances: [
|
||||
{
|
||||
available: "EUR:1",
|
||||
@ -73,7 +73,7 @@ export const SomeCoinsInTreeCurrencies = createExample(TestedComponent, {
|
||||
addAction: {},
|
||||
});
|
||||
|
||||
export const NoCoinsInTreeCurrencies = createExample(TestedComponent, {
|
||||
export const NoCoinsInTreeCurrencies = tests.createExample(TestedComponent, {
|
||||
balances: [
|
||||
{
|
||||
available: "EUR:3",
|
||||
@ -101,7 +101,7 @@ export const NoCoinsInTreeCurrencies = createExample(TestedComponent, {
|
||||
addAction: {},
|
||||
});
|
||||
|
||||
export const SomeCoinsInFiveCurrencies = createExample(TestedComponent, {
|
||||
export const SomeCoinsInFiveCurrencies = tests.createExample(TestedComponent, {
|
||||
balances: [
|
||||
{
|
||||
available: "USD:0",
|
||||
|
@ -22,7 +22,11 @@ import { BalanceTable } from "../components/BalanceTable.js";
|
||||
import { ErrorAlertView } from "../components/CurrentAlerts.js";
|
||||
import { Loading } from "../components/Loading.js";
|
||||
import { MultiActionButton } from "../components/MultiActionButton.js";
|
||||
import { alertFromError, ErrorAlert } from "../context/alert.js";
|
||||
import {
|
||||
alertFromError,
|
||||
ErrorAlert,
|
||||
useAlertContext,
|
||||
} from "../context/alert.js";
|
||||
import { useBackendContext } from "../context/backend.js";
|
||||
import { useTranslationContext } from "../context/translation.js";
|
||||
import { useAsyncAsHook } from "../hooks/useAsyncAsHook.js";
|
||||
@ -75,6 +79,7 @@ function useComponentState({
|
||||
}: Props): State {
|
||||
const api = useBackendContext();
|
||||
const { i18n } = useTranslationContext();
|
||||
const { pushAlertOnError } = useAlertContext();
|
||||
const [addingAction, setAddingAction] = useState(false);
|
||||
const state = useAsyncAsHook(() =>
|
||||
api.wallet.call(WalletApiOperation.GetBalances, {}),
|
||||
@ -104,7 +109,7 @@ function useComponentState({
|
||||
status: "action",
|
||||
error: undefined,
|
||||
cancel: {
|
||||
onClick: async () => setAddingAction(false),
|
||||
onClick: pushAlertOnError(async () => setAddingAction(false)),
|
||||
},
|
||||
};
|
||||
}
|
||||
@ -113,10 +118,10 @@ function useComponentState({
|
||||
error: undefined,
|
||||
balances: state.response.balances,
|
||||
addAction: {
|
||||
onClick: async () => setAddingAction(true),
|
||||
onClick: pushAlertOnError(async () => setAddingAction(true)),
|
||||
},
|
||||
goToWalletManualWithdraw: {
|
||||
onClick: goToWalletManualWithdraw,
|
||||
onClick: pushAlertOnError(goToWalletManualWithdraw),
|
||||
},
|
||||
goToWalletDeposit,
|
||||
goToWalletHistory,
|
||||
|
@ -19,33 +19,33 @@
|
||||
* @author Sebastian Javier Marchano (sebasjm)
|
||||
*/
|
||||
|
||||
import { createExample } from "../test-utils.js";
|
||||
import { tests } from "@gnu-taler/web-util/lib/index.browser";
|
||||
import { TalerActionFound as TestedComponent } from "./TalerActionFound.js";
|
||||
|
||||
export default {
|
||||
title: "TalerActionFound",
|
||||
};
|
||||
|
||||
export const PayAction = createExample(TestedComponent, {
|
||||
export const PayAction = tests.createExample(TestedComponent, {
|
||||
url: "taler://pay/something",
|
||||
});
|
||||
|
||||
export const WithdrawalAction = createExample(TestedComponent, {
|
||||
export const WithdrawalAction = tests.createExample(TestedComponent, {
|
||||
url: "taler://withdraw/something",
|
||||
});
|
||||
|
||||
export const TipAction = createExample(TestedComponent, {
|
||||
export const TipAction = tests.createExample(TestedComponent, {
|
||||
url: "taler://tip/something",
|
||||
});
|
||||
|
||||
export const NotifyAction = createExample(TestedComponent, {
|
||||
export const NotifyAction = tests.createExample(TestedComponent, {
|
||||
url: "taler://notify-reserve/something",
|
||||
});
|
||||
|
||||
export const RefundAction = createExample(TestedComponent, {
|
||||
export const RefundAction = tests.createExample(TestedComponent, {
|
||||
url: "taler://refund/something",
|
||||
});
|
||||
|
||||
export const InvalidAction = createExample(TestedComponent, {
|
||||
export const InvalidAction = tests.createExample(TestedComponent, {
|
||||
url: "taler://something/asd",
|
||||
});
|
||||
|
@ -20,15 +20,17 @@
|
||||
*/
|
||||
import { setupI18n } from "@gnu-taler/taler-util";
|
||||
import { parseGroupImport } from "@gnu-taler/web-util/lib/index.browser";
|
||||
import { setupPlatform } from "./platform/foreground.js";
|
||||
import chromeAPI from "./platform/chrome.js";
|
||||
import { renderNodeOrBrowser } from "./test-utils.js";
|
||||
import { setupPlatform } from "./platform/foreground.js";
|
||||
|
||||
import * as components from "./components/index.stories.js";
|
||||
import * as cta from "./cta/index.stories.js";
|
||||
import * as mui from "./mui/index.stories.js";
|
||||
import * as popup from "./popup/index.stories.js";
|
||||
import * as wallet from "./wallet/index.stories.js";
|
||||
import { renderNodeOrBrowser } from "./test-utils.js";
|
||||
import { h, VNode } from "preact";
|
||||
import { AlertProvider } from "./context/alert.js";
|
||||
|
||||
setupI18n("en", { en: {} });
|
||||
setupPlatform(chromeAPI);
|
||||
@ -41,10 +43,15 @@ describe("All the examples:", () => {
|
||||
describe(`Component ${component.name}:`, () => {
|
||||
component.examples.forEach((example) => {
|
||||
it(`should render example: ${example.name}`, () => {
|
||||
renderNodeOrBrowser(
|
||||
example.render.component,
|
||||
example.render.props,
|
||||
);
|
||||
function C(): VNode {
|
||||
const B = h(example.render.component, example.render.props);
|
||||
//FIXME:
|
||||
//some components push the alter in the UI function
|
||||
//that's not correct, should be moved into the sate function
|
||||
// until then, we ran the tests with the alert provider
|
||||
return h(AlertProvider, { children: B }, B);
|
||||
}
|
||||
renderNodeOrBrowser(C, {});
|
||||
});
|
||||
});
|
||||
});
|
||||
|
@ -31,8 +31,10 @@ import {
|
||||
VNode,
|
||||
} from "preact";
|
||||
import { render as renderToString } from "preact-render-to-string";
|
||||
import { AlertProvider } from "./context/alert.js";
|
||||
import { BackendProvider } from "./context/backend.js";
|
||||
import { TranslationProvider } from "./context/translation.js";
|
||||
import { nullFunction } from "./mui/handlers.js";
|
||||
import { BackgroundApiClient, wxApi } from "./wxApi.js";
|
||||
|
||||
// When doing tests we want the requestAnimationFrame to be as fast as possible.
|
||||
@ -218,7 +220,7 @@ export function mountHook<T extends object>(
|
||||
};
|
||||
}
|
||||
|
||||
export const nullFunction: any = () => null;
|
||||
// export const nullFunction: any = () => null;
|
||||
|
||||
interface MockHandler {
|
||||
addWalletCallResponse<Op extends WalletCoreOpKeys>(
|
||||
@ -365,6 +367,7 @@ export function createWalletApiMock(): {
|
||||
children: ComponentChildren;
|
||||
}): VNode {
|
||||
let children = _cs;
|
||||
children = create(AlertProvider, { children }, children);
|
||||
children = create(TranslationProvider, { children }, children);
|
||||
return create(
|
||||
BackendProvider,
|
||||
|
@ -53,7 +53,7 @@ export namespace State {
|
||||
|
||||
export interface ConfirmProvider {
|
||||
status: "confirm-provider";
|
||||
error: undefined | TalerErrorDetail;
|
||||
error: undefined;
|
||||
url: string;
|
||||
provider: SyncTermsOfServiceResponse;
|
||||
tos: ToggleHandler;
|
||||
|
@ -14,16 +14,13 @@
|
||||
GNU Taler; see the file COPYING. If not, see <http://www.gnu.org/licenses/>
|
||||
*/
|
||||
|
||||
import {
|
||||
canonicalizeBaseUrl,
|
||||
Codec,
|
||||
TalerErrorDetail,
|
||||
} from "@gnu-taler/taler-util";
|
||||
import { canonicalizeBaseUrl, Codec } from "@gnu-taler/taler-util";
|
||||
import {
|
||||
codecForSyncTermsOfServiceResponse,
|
||||
WalletApiOperation,
|
||||
} from "@gnu-taler/taler-wallet-core";
|
||||
import { useEffect, useState } from "preact/hooks";
|
||||
import { useAlertContext } from "../../context/alert.js";
|
||||
import { useBackendContext } from "../../context/backend.js";
|
||||
import { assertUnreachable } from "../../utils/index.js";
|
||||
import { Props, State } from "./index.js";
|
||||
@ -152,17 +149,15 @@ export function useComponentState({
|
||||
const [url, setHost] = useState<string | undefined>();
|
||||
const [name, setName] = useState<string | undefined>();
|
||||
const [tos, setTos] = useState(false);
|
||||
const { pushAlertOnError } = useAlertContext();
|
||||
const urlState = useUrlState(
|
||||
url,
|
||||
"config",
|
||||
codecForSyncTermsOfServiceResponse(),
|
||||
);
|
||||
const [operationError, setOperationError] = useState<
|
||||
TalerErrorDetail | undefined
|
||||
>();
|
||||
const [showConfirm, setShowConfirm] = useState(false);
|
||||
|
||||
async function addBackupProvider() {
|
||||
async function addBackupProvider(): Promise<void> {
|
||||
if (!url || !name) return;
|
||||
|
||||
const resp = await api.wallet.call(WalletApiOperation.AddBackupProvider, {
|
||||
@ -178,8 +173,6 @@ export function useComponentState({
|
||||
} else {
|
||||
return onComplete(url);
|
||||
}
|
||||
case "error":
|
||||
return setOperationError(resp.error);
|
||||
case "ok":
|
||||
return onComplete(url);
|
||||
default:
|
||||
@ -190,18 +183,18 @@ export function useComponentState({
|
||||
if (showConfirm && urlState && urlState.status === "ok") {
|
||||
return {
|
||||
status: "confirm-provider",
|
||||
error: operationError,
|
||||
error: undefined,
|
||||
onAccept: {
|
||||
onClick: !tos ? undefined : addBackupProvider,
|
||||
onClick: !tos ? undefined : pushAlertOnError(addBackupProvider),
|
||||
},
|
||||
onCancel: {
|
||||
onClick: onBack,
|
||||
onClick: pushAlertOnError(onBack),
|
||||
},
|
||||
provider: urlState.result,
|
||||
tos: {
|
||||
value: tos,
|
||||
button: {
|
||||
onClick: async () => setTos(!tos),
|
||||
onClick: pushAlertOnError(async () => setTos(!tos)),
|
||||
},
|
||||
},
|
||||
url: url ?? "",
|
||||
@ -213,25 +206,25 @@ export function useComponentState({
|
||||
error: undefined,
|
||||
name: {
|
||||
value: name || "",
|
||||
onInput: async (e) => setName(e),
|
||||
onInput: pushAlertOnError(async (e) => setName(e)),
|
||||
error:
|
||||
name === undefined ? undefined : !name ? "Can't be empty" : undefined,
|
||||
},
|
||||
onCancel: {
|
||||
onClick: onBack,
|
||||
onClick: pushAlertOnError(onBack),
|
||||
},
|
||||
onConfirm: {
|
||||
onClick:
|
||||
!urlState || urlState.status !== "ok" || !name
|
||||
? undefined
|
||||
: async () => {
|
||||
: pushAlertOnError(async () => {
|
||||
setShowConfirm(true);
|
||||
},
|
||||
}),
|
||||
},
|
||||
urlOk: urlState?.status === "ok",
|
||||
url: {
|
||||
value: url || "",
|
||||
onInput: async (e) => setHost(e),
|
||||
onInput: pushAlertOnError(async (e) => setHost(e)),
|
||||
error: errorString(urlState),
|
||||
},
|
||||
};
|
||||
|
@ -19,14 +19,14 @@
|
||||
* @author Sebastian Javier Marchano (sebasjm)
|
||||
*/
|
||||
|
||||
import { createExample } from "../../test-utils.js";
|
||||
import { tests } from "@gnu-taler/web-util/lib/index.browser";
|
||||
import { ConfirmProviderView, SelectProviderView } from "./views.js";
|
||||
|
||||
export default {
|
||||
title: "add backup provider",
|
||||
};
|
||||
|
||||
export const DemoService = createExample(ConfirmProviderView, {
|
||||
export const DemoService = tests.createExample(ConfirmProviderView, {
|
||||
url: "https://sync.demo.taler.net/",
|
||||
provider: {
|
||||
annual_fee: "KUDOS:0.1",
|
||||
@ -40,7 +40,7 @@ export const DemoService = createExample(ConfirmProviderView, {
|
||||
onCancel: {},
|
||||
});
|
||||
|
||||
export const FreeService = createExample(ConfirmProviderView, {
|
||||
export const FreeService = tests.createExample(ConfirmProviderView, {
|
||||
url: "https://sync.taler:9667/",
|
||||
provider: {
|
||||
annual_fee: "ARS:0",
|
||||
@ -54,14 +54,14 @@ export const FreeService = createExample(ConfirmProviderView, {
|
||||
onCancel: {},
|
||||
});
|
||||
|
||||
export const Initial = createExample(SelectProviderView, {
|
||||
export const Initial = tests.createExample(SelectProviderView, {
|
||||
url: { value: "" },
|
||||
name: { value: "" },
|
||||
onCancel: {},
|
||||
onConfirm: {},
|
||||
});
|
||||
|
||||
export const WithValue = createExample(SelectProviderView, {
|
||||
export const WithValue = tests.createExample(SelectProviderView, {
|
||||
url: {
|
||||
value: "sync.demo.taler.net",
|
||||
},
|
||||
@ -72,7 +72,7 @@ export const WithValue = createExample(SelectProviderView, {
|
||||
onConfirm: {},
|
||||
});
|
||||
|
||||
export const WithConnectionError = createExample(SelectProviderView, {
|
||||
export const WithConnectionError = tests.createExample(SelectProviderView, {
|
||||
url: {
|
||||
value: "sync.demo.taler.net",
|
||||
error: "Network error",
|
||||
@ -84,7 +84,7 @@ export const WithConnectionError = createExample(SelectProviderView, {
|
||||
onConfirm: {},
|
||||
});
|
||||
|
||||
export const WithClientError = createExample(SelectProviderView, {
|
||||
export const WithClientError = tests.createExample(SelectProviderView, {
|
||||
url: {
|
||||
value: "sync.demo.taler.net",
|
||||
error: "URL may not be right: (404) Not Found",
|
||||
@ -96,7 +96,7 @@ export const WithClientError = createExample(SelectProviderView, {
|
||||
onConfirm: {},
|
||||
});
|
||||
|
||||
export const WithServerError = createExample(SelectProviderView, {
|
||||
export const WithServerError = tests.createExample(SelectProviderView, {
|
||||
url: {
|
||||
value: "sync.demo.taler.net",
|
||||
error: "Try another server: (500) Internal Server Error",
|
||||
|
@ -21,7 +21,8 @@
|
||||
|
||||
import { expect } from "chai";
|
||||
import { tests } from "../../../../web-util/src/index.browser.js";
|
||||
import { createWalletApiMock, nullFunction } from "../../test-utils.js";
|
||||
import { nullFunction } from "../../mui/handlers.js";
|
||||
import { createWalletApiMock } from "../../test-utils.js";
|
||||
import { Props } from "./index.js";
|
||||
import { useComponentState } from "./state.js";
|
||||
|
||||
|
@ -19,7 +19,7 @@
|
||||
* @author Sebastian Javier Marchano (sebasjm)
|
||||
*/
|
||||
|
||||
import { createExample } from "../test-utils.js";
|
||||
import { tests } from "@gnu-taler/web-util/lib/index.browser";
|
||||
import { AddNewActionView as TestedComponent } from "./AddNewActionView.js";
|
||||
|
||||
export default {
|
||||
@ -30,4 +30,4 @@ export default {
|
||||
},
|
||||
};
|
||||
|
||||
export const Initial = createExample(TestedComponent, {});
|
||||
export const Initial = tests.createExample(TestedComponent, {});
|
||||
|
@ -25,14 +25,14 @@ import {
|
||||
BackupView as TestedComponent,
|
||||
ShowRecoveryInfo,
|
||||
} from "./BackupPage.js";
|
||||
import { createExample } from "../test-utils.js";
|
||||
import { tests } from "@gnu-taler/web-util/lib/index.browser";
|
||||
import { TalerProtocolTimestamp } from "@gnu-taler/taler-util";
|
||||
|
||||
export default {
|
||||
title: "backup",
|
||||
};
|
||||
|
||||
export const LotOfProviders = createExample(TestedComponent, {
|
||||
export const LotOfProviders = tests.createExample(TestedComponent, {
|
||||
providers: [
|
||||
{
|
||||
active: true,
|
||||
@ -164,7 +164,7 @@ export const LotOfProviders = createExample(TestedComponent, {
|
||||
],
|
||||
});
|
||||
|
||||
export const OneProvider = createExample(TestedComponent, {
|
||||
export const OneProvider = tests.createExample(TestedComponent, {
|
||||
providers: [
|
||||
{
|
||||
active: true,
|
||||
@ -190,10 +190,10 @@ export const OneProvider = createExample(TestedComponent, {
|
||||
],
|
||||
});
|
||||
|
||||
export const Empty = createExample(TestedComponent, {
|
||||
export const Empty = tests.createExample(TestedComponent, {
|
||||
providers: [],
|
||||
});
|
||||
|
||||
export const Recovery = createExample(ShowRecoveryInfo, {
|
||||
export const Recovery = tests.createExample(ShowRecoveryInfo, {
|
||||
info: "taler://recovery/ASLDKJASLKDJASD",
|
||||
});
|
||||
|
@ -29,7 +29,7 @@ import {
|
||||
} from "date-fns";
|
||||
import { Fragment, h, VNode } from "preact";
|
||||
import { useEffect, useState } from "preact/hooks";
|
||||
import { AlertView } from "../components/CurrentAlerts.js";
|
||||
import { ErrorAlertView } from "../components/CurrentAlerts.js";
|
||||
import { Loading } from "../components/Loading.js";
|
||||
import { QR } from "../components/QR.js";
|
||||
import {
|
||||
@ -118,8 +118,8 @@ export function BackupPage({ onAddProvider }: Props): VNode {
|
||||
}
|
||||
if (status.hasError) {
|
||||
return (
|
||||
<AlertView
|
||||
alert={alertFromError(
|
||||
<ErrorAlertView
|
||||
error={alertFromError(
|
||||
i18n.str`Could not load backup providers`,
|
||||
status,
|
||||
)}
|
||||
|
@ -25,7 +25,7 @@ import {
|
||||
} from "@gnu-taler/taler-util";
|
||||
import { WalletApiOperation } from "@gnu-taler/taler-wallet-core";
|
||||
import { useState } from "preact/hooks";
|
||||
import { alertFromError } from "../../context/alert.js";
|
||||
import { alertFromError, useAlertContext } from "../../context/alert.js";
|
||||
import { useBackendContext } from "../../context/backend.js";
|
||||
import { useTranslationContext } from "../../context/translation.js";
|
||||
import { useAsyncAsHook } from "../../hooks/useAsyncAsHook.js";
|
||||
@ -39,6 +39,7 @@ export function useComponentState({
|
||||
}: Props): State {
|
||||
const api = useBackendContext();
|
||||
const { i18n } = useTranslationContext();
|
||||
const { pushAlertOnError } = useAlertContext();
|
||||
const parsed = amountStr === undefined ? undefined : Amounts.parse(amountStr);
|
||||
const currency = parsed !== undefined ? parsed.currency : currencyStr;
|
||||
|
||||
@ -130,9 +131,9 @@ export function useComponentState({
|
||||
error: undefined,
|
||||
currency,
|
||||
onAddAccount: {
|
||||
onClick: async () => {
|
||||
onClick: pushAlertOnError(async () => {
|
||||
setAddingAccount(true);
|
||||
},
|
||||
}),
|
||||
},
|
||||
};
|
||||
}
|
||||
@ -221,27 +222,27 @@ export function useComponentState({
|
||||
currency,
|
||||
amount: {
|
||||
value: amount,
|
||||
onInput: updateAmount,
|
||||
onInput: pushAlertOnError(updateAmount),
|
||||
error: amountError,
|
||||
},
|
||||
onAddAccount: {
|
||||
onClick: async () => {
|
||||
onClick: pushAlertOnError(async () => {
|
||||
setAddingAccount(true);
|
||||
},
|
||||
}),
|
||||
},
|
||||
account: {
|
||||
list: accountMap,
|
||||
value: stringifyPaytoUri(currentAccount),
|
||||
onChange: updateAccountFromList,
|
||||
onChange: pushAlertOnError(updateAccountFromList),
|
||||
},
|
||||
currentAccount,
|
||||
cancelHandler: {
|
||||
onClick: async () => {
|
||||
onClick: pushAlertOnError(async () => {
|
||||
onCancel(currency);
|
||||
},
|
||||
}),
|
||||
},
|
||||
depositHandler: {
|
||||
onClick: unableToDeposit ? undefined : doSend,
|
||||
onClick: unableToDeposit ? undefined : pushAlertOnError(doSend),
|
||||
},
|
||||
totalFee,
|
||||
totalToDeposit,
|
||||
@ -263,7 +264,7 @@ async function getFeeForAmount(
|
||||
});
|
||||
}
|
||||
|
||||
export function labelForAccountType(id: string) {
|
||||
export function labelForAccountType(id: string): string {
|
||||
switch (id) {
|
||||
case "":
|
||||
return "Choose one";
|
||||
|
@ -19,26 +19,21 @@
|
||||
* @author Sebastian Javier Marchano (sebasjm)
|
||||
*/
|
||||
|
||||
import { Amounts, DepositGroupFees } from "@gnu-taler/taler-util";
|
||||
import { createExample } from "../../test-utils.js";
|
||||
import { labelForAccountType } from "./state.js";
|
||||
import { Amounts } from "@gnu-taler/taler-util";
|
||||
import { tests } from "@gnu-taler/web-util/lib/index.browser";
|
||||
import { nullFunction } from "../../mui/handlers.js";
|
||||
import { ReadyView } from "./views.js";
|
||||
|
||||
export default {
|
||||
title: "deposit",
|
||||
};
|
||||
|
||||
// const ac = parsePaytoUri("payto://iban/ES8877998399652238")!;
|
||||
// const accountMap = createLabelsForBankAccount([ac]);
|
||||
|
||||
export const WithNoAccountForIBAN = createExample(ReadyView, {
|
||||
export const WithNoAccountForIBAN = tests.createExample(ReadyView, {
|
||||
status: "ready",
|
||||
account: {
|
||||
list: {},
|
||||
value: "",
|
||||
onChange: async () => {
|
||||
null;
|
||||
},
|
||||
onChange: nullFunction,
|
||||
},
|
||||
currentAccount: {
|
||||
isKnown: true,
|
||||
@ -49,31 +44,25 @@ export const WithNoAccountForIBAN = createExample(ReadyView, {
|
||||
},
|
||||
currency: "USD",
|
||||
amount: {
|
||||
onInput: async () => {
|
||||
null;
|
||||
},
|
||||
onInput: nullFunction,
|
||||
value: Amounts.parseOrThrow("USD:10"),
|
||||
},
|
||||
onAddAccount: {},
|
||||
cancelHandler: {},
|
||||
depositHandler: {
|
||||
onClick: async () => {
|
||||
return;
|
||||
},
|
||||
onClick: nullFunction,
|
||||
},
|
||||
totalFee: Amounts.zeroOfCurrency("USD"),
|
||||
totalToDeposit: Amounts.parseOrThrow("USD:10"),
|
||||
// onCalculateFee: alwaysReturnFeeToOne,
|
||||
});
|
||||
|
||||
export const WithIBANAccountTypeSelected = createExample(ReadyView, {
|
||||
export const WithIBANAccountTypeSelected = tests.createExample(ReadyView, {
|
||||
status: "ready",
|
||||
account: {
|
||||
list: { asdlkajsdlk: "asdlkajsdlk", qwerqwer: "qwerqwer" },
|
||||
value: "asdlkajsdlk",
|
||||
onChange: async () => {
|
||||
null;
|
||||
},
|
||||
onChange: nullFunction,
|
||||
},
|
||||
currentAccount: {
|
||||
isKnown: true,
|
||||
@ -84,31 +73,25 @@ export const WithIBANAccountTypeSelected = createExample(ReadyView, {
|
||||
},
|
||||
currency: "USD",
|
||||
amount: {
|
||||
onInput: async () => {
|
||||
null;
|
||||
},
|
||||
onInput: nullFunction,
|
||||
value: Amounts.parseOrThrow("USD:10"),
|
||||
},
|
||||
onAddAccount: {},
|
||||
cancelHandler: {},
|
||||
depositHandler: {
|
||||
onClick: async () => {
|
||||
return;
|
||||
},
|
||||
onClick: nullFunction,
|
||||
},
|
||||
totalFee: Amounts.zeroOfCurrency("USD"),
|
||||
totalToDeposit: Amounts.parseOrThrow("USD:10"),
|
||||
// onCalculateFee: alwaysReturnFeeToOne,
|
||||
});
|
||||
|
||||
export const NewBitcoinAccountTypeSelected = createExample(ReadyView, {
|
||||
export const NewBitcoinAccountTypeSelected = tests.createExample(ReadyView, {
|
||||
status: "ready",
|
||||
account: {
|
||||
list: {},
|
||||
value: "asdlkajsdlk",
|
||||
onChange: async () => {
|
||||
null;
|
||||
},
|
||||
onChange: nullFunction,
|
||||
},
|
||||
currentAccount: {
|
||||
isKnown: true,
|
||||
@ -120,16 +103,12 @@ export const NewBitcoinAccountTypeSelected = createExample(ReadyView, {
|
||||
onAddAccount: {},
|
||||
currency: "USD",
|
||||
amount: {
|
||||
onInput: async () => {
|
||||
null;
|
||||
},
|
||||
onInput: nullFunction,
|
||||
value: Amounts.parseOrThrow("USD:10"),
|
||||
},
|
||||
cancelHandler: {},
|
||||
depositHandler: {
|
||||
onClick: async () => {
|
||||
return;
|
||||
},
|
||||
onClick: nullFunction,
|
||||
},
|
||||
totalFee: Amounts.zeroOfCurrency("USD"),
|
||||
totalToDeposit: Amounts.parseOrThrow("USD:10"),
|
||||
|
@ -28,7 +28,8 @@ import {
|
||||
import { WalletApiOperation } from "@gnu-taler/taler-wallet-core";
|
||||
import { expect } from "chai";
|
||||
import { tests } from "../../../../web-util/src/index.browser.js";
|
||||
import { createWalletApiMock, nullFunction } from "../../test-utils.js";
|
||||
import { nullFunction } from "../../mui/handlers.js";
|
||||
import { createWalletApiMock } from "../../test-utils.js";
|
||||
|
||||
import { useComponentState } from "./state.js";
|
||||
|
||||
|
@ -17,7 +17,7 @@
|
||||
import { Amounts } from "@gnu-taler/taler-util";
|
||||
import { WalletApiOperation } from "@gnu-taler/taler-wallet-core";
|
||||
import { useState } from "preact/hooks";
|
||||
import { alertFromError } from "../../context/alert.js";
|
||||
import { alertFromError, useAlertContext } from "../../context/alert.js";
|
||||
import { useBackendContext } from "../../context/backend.js";
|
||||
import { useTranslationContext } from "../../context/translation.js";
|
||||
import { useAsyncAsHook } from "../../hooks/useAsyncAsHook.js";
|
||||
@ -26,6 +26,7 @@ import { Contact, Props, State } from "./index.js";
|
||||
|
||||
export function useComponentState(props: Props): RecursiveState<State> {
|
||||
const api = useBackendContext();
|
||||
const { pushAlertOnError } = useAlertContext();
|
||||
const parsedInitialAmount = !props.amount
|
||||
? undefined
|
||||
: Amounts.parse(props.amount);
|
||||
@ -108,26 +109,26 @@ export function useComponentState(props: Props): RecursiveState<State> {
|
||||
error: undefined,
|
||||
previous,
|
||||
selectCurrency: {
|
||||
onClick: async () => {
|
||||
onClick: pushAlertOnError(async () => {
|
||||
setAmount(undefined);
|
||||
},
|
||||
}),
|
||||
},
|
||||
goToBank: {
|
||||
onClick: invalid
|
||||
? undefined
|
||||
: async () => {
|
||||
: pushAlertOnError(async () => {
|
||||
props.goToWalletBankDeposit(currencyAndAmount);
|
||||
},
|
||||
}),
|
||||
},
|
||||
goToWallet: {
|
||||
onClick: invalid
|
||||
? undefined
|
||||
: async () => {
|
||||
: pushAlertOnError(async () => {
|
||||
props.goToWalletWalletSend(currencyAndAmount);
|
||||
},
|
||||
}),
|
||||
},
|
||||
amountHandler: {
|
||||
onInput: async (s) => setAmount(s),
|
||||
onInput: pushAlertOnError(async (s) => setAmount(s)),
|
||||
value: amount,
|
||||
},
|
||||
type: props.type,
|
||||
@ -138,26 +139,26 @@ export function useComponentState(props: Props): RecursiveState<State> {
|
||||
error: undefined,
|
||||
previous,
|
||||
selectCurrency: {
|
||||
onClick: async () => {
|
||||
onClick: pushAlertOnError(async () => {
|
||||
setAmount(undefined);
|
||||
},
|
||||
}),
|
||||
},
|
||||
goToBank: {
|
||||
onClick: invalid
|
||||
? undefined
|
||||
: async () => {
|
||||
: pushAlertOnError(async () => {
|
||||
props.goToWalletManualWithdraw(currencyAndAmount);
|
||||
},
|
||||
}),
|
||||
},
|
||||
goToWallet: {
|
||||
onClick: invalid
|
||||
? undefined
|
||||
: async () => {
|
||||
: pushAlertOnError(async () => {
|
||||
props.goToWalletWalletInvoice(currencyAndAmount);
|
||||
},
|
||||
}),
|
||||
},
|
||||
amountHandler: {
|
||||
onInput: async (s) => setAmount(s),
|
||||
onInput: pushAlertOnError(async (s) => setAmount(s)),
|
||||
value: amount,
|
||||
},
|
||||
type: props.type,
|
||||
|
@ -19,14 +19,14 @@
|
||||
* @author Sebastian Javier Marchano (sebasjm)
|
||||
*/
|
||||
|
||||
import { createExample } from "../../test-utils.js";
|
||||
import { tests } from "@gnu-taler/web-util/lib/index.browser";
|
||||
import { ReadyView, SelectCurrencyView } from "./views.js";
|
||||
|
||||
export default {
|
||||
title: "destination",
|
||||
};
|
||||
|
||||
export const GetCash = createExample(ReadyView, {
|
||||
export const GetCash = tests.createExample(ReadyView, {
|
||||
amountHandler: {
|
||||
value: {
|
||||
currency: "EUR",
|
||||
@ -40,7 +40,7 @@ export const GetCash = createExample(ReadyView, {
|
||||
selectCurrency: {},
|
||||
type: "get",
|
||||
});
|
||||
export const SendCash = createExample(ReadyView, {
|
||||
export const SendCash = tests.createExample(ReadyView, {
|
||||
amountHandler: {
|
||||
value: {
|
||||
currency: "EUR",
|
||||
@ -55,7 +55,7 @@ export const SendCash = createExample(ReadyView, {
|
||||
type: "send",
|
||||
});
|
||||
|
||||
export const SelectCurrency = createExample(SelectCurrencyView, {
|
||||
export const SelectCurrency = tests.createExample(SelectCurrencyView, {
|
||||
currencies: {
|
||||
"": "Select a currency",
|
||||
USD: "USD",
|
||||
|
@ -28,7 +28,8 @@ import {
|
||||
import { WalletApiOperation } from "@gnu-taler/taler-wallet-core";
|
||||
import { expect } from "chai";
|
||||
import { tests } from "../../../../web-util/src/index.browser.js";
|
||||
import { createWalletApiMock, nullFunction } from "../../test-utils.js";
|
||||
import { nullFunction } from "../../mui/handlers.js";
|
||||
import { createWalletApiMock } from "../../test-utils.js";
|
||||
import { useComponentState } from "./state.js";
|
||||
|
||||
const exchangeArs: ExchangeListItem = {
|
||||
|
@ -20,7 +20,7 @@
|
||||
*/
|
||||
|
||||
import { PendingTaskType } from "@gnu-taler/taler-wallet-core";
|
||||
import { createExample } from "../test-utils.js";
|
||||
import { tests } from "@gnu-taler/web-util/lib/index.browser";
|
||||
import { View as TestedComponent } from "./DeveloperPage.js";
|
||||
|
||||
export default {
|
||||
@ -31,7 +31,7 @@ export default {
|
||||
},
|
||||
};
|
||||
|
||||
export const AllOff = createExample(TestedComponent, {
|
||||
export const AllOff = tests.createExample(TestedComponent, {
|
||||
onDownloadDatabase: async () => "this is the content of the database",
|
||||
operations: [
|
||||
{
|
||||
|
@ -19,11 +19,11 @@
|
||||
* @author Sebastian Javier Marchano (sebasjm)
|
||||
*/
|
||||
|
||||
import { createExample } from "../../test-utils.js";
|
||||
import { tests } from "@gnu-taler/web-util/lib/index.browser";
|
||||
import { ReadyView } from "./views.js";
|
||||
|
||||
export default {
|
||||
title: "example",
|
||||
};
|
||||
|
||||
export const Ready = createExample(ReadyView, {});
|
||||
export const Ready = tests.createExample(ReadyView, {});
|
||||
|
@ -19,7 +19,7 @@
|
||||
* @author Sebastian Javier Marchano (sebasjm)
|
||||
*/
|
||||
|
||||
import { createExample } from "../test-utils.js";
|
||||
import { tests } from "@gnu-taler/web-util/lib/index.browser";
|
||||
import { ExchangeAddConfirmPage as TestedComponent } from "./ExchangeAddConfirm.js";
|
||||
|
||||
export default {
|
||||
@ -32,14 +32,14 @@ export default {
|
||||
},
|
||||
};
|
||||
|
||||
export const TermsNotFound = createExample(TestedComponent, {
|
||||
export const TermsNotFound = tests.createExample(TestedComponent, {
|
||||
url: "https://exchange.demo.taler.net/",
|
||||
});
|
||||
|
||||
export const NewTerms = createExample(TestedComponent, {
|
||||
export const NewTerms = tests.createExample(TestedComponent, {
|
||||
url: "https://exchange.demo.taler.net/",
|
||||
});
|
||||
|
||||
export const TermsChanged = createExample(TestedComponent, {
|
||||
export const TermsChanged = tests.createExample(TestedComponent, {
|
||||
url: "https://exchange.demo.taler.net/",
|
||||
});
|
||||
|
@ -19,7 +19,7 @@
|
||||
* @author Sebastian Javier Marchano (sebasjm)
|
||||
*/
|
||||
|
||||
import { createExample } from "../test-utils.js";
|
||||
import { tests } from "@gnu-taler/web-util/lib/index.browser";
|
||||
import { queryToSlashKeys } from "../utils/index.js";
|
||||
import { ExchangeSetUrlPage as TestedComponent } from "./ExchangeSetUrl.js";
|
||||
|
||||
@ -27,17 +27,17 @@ export default {
|
||||
title: "exchange add set url",
|
||||
};
|
||||
|
||||
export const ExpectedUSD = createExample(TestedComponent, {
|
||||
export const ExpectedUSD = tests.createExample(TestedComponent, {
|
||||
expectedCurrency: "USD",
|
||||
onVerify: queryToSlashKeys,
|
||||
});
|
||||
|
||||
export const ExpectedKUDOS = createExample(TestedComponent, {
|
||||
export const ExpectedKUDOS = tests.createExample(TestedComponent, {
|
||||
expectedCurrency: "KUDOS",
|
||||
onVerify: queryToSlashKeys,
|
||||
});
|
||||
|
||||
export const InitialState = createExample(TestedComponent, {
|
||||
export const InitialState = tests.createExample(TestedComponent, {
|
||||
onVerify: queryToSlashKeys,
|
||||
});
|
||||
|
||||
@ -55,7 +55,7 @@ const knownExchanges = [
|
||||
},
|
||||
];
|
||||
|
||||
export const WithDemoAsKnownExchange = createExample(TestedComponent, {
|
||||
export const WithDemoAsKnownExchange = tests.createExample(TestedComponent, {
|
||||
onVerify: async (url) => {
|
||||
const found =
|
||||
knownExchanges.findIndex((e) => e.exchangeBaseUrl === url) !== -1;
|
||||
|
@ -20,7 +20,7 @@ import {
|
||||
WalletApiOperation,
|
||||
} from "@gnu-taler/taler-wallet-core";
|
||||
import { useState } from "preact/hooks";
|
||||
import { alertFromError } from "../../context/alert.js";
|
||||
import { alertFromError, useAlertContext } from "../../context/alert.js";
|
||||
import { useBackendContext } from "../../context/backend.js";
|
||||
import { useTranslationContext } from "../../context/translation.js";
|
||||
import { useAsyncAsHook } from "../../hooks/useAsyncAsHook.js";
|
||||
@ -33,6 +33,7 @@ export function useComponentState({
|
||||
currentExchange,
|
||||
}: Props): State {
|
||||
const api = useBackendContext();
|
||||
const { pushAlertOnError } = useAlertContext();
|
||||
const { i18n } = useTranslationContext();
|
||||
const initialValue = exchanges.findIndex(
|
||||
(e) => e.exchangeBaseUrl === currentExchange,
|
||||
@ -115,7 +116,7 @@ export function useComponentState({
|
||||
status: "showing-privacy",
|
||||
error: undefined,
|
||||
onClose: {
|
||||
onClick: async () => setShowingPrivacy(undefined),
|
||||
onClick: pushAlertOnError(async () => setShowingPrivacy(undefined)),
|
||||
},
|
||||
exchangeUrl: showingPrivacy,
|
||||
};
|
||||
@ -125,7 +126,7 @@ export function useComponentState({
|
||||
status: "showing-tos",
|
||||
error: undefined,
|
||||
onClose: {
|
||||
onClick: async () => setShowingTos(undefined),
|
||||
onClick: pushAlertOnError(async () => setShowingTos(undefined)),
|
||||
},
|
||||
exchangeUrl: showingTos,
|
||||
};
|
||||
@ -138,24 +139,24 @@ export function useComponentState({
|
||||
exchanges: {
|
||||
list: exchangeMap,
|
||||
value: value,
|
||||
onChange: async (v) => {
|
||||
onChange: pushAlertOnError(async (v) => {
|
||||
setValue(v);
|
||||
},
|
||||
}),
|
||||
},
|
||||
error: undefined,
|
||||
onClose: {
|
||||
onClick: onCancel,
|
||||
onClick: pushAlertOnError(onCancel),
|
||||
},
|
||||
selected,
|
||||
onShowPrivacy: {
|
||||
onClick: async () => {
|
||||
onClick: pushAlertOnError(async () => {
|
||||
setShowingPrivacy(selected.exchangeBaseUrl);
|
||||
},
|
||||
}),
|
||||
},
|
||||
onShowTerms: {
|
||||
onClick: async () => {
|
||||
onClick: pushAlertOnError(async () => {
|
||||
setShowingTos(selected.exchangeBaseUrl);
|
||||
},
|
||||
}),
|
||||
},
|
||||
};
|
||||
}
|
||||
@ -215,30 +216,30 @@ export function useComponentState({
|
||||
exchanges: {
|
||||
list: exchangeMap,
|
||||
value: value,
|
||||
onChange: async (v) => {
|
||||
onChange: pushAlertOnError(async (v) => {
|
||||
setValue(v);
|
||||
},
|
||||
}),
|
||||
},
|
||||
error: undefined,
|
||||
onReset: {
|
||||
onClick: async () => {
|
||||
onClick: pushAlertOnError(async () => {
|
||||
setValue(String(initialValue));
|
||||
},
|
||||
}),
|
||||
},
|
||||
onSelect: {
|
||||
onClick: async () => {
|
||||
onClick: pushAlertOnError(async () => {
|
||||
onSelection(selected.exchangeBaseUrl);
|
||||
},
|
||||
}),
|
||||
},
|
||||
onShowPrivacy: {
|
||||
onClick: async () => {
|
||||
onClick: pushAlertOnError(async () => {
|
||||
setShowingPrivacy(selected.exchangeBaseUrl);
|
||||
},
|
||||
}),
|
||||
},
|
||||
onShowTerms: {
|
||||
onClick: async () => {
|
||||
onClick: pushAlertOnError(async () => {
|
||||
setShowingTos(selected.exchangeBaseUrl);
|
||||
},
|
||||
}),
|
||||
},
|
||||
selected,
|
||||
coinOperationTimeline,
|
||||
|
@ -19,14 +19,14 @@
|
||||
* @author Sebastian Javier Marchano (sebasjm)
|
||||
*/
|
||||
|
||||
import { createExample } from "../../test-utils.js";
|
||||
import { tests } from "@gnu-taler/web-util/lib/index.browser";
|
||||
import { ComparingView, ReadyView } from "./views.js";
|
||||
|
||||
export default {
|
||||
title: "select exchange",
|
||||
};
|
||||
|
||||
export const Bitcoin1 = createExample(ReadyView, {
|
||||
export const Bitcoin1 = tests.createExample(ReadyView, {
|
||||
exchanges: {
|
||||
list: { "0": "https://exchange.taler.ar" },
|
||||
value: "0",
|
||||
@ -43,7 +43,7 @@ export const Bitcoin1 = createExample(ReadyView, {
|
||||
onShowTerms: {},
|
||||
onClose: {},
|
||||
});
|
||||
export const Bitcoin2 = createExample(ReadyView, {
|
||||
export const Bitcoin2 = tests.createExample(ReadyView, {
|
||||
exchanges: {
|
||||
list: {
|
||||
"https://exchange.taler.ar": "https://exchange.taler.ar",
|
||||
@ -64,7 +64,7 @@ export const Bitcoin2 = createExample(ReadyView, {
|
||||
onClose: {},
|
||||
});
|
||||
|
||||
export const Kudos1 = createExample(ReadyView, {
|
||||
export const Kudos1 = tests.createExample(ReadyView, {
|
||||
exchanges: {
|
||||
list: {
|
||||
"https://exchange-kudos.taler.ar": "https://exchange-kudos.taler.ar",
|
||||
@ -83,7 +83,7 @@ export const Kudos1 = createExample(ReadyView, {
|
||||
onShowTerms: {},
|
||||
onClose: {},
|
||||
});
|
||||
export const Kudos2 = createExample(ReadyView, {
|
||||
export const Kudos2 = tests.createExample(ReadyView, {
|
||||
exchanges: {
|
||||
list: {
|
||||
"https://exchange-kudos.taler.ar": "https://exchange-kudos.taler.ar",
|
||||
@ -103,7 +103,7 @@ export const Kudos2 = createExample(ReadyView, {
|
||||
onShowTerms: {},
|
||||
onClose: {},
|
||||
});
|
||||
export const ComparingBitcoin = createExample(ComparingView, {
|
||||
export const ComparingBitcoin = tests.createExample(ComparingView, {
|
||||
exchanges: {
|
||||
list: { "http://exchange": "http://exchange" },
|
||||
value: "http://exchange",
|
||||
@ -131,7 +131,7 @@ export const ComparingBitcoin = createExample(ComparingView, {
|
||||
missingWireTYpe: [],
|
||||
wireFeeTimeline: {},
|
||||
});
|
||||
export const ComparingKudos = createExample(ComparingView, {
|
||||
export const ComparingKudos = tests.createExample(ComparingView, {
|
||||
exchanges: {
|
||||
list: { "http://exchange": "http://exchange" },
|
||||
value: "http://exchange",
|
||||
|
@ -37,7 +37,7 @@ import {
|
||||
WithdrawalType,
|
||||
} from "@gnu-taler/taler-util";
|
||||
import { HistoryView as TestedComponent } from "./History.js";
|
||||
import { createExample } from "../test-utils.js";
|
||||
import { tests } from "@gnu-taler/web-util/lib/index.browser";
|
||||
|
||||
export default {
|
||||
title: "balance",
|
||||
@ -160,12 +160,14 @@ const exampleData = {
|
||||
} as TransactionPeerPullDebit,
|
||||
};
|
||||
|
||||
export const NoBalance = createExample(TestedComponent, {
|
||||
export const NoBalance = tests.createExample(TestedComponent, {
|
||||
transactions: [],
|
||||
balances: [],
|
||||
});
|
||||
|
||||
export const SomeBalanceWithNoTransactions = createExample(TestedComponent, {
|
||||
export const SomeBalanceWithNoTransactions = tests.createExample(
|
||||
TestedComponent,
|
||||
{
|
||||
transactions: [],
|
||||
balances: [
|
||||
{
|
||||
@ -176,9 +178,10 @@ export const SomeBalanceWithNoTransactions = createExample(TestedComponent, {
|
||||
requiresUserInput: false,
|
||||
},
|
||||
],
|
||||
});
|
||||
},
|
||||
);
|
||||
|
||||
export const OneSimpleTransaction = createExample(TestedComponent, {
|
||||
export const OneSimpleTransaction = tests.createExample(TestedComponent, {
|
||||
transactions: [exampleData.withdraw],
|
||||
balances: [
|
||||
{
|
||||
@ -191,7 +194,9 @@ export const OneSimpleTransaction = createExample(TestedComponent, {
|
||||
],
|
||||
});
|
||||
|
||||
export const TwoTransactionsAndZeroBalance = createExample(TestedComponent, {
|
||||
export const TwoTransactionsAndZeroBalance = tests.createExample(
|
||||
TestedComponent,
|
||||
{
|
||||
transactions: [exampleData.withdraw, exampleData.deposit],
|
||||
balances: [
|
||||
{
|
||||
@ -202,9 +207,10 @@ export const TwoTransactionsAndZeroBalance = createExample(TestedComponent, {
|
||||
requiresUserInput: false,
|
||||
},
|
||||
],
|
||||
});
|
||||
},
|
||||
);
|
||||
|
||||
export const OneTransactionPending = createExample(TestedComponent, {
|
||||
export const OneTransactionPending = tests.createExample(TestedComponent, {
|
||||
transactions: [
|
||||
{
|
||||
...exampleData.withdraw,
|
||||
@ -222,7 +228,7 @@ export const OneTransactionPending = createExample(TestedComponent, {
|
||||
],
|
||||
});
|
||||
|
||||
export const SomeTransactions = createExample(TestedComponent, {
|
||||
export const SomeTransactions = tests.createExample(TestedComponent, {
|
||||
transactions: [
|
||||
exampleData.withdraw,
|
||||
exampleData.payment,
|
||||
@ -251,7 +257,7 @@ export const SomeTransactions = createExample(TestedComponent, {
|
||||
],
|
||||
});
|
||||
|
||||
export const SomeTransactionsWithTwoCurrencies = createExample(
|
||||
export const SomeTransactionsWithTwoCurrencies = tests.createExample(
|
||||
TestedComponent,
|
||||
{
|
||||
transactions: [
|
||||
@ -283,7 +289,7 @@ export const SomeTransactionsWithTwoCurrencies = createExample(
|
||||
},
|
||||
);
|
||||
|
||||
export const FiveOfficialCurrencies = createExample(TestedComponent, {
|
||||
export const FiveOfficialCurrencies = tests.createExample(TestedComponent, {
|
||||
transactions: [exampleData.withdraw],
|
||||
balances: [
|
||||
{
|
||||
@ -324,7 +330,7 @@ export const FiveOfficialCurrencies = createExample(TestedComponent, {
|
||||
],
|
||||
});
|
||||
|
||||
export const FiveOfficialCurrenciesWithHighValue = createExample(
|
||||
export const FiveOfficialCurrenciesWithHighValue = tests.createExample(
|
||||
TestedComponent,
|
||||
{
|
||||
transactions: [exampleData.withdraw],
|
||||
@ -368,7 +374,7 @@ export const FiveOfficialCurrenciesWithHighValue = createExample(
|
||||
},
|
||||
);
|
||||
|
||||
export const PeerToPeer = createExample(TestedComponent, {
|
||||
export const PeerToPeer = tests.createExample(TestedComponent, {
|
||||
transactions: [
|
||||
exampleData.pull_credit,
|
||||
exampleData.pull_debit,
|
||||
|
@ -23,7 +23,7 @@ import {
|
||||
import { WalletApiOperation } from "@gnu-taler/taler-wallet-core";
|
||||
import { Fragment, h, VNode } from "preact";
|
||||
import { useEffect, useState } from "preact/hooks";
|
||||
import { AlertView } from "../components/CurrentAlerts.js";
|
||||
import { ErrorAlertView } from "../components/CurrentAlerts.js";
|
||||
import { Loading } from "../components/Loading.js";
|
||||
import {
|
||||
CenteredBoldText,
|
||||
@ -33,7 +33,7 @@ import {
|
||||
} from "../components/styled/index.js";
|
||||
import { Time } from "../components/Time.js";
|
||||
import { TransactionItem } from "../components/TransactionItem.js";
|
||||
import { alertFromError } from "../context/alert.js";
|
||||
import { alertFromError, useAlertContext } from "../context/alert.js";
|
||||
import { useBackendContext } from "../context/backend.js";
|
||||
import { useTranslationContext } from "../context/translation.js";
|
||||
import { useAsyncAsHook } from "../hooks/useAsyncAsHook.js";
|
||||
@ -72,8 +72,8 @@ export function HistoryPage({
|
||||
|
||||
if (state.hasError) {
|
||||
return (
|
||||
<AlertView
|
||||
alert={alertFromError(
|
||||
<ErrorAlertView
|
||||
error={alertFromError(
|
||||
i18n.str`Could not load the list of transactions`,
|
||||
state,
|
||||
)}
|
||||
@ -112,6 +112,7 @@ export function HistoryView({
|
||||
}): VNode {
|
||||
const { i18n } = useTranslationContext();
|
||||
const currencies = balances.map((b) => b.available.split(":")[0]);
|
||||
const { pushAlertOnError } = useAlertContext();
|
||||
|
||||
const defaultCurrencyIndex = currencies.findIndex(
|
||||
(c) => c === defaultCurrency,
|
||||
@ -145,7 +146,7 @@ export function HistoryView({
|
||||
return (
|
||||
<NoBalanceHelp
|
||||
goToWalletManualWithdraw={{
|
||||
onClick: goToWalletManualWithdraw,
|
||||
onClick: pushAlertOnError(goToWalletManualWithdraw),
|
||||
}}
|
||||
/>
|
||||
);
|
||||
|
@ -21,7 +21,7 @@ import {
|
||||
} from "@gnu-taler/taler-util";
|
||||
import { WalletApiOperation } from "@gnu-taler/taler-wallet-core";
|
||||
import { useState } from "preact/hooks";
|
||||
import { alertFromError } from "../../context/alert.js";
|
||||
import { alertFromError, useAlertContext } from "../../context/alert.js";
|
||||
import { useBackendContext } from "../../context/backend.js";
|
||||
import { useTranslationContext } from "../../context/translation.js";
|
||||
import { useAsyncAsHook } from "../../hooks/useAsyncAsHook.js";
|
||||
@ -33,6 +33,7 @@ export function useComponentState({
|
||||
onCancel,
|
||||
}: Props): State {
|
||||
const api = useBackendContext();
|
||||
const { pushAlertOnError } = useAlertContext();
|
||||
const { i18n } = useTranslationContext();
|
||||
const hook = useAsyncAsHook(() =>
|
||||
api.wallet.call(WalletApiOperation.ListKnownBankAccounts, { currency }),
|
||||
@ -109,30 +110,30 @@ export function useComponentState({
|
||||
accountType: {
|
||||
list: accountType,
|
||||
value: type,
|
||||
onChange: async (v) => {
|
||||
onChange: pushAlertOnError(async (v) => {
|
||||
setType(v);
|
||||
},
|
||||
}),
|
||||
},
|
||||
alias: {
|
||||
value: alias,
|
||||
onInput: async (v) => {
|
||||
onInput: pushAlertOnError(async (v) => {
|
||||
setAlias(v);
|
||||
},
|
||||
}),
|
||||
},
|
||||
uri: {
|
||||
value: payto,
|
||||
error: paytoUriError,
|
||||
onInput: async (v) => {
|
||||
onInput: pushAlertOnError(async (v) => {
|
||||
setPayto(v);
|
||||
},
|
||||
}),
|
||||
},
|
||||
accountByType,
|
||||
deleteAccount,
|
||||
onAccountAdded: {
|
||||
onClick: unableToAdd ? undefined : addAccount,
|
||||
onClick: unableToAdd ? undefined : pushAlertOnError(addAccount),
|
||||
},
|
||||
onCancel: {
|
||||
onClick: async () => onCancel(),
|
||||
onClick: pushAlertOnError(async () => onCancel()),
|
||||
},
|
||||
};
|
||||
}
|
||||
|
@ -19,18 +19,15 @@
|
||||
* @author Sebastian Javier Marchano (sebasjm)
|
||||
*/
|
||||
|
||||
import { createExample } from "../../test-utils.js";
|
||||
import { tests } from "@gnu-taler/web-util/lib/index.browser";
|
||||
import { nullFunction } from "../../mui/handlers.js";
|
||||
import { ReadyView } from "./views.js";
|
||||
|
||||
export default {
|
||||
title: "manage account",
|
||||
};
|
||||
|
||||
const nullFunction = async () => {
|
||||
null;
|
||||
};
|
||||
|
||||
export const JustTwoBitcoinAccounts = createExample(ReadyView, {
|
||||
export const JustTwoBitcoinAccounts = tests.createExample(ReadyView, {
|
||||
status: "ready",
|
||||
currency: "ARS",
|
||||
accountType: {
|
||||
@ -84,7 +81,7 @@ export const JustTwoBitcoinAccounts = createExample(ReadyView, {
|
||||
onCancel: {},
|
||||
});
|
||||
|
||||
export const WithAllTypeOfAccounts = createExample(ReadyView, {
|
||||
export const WithAllTypeOfAccounts = tests.createExample(ReadyView, {
|
||||
status: "ready",
|
||||
currency: "ARS",
|
||||
accountType: {
|
||||
@ -165,7 +162,7 @@ export const WithAllTypeOfAccounts = createExample(ReadyView, {
|
||||
onCancel: {},
|
||||
});
|
||||
|
||||
export const AddingIbanAccount = createExample(ReadyView, {
|
||||
export const AddingIbanAccount = tests.createExample(ReadyView, {
|
||||
status: "ready",
|
||||
currency: "ARS",
|
||||
accountType: {
|
||||
|
@ -20,14 +20,14 @@
|
||||
*/
|
||||
|
||||
import { AbsoluteTime, AttentionType } from "@gnu-taler/taler-util";
|
||||
import { createExample } from "../../test-utils.js";
|
||||
import { tests } from "@gnu-taler/web-util/lib/index.browser";
|
||||
import { ReadyView } from "./views.js";
|
||||
|
||||
export default {
|
||||
title: "notifications",
|
||||
};
|
||||
|
||||
export const Ready = createExample(ReadyView, {
|
||||
export const Ready = tests.createExample(ReadyView, {
|
||||
list: [
|
||||
{
|
||||
when: AbsoluteTime.now(),
|
||||
|
@ -19,7 +19,7 @@
|
||||
* @author Sebastian Javier Marchano (sebasjm)
|
||||
*/
|
||||
|
||||
import { createExample } from "../test-utils.js";
|
||||
import { tests } from "@gnu-taler/web-util/lib/index.browser";
|
||||
import { ConfirmProviderView as TestedComponent } from "./ProviderAddPage.js";
|
||||
|
||||
export default {
|
||||
@ -32,7 +32,7 @@ export default {
|
||||
},
|
||||
};
|
||||
|
||||
export const DemoService = createExample(TestedComponent, {
|
||||
export const DemoService = tests.createExample(TestedComponent, {
|
||||
url: "https://sync.demo.taler.net/",
|
||||
provider: {
|
||||
annual_fee: "KUDOS:0.1",
|
||||
@ -41,7 +41,7 @@ export const DemoService = createExample(TestedComponent, {
|
||||
},
|
||||
});
|
||||
|
||||
export const FreeService = createExample(TestedComponent, {
|
||||
export const FreeService = tests.createExample(TestedComponent, {
|
||||
url: "https://sync.taler:9667/",
|
||||
provider: {
|
||||
annual_fee: "ARS:0",
|
||||
|
@ -19,7 +19,7 @@
|
||||
* @author Sebastian Javier Marchano (sebasjm)
|
||||
*/
|
||||
|
||||
import { createExample } from "../test-utils.js";
|
||||
import { tests } from "@gnu-taler/web-util/lib/index.browser";
|
||||
import { SetUrlView as TestedComponent } from "./ProviderAddPage.js";
|
||||
|
||||
export default {
|
||||
@ -32,20 +32,20 @@ export default {
|
||||
},
|
||||
};
|
||||
|
||||
export const Initial = createExample(TestedComponent, {});
|
||||
export const Initial = tests.createExample(TestedComponent, {});
|
||||
|
||||
export const WithValue = createExample(TestedComponent, {
|
||||
export const WithValue = tests.createExample(TestedComponent, {
|
||||
initialValue: "sync.demo.taler.net",
|
||||
});
|
||||
|
||||
export const WithConnectionError = createExample(TestedComponent, {
|
||||
export const WithConnectionError = tests.createExample(TestedComponent, {
|
||||
withError: "Network error",
|
||||
});
|
||||
|
||||
export const WithClientError = createExample(TestedComponent, {
|
||||
export const WithClientError = tests.createExample(TestedComponent, {
|
||||
withError: "URL may not be right: (404) Not Found",
|
||||
});
|
||||
|
||||
export const WithServerError = createExample(TestedComponent, {
|
||||
export const WithServerError = tests.createExample(TestedComponent, {
|
||||
withError: "Try another server: (500) Internal Server Error",
|
||||
});
|
||||
|
@ -21,7 +21,7 @@
|
||||
|
||||
import { TalerProtocolTimestamp } from "@gnu-taler/taler-util";
|
||||
import { ProviderPaymentType } from "@gnu-taler/taler-wallet-core";
|
||||
import { createExample } from "../test-utils.js";
|
||||
import { tests } from "@gnu-taler/web-util/lib/index.browser";
|
||||
import { ProviderView as TestedComponent } from "./ProviderDetailPage.js";
|
||||
|
||||
export default {
|
||||
@ -34,7 +34,7 @@ export default {
|
||||
},
|
||||
};
|
||||
|
||||
export const Active = createExample(TestedComponent, {
|
||||
export const Active = tests.createExample(TestedComponent, {
|
||||
info: {
|
||||
active: true,
|
||||
name: "sync.demo",
|
||||
@ -58,7 +58,7 @@ export const Active = createExample(TestedComponent, {
|
||||
},
|
||||
});
|
||||
|
||||
export const ActiveErrorSync = createExample(TestedComponent, {
|
||||
export const ActiveErrorSync = tests.createExample(TestedComponent, {
|
||||
info: {
|
||||
active: true,
|
||||
name: "sync.demo",
|
||||
@ -79,6 +79,7 @@ export const ActiveErrorSync = createExample(TestedComponent, {
|
||||
lastError: {
|
||||
code: 2002,
|
||||
details: "details",
|
||||
when: new Date().toISOString(),
|
||||
hint: "error hint from the server",
|
||||
message: "message",
|
||||
},
|
||||
@ -90,7 +91,9 @@ export const ActiveErrorSync = createExample(TestedComponent, {
|
||||
},
|
||||
});
|
||||
|
||||
export const ActiveBackupProblemUnreadable = createExample(TestedComponent, {
|
||||
export const ActiveBackupProblemUnreadable = tests.createExample(
|
||||
TestedComponent,
|
||||
{
|
||||
info: {
|
||||
active: true,
|
||||
name: "sync.demo",
|
||||
@ -115,9 +118,10 @@ export const ActiveBackupProblemUnreadable = createExample(TestedComponent, {
|
||||
supportedProtocolVersion: "0.0",
|
||||
},
|
||||
},
|
||||
});
|
||||
},
|
||||
);
|
||||
|
||||
export const ActiveBackupProblemDevice = createExample(TestedComponent, {
|
||||
export const ActiveBackupProblemDevice = tests.createExample(TestedComponent, {
|
||||
info: {
|
||||
active: true,
|
||||
name: "sync.demo",
|
||||
@ -149,7 +153,7 @@ export const ActiveBackupProblemDevice = createExample(TestedComponent, {
|
||||
},
|
||||
});
|
||||
|
||||
export const InactiveUnpaid = createExample(TestedComponent, {
|
||||
export const InactiveUnpaid = tests.createExample(TestedComponent, {
|
||||
info: {
|
||||
active: false,
|
||||
name: "sync.demo",
|
||||
@ -166,7 +170,9 @@ export const InactiveUnpaid = createExample(TestedComponent, {
|
||||
},
|
||||
});
|
||||
|
||||
export const InactiveInsufficientBalance = createExample(TestedComponent, {
|
||||
export const InactiveInsufficientBalance = tests.createExample(
|
||||
TestedComponent,
|
||||
{
|
||||
info: {
|
||||
active: false,
|
||||
name: "sync.demo",
|
||||
@ -182,9 +188,10 @@ export const InactiveInsufficientBalance = createExample(TestedComponent, {
|
||||
supportedProtocolVersion: "0.0",
|
||||
},
|
||||
},
|
||||
});
|
||||
},
|
||||
);
|
||||
|
||||
export const InactivePending = createExample(TestedComponent, {
|
||||
export const InactivePending = tests.createExample(TestedComponent, {
|
||||
info: {
|
||||
active: false,
|
||||
name: "sync.demo",
|
||||
@ -202,7 +209,7 @@ export const InactivePending = createExample(TestedComponent, {
|
||||
},
|
||||
});
|
||||
|
||||
export const ActiveTermsChanged = createExample(TestedComponent, {
|
||||
export const ActiveTermsChanged = tests.createExample(TestedComponent, {
|
||||
info: {
|
||||
active: true,
|
||||
name: "sync.demo",
|
||||
|
@ -23,7 +23,7 @@ import {
|
||||
WalletApiOperation,
|
||||
} from "@gnu-taler/taler-wallet-core";
|
||||
import { Fragment, h, VNode } from "preact";
|
||||
import { AlertView } from "../components/CurrentAlerts.js";
|
||||
import { ErrorAlertView } from "../components/CurrentAlerts.js";
|
||||
import { ErrorMessage } from "../components/ErrorMessage.js";
|
||||
import { Loading } from "../components/Loading.js";
|
||||
import { PaymentStatus, SmallLightText } from "../components/styled/index.js";
|
||||
@ -66,8 +66,8 @@ export function ProviderDetailPage({
|
||||
}
|
||||
if (state.hasError) {
|
||||
return (
|
||||
<AlertView
|
||||
alert={alertFromError(
|
||||
<ErrorAlertView
|
||||
error={alertFromError(
|
||||
i18n.str`There was an error loading the provider detail for "${providerURL}"`,
|
||||
state,
|
||||
)}
|
||||
|
@ -19,11 +19,11 @@
|
||||
* @author Sebastian Javier Marchano (sebasjm)
|
||||
*/
|
||||
|
||||
import { createExample } from "../test-utils.js";
|
||||
import { tests } from "@gnu-taler/web-util/lib/index.browser";
|
||||
import { QrReaderPage } from "./QrReader.js";
|
||||
|
||||
export default {
|
||||
title: "qr reader",
|
||||
};
|
||||
|
||||
export const Reading = createExample(QrReaderPage, {});
|
||||
export const Reading = tests.createExample(QrReaderPage, {});
|
||||
|
@ -20,7 +20,7 @@
|
||||
*/
|
||||
|
||||
import { parsePaytoUri } from "@gnu-taler/taler-util";
|
||||
import { createExample } from "../test-utils.js";
|
||||
import { tests } from "@gnu-taler/web-util/lib/index.browser";
|
||||
import { ReserveCreated as TestedComponent } from "./ReserveCreated.js";
|
||||
|
||||
export default {
|
||||
@ -29,7 +29,7 @@ export default {
|
||||
argTypes: {},
|
||||
};
|
||||
|
||||
export const TalerBank = createExample(TestedComponent, {
|
||||
export const TalerBank = tests.createExample(TestedComponent, {
|
||||
reservePub: "A05AJGMFNSK4Q62NXR2FKNDB1J4EXTYQTE7VA4M9GZQ4TR06YBNG",
|
||||
paytoURI: parsePaytoUri(
|
||||
"payto://x-taler-bank/bank.taler:5882/exchangeminator?amount=COL%3A1&message=Taler+Withdrawal+A05AJGMFNSK4Q62NXR2FKNDB1J4EXTYQTE7VA4M9GZQ4TR06YBNG",
|
||||
@ -42,7 +42,7 @@ export const TalerBank = createExample(TestedComponent, {
|
||||
exchangeBaseUrl: "https://exchange.demo.taler.net",
|
||||
});
|
||||
|
||||
export const IBAN = createExample(TestedComponent, {
|
||||
export const IBAN = tests.createExample(TestedComponent, {
|
||||
reservePub: "A05AJGMFNSK4Q62NXR2FKNDB1J4EXTYQTE7VA4M9GZQ4TR06YBNG",
|
||||
paytoURI: parsePaytoUri(
|
||||
"payto://iban/ES8877998399652238?amount=COL%3A1&message=Taler+Withdrawal+A05AJGMFNSK4Q62NXR2FKNDB1J4EXTYQTE7VA4M9GZQ4TR06YBNG",
|
||||
@ -55,7 +55,7 @@ export const IBAN = createExample(TestedComponent, {
|
||||
exchangeBaseUrl: "https://exchange.demo.taler.net",
|
||||
});
|
||||
|
||||
export const WithReceiverName = createExample(TestedComponent, {
|
||||
export const WithReceiverName = tests.createExample(TestedComponent, {
|
||||
reservePub: "A05AJGMFNSK4Q62NXR2FKNDB1J4EXTYQTE7VA4M9GZQ4TR06YBNG",
|
||||
paytoURI: parsePaytoUri(
|
||||
"payto://iban/ES8877998399652238?amount=COL%3A1&message=Taler+Withdrawal+A05AJGMFNSK4Q62NXR2FKNDB1J4EXTYQTE7VA4M9GZQ4TR06YBNG&receiver=Sebastian",
|
||||
@ -68,7 +68,7 @@ export const WithReceiverName = createExample(TestedComponent, {
|
||||
exchangeBaseUrl: "https://exchange.demo.taler.net",
|
||||
});
|
||||
|
||||
export const Bitcoin = createExample(TestedComponent, {
|
||||
export const Bitcoin = tests.createExample(TestedComponent, {
|
||||
reservePub: "0ZSX8SH0M30KHX8K3Y1DAMVGDQV82XEF9DG1HC4QMQ3QWYT4AF00",
|
||||
paytoURI: parsePaytoUri(
|
||||
"payto://bitcoin/bc1qw508d6qejxtdg4y5r3zarvary0c5xw7kv8f3t4?amount=BTC:0.1&subject=0ZSX8SH0M30KHX8K3Y1DAMVGDQV82XEF9DG1HC4QMQ3QWYT4AF00",
|
||||
@ -81,7 +81,7 @@ export const Bitcoin = createExample(TestedComponent, {
|
||||
exchangeBaseUrl: "https://exchange.demo.taler.net",
|
||||
});
|
||||
|
||||
export const BitcoinRegTest = createExample(TestedComponent, {
|
||||
export const BitcoinRegTest = tests.createExample(TestedComponent, {
|
||||
reservePub: "0ZSX8SH0M30KHX8K3Y1DAMVGDQV82XEF9DG1HC4QMQ3QWYT4AF00",
|
||||
paytoURI: parsePaytoUri(
|
||||
"payto://bitcoin/bcrt1q6ps8qs6v8tkqrnru4xqqqa6rfwcx5ufpdfqht4?amount=BTC:0.1&subject=0ZSX8SH0M30KHX8K3Y1DAMVGDQV82XEF9DG1HC4QMQ3QWYT4AF00",
|
||||
@ -93,7 +93,7 @@ export const BitcoinRegTest = createExample(TestedComponent, {
|
||||
},
|
||||
exchangeBaseUrl: "https://exchange.demo.taler.net",
|
||||
});
|
||||
export const BitcoinTest = createExample(TestedComponent, {
|
||||
export const BitcoinTest = tests.createExample(TestedComponent, {
|
||||
reservePub: "0ZSX8SH0M30KHX8K3Y1DAMVGDQV82XEF9DG1HC4QMQ3QWYT4AF00",
|
||||
paytoURI: parsePaytoUri(
|
||||
"payto://bitcoin/tb1qw508d6qejxtdg4y5r3zarvary0c5xw7kxpjzsx?amount=BTC:0.1&subject=0ZSX8SH0M30KHX8K3Y1DAMVGDQV82XEF9DG1HC4QMQ3QWYT4AF00",
|
||||
|
@ -19,7 +19,7 @@
|
||||
* @author Sebastian Javier Marchano (sebasjm)
|
||||
*/
|
||||
|
||||
import { createExample } from "../test-utils.js";
|
||||
import { tests } from "@gnu-taler/web-util/lib/index.browser";
|
||||
import { SettingsView as TestedComponent } from "./Settings.js";
|
||||
|
||||
export default {
|
||||
@ -45,7 +45,7 @@ const version = {
|
||||
},
|
||||
};
|
||||
|
||||
export const AllOff = createExample(TestedComponent, {
|
||||
export const AllOff = tests.createExample(TestedComponent, {
|
||||
deviceName: "this-is-the-device-name",
|
||||
devModeToggle: { value: false, button: {} },
|
||||
autoOpenToggle: { value: false, button: {} },
|
||||
@ -54,7 +54,7 @@ export const AllOff = createExample(TestedComponent, {
|
||||
...version,
|
||||
});
|
||||
|
||||
export const OneChecked = createExample(TestedComponent, {
|
||||
export const OneChecked = tests.createExample(TestedComponent, {
|
||||
deviceName: "this-is-the-device-name",
|
||||
devModeToggle: { value: false, button: {} },
|
||||
autoOpenToggle: { value: false, button: {} },
|
||||
@ -63,7 +63,7 @@ export const OneChecked = createExample(TestedComponent, {
|
||||
...version,
|
||||
});
|
||||
|
||||
export const WithOneExchange = createExample(TestedComponent, {
|
||||
export const WithOneExchange = tests.createExample(TestedComponent, {
|
||||
deviceName: "this-is-the-device-name",
|
||||
devModeToggle: { value: false, button: {} },
|
||||
autoOpenToggle: { value: false, button: {} },
|
||||
@ -85,7 +85,9 @@ export const WithOneExchange = createExample(TestedComponent, {
|
||||
...version,
|
||||
});
|
||||
|
||||
export const WithExchangeInDifferentState = createExample(TestedComponent, {
|
||||
export const WithExchangeInDifferentState = tests.createExample(
|
||||
TestedComponent,
|
||||
{
|
||||
deviceName: "this-is-the-device-name",
|
||||
devModeToggle: { value: false, button: {} },
|
||||
autoOpenToggle: { value: false, button: {} },
|
||||
@ -101,7 +103,9 @@ export const WithExchangeInDifferentState = createExample(TestedComponent, {
|
||||
content: "content of tos",
|
||||
contentType: "text/plain",
|
||||
},
|
||||
paytoUris: ["payto://x-taler-bank/bank.rpi.sebasjm.com/exchangeminator"],
|
||||
paytoUris: [
|
||||
"payto://x-taler-bank/bank.rpi.sebasjm.com/exchangeminator",
|
||||
],
|
||||
},
|
||||
{
|
||||
currency: "USD",
|
||||
@ -112,7 +116,9 @@ export const WithExchangeInDifferentState = createExample(TestedComponent, {
|
||||
content: "content of tos",
|
||||
contentType: "text/plain",
|
||||
},
|
||||
paytoUris: ["payto://x-taler-bank/bank.rpi.sebasjm.com/exchangeminator"],
|
||||
paytoUris: [
|
||||
"payto://x-taler-bank/bank.rpi.sebasjm.com/exchangeminator",
|
||||
],
|
||||
} as any, //TODO: complete with auditors, wireInfo and denominations
|
||||
{
|
||||
currency: "USD",
|
||||
@ -122,8 +128,11 @@ export const WithExchangeInDifferentState = createExample(TestedComponent, {
|
||||
content: "content of tos",
|
||||
contentType: "text/plain",
|
||||
},
|
||||
paytoUris: ["payto://x-taler-bank/bank.rpi.sebasjm.com/exchangeminator"],
|
||||
paytoUris: [
|
||||
"payto://x-taler-bank/bank.rpi.sebasjm.com/exchangeminator",
|
||||
],
|
||||
},
|
||||
],
|
||||
...version,
|
||||
});
|
||||
},
|
||||
);
|
||||
|
@ -22,7 +22,6 @@ import {
|
||||
import { WalletApiOperation } from "@gnu-taler/taler-wallet-core";
|
||||
import { Fragment, h, VNode } from "preact";
|
||||
import { Checkbox } from "../components/Checkbox.js";
|
||||
import { ErrorTalerOperation } from "../components/ErrorTalerOperation.js";
|
||||
import { JustInDevMode } from "../components/JustInDevMode.js";
|
||||
import { Part } from "../components/Part.js";
|
||||
import { SelectList } from "../components/SelectList.js";
|
||||
@ -34,6 +33,7 @@ import {
|
||||
SuccessText,
|
||||
WarningText,
|
||||
} from "../components/styled/index.js";
|
||||
import { useAlertContext } from "../context/alert.js";
|
||||
import { useBackendContext } from "../context/backend.js";
|
||||
import { useDevContext } from "../context/devContext.js";
|
||||
import { useTranslationContext } from "../context/translation.js";
|
||||
@ -50,8 +50,9 @@ const GIT_HASH = typeof __GIT_HASH__ !== "undefined" ? __GIT_HASH__ : undefined;
|
||||
export function SettingsPage(): VNode {
|
||||
const autoOpenToggle = useAutoOpenPermissions();
|
||||
const clipboardToggle = useClipboardPermissions();
|
||||
const { devModeToggle } = useDevContext();
|
||||
const { devMode, toggle } = useDevContext();
|
||||
const { name, update } = useBackupDeviceName();
|
||||
const { pushAlertOnError } = useAlertContext();
|
||||
const webex = platform.getWalletWebExVersion();
|
||||
const api = useBackendContext();
|
||||
|
||||
@ -72,7 +73,12 @@ export function SettingsPage(): VNode {
|
||||
setDeviceName={update}
|
||||
autoOpenToggle={autoOpenToggle}
|
||||
clipboardToggle={clipboardToggle}
|
||||
devModeToggle={devModeToggle}
|
||||
devModeToggle={{
|
||||
value: devMode,
|
||||
button: {
|
||||
onClick: pushAlertOnError(toggle),
|
||||
},
|
||||
}}
|
||||
webexVersion={{
|
||||
version: webex.version,
|
||||
hash: GIT_HASH,
|
||||
@ -109,18 +115,6 @@ export function SettingsView({
|
||||
return (
|
||||
<Fragment>
|
||||
<section>
|
||||
{autoOpenToggle.button.error && (
|
||||
<ErrorTalerOperation
|
||||
title={i18n.str`Could not toggle auto-open`}
|
||||
error={autoOpenToggle.button.error.errorDetail}
|
||||
/>
|
||||
)}
|
||||
{/* {clipboardToggle.button.error && (
|
||||
<ErrorTalerOperation
|
||||
title={i18n.str`Could not toggle clipboard`}
|
||||
error={clipboardToggle.button.error.errorDetail}
|
||||
/>
|
||||
)} */}
|
||||
<SubTitle>
|
||||
<i18n.Translate>Navigator</i18n.Translate>
|
||||
</SubTitle>
|
||||
|
@ -39,11 +39,13 @@ import {
|
||||
WithdrawalType,
|
||||
} from "@gnu-taler/taler-util";
|
||||
import { DevContextProviderForTesting } from "../context/devContext.js";
|
||||
import {
|
||||
createExample,
|
||||
createExampleWithCustomContext as createExampleInCustomContext,
|
||||
} from "../test-utils.js";
|
||||
// import {
|
||||
// createExample,
|
||||
// createExampleWithCustomContext as createExampleInCustomContext,
|
||||
// } from "../test-utils.js";
|
||||
import { TransactionView as TestedComponent } from "./Transaction.js";
|
||||
import { tests } from "@gnu-taler/web-util/lib/index.browser";
|
||||
import beer from "../../static-dev/beer.png";
|
||||
|
||||
export default {
|
||||
title: "transaction details",
|
||||
@ -214,24 +216,28 @@ const transactionError = {
|
||||
hint: "The payment is too late, the offer has expired.",
|
||||
},
|
||||
},
|
||||
when: new Date().toISOString(),
|
||||
hint: "Error: WALLET_UNEXPECTED_REQUEST_ERROR",
|
||||
message: "Unexpected error code in response",
|
||||
};
|
||||
|
||||
export const Withdraw = createExample(TestedComponent, {
|
||||
export const Withdraw = tests.createExample(TestedComponent, {
|
||||
transaction: exampleData.withdraw,
|
||||
});
|
||||
|
||||
export const WithdrawFiveMinutesAgo = createExample(TestedComponent, () => ({
|
||||
export const WithdrawFiveMinutesAgo = tests.createExample(
|
||||
TestedComponent,
|
||||
() => ({
|
||||
transaction: {
|
||||
...exampleData.withdraw,
|
||||
timestamp: TalerProtocolTimestamp.fromSeconds(
|
||||
new Date().getTime() / 1000 - 60 * 5,
|
||||
),
|
||||
},
|
||||
}));
|
||||
}),
|
||||
);
|
||||
|
||||
export const WithdrawFiveMinutesAgoAndPending = createExample(
|
||||
export const WithdrawFiveMinutesAgoAndPending = tests.createExample(
|
||||
TestedComponent,
|
||||
() => ({
|
||||
transaction: {
|
||||
@ -244,26 +250,28 @@ export const WithdrawFiveMinutesAgoAndPending = createExample(
|
||||
}),
|
||||
);
|
||||
|
||||
export const WithdrawError = createExample(TestedComponent, {
|
||||
export const WithdrawError = tests.createExample(TestedComponent, {
|
||||
transaction: {
|
||||
...exampleData.withdraw,
|
||||
error: transactionError,
|
||||
},
|
||||
});
|
||||
|
||||
export const WithdrawErrorInDevMode = createExampleInCustomContext(
|
||||
TestedComponent,
|
||||
{
|
||||
transaction: {
|
||||
...exampleData.withdraw,
|
||||
error: transactionError,
|
||||
},
|
||||
},
|
||||
DevContextProviderForTesting,
|
||||
{ value: true },
|
||||
);
|
||||
// export const WithdrawErrorInDevMode = tests.createExampleInCustomContext(
|
||||
// TestedComponent,
|
||||
// {
|
||||
// transaction: {
|
||||
// ...exampleData.withdraw,
|
||||
// error: transactionError,
|
||||
// },
|
||||
// },
|
||||
// DevContextProviderForTesting,
|
||||
// { value: true },
|
||||
// );
|
||||
|
||||
export const WithdrawPendingManual = createExample(TestedComponent, () => ({
|
||||
export const WithdrawPendingManual = tests.createExample(
|
||||
TestedComponent,
|
||||
() => ({
|
||||
transaction: {
|
||||
...exampleData.withdraw,
|
||||
withdrawalDetails: {
|
||||
@ -273,9 +281,10 @@ export const WithdrawPendingManual = createExample(TestedComponent, () => ({
|
||||
} as WithdrawalDetails,
|
||||
pending: true,
|
||||
},
|
||||
}));
|
||||
}),
|
||||
);
|
||||
|
||||
export const WithdrawPendingTalerBankUnconfirmed = createExample(
|
||||
export const WithdrawPendingTalerBankUnconfirmed = tests.createExample(
|
||||
TestedComponent,
|
||||
{
|
||||
transaction: {
|
||||
@ -291,7 +300,7 @@ export const WithdrawPendingTalerBankUnconfirmed = createExample(
|
||||
},
|
||||
);
|
||||
|
||||
export const WithdrawPendingTalerBankConfirmed = createExample(
|
||||
export const WithdrawPendingTalerBankConfirmed = tests.createExample(
|
||||
TestedComponent,
|
||||
{
|
||||
transaction: {
|
||||
@ -306,18 +315,18 @@ export const WithdrawPendingTalerBankConfirmed = createExample(
|
||||
},
|
||||
);
|
||||
|
||||
export const Payment = createExample(TestedComponent, {
|
||||
export const Payment = tests.createExample(TestedComponent, {
|
||||
transaction: exampleData.payment,
|
||||
});
|
||||
|
||||
export const PaymentError = createExample(TestedComponent, {
|
||||
export const PaymentError = tests.createExample(TestedComponent, {
|
||||
transaction: {
|
||||
...exampleData.payment,
|
||||
error: transactionError,
|
||||
},
|
||||
});
|
||||
|
||||
export const PaymentWithRefund = createExample(TestedComponent, {
|
||||
export const PaymentWithRefund = tests.createExample(TestedComponent, {
|
||||
transaction: {
|
||||
...exampleData.payment,
|
||||
amountRaw: "KUDOS:12",
|
||||
@ -334,7 +343,7 @@ export const PaymentWithRefund = createExample(TestedComponent, {
|
||||
},
|
||||
});
|
||||
|
||||
export const PaymentWithDeliveryDate = createExample(TestedComponent, {
|
||||
export const PaymentWithDeliveryDate = tests.createExample(TestedComponent, {
|
||||
transaction: {
|
||||
...exampleData.payment,
|
||||
amountRaw: "KUDOS:12",
|
||||
@ -347,7 +356,7 @@ export const PaymentWithDeliveryDate = createExample(TestedComponent, {
|
||||
},
|
||||
});
|
||||
|
||||
export const PaymentWithDeliveryAddr = createExample(TestedComponent, {
|
||||
export const PaymentWithDeliveryAddr = tests.createExample(TestedComponent, {
|
||||
transaction: {
|
||||
...exampleData.payment,
|
||||
amountRaw: "KUDOS:12",
|
||||
@ -363,7 +372,7 @@ export const PaymentWithDeliveryAddr = createExample(TestedComponent, {
|
||||
},
|
||||
});
|
||||
|
||||
export const PaymentWithDeliveryFull = createExample(TestedComponent, {
|
||||
export const PaymentWithDeliveryFull = tests.createExample(TestedComponent, {
|
||||
transaction: {
|
||||
...exampleData.payment,
|
||||
amountRaw: "KUDOS:12",
|
||||
@ -382,7 +391,7 @@ export const PaymentWithDeliveryFull = createExample(TestedComponent, {
|
||||
},
|
||||
});
|
||||
|
||||
export const PaymentWithRefundPending = createExample(TestedComponent, {
|
||||
export const PaymentWithRefundPending = tests.createExample(TestedComponent, {
|
||||
transaction: {
|
||||
...exampleData.payment,
|
||||
amountRaw: "KUDOS:12",
|
||||
@ -392,7 +401,7 @@ export const PaymentWithRefundPending = createExample(TestedComponent, {
|
||||
},
|
||||
});
|
||||
|
||||
export const PaymentWithFeeAndRefund = createExample(TestedComponent, {
|
||||
export const PaymentWithFeeAndRefund = tests.createExample(TestedComponent, {
|
||||
transaction: {
|
||||
...exampleData.payment,
|
||||
amountRaw: "KUDOS:11",
|
||||
@ -401,7 +410,7 @@ export const PaymentWithFeeAndRefund = createExample(TestedComponent, {
|
||||
},
|
||||
});
|
||||
|
||||
export const PaymentWithFeeAndRefundFee = createExample(TestedComponent, {
|
||||
export const PaymentWithFeeAndRefundFee = tests.createExample(TestedComponent, {
|
||||
transaction: {
|
||||
...exampleData.payment,
|
||||
amountRaw: "KUDOS:11",
|
||||
@ -410,20 +419,18 @@ export const PaymentWithFeeAndRefundFee = createExample(TestedComponent, {
|
||||
},
|
||||
});
|
||||
|
||||
export const PaymentWithoutFee = createExample(TestedComponent, {
|
||||
export const PaymentWithoutFee = tests.createExample(TestedComponent, {
|
||||
transaction: {
|
||||
...exampleData.payment,
|
||||
amountRaw: "KUDOS:12",
|
||||
},
|
||||
});
|
||||
|
||||
export const PaymentPending = createExample(TestedComponent, {
|
||||
export const PaymentPending = tests.createExample(TestedComponent, {
|
||||
transaction: { ...exampleData.payment, pending: true },
|
||||
});
|
||||
|
||||
import beer from "../../static-dev/beer.png";
|
||||
|
||||
export const PaymentWithProducts = createExample(TestedComponent, {
|
||||
export const PaymentWithProducts = tests.createExample(TestedComponent, {
|
||||
transaction: {
|
||||
...exampleData.payment,
|
||||
info: {
|
||||
@ -460,7 +467,7 @@ export const PaymentWithProducts = createExample(TestedComponent, {
|
||||
} as TransactionPayment,
|
||||
});
|
||||
|
||||
export const PaymentWithLongSummary = createExample(TestedComponent, {
|
||||
export const PaymentWithLongSummary = tests.createExample(TestedComponent, {
|
||||
transaction: {
|
||||
...exampleData.payment,
|
||||
info: {
|
||||
@ -484,16 +491,16 @@ export const PaymentWithLongSummary = createExample(TestedComponent, {
|
||||
} as TransactionPayment,
|
||||
});
|
||||
|
||||
export const Deposit = createExample(TestedComponent, {
|
||||
export const Deposit = tests.createExample(TestedComponent, {
|
||||
transaction: exampleData.deposit,
|
||||
});
|
||||
export const DepositTalerBank = createExample(TestedComponent, {
|
||||
export const DepositTalerBank = tests.createExample(TestedComponent, {
|
||||
transaction: {
|
||||
...exampleData.deposit,
|
||||
targetPaytoUri: "payto://x-taler-bank/bank.demo.taler.net/Exchange",
|
||||
},
|
||||
});
|
||||
export const DepositBitcoin = createExample(TestedComponent, {
|
||||
export const DepositBitcoin = tests.createExample(TestedComponent, {
|
||||
transaction: {
|
||||
...exampleData.deposit,
|
||||
amountRaw: "BITCOINBTC:0.0000011",
|
||||
@ -502,88 +509,88 @@ export const DepositBitcoin = createExample(TestedComponent, {
|
||||
"payto://bitcoin/bcrt1q6ps8qs6v8tkqrnru4xqqqa6rfwcx5ufpdfqht4?amount=BTC:0.1&subject=0ZSX8SH0M30KHX8K3Y1DAMVGDQV82XEF9DG1HC4QMQ3QWYT4AF00",
|
||||
},
|
||||
});
|
||||
export const DepositIBAN = createExample(TestedComponent, {
|
||||
export const DepositIBAN = tests.createExample(TestedComponent, {
|
||||
transaction: {
|
||||
...exampleData.deposit,
|
||||
targetPaytoUri: "payto://iban/ES8877998399652238",
|
||||
},
|
||||
});
|
||||
|
||||
export const DepositError = createExample(TestedComponent, {
|
||||
export const DepositError = tests.createExample(TestedComponent, {
|
||||
transaction: {
|
||||
...exampleData.deposit,
|
||||
error: transactionError,
|
||||
},
|
||||
});
|
||||
|
||||
export const DepositPending = createExample(TestedComponent, {
|
||||
export const DepositPending = tests.createExample(TestedComponent, {
|
||||
transaction: { ...exampleData.deposit, pending: true },
|
||||
});
|
||||
|
||||
export const Refresh = createExample(TestedComponent, {
|
||||
export const Refresh = tests.createExample(TestedComponent, {
|
||||
transaction: exampleData.refresh,
|
||||
});
|
||||
|
||||
export const RefreshError = createExample(TestedComponent, {
|
||||
export const RefreshError = tests.createExample(TestedComponent, {
|
||||
transaction: {
|
||||
...exampleData.refresh,
|
||||
error: transactionError,
|
||||
},
|
||||
});
|
||||
|
||||
export const Tip = createExample(TestedComponent, {
|
||||
export const Tip = tests.createExample(TestedComponent, {
|
||||
transaction: exampleData.tip,
|
||||
});
|
||||
|
||||
export const TipError = createExample(TestedComponent, {
|
||||
export const TipError = tests.createExample(TestedComponent, {
|
||||
transaction: {
|
||||
...exampleData.tip,
|
||||
error: transactionError,
|
||||
},
|
||||
});
|
||||
|
||||
export const TipPending = createExample(TestedComponent, {
|
||||
export const TipPending = tests.createExample(TestedComponent, {
|
||||
transaction: { ...exampleData.tip, pending: true },
|
||||
});
|
||||
|
||||
export const Refund = createExample(TestedComponent, {
|
||||
export const Refund = tests.createExample(TestedComponent, {
|
||||
transaction: exampleData.refund,
|
||||
});
|
||||
|
||||
export const RefundError = createExample(TestedComponent, {
|
||||
export const RefundError = tests.createExample(TestedComponent, {
|
||||
transaction: {
|
||||
...exampleData.refund,
|
||||
error: transactionError,
|
||||
},
|
||||
});
|
||||
|
||||
export const RefundPending = createExample(TestedComponent, {
|
||||
export const RefundPending = tests.createExample(TestedComponent, {
|
||||
transaction: { ...exampleData.refund, pending: true },
|
||||
});
|
||||
|
||||
export const InvoiceCreditComplete = createExample(TestedComponent, {
|
||||
export const InvoiceCreditComplete = tests.createExample(TestedComponent, {
|
||||
transaction: { ...exampleData.pull_credit },
|
||||
});
|
||||
|
||||
export const InvoiceCreditIncomplete = createExample(TestedComponent, {
|
||||
export const InvoiceCreditIncomplete = tests.createExample(TestedComponent, {
|
||||
transaction: {
|
||||
...exampleData.pull_credit,
|
||||
pending: true,
|
||||
},
|
||||
});
|
||||
|
||||
export const InvoiceDebit = createExample(TestedComponent, {
|
||||
export const InvoiceDebit = tests.createExample(TestedComponent, {
|
||||
transaction: { ...exampleData.pull_debit },
|
||||
});
|
||||
|
||||
export const TransferCredit = createExample(TestedComponent, {
|
||||
export const TransferCredit = tests.createExample(TestedComponent, {
|
||||
transaction: { ...exampleData.push_credit },
|
||||
});
|
||||
|
||||
export const TransferDebitComplete = createExample(TestedComponent, {
|
||||
export const TransferDebitComplete = tests.createExample(TestedComponent, {
|
||||
transaction: { ...exampleData.push_debit },
|
||||
});
|
||||
export const TransferDebitIncomplete = createExample(TestedComponent, {
|
||||
export const TransferDebitIncomplete = tests.createExample(TestedComponent, {
|
||||
transaction: {
|
||||
...exampleData.push_debit,
|
||||
pending: true,
|
||||
|
@ -44,7 +44,7 @@ import emptyImg from "../../static/img/empty.png";
|
||||
import { Amount } from "../components/Amount.js";
|
||||
import { BankDetailsByPaytoType } from "../components/BankDetailsByPaytoType.js";
|
||||
import { CopyButton } from "../components/CopyButton.js";
|
||||
import { AlertView, ErrorAlertView } from "../components/CurrentAlerts.js";
|
||||
import { ErrorAlertView } from "../components/CurrentAlerts.js";
|
||||
import { Loading } from "../components/Loading.js";
|
||||
import { Kind, Part, PartCollapsible, PartPayto } from "../components/Part.js";
|
||||
import { QR } from "../components/QR.js";
|
||||
@ -99,8 +99,8 @@ export function TransactionPage({
|
||||
|
||||
if (state.hasError) {
|
||||
return (
|
||||
<AlertView
|
||||
alert={alertFromError(
|
||||
<ErrorAlertView
|
||||
error={alertFromError(
|
||||
i18n.str`Could not load transaction information`,
|
||||
state,
|
||||
)}
|
||||
|
@ -19,7 +19,7 @@
|
||||
* @author Sebastian Javier Marchano (sebasjm)
|
||||
*/
|
||||
|
||||
import { createExample } from "../test-utils.js";
|
||||
import { tests } from "@gnu-taler/web-util/lib/index.browser";
|
||||
import { View as TestedComponent } from "./Welcome.js";
|
||||
|
||||
export default {
|
||||
@ -27,7 +27,7 @@ export default {
|
||||
component: TestedComponent,
|
||||
};
|
||||
|
||||
export const Normal = createExample(TestedComponent, {
|
||||
export const Normal = tests.createExample(TestedComponent, {
|
||||
permissionToggle: { value: true, button: {} },
|
||||
diagnostics: {
|
||||
errors: [],
|
||||
@ -38,11 +38,11 @@ export const Normal = createExample(TestedComponent, {
|
||||
},
|
||||
});
|
||||
|
||||
export const TimedoutDiagnostics = createExample(TestedComponent, {
|
||||
export const TimedoutDiagnostics = tests.createExample(TestedComponent, {
|
||||
timedOut: true,
|
||||
permissionToggle: { value: true, button: {} },
|
||||
});
|
||||
|
||||
export const RunningDiagnostics = createExample(TestedComponent, {
|
||||
export const RunningDiagnostics = tests.createExample(TestedComponent, {
|
||||
permissionToggle: { value: true, button: {} },
|
||||
});
|
||||
|
@ -93,22 +93,12 @@ export interface BackgroundApiClient {
|
||||
): Promise<BackgroundOperations[Op]["response"]>;
|
||||
}
|
||||
|
||||
export class WalletError extends Error {
|
||||
public errorDetail: TalerError;
|
||||
|
||||
constructor(op: string, e: TalerError) {
|
||||
super(`Wallet operation "${op}" failed: ${e.message}`);
|
||||
this.errorDetail = e;
|
||||
// Object.setPrototypeOf(this, WalletError.prototype);
|
||||
}
|
||||
}
|
||||
export class BackgroundError extends Error {
|
||||
public errorDetail: TalerErrorDetail;
|
||||
|
||||
constructor(op: string, e: TalerErrorDetail) {
|
||||
super(`Background operation "${op}" failed: ${e.message}`);
|
||||
constructor(title: string, e: TalerErrorDetail) {
|
||||
super(title);
|
||||
this.errorDetail = e;
|
||||
// Object.setPrototypeOf(this, BackgroundError.prototype);
|
||||
}
|
||||
}
|
||||
|
||||
@ -135,13 +125,17 @@ class BackgroundApiClientImpl implements BackgroundApiClient {
|
||||
if (error instanceof Error) {
|
||||
throw new BackgroundError(operation, {
|
||||
code: TalerErrorCode.GENERIC_UNEXPECTED_REQUEST_ERROR,
|
||||
when: new Date().toISOString(),
|
||||
});
|
||||
}
|
||||
throw error;
|
||||
}
|
||||
logger.info("got response", response);
|
||||
if (response.type === "error") {
|
||||
throw new BackgroundError(operation, response.error);
|
||||
throw new BackgroundError(
|
||||
`Background operation "${operation}" failed`,
|
||||
response.error,
|
||||
);
|
||||
}
|
||||
return response.result as any;
|
||||
}
|
||||
@ -169,8 +163,10 @@ class WalletApiClientImpl implements WalletCoreApiClient {
|
||||
}
|
||||
logger.info("got response", response);
|
||||
if (response.type === "error") {
|
||||
const error = TalerError.fromUncheckedDetail(response.error);
|
||||
throw new WalletError(operation, error);
|
||||
throw new BackgroundError(
|
||||
`Wallet operation "${operation}" failed`,
|
||||
response.error,
|
||||
);
|
||||
}
|
||||
return response.result as any;
|
||||
}
|
||||
|
Loading…
Reference in New Issue
Block a user