pretty
This commit is contained in:
parent
f93bd51499
commit
f1f8f818db
@ -25,7 +25,7 @@ import {
|
|||||||
LoadingUriView,
|
LoadingUriView,
|
||||||
ShowButtonsAcceptedTosView,
|
ShowButtonsAcceptedTosView,
|
||||||
ShowButtonsNonAcceptedTosView,
|
ShowButtonsNonAcceptedTosView,
|
||||||
ShowTosContentView
|
ShowTosContentView,
|
||||||
} from "./views.js";
|
} from "./views.js";
|
||||||
|
|
||||||
export interface Props {
|
export interface Props {
|
||||||
|
@ -21,10 +21,8 @@ import { useAsyncAsHook } from "../../hooks/useAsyncAsHook.js";
|
|||||||
import { Props, State } from "./index.js";
|
import { Props, State } from "./index.js";
|
||||||
import { buildTermsOfServiceState } from "./utils.js";
|
import { buildTermsOfServiceState } from "./utils.js";
|
||||||
|
|
||||||
export function useComponentState(
|
export function useComponentState({ exchangeUrl, onChange }: Props): State {
|
||||||
{ exchangeUrl, onChange }: Props,
|
const api = useBackendContext();
|
||||||
): State {
|
|
||||||
const api = useBackendContext()
|
|
||||||
const readOnly = !onChange;
|
const readOnly = !onChange;
|
||||||
const [showContent, setShowContent] = useState<boolean>(readOnly);
|
const [showContent, setShowContent] = useState<boolean>(readOnly);
|
||||||
const [errorAccepting, setErrorAccepting] = useState<Error | undefined>(
|
const [errorAccepting, setErrorAccepting] = useState<Error | undefined>(
|
||||||
|
@ -23,7 +23,7 @@ import { ComponentChildren, createContext, h, VNode } from "preact";
|
|||||||
import { useContext } from "preact/hooks";
|
import { useContext } from "preact/hooks";
|
||||||
import { wxApi, WxApiType } from "../wxApi.js";
|
import { wxApi, WxApiType } from "../wxApi.js";
|
||||||
|
|
||||||
type Type = WxApiType
|
type Type = WxApiType;
|
||||||
|
|
||||||
const initial = wxApi;
|
const initial = wxApi;
|
||||||
|
|
||||||
@ -31,7 +31,7 @@ const Context = createContext<Type>(initial);
|
|||||||
|
|
||||||
type Props = Partial<WxApiType> & {
|
type Props = Partial<WxApiType> & {
|
||||||
children: ComponentChildren;
|
children: ComponentChildren;
|
||||||
}
|
};
|
||||||
|
|
||||||
export const BackendProvider = ({
|
export const BackendProvider = ({
|
||||||
wallet,
|
wallet,
|
||||||
@ -39,12 +39,11 @@ export const BackendProvider = ({
|
|||||||
listener,
|
listener,
|
||||||
children,
|
children,
|
||||||
}: Props): VNode => {
|
}: Props): VNode => {
|
||||||
|
|
||||||
return h(Context.Provider, {
|
return h(Context.Provider, {
|
||||||
value: {
|
value: {
|
||||||
wallet: wallet ?? initial.wallet,
|
wallet: wallet ?? initial.wallet,
|
||||||
background: background ?? initial.background,
|
background: background ?? initial.background,
|
||||||
listener: listener ?? initial.listener
|
listener: listener ?? initial.listener,
|
||||||
},
|
},
|
||||||
children,
|
children,
|
||||||
});
|
});
|
||||||
|
@ -20,10 +20,13 @@ import { useBackendContext } from "../../context/backend.js";
|
|||||||
import { useAsyncAsHook } from "../../hooks/useAsyncAsHook.js";
|
import { useAsyncAsHook } from "../../hooks/useAsyncAsHook.js";
|
||||||
import { Props, State } from "./index.js";
|
import { Props, State } from "./index.js";
|
||||||
|
|
||||||
export function useComponentState(
|
export function useComponentState({
|
||||||
{ talerDepositUri, amountStr, cancel, onSuccess }: Props,
|
talerDepositUri,
|
||||||
): State {
|
amountStr,
|
||||||
const api = useBackendContext()
|
cancel,
|
||||||
|
onSuccess,
|
||||||
|
}: Props): State {
|
||||||
|
const api = useBackendContext();
|
||||||
const info = useAsyncAsHook(async () => {
|
const info = useAsyncAsHook(async () => {
|
||||||
if (!talerDepositUri) throw Error("ERROR_NO-URI-FOR-DEPOSIT");
|
if (!talerDepositUri) throw Error("ERROR_NO-URI-FOR-DEPOSIT");
|
||||||
if (!amountStr) throw Error("ERROR_NO-AMOUNT-FOR-DEPOSIT");
|
if (!amountStr) throw Error("ERROR_NO-AMOUNT-FOR-DEPOSIT");
|
||||||
|
@ -42,21 +42,26 @@ describe("Deposit CTA states", () => {
|
|||||||
},
|
},
|
||||||
};
|
};
|
||||||
|
|
||||||
const hookBehavior = await tests.hookBehaveLikeThis(useComponentState, props, [
|
const hookBehavior = await tests.hookBehaveLikeThis(
|
||||||
({ status }) => {
|
useComponentState,
|
||||||
expect(status).equals("loading");
|
props,
|
||||||
},
|
[
|
||||||
({ status, error }) => {
|
({ status }) => {
|
||||||
expect(status).equals("loading-uri");
|
expect(status).equals("loading");
|
||||||
|
},
|
||||||
|
({ status, error }) => {
|
||||||
|
expect(status).equals("loading-uri");
|
||||||
|
|
||||||
if (!error) expect.fail();
|
if (!error) expect.fail();
|
||||||
if (!error.hasError) expect.fail();
|
if (!error.hasError) expect.fail();
|
||||||
if (error.operational) expect.fail();
|
if (error.operational) expect.fail();
|
||||||
expect(error.message).eq("ERROR_NO-URI-FOR-DEPOSIT");
|
expect(error.message).eq("ERROR_NO-URI-FOR-DEPOSIT");
|
||||||
},
|
},
|
||||||
], TestingContext)
|
],
|
||||||
|
TestingContext,
|
||||||
|
);
|
||||||
|
|
||||||
expect(hookBehavior).deep.equal({ result: "ok" })
|
expect(hookBehavior).deep.equal({ result: "ok" });
|
||||||
expect(handler.getCallingQueueState()).eq("empty");
|
expect(handler.getCallingQueueState()).eq("empty");
|
||||||
});
|
});
|
||||||
|
|
||||||
@ -83,21 +88,26 @@ describe("Deposit CTA states", () => {
|
|||||||
},
|
},
|
||||||
};
|
};
|
||||||
|
|
||||||
const hookBehavior = await tests.hookBehaveLikeThis(useComponentState, props, [
|
const hookBehavior = await tests.hookBehaveLikeThis(
|
||||||
({ status }) => {
|
useComponentState,
|
||||||
expect(status).equals("loading");
|
props,
|
||||||
},
|
[
|
||||||
(state) => {
|
({ status }) => {
|
||||||
if (state.status !== "ready") expect.fail();
|
expect(status).equals("loading");
|
||||||
if (state.error) expect.fail();
|
},
|
||||||
expect(state.confirm.onClick).not.undefined;
|
(state) => {
|
||||||
expect(state.cost).deep.eq(Amounts.parseOrThrow("EUR:1.2"));
|
if (state.status !== "ready") expect.fail();
|
||||||
expect(state.fee).deep.eq(Amounts.parseOrThrow("EUR:0.2"));
|
if (state.error) expect.fail();
|
||||||
expect(state.effective).deep.eq(Amounts.parseOrThrow("EUR:1"));
|
expect(state.confirm.onClick).not.undefined;
|
||||||
},
|
expect(state.cost).deep.eq(Amounts.parseOrThrow("EUR:1.2"));
|
||||||
], TestingContext)
|
expect(state.fee).deep.eq(Amounts.parseOrThrow("EUR:0.2"));
|
||||||
|
expect(state.effective).deep.eq(Amounts.parseOrThrow("EUR:1"));
|
||||||
|
},
|
||||||
|
],
|
||||||
|
TestingContext,
|
||||||
|
);
|
||||||
|
|
||||||
expect(hookBehavior).deep.equal({ result: "ok" })
|
expect(hookBehavior).deep.equal({ result: "ok" });
|
||||||
expect(handler.getCallingQueueState()).eq("empty");
|
expect(handler.getCallingQueueState()).eq("empty");
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
|
@ -29,11 +29,13 @@ import { useSelectedExchange } from "../../hooks/useSelectedExchange.js";
|
|||||||
import { RecursiveState } from "../../utils/index.js";
|
import { RecursiveState } from "../../utils/index.js";
|
||||||
import { Props, State } from "./index.js";
|
import { Props, State } from "./index.js";
|
||||||
|
|
||||||
export function useComponentState(
|
export function useComponentState({
|
||||||
{ amount: amountStr, onClose, onSuccess }: Props,
|
amount: amountStr,
|
||||||
): RecursiveState<State> {
|
onClose,
|
||||||
|
onSuccess,
|
||||||
|
}: Props): RecursiveState<State> {
|
||||||
const amount = Amounts.parseOrThrow(amountStr);
|
const amount = Amounts.parseOrThrow(amountStr);
|
||||||
const api = useBackendContext()
|
const api = useBackendContext();
|
||||||
|
|
||||||
const hook = useAsyncAsHook(() =>
|
const hook = useAsyncAsHook(() =>
|
||||||
api.wallet.call(WalletApiOperation.ListExchanges, {}),
|
api.wallet.call(WalletApiOperation.ListExchanges, {}),
|
||||||
@ -158,8 +160,8 @@ export function useComponentState(
|
|||||||
subject === undefined
|
subject === undefined
|
||||||
? undefined
|
? undefined
|
||||||
: !subject
|
: !subject
|
||||||
? "Can't be empty"
|
? "Can't be empty"
|
||||||
: undefined,
|
: undefined,
|
||||||
value: subject ?? "",
|
value: subject ?? "",
|
||||||
onInput: async (e) => setSubject(e),
|
onInput: async (e) => setSubject(e),
|
||||||
},
|
},
|
||||||
|
@ -18,7 +18,7 @@ import {
|
|||||||
AbsoluteTime,
|
AbsoluteTime,
|
||||||
AmountJson,
|
AmountJson,
|
||||||
PreparePayResult,
|
PreparePayResult,
|
||||||
TalerErrorDetail
|
TalerErrorDetail,
|
||||||
} from "@gnu-taler/taler-util";
|
} from "@gnu-taler/taler-util";
|
||||||
import { Loading } from "../../components/Loading.js";
|
import { Loading } from "../../components/Loading.js";
|
||||||
import { HookError } from "../../hooks/useAsyncAsHook.js";
|
import { HookError } from "../../hooks/useAsyncAsHook.js";
|
||||||
|
@ -29,10 +29,13 @@ import { useBackendContext } from "../../context/backend.js";
|
|||||||
import { useAsyncAsHook } from "../../hooks/useAsyncAsHook.js";
|
import { useAsyncAsHook } from "../../hooks/useAsyncAsHook.js";
|
||||||
import { Props, State } from "./index.js";
|
import { Props, State } from "./index.js";
|
||||||
|
|
||||||
export function useComponentState(
|
export function useComponentState({
|
||||||
{ talerPayPullUri, onClose, goToWalletManualWithdraw, onSuccess }: Props,
|
talerPayPullUri,
|
||||||
): State {
|
onClose,
|
||||||
const api = useBackendContext()
|
goToWalletManualWithdraw,
|
||||||
|
onSuccess,
|
||||||
|
}: Props): State {
|
||||||
|
const api = useBackendContext();
|
||||||
const hook = useAsyncAsHook(async () => {
|
const hook = useAsyncAsHook(async () => {
|
||||||
const p2p = await api.wallet.call(WalletApiOperation.CheckPeerPullPayment, {
|
const p2p = await api.wallet.call(WalletApiOperation.CheckPeerPullPayment, {
|
||||||
talerUri: talerPayPullUri,
|
talerUri: talerPayPullUri,
|
||||||
|
@ -19,7 +19,7 @@ import {
|
|||||||
PreparePayResult,
|
PreparePayResult,
|
||||||
PreparePayResultAlreadyConfirmed,
|
PreparePayResultAlreadyConfirmed,
|
||||||
PreparePayResultInsufficientBalance,
|
PreparePayResultInsufficientBalance,
|
||||||
PreparePayResultPaymentPossible
|
PreparePayResultPaymentPossible,
|
||||||
} from "@gnu-taler/taler-util";
|
} from "@gnu-taler/taler-util";
|
||||||
import { Loading } from "../../components/Loading.js";
|
import { Loading } from "../../components/Loading.js";
|
||||||
import { HookError } from "../../hooks/useAsyncAsHook.js";
|
import { HookError } from "../../hooks/useAsyncAsHook.js";
|
||||||
|
@ -28,11 +28,14 @@ import { useAsyncAsHook } from "../../hooks/useAsyncAsHook.js";
|
|||||||
import { ButtonHandler } from "../../mui/handlers.js";
|
import { ButtonHandler } from "../../mui/handlers.js";
|
||||||
import { Props, State } from "./index.js";
|
import { Props, State } from "./index.js";
|
||||||
|
|
||||||
export function useComponentState(
|
export function useComponentState({
|
||||||
{ talerPayUri, cancel, goToWalletManualWithdraw, onSuccess }: Props,
|
talerPayUri,
|
||||||
): State {
|
cancel,
|
||||||
|
goToWalletManualWithdraw,
|
||||||
|
onSuccess,
|
||||||
|
}: Props): State {
|
||||||
const [payErrMsg, setPayErrMsg] = useState<TalerError | undefined>(undefined);
|
const [payErrMsg, setPayErrMsg] = useState<TalerError | undefined>(undefined);
|
||||||
const api = useBackendContext()
|
const api = useBackendContext();
|
||||||
|
|
||||||
const hook = useAsyncAsHook(async () => {
|
const hook = useAsyncAsHook(async () => {
|
||||||
if (!talerPayUri) throw Error("ERROR_NO-URI-FOR-PAYMENT");
|
if (!talerPayUri) throw Error("ERROR_NO-URI-FOR-PAYMENT");
|
||||||
|
@ -45,22 +45,26 @@ describe("Payment CTA states", () => {
|
|||||||
onSuccess: nullFunction,
|
onSuccess: nullFunction,
|
||||||
};
|
};
|
||||||
|
|
||||||
const hookBehavior = await tests.hookBehaveLikeThis(useComponentState, props, [
|
const hookBehavior = await tests.hookBehaveLikeThis(
|
||||||
({ status, error }) => {
|
useComponentState,
|
||||||
expect(status).equals("loading");
|
props,
|
||||||
expect(error).undefined;
|
[
|
||||||
},
|
({ status, error }) => {
|
||||||
({ status, error }) => {
|
expect(status).equals("loading");
|
||||||
expect(status).equals("loading-uri");
|
expect(error).undefined;
|
||||||
if (error === undefined) expect.fail();
|
},
|
||||||
expect(error.hasError).true;
|
({ status, error }) => {
|
||||||
expect(error.operational).false;
|
expect(status).equals("loading-uri");
|
||||||
},
|
if (error === undefined) expect.fail();
|
||||||
], TestingContext)
|
expect(error.hasError).true;
|
||||||
|
expect(error.operational).false;
|
||||||
|
},
|
||||||
|
],
|
||||||
|
TestingContext,
|
||||||
|
);
|
||||||
|
|
||||||
expect(hookBehavior).deep.equal({ result: "ok" })
|
expect(hookBehavior).deep.equal({ result: "ok" });
|
||||||
expect(handler.getCallingQueueState()).eq("empty");
|
expect(handler.getCallingQueueState()).eq("empty");
|
||||||
|
|
||||||
});
|
});
|
||||||
|
|
||||||
it("should response with no balance", async () => {
|
it("should response with no balance", async () => {
|
||||||
@ -86,22 +90,27 @@ describe("Payment CTA states", () => {
|
|||||||
{ balances: [] },
|
{ balances: [] },
|
||||||
);
|
);
|
||||||
|
|
||||||
const hookBehavior = await tests.hookBehaveLikeThis(useComponentState, props, [
|
const hookBehavior = await tests.hookBehaveLikeThis(
|
||||||
({ status, error }) => {
|
useComponentState,
|
||||||
expect(status).equals("loading");
|
props,
|
||||||
expect(error).undefined;
|
[
|
||||||
},
|
({ status, error }) => {
|
||||||
(state) => {
|
expect(status).equals("loading");
|
||||||
if (state.status !== "no-balance-for-currency") {
|
expect(error).undefined;
|
||||||
expect(state).eq({});
|
},
|
||||||
return;
|
(state) => {
|
||||||
}
|
if (state.status !== "no-balance-for-currency") {
|
||||||
expect(state.balance).undefined;
|
expect(state).eq({});
|
||||||
expect(state.amount).deep.equal(Amounts.parseOrThrow("USD:10"));
|
return;
|
||||||
},
|
}
|
||||||
], TestingContext)
|
expect(state.balance).undefined;
|
||||||
|
expect(state.amount).deep.equal(Amounts.parseOrThrow("USD:10"));
|
||||||
|
},
|
||||||
|
],
|
||||||
|
TestingContext,
|
||||||
|
);
|
||||||
|
|
||||||
expect(hookBehavior).deep.equal({ result: "ok" })
|
expect(hookBehavior).deep.equal({ result: "ok" });
|
||||||
expect(handler.getCallingQueueState()).eq("empty");
|
expect(handler.getCallingQueueState()).eq("empty");
|
||||||
});
|
});
|
||||||
|
|
||||||
@ -138,19 +147,24 @@ describe("Payment CTA states", () => {
|
|||||||
},
|
},
|
||||||
);
|
);
|
||||||
|
|
||||||
const hookBehavior = await tests.hookBehaveLikeThis(useComponentState, props, [
|
const hookBehavior = await tests.hookBehaveLikeThis(
|
||||||
({ status, error }) => {
|
useComponentState,
|
||||||
expect(status).equals("loading");
|
props,
|
||||||
expect(error).undefined;
|
[
|
||||||
},
|
({ status, error }) => {
|
||||||
(state) => {
|
expect(status).equals("loading");
|
||||||
if (state.status !== "no-enough-balance") expect.fail();
|
expect(error).undefined;
|
||||||
expect(state.balance).deep.equal(Amounts.parseOrThrow("USD:5"));
|
},
|
||||||
expect(state.amount).deep.equal(Amounts.parseOrThrow("USD:10"));
|
(state) => {
|
||||||
},
|
if (state.status !== "no-enough-balance") expect.fail();
|
||||||
], TestingContext)
|
expect(state.balance).deep.equal(Amounts.parseOrThrow("USD:5"));
|
||||||
|
expect(state.amount).deep.equal(Amounts.parseOrThrow("USD:10"));
|
||||||
|
},
|
||||||
|
],
|
||||||
|
TestingContext,
|
||||||
|
);
|
||||||
|
|
||||||
expect(hookBehavior).deep.equal({ result: "ok" })
|
expect(hookBehavior).deep.equal({ result: "ok" });
|
||||||
expect(handler.getCallingQueueState()).eq("empty");
|
expect(handler.getCallingQueueState()).eq("empty");
|
||||||
});
|
});
|
||||||
|
|
||||||
@ -187,25 +201,29 @@ describe("Payment CTA states", () => {
|
|||||||
],
|
],
|
||||||
},
|
},
|
||||||
);
|
);
|
||||||
const hookBehavior = await tests.hookBehaveLikeThis(useComponentState, props, [
|
const hookBehavior = await tests.hookBehaveLikeThis(
|
||||||
({ status, error }) => {
|
useComponentState,
|
||||||
expect(status).equals("loading");
|
props,
|
||||||
expect(error).undefined;
|
[
|
||||||
},
|
({ status, error }) => {
|
||||||
(state) => {
|
expect(status).equals("loading");
|
||||||
if (state.status !== "ready") {
|
expect(error).undefined;
|
||||||
expect(state).eq({});
|
},
|
||||||
return;
|
(state) => {
|
||||||
}
|
if (state.status !== "ready") {
|
||||||
expect(state.balance).deep.equal(Amounts.parseOrThrow("USD:15"));
|
expect(state).eq({});
|
||||||
expect(state.amount).deep.equal(Amounts.parseOrThrow("USD:10"));
|
return;
|
||||||
expect(state.payHandler.onClick).not.undefined;
|
}
|
||||||
},
|
expect(state.balance).deep.equal(Amounts.parseOrThrow("USD:15"));
|
||||||
], TestingContext)
|
expect(state.amount).deep.equal(Amounts.parseOrThrow("USD:10"));
|
||||||
|
expect(state.payHandler.onClick).not.undefined;
|
||||||
|
},
|
||||||
|
],
|
||||||
|
TestingContext,
|
||||||
|
);
|
||||||
|
|
||||||
expect(hookBehavior).deep.equal({ result: "ok" })
|
expect(hookBehavior).deep.equal({ result: "ok" });
|
||||||
expect(handler.getCallingQueueState()).eq("empty");
|
expect(handler.getCallingQueueState()).eq("empty");
|
||||||
|
|
||||||
});
|
});
|
||||||
|
|
||||||
it("should be able to pay (with fee)", async () => {
|
it("should be able to pay (with fee)", async () => {
|
||||||
@ -241,20 +259,25 @@ describe("Payment CTA states", () => {
|
|||||||
],
|
],
|
||||||
},
|
},
|
||||||
);
|
);
|
||||||
const hookBehavior = await tests.hookBehaveLikeThis(useComponentState, props, [
|
const hookBehavior = await tests.hookBehaveLikeThis(
|
||||||
({ status, error }) => {
|
useComponentState,
|
||||||
expect(status).equals("loading");
|
props,
|
||||||
expect(error).undefined;
|
[
|
||||||
},
|
({ status, error }) => {
|
||||||
(state) => {
|
expect(status).equals("loading");
|
||||||
if (state.status !== "ready") expect.fail();
|
expect(error).undefined;
|
||||||
expect(state.balance).deep.equal(Amounts.parseOrThrow("USD:15"));
|
},
|
||||||
expect(state.amount).deep.equal(Amounts.parseOrThrow("USD:9"));
|
(state) => {
|
||||||
expect(state.payHandler.onClick).not.undefined;
|
if (state.status !== "ready") expect.fail();
|
||||||
},
|
expect(state.balance).deep.equal(Amounts.parseOrThrow("USD:15"));
|
||||||
], TestingContext)
|
expect(state.amount).deep.equal(Amounts.parseOrThrow("USD:9"));
|
||||||
|
expect(state.payHandler.onClick).not.undefined;
|
||||||
|
},
|
||||||
|
],
|
||||||
|
TestingContext,
|
||||||
|
);
|
||||||
|
|
||||||
expect(hookBehavior).deep.equal({ result: "ok" })
|
expect(hookBehavior).deep.equal({ result: "ok" });
|
||||||
expect(handler.getCallingQueueState()).eq("empty");
|
expect(handler.getCallingQueueState()).eq("empty");
|
||||||
});
|
});
|
||||||
|
|
||||||
@ -297,26 +320,30 @@ describe("Payment CTA states", () => {
|
|||||||
contractTerms: {},
|
contractTerms: {},
|
||||||
} as ConfirmPayResult);
|
} as ConfirmPayResult);
|
||||||
|
|
||||||
const hookBehavior = await tests.hookBehaveLikeThis(useComponentState, props, [
|
const hookBehavior = await tests.hookBehaveLikeThis(
|
||||||
({ status, error }) => {
|
useComponentState,
|
||||||
expect(status).equals("loading");
|
props,
|
||||||
expect(error).undefined;
|
[
|
||||||
},
|
({ status, error }) => {
|
||||||
(state) => {
|
expect(status).equals("loading");
|
||||||
if (state.status !== "ready") {
|
expect(error).undefined;
|
||||||
expect(state).eq({});
|
},
|
||||||
return;
|
(state) => {
|
||||||
}
|
if (state.status !== "ready") {
|
||||||
expect(state.balance).deep.equal(Amounts.parseOrThrow("USD:15"));
|
expect(state).eq({});
|
||||||
expect(state.amount).deep.equal(Amounts.parseOrThrow("USD:9"));
|
return;
|
||||||
if (state.payHandler.onClick === undefined) expect.fail();
|
}
|
||||||
state.payHandler.onClick();
|
expect(state.balance).deep.equal(Amounts.parseOrThrow("USD:15"));
|
||||||
},
|
expect(state.amount).deep.equal(Amounts.parseOrThrow("USD:9"));
|
||||||
], TestingContext)
|
if (state.payHandler.onClick === undefined) expect.fail();
|
||||||
|
state.payHandler.onClick();
|
||||||
|
},
|
||||||
|
],
|
||||||
|
TestingContext,
|
||||||
|
);
|
||||||
|
|
||||||
expect(hookBehavior).deep.equal({ result: "ok" })
|
expect(hookBehavior).deep.equal({ result: "ok" });
|
||||||
expect(handler.getCallingQueueState()).eq("empty");
|
expect(handler.getCallingQueueState()).eq("empty");
|
||||||
|
|
||||||
});
|
});
|
||||||
|
|
||||||
it("should not stay in ready state after pay with error", async () => {
|
it("should not stay in ready state after pay with error", async () => {
|
||||||
@ -357,40 +384,44 @@ describe("Payment CTA states", () => {
|
|||||||
lastError: { code: 1 },
|
lastError: { code: 1 },
|
||||||
} as ConfirmPayResult);
|
} as ConfirmPayResult);
|
||||||
|
|
||||||
const hookBehavior = await tests.hookBehaveLikeThis(useComponentState, props, [
|
const hookBehavior = await tests.hookBehaveLikeThis(
|
||||||
({ status, error }) => {
|
useComponentState,
|
||||||
expect(status).equals("loading");
|
props,
|
||||||
expect(error).undefined;
|
[
|
||||||
},
|
({ status, error }) => {
|
||||||
(state) => {
|
expect(status).equals("loading");
|
||||||
if (state.status !== "ready") expect.fail();
|
expect(error).undefined;
|
||||||
expect(state.balance).deep.equal(Amounts.parseOrThrow("USD:15"));
|
},
|
||||||
expect(state.amount).deep.equal(Amounts.parseOrThrow("USD:9"));
|
(state) => {
|
||||||
// expect(r.totalFees).deep.equal(Amounts.parseOrThrow("USD:1"));
|
if (state.status !== "ready") expect.fail();
|
||||||
if (state.payHandler.onClick === undefined) expect.fail();
|
expect(state.balance).deep.equal(Amounts.parseOrThrow("USD:15"));
|
||||||
state.payHandler.onClick();
|
expect(state.amount).deep.equal(Amounts.parseOrThrow("USD:9"));
|
||||||
},
|
// expect(r.totalFees).deep.equal(Amounts.parseOrThrow("USD:1"));
|
||||||
(state) => {
|
if (state.payHandler.onClick === undefined) expect.fail();
|
||||||
if (state.status !== "ready") expect.fail();
|
state.payHandler.onClick();
|
||||||
expect(state.balance).deep.equal(Amounts.parseOrThrow("USD:15"));
|
},
|
||||||
expect(state.amount).deep.equal(Amounts.parseOrThrow("USD:9"));
|
(state) => {
|
||||||
// expect(r.totalFees).deep.equal(Amounts.parseOrThrow("USD:1"));
|
if (state.status !== "ready") expect.fail();
|
||||||
expect(state.payHandler.onClick).undefined;
|
expect(state.balance).deep.equal(Amounts.parseOrThrow("USD:15"));
|
||||||
if (state.payHandler.error === undefined) expect.fail();
|
expect(state.amount).deep.equal(Amounts.parseOrThrow("USD:9"));
|
||||||
//FIXME: error message here is bad
|
// expect(r.totalFees).deep.equal(Amounts.parseOrThrow("USD:1"));
|
||||||
expect(state.payHandler.error.errorDetail.hint).eq(
|
expect(state.payHandler.onClick).undefined;
|
||||||
"could not confirm payment",
|
if (state.payHandler.error === undefined) expect.fail();
|
||||||
);
|
//FIXME: error message here is bad
|
||||||
expect(state.payHandler.error.errorDetail.payResult).deep.equal({
|
expect(state.payHandler.error.errorDetail.hint).eq(
|
||||||
type: ConfirmPayResultType.Pending,
|
"could not confirm payment",
|
||||||
lastError: { code: 1 },
|
);
|
||||||
});
|
expect(state.payHandler.error.errorDetail.payResult).deep.equal({
|
||||||
},
|
type: ConfirmPayResultType.Pending,
|
||||||
], TestingContext)
|
lastError: { code: 1 },
|
||||||
|
});
|
||||||
|
},
|
||||||
|
],
|
||||||
|
TestingContext,
|
||||||
|
);
|
||||||
|
|
||||||
expect(hookBehavior).deep.equal({ result: "ok" })
|
expect(hookBehavior).deep.equal({ result: "ok" });
|
||||||
expect(handler.getCallingQueueState()).eq("empty");
|
expect(handler.getCallingQueueState()).eq("empty");
|
||||||
|
|
||||||
});
|
});
|
||||||
|
|
||||||
it("should update balance if a coins is withdraw", async () => {
|
it("should update balance if a coins is withdraw", async () => {
|
||||||
@ -455,30 +486,35 @@ describe("Payment CTA states", () => {
|
|||||||
},
|
},
|
||||||
);
|
);
|
||||||
|
|
||||||
const hookBehavior = await tests.hookBehaveLikeThis(useComponentState, props, [
|
const hookBehavior = await tests.hookBehaveLikeThis(
|
||||||
({ status, error }) => {
|
useComponentState,
|
||||||
expect(status).equals("loading");
|
props,
|
||||||
expect(error).undefined;
|
[
|
||||||
},
|
({ status, error }) => {
|
||||||
(state) => {
|
expect(status).equals("loading");
|
||||||
if (state.status !== "ready") expect.fail()
|
expect(error).undefined;
|
||||||
expect(state.balance).deep.equal(Amounts.parseOrThrow("USD:10"));
|
},
|
||||||
expect(state.amount).deep.equal(Amounts.parseOrThrow("USD:9"));
|
(state) => {
|
||||||
// expect(r.totalFees).deep.equal(Amounts.parseOrThrow("USD:1"));
|
if (state.status !== "ready") expect.fail();
|
||||||
expect(state.payHandler.onClick).not.undefined;
|
expect(state.balance).deep.equal(Amounts.parseOrThrow("USD:10"));
|
||||||
|
expect(state.amount).deep.equal(Amounts.parseOrThrow("USD:9"));
|
||||||
|
// expect(r.totalFees).deep.equal(Amounts.parseOrThrow("USD:1"));
|
||||||
|
expect(state.payHandler.onClick).not.undefined;
|
||||||
|
|
||||||
handler.notifyEventFromWallet(NotificationType.CoinWithdrawn);
|
handler.notifyEventFromWallet(NotificationType.CoinWithdrawn);
|
||||||
},
|
},
|
||||||
(state) => {
|
(state) => {
|
||||||
if (state.status !== "ready") expect.fail()
|
if (state.status !== "ready") expect.fail();
|
||||||
expect(state.balance).deep.equal(Amounts.parseOrThrow("USD:15"));
|
expect(state.balance).deep.equal(Amounts.parseOrThrow("USD:15"));
|
||||||
expect(state.amount).deep.equal(Amounts.parseOrThrow("USD:9"));
|
expect(state.amount).deep.equal(Amounts.parseOrThrow("USD:9"));
|
||||||
// expect(r.totalFees).deep.equal(Amounts.parseOrThrow("USD:1"));
|
// expect(r.totalFees).deep.equal(Amounts.parseOrThrow("USD:1"));
|
||||||
expect(state.payHandler.onClick).not.undefined;
|
expect(state.payHandler.onClick).not.undefined;
|
||||||
},
|
},
|
||||||
], TestingContext)
|
],
|
||||||
|
TestingContext,
|
||||||
|
);
|
||||||
|
|
||||||
expect(hookBehavior).deep.equal({ result: "ok" })
|
expect(hookBehavior).deep.equal({ result: "ok" });
|
||||||
expect(handler.getCallingQueueState()).eq("empty");
|
expect(handler.getCallingQueueState()).eq("empty");
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
|
@ -19,10 +19,12 @@ import { WalletApiOperation } from "@gnu-taler/taler-wallet-core";
|
|||||||
import { useBackendContext } from "../../context/backend.js";
|
import { useBackendContext } from "../../context/backend.js";
|
||||||
import { Props, State } from "./index.js";
|
import { Props, State } from "./index.js";
|
||||||
|
|
||||||
export function useComponentState(
|
export function useComponentState({
|
||||||
{ talerRecoveryUri, onCancel, onSuccess }: Props,
|
talerRecoveryUri,
|
||||||
): State {
|
onCancel,
|
||||||
const api = useBackendContext()
|
onSuccess,
|
||||||
|
}: Props): State {
|
||||||
|
const api = useBackendContext();
|
||||||
if (!talerRecoveryUri) {
|
if (!talerRecoveryUri) {
|
||||||
return {
|
return {
|
||||||
status: "loading-uri",
|
status: "loading-uri",
|
||||||
|
@ -24,7 +24,7 @@ import {
|
|||||||
IgnoredView,
|
IgnoredView,
|
||||||
InProgressView,
|
InProgressView,
|
||||||
LoadingUriView,
|
LoadingUriView,
|
||||||
ReadyView
|
ReadyView,
|
||||||
} from "./views.js";
|
} from "./views.js";
|
||||||
|
|
||||||
export interface Props {
|
export interface Props {
|
||||||
|
@ -21,10 +21,12 @@ import { useBackendContext } from "../../context/backend.js";
|
|||||||
import { useAsyncAsHook } from "../../hooks/useAsyncAsHook.js";
|
import { useAsyncAsHook } from "../../hooks/useAsyncAsHook.js";
|
||||||
import { Props, State } from "./index.js";
|
import { Props, State } from "./index.js";
|
||||||
|
|
||||||
export function useComponentState(
|
export function useComponentState({
|
||||||
{ talerRefundUri, cancel, onSuccess }: Props,
|
talerRefundUri,
|
||||||
): State {
|
cancel,
|
||||||
const api = useBackendContext()
|
onSuccess,
|
||||||
|
}: Props): State {
|
||||||
|
const api = useBackendContext();
|
||||||
const [ignored, setIgnored] = useState(false);
|
const [ignored, setIgnored] = useState(false);
|
||||||
|
|
||||||
const info = useAsyncAsHook(async () => {
|
const info = useAsyncAsHook(async () => {
|
||||||
|
@ -22,12 +22,16 @@
|
|||||||
import {
|
import {
|
||||||
Amounts,
|
Amounts,
|
||||||
NotificationType,
|
NotificationType,
|
||||||
OrderShortInfo
|
OrderShortInfo,
|
||||||
} from "@gnu-taler/taler-util";
|
} from "@gnu-taler/taler-util";
|
||||||
import { WalletApiOperation } from "@gnu-taler/taler-wallet-core";
|
import { WalletApiOperation } from "@gnu-taler/taler-wallet-core";
|
||||||
import { expect } from "chai";
|
import { expect } from "chai";
|
||||||
import { tests } from "../../../../web-util/src/index.browser.js";
|
import { tests } from "../../../../web-util/src/index.browser.js";
|
||||||
import { createWalletApiMock, mountHook, nullFunction } from "../../test-utils.js";
|
import {
|
||||||
|
createWalletApiMock,
|
||||||
|
mountHook,
|
||||||
|
nullFunction,
|
||||||
|
} from "../../test-utils.js";
|
||||||
import { useComponentState } from "./state.js";
|
import { useComponentState } from "./state.js";
|
||||||
|
|
||||||
describe("Refund CTA states", () => {
|
describe("Refund CTA states", () => {
|
||||||
@ -38,23 +42,28 @@ describe("Refund CTA states", () => {
|
|||||||
talerRefundUri: undefined,
|
talerRefundUri: undefined,
|
||||||
cancel: nullFunction,
|
cancel: nullFunction,
|
||||||
onSuccess: nullFunction,
|
onSuccess: nullFunction,
|
||||||
}
|
};
|
||||||
|
|
||||||
const hookBehavior = await tests.hookBehaveLikeThis(useComponentState, props, [
|
const hookBehavior = await tests.hookBehaveLikeThis(
|
||||||
({ status, error }) => {
|
useComponentState,
|
||||||
expect(status).equals("loading");
|
props,
|
||||||
expect(error).undefined;
|
[
|
||||||
},
|
({ status, error }) => {
|
||||||
({ status, error }) => {
|
expect(status).equals("loading");
|
||||||
expect(status).equals("loading-uri");
|
expect(error).undefined;
|
||||||
if (!error) expect.fail();
|
},
|
||||||
if (!error.hasError) expect.fail();
|
({ status, error }) => {
|
||||||
if (error.operational) expect.fail();
|
expect(status).equals("loading-uri");
|
||||||
expect(error.message).eq("ERROR_NO-URI-FOR-REFUND");
|
if (!error) expect.fail();
|
||||||
},
|
if (!error.hasError) expect.fail();
|
||||||
], TestingContext)
|
if (error.operational) expect.fail();
|
||||||
|
expect(error.message).eq("ERROR_NO-URI-FOR-REFUND");
|
||||||
|
},
|
||||||
|
],
|
||||||
|
TestingContext,
|
||||||
|
);
|
||||||
|
|
||||||
expect(hookBehavior).deep.equal({ result: "ok" })
|
expect(hookBehavior).deep.equal({ result: "ok" });
|
||||||
expect(handler.getCallingQueueState()).eq("empty");
|
expect(handler.getCallingQueueState()).eq("empty");
|
||||||
});
|
});
|
||||||
|
|
||||||
@ -83,23 +92,28 @@ describe("Refund CTA states", () => {
|
|||||||
} as OrderShortInfo,
|
} as OrderShortInfo,
|
||||||
});
|
});
|
||||||
|
|
||||||
const hookBehavior = await tests.hookBehaveLikeThis(useComponentState, props, [
|
const hookBehavior = await tests.hookBehaveLikeThis(
|
||||||
({ status, error }) => {
|
useComponentState,
|
||||||
expect(status).equals("loading");
|
props,
|
||||||
expect(error).undefined;
|
[
|
||||||
},
|
({ status, error }) => {
|
||||||
(state) => {
|
expect(status).equals("loading");
|
||||||
if (state.status !== "ready") expect.fail();
|
expect(error).undefined;
|
||||||
if (state.error) expect.fail();
|
},
|
||||||
expect(state.accept.onClick).not.undefined;
|
(state) => {
|
||||||
expect(state.ignore.onClick).not.undefined;
|
if (state.status !== "ready") expect.fail();
|
||||||
expect(state.merchantName).eq("the merchant name");
|
if (state.error) expect.fail();
|
||||||
expect(state.orderId).eq("orderId1");
|
expect(state.accept.onClick).not.undefined;
|
||||||
expect(state.products).undefined;
|
expect(state.ignore.onClick).not.undefined;
|
||||||
},
|
expect(state.merchantName).eq("the merchant name");
|
||||||
], TestingContext)
|
expect(state.orderId).eq("orderId1");
|
||||||
|
expect(state.products).undefined;
|
||||||
|
},
|
||||||
|
],
|
||||||
|
TestingContext,
|
||||||
|
);
|
||||||
|
|
||||||
expect(hookBehavior).deep.equal({ result: "ok" })
|
expect(hookBehavior).deep.equal({ result: "ok" });
|
||||||
expect(handler.getCallingQueueState()).eq("empty");
|
expect(handler.getCallingQueueState()).eq("empty");
|
||||||
});
|
});
|
||||||
|
|
||||||
@ -132,30 +146,35 @@ describe("Refund CTA states", () => {
|
|||||||
} as OrderShortInfo,
|
} as OrderShortInfo,
|
||||||
});
|
});
|
||||||
|
|
||||||
const hookBehavior = await tests.hookBehaveLikeThis(useComponentState, props, [
|
const hookBehavior = await tests.hookBehaveLikeThis(
|
||||||
({ status, error }) => {
|
useComponentState,
|
||||||
expect(status).equals("loading");
|
props,
|
||||||
expect(error).undefined;
|
[
|
||||||
},
|
({ status, error }) => {
|
||||||
(state) => {
|
expect(status).equals("loading");
|
||||||
if (state.status !== "ready") expect.fail()
|
expect(error).undefined;
|
||||||
if (state.error) expect.fail()
|
},
|
||||||
expect(state.accept.onClick).not.undefined;
|
(state) => {
|
||||||
expect(state.merchantName).eq("the merchant name");
|
if (state.status !== "ready") expect.fail();
|
||||||
expect(state.orderId).eq("orderId1");
|
if (state.error) expect.fail();
|
||||||
expect(state.products).undefined;
|
expect(state.accept.onClick).not.undefined;
|
||||||
|
expect(state.merchantName).eq("the merchant name");
|
||||||
|
expect(state.orderId).eq("orderId1");
|
||||||
|
expect(state.products).undefined;
|
||||||
|
|
||||||
if (state.ignore.onClick === undefined) expect.fail();
|
if (state.ignore.onClick === undefined) expect.fail();
|
||||||
state.ignore.onClick();
|
state.ignore.onClick();
|
||||||
},
|
},
|
||||||
(state) => {
|
(state) => {
|
||||||
if (state.status !== "ignored") expect.fail()
|
if (state.status !== "ignored") expect.fail();
|
||||||
if (state.error) expect.fail()
|
if (state.error) expect.fail();
|
||||||
expect(state.merchantName).eq("the merchant name");
|
expect(state.merchantName).eq("the merchant name");
|
||||||
},
|
},
|
||||||
], TestingContext)
|
],
|
||||||
|
TestingContext,
|
||||||
|
);
|
||||||
|
|
||||||
expect(hookBehavior).deep.equal({ result: "ok" })
|
expect(hookBehavior).deep.equal({ result: "ok" });
|
||||||
expect(handler.getCallingQueueState()).eq("empty");
|
expect(handler.getCallingQueueState()).eq("empty");
|
||||||
});
|
});
|
||||||
|
|
||||||
@ -220,42 +239,46 @@ describe("Refund CTA states", () => {
|
|||||||
} as OrderShortInfo,
|
} as OrderShortInfo,
|
||||||
});
|
});
|
||||||
|
|
||||||
const hookBehavior = await tests.hookBehaveLikeThis(useComponentState, props, [
|
const hookBehavior = await tests.hookBehaveLikeThis(
|
||||||
({ status, error }) => {
|
useComponentState,
|
||||||
expect(status).equals("loading");
|
props,
|
||||||
expect(error).undefined;
|
[
|
||||||
},
|
({ status, error }) => {
|
||||||
(state) => {
|
expect(status).equals("loading");
|
||||||
if (state.status !== "in-progress") expect.fail()
|
expect(error).undefined;
|
||||||
if (state.error) expect.fail();
|
},
|
||||||
expect(state.merchantName).eq("the merchant name");
|
(state) => {
|
||||||
expect(state.products).undefined;
|
if (state.status !== "in-progress") expect.fail();
|
||||||
expect(state.amount).deep.eq(Amounts.parseOrThrow("EUR:2"));
|
if (state.error) expect.fail();
|
||||||
// expect(state.progress).closeTo(1 / 3, 0.01)
|
expect(state.merchantName).eq("the merchant name");
|
||||||
|
expect(state.products).undefined;
|
||||||
|
expect(state.amount).deep.eq(Amounts.parseOrThrow("EUR:2"));
|
||||||
|
// expect(state.progress).closeTo(1 / 3, 0.01)
|
||||||
|
|
||||||
handler.notifyEventFromWallet(NotificationType.RefreshMelted);
|
handler.notifyEventFromWallet(NotificationType.RefreshMelted);
|
||||||
},
|
},
|
||||||
(state) => {
|
(state) => {
|
||||||
if (state.status !== "in-progress") expect.fail()
|
if (state.status !== "in-progress") expect.fail();
|
||||||
if (state.error) expect.fail();
|
if (state.error) expect.fail();
|
||||||
expect(state.merchantName).eq("the merchant name");
|
expect(state.merchantName).eq("the merchant name");
|
||||||
expect(state.products).undefined;
|
expect(state.products).undefined;
|
||||||
expect(state.amount).deep.eq(Amounts.parseOrThrow("EUR:2"));
|
expect(state.amount).deep.eq(Amounts.parseOrThrow("EUR:2"));
|
||||||
// expect(state.progress).closeTo(2 / 3, 0.01)
|
// expect(state.progress).closeTo(2 / 3, 0.01)
|
||||||
|
|
||||||
handler.notifyEventFromWallet(NotificationType.RefreshMelted);
|
handler.notifyEventFromWallet(NotificationType.RefreshMelted);
|
||||||
},
|
},
|
||||||
(state) => {
|
(state) => {
|
||||||
if (state.status !== "ready") expect.fail()
|
if (state.status !== "ready") expect.fail();
|
||||||
if (state.error) expect.fail();
|
if (state.error) expect.fail();
|
||||||
expect(state.merchantName).eq("the merchant name");
|
expect(state.merchantName).eq("the merchant name");
|
||||||
expect(state.products).undefined;
|
expect(state.products).undefined;
|
||||||
expect(state.amount).deep.eq(Amounts.parseOrThrow("EUR:2"));
|
expect(state.amount).deep.eq(Amounts.parseOrThrow("EUR:2"));
|
||||||
|
},
|
||||||
|
],
|
||||||
|
TestingContext,
|
||||||
|
);
|
||||||
|
|
||||||
},
|
expect(hookBehavior).deep.equal({ result: "ok" });
|
||||||
], TestingContext)
|
|
||||||
|
|
||||||
expect(hookBehavior).deep.equal({ result: "ok" })
|
|
||||||
expect(handler.getCallingQueueState()).eq("empty");
|
expect(handler.getCallingQueueState()).eq("empty");
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
|
@ -24,7 +24,7 @@ import {
|
|||||||
AcceptedView,
|
AcceptedView,
|
||||||
IgnoredView,
|
IgnoredView,
|
||||||
LoadingUriView,
|
LoadingUriView,
|
||||||
ReadyView
|
ReadyView,
|
||||||
} from "./views.js";
|
} from "./views.js";
|
||||||
|
|
||||||
export interface Props {
|
export interface Props {
|
||||||
|
@ -20,10 +20,12 @@ import { useBackendContext } from "../../context/backend.js";
|
|||||||
import { useAsyncAsHook } from "../../hooks/useAsyncAsHook.js";
|
import { useAsyncAsHook } from "../../hooks/useAsyncAsHook.js";
|
||||||
import { Props, State } from "./index.js";
|
import { Props, State } from "./index.js";
|
||||||
|
|
||||||
export function useComponentState(
|
export function useComponentState({
|
||||||
{ talerTipUri, onCancel, onSuccess }: Props,
|
talerTipUri,
|
||||||
): State {
|
onCancel,
|
||||||
const api = useBackendContext()
|
onSuccess,
|
||||||
|
}: Props): State {
|
||||||
|
const api = useBackendContext();
|
||||||
const tipInfo = useAsyncAsHook(async () => {
|
const tipInfo = useAsyncAsHook(async () => {
|
||||||
if (!talerTipUri) throw Error("ERROR_NO-URI-FOR-TIP");
|
if (!talerTipUri) throw Error("ERROR_NO-URI-FOR-TIP");
|
||||||
const tip = await api.wallet.call(WalletApiOperation.PrepareTip, {
|
const tip = await api.wallet.call(WalletApiOperation.PrepareTip, {
|
||||||
|
@ -36,23 +36,28 @@ describe("Tip CTA states", () => {
|
|||||||
talerTipUri: undefined,
|
talerTipUri: undefined,
|
||||||
onCancel: nullFunction,
|
onCancel: nullFunction,
|
||||||
onSuccess: nullFunction,
|
onSuccess: nullFunction,
|
||||||
}
|
};
|
||||||
|
|
||||||
const hookBehavior = await tests.hookBehaveLikeThis(useComponentState, props, [
|
const hookBehavior = await tests.hookBehaveLikeThis(
|
||||||
({ status, error }) => {
|
useComponentState,
|
||||||
expect(status).equals("loading");
|
props,
|
||||||
expect(error).undefined;
|
[
|
||||||
},
|
({ status, error }) => {
|
||||||
({ status, error }) => {
|
expect(status).equals("loading");
|
||||||
expect(status).equals("loading-uri");
|
expect(error).undefined;
|
||||||
if (!error) expect.fail();
|
},
|
||||||
if (!error.hasError) expect.fail();
|
({ status, error }) => {
|
||||||
if (error.operational) expect.fail();
|
expect(status).equals("loading-uri");
|
||||||
expect(error.message).eq("ERROR_NO-URI-FOR-TIP");
|
if (!error) expect.fail();
|
||||||
},
|
if (!error.hasError) expect.fail();
|
||||||
], TestingContext)
|
if (error.operational) expect.fail();
|
||||||
|
expect(error.message).eq("ERROR_NO-URI-FOR-TIP");
|
||||||
|
},
|
||||||
|
],
|
||||||
|
TestingContext,
|
||||||
|
);
|
||||||
|
|
||||||
expect(hookBehavior).deep.equal({ result: "ok" })
|
expect(hookBehavior).deep.equal({ result: "ok" });
|
||||||
expect(handler.getCallingQueueState()).eq("empty");
|
expect(handler.getCallingQueueState()).eq("empty");
|
||||||
});
|
});
|
||||||
|
|
||||||
@ -75,50 +80,58 @@ describe("Tip CTA states", () => {
|
|||||||
talerTipUri: "taler://tip/asd",
|
talerTipUri: "taler://tip/asd",
|
||||||
onCancel: nullFunction,
|
onCancel: nullFunction,
|
||||||
onSuccess: nullFunction,
|
onSuccess: nullFunction,
|
||||||
}
|
};
|
||||||
|
|
||||||
const hookBehavior = await tests.hookBehaveLikeThis(useComponentState, props, [
|
const hookBehavior = await tests.hookBehaveLikeThis(
|
||||||
({ status, error }) => {
|
useComponentState,
|
||||||
expect(status).equals("loading");
|
props,
|
||||||
expect(error).undefined;
|
[
|
||||||
},
|
({ status, error }) => {
|
||||||
(state) => {
|
expect(status).equals("loading");
|
||||||
if (state.status !== "ready") {
|
expect(error).undefined;
|
||||||
expect(state).eq({ status: "ready" });
|
},
|
||||||
return;
|
(state) => {
|
||||||
}
|
if (state.status !== "ready") {
|
||||||
if (state.error) expect.fail();
|
expect(state).eq({ status: "ready" });
|
||||||
expect(state.amount).deep.eq(Amounts.parseOrThrow("EUR:1"));
|
return;
|
||||||
expect(state.merchantBaseUrl).eq("merchant url");
|
}
|
||||||
expect(state.exchangeBaseUrl).eq("exchange url");
|
if (state.error) expect.fail();
|
||||||
if (state.accept.onClick === undefined) expect.fail();
|
expect(state.amount).deep.eq(Amounts.parseOrThrow("EUR:1"));
|
||||||
|
expect(state.merchantBaseUrl).eq("merchant url");
|
||||||
|
expect(state.exchangeBaseUrl).eq("exchange url");
|
||||||
|
if (state.accept.onClick === undefined) expect.fail();
|
||||||
|
|
||||||
handler.addWalletCallResponse(WalletApiOperation.AcceptTip);
|
handler.addWalletCallResponse(WalletApiOperation.AcceptTip);
|
||||||
state.accept.onClick();
|
state.accept.onClick();
|
||||||
|
|
||||||
handler.addWalletCallResponse(WalletApiOperation.PrepareTip, undefined, {
|
handler.addWalletCallResponse(
|
||||||
accepted: true,
|
WalletApiOperation.PrepareTip,
|
||||||
exchangeBaseUrl: "exchange url",
|
undefined,
|
||||||
merchantBaseUrl: "merchant url",
|
{
|
||||||
tipAmountEffective: "EUR:1",
|
accepted: true,
|
||||||
walletTipId: "tip_id",
|
exchangeBaseUrl: "exchange url",
|
||||||
expirationTimestamp: {
|
merchantBaseUrl: "merchant url",
|
||||||
t_s: 1,
|
tipAmountEffective: "EUR:1",
|
||||||
},
|
walletTipId: "tip_id",
|
||||||
tipAmountRaw: "",
|
expirationTimestamp: {
|
||||||
});
|
t_s: 1,
|
||||||
|
},
|
||||||
|
tipAmountRaw: "",
|
||||||
|
},
|
||||||
|
);
|
||||||
|
},
|
||||||
|
(state) => {
|
||||||
|
if (state.status !== "accepted") expect.fail();
|
||||||
|
if (state.error) expect.fail();
|
||||||
|
expect(state.amount).deep.eq(Amounts.parseOrThrow("EUR:1"));
|
||||||
|
expect(state.merchantBaseUrl).eq("merchant url");
|
||||||
|
expect(state.exchangeBaseUrl).eq("exchange url");
|
||||||
|
},
|
||||||
|
],
|
||||||
|
TestingContext,
|
||||||
|
);
|
||||||
|
|
||||||
},
|
expect(hookBehavior).deep.equal({ result: "ok" });
|
||||||
(state) => {
|
|
||||||
if (state.status !== "accepted") expect.fail()
|
|
||||||
if (state.error) expect.fail();
|
|
||||||
expect(state.amount).deep.eq(Amounts.parseOrThrow("EUR:1"));
|
|
||||||
expect(state.merchantBaseUrl).eq("merchant url");
|
|
||||||
expect(state.exchangeBaseUrl).eq("exchange url");
|
|
||||||
},
|
|
||||||
], TestingContext)
|
|
||||||
|
|
||||||
expect(hookBehavior).deep.equal({ result: "ok" })
|
|
||||||
expect(handler.getCallingQueueState()).eq("empty");
|
expect(handler.getCallingQueueState()).eq("empty");
|
||||||
});
|
});
|
||||||
|
|
||||||
@ -140,25 +153,30 @@ describe("Tip CTA states", () => {
|
|||||||
talerTipUri: "taler://tip/asd",
|
talerTipUri: "taler://tip/asd",
|
||||||
onCancel: nullFunction,
|
onCancel: nullFunction,
|
||||||
onSuccess: nullFunction,
|
onSuccess: nullFunction,
|
||||||
}
|
};
|
||||||
|
|
||||||
const hookBehavior = await tests.hookBehaveLikeThis(useComponentState, props, [
|
const hookBehavior = await tests.hookBehaveLikeThis(
|
||||||
({ status, error }) => {
|
useComponentState,
|
||||||
expect(status).equals("loading");
|
props,
|
||||||
expect(error).undefined;
|
[
|
||||||
},
|
({ status, error }) => {
|
||||||
(state) => {
|
expect(status).equals("loading");
|
||||||
if (state.status !== "ready") expect.fail();
|
expect(error).undefined;
|
||||||
if (state.error) expect.fail();
|
},
|
||||||
expect(state.amount).deep.eq(Amounts.parseOrThrow("EUR:1"));
|
(state) => {
|
||||||
expect(state.merchantBaseUrl).eq("merchant url");
|
if (state.status !== "ready") expect.fail();
|
||||||
expect(state.exchangeBaseUrl).eq("exchange url");
|
if (state.error) expect.fail();
|
||||||
|
expect(state.amount).deep.eq(Amounts.parseOrThrow("EUR:1"));
|
||||||
|
expect(state.merchantBaseUrl).eq("merchant url");
|
||||||
|
expect(state.exchangeBaseUrl).eq("exchange url");
|
||||||
|
|
||||||
//FIXME: add ignore button
|
//FIXME: add ignore button
|
||||||
},
|
},
|
||||||
], TestingContext)
|
],
|
||||||
|
TestingContext,
|
||||||
|
);
|
||||||
|
|
||||||
expect(hookBehavior).deep.equal({ result: "ok" })
|
expect(hookBehavior).deep.equal({ result: "ok" });
|
||||||
expect(handler.getCallingQueueState()).eq("empty");
|
expect(handler.getCallingQueueState()).eq("empty");
|
||||||
});
|
});
|
||||||
|
|
||||||
@ -181,24 +199,28 @@ describe("Tip CTA states", () => {
|
|||||||
talerTipUri: "taler://tip/asd",
|
talerTipUri: "taler://tip/asd",
|
||||||
onCancel: nullFunction,
|
onCancel: nullFunction,
|
||||||
onSuccess: nullFunction,
|
onSuccess: nullFunction,
|
||||||
}
|
};
|
||||||
|
|
||||||
const hookBehavior = await tests.hookBehaveLikeThis(useComponentState, props, [
|
const hookBehavior = await tests.hookBehaveLikeThis(
|
||||||
({ status, error }) => {
|
useComponentState,
|
||||||
expect(status).equals("loading");
|
props,
|
||||||
expect(error).undefined;
|
[
|
||||||
},
|
({ status, error }) => {
|
||||||
(state) => {
|
expect(status).equals("loading");
|
||||||
if (state.status !== "accepted") expect.fail();
|
expect(error).undefined;
|
||||||
if (state.error) expect.fail();
|
},
|
||||||
expect(state.amount).deep.eq(Amounts.parseOrThrow("EUR:1"));
|
(state) => {
|
||||||
expect(state.merchantBaseUrl).eq("merchant url");
|
if (state.status !== "accepted") expect.fail();
|
||||||
expect(state.exchangeBaseUrl).eq("exchange url");
|
if (state.error) expect.fail();
|
||||||
},
|
expect(state.amount).deep.eq(Amounts.parseOrThrow("EUR:1"));
|
||||||
], TestingContext)
|
expect(state.merchantBaseUrl).eq("merchant url");
|
||||||
|
expect(state.exchangeBaseUrl).eq("exchange url");
|
||||||
|
},
|
||||||
|
],
|
||||||
|
TestingContext,
|
||||||
|
);
|
||||||
|
|
||||||
expect(hookBehavior).deep.equal({ result: "ok" })
|
expect(hookBehavior).deep.equal({ result: "ok" });
|
||||||
expect(handler.getCallingQueueState()).eq("empty");
|
expect(handler.getCallingQueueState()).eq("empty");
|
||||||
|
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
|
@ -17,7 +17,7 @@
|
|||||||
import {
|
import {
|
||||||
Amounts,
|
Amounts,
|
||||||
TalerErrorDetail,
|
TalerErrorDetail,
|
||||||
TalerProtocolTimestamp
|
TalerProtocolTimestamp,
|
||||||
} from "@gnu-taler/taler-util";
|
} from "@gnu-taler/taler-util";
|
||||||
import { TalerError, WalletApiOperation } from "@gnu-taler/taler-wallet-core";
|
import { TalerError, WalletApiOperation } from "@gnu-taler/taler-wallet-core";
|
||||||
import { isFuture, parse } from "date-fns";
|
import { isFuture, parse } from "date-fns";
|
||||||
@ -26,10 +26,12 @@ import { useBackendContext } from "../../context/backend.js";
|
|||||||
import { useAsyncAsHook } from "../../hooks/useAsyncAsHook.js";
|
import { useAsyncAsHook } from "../../hooks/useAsyncAsHook.js";
|
||||||
import { Props, State } from "./index.js";
|
import { Props, State } from "./index.js";
|
||||||
|
|
||||||
export function useComponentState(
|
export function useComponentState({
|
||||||
{ amount: amountStr, onClose, onSuccess }: Props,
|
amount: amountStr,
|
||||||
): State {
|
onClose,
|
||||||
const api = useBackendContext()
|
onSuccess,
|
||||||
|
}: Props): State {
|
||||||
|
const api = useBackendContext();
|
||||||
const amount = Amounts.parseOrThrow(amountStr);
|
const amount = Amounts.parseOrThrow(amountStr);
|
||||||
|
|
||||||
const [subject, setSubject] = useState<string | undefined>();
|
const [subject, setSubject] = useState<string | undefined>();
|
||||||
@ -124,8 +126,8 @@ export function useComponentState(
|
|||||||
subject === undefined
|
subject === undefined
|
||||||
? undefined
|
? undefined
|
||||||
: !subject
|
: !subject
|
||||||
? "Can't be empty"
|
? "Can't be empty"
|
||||||
: undefined,
|
: undefined,
|
||||||
value: subject ?? "",
|
value: subject ?? "",
|
||||||
onInput: async (e) => setSubject(e),
|
onInput: async (e) => setSubject(e),
|
||||||
},
|
},
|
||||||
|
@ -17,7 +17,7 @@
|
|||||||
import {
|
import {
|
||||||
AbsoluteTime,
|
AbsoluteTime,
|
||||||
AmountJson,
|
AmountJson,
|
||||||
TalerErrorDetail
|
TalerErrorDetail,
|
||||||
} from "@gnu-taler/taler-util";
|
} from "@gnu-taler/taler-util";
|
||||||
import { Loading } from "../../components/Loading.js";
|
import { Loading } from "../../components/Loading.js";
|
||||||
import { HookError } from "../../hooks/useAsyncAsHook.js";
|
import { HookError } from "../../hooks/useAsyncAsHook.js";
|
||||||
|
@ -18,7 +18,7 @@ import {
|
|||||||
AbsoluteTime,
|
AbsoluteTime,
|
||||||
Amounts,
|
Amounts,
|
||||||
TalerErrorDetail,
|
TalerErrorDetail,
|
||||||
TalerProtocolTimestamp
|
TalerProtocolTimestamp,
|
||||||
} from "@gnu-taler/taler-util";
|
} from "@gnu-taler/taler-util";
|
||||||
import { TalerError, WalletApiOperation } from "@gnu-taler/taler-wallet-core";
|
import { TalerError, WalletApiOperation } from "@gnu-taler/taler-wallet-core";
|
||||||
import { useState } from "preact/hooks";
|
import { useState } from "preact/hooks";
|
||||||
@ -26,10 +26,12 @@ import { useBackendContext } from "../../context/backend.js";
|
|||||||
import { useAsyncAsHook } from "../../hooks/useAsyncAsHook.js";
|
import { useAsyncAsHook } from "../../hooks/useAsyncAsHook.js";
|
||||||
import { Props, State } from "./index.js";
|
import { Props, State } from "./index.js";
|
||||||
|
|
||||||
export function useComponentState(
|
export function useComponentState({
|
||||||
{ talerPayPushUri, onClose, onSuccess }: Props,
|
talerPayPushUri,
|
||||||
): State {
|
onClose,
|
||||||
const api = useBackendContext()
|
onSuccess,
|
||||||
|
}: Props): State {
|
||||||
|
const api = useBackendContext();
|
||||||
const hook = useAsyncAsHook(async () => {
|
const hook = useAsyncAsHook(async () => {
|
||||||
return await api.wallet.call(WalletApiOperation.CheckPeerPushPayment, {
|
return await api.wallet.call(WalletApiOperation.CheckPeerPushPayment, {
|
||||||
talerUri: talerPayPushUri,
|
talerUri: talerPayPushUri,
|
||||||
|
@ -22,7 +22,7 @@ import { ButtonHandler, SelectFieldHandler } from "../../mui/handlers.js";
|
|||||||
import { compose, StateViewMap } from "../../utils/index.js";
|
import { compose, StateViewMap } from "../../utils/index.js";
|
||||||
import {
|
import {
|
||||||
useComponentStateFromParams,
|
useComponentStateFromParams,
|
||||||
useComponentStateFromURI
|
useComponentStateFromURI,
|
||||||
} from "./state.js";
|
} from "./state.js";
|
||||||
|
|
||||||
import { ExchangeSelectionPage } from "../../wallet/ExchangeSelection/index.js";
|
import { ExchangeSelectionPage } from "../../wallet/ExchangeSelection/index.js";
|
||||||
|
@ -19,7 +19,7 @@ import {
|
|||||||
AmountJson,
|
AmountJson,
|
||||||
Amounts,
|
Amounts,
|
||||||
ExchangeListItem,
|
ExchangeListItem,
|
||||||
ExchangeTosStatus
|
ExchangeTosStatus,
|
||||||
} from "@gnu-taler/taler-util";
|
} from "@gnu-taler/taler-util";
|
||||||
import { TalerError, WalletApiOperation } from "@gnu-taler/taler-wallet-core";
|
import { TalerError, WalletApiOperation } from "@gnu-taler/taler-wallet-core";
|
||||||
import { useState } from "preact/hooks";
|
import { useState } from "preact/hooks";
|
||||||
@ -29,10 +29,12 @@ import { useSelectedExchange } from "../../hooks/useSelectedExchange.js";
|
|||||||
import { RecursiveState } from "../../utils/index.js";
|
import { RecursiveState } from "../../utils/index.js";
|
||||||
import { PropsFromParams, PropsFromURI, State } from "./index.js";
|
import { PropsFromParams, PropsFromURI, State } from "./index.js";
|
||||||
|
|
||||||
export function useComponentStateFromParams(
|
export function useComponentStateFromParams({
|
||||||
{ amount, cancel, onSuccess }: PropsFromParams,
|
amount,
|
||||||
): RecursiveState<State> {
|
cancel,
|
||||||
const api = useBackendContext()
|
onSuccess,
|
||||||
|
}: PropsFromParams): RecursiveState<State> {
|
||||||
|
const api = useBackendContext();
|
||||||
const uriInfoHook = useAsyncAsHook(async () => {
|
const uriInfoHook = useAsyncAsHook(async () => {
|
||||||
const exchanges = await api.wallet.call(
|
const exchanges = await api.wallet.call(
|
||||||
WalletApiOperation.ListExchanges,
|
WalletApiOperation.ListExchanges,
|
||||||
@ -87,10 +89,12 @@ export function useComponentStateFromParams(
|
|||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
export function useComponentStateFromURI(
|
export function useComponentStateFromURI({
|
||||||
{ talerWithdrawUri, cancel, onSuccess }: PropsFromURI,
|
talerWithdrawUri,
|
||||||
): RecursiveState<State> {
|
cancel,
|
||||||
const api = useBackendContext()
|
onSuccess,
|
||||||
|
}: PropsFromURI): RecursiveState<State> {
|
||||||
|
const api = useBackendContext();
|
||||||
/**
|
/**
|
||||||
* Ask the wallet about the withdraw URI
|
* Ask the wallet about the withdraw URI
|
||||||
*/
|
*/
|
||||||
@ -175,7 +179,7 @@ function exchangeSelectionState(
|
|||||||
exchangeList: ExchangeListItem[],
|
exchangeList: ExchangeListItem[],
|
||||||
defaultExchange: string | undefined,
|
defaultExchange: string | undefined,
|
||||||
): RecursiveState<State> {
|
): RecursiveState<State> {
|
||||||
const api = useBackendContext()
|
const api = useBackendContext();
|
||||||
const selectedExchange = useSelectedExchange({
|
const selectedExchange = useSelectedExchange({
|
||||||
currency: chosenAmount.currency,
|
currency: chosenAmount.currency,
|
||||||
defaultExchange,
|
defaultExchange,
|
||||||
@ -276,10 +280,10 @@ function exchangeSelectionState(
|
|||||||
//TODO: calculate based on exchange info
|
//TODO: calculate based on exchange info
|
||||||
const ageRestriction = ageRestrictionEnabled
|
const ageRestriction = ageRestrictionEnabled
|
||||||
? {
|
? {
|
||||||
list: ageRestrictionOptions,
|
list: ageRestrictionOptions,
|
||||||
value: String(ageRestricted),
|
value: String(ageRestricted),
|
||||||
onChange: async (v: string) => setAgeRestricted(parseInt(v, 10)),
|
onChange: async (v: string) => setAgeRestricted(parseInt(v, 10)),
|
||||||
}
|
}
|
||||||
: undefined;
|
: undefined;
|
||||||
|
|
||||||
return {
|
return {
|
||||||
|
@ -64,7 +64,7 @@ const exchanges: ExchangeListItem[] = [
|
|||||||
|
|
||||||
const nullFunction = async (): Promise<void> => {
|
const nullFunction = async (): Promise<void> => {
|
||||||
null;
|
null;
|
||||||
}
|
};
|
||||||
|
|
||||||
describe("Withdraw CTA states", () => {
|
describe("Withdraw CTA states", () => {
|
||||||
it("should tell the user that the URI is missing", async () => {
|
it("should tell the user that the URI is missing", async () => {
|
||||||
@ -76,20 +76,25 @@ describe("Withdraw CTA states", () => {
|
|||||||
onSuccess: nullFunction,
|
onSuccess: nullFunction,
|
||||||
};
|
};
|
||||||
|
|
||||||
const hookBehavior = await tests.hookBehaveLikeThis(useComponentStateFromURI, props, [
|
const hookBehavior = await tests.hookBehaveLikeThis(
|
||||||
({ status }) => {
|
useComponentStateFromURI,
|
||||||
expect(status).equals("loading");
|
props,
|
||||||
},
|
[
|
||||||
({ status, error }) => {
|
({ status }) => {
|
||||||
if (status != "uri-error") expect.fail();
|
expect(status).equals("loading");
|
||||||
if (!error) expect.fail();
|
},
|
||||||
if (!error.hasError) expect.fail();
|
({ status, error }) => {
|
||||||
if (error.operational) expect.fail();
|
if (status != "uri-error") expect.fail();
|
||||||
expect(error.message).eq("ERROR_NO-URI-FOR-WITHDRAWAL");
|
if (!error) expect.fail();
|
||||||
},
|
if (!error.hasError) expect.fail();
|
||||||
], TestingContext)
|
if (error.operational) expect.fail();
|
||||||
|
expect(error.message).eq("ERROR_NO-URI-FOR-WITHDRAWAL");
|
||||||
|
},
|
||||||
|
],
|
||||||
|
TestingContext,
|
||||||
|
);
|
||||||
|
|
||||||
expect(hookBehavior).deep.equal({ result: "ok" })
|
expect(hookBehavior).deep.equal({ result: "ok" });
|
||||||
expect(handler.getCallingQueueState()).eq("empty");
|
expect(handler.getCallingQueueState()).eq("empty");
|
||||||
});
|
});
|
||||||
|
|
||||||
@ -110,17 +115,22 @@ describe("Withdraw CTA states", () => {
|
|||||||
},
|
},
|
||||||
);
|
);
|
||||||
|
|
||||||
const hookBehavior = await tests.hookBehaveLikeThis(useComponentStateFromURI, props, [
|
const hookBehavior = await tests.hookBehaveLikeThis(
|
||||||
({ status }) => {
|
useComponentStateFromURI,
|
||||||
expect(status).equals("loading");
|
props,
|
||||||
},
|
[
|
||||||
({ status, error }) => {
|
({ status }) => {
|
||||||
expect(status).equals("no-exchange");
|
expect(status).equals("loading");
|
||||||
expect(error).undefined;
|
},
|
||||||
},
|
({ status, error }) => {
|
||||||
], TestingContext)
|
expect(status).equals("no-exchange");
|
||||||
|
expect(error).undefined;
|
||||||
|
},
|
||||||
|
],
|
||||||
|
TestingContext,
|
||||||
|
);
|
||||||
|
|
||||||
expect(hookBehavior).deep.equal({ result: "ok" })
|
expect(hookBehavior).deep.equal({ result: "ok" });
|
||||||
expect(handler.getCallingQueueState()).eq("empty");
|
expect(handler.getCallingQueueState()).eq("empty");
|
||||||
});
|
});
|
||||||
|
|
||||||
@ -153,27 +163,32 @@ describe("Withdraw CTA states", () => {
|
|||||||
},
|
},
|
||||||
);
|
);
|
||||||
|
|
||||||
const hookBehavior = await tests.hookBehaveLikeThis(useComponentStateFromURI, props, [
|
const hookBehavior = await tests.hookBehaveLikeThis(
|
||||||
({ status }) => {
|
useComponentStateFromURI,
|
||||||
expect(status).equals("loading");
|
props,
|
||||||
},
|
[
|
||||||
({ status, error }) => {
|
({ status }) => {
|
||||||
expect(status).equals("loading");
|
expect(status).equals("loading");
|
||||||
expect(error).undefined;
|
},
|
||||||
},
|
({ status, error }) => {
|
||||||
(state) => {
|
expect(status).equals("loading");
|
||||||
expect(state.status).equals("success");
|
expect(error).undefined;
|
||||||
if (state.status !== "success") return;
|
},
|
||||||
|
(state) => {
|
||||||
|
expect(state.status).equals("success");
|
||||||
|
if (state.status !== "success") return;
|
||||||
|
|
||||||
expect(state.toBeReceived).deep.equal(Amounts.parseOrThrow("ARS:2"));
|
expect(state.toBeReceived).deep.equal(Amounts.parseOrThrow("ARS:2"));
|
||||||
expect(state.withdrawalFee).deep.equal(Amounts.parseOrThrow("ARS:0"));
|
expect(state.withdrawalFee).deep.equal(Amounts.parseOrThrow("ARS:0"));
|
||||||
expect(state.chosenAmount).deep.equal(Amounts.parseOrThrow("ARS:2"));
|
expect(state.chosenAmount).deep.equal(Amounts.parseOrThrow("ARS:2"));
|
||||||
|
|
||||||
expect(state.doWithdrawal.onClick).not.undefined;
|
expect(state.doWithdrawal.onClick).not.undefined;
|
||||||
},
|
},
|
||||||
], TestingContext)
|
],
|
||||||
|
TestingContext,
|
||||||
|
);
|
||||||
|
|
||||||
expect(hookBehavior).deep.equal({ result: "ok" })
|
expect(hookBehavior).deep.equal({ result: "ok" });
|
||||||
expect(handler.getCallingQueueState()).eq("empty");
|
expect(handler.getCallingQueueState()).eq("empty");
|
||||||
});
|
});
|
||||||
|
|
||||||
@ -221,39 +236,44 @@ describe("Withdraw CTA states", () => {
|
|||||||
},
|
},
|
||||||
);
|
);
|
||||||
|
|
||||||
const hookBehavior = await tests.hookBehaveLikeThis(useComponentStateFromURI, props, [
|
const hookBehavior = await tests.hookBehaveLikeThis(
|
||||||
({ status }) => {
|
useComponentStateFromURI,
|
||||||
expect(status).equals("loading");
|
props,
|
||||||
},
|
[
|
||||||
({ status, error }) => {
|
({ status }) => {
|
||||||
expect(status).equals("loading");
|
expect(status).equals("loading");
|
||||||
expect(error).undefined;
|
},
|
||||||
},
|
({ status, error }) => {
|
||||||
(state) => {
|
expect(status).equals("loading");
|
||||||
expect(state.status).equals("success");
|
expect(error).undefined;
|
||||||
if (state.status !== "success") return;
|
},
|
||||||
|
(state) => {
|
||||||
|
expect(state.status).equals("success");
|
||||||
|
if (state.status !== "success") return;
|
||||||
|
|
||||||
expect(state.toBeReceived).deep.equal(Amounts.parseOrThrow("ARS:2"));
|
expect(state.toBeReceived).deep.equal(Amounts.parseOrThrow("ARS:2"));
|
||||||
expect(state.withdrawalFee).deep.equal(Amounts.parseOrThrow("ARS:0"));
|
expect(state.withdrawalFee).deep.equal(Amounts.parseOrThrow("ARS:0"));
|
||||||
expect(state.chosenAmount).deep.equal(Amounts.parseOrThrow("ARS:2"));
|
expect(state.chosenAmount).deep.equal(Amounts.parseOrThrow("ARS:2"));
|
||||||
|
|
||||||
expect(state.doWithdrawal.onClick).undefined;
|
expect(state.doWithdrawal.onClick).undefined;
|
||||||
|
|
||||||
state.onTosUpdate();
|
state.onTosUpdate();
|
||||||
},
|
},
|
||||||
(state) => {
|
(state) => {
|
||||||
expect(state.status).equals("success");
|
expect(state.status).equals("success");
|
||||||
if (state.status !== "success") return;
|
if (state.status !== "success") return;
|
||||||
|
|
||||||
expect(state.toBeReceived).deep.equal(Amounts.parseOrThrow("ARS:2"));
|
expect(state.toBeReceived).deep.equal(Amounts.parseOrThrow("ARS:2"));
|
||||||
expect(state.withdrawalFee).deep.equal(Amounts.parseOrThrow("ARS:0"));
|
expect(state.withdrawalFee).deep.equal(Amounts.parseOrThrow("ARS:0"));
|
||||||
expect(state.chosenAmount).deep.equal(Amounts.parseOrThrow("ARS:2"));
|
expect(state.chosenAmount).deep.equal(Amounts.parseOrThrow("ARS:2"));
|
||||||
|
|
||||||
expect(state.doWithdrawal.onClick).not.undefined;
|
expect(state.doWithdrawal.onClick).not.undefined;
|
||||||
},
|
},
|
||||||
], TestingContext)
|
],
|
||||||
|
TestingContext,
|
||||||
|
);
|
||||||
|
|
||||||
expect(hookBehavior).deep.equal({ result: "ok" })
|
expect(hookBehavior).deep.equal({ result: "ok" });
|
||||||
expect(handler.getCallingQueueState()).eq("empty");
|
expect(handler.getCallingQueueState()).eq("empty");
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
|
@ -25,9 +25,11 @@ export function useAutoOpenPermissions(): ToggleHandler {
|
|||||||
const [enabled, setEnabled] = useState(false);
|
const [enabled, setEnabled] = useState(false);
|
||||||
const [error, setError] = useState<TalerError | undefined>();
|
const [error, setError] = useState<TalerError | undefined>();
|
||||||
const toggle = async (): Promise<void> => {
|
const toggle = async (): Promise<void> => {
|
||||||
return handleAutoOpenPerm(enabled, setEnabled, api.background).catch((e) => {
|
return handleAutoOpenPerm(enabled, setEnabled, api.background).catch(
|
||||||
setError(TalerError.fromException(e));
|
(e) => {
|
||||||
});
|
setError(TalerError.fromException(e));
|
||||||
|
},
|
||||||
|
);
|
||||||
};
|
};
|
||||||
|
|
||||||
useEffect(() => {
|
useEffect(() => {
|
||||||
|
@ -28,7 +28,7 @@ export function useBackupDeviceName(): BackupDeviceName {
|
|||||||
name: "",
|
name: "",
|
||||||
update: () => Promise.resolve(),
|
update: () => Promise.resolve(),
|
||||||
});
|
});
|
||||||
const api = useBackendContext()
|
const api = useBackendContext();
|
||||||
|
|
||||||
useEffect(() => {
|
useEffect(() => {
|
||||||
async function run(): Promise<void> {
|
async function run(): Promise<void> {
|
||||||
|
@ -23,12 +23,14 @@ import { platform } from "../platform/api.js";
|
|||||||
export function useClipboardPermissions(): ToggleHandler {
|
export function useClipboardPermissions(): ToggleHandler {
|
||||||
const [enabled, setEnabled] = useState(false);
|
const [enabled, setEnabled] = useState(false);
|
||||||
const [error, setError] = useState<TalerError | undefined>();
|
const [error, setError] = useState<TalerError | undefined>();
|
||||||
const api = useBackendContext()
|
const api = useBackendContext();
|
||||||
|
|
||||||
const toggle = async (): Promise<void> => {
|
const toggle = async (): Promise<void> => {
|
||||||
return handleClipboardPerm(enabled, setEnabled, api.background).catch((e) => {
|
return handleClipboardPerm(enabled, setEnabled, api.background).catch(
|
||||||
setError(TalerError.fromException(e));
|
(e) => {
|
||||||
});
|
setError(TalerError.fromException(e));
|
||||||
|
},
|
||||||
|
);
|
||||||
};
|
};
|
||||||
|
|
||||||
useEffect(() => {
|
useEffect(() => {
|
||||||
|
@ -444,8 +444,8 @@ function registerTalerHeaderListener(
|
|||||||
info: chrome.tabs.TabChangeInfo,
|
info: chrome.tabs.TabChangeInfo,
|
||||||
): Promise<void> {
|
): Promise<void> {
|
||||||
if (tabId < 0) return;
|
if (tabId < 0) return;
|
||||||
const tabLocationHasBeenUpdated = info.status === "complete"
|
const tabLocationHasBeenUpdated = info.status === "complete";
|
||||||
const tabTitleHasBeenUpdated = info.title !== undefined
|
const tabTitleHasBeenUpdated = info.title !== undefined;
|
||||||
if (tabLocationHasBeenUpdated || tabTitleHasBeenUpdated) {
|
if (tabLocationHasBeenUpdated || tabTitleHasBeenUpdated) {
|
||||||
const uri = await findTalerUriInTab(tabId);
|
const uri = await findTalerUriInTab(tabId);
|
||||||
if (!uri) return;
|
if (!uri) return;
|
||||||
@ -543,26 +543,26 @@ function setAlertedIcon(): void {
|
|||||||
|
|
||||||
interface OffscreenCanvasRenderingContext2D
|
interface OffscreenCanvasRenderingContext2D
|
||||||
extends CanvasState,
|
extends CanvasState,
|
||||||
CanvasTransform,
|
CanvasTransform,
|
||||||
CanvasCompositing,
|
CanvasCompositing,
|
||||||
CanvasImageSmoothing,
|
CanvasImageSmoothing,
|
||||||
CanvasFillStrokeStyles,
|
CanvasFillStrokeStyles,
|
||||||
CanvasShadowStyles,
|
CanvasShadowStyles,
|
||||||
CanvasFilters,
|
CanvasFilters,
|
||||||
CanvasRect,
|
CanvasRect,
|
||||||
CanvasDrawPath,
|
CanvasDrawPath,
|
||||||
CanvasUserInterface,
|
CanvasUserInterface,
|
||||||
CanvasText,
|
CanvasText,
|
||||||
CanvasDrawImage,
|
CanvasDrawImage,
|
||||||
CanvasImageData,
|
CanvasImageData,
|
||||||
CanvasPathDrawingStyles,
|
CanvasPathDrawingStyles,
|
||||||
CanvasTextDrawingStyles,
|
CanvasTextDrawingStyles,
|
||||||
CanvasPath {
|
CanvasPath {
|
||||||
readonly canvas: OffscreenCanvas;
|
readonly canvas: OffscreenCanvas;
|
||||||
}
|
}
|
||||||
declare const OffscreenCanvasRenderingContext2D: {
|
declare const OffscreenCanvasRenderingContext2D: {
|
||||||
prototype: OffscreenCanvasRenderingContext2D;
|
prototype: OffscreenCanvasRenderingContext2D;
|
||||||
new(): OffscreenCanvasRenderingContext2D;
|
new (): OffscreenCanvasRenderingContext2D;
|
||||||
};
|
};
|
||||||
|
|
||||||
interface OffscreenCanvas extends EventTarget {
|
interface OffscreenCanvas extends EventTarget {
|
||||||
@ -575,7 +575,7 @@ interface OffscreenCanvas extends EventTarget {
|
|||||||
}
|
}
|
||||||
declare const OffscreenCanvas: {
|
declare const OffscreenCanvas: {
|
||||||
prototype: OffscreenCanvas;
|
prototype: OffscreenCanvas;
|
||||||
new(width: number, height: number): OffscreenCanvas;
|
new (width: number, height: number): OffscreenCanvas;
|
||||||
};
|
};
|
||||||
|
|
||||||
function createCanvas(size: number): OffscreenCanvas {
|
function createCanvas(size: number): OffscreenCanvas {
|
||||||
|
@ -34,18 +34,21 @@ setupI18n("en", { en: {} });
|
|||||||
setupPlatform(chromeAPI);
|
setupPlatform(chromeAPI);
|
||||||
|
|
||||||
describe("All the examples:", () => {
|
describe("All the examples:", () => {
|
||||||
const cms = parseGroupImport({ popup, wallet, cta, mui, components })
|
const cms = parseGroupImport({ popup, wallet, cta, mui, components });
|
||||||
cms.forEach(group => {
|
cms.forEach((group) => {
|
||||||
describe(`Example for group "${group.title}:"`, () => {
|
describe(`Example for group "${group.title}:"`, () => {
|
||||||
group.list.forEach(component => {
|
group.list.forEach((component) => {
|
||||||
describe(`Component ${component.name}:`, () => {
|
describe(`Component ${component.name}:`, () => {
|
||||||
component.examples.forEach(example => {
|
component.examples.forEach((example) => {
|
||||||
it(`should render example: ${example.name}`, () => {
|
it(`should render example: ${example.name}`, () => {
|
||||||
renderNodeOrBrowser(example.render.component, example.render.props)
|
renderNodeOrBrowser(
|
||||||
})
|
example.render.component,
|
||||||
})
|
example.render.props,
|
||||||
})
|
);
|
||||||
})
|
});
|
||||||
})
|
});
|
||||||
})
|
});
|
||||||
|
});
|
||||||
|
});
|
||||||
|
});
|
||||||
});
|
});
|
||||||
|
@ -54,7 +54,7 @@ export function createExample<Props>(
|
|||||||
|
|
||||||
return {
|
return {
|
||||||
component: Render,
|
component: Render,
|
||||||
props: evaluatedProps
|
props: evaluatedProps,
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -74,7 +74,7 @@ export function createExampleWithCustomContext<Props, ContextProps>(
|
|||||||
|
|
||||||
return {
|
return {
|
||||||
component: WithContext,
|
component: WithContext,
|
||||||
props: evaluatedProps
|
props: evaluatedProps,
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -253,7 +253,7 @@ type Subscriptions = {
|
|||||||
|
|
||||||
export function createWalletApiMock(): {
|
export function createWalletApiMock(): {
|
||||||
handler: MockHandler;
|
handler: MockHandler;
|
||||||
TestingContext: FunctionalComponent<{ children: ComponentChildren }>
|
TestingContext: FunctionalComponent<{ children: ComponentChildren }>;
|
||||||
} {
|
} {
|
||||||
const calls = new Array<CallRecord>();
|
const calls = new Array<CallRecord>();
|
||||||
const subscriptions: Subscriptions = {};
|
const subscriptions: Subscriptions = {};
|
||||||
@ -342,8 +342,8 @@ export function createWalletApiMock(): {
|
|||||||
callback: cb
|
callback: cb
|
||||||
? cb
|
? cb
|
||||||
: () => {
|
: () => {
|
||||||
null;
|
null;
|
||||||
},
|
},
|
||||||
});
|
});
|
||||||
return handler;
|
return handler;
|
||||||
},
|
},
|
||||||
@ -358,13 +358,21 @@ export function createWalletApiMock(): {
|
|||||||
},
|
},
|
||||||
};
|
};
|
||||||
|
|
||||||
function TestingContext({ children }: { children: ComponentChildren }): VNode {
|
function TestingContext({
|
||||||
return create(BackendProvider, {
|
children,
|
||||||
wallet: mock.wallet,
|
}: {
|
||||||
background: mock.background,
|
children: ComponentChildren;
|
||||||
listener: mock.listener,
|
}): VNode {
|
||||||
|
return create(
|
||||||
|
BackendProvider,
|
||||||
|
{
|
||||||
|
wallet: mock.wallet,
|
||||||
|
background: mock.background,
|
||||||
|
listener: mock.listener,
|
||||||
|
children,
|
||||||
|
},
|
||||||
children,
|
children,
|
||||||
}, children)
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
return { handler, TestingContext };
|
return { handler, TestingContext };
|
||||||
|
@ -14,22 +14,21 @@
|
|||||||
GNU Taler; see the file COPYING. If not, see <http://www.gnu.org/licenses/>
|
GNU Taler; see the file COPYING. If not, see <http://www.gnu.org/licenses/>
|
||||||
*/
|
*/
|
||||||
|
|
||||||
import {
|
import { TalerErrorDetail } from "@gnu-taler/taler-util";
|
||||||
TalerErrorDetail
|
|
||||||
} from "@gnu-taler/taler-util";
|
|
||||||
import { SyncTermsOfServiceResponse } from "@gnu-taler/taler-wallet-core";
|
import { SyncTermsOfServiceResponse } from "@gnu-taler/taler-wallet-core";
|
||||||
import { Loading } from "../../components/Loading.js";
|
import { Loading } from "../../components/Loading.js";
|
||||||
import { HookError } from "../../hooks/useAsyncAsHook.js";
|
import { HookError } from "../../hooks/useAsyncAsHook.js";
|
||||||
import {
|
import {
|
||||||
ButtonHandler,
|
ButtonHandler,
|
||||||
TextFieldHandler,
|
TextFieldHandler,
|
||||||
ToggleHandler
|
ToggleHandler,
|
||||||
} from "../../mui/handlers.js";
|
} from "../../mui/handlers.js";
|
||||||
import { compose, StateViewMap } from "../../utils/index.js";
|
import { compose, StateViewMap } from "../../utils/index.js";
|
||||||
import { useComponentState } from "./state.js";
|
import { useComponentState } from "./state.js";
|
||||||
import {
|
import {
|
||||||
ConfirmProviderView, LoadingUriView,
|
ConfirmProviderView,
|
||||||
SelectProviderView
|
LoadingUriView,
|
||||||
|
SelectProviderView,
|
||||||
} from "./views.js";
|
} from "./views.js";
|
||||||
|
|
||||||
export interface Props {
|
export interface Props {
|
||||||
|
@ -17,11 +17,11 @@
|
|||||||
import {
|
import {
|
||||||
canonicalizeBaseUrl,
|
canonicalizeBaseUrl,
|
||||||
Codec,
|
Codec,
|
||||||
TalerErrorDetail
|
TalerErrorDetail,
|
||||||
} from "@gnu-taler/taler-util";
|
} from "@gnu-taler/taler-util";
|
||||||
import {
|
import {
|
||||||
codecForSyncTermsOfServiceResponse,
|
codecForSyncTermsOfServiceResponse,
|
||||||
WalletApiOperation
|
WalletApiOperation,
|
||||||
} from "@gnu-taler/taler-wallet-core";
|
} from "@gnu-taler/taler-wallet-core";
|
||||||
import { useEffect, useState } from "preact/hooks";
|
import { useEffect, useState } from "preact/hooks";
|
||||||
import { useBackendContext } from "../../context/backend.js";
|
import { useBackendContext } from "../../context/backend.js";
|
||||||
@ -106,47 +106,50 @@ function useUrlState<T>(
|
|||||||
constHref == undefined
|
constHref == undefined
|
||||||
? undefined
|
? undefined
|
||||||
: async () => {
|
: async () => {
|
||||||
const req = await fetch(constHref).catch((e) => {
|
const req = await fetch(constHref).catch((e) => {
|
||||||
return setState({
|
return setState({
|
||||||
status: "network-error",
|
status: "network-error",
|
||||||
href: constHref,
|
href: constHref,
|
||||||
|
});
|
||||||
});
|
});
|
||||||
});
|
if (!req) return;
|
||||||
if (!req) return;
|
|
||||||
|
|
||||||
if (req.status >= 400 && req.status < 500) {
|
if (req.status >= 400 && req.status < 500) {
|
||||||
setState({
|
setState({
|
||||||
status: "client-error",
|
status: "client-error",
|
||||||
code: req.status,
|
code: req.status,
|
||||||
});
|
});
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
if (req.status > 500) {
|
if (req.status > 500) {
|
||||||
setState({
|
setState({
|
||||||
status: "server-error",
|
status: "server-error",
|
||||||
code: req.status,
|
code: req.status,
|
||||||
});
|
});
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
const json = await req.json();
|
const json = await req.json();
|
||||||
try {
|
try {
|
||||||
const result = codec.decode(json);
|
const result = codec.decode(json);
|
||||||
setState({ status: "ok", result });
|
setState({ status: "ok", result });
|
||||||
} catch (e: any) {
|
} catch (e: any) {
|
||||||
setState({ status: "parsing-error", json });
|
setState({ status: "parsing-error", json });
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
[host, path],
|
[host, path],
|
||||||
);
|
);
|
||||||
|
|
||||||
return state;
|
return state;
|
||||||
}
|
}
|
||||||
|
|
||||||
export function useComponentState(
|
export function useComponentState({
|
||||||
{ currency, onBack, onComplete, onPaymentRequired }: Props,
|
currency,
|
||||||
): State {
|
onBack,
|
||||||
const api = useBackendContext()
|
onComplete,
|
||||||
|
onPaymentRequired,
|
||||||
|
}: Props): State {
|
||||||
|
const api = useBackendContext();
|
||||||
const [url, setHost] = useState<string | undefined>();
|
const [url, setHost] = useState<string | undefined>();
|
||||||
const [name, setName] = useState<string | undefined>();
|
const [name, setName] = useState<string | undefined>();
|
||||||
const [tos, setTos] = useState(false);
|
const [tos, setTos] = useState(false);
|
||||||
@ -223,8 +226,8 @@ export function useComponentState(
|
|||||||
!urlState || urlState.status !== "ok" || !name
|
!urlState || urlState.status !== "ok" || !name
|
||||||
? undefined
|
? undefined
|
||||||
: async () => {
|
: async () => {
|
||||||
setShowConfirm(true);
|
setShowConfirm(true);
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
urlOk: urlState?.status === "ok",
|
urlOk: urlState?.status === "ok",
|
||||||
url: {
|
url: {
|
||||||
|
@ -21,9 +21,7 @@
|
|||||||
|
|
||||||
import { expect } from "chai";
|
import { expect } from "chai";
|
||||||
import { tests } from "../../../../web-util/src/index.browser.js";
|
import { tests } from "../../../../web-util/src/index.browser.js";
|
||||||
import {
|
import { createWalletApiMock, nullFunction } from "../../test-utils.js";
|
||||||
createWalletApiMock, nullFunction
|
|
||||||
} from "../../test-utils.js";
|
|
||||||
import { Props } from "./index.js";
|
import { Props } from "./index.js";
|
||||||
import { useComponentState } from "./state.js";
|
import { useComponentState } from "./state.js";
|
||||||
|
|
||||||
@ -34,21 +32,24 @@ const props: Props = {
|
|||||||
onPaymentRequired: nullFunction,
|
onPaymentRequired: nullFunction,
|
||||||
};
|
};
|
||||||
describe("AddBackupProvider states", () => {
|
describe("AddBackupProvider states", () => {
|
||||||
|
|
||||||
it("should start in 'select-provider' state", async () => {
|
it("should start in 'select-provider' state", async () => {
|
||||||
const { handler, TestingContext } = createWalletApiMock();
|
const { handler, TestingContext } = createWalletApiMock();
|
||||||
|
|
||||||
const hookBehavior = await tests.hookBehaveLikeThis(useComponentState, props, [
|
const hookBehavior = await tests.hookBehaveLikeThis(
|
||||||
(state) => {
|
useComponentState,
|
||||||
expect(state.status).equal("select-provider");
|
props,
|
||||||
if (state.status !== "select-provider") return;
|
[
|
||||||
expect(state.name.value).eq("");
|
(state) => {
|
||||||
expect(state.url.value).eq("");
|
expect(state.status).equal("select-provider");
|
||||||
},
|
if (state.status !== "select-provider") return;
|
||||||
], TestingContext)
|
expect(state.name.value).eq("");
|
||||||
|
expect(state.url.value).eq("");
|
||||||
|
},
|
||||||
|
],
|
||||||
|
TestingContext,
|
||||||
|
);
|
||||||
|
|
||||||
expect(hookBehavior).deep.equal({ result: "ok" })
|
expect(hookBehavior).deep.equal({ result: "ok" });
|
||||||
expect(handler.getCallingQueueState()).eq("empty");
|
expect(handler.getCallingQueueState()).eq("empty");
|
||||||
|
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
|
@ -20,7 +20,7 @@ import { HookError } from "../../hooks/useAsyncAsHook.js";
|
|||||||
import {
|
import {
|
||||||
AmountFieldHandler,
|
AmountFieldHandler,
|
||||||
ButtonHandler,
|
ButtonHandler,
|
||||||
SelectFieldHandler
|
SelectFieldHandler,
|
||||||
} from "../../mui/handlers.js";
|
} from "../../mui/handlers.js";
|
||||||
import { compose, StateViewMap } from "../../utils/index.js";
|
import { compose, StateViewMap } from "../../utils/index.js";
|
||||||
import { ManageAccountPage } from "../ManageAccount/index.js";
|
import { ManageAccountPage } from "../ManageAccount/index.js";
|
||||||
@ -30,7 +30,7 @@ import {
|
|||||||
LoadingErrorView,
|
LoadingErrorView,
|
||||||
NoAccountToDepositView,
|
NoAccountToDepositView,
|
||||||
NoEnoughBalanceView,
|
NoEnoughBalanceView,
|
||||||
ReadyView
|
ReadyView,
|
||||||
} from "./views.js";
|
} from "./views.js";
|
||||||
|
|
||||||
export interface Props {
|
export interface Props {
|
||||||
|
@ -21,7 +21,7 @@ import {
|
|||||||
KnownBankAccountsInfo,
|
KnownBankAccountsInfo,
|
||||||
parsePaytoUri,
|
parsePaytoUri,
|
||||||
PaytoUri,
|
PaytoUri,
|
||||||
stringifyPaytoUri
|
stringifyPaytoUri,
|
||||||
} from "@gnu-taler/taler-util";
|
} from "@gnu-taler/taler-util";
|
||||||
import { WalletApiOperation } from "@gnu-taler/taler-wallet-core";
|
import { WalletApiOperation } from "@gnu-taler/taler-wallet-core";
|
||||||
import { useState } from "preact/hooks";
|
import { useState } from "preact/hooks";
|
||||||
@ -29,10 +29,13 @@ import { useBackendContext } from "../../context/backend.js";
|
|||||||
import { useAsyncAsHook } from "../../hooks/useAsyncAsHook.js";
|
import { useAsyncAsHook } from "../../hooks/useAsyncAsHook.js";
|
||||||
import { Props, State } from "./index.js";
|
import { Props, State } from "./index.js";
|
||||||
|
|
||||||
export function useComponentState(
|
export function useComponentState({
|
||||||
{ amount: amountStr, currency: currencyStr, onCancel, onSuccess }: Props,
|
amount: amountStr,
|
||||||
): State {
|
currency: currencyStr,
|
||||||
const api = useBackendContext()
|
onCancel,
|
||||||
|
onSuccess,
|
||||||
|
}: Props): State {
|
||||||
|
const api = useBackendContext();
|
||||||
const parsed = amountStr === undefined ? undefined : Amounts.parse(amountStr);
|
const parsed = amountStr === undefined ? undefined : Amounts.parse(amountStr);
|
||||||
const currency = parsed !== undefined ? parsed.currency : currencyStr;
|
const currency = parsed !== undefined ? parsed.currency : currencyStr;
|
||||||
|
|
||||||
@ -55,8 +58,8 @@ export function useComponentState(
|
|||||||
parsed !== undefined
|
parsed !== undefined
|
||||||
? parsed
|
? parsed
|
||||||
: currency !== undefined
|
: currency !== undefined
|
||||||
? Amounts.zeroOfCurrency(currency)
|
? Amounts.zeroOfCurrency(currency)
|
||||||
: undefined;
|
: undefined;
|
||||||
// const [accountIdx, setAccountIdx] = useState<number>(0);
|
// const [accountIdx, setAccountIdx] = useState<number>(0);
|
||||||
const [amount, setAmount] = useState<AmountJson>(initialValue ?? ({} as any));
|
const [amount, setAmount] = useState<AmountJson>(initialValue ?? ({} as any));
|
||||||
const [selectedAccount, setSelectedAccount] = useState<PaytoUri>();
|
const [selectedAccount, setSelectedAccount] = useState<PaytoUri>();
|
||||||
@ -162,7 +165,11 @@ export function useComponentState(
|
|||||||
async function updateAmount(newAmount: AmountJson): Promise<void> {
|
async function updateAmount(newAmount: AmountJson): Promise<void> {
|
||||||
// const parsed = Amounts.parse(`${currency}:${numStr}`);
|
// const parsed = Amounts.parse(`${currency}:${numStr}`);
|
||||||
try {
|
try {
|
||||||
const result = await getFeeForAmount(currentAccount, newAmount, api.wallet);
|
const result = await getFeeForAmount(
|
||||||
|
currentAccount,
|
||||||
|
newAmount,
|
||||||
|
api.wallet,
|
||||||
|
);
|
||||||
setAmount(newAmount);
|
setAmount(newAmount);
|
||||||
setFee(result);
|
setFee(result);
|
||||||
} catch (e) {
|
} catch (e) {
|
||||||
@ -185,8 +192,8 @@ export function useComponentState(
|
|||||||
const amountError = !isDirty
|
const amountError = !isDirty
|
||||||
? undefined
|
? undefined
|
||||||
: Amounts.cmp(balance, amount) === -1
|
: Amounts.cmp(balance, amount) === -1
|
||||||
? `Too much, your current balance is ${Amounts.stringifyValue(balance)}`
|
? `Too much, your current balance is ${Amounts.stringifyValue(balance)}`
|
||||||
: undefined;
|
: undefined;
|
||||||
|
|
||||||
const unableToDeposit =
|
const unableToDeposit =
|
||||||
Amounts.isZero(totalToDeposit) || //deposit may be zero because of fee
|
Amounts.isZero(totalToDeposit) || //deposit may be zero because of fee
|
||||||
|
@ -23,14 +23,12 @@ import {
|
|||||||
Amounts,
|
Amounts,
|
||||||
DepositGroupFees,
|
DepositGroupFees,
|
||||||
parsePaytoUri,
|
parsePaytoUri,
|
||||||
stringifyPaytoUri
|
stringifyPaytoUri,
|
||||||
} from "@gnu-taler/taler-util";
|
} from "@gnu-taler/taler-util";
|
||||||
import { WalletApiOperation } from "@gnu-taler/taler-wallet-core";
|
import { WalletApiOperation } from "@gnu-taler/taler-wallet-core";
|
||||||
import { expect } from "chai";
|
import { expect } from "chai";
|
||||||
import { tests } from "../../../../web-util/src/index.browser.js";
|
import { tests } from "../../../../web-util/src/index.browser.js";
|
||||||
import {
|
import { createWalletApiMock, nullFunction } from "../../test-utils.js";
|
||||||
createWalletApiMock, nullFunction
|
|
||||||
} from "../../test-utils.js";
|
|
||||||
|
|
||||||
import { useComponentState } from "./state.js";
|
import { useComponentState } from "./state.js";
|
||||||
|
|
||||||
@ -71,16 +69,21 @@ describe("DepositPage states", () => {
|
|||||||
},
|
},
|
||||||
);
|
);
|
||||||
|
|
||||||
const hookBehavior = await tests.hookBehaveLikeThis(useComponentState, props, [
|
const hookBehavior = await tests.hookBehaveLikeThis(
|
||||||
({ status }) => {
|
useComponentState,
|
||||||
expect(status).equal("loading");
|
props,
|
||||||
},
|
[
|
||||||
({ status }) => {
|
({ status }) => {
|
||||||
expect(status).equal("no-enough-balance");
|
expect(status).equal("loading");
|
||||||
},
|
},
|
||||||
], TestingContext)
|
({ status }) => {
|
||||||
|
expect(status).equal("no-enough-balance");
|
||||||
|
},
|
||||||
|
],
|
||||||
|
TestingContext,
|
||||||
|
);
|
||||||
|
|
||||||
expect(hookBehavior).deep.equal({ result: "ok" })
|
expect(hookBehavior).deep.equal({ result: "ok" });
|
||||||
expect(handler.getCallingQueueState()).eq("empty");
|
expect(handler.getCallingQueueState()).eq("empty");
|
||||||
});
|
});
|
||||||
|
|
||||||
@ -107,16 +110,21 @@ describe("DepositPage states", () => {
|
|||||||
},
|
},
|
||||||
);
|
);
|
||||||
|
|
||||||
const hookBehavior = await tests.hookBehaveLikeThis(useComponentState, props, [
|
const hookBehavior = await tests.hookBehaveLikeThis(
|
||||||
({ status }) => {
|
useComponentState,
|
||||||
expect(status).equal("loading");
|
props,
|
||||||
},
|
[
|
||||||
({ status }) => {
|
({ status }) => {
|
||||||
expect(status).equal("no-accounts");
|
expect(status).equal("loading");
|
||||||
},
|
},
|
||||||
], TestingContext)
|
({ status }) => {
|
||||||
|
expect(status).equal("no-accounts");
|
||||||
|
},
|
||||||
|
],
|
||||||
|
TestingContext,
|
||||||
|
);
|
||||||
|
|
||||||
expect(hookBehavior).deep.equal({ result: "ok" })
|
expect(hookBehavior).deep.equal({ result: "ok" });
|
||||||
expect(handler.getCallingQueueState()).eq("empty");
|
expect(handler.getCallingQueueState()).eq("empty");
|
||||||
});
|
});
|
||||||
|
|
||||||
@ -161,24 +169,29 @@ describe("DepositPage states", () => {
|
|||||||
withoutFee(),
|
withoutFee(),
|
||||||
);
|
);
|
||||||
|
|
||||||
const hookBehavior = await tests.hookBehaveLikeThis(useComponentState, props, [
|
const hookBehavior = await tests.hookBehaveLikeThis(
|
||||||
({ status }) => {
|
useComponentState,
|
||||||
expect(status).equal("loading");
|
props,
|
||||||
},
|
[
|
||||||
({ status }) => {
|
({ status }) => {
|
||||||
expect(status).equal("loading");
|
expect(status).equal("loading");
|
||||||
},
|
},
|
||||||
(state) => {
|
({ status }) => {
|
||||||
if (state.status !== "ready") expect.fail();
|
expect(status).equal("loading");
|
||||||
expect(state.cancelHandler.onClick).not.undefined;
|
},
|
||||||
expect(state.currency).eq(currency);
|
(state) => {
|
||||||
expect(state.account.value).eq(stringifyPaytoUri(ibanPayto.uri));
|
if (state.status !== "ready") expect.fail();
|
||||||
expect(state.amount.value).deep.eq(Amounts.parseOrThrow("EUR:0"));
|
expect(state.cancelHandler.onClick).not.undefined;
|
||||||
expect(state.depositHandler.onClick).undefined;
|
expect(state.currency).eq(currency);
|
||||||
},
|
expect(state.account.value).eq(stringifyPaytoUri(ibanPayto.uri));
|
||||||
], TestingContext)
|
expect(state.amount.value).deep.eq(Amounts.parseOrThrow("EUR:0"));
|
||||||
|
expect(state.depositHandler.onClick).undefined;
|
||||||
|
},
|
||||||
|
],
|
||||||
|
TestingContext,
|
||||||
|
);
|
||||||
|
|
||||||
expect(hookBehavior).deep.equal({ result: "ok" })
|
expect(hookBehavior).deep.equal({ result: "ok" });
|
||||||
expect(handler.getCallingQueueState()).eq("empty");
|
expect(handler.getCallingQueueState()).eq("empty");
|
||||||
});
|
});
|
||||||
|
|
||||||
@ -218,37 +231,42 @@ describe("DepositPage states", () => {
|
|||||||
|
|
||||||
const accountSelected = stringifyPaytoUri(ibanPayto.uri);
|
const accountSelected = stringifyPaytoUri(ibanPayto.uri);
|
||||||
|
|
||||||
const hookBehavior = await tests.hookBehaveLikeThis(useComponentState, props, [
|
const hookBehavior = await tests.hookBehaveLikeThis(
|
||||||
({ status }) => {
|
useComponentState,
|
||||||
expect(status).equal("loading");
|
props,
|
||||||
},
|
[
|
||||||
({ status }) => {
|
({ status }) => {
|
||||||
expect(status).equal("loading");
|
expect(status).equal("loading");
|
||||||
},
|
},
|
||||||
(state) => {
|
({ status }) => {
|
||||||
if (state.status !== "ready") expect.fail();
|
expect(status).equal("loading");
|
||||||
expect(state.cancelHandler.onClick).not.undefined;
|
},
|
||||||
expect(state.currency).eq(currency);
|
(state) => {
|
||||||
expect(state.account.value).eq(stringifyPaytoUri(talerBankPayto.uri));
|
if (state.status !== "ready") expect.fail();
|
||||||
expect(state.amount.value).deep.eq(Amounts.parseOrThrow("EUR:0"));
|
expect(state.cancelHandler.onClick).not.undefined;
|
||||||
expect(state.depositHandler.onClick).undefined;
|
expect(state.currency).eq(currency);
|
||||||
expect(state.totalFee).deep.eq(Amounts.parseOrThrow(`${currency}:0`));
|
expect(state.account.value).eq(stringifyPaytoUri(talerBankPayto.uri));
|
||||||
expect(state.account.onChange).not.undefined;
|
expect(state.amount.value).deep.eq(Amounts.parseOrThrow("EUR:0"));
|
||||||
|
expect(state.depositHandler.onClick).undefined;
|
||||||
|
expect(state.totalFee).deep.eq(Amounts.parseOrThrow(`${currency}:0`));
|
||||||
|
expect(state.account.onChange).not.undefined;
|
||||||
|
|
||||||
state.account.onChange!(accountSelected);
|
state.account.onChange!(accountSelected);
|
||||||
},
|
},
|
||||||
(state) => {
|
(state) => {
|
||||||
if (state.status !== "ready") expect.fail();
|
if (state.status !== "ready") expect.fail();
|
||||||
expect(state.cancelHandler.onClick).not.undefined;
|
expect(state.cancelHandler.onClick).not.undefined;
|
||||||
expect(state.currency).eq(currency);
|
expect(state.currency).eq(currency);
|
||||||
expect(state.account.value).eq(accountSelected);
|
expect(state.account.value).eq(accountSelected);
|
||||||
expect(state.amount.value).deep.eq(Amounts.parseOrThrow("EUR:0"));
|
expect(state.amount.value).deep.eq(Amounts.parseOrThrow("EUR:0"));
|
||||||
expect(state.totalFee).deep.eq(Amounts.parseOrThrow(`${currency}:0`));
|
expect(state.totalFee).deep.eq(Amounts.parseOrThrow(`${currency}:0`));
|
||||||
expect(state.depositHandler.onClick).undefined;
|
expect(state.depositHandler.onClick).undefined;
|
||||||
},
|
},
|
||||||
], TestingContext)
|
],
|
||||||
|
TestingContext,
|
||||||
|
);
|
||||||
|
|
||||||
expect(hookBehavior).deep.equal({ result: "ok" })
|
expect(hookBehavior).deep.equal({ result: "ok" });
|
||||||
expect(handler.getCallingQueueState()).eq("empty");
|
expect(handler.getCallingQueueState()).eq("empty");
|
||||||
});
|
});
|
||||||
|
|
||||||
@ -292,52 +310,58 @@ describe("DepositPage states", () => {
|
|||||||
|
|
||||||
const accountSelected = stringifyPaytoUri(ibanPayto.uri);
|
const accountSelected = stringifyPaytoUri(ibanPayto.uri);
|
||||||
|
|
||||||
const hookBehavior = await tests.hookBehaveLikeThis(useComponentState, props, [
|
const hookBehavior = await tests.hookBehaveLikeThis(
|
||||||
({ status }) => {
|
useComponentState,
|
||||||
expect(status).equal("loading");
|
props,
|
||||||
},
|
[
|
||||||
({ status }) => {
|
({ status }) => {
|
||||||
expect(status).equal("loading");
|
expect(status).equal("loading");
|
||||||
},
|
},
|
||||||
(state) => {
|
({ status }) => {
|
||||||
if (state.status !== "ready") expect.fail();
|
expect(status).equal("loading");
|
||||||
expect(state.cancelHandler.onClick).not.undefined;
|
},
|
||||||
expect(state.currency).eq(currency);
|
(state) => {
|
||||||
expect(state.account.value).eq(stringifyPaytoUri(talerBankPayto.uri));
|
if (state.status !== "ready") expect.fail();
|
||||||
expect(state.amount.value).deep.eq(Amounts.parseOrThrow("EUR:0"));
|
expect(state.cancelHandler.onClick).not.undefined;
|
||||||
expect(state.depositHandler.onClick).undefined;
|
expect(state.currency).eq(currency);
|
||||||
expect(state.totalFee).deep.eq(Amounts.parseOrThrow(`${currency}:0`));
|
expect(state.account.value).eq(stringifyPaytoUri(talerBankPayto.uri));
|
||||||
expect(state.account.onChange).not.undefined;
|
expect(state.amount.value).deep.eq(Amounts.parseOrThrow("EUR:0"));
|
||||||
|
expect(state.depositHandler.onClick).undefined;
|
||||||
|
expect(state.totalFee).deep.eq(Amounts.parseOrThrow(`${currency}:0`));
|
||||||
|
expect(state.account.onChange).not.undefined;
|
||||||
|
|
||||||
state.account.onChange!(accountSelected);
|
state.account.onChange!(accountSelected);
|
||||||
},
|
},
|
||||||
(state) => {
|
(state) => {
|
||||||
if (state.status !== "ready") expect.fail();
|
if (state.status !== "ready") expect.fail();
|
||||||
expect(state.cancelHandler.onClick).not.undefined;
|
expect(state.cancelHandler.onClick).not.undefined;
|
||||||
expect(state.currency).eq(currency);
|
expect(state.currency).eq(currency);
|
||||||
expect(state.account.value).eq(accountSelected);
|
expect(state.account.value).eq(accountSelected);
|
||||||
expect(state.amount.value).deep.eq(Amounts.parseOrThrow("EUR:0"));
|
expect(state.amount.value).deep.eq(Amounts.parseOrThrow("EUR:0"));
|
||||||
expect(state.depositHandler.onClick).undefined;
|
expect(state.depositHandler.onClick).undefined;
|
||||||
expect(state.totalFee).deep.eq(Amounts.parseOrThrow(`${currency}:3`));
|
expect(state.totalFee).deep.eq(Amounts.parseOrThrow(`${currency}:3`));
|
||||||
|
|
||||||
expect(state.amount.onInput).not.undefined;
|
expect(state.amount.onInput).not.undefined;
|
||||||
if (!state.amount.onInput) return;
|
if (!state.amount.onInput) return;
|
||||||
state.amount.onInput(Amounts.parseOrThrow("EUR:10"));
|
state.amount.onInput(Amounts.parseOrThrow("EUR:10"));
|
||||||
},
|
},
|
||||||
(state) => {
|
(state) => {
|
||||||
if (state.status !== "ready") expect.fail();
|
if (state.status !== "ready") expect.fail();
|
||||||
expect(state.cancelHandler.onClick).not.undefined;
|
expect(state.cancelHandler.onClick).not.undefined;
|
||||||
expect(state.currency).eq(currency);
|
expect(state.currency).eq(currency);
|
||||||
expect(state.account.value).eq(accountSelected);
|
expect(state.account.value).eq(accountSelected);
|
||||||
expect(state.amount.value).deep.eq(Amounts.parseOrThrow("EUR:10"));
|
expect(state.amount.value).deep.eq(Amounts.parseOrThrow("EUR:10"));
|
||||||
expect(state.totalFee).deep.eq(Amounts.parseOrThrow(`${currency}:3`));
|
expect(state.totalFee).deep.eq(Amounts.parseOrThrow(`${currency}:3`));
|
||||||
expect(state.totalToDeposit).deep.eq(Amounts.parseOrThrow(`${currency}:7`));
|
expect(state.totalToDeposit).deep.eq(
|
||||||
expect(state.depositHandler.onClick).not.undefined;
|
Amounts.parseOrThrow(`${currency}:7`),
|
||||||
},
|
);
|
||||||
], TestingContext)
|
expect(state.depositHandler.onClick).not.undefined;
|
||||||
|
},
|
||||||
|
],
|
||||||
|
TestingContext,
|
||||||
|
);
|
||||||
|
|
||||||
expect(hookBehavior).deep.equal({ result: "ok" })
|
expect(hookBehavior).deep.equal({ result: "ok" });
|
||||||
expect(handler.getCallingQueueState()).eq("empty");
|
expect(handler.getCallingQueueState()).eq("empty");
|
||||||
|
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
|
@ -22,10 +22,8 @@ import { useAsyncAsHook } from "../../hooks/useAsyncAsHook.js";
|
|||||||
import { assertUnreachable, RecursiveState } from "../../utils/index.js";
|
import { assertUnreachable, RecursiveState } from "../../utils/index.js";
|
||||||
import { Contact, Props, State } from "./index.js";
|
import { Contact, Props, State } from "./index.js";
|
||||||
|
|
||||||
export function useComponentState(
|
export function useComponentState(props: Props): RecursiveState<State> {
|
||||||
props: Props,
|
const api = useBackendContext();
|
||||||
): RecursiveState<State> {
|
|
||||||
const api = useBackendContext()
|
|
||||||
const parsedInitialAmount = !props.amount
|
const parsedInitialAmount = !props.amount
|
||||||
? undefined
|
? undefined
|
||||||
: Amounts.parse(props.amount);
|
: Amounts.parse(props.amount);
|
||||||
@ -41,22 +39,22 @@ export function useComponentState(
|
|||||||
const previous: Contact[] = true
|
const previous: Contact[] = true
|
||||||
? []
|
? []
|
||||||
: [
|
: [
|
||||||
{
|
{
|
||||||
name: "International Bank",
|
name: "International Bank",
|
||||||
icon_type: 'bank',
|
icon_type: "bank",
|
||||||
description: "account ending with 3454",
|
description: "account ending with 3454",
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
name: "Max",
|
name: "Max",
|
||||||
icon_type: 'bank',
|
icon_type: "bank",
|
||||||
description: "account ending with 3454",
|
description: "account ending with 3454",
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
name: "Alex",
|
name: "Alex",
|
||||||
icon_type: 'bank',
|
icon_type: "bank",
|
||||||
description: "account ending with 3454",
|
description: "account ending with 3454",
|
||||||
},
|
},
|
||||||
];
|
];
|
||||||
|
|
||||||
if (!amount) {
|
if (!amount) {
|
||||||
return () => {
|
return () => {
|
||||||
@ -114,15 +112,15 @@ export function useComponentState(
|
|||||||
onClick: invalid
|
onClick: invalid
|
||||||
? undefined
|
? undefined
|
||||||
: async () => {
|
: async () => {
|
||||||
props.goToWalletBankDeposit(currencyAndAmount);
|
props.goToWalletBankDeposit(currencyAndAmount);
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
goToWallet: {
|
goToWallet: {
|
||||||
onClick: invalid
|
onClick: invalid
|
||||||
? undefined
|
? undefined
|
||||||
: async () => {
|
: async () => {
|
||||||
props.goToWalletWalletSend(currencyAndAmount);
|
props.goToWalletWalletSend(currencyAndAmount);
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
amountHandler: {
|
amountHandler: {
|
||||||
onInput: async (s) => setAmount(s),
|
onInput: async (s) => setAmount(s),
|
||||||
@ -144,15 +142,15 @@ export function useComponentState(
|
|||||||
onClick: invalid
|
onClick: invalid
|
||||||
? undefined
|
? undefined
|
||||||
: async () => {
|
: async () => {
|
||||||
props.goToWalletManualWithdraw(currencyAndAmount);
|
props.goToWalletManualWithdraw(currencyAndAmount);
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
goToWallet: {
|
goToWallet: {
|
||||||
onClick: invalid
|
onClick: invalid
|
||||||
? undefined
|
? undefined
|
||||||
: async () => {
|
: async () => {
|
||||||
props.goToWalletWalletInvoice(currencyAndAmount);
|
props.goToWalletWalletInvoice(currencyAndAmount);
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
amountHandler: {
|
amountHandler: {
|
||||||
onInput: async (s) => setAmount(s),
|
onInput: async (s) => setAmount(s),
|
||||||
|
@ -23,7 +23,7 @@ import {
|
|||||||
Amounts,
|
Amounts,
|
||||||
ExchangeEntryStatus,
|
ExchangeEntryStatus,
|
||||||
ExchangeListItem,
|
ExchangeListItem,
|
||||||
ExchangeTosStatus
|
ExchangeTosStatus,
|
||||||
} from "@gnu-taler/taler-util";
|
} from "@gnu-taler/taler-util";
|
||||||
import { WalletApiOperation } from "@gnu-taler/taler-wallet-core";
|
import { WalletApiOperation } from "@gnu-taler/taler-wallet-core";
|
||||||
import { expect } from "chai";
|
import { expect } from "chai";
|
||||||
@ -59,33 +59,39 @@ describe("Destination selection states", () => {
|
|||||||
goToWalletWalletInvoice: nullFunction,
|
goToWalletWalletInvoice: nullFunction,
|
||||||
};
|
};
|
||||||
|
|
||||||
const hookBehavior = await tests.hookBehaveLikeThis(useComponentState, props, [
|
const hookBehavior = await tests.hookBehaveLikeThis(
|
||||||
({ status }) => {
|
useComponentState,
|
||||||
expect(status).equal("loading");
|
props,
|
||||||
},
|
[
|
||||||
(state) => {
|
({ status }) => {
|
||||||
if (state.status !== "select-currency") expect.fail();
|
expect(status).equal("loading");
|
||||||
if (state.error) expect.fail();
|
},
|
||||||
expect(state.currencies).deep.eq({
|
(state) => {
|
||||||
ARS: "ARS",
|
if (state.status !== "select-currency") expect.fail();
|
||||||
"": "Select a currency",
|
if (state.error) expect.fail();
|
||||||
});
|
expect(state.currencies).deep.eq({
|
||||||
|
ARS: "ARS",
|
||||||
|
"": "Select a currency",
|
||||||
|
});
|
||||||
|
|
||||||
state.onCurrencySelected(exchangeArs.currency!);
|
state.onCurrencySelected(exchangeArs.currency!);
|
||||||
},
|
},
|
||||||
(state) => {
|
(state) => {
|
||||||
if (state.status !== "ready") expect.fail();
|
if (state.status !== "ready") expect.fail();
|
||||||
if (state.error) expect.fail();
|
if (state.error) expect.fail();
|
||||||
expect(state.goToBank.onClick).eq(undefined);
|
expect(state.goToBank.onClick).eq(undefined);
|
||||||
expect(state.goToWallet.onClick).eq(undefined);
|
expect(state.goToWallet.onClick).eq(undefined);
|
||||||
|
|
||||||
expect(state.amountHandler.value).deep.eq(Amounts.parseOrThrow("ARS:0"));
|
expect(state.amountHandler.value).deep.eq(
|
||||||
},
|
Amounts.parseOrThrow("ARS:0"),
|
||||||
], TestingContext)
|
);
|
||||||
|
},
|
||||||
|
],
|
||||||
|
TestingContext,
|
||||||
|
);
|
||||||
|
|
||||||
expect(hookBehavior).deep.equal({ result: "ok" })
|
expect(hookBehavior).deep.equal({ result: "ok" });
|
||||||
expect(handler.getCallingQueueState()).eq("empty");
|
expect(handler.getCallingQueueState()).eq("empty");
|
||||||
|
|
||||||
});
|
});
|
||||||
|
|
||||||
it("should be possible to start with an amount specified in request params", async () => {
|
it("should be possible to start with an amount specified in request params", async () => {
|
||||||
@ -98,22 +104,28 @@ describe("Destination selection states", () => {
|
|||||||
amount: "ARS:2",
|
amount: "ARS:2",
|
||||||
};
|
};
|
||||||
|
|
||||||
const hookBehavior = await tests.hookBehaveLikeThis(useComponentState, props, [
|
const hookBehavior = await tests.hookBehaveLikeThis(
|
||||||
// ({ status }) => {
|
useComponentState,
|
||||||
// expect(status).equal("loading");
|
props,
|
||||||
// },
|
[
|
||||||
(state) => {
|
// ({ status }) => {
|
||||||
if (state.status !== "ready") expect.fail();
|
// expect(status).equal("loading");
|
||||||
if (state.error) expect.fail();
|
// },
|
||||||
expect(state.goToBank.onClick).not.eq(undefined);
|
(state) => {
|
||||||
expect(state.goToWallet.onClick).not.eq(undefined);
|
if (state.status !== "ready") expect.fail();
|
||||||
|
if (state.error) expect.fail();
|
||||||
|
expect(state.goToBank.onClick).not.eq(undefined);
|
||||||
|
expect(state.goToWallet.onClick).not.eq(undefined);
|
||||||
|
|
||||||
expect(state.amountHandler.value).deep.eq(Amounts.parseOrThrow("ARS:2"));
|
expect(state.amountHandler.value).deep.eq(
|
||||||
},
|
Amounts.parseOrThrow("ARS:2"),
|
||||||
], TestingContext)
|
);
|
||||||
|
},
|
||||||
|
],
|
||||||
|
TestingContext,
|
||||||
|
);
|
||||||
|
|
||||||
expect(hookBehavior).deep.equal({ result: "ok" })
|
expect(hookBehavior).deep.equal({ result: "ok" });
|
||||||
expect(handler.getCallingQueueState()).eq("empty");
|
expect(handler.getCallingQueueState()).eq("empty");
|
||||||
|
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
|
@ -18,7 +18,7 @@ import {
|
|||||||
DenomOperationMap,
|
DenomOperationMap,
|
||||||
ExchangeFullDetails,
|
ExchangeFullDetails,
|
||||||
ExchangeListItem,
|
ExchangeListItem,
|
||||||
FeeDescriptionPair
|
FeeDescriptionPair,
|
||||||
} from "@gnu-taler/taler-util";
|
} from "@gnu-taler/taler-util";
|
||||||
import { Loading } from "../../components/Loading.js";
|
import { Loading } from "../../components/Loading.js";
|
||||||
import { HookError } from "../../hooks/useAsyncAsHook.js";
|
import { HookError } from "../../hooks/useAsyncAsHook.js";
|
||||||
@ -32,7 +32,7 @@ import {
|
|||||||
NoExchangesView,
|
NoExchangesView,
|
||||||
PrivacyContentView,
|
PrivacyContentView,
|
||||||
ReadyView,
|
ReadyView,
|
||||||
TosContentView
|
TosContentView,
|
||||||
} from "./views.js";
|
} from "./views.js";
|
||||||
|
|
||||||
export interface Props {
|
export interface Props {
|
||||||
|
@ -17,17 +17,20 @@
|
|||||||
import { DenomOperationMap, FeeDescription } from "@gnu-taler/taler-util";
|
import { DenomOperationMap, FeeDescription } from "@gnu-taler/taler-util";
|
||||||
import {
|
import {
|
||||||
createPairTimeline,
|
createPairTimeline,
|
||||||
WalletApiOperation
|
WalletApiOperation,
|
||||||
} from "@gnu-taler/taler-wallet-core";
|
} from "@gnu-taler/taler-wallet-core";
|
||||||
import { useState } from "preact/hooks";
|
import { useState } from "preact/hooks";
|
||||||
import { useBackendContext } from "../../context/backend.js";
|
import { useBackendContext } from "../../context/backend.js";
|
||||||
import { useAsyncAsHook } from "../../hooks/useAsyncAsHook.js";
|
import { useAsyncAsHook } from "../../hooks/useAsyncAsHook.js";
|
||||||
import { Props, State } from "./index.js";
|
import { Props, State } from "./index.js";
|
||||||
|
|
||||||
export function useComponentState(
|
export function useComponentState({
|
||||||
{ onCancel, onSelection, list: exchanges, currentExchange }: Props,
|
onCancel,
|
||||||
): State {
|
onSelection,
|
||||||
const api = useBackendContext()
|
list: exchanges,
|
||||||
|
currentExchange,
|
||||||
|
}: Props): State {
|
||||||
|
const api = useBackendContext();
|
||||||
const initialValue = exchanges.findIndex(
|
const initialValue = exchanges.findIndex(
|
||||||
(e) => e.exchangeBaseUrl === currentExchange,
|
(e) => e.exchangeBaseUrl === currentExchange,
|
||||||
);
|
);
|
||||||
@ -52,14 +55,14 @@ export function useComponentState(
|
|||||||
const selected = !selectedExchange
|
const selected = !selectedExchange
|
||||||
? undefined
|
? undefined
|
||||||
: await api.wallet.call(WalletApiOperation.GetExchangeDetailedInfo, {
|
: await api.wallet.call(WalletApiOperation.GetExchangeDetailedInfo, {
|
||||||
exchangeBaseUrl: selectedExchange.exchangeBaseUrl,
|
exchangeBaseUrl: selectedExchange.exchangeBaseUrl,
|
||||||
});
|
});
|
||||||
|
|
||||||
const original = !initialExchange
|
const original = !initialExchange
|
||||||
? undefined
|
? undefined
|
||||||
: await api.wallet.call(WalletApiOperation.GetExchangeDetailedInfo, {
|
: await api.wallet.call(WalletApiOperation.GetExchangeDetailedInfo, {
|
||||||
exchangeBaseUrl: initialExchange.exchangeBaseUrl,
|
exchangeBaseUrl: initialExchange.exchangeBaseUrl,
|
||||||
});
|
});
|
||||||
|
|
||||||
return {
|
return {
|
||||||
exchanges,
|
exchanges,
|
||||||
|
@ -20,7 +20,7 @@ import { HookError } from "../../hooks/useAsyncAsHook.js";
|
|||||||
import {
|
import {
|
||||||
ButtonHandler,
|
ButtonHandler,
|
||||||
SelectFieldHandler,
|
SelectFieldHandler,
|
||||||
TextFieldHandler
|
TextFieldHandler,
|
||||||
} from "../../mui/handlers.js";
|
} from "../../mui/handlers.js";
|
||||||
import { compose, StateViewMap } from "../../utils/index.js";
|
import { compose, StateViewMap } from "../../utils/index.js";
|
||||||
import { useComponentState } from "./state.js";
|
import { useComponentState } from "./state.js";
|
||||||
|
@ -17,7 +17,7 @@
|
|||||||
import {
|
import {
|
||||||
KnownBankAccountsInfo,
|
KnownBankAccountsInfo,
|
||||||
parsePaytoUri,
|
parsePaytoUri,
|
||||||
stringifyPaytoUri
|
stringifyPaytoUri,
|
||||||
} from "@gnu-taler/taler-util";
|
} from "@gnu-taler/taler-util";
|
||||||
import { WalletApiOperation } from "@gnu-taler/taler-wallet-core";
|
import { WalletApiOperation } from "@gnu-taler/taler-wallet-core";
|
||||||
import { useState } from "preact/hooks";
|
import { useState } from "preact/hooks";
|
||||||
@ -25,10 +25,12 @@ import { useBackendContext } from "../../context/backend.js";
|
|||||||
import { useAsyncAsHook } from "../../hooks/useAsyncAsHook.js";
|
import { useAsyncAsHook } from "../../hooks/useAsyncAsHook.js";
|
||||||
import { AccountByType, Props, State } from "./index.js";
|
import { AccountByType, Props, State } from "./index.js";
|
||||||
|
|
||||||
export function useComponentState(
|
export function useComponentState({
|
||||||
{ currency, onAccountAdded, onCancel }: Props,
|
currency,
|
||||||
): State {
|
onAccountAdded,
|
||||||
const api = useBackendContext()
|
onCancel,
|
||||||
|
}: Props): State {
|
||||||
|
const api = useBackendContext();
|
||||||
const hook = useAsyncAsHook(() =>
|
const hook = useAsyncAsHook(() =>
|
||||||
api.wallet.call(WalletApiOperation.ListKnownBankAccounts, { currency }),
|
api.wallet.call(WalletApiOperation.ListKnownBankAccounts, { currency }),
|
||||||
);
|
);
|
||||||
|
@ -21,7 +21,7 @@ import { compose, StateViewMap } from "../../utils/index.js";
|
|||||||
import { useComponentState } from "./state.js";
|
import { useComponentState } from "./state.js";
|
||||||
import { LoadingUriView, ReadyView } from "./views.js";
|
import { LoadingUriView, ReadyView } from "./views.js";
|
||||||
|
|
||||||
export type Props = object
|
export type Props = object;
|
||||||
|
|
||||||
export type State = State.Loading | State.LoadingUriError | State.Ready;
|
export type State = State.Loading | State.LoadingUriError | State.Ready;
|
||||||
|
|
||||||
|
@ -20,7 +20,7 @@ import { useAsyncAsHook } from "../../hooks/useAsyncAsHook.js";
|
|||||||
import { Props, State } from "./index.js";
|
import { Props, State } from "./index.js";
|
||||||
|
|
||||||
export function useComponentState(p: Props): State {
|
export function useComponentState(p: Props): State {
|
||||||
const api = useBackendContext()
|
const api = useBackendContext();
|
||||||
const hook = useAsyncAsHook(async () => {
|
const hook = useAsyncAsHook(async () => {
|
||||||
return await api.wallet.call(
|
return await api.wallet.call(
|
||||||
WalletApiOperation.GetUserAttentionRequests,
|
WalletApiOperation.GetUserAttentionRequests,
|
||||||
|
@ -156,8 +156,8 @@ export type WxApiType = {
|
|||||||
background: BackgroundApiClient;
|
background: BackgroundApiClient;
|
||||||
listener: {
|
listener: {
|
||||||
onUpdateNotification: typeof onUpdateNotification;
|
onUpdateNotification: typeof onUpdateNotification;
|
||||||
}
|
};
|
||||||
}
|
};
|
||||||
|
|
||||||
export const wxApi = {
|
export const wxApi = {
|
||||||
wallet: new WxWalletCoreApiClient(),
|
wallet: new WxWalletCoreApiClient(),
|
||||||
|
Loading…
Reference in New Issue
Block a user