2022-04-21 19:23:53 +02:00
|
|
|
/*
|
|
|
|
This file is part of GNU Taler
|
|
|
|
(C) 2021 Taler Systems S.A.
|
|
|
|
|
|
|
|
GNU Taler is free software; you can redistribute it and/or modify it under the
|
|
|
|
terms of the GNU General Public License as published by the Free Software
|
|
|
|
Foundation; either version 3, or (at your option) any later version.
|
|
|
|
|
|
|
|
GNU Taler is distributed in the hope that it will be useful, but WITHOUT ANY
|
|
|
|
WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR
|
|
|
|
A PARTICULAR PURPOSE. See the GNU General Public License for more details.
|
|
|
|
|
|
|
|
You should have received a copy of the GNU General Public License along with
|
|
|
|
GNU Taler; see the file COPYING. If not, see <http://www.gnu.org/licenses/>
|
|
|
|
*/
|
|
|
|
|
|
|
|
/**
|
|
|
|
*
|
|
|
|
* @author Sebastian Javier Marchano (sebasjm)
|
|
|
|
*/
|
|
|
|
|
2022-06-06 05:09:25 +02:00
|
|
|
import {
|
|
|
|
AmountJson,
|
|
|
|
Amounts,
|
|
|
|
BalancesResponse,
|
|
|
|
ConfirmPayResult,
|
|
|
|
ConfirmPayResultType,
|
|
|
|
NotificationType,
|
|
|
|
PreparePayResult,
|
|
|
|
PreparePayResultType,
|
|
|
|
} from "@gnu-taler/taler-util";
|
2022-04-21 19:23:53 +02:00
|
|
|
import { expect } from "chai";
|
|
|
|
import { mountHook } from "../test-utils.js";
|
|
|
|
import * as wxApi from "../wxApi.js";
|
|
|
|
import { useComponentState } from "./Pay.jsx";
|
|
|
|
|
|
|
|
const nullFunction: any = () => null;
|
|
|
|
type VoidFunction = () => void;
|
|
|
|
|
|
|
|
type Subs = {
|
2022-06-06 05:09:25 +02:00
|
|
|
[key in NotificationType]?: VoidFunction;
|
|
|
|
};
|
2022-04-21 19:23:53 +02:00
|
|
|
|
2022-05-03 00:21:34 +02:00
|
|
|
export class SubsHandler {
|
2022-04-21 19:23:53 +02:00
|
|
|
private subs: Subs = {};
|
|
|
|
|
|
|
|
constructor() {
|
|
|
|
this.saveSubscription = this.saveSubscription.bind(this);
|
|
|
|
}
|
|
|
|
|
2022-06-06 05:09:25 +02:00
|
|
|
saveSubscription(
|
|
|
|
messageTypes: NotificationType[],
|
|
|
|
callback: VoidFunction,
|
|
|
|
): VoidFunction {
|
|
|
|
messageTypes.forEach((m) => {
|
2022-04-21 19:23:53 +02:00
|
|
|
this.subs[m] = callback;
|
2022-06-06 05:09:25 +02:00
|
|
|
});
|
2022-04-21 19:23:53 +02:00
|
|
|
return nullFunction;
|
|
|
|
}
|
|
|
|
|
|
|
|
notifyEvent(event: NotificationType): void {
|
|
|
|
const cb = this.subs[event];
|
2022-06-06 05:09:25 +02:00
|
|
|
if (cb === undefined)
|
|
|
|
expect.fail(`Expected to have a subscription for ${event}`);
|
|
|
|
cb();
|
2022-04-21 19:23:53 +02:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
describe("Pay CTA states", () => {
|
|
|
|
it("should tell the user that the URI is missing", async () => {
|
2022-06-06 05:09:25 +02:00
|
|
|
const { getLastResultOrThrow, waitNextUpdate, assertNoPendingUpdate } =
|
|
|
|
mountHook(() =>
|
|
|
|
useComponentState(undefined, {
|
|
|
|
onUpdateNotification: nullFunction,
|
|
|
|
} as Partial<typeof wxApi> as any),
|
|
|
|
);
|
2022-04-21 19:23:53 +02:00
|
|
|
|
|
|
|
{
|
2022-06-06 05:09:25 +02:00
|
|
|
const { status, hook } = getLastResultOrThrow();
|
|
|
|
expect(status).equals("loading");
|
2022-04-21 19:23:53 +02:00
|
|
|
expect(hook).undefined;
|
|
|
|
}
|
|
|
|
|
2022-06-06 05:09:25 +02:00
|
|
|
await waitNextUpdate();
|
2022-04-21 19:23:53 +02:00
|
|
|
|
|
|
|
{
|
2022-06-06 05:09:25 +02:00
|
|
|
const { status, hook } = getLastResultOrThrow();
|
2022-04-21 19:23:53 +02:00
|
|
|
|
2022-06-06 05:09:25 +02:00
|
|
|
expect(status).equals("loading");
|
|
|
|
if (hook === undefined) expect.fail();
|
2022-04-21 19:23:53 +02:00
|
|
|
expect(hook.hasError).true;
|
|
|
|
expect(hook.operational).false;
|
|
|
|
}
|
|
|
|
|
2022-06-06 05:09:25 +02:00
|
|
|
await assertNoPendingUpdate();
|
2022-04-21 19:23:53 +02:00
|
|
|
});
|
|
|
|
|
|
|
|
it("should response with no balance", async () => {
|
2022-06-06 05:09:25 +02:00
|
|
|
const { getLastResultOrThrow, waitNextUpdate, assertNoPendingUpdate } =
|
|
|
|
mountHook(() =>
|
|
|
|
useComponentState("taller://pay", {
|
|
|
|
onUpdateNotification: nullFunction,
|
|
|
|
preparePay: async () =>
|
|
|
|
({
|
|
|
|
amountRaw: "USD:10",
|
|
|
|
status: PreparePayResultType.InsufficientBalance,
|
|
|
|
} as Partial<PreparePayResult>),
|
|
|
|
getBalance: async () =>
|
|
|
|
({
|
|
|
|
balances: [],
|
|
|
|
} as Partial<BalancesResponse>),
|
|
|
|
} as Partial<typeof wxApi> as any),
|
|
|
|
);
|
2022-04-21 19:23:53 +02:00
|
|
|
|
|
|
|
{
|
2022-06-06 05:09:25 +02:00
|
|
|
const { status, hook } = getLastResultOrThrow();
|
|
|
|
expect(status).equals("loading");
|
2022-04-21 19:23:53 +02:00
|
|
|
expect(hook).undefined;
|
|
|
|
}
|
|
|
|
|
|
|
|
await waitNextUpdate();
|
|
|
|
|
|
|
|
{
|
2022-06-06 05:09:25 +02:00
|
|
|
const r = getLastResultOrThrow();
|
|
|
|
if (r.status !== "ready") expect.fail();
|
2022-04-21 19:23:53 +02:00
|
|
|
expect(r.balance).undefined;
|
2022-06-06 05:09:25 +02:00
|
|
|
expect(r.amount).deep.equal(Amounts.parseOrThrow("USD:10"));
|
2022-04-21 19:23:53 +02:00
|
|
|
expect(r.payHandler.onClick).undefined;
|
|
|
|
}
|
|
|
|
|
2022-06-06 05:09:25 +02:00
|
|
|
await assertNoPendingUpdate();
|
2022-04-21 19:23:53 +02:00
|
|
|
});
|
|
|
|
|
|
|
|
it("should not be able to pay if there is no enough balance", async () => {
|
2022-06-06 05:09:25 +02:00
|
|
|
const { getLastResultOrThrow, waitNextUpdate, assertNoPendingUpdate } =
|
|
|
|
mountHook(() =>
|
|
|
|
useComponentState("taller://pay", {
|
|
|
|
onUpdateNotification: nullFunction,
|
|
|
|
preparePay: async () =>
|
|
|
|
({
|
|
|
|
amountRaw: "USD:10",
|
|
|
|
status: PreparePayResultType.InsufficientBalance,
|
|
|
|
} as Partial<PreparePayResult>),
|
|
|
|
getBalance: async () =>
|
|
|
|
({
|
|
|
|
balances: [
|
|
|
|
{
|
|
|
|
available: "USD:5",
|
|
|
|
},
|
|
|
|
],
|
|
|
|
} as Partial<BalancesResponse>),
|
|
|
|
} as Partial<typeof wxApi> as any),
|
|
|
|
);
|
2022-04-21 19:23:53 +02:00
|
|
|
|
|
|
|
{
|
2022-06-06 05:09:25 +02:00
|
|
|
const { status, hook } = getLastResultOrThrow();
|
|
|
|
expect(status).equals("loading");
|
2022-04-21 19:23:53 +02:00
|
|
|
expect(hook).undefined;
|
|
|
|
}
|
|
|
|
|
|
|
|
await waitNextUpdate();
|
|
|
|
|
|
|
|
{
|
2022-06-06 05:09:25 +02:00
|
|
|
const r = getLastResultOrThrow();
|
|
|
|
if (r.status !== "ready") expect.fail();
|
|
|
|
expect(r.balance).deep.equal(Amounts.parseOrThrow("USD:5"));
|
|
|
|
expect(r.amount).deep.equal(Amounts.parseOrThrow("USD:10"));
|
2022-04-21 19:23:53 +02:00
|
|
|
expect(r.payHandler.onClick).undefined;
|
|
|
|
}
|
|
|
|
|
2022-06-06 05:09:25 +02:00
|
|
|
await assertNoPendingUpdate();
|
2022-04-21 19:23:53 +02:00
|
|
|
});
|
|
|
|
|
|
|
|
it("should be able to pay (without fee)", async () => {
|
2022-06-06 05:09:25 +02:00
|
|
|
const { getLastResultOrThrow, waitNextUpdate, assertNoPendingUpdate } =
|
|
|
|
mountHook(() =>
|
|
|
|
useComponentState("taller://pay", {
|
|
|
|
onUpdateNotification: nullFunction,
|
|
|
|
preparePay: async () =>
|
|
|
|
({
|
|
|
|
amountRaw: "USD:10",
|
|
|
|
amountEffective: "USD:10",
|
|
|
|
status: PreparePayResultType.PaymentPossible,
|
|
|
|
} as Partial<PreparePayResult>),
|
|
|
|
getBalance: async () =>
|
|
|
|
({
|
|
|
|
balances: [
|
|
|
|
{
|
|
|
|
available: "USD:15",
|
|
|
|
},
|
|
|
|
],
|
|
|
|
} as Partial<BalancesResponse>),
|
|
|
|
} as Partial<typeof wxApi> as any),
|
|
|
|
);
|
2022-04-21 19:23:53 +02:00
|
|
|
|
|
|
|
{
|
2022-06-06 05:09:25 +02:00
|
|
|
const { status, hook } = getLastResultOrThrow();
|
|
|
|
expect(status).equals("loading");
|
2022-04-21 19:23:53 +02:00
|
|
|
expect(hook).undefined;
|
|
|
|
}
|
|
|
|
|
|
|
|
await waitNextUpdate();
|
|
|
|
|
|
|
|
{
|
2022-06-06 05:09:25 +02:00
|
|
|
const r = getLastResultOrThrow();
|
|
|
|
if (r.status !== "ready") expect.fail();
|
|
|
|
expect(r.balance).deep.equal(Amounts.parseOrThrow("USD:15"));
|
|
|
|
expect(r.amount).deep.equal(Amounts.parseOrThrow("USD:10"));
|
|
|
|
expect(r.totalFees).deep.equal(Amounts.parseOrThrow("USD:0"));
|
2022-04-21 19:23:53 +02:00
|
|
|
expect(r.payHandler.onClick).not.undefined;
|
|
|
|
}
|
|
|
|
|
2022-06-06 05:09:25 +02:00
|
|
|
await assertNoPendingUpdate();
|
2022-04-21 19:23:53 +02:00
|
|
|
});
|
|
|
|
|
|
|
|
it("should be able to pay (with fee)", async () => {
|
2022-06-06 05:09:25 +02:00
|
|
|
const { getLastResultOrThrow, waitNextUpdate, assertNoPendingUpdate } =
|
|
|
|
mountHook(() =>
|
|
|
|
useComponentState("taller://pay", {
|
|
|
|
onUpdateNotification: nullFunction,
|
|
|
|
preparePay: async () =>
|
|
|
|
({
|
|
|
|
amountRaw: "USD:9",
|
|
|
|
amountEffective: "USD:10",
|
|
|
|
status: PreparePayResultType.PaymentPossible,
|
|
|
|
} as Partial<PreparePayResult>),
|
|
|
|
getBalance: async () =>
|
|
|
|
({
|
|
|
|
balances: [
|
|
|
|
{
|
|
|
|
available: "USD:15",
|
|
|
|
},
|
|
|
|
],
|
|
|
|
} as Partial<BalancesResponse>),
|
|
|
|
} as Partial<typeof wxApi> as any),
|
|
|
|
);
|
2022-04-21 19:23:53 +02:00
|
|
|
|
|
|
|
{
|
2022-06-06 05:09:25 +02:00
|
|
|
const { status, hook } = getLastResultOrThrow();
|
|
|
|
expect(status).equals("loading");
|
2022-04-21 19:23:53 +02:00
|
|
|
expect(hook).undefined;
|
|
|
|
}
|
|
|
|
|
|
|
|
await waitNextUpdate();
|
|
|
|
|
|
|
|
{
|
2022-06-06 05:09:25 +02:00
|
|
|
const r = getLastResultOrThrow();
|
|
|
|
if (r.status !== "ready") expect.fail();
|
|
|
|
expect(r.balance).deep.equal(Amounts.parseOrThrow("USD:15"));
|
|
|
|
expect(r.amount).deep.equal(Amounts.parseOrThrow("USD:9"));
|
|
|
|
expect(r.totalFees).deep.equal(Amounts.parseOrThrow("USD:1"));
|
2022-04-21 19:23:53 +02:00
|
|
|
expect(r.payHandler.onClick).not.undefined;
|
|
|
|
}
|
|
|
|
|
2022-06-06 05:09:25 +02:00
|
|
|
await assertNoPendingUpdate();
|
2022-04-21 19:23:53 +02:00
|
|
|
});
|
|
|
|
|
|
|
|
it("should get confirmation done after pay successfully", async () => {
|
2022-06-06 05:09:25 +02:00
|
|
|
const { getLastResultOrThrow, waitNextUpdate, assertNoPendingUpdate } =
|
|
|
|
mountHook(() =>
|
|
|
|
useComponentState("taller://pay", {
|
|
|
|
onUpdateNotification: nullFunction,
|
|
|
|
preparePay: async () =>
|
|
|
|
({
|
|
|
|
amountRaw: "USD:9",
|
|
|
|
amountEffective: "USD:10",
|
|
|
|
status: PreparePayResultType.PaymentPossible,
|
|
|
|
} as Partial<PreparePayResult>),
|
|
|
|
getBalance: async () =>
|
|
|
|
({
|
|
|
|
balances: [
|
|
|
|
{
|
|
|
|
available: "USD:15",
|
|
|
|
},
|
|
|
|
],
|
|
|
|
} as Partial<BalancesResponse>),
|
|
|
|
confirmPay: async () =>
|
|
|
|
({
|
|
|
|
type: ConfirmPayResultType.Done,
|
|
|
|
contractTerms: {},
|
|
|
|
} as Partial<ConfirmPayResult>),
|
|
|
|
} as Partial<typeof wxApi> as any),
|
|
|
|
);
|
2022-04-21 19:23:53 +02:00
|
|
|
|
|
|
|
{
|
2022-06-06 05:09:25 +02:00
|
|
|
const { status, hook } = getLastResultOrThrow();
|
|
|
|
expect(status).equals("loading");
|
2022-04-21 19:23:53 +02:00
|
|
|
expect(hook).undefined;
|
|
|
|
}
|
|
|
|
|
|
|
|
await waitNextUpdate();
|
|
|
|
|
|
|
|
{
|
2022-06-06 05:09:25 +02:00
|
|
|
const r = getLastResultOrThrow();
|
|
|
|
if (r.status !== "ready") expect.fail();
|
|
|
|
expect(r.balance).deep.equal(Amounts.parseOrThrow("USD:15"));
|
|
|
|
expect(r.amount).deep.equal(Amounts.parseOrThrow("USD:9"));
|
|
|
|
expect(r.totalFees).deep.equal(Amounts.parseOrThrow("USD:1"));
|
2022-04-21 19:23:53 +02:00
|
|
|
if (r.payHandler.onClick === undefined) expect.fail();
|
2022-06-06 05:09:25 +02:00
|
|
|
r.payHandler.onClick();
|
2022-04-21 19:23:53 +02:00
|
|
|
}
|
|
|
|
|
|
|
|
await waitNextUpdate();
|
|
|
|
|
|
|
|
{
|
2022-06-06 05:09:25 +02:00
|
|
|
const r = getLastResultOrThrow();
|
|
|
|
if (r.status !== "confirmed") expect.fail();
|
|
|
|
expect(r.balance).deep.equal(Amounts.parseOrThrow("USD:15"));
|
|
|
|
expect(r.amount).deep.equal(Amounts.parseOrThrow("USD:9"));
|
|
|
|
expect(r.totalFees).deep.equal(Amounts.parseOrThrow("USD:1"));
|
2022-04-21 19:23:53 +02:00
|
|
|
if (r.payResult.type !== ConfirmPayResultType.Done) expect.fail();
|
|
|
|
expect(r.payResult.contractTerms).not.undefined;
|
|
|
|
expect(r.payHandler.onClick).undefined;
|
|
|
|
}
|
|
|
|
|
2022-06-06 05:09:25 +02:00
|
|
|
await assertNoPendingUpdate();
|
2022-04-21 19:23:53 +02:00
|
|
|
});
|
|
|
|
|
|
|
|
it("should not stay in ready state after pay with error", async () => {
|
2022-06-06 05:09:25 +02:00
|
|
|
const { getLastResultOrThrow, waitNextUpdate, assertNoPendingUpdate } =
|
|
|
|
mountHook(() =>
|
|
|
|
useComponentState("taller://pay", {
|
|
|
|
onUpdateNotification: nullFunction,
|
|
|
|
preparePay: async () =>
|
|
|
|
({
|
|
|
|
amountRaw: "USD:9",
|
|
|
|
amountEffective: "USD:10",
|
|
|
|
status: PreparePayResultType.PaymentPossible,
|
|
|
|
} as Partial<PreparePayResult>),
|
|
|
|
getBalance: async () =>
|
|
|
|
({
|
|
|
|
balances: [
|
|
|
|
{
|
|
|
|
available: "USD:15",
|
|
|
|
},
|
|
|
|
],
|
|
|
|
} as Partial<BalancesResponse>),
|
|
|
|
confirmPay: async () =>
|
|
|
|
({
|
|
|
|
type: ConfirmPayResultType.Pending,
|
|
|
|
lastError: { code: 1 },
|
|
|
|
} as Partial<ConfirmPayResult>),
|
|
|
|
} as Partial<typeof wxApi> as any),
|
|
|
|
);
|
2022-04-21 19:23:53 +02:00
|
|
|
|
|
|
|
{
|
2022-06-06 05:09:25 +02:00
|
|
|
const { status, hook } = getLastResultOrThrow();
|
|
|
|
expect(status).equals("loading");
|
2022-04-21 19:23:53 +02:00
|
|
|
expect(hook).undefined;
|
|
|
|
}
|
|
|
|
|
|
|
|
await waitNextUpdate();
|
|
|
|
|
|
|
|
{
|
2022-06-06 05:09:25 +02:00
|
|
|
const r = getLastResultOrThrow();
|
|
|
|
if (r.status !== "ready") expect.fail();
|
|
|
|
expect(r.balance).deep.equal(Amounts.parseOrThrow("USD:15"));
|
|
|
|
expect(r.amount).deep.equal(Amounts.parseOrThrow("USD:9"));
|
|
|
|
expect(r.totalFees).deep.equal(Amounts.parseOrThrow("USD:1"));
|
2022-04-21 19:23:53 +02:00
|
|
|
if (r.payHandler.onClick === undefined) expect.fail();
|
2022-06-06 05:09:25 +02:00
|
|
|
r.payHandler.onClick();
|
2022-04-21 19:23:53 +02:00
|
|
|
}
|
|
|
|
|
|
|
|
await waitNextUpdate();
|
|
|
|
|
|
|
|
{
|
2022-06-06 05:09:25 +02:00
|
|
|
const r = getLastResultOrThrow();
|
|
|
|
if (r.status !== "ready") expect.fail();
|
|
|
|
expect(r.balance).deep.equal(Amounts.parseOrThrow("USD:15"));
|
|
|
|
expect(r.amount).deep.equal(Amounts.parseOrThrow("USD:9"));
|
|
|
|
expect(r.totalFees).deep.equal(Amounts.parseOrThrow("USD:1"));
|
2022-04-21 19:23:53 +02:00
|
|
|
expect(r.payHandler.onClick).undefined;
|
|
|
|
if (r.payHandler.error === undefined) expect.fail();
|
|
|
|
//FIXME: error message here is bad
|
2022-06-06 05:09:25 +02:00
|
|
|
expect(r.payHandler.error.errorDetail.hint).eq(
|
|
|
|
"could not confirm payment",
|
|
|
|
);
|
2022-04-21 19:23:53 +02:00
|
|
|
expect(r.payHandler.error.errorDetail.payResult).deep.equal({
|
|
|
|
type: ConfirmPayResultType.Pending,
|
2022-06-06 05:09:25 +02:00
|
|
|
lastError: { code: 1 },
|
|
|
|
});
|
2022-04-21 19:23:53 +02:00
|
|
|
}
|
|
|
|
|
2022-06-06 05:09:25 +02:00
|
|
|
await assertNoPendingUpdate();
|
2022-04-21 19:23:53 +02:00
|
|
|
});
|
|
|
|
|
|
|
|
it("should update balance if a coins is withdraw", async () => {
|
|
|
|
const subscriptions = new SubsHandler();
|
|
|
|
let availableBalance = Amounts.parseOrThrow("USD:10");
|
|
|
|
|
|
|
|
function notifyCoinWithdrawn(newAmount: AmountJson): void {
|
2022-06-06 05:09:25 +02:00
|
|
|
availableBalance = Amounts.add(availableBalance, newAmount).amount;
|
|
|
|
subscriptions.notifyEvent(NotificationType.CoinWithdrawn);
|
2022-04-21 19:23:53 +02:00
|
|
|
}
|
|
|
|
|
2022-06-06 05:09:25 +02:00
|
|
|
const { getLastResultOrThrow, waitNextUpdate, assertNoPendingUpdate } =
|
|
|
|
mountHook(() =>
|
|
|
|
useComponentState("taller://pay", {
|
|
|
|
onUpdateNotification: subscriptions.saveSubscription,
|
|
|
|
preparePay: async () =>
|
|
|
|
({
|
|
|
|
amountRaw: "USD:9",
|
|
|
|
amountEffective: "USD:10",
|
|
|
|
status: PreparePayResultType.PaymentPossible,
|
|
|
|
} as Partial<PreparePayResult>),
|
|
|
|
getBalance: async () =>
|
|
|
|
({
|
|
|
|
balances: [
|
|
|
|
{
|
|
|
|
available: Amounts.stringify(availableBalance),
|
|
|
|
},
|
|
|
|
],
|
|
|
|
} as Partial<BalancesResponse>),
|
|
|
|
} as Partial<typeof wxApi> as any),
|
|
|
|
);
|
2022-04-21 19:23:53 +02:00
|
|
|
|
|
|
|
{
|
2022-06-06 05:09:25 +02:00
|
|
|
const { status, hook } = getLastResultOrThrow();
|
|
|
|
expect(status).equals("loading");
|
2022-04-21 19:23:53 +02:00
|
|
|
expect(hook).undefined;
|
|
|
|
}
|
|
|
|
|
|
|
|
await waitNextUpdate();
|
|
|
|
|
|
|
|
{
|
2022-06-06 05:09:25 +02:00
|
|
|
const r = getLastResultOrThrow();
|
|
|
|
if (r.status !== "ready") expect.fail();
|
|
|
|
expect(r.balance).deep.equal(Amounts.parseOrThrow("USD:10"));
|
|
|
|
expect(r.amount).deep.equal(Amounts.parseOrThrow("USD:9"));
|
|
|
|
expect(r.totalFees).deep.equal(Amounts.parseOrThrow("USD:1"));
|
2022-04-21 19:23:53 +02:00
|
|
|
expect(r.payHandler.onClick).not.undefined;
|
|
|
|
|
|
|
|
notifyCoinWithdrawn(Amounts.parseOrThrow("USD:5"));
|
|
|
|
}
|
|
|
|
|
|
|
|
await waitNextUpdate();
|
|
|
|
|
|
|
|
{
|
2022-06-06 05:09:25 +02:00
|
|
|
const r = getLastResultOrThrow();
|
|
|
|
if (r.status !== "ready") expect.fail();
|
|
|
|
expect(r.balance).deep.equal(Amounts.parseOrThrow("USD:15"));
|
|
|
|
expect(r.amount).deep.equal(Amounts.parseOrThrow("USD:9"));
|
|
|
|
expect(r.totalFees).deep.equal(Amounts.parseOrThrow("USD:1"));
|
2022-04-21 19:23:53 +02:00
|
|
|
expect(r.payHandler.onClick).not.undefined;
|
|
|
|
}
|
|
|
|
|
2022-06-06 05:09:25 +02:00
|
|
|
await assertNoPendingUpdate();
|
2022-04-21 19:23:53 +02:00
|
|
|
});
|
2022-06-06 05:09:25 +02:00
|
|
|
});
|