gnunet-svn
[Top][All Lists]
Advanced

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

[taler-merchant-backoffice] branch master updated: reserve hook test


From: gnunet
Subject: [taler-merchant-backoffice] branch master updated: reserve hook test
Date: Fri, 10 Dec 2021 18:26:36 +0100

This is an automated email from the git hooks/post-receive script.

sebasjm pushed a commit to branch master
in repository merchant-backoffice.

The following commit(s) were added to refs/heads/master by this push:
     new f4b71ec  reserve hook test
f4b71ec is described below

commit f4b71ececef38778ae813e7557f6ed6b78bfd591
Author: Sebastian <sebasjm@gmail.com>
AuthorDate: Fri Dec 10 14:26:24 2021 -0300

    reserve hook test
---
 .../src/components/exception/QR.tsx                |  30 +++--
 packages/merchant-backoffice/src/hooks/listener.ts |  19 ++-
 .../merchant-backoffice/src/hooks/notification.ts  |  43 -------
 packages/merchant-backoffice/src/hooks/order.ts    |  39 ++----
 packages/merchant-backoffice/src/hooks/product.ts  | 110 ++--------------
 .../src/hooks/{tips.ts => reserves.ts}             |  24 +---
 packages/merchant-backoffice/src/hooks/transfer.ts |  45 +++----
 .../src/paths/instance/reserves/create/index.tsx   |  78 ++++++------
 .../paths/instance/reserves/details/DetailPage.tsx |   2 +-
 .../src/paths/instance/reserves/details/index.tsx  |  45 ++++---
 .../src/paths/instance/reserves/list/index.tsx     | 138 ++++++++++++---------
 packages/merchant-backoffice/tests/axiosMock.ts    |  45 +++++--
 .../tests/hooks/listener.test.ts                   |  62 +++++++++
 .../tests/hooks/swr/order-create.test.tsx          |  23 ++--
 .../tests/hooks/swr/order-pagination.test.tsx      |  32 +++--
 .../tests/hooks/swr/product-create.test.tsx        |  24 ++--
 .../tests/hooks/swr/product-delete.test.tsx        |  46 +++----
 .../hooks/swr/product-details-update.test.tsx      |  18 +--
 .../tests/hooks/swr/product-update.test.tsx        |  27 ++--
 ...der-create.test.tsx => reserve-create.test.tsx} | 116 +++++++++--------
 ...ation.test.tsx => transfer-pagination.test.tsx} |  76 +++++-------
 21 files changed, 507 insertions(+), 535 deletions(-)

diff --git a/packages/merchant-backoffice/src/components/exception/QR.tsx 
b/packages/merchant-backoffice/src/components/exception/QR.tsx
index 4295c63..bcb9964 100644
--- a/packages/merchant-backoffice/src/components/exception/QR.tsx
+++ b/packages/merchant-backoffice/src/components/exception/QR.tsx
@@ -18,18 +18,32 @@ import { h, VNode } from "preact";
 import { useEffect, useRef } from "preact/hooks";
 import qrcode from "qrcode-generator";
 
-export function QR({ text }: { text: string; }):VNode {
+export function QR({ text }: { text: string }): VNode {
   const divRef = useRef<HTMLDivElement>(null);
   useEffect(() => {
-    const qr = qrcode(0, 'L');
+    const qr = qrcode(0, "L");
     qr.addData(text);
     qr.make();
-    divRef.current.innerHTML = qr.createSvgTag({
-      scalable: true,
-    });
+    if (divRef.current) {
+      divRef.current.innerHTML = qr.createSvgTag({
+        scalable: true,
+      });
+    }
   });
 
-  return <div style={{ width: '100%', display: 'flex', flexDirection: 
'column', alignItems: 'center' }}>
-    <div style={{ width: '50%', minWidth: 200, maxWidth: 300 }} ref={divRef} />
-  </div>;
+  return (
+    <div
+      style={{
+        width: "100%",
+        display: "flex",
+        flexDirection: "column",
+        alignItems: "center",
+      }}
+    >
+      <div
+        style={{ width: "50%", minWidth: 200, maxWidth: 300 }}
+        ref={divRef}
+      />
+    </div>
+  );
 }
diff --git a/packages/merchant-backoffice/src/hooks/listener.ts 
b/packages/merchant-backoffice/src/hooks/listener.ts
index 231ed6c..e7e3327 100644
--- a/packages/merchant-backoffice/src/hooks/listener.ts
+++ b/packages/merchant-backoffice/src/hooks/listener.ts
@@ -22,9 +22,22 @@
 import { useState } from "preact/hooks";
 
 /**
- * returns subscriber and activator
- * subscriber will receive a method (listener) that will be call when the 
activator runs.
- * the result of calling the listener will be sent to @action
+ * This component is used when a component wants one child to have a trigger 
for
+ * an action (a button) and other child have the action implemented (like
+ * gathering information with a form). The difference with other approaches is
+ * that in this case the parent component is not holding the state.
+ * 
+ * It will return a subscriber and activator. 
+ * 
+ * The activator may be undefined, if it is undefined it is indicating that the
+ * subscriber is not ready to be called.
+ *
+ * The subscriber will receive a function (the listener) that will be call 
when the
+ * activator runs. The listener must return the collected information.
+ * 
+ * As a result, when the activator is triggered by a child component, the
+ * @action function is called receives the information from the listener 
defined by other
+ * child component 
  *
  * @param action from <T> to <R>
  * @returns activator and subscriber, undefined activator means that there is 
not subscriber
diff --git a/packages/merchant-backoffice/src/hooks/notification.ts 
b/packages/merchant-backoffice/src/hooks/notification.ts
deleted file mode 100644
index d1dfbff..0000000
--- a/packages/merchant-backoffice/src/hooks/notification.ts
+++ /dev/null
@@ -1,43 +0,0 @@
-/*
- This file is part of GNU Taler
- (C) 2021 Taler Systems S.A.
-
- GNU Taler is free software; you can redistribute it and/or modify it under the
- terms of the GNU General Public License as published by the Free Software
- Foundation; either version 3, or (at your option) any later version.
-
- GNU Taler is distributed in the hope that it will be useful, but WITHOUT ANY
- WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR
- A PARTICULAR PURPOSE.  See the GNU General Public License for more details.
-
- You should have received a copy of the GNU General Public License along with
- GNU Taler; see the file COPYING.  If not, see <http://www.gnu.org/licenses/>
- */
-
-/**
-*
-* @author Sebastian Javier Marchano (sebasjm)
-*/
-
-import { useCallback, useState } from "preact/hooks";
-import { Notification } from '../utils/types';
-
-interface Result {
-  notification?: Notification;
-  pushNotification: (n: Notification) => void;
-  removeNotification: () => void;
-}
-
-export function useNotification(): Result {
-  const [notification, setNotifications] = 
useState<Notification|undefined>(undefined)
-
-  const pushNotification = useCallback((n: Notification): void => {
-    setNotifications(n)
-  },[])
-
-  const removeNotification = useCallback(() => {
-    setNotifications(undefined)
-  },[])
-
-  return { notification, pushNotification, removeNotification }
-}
diff --git a/packages/merchant-backoffice/src/hooks/order.ts 
b/packages/merchant-backoffice/src/hooks/order.ts
index c0cf5b9..883bcef 100644
--- a/packages/merchant-backoffice/src/hooks/order.ts
+++ b/packages/merchant-backoffice/src/hooks/order.ts
@@ -73,19 +73,18 @@ export function orderFetcher<T>(
 
 export function useOrderAPI(): OrderAPI {
   const mutateAll = useMatchMutate();
-  // const { mutate } = useSWRConfig();
   const { url: baseUrl, token: adminToken } = useBackendContext();
   const { token: instanceToken, id, admin } = useInstanceContext();
 
   const { url, token } = !admin
     ? {
-        url: baseUrl,
-        token: adminToken,
-      }
+      url: baseUrl,
+      token: adminToken,
+    }
     : {
-        url: `${baseUrl}/instances/${id}`,
-        token: instanceToken,
-      };
+      url: `${baseUrl}/instances/${id}`,
+      token: instanceToken,
+    };
 
   const createOrder = async (
     data: MerchantBackend.Orders.PostOrderRequest
@@ -170,14 +169,8 @@ export function useOrderDetails(
   const { token: instanceToken, id, admin } = useInstanceContext();
 
   const { url, token } = !admin
-    ? {
-        url: baseUrl,
-        token: baseToken,
-      }
-    : {
-        url: `${baseUrl}/instances/${id}`,
-        token: instanceToken,
-      };
+    ? { url: baseUrl, token: baseToken, }
+    : { url: `${baseUrl}/instances/${id}`, token: instanceToken, };
 
   const { data, error, isValidating } = useSWR<
     HttpResponseOk<MerchantBackend.Orders.MerchantOrderStatusResponse>,
@@ -211,14 +204,8 @@ export function useInstanceOrders(
   const { token: instanceToken, id, admin } = useInstanceContext();
 
   const { url, token } = !admin
-    ? {
-        url: baseUrl,
-        token: baseToken,
-      }
-    : {
-        url: `${baseUrl}/instances/${id}`,
-        token: instanceToken,
-      };
+    ? { url: baseUrl, token: baseToken, }
+    : { url: `${baseUrl}/instances/${id}`, token: instanceToken, };
 
   const [pageBefore, setPageBefore] = useState(1);
   const [pageAfter, setPageAfter] = useState(1);
@@ -317,9 +304,9 @@ export function useInstanceOrders(
     !beforeData || !afterData
       ? []
       : (beforeData || lastBefore).data.orders
-          .slice()
-          .reverse()
-          .concat((afterData || lastAfter).data.orders);
+        .slice()
+        .reverse()
+        .concat((afterData || lastAfter).data.orders);
   if (loadingAfter || loadingBefore) return { loading: true, data: { orders } 
};
   if (beforeData && afterData) {
     return { ok: true, data: { orders }, ...pagination };
diff --git a/packages/merchant-backoffice/src/hooks/product.ts 
b/packages/merchant-backoffice/src/hooks/product.ts
index b2cc21c..1e6ebf2 100644
--- a/packages/merchant-backoffice/src/hooks/product.ts
+++ b/packages/merchant-backoffice/src/hooks/product.ts
@@ -13,11 +13,8 @@
  You should have received a copy of the GNU General Public License along with
  GNU Taler; see the file COPYING.  If not, see <http://www.gnu.org/licenses/>
  */
-import { useEffect } from "preact/hooks";
 import useSWR, { useSWRConfig } from "swr";
-import useSWRInfinite, { SWRInfiniteConfiguration } from "swr/infinite";
 import { useBackendContext } from "../context/backend";
-// import { useFetchContext } from '../context/fetch';
 import { useInstanceContext } from "../context/instance";
 import { MerchantBackend, WithId } from "../declaration";
 import {
@@ -27,7 +24,7 @@ import {
   HttpResponseOk,
   multiFetcher,
   request,
-  useMatchMutate,
+  useMatchMutate
 } from "./backend";
 
 export interface ProductAPI {
@@ -48,19 +45,12 @@ export interface ProductAPI {
 export function useProductAPI(): ProductAPI {
   const mutateAll = useMatchMutate();
   const { mutate } = useSWRConfig();
-  // const { mutate } = SWRInfiniteConfiguration();
   const { url: baseUrl, token: adminToken } = useBackendContext();
   const { token: instanceToken, id, admin } = useInstanceContext();
 
   const { url, token } = !admin
-    ? {
-        url: baseUrl,
-        token: adminToken,
-      }
-    : {
-        url: `${baseUrl}/instances/${id}`,
-        token: instanceToken,
-      };
+    ? { url: baseUrl, token: adminToken, }
+    : { url: `${baseUrl}/instances/${id}`, token: instanceToken, };
 
   const createProduct = async (
     data: MerchantBackend.Products.ProductAddDetail
@@ -84,51 +74,7 @@ export function useProductAPI(): ProductAPI {
       data,
     });
 
-    // await mutate([`/private/products`, token, url])
-    // await mutate([`/private/products/${productId}`, token, url], undefined, 
true);
     return await mutateAll(/.*"\/private\/products.*/);
-    return Promise.resolve();
-    /**
-     * There is some inconsistency in how the cache is evicted.
-     * I'm keeping this for later inspection
-     */
-
-    // -- Clear all cache
-    // -- This seems to work always but is bad
-
-    // const keys = [...cache.keys()]
-    // console.log(keys)
-    // cache.clear()
-    // await Promise.all(keys.map(k => trigger(k)))
-
-    // -- From the keys to the cache trigger
-    // -- An intermediate step
-
-    // const keys = [
-    //   [`/private/products`, token, url],
-    //   [`/private/products/${productId}`, token, url],
-    // ]
-    // cache.clear()
-    // const f: string[][] = keys.map(k => cache.serializeKey(k))
-    // console.log(f)
-    // const m = flat(f)
-    // console.log(m)
-    // await Promise.all(m.map(k => trigger(k, true)))
-
-    // await Promise.all(keys.map(k => mutate(k)))
-
-    // -- This is how is supposed to be use
-
-    // await mutate([`/private/products`, token, url])
-    // await mutate([`/private/products/${productId}`, token, url])
-
-    // await mutateAll(/@"\/private\/products"@/);
-    // await mutateAll(/@"\/private\/products\/.*"@/);
-    // return true
-    // return r
-
-    // -- FIXME: why this un-break the tests?
-    // return Promise.resolve()
   };
 
   const deleteProduct = async (productId: string): Promise<void> => {
@@ -160,17 +106,10 @@ export function useInstanceProducts(): HttpResponse<
 > {
   const { url: baseUrl, token: baseToken } = useBackendContext();
   const { token: instanceToken, id, admin } = useInstanceContext();
-  // const { useSWR, useSWRInfinite } = useFetchContext();
 
   const { url, token } = !admin
-    ? {
-        url: baseUrl,
-        token: baseToken,
-      }
-    : {
-        url: `${baseUrl}/instances/${id}`,
-        token: instanceToken,
-      };
+    ? { url: baseUrl, token: baseToken, }
+    : { url: `${baseUrl}/instances/${id}`, token: instanceToken, };
 
   const { data: list, error: listError } = useSWR<
     HttpResponseOk<MerchantBackend.Products.InventorySummaryResponse>,
@@ -183,21 +122,6 @@ export function useInstanceProducts(): HttpResponse<
     refreshWhenOffline: false,
   });
 
-  // const dataLength = list?.data.products.length || 0
-  // const prods: Array<MerchantBackend.Products.InventoryEntry>[] = []
-  // prods[0] = list?.data.products || []
-
-  // const { data: products, error: productError, setSize } = 
useSWRInfinite<HttpResponseOk<MerchantBackend.Products.ProductDetail>, 
HttpError>((pageIndex: number) => {
-  //   console.log('fetcher', prods[0], pageIndex)
-  //   if (!list?.data || !prods[0].length || listError) return null
-
-  //   console.log(`/private/products/${prods[0][pageIndex].product_id}`)
-  //   return [`/private/products/${prods[0][pageIndex].product_id}`, token, 
url]
-  // }, fetcher, {
-  //   initialSize: dataLength,
-  //   revalidateAll: true,
-  // })
-  // [`/private/products`]
   const paths = (list?.data.products || []).map(
     (p) => `/private/products/${p.product_id}`
   );
@@ -212,19 +136,10 @@ export function useInstanceProducts(): HttpResponse<
     refreshWhenOffline: false,
   });
 
-  // console.log('data length', dataLength, list?.data)
-  // useEffect(() => {
-  //   if (dataLength > 0) {
-  //     console.log('set size', dataLength)
-  //     setSize(dataLength)
-  //   }
-  // }, [dataLength, setSize])
 
   if (listError) return listError;
   if (productError) return productError;
-  // if (dataLength === 0) {
-  //   return { ok: true, data: [] }
-  // }
+
   if (products) {
     const dataWithId = products.map((d) => {
       //take the id from the queried url
@@ -233,7 +148,6 @@ export function useInstanceProducts(): HttpResponse<
         id: d.info?.url.replace(/.*\/private\/products\//, "") || "",
       };
     });
-    // console.log('data with id', dataWithId)
     return { ok: true, data: dataWithId };
   }
   return { loading: true };
@@ -247,13 +161,13 @@ export function useProductDetails(
 
   const { url, token } = !admin
     ? {
-        url: baseUrl,
-        token: baseToken,
-      }
+      url: baseUrl,
+      token: baseToken,
+    }
     : {
-        url: `${baseUrl}/instances/${id}`,
-        token: instanceToken,
-      };
+      url: `${baseUrl}/instances/${id}`,
+      token: instanceToken,
+    };
 
   const { data, error, isValidating } = useSWR<
     HttpResponseOk<MerchantBackend.Products.ProductDetail>,
diff --git a/packages/merchant-backoffice/src/hooks/tips.ts 
b/packages/merchant-backoffice/src/hooks/reserves.ts
similarity index 92%
rename from packages/merchant-backoffice/src/hooks/tips.ts
rename to packages/merchant-backoffice/src/hooks/reserves.ts
index a632e34..259bd1c 100644
--- a/packages/merchant-backoffice/src/hooks/tips.ts
+++ b/packages/merchant-backoffice/src/hooks/reserves.ts
@@ -32,14 +32,8 @@ export function useReservesAPI(): ReserveMutateAPI {
   const { token: instanceToken, id, admin } = useInstanceContext();
 
   const { url, token } = !admin
-    ? {
-        url: baseUrl,
-        token: adminToken,
-      }
-    : {
-        url: `${baseUrl}/instances/${id}`,
-        token: instanceToken,
-      };
+    ? { url: baseUrl, token: adminToken, }
+    : { url: `${baseUrl}/instances/${id}`, token: instanceToken, };
 
   const createReserve = async (
     data: MerchantBackend.Tips.ReserveCreateRequest
@@ -55,7 +49,7 @@ export function useReservesAPI(): ReserveMutateAPI {
       }
     );
 
-    await mutateAll(/@"\/private\/reserves"@/);
+    await mutateAll(/.*private\/reserves.*/);
 
     return res;
   };
@@ -122,19 +116,13 @@ export interface ReserveMutateAPI {
   deleteReserve: (id: string) => Promise<HttpResponse<void>>;
 }
 
-export function useInstanceTips(): 
HttpResponse<MerchantBackend.Tips.TippingReserveStatus> {
+export function useInstanceReserves(): 
HttpResponse<MerchantBackend.Tips.TippingReserveStatus> {
   const { url: baseUrl, token: baseToken } = useBackendContext();
   const { token: instanceToken, id, admin } = useInstanceContext();
 
   const { url, token } = !admin
-    ? {
-        url: baseUrl,
-        token: baseToken,
-      }
-    : {
-        url: `${baseUrl}/instances/${id}`,
-        token: instanceToken,
-      };
+    ? { url: baseUrl, token: baseToken, }
+    : { url: `${baseUrl}/instances/${id}`, token: instanceToken, };
 
   const { data, error, isValidating } = useSWR<
     HttpResponseOk<MerchantBackend.Tips.TippingReserveStatus>,
diff --git a/packages/merchant-backoffice/src/hooks/transfer.ts 
b/packages/merchant-backoffice/src/hooks/transfer.ts
index c455b0c..86ed420 100644
--- a/packages/merchant-backoffice/src/hooks/transfer.ts
+++ b/packages/merchant-backoffice/src/hooks/transfer.ts
@@ -41,11 +41,6 @@ async function transferFetcher<T>(
   if (payto_uri !== undefined) params.payto_uri = payto_uri;
   if (verified !== undefined) params.verified = verified;
   if (delta !== undefined) {
-    // if (delta > 0) {
-    //   params.after = searchDate?.getTime()
-    // } else {
-    //   params.before = searchDate?.getTime()
-    // }
     params.limit = delta;
   }
   if (position !== undefined) params.offset = position;
@@ -60,13 +55,13 @@ export function useTransferAPI(): TransferAPI {
 
   const { url, token } = !admin
     ? {
-        url: baseUrl,
-        token: adminToken,
-      }
+      url: baseUrl,
+      token: adminToken,
+    }
     : {
-        url: `${baseUrl}/instances/${id}`,
-        token: instanceToken,
-      };
+      url: `${baseUrl}/instances/${id}`,
+      token: instanceToken,
+    };
 
   const informTransfer = async (
     data: MerchantBackend.Transfers.TransferInformation
@@ -110,14 +105,8 @@ export function useInstanceTransfers(
   const { token: instanceToken, id, admin } = useInstanceContext();
 
   const { url, token } = !admin
-    ? {
-        url: baseUrl,
-        token: baseToken,
-      }
-    : {
-        url: `${baseUrl}/instances/${id}`,
-        token: instanceToken,
-      };
+    ? { url: baseUrl, token: baseToken }
+    : { url: `${baseUrl}/instances/${id}`, token: instanceToken };
 
   const [pageBefore, setPageBefore] = useState(1);
   const [pageAfter, setPageAfter] = useState(1);
@@ -192,9 +181,9 @@ export function useInstanceTransfers(
         setPageAfter(pageAfter + 1);
       } else {
         const from =
-          "" +
-          afterData.data.transfers[afterData.data.transfers.length - 1]
-            .transfer_serial_id;
+          `${afterData.data
+            .transfers[afterData.data.transfers.length - 1]
+            .transfer_serial_id}`;
         if (from && updatePosition) updatePosition(from);
       }
     },
@@ -204,9 +193,9 @@ export function useInstanceTransfers(
         setPageBefore(pageBefore + 1);
       } else if (beforeData) {
         const from =
-          "" +
-          beforeData.data.transfers[beforeData.data.transfers.length - 1]
-            .transfer_serial_id;
+          `${beforeData.data
+            .transfers[beforeData.data.transfers.length - 1]
+            .transfer_serial_id}`;
         if (from && updatePosition) updatePosition(from);
       }
     },
@@ -216,9 +205,9 @@ export function useInstanceTransfers(
     !beforeData || !afterData
       ? []
       : (beforeData || lastBefore).data.transfers
-          .slice()
-          .reverse()
-          .concat((afterData || lastAfter).data.transfers);
+        .slice()
+        .reverse()
+        .concat((afterData || lastAfter).data.transfers);
   if (loadingAfter || loadingBefore)
     return { loading: true, data: { transfers } };
   if (beforeData && afterData) {
diff --git 
a/packages/merchant-backoffice/src/paths/instance/reserves/create/index.tsx 
b/packages/merchant-backoffice/src/paths/instance/reserves/create/index.tsx
index eb16f85..5c2fdaf 100644
--- a/packages/merchant-backoffice/src/paths/instance/reserves/create/index.tsx
+++ b/packages/merchant-backoffice/src/paths/instance/reserves/create/index.tsx
@@ -15,49 +15,57 @@
  */
 
 /**
-*
-* @author Sebastian Javier Marchano (sebasjm)
-*/
-
-import { Fragment, h, VNode } from 'preact';
-import { useState } from 'preact/hooks';
-import { NotificationCard } from '../../../../components/menu';
-import { MerchantBackend } from '../../../../declaration';
-import { useReservesAPI } from '../../../../hooks/tips';
-import { useTranslator } from '../../../../i18n';
-import { Notification } from '../../../../utils/types';
-import { CreatedSuccessfully } from './CreatedSuccessfully';
-import { CreatePage } from './CreatePage';
+ *
+ * @author Sebastian Javier Marchano (sebasjm)
+ */
+
+import { Fragment, h, VNode } from "preact";
+import { useState } from "preact/hooks";
+import { NotificationCard } from "../../../../components/menu";
+import { MerchantBackend } from "../../../../declaration";
+import { useReservesAPI } from "../../../../hooks/reserves";
+import { useTranslator } from "../../../../i18n";
+import { Notification } from "../../../../utils/types";
+import { CreatedSuccessfully } from "./CreatedSuccessfully";
+import { CreatePage } from "./CreatePage";
 interface Props {
   onBack: () => void;
   onConfirm: () => void;
 }
 export default function CreateReserve({ onBack, onConfirm }: Props): VNode {
-  const { createReserve } = useReservesAPI()
-  const [notif, setNotif] = useState<Notification | undefined>(undefined)
-  const i18n = useTranslator()
+  const { createReserve } = useReservesAPI();
+  const [notif, setNotif] = useState<Notification | undefined>(undefined);
+  const i18n = useTranslator();
 
-  const [createdOk, setCreatedOk] = useState<{
-    request: MerchantBackend.Tips.ReserveCreateRequest,
-    response: MerchantBackend.Tips.ReserveCreateConfirmation
-  } | undefined>(undefined);
+  const [createdOk, setCreatedOk] = useState<
+    | {
+        request: MerchantBackend.Tips.ReserveCreateRequest;
+        response: MerchantBackend.Tips.ReserveCreateConfirmation;
+      }
+    | undefined
+  >(undefined);
 
   if (createdOk) {
-    return <CreatedSuccessfully entity={createdOk} onConfirm={onConfirm} />
+    return <CreatedSuccessfully entity={createdOk} onConfirm={onConfirm} />;
   }
 
-  return <Fragment>
-    <NotificationCard notification={notif} />
-    <CreatePage
-      onBack={onBack}
-      onCreate={(request: MerchantBackend.Tips.ReserveCreateRequest) => {
-        return createReserve(request).then((r) => setCreatedOk({ request, 
response: r.data })).catch((error) => {
-          setNotif({
-            message: i18n`could not create reserve`,
-            type: "ERROR",
-            description: error.message
-          })
-        })
-      }} />
-  </Fragment>
+  return (
+    <Fragment>
+      <NotificationCard notification={notif} />
+      <CreatePage
+        onBack={onBack}
+        onCreate={(request: MerchantBackend.Tips.ReserveCreateRequest) => {
+          return createReserve(request)
+            .then((r) => setCreatedOk({ request, response: r.data }))
+            .catch((error) => {
+              setNotif({
+                message: i18n`could not create reserve`,
+                type: "ERROR",
+                description: error.message,
+              });
+            });
+        }}
+      />
+    </Fragment>
+  );
 }
diff --git 
a/packages/merchant-backoffice/src/paths/instance/reserves/details/DetailPage.tsx
 
b/packages/merchant-backoffice/src/paths/instance/reserves/details/DetailPage.tsx
index 46e0bbf..64d7a3a 100644
--- 
a/packages/merchant-backoffice/src/paths/instance/reserves/details/DetailPage.tsx
+++ 
b/packages/merchant-backoffice/src/paths/instance/reserves/details/DetailPage.tsx
@@ -29,7 +29,7 @@ import { InputCurrency } from 
"../../../../components/form/InputCurrency";
 import { InputDate } from "../../../../components/form/InputDate";
 import { TextField } from "../../../../components/form/TextField";
 import { MerchantBackend } from "../../../../declaration";
-import { useTipDetails } from "../../../../hooks/tips";
+import { useTipDetails } from "../../../../hooks/reserves";
 import { Translate, useTranslator } from "../../../../i18n";
 
 type Entity = MerchantBackend.Tips.ReserveDetail;
diff --git 
a/packages/merchant-backoffice/src/paths/instance/reserves/details/index.tsx 
b/packages/merchant-backoffice/src/paths/instance/reserves/details/index.tsx
index aaf275b..c2483f0 100644
--- a/packages/merchant-backoffice/src/paths/instance/reserves/details/index.tsx
+++ b/packages/merchant-backoffice/src/paths/instance/reserves/details/index.tsx
@@ -15,15 +15,15 @@
  */
 
 /**
-*
-* @author Sebastian Javier Marchano (sebasjm)
-*/
+ *
+ * @author Sebastian Javier Marchano (sebasjm)
+ */
 
-import { Fragment, h, VNode } from 'preact';
-import { Loading } from '../../../../components/exception/loading';
-import { HttpError } from '../../../../hooks/backend';
-import { useReserveDetails } from '../../../../hooks/tips';
-import { DetailPage } from './DetailPage';
+import { Fragment, h, VNode } from "preact";
+import { Loading } from "../../../../components/exception/loading";
+import { HttpError } from "../../../../hooks/backend";
+import { useReserveDetails } from "../../../../hooks/reserves";
+import { DetailPage } from "./DetailPage";
 
 interface Props {
   rid: string;
@@ -34,14 +34,23 @@ interface Props {
   onDelete: () => void;
   onBack: () => void;
 }
-export default function DetailReserve({ rid, onUnauthorized, onLoadError, 
onNotFound, onBack, onDelete }: Props): VNode {
-  const result = useReserveDetails(rid)
-
-  if (result.clientError && result.isUnauthorized) return onUnauthorized()
-  if (result.clientError && result.isNotfound) return onNotFound()
-  if (result.loading) return <Loading />
-  if (!result.ok) return onLoadError(result)
-  return <Fragment>
-    <DetailPage selected={result.data} onBack={onBack} id={rid} />
-  </Fragment>
+export default function DetailReserve({
+  rid,
+  onUnauthorized,
+  onLoadError,
+  onNotFound,
+  onBack,
+  onDelete,
+}: Props): VNode {
+  const result = useReserveDetails(rid);
+
+  if (result.clientError && result.isUnauthorized) return onUnauthorized();
+  if (result.clientError && result.isNotfound) return onNotFound();
+  if (result.loading) return <Loading />;
+  if (!result.ok) return onLoadError(result);
+  return (
+    <Fragment>
+      <DetailPage selected={result.data} onBack={onBack} id={rid} />
+    </Fragment>
+  );
 }
diff --git 
a/packages/merchant-backoffice/src/paths/instance/reserves/list/index.tsx 
b/packages/merchant-backoffice/src/paths/instance/reserves/list/index.tsx
index 7a1cfdb..f071b56 100644
--- a/packages/merchant-backoffice/src/paths/instance/reserves/list/index.tsx
+++ b/packages/merchant-backoffice/src/paths/instance/reserves/list/index.tsx
@@ -15,21 +15,24 @@
  */
 
 /**
-*
-* @author Sebastian Javier Marchano (sebasjm)
-*/
+ *
+ * @author Sebastian Javier Marchano (sebasjm)
+ */
 
-import { h, VNode } from 'preact';
-import { useState } from 'preact/hooks';
-import { Loading } from '../../../../components/exception/loading';
-import { NotificationCard } from '../../../../components/menu';
-import { MerchantBackend } from '../../../../declaration';
-import { HttpError } from '../../../../hooks/backend';
-import { useInstanceTips, useReservesAPI } from "../../../../hooks/tips";
-import { useTranslator } from '../../../../i18n';
-import { Notification } from '../../../../utils/types';
-import { CardTable } from './Table';
-import { AuthorizeTipModal } from './AutorizeTipModal';
+import { h, VNode } from "preact";
+import { useState } from "preact/hooks";
+import { Loading } from "../../../../components/exception/loading";
+import { NotificationCard } from "../../../../components/menu";
+import { MerchantBackend } from "../../../../declaration";
+import { HttpError } from "../../../../hooks/backend";
+import {
+  useInstanceReserves,
+  useReservesAPI,
+} from "../../../../hooks/reserves";
+import { useTranslator } from "../../../../i18n";
+import { Notification } from "../../../../utils/types";
+import { CardTable } from "./Table";
+import { AuthorizeTipModal } from "./AutorizeTipModal";
 
 interface Props {
   onUnauthorized: () => VNode;
@@ -44,54 +47,71 @@ interface TipConfirmation {
   request: MerchantBackend.Tips.TipCreateRequest;
 }
 
-export default function ListTips({ onUnauthorized, onLoadError, onNotFound, 
onSelect, onCreate }: Props): VNode {
-  const result = useInstanceTips()
-  const { deleteReserve, authorizeTipReserve } = useReservesAPI()
-  const [notif, setNotif] = useState<Notification | undefined>(undefined)
-  const i18n = useTranslator()
-  const [reserveForTip, setReserveForTip] = useState<string | 
undefined>(undefined);
-  const [tipAuthorized, setTipAuthorized] = useState<TipConfirmation | 
undefined>(undefined);
+export default function ListTips({
+  onUnauthorized,
+  onLoadError,
+  onNotFound,
+  onSelect,
+  onCreate,
+}: Props): VNode {
+  const result = useInstanceReserves();
+  const { deleteReserve, authorizeTipReserve } = useReservesAPI();
+  const [notif, setNotif] = useState<Notification | undefined>(undefined);
+  const i18n = useTranslator();
+  const [reserveForTip, setReserveForTip] = useState<string | undefined>(
+    undefined
+  );
+  const [tipAuthorized, setTipAuthorized] = useState<
+    TipConfirmation | undefined
+  >(undefined);
 
-  if (result.clientError && result.isUnauthorized) return onUnauthorized()
-  if (result.clientError && result.isNotfound) return onNotFound()
-  if (result.loading) return <Loading />
-  if (!result.ok) return onLoadError(result)
+  if (result.clientError && result.isUnauthorized) return onUnauthorized();
+  if (result.clientError && result.isNotfound) return onNotFound();
+  if (result.loading) return <Loading />;
+  if (!result.ok) return onLoadError(result);
 
+  return (
+    <section class="section is-main-section">
+      <NotificationCard notification={notif} />
 
-  return <section class="section is-main-section">
-    <NotificationCard notification={notif} />
+      {reserveForTip && (
+        <AuthorizeTipModal
+          onCancel={() => {
+            setReserveForTip(undefined);
+            setTipAuthorized(undefined);
+          }}
+          tipAuthorized={tipAuthorized}
+          onConfirm={async (request) => {
+            try {
+              const response = await authorizeTipReserve(
+                reserveForTip,
+                request
+              );
+              setTipAuthorized({
+                request,
+                response: response.data,
+              });
+            } catch (error) {
+              setNotif({
+                message: i18n`could not create the tip`,
+                type: "ERROR",
+                description: error instanceof Error ? error.message : 
undefined,
+              });
+              setReserveForTip(undefined);
+            }
+          }}
+        />
+      )}
 
-    {reserveForTip && (
-      <AuthorizeTipModal
-        onCancel={() => {
-          setReserveForTip(undefined)
-          setTipAuthorized(undefined)
-        }}
-        tipAuthorized={tipAuthorized}
-        onConfirm={async (request) => {
-          try {
-            const response = await authorizeTipReserve(reserveForTip, request)
-            setTipAuthorized({
-              request, response: response.data
-            })
-          } catch (error) {
-            setNotif({
-              message: i18n`could not create the tip`,
-              type: "ERROR",
-              description: error instanceof Error ? error.message : undefined
-            })
-            setReserveForTip(undefined)
-          }
-        }
-        }
+      <CardTable
+        instances={result.data.reserves
+          .filter((r) => r.active)
+          .map((o) => ({ ...o, id: o.reserve_pub }))}
+        onCreate={onCreate}
+        onDelete={(reserve) => deleteReserve(reserve.reserve_pub)}
+        onSelect={(reserve) => onSelect(reserve.id)}
+        onNewTip={(reserve) => setReserveForTip(reserve.id)}
       />
-    )}
-
-    <CardTable instances={result.data.reserves.filter(r => r.active).map(o => 
({ ...o, id: o.reserve_pub }))}
-      onCreate={onCreate}
-      onDelete={(reserve) => deleteReserve(reserve.reserve_pub)}
-      onSelect={(reserve) => onSelect(reserve.id)}
-      onNewTip={(reserve) => setReserveForTip(reserve.id)}
-    />
-  </section>
+    </section>
+  );
 }
diff --git a/packages/merchant-backoffice/tests/axiosMock.ts 
b/packages/merchant-backoffice/tests/axiosMock.ts
index c38bc44..4f50bec 100644
--- a/packages/merchant-backoffice/tests/axiosMock.ts
+++ b/packages/merchant-backoffice/tests/axiosMock.ts
@@ -52,7 +52,7 @@ export class AxiosMockEnvironment {
     this.axiosMock = (axios.default as 
jest.MockedFunction<axios.AxiosStatic>).mockImplementation(defaultCallback as 
any)
   }
 
-  addRequestExpectation<RequestType, ResponseType>(expectedQuery?: 
Query<RequestType, ResponseType> | undefined, params?: { request?: RequestType, 
qparam?: any, response?: ResponseType }): void {
+  addRequestExpectation<RequestType, ResponseType>(expectedQuery: 
Query<RequestType, ResponseType>, params: { request?: RequestType, qparam?: 
any, response?: ResponseType }): void {
     this.expectations.push(expectedQuery ? { query: expectedQuery, params } : 
undefined)
     this.axiosMock = this.axiosMock.mockImplementationOnce(function 
(actualQuery?: axios.AxiosRequestConfig): axios.AxiosPromise {
 
@@ -113,28 +113,27 @@ export class AxiosMockEnvironment {
 
 }
 
-export function testAllExpectedRequestAndNoMore(env: AxiosMockEnvironment): 
void {
+export function assertJustExpectedRequestWereMade(env: AxiosMockEnvironment): 
void {
   let size = env.expectations.length
   while (size-- > 0) {
-    testOneRequestToBackend(env)
+    assertNextRequest(env)
   }
-  testNoOtherRequestWasMade(env)
+  assertNoMoreRequestWereMade(env)
 }
 
-export function testNoOtherRequestWasMade(env: AxiosMockEnvironment): void {
+export function assertNoMoreRequestWereMade(env: AxiosMockEnvironment): void {
   const [actualQuery, expectedQuery] = env.getLastTestValues()
 
   expect(actualQuery).toBeUndefined();
   expect(expectedQuery).toBeUndefined();
 }
 
-export function testOneRequestToBackend(env: AxiosMockEnvironment): void {
+export function assertNextRequest(env: AxiosMockEnvironment): void {
   const [actualQuery, expectedQuery] = env.getLastTestValues()
 
   if (!actualQuery) {
+    //expected one query but the tested component didn't execute one
     expect(actualQuery).toBe(expectedQuery);
-
-    // throw Error('actual query was undefined');
     return
   }
 
@@ -152,7 +151,6 @@ export function testOneRequestToBackend(env: 
AxiosMockEnvironment): void {
   if ('post' in expectedQuery.query) {
     expect(actualQuery.method).toBe('post');
     expect(actualQuery.url).toBe(expectedQuery.query.post);
-    if (actualQuery.method !== 'post') throw Error('tu vieja')
   }
   if ('delete' in expectedQuery.query) {
     expect(actualQuery.method).toBe('delete');
@@ -179,6 +177,13 @@ export const API_LIST_PRODUCTS: Query<
   get: "http://backend/instances/default/private/products";,
 };
 
+export const API_LIST_RESERVES: Query<
+  unknown,
+  MerchantBackend.Tips.TippingReserveStatus
+> = {
+  get: "http://backend/instances/default/private/reserves";,
+};
+
 export const API_LIST_ORDERS: Query<
   unknown,
   MerchantBackend.Orders.OrderHistory
@@ -186,12 +191,25 @@ export const API_LIST_ORDERS: Query<
   get: "http://backend/instances/default/private/orders";,
 };
 
+export const API_LIST_TRANSFERS: Query<
+  unknown,
+  MerchantBackend.Transfers.TransferList
+> = {
+  get: "http://backend/instances/default/private/transfers";,
+};
+
 export const API_CREATE_PRODUCT: Query<
   MerchantBackend.Products.ProductAddDetail,
   unknown
 > = {
   post: "http://backend/instances/default/private/products";,
 };
+export const API_CREATE_RESERVE: Query<
+  MerchantBackend.Tips.ReserveCreateRequest,
+  MerchantBackend.Tips.ReserveCreateConfirmation
+> = {
+  post: "http://backend/instances/default/private/reserves";,
+};
 
 export const API_CREATE_ORDER: Query<
   MerchantBackend.Orders.PostOrderRequest,
@@ -202,7 +220,7 @@ export const API_CREATE_ORDER: Query<
 
 export const API_GET_PRODUCT_BY_ID = (
   id: string
-): Query<unknown, MerchantBackend.Products.InventorySummaryResponse> => ({
+): Query<unknown, MerchantBackend.Products.ProductDetail> => ({
   get: `http://backend/instances/default/private/products/${id}`,
 });
 
@@ -214,3 +232,10 @@ export const API_UPDATE_PRODUCT_BY_ID = (
 > => ({
   patch: `http://backend/instances/default/private/products/${id}`,
 });
+
+export const API_GET_RESERVE_BY_ID = (
+  pub: string
+): Query<unknown, MerchantBackend.Tips.ReserveDetail> => ({
+  get: `http://backend/instances/default/private/reserves/${pub}`,
+});
+
diff --git a/packages/merchant-backoffice/tests/hooks/listener.test.ts 
b/packages/merchant-backoffice/tests/hooks/listener.test.ts
new file mode 100644
index 0000000..ae34c13
--- /dev/null
+++ b/packages/merchant-backoffice/tests/hooks/listener.test.ts
@@ -0,0 +1,62 @@
+/*
+ This file is part of GNU Taler
+ (C) 2021 Taler Systems S.A.
+
+ GNU Taler is free software; you can redistribute it and/or modify it under the
+ terms of the GNU General Public License as published by the Free Software
+ Foundation; either version 3, or (at your option) any later version.
+
+ GNU Taler is distributed in the hope that it will be useful, but WITHOUT ANY
+ WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR
+ A PARTICULAR PURPOSE.  See the GNU General Public License for more details.
+
+ You should have received a copy of the GNU General Public License along with
+ GNU Taler; see the file COPYING.  If not, see <http://www.gnu.org/licenses/>
+ */
+
+/**
+*
+* @author Sebastian Javier Marchano (sebasjm)
+*/
+
+import { renderHook, act } from '@testing-library/preact-hooks';
+import { useListener } from '../../src/hooks/listener';
+
+// jest.useFakeTimers()
+
+test('listener', async () => {
+
+
+  function createSomeString() {
+    return "hello"
+  }
+  async function addWorldToTheEnd(resultFromComponentB: string) {
+    return `${resultFromComponentB} world`
+  }
+  const expectedResult = "hello world"
+
+  const { result } = renderHook(() => useListener(addWorldToTheEnd))
+
+  if (!result.current) {
+    expect(result.current).toBeDefined()
+    return;
+  }
+
+  {
+    const [activator, subscriber] = result.current
+    expect(activator).toBeUndefined()
+
+    act(() => {
+      subscriber(createSomeString)
+    })
+
+  }
+
+  const [activator] = result.current
+  expect(activator).toBeDefined()
+  if (!activator) return;
+
+  const response = await activator()
+  expect(response).toBe(expectedResult)
+
+});
diff --git a/packages/merchant-backoffice/tests/hooks/swr/order-create.test.tsx 
b/packages/merchant-backoffice/tests/hooks/swr/order-create.test.tsx
index 0defaec..4563acd 100644
--- a/packages/merchant-backoffice/tests/hooks/swr/order-create.test.tsx
+++ b/packages/merchant-backoffice/tests/hooks/swr/order-create.test.tsx
@@ -23,13 +23,14 @@ import { renderHook } from "@testing-library/preact-hooks";
 import { act } from "preact/test-utils";
 import * as backend from "../../../src/context/backend";
 import * as instance from "../../../src/context/instance";
+import { MerchantBackend } from "../../../src/declaration";
 import { useInstanceOrders, useOrderAPI } from "../../../src/hooks/order";
 import {
   API_CREATE_ORDER,
   API_LIST_ORDERS,
   AxiosMockEnvironment,
-  testNoOtherRequestWasMade,
-  testOneRequestToBackend,
+  assertNoMoreRequestWereMade,
+  assertNextRequest,
 } from "../../axiosMock";
 
 jest.mock("axios");
@@ -53,14 +54,14 @@ describe("order api", () => {
     env.addRequestExpectation(API_LIST_ORDERS, {
       qparam: { delta: 0, paid: "yes" },
       response: {
-        orders: [{ order_id: "1" }],
+        orders: [{ order_id: "1" } as 
MerchantBackend.Orders.OrderHistoryEntry],
       },
     });
 
     env.addRequestExpectation(API_LIST_ORDERS, {
       qparam: { delta: -20, paid: "yes" },
       response: {
-        orders: [{ order_id: "2" }],
+        orders: [{ order_id: "2" } as 
MerchantBackend.Orders.OrderHistoryEntry],
       },
     });
 
@@ -82,9 +83,9 @@ describe("order api", () => {
 
     expect(result.current.query.loading).toBeTruthy();
     await waitForNextUpdate();
-    testOneRequestToBackend(env);
-    testOneRequestToBackend(env);
-    testNoOtherRequestWasMade(env);
+    assertNextRequest(env);
+    assertNextRequest(env);
+    assertNoMoreRequestWereMade(env);
 
     expect(result.current.query.loading).toBeFalsy();
     expect(result.current?.query.ok).toBeTruthy();
@@ -121,11 +122,11 @@ describe("order api", () => {
       } as any);
     });
 
-    testOneRequestToBackend(env); //post
+    assertNextRequest(env); //post
     await waitForNextUpdate();
-    testOneRequestToBackend(env); //get
-    testOneRequestToBackend(env); //get
-    testNoOtherRequestWasMade(env);
+    assertNextRequest(env); //get
+    assertNextRequest(env); //get
+    assertNoMoreRequestWereMade(env);
 
     expect(result.current.query.loading).toBeFalsy();
     expect(result.current?.query.ok).toBeTruthy();
diff --git 
a/packages/merchant-backoffice/tests/hooks/swr/order-pagination.test.tsx 
b/packages/merchant-backoffice/tests/hooks/swr/order-pagination.test.tsx
index d62ead7..b29f057 100644
--- a/packages/merchant-backoffice/tests/hooks/swr/order-pagination.test.tsx
+++ b/packages/merchant-backoffice/tests/hooks/swr/order-pagination.test.tsx
@@ -22,18 +22,14 @@
 import { act, renderHook } from "@testing-library/preact-hooks";
 import * as backend from "../../../src/context/backend";
 import * as instance from "../../../src/context/instance";
-import { MerchantBackend } from "../../../src/declaration";
-import { setAxiosRequestAsTestingEnvironment } from 
"../../../src/hooks/backend";
 import { useInstanceOrders } from "../../../src/hooks/order";
 import {
   API_LIST_ORDERS,
   AxiosMockEnvironment,
-  testNoOtherRequestWasMade,
-  testOneRequestToBackend,
+  assertNoMoreRequestWereMade,
+  assertNextRequest,
 } from "../../axiosMock";
 
-setAxiosRequestAsTestingEnvironment();
-
 jest.mock("axios");
 
 describe("order pagination", () => {
@@ -73,13 +69,13 @@ describe("order pagination", () => {
     const date = new Date(12);
     const { result, waitForNextUpdate } = renderHook(() =>
       useInstanceOrders({ wired: "yes", date }, newDate)
-    ); // get products -> loading
+    );
 
-    testOneRequestToBackend(env);
-    testOneRequestToBackend(env);
-    testNoOtherRequestWasMade(env);
+    assertNextRequest(env);
+    assertNextRequest(env);
+    assertNoMoreRequestWereMade(env);
 
-    await waitForNextUpdate(); // get info of every product, -> loading
+    await waitForNextUpdate();
 
     expect(result.current?.ok).toBeTruthy();
     if (!result.current?.ok) return;
@@ -99,10 +95,10 @@ describe("order pagination", () => {
       if (!result.current?.ok) throw Error("not ok");
       result.current.loadMore();
     });
-    await waitForNextUpdate(); // loading product -> products
-    // await waitForNextUpdate(); // loading product -> products
-    testOneRequestToBackend(env);
-    testNoOtherRequestWasMade(env);
+    await waitForNextUpdate();
+
+    assertNextRequest(env);
+    assertNoMoreRequestWereMade(env);
 
     env.addRequestExpectation(API_LIST_ORDERS, {
       qparam: { delta: 40, wired: "yes", date_ms: 12 },
@@ -114,9 +110,9 @@ describe("order pagination", () => {
       if (!result.current?.ok) throw Error("not ok");
       result.current.loadMorePrev();
     });
-    await waitForNextUpdate(); // loading product -> products
-    testOneRequestToBackend(env);
-    testNoOtherRequestWasMade(env);
+    await waitForNextUpdate();
+    assertNextRequest(env);
+    assertNoMoreRequestWereMade(env);
 
     expect(result.current.data).toEqual({
       orders: [
diff --git 
a/packages/merchant-backoffice/tests/hooks/swr/product-create.test.tsx 
b/packages/merchant-backoffice/tests/hooks/swr/product-create.test.tsx
index 611a470..8b49b8d 100644
--- a/packages/merchant-backoffice/tests/hooks/swr/product-create.test.tsx
+++ b/packages/merchant-backoffice/tests/hooks/swr/product-create.test.tsx
@@ -23,13 +23,14 @@ import { renderHook } from "@testing-library/preact-hooks";
 import { act } from "preact/test-utils";
 import * as backend from "../../../src/context/backend";
 import * as instance from "../../../src/context/instance";
+import { MerchantBackend } from "../../../src/declaration";
 import { useInstanceProducts, useProductAPI } from 
"../../../src/hooks/product";
 import {
   API_CREATE_PRODUCT,
   API_LIST_PRODUCTS,
   API_GET_PRODUCT_BY_ID,
   AxiosMockEnvironment,
-  testAllExpectedRequestAndNoMore,
+  assertJustExpectedRequestWereMade,
 } from "../../axiosMock";
 
 jest.mock("axios");
@@ -58,7 +59,7 @@ describe("product create api", () => {
     });
 
     env.addRequestExpectation(API_GET_PRODUCT_BY_ID("1234"), {
-      response: { price: "ARS:33" },
+      response: { price: "ARS:33" } as MerchantBackend.Products.ProductDetail,
     });
 
     const { result, waitForNextUpdate } = renderHook(() => {
@@ -66,8 +67,7 @@ describe("product create api", () => {
       const query = useInstanceProducts();
 
       return { query, api };
-    }); // get products -> loading
-
+    });
     if (!result.current) {
       expect(result.current).toBeDefined();
       return;
@@ -78,7 +78,7 @@ describe("product create api", () => {
     expect(result.current.query.loading).toBeTruthy();
 
     await waitForNextUpdate(); // second query to get product details
-    testAllExpectedRequestAndNoMore(env);
+    assertJustExpectedRequestWereMade(env);
 
     expect(result.current.query.loading).toBeFalsy();
     expect(result.current?.query.ok).toBeTruthy();
@@ -89,7 +89,9 @@ describe("product create api", () => {
     ]);
 
     env.addRequestExpectation(API_CREATE_PRODUCT, {
-      request: { price: "ARS:3333" },
+      request: {
+        price: "ARS:3333",
+      } as MerchantBackend.Products.ProductAddDetail,
     });
 
     act(async () => {
@@ -98,7 +100,7 @@ describe("product create api", () => {
       } as any);
     });
 
-    testAllExpectedRequestAndNoMore(env);
+    assertJustExpectedRequestWereMade(env);
 
     env.addRequestExpectation(API_LIST_PRODUCTS, {
       response: {
@@ -107,21 +109,21 @@ describe("product create api", () => {
     });
 
     env.addRequestExpectation(API_GET_PRODUCT_BY_ID("1234"), {
-      response: { price: "ARS:33" },
+      response: { price: "ARS:33" } as MerchantBackend.Products.ProductDetail,
     });
     env.addRequestExpectation(API_GET_PRODUCT_BY_ID("1234"), {
-      response: { price: "ARS:33" },
+      response: { price: "ARS:33" } as MerchantBackend.Products.ProductDetail,
     });
 
     env.addRequestExpectation(API_GET_PRODUCT_BY_ID("2222"), {
-      response: { price: "ARS:3333" },
+      response: { price: "ARS:3333" } as 
MerchantBackend.Products.ProductDetail,
     });
     expect(result.current.query.loading).toBeFalsy();
 
     await waitForNextUpdate(); // loading product -> products
     await waitForNextUpdate(); // loading product -> products
 
-    testAllExpectedRequestAndNoMore(env);
+    assertJustExpectedRequestWereMade(env);
 
     expect(result.current.query.loading).toBeFalsy();
     expect(result.current.query.ok).toBeTruthy();
diff --git 
a/packages/merchant-backoffice/tests/hooks/swr/product-delete.test.tsx 
b/packages/merchant-backoffice/tests/hooks/swr/product-delete.test.tsx
index 4c67ec1..7586af4 100644
--- a/packages/merchant-backoffice/tests/hooks/swr/product-delete.test.tsx
+++ b/packages/merchant-backoffice/tests/hooks/swr/product-delete.test.tsx
@@ -23,13 +23,14 @@ import { renderHook } from "@testing-library/preact-hooks";
 import { act } from "preact/test-utils";
 import * as backend from "../../../src/context/backend";
 import * as instance from "../../../src/context/instance";
+import { MerchantBackend } from "../../../src/declaration";
 import { useInstanceProducts, useProductAPI } from 
"../../../src/hooks/product";
 import {
   API_LIST_PRODUCTS,
   API_GET_PRODUCT_BY_ID,
   AxiosMockEnvironment,
-  testAllExpectedRequestAndNoMore,
-  testOneRequestToBackend,
+  assertNextRequest,
+  assertJustExpectedRequestWereMade,
 } from "../../axiosMock";
 
 jest.mock("axios");
@@ -46,7 +47,6 @@ describe("product delete api", () => {
       .mockImplementation(
         () => ({ token: "token", id: "default", admin: true } as any)
       );
-    // console.log("CLEAR")
   });
 
   it("should not have problem with cache after a delete", async () => {
@@ -59,31 +59,22 @@ describe("product delete api", () => {
     });
 
     env.addRequestExpectation(API_GET_PRODUCT_BY_ID("1234"), {
-      response: { price: "ARS:12" },
+      response: { price: "ARS:12" } as MerchantBackend.Products.ProductDetail,
     });
 
     env.addRequestExpectation(API_GET_PRODUCT_BY_ID("2345"), {
-      response: { price: "ARS:23" },
+      response: { price: "ARS:23" } as MerchantBackend.Products.ProductDetail,
     });
 
-    // env.addRequestExpectation(API_GET_PRODUCT_BY_ID("1234"), {
-    //   response: { price: "ARS:12" },
-    // });
-
-    // env.addRequestExpectation(API_GET_PRODUCT_BY_ID("2345"), {
-    //   response: { price: "ARS:23" },
-    // });
-
     const { result, waitForNextUpdate } = renderHook(() => {
       const query = useInstanceProducts();
       const api = useProductAPI();
       return { query, api };
-    }); // get products -> loading
+    });
 
-    await waitForNextUpdate(); // get info of every product, -> loading
-    await waitForNextUpdate(); // loading product -> products
-    testAllExpectedRequestAndNoMore(env);
-    // await waitForNextUpdate(); // loading product -> products
+    await waitForNextUpdate();
+    await waitForNextUpdate();
+    assertJustExpectedRequestWereMade(env);
 
     expect(result.current?.query.ok).toBeTruthy();
     if (!result.current?.query.ok) return;
@@ -93,9 +84,12 @@ describe("product delete api", () => {
       { id: "2345", price: "ARS:23" },
     ]);
 
-    env.addRequestExpectation({
-      delete: "http://backend/instances/default/private/products/1234";,
-    });
+    env.addRequestExpectation(
+      {
+        delete: "http://backend/instances/default/private/products/1234";,
+      },
+      {}
+    );
 
     env.addRequestExpectation(API_LIST_PRODUCTS, {
       response: {
@@ -104,21 +98,17 @@ describe("product delete api", () => {
     });
 
     env.addRequestExpectation(API_GET_PRODUCT_BY_ID("2345"), {
-      response: { price: "ARS:23" },
+      response: { price: "ARS:23" } as MerchantBackend.Products.ProductDetail,
     });
 
-    // env.addRequestExpectation(API_GET_PRODUCT_BY_ID("2345"), {
-    //   response: { price: "ARS:23" },
-    // });
-
     act(async () => {
       await result.current?.api.deleteProduct("1234");
     });
 
-    testOneRequestToBackend(env);
+    assertNextRequest(env);
     await waitForNextUpdate();
     await waitForNextUpdate();
-    testAllExpectedRequestAndNoMore(env);
+    assertJustExpectedRequestWereMade(env);
 
     expect(result.current.query.data).toEqual([
       {
diff --git 
a/packages/merchant-backoffice/tests/hooks/swr/product-details-update.test.tsx 
b/packages/merchant-backoffice/tests/hooks/swr/product-details-update.test.tsx
index f5941f3..6b43520 100644
--- 
a/packages/merchant-backoffice/tests/hooks/swr/product-details-update.test.tsx
+++ 
b/packages/merchant-backoffice/tests/hooks/swr/product-details-update.test.tsx
@@ -29,8 +29,8 @@ import {
   API_GET_PRODUCT_BY_ID,
   API_UPDATE_PRODUCT_BY_ID,
   AxiosMockEnvironment,
-  testAllExpectedRequestAndNoMore,
-  testOneRequestToBackend,
+  assertNextRequest,
+  assertJustExpectedRequestWereMade,
 } from "../../axiosMock";
 
 jest.mock("axios");
@@ -53,7 +53,9 @@ describe("product details api", () => {
     const env = new AxiosMockEnvironment();
 
     env.addRequestExpectation(API_GET_PRODUCT_BY_ID("12"), {
-      response: { description: "this is a description" },
+      response: {
+        description: "this is a description",
+      } as MerchantBackend.Products.ProductDetail,
     });
 
     const { result, waitForNextUpdate } = renderHook(() => {
@@ -69,7 +71,7 @@ describe("product details api", () => {
     expect(result.current.query.loading).toBeTruthy();
     await waitForNextUpdate();
 
-    testAllExpectedRequestAndNoMore(env);
+    assertJustExpectedRequestWereMade(env);
 
     expect(result.current.query.loading).toBeFalsy();
     expect(result.current?.query.ok).toBeTruthy();
@@ -84,7 +86,9 @@ describe("product details api", () => {
     });
 
     env.addRequestExpectation(API_GET_PRODUCT_BY_ID("12"), {
-      response: { description: "other description" },
+      response: {
+        description: "other description",
+      } as MerchantBackend.Products.ProductDetail,
     });
 
     act(async () => {
@@ -93,10 +97,10 @@ describe("product details api", () => {
       } as any);
     });
 
-    testOneRequestToBackend(env);
+    assertNextRequest(env);
     await waitForNextUpdate();
 
-    testAllExpectedRequestAndNoMore(env);
+    assertJustExpectedRequestWereMade(env);
 
     expect(result.current.query.loading).toBeFalsy();
     expect(result.current?.query.ok).toBeTruthy();
diff --git 
a/packages/merchant-backoffice/tests/hooks/swr/product-update.test.tsx 
b/packages/merchant-backoffice/tests/hooks/swr/product-update.test.tsx
index d3a106b..ca94367 100644
--- a/packages/merchant-backoffice/tests/hooks/swr/product-update.test.tsx
+++ b/packages/merchant-backoffice/tests/hooks/swr/product-update.test.tsx
@@ -23,14 +23,15 @@ import { renderHook } from "@testing-library/preact-hooks";
 import { act } from "preact/test-utils";
 import * as backend from "../../../src/context/backend";
 import * as instance from "../../../src/context/instance";
+import { MerchantBackend } from "../../../src/declaration";
 import { useInstanceProducts, useProductAPI } from 
"../../../src/hooks/product";
 import {
   API_GET_PRODUCT_BY_ID,
   API_LIST_PRODUCTS,
   API_UPDATE_PRODUCT_BY_ID,
   AxiosMockEnvironment,
-  testAllExpectedRequestAndNoMore,
-  testOneRequestToBackend,
+  assertJustExpectedRequestWereMade,
+  assertNextRequest,
 } from "../../axiosMock";
 
 jest.mock("axios");
@@ -59,7 +60,7 @@ describe("product list api", () => {
     });
 
     env.addRequestExpectation(API_GET_PRODUCT_BY_ID("1234"), {
-      response: { price: "ARS:12" },
+      response: { price: "ARS:12" } as MerchantBackend.Products.ProductDetail,
     });
 
     const { result, waitForNextUpdate } = renderHook(() => {
@@ -76,7 +77,7 @@ describe("product list api", () => {
     await waitForNextUpdate();
 
     await waitForNextUpdate();
-    testAllExpectedRequestAndNoMore(env);
+    assertJustExpectedRequestWereMade(env);
 
     expect(result.current.query.loading).toBeFalsy();
     expect(result.current.query.ok).toBeTruthy();
@@ -96,20 +97,8 @@ describe("product list api", () => {
       },
     });
     env.addRequestExpectation(API_GET_PRODUCT_BY_ID("1234"), {
-      response: { price: "ARS:13" },
+      response: { price: "ARS:13" } as MerchantBackend.Products.ProductDetail,
     });
-    // env.addRequestExpectation(API_GET_PRODUCT_BY_ID("1234"), {
-    //   request: { price: "ARS:13" },
-    // });
-    // env.addRequestExpectation(API_GET_PRODUCT_BY_ID("1234"), {
-    //   request: { price: "ARS:13" },
-    // });
-    // env.addRequestExpectation(API_GET_PRODUCT_BY_ID("1234"), {
-    //   request: { price: "ARS:13" },
-    // });
-    // env.addRequestExpectation(API_GET_PRODUCT_BY_ID("1234"), {
-    //   request: { price: "ARS:13" },
-    // });
 
     act(async () => {
       await result.current?.api.updateProduct("1234", {
@@ -117,11 +106,11 @@ describe("product list api", () => {
       } as any);
     });
 
-    testOneRequestToBackend(env);
+    assertNextRequest(env);
     await waitForNextUpdate();
     // await waitForNextUpdate();
 
-    // testAllExpectedRequestAndNoMore(env);
+    assertJustExpectedRequestWereMade(env);
     // await waitForNextUpdate();
 
     expect(result.current.query.loading).toBeFalsy();
diff --git a/packages/merchant-backoffice/tests/hooks/swr/order-create.test.tsx 
b/packages/merchant-backoffice/tests/hooks/swr/reserve-create.test.tsx
similarity index 54%
copy from packages/merchant-backoffice/tests/hooks/swr/order-create.test.tsx
copy to packages/merchant-backoffice/tests/hooks/swr/reserve-create.test.tsx
index 0defaec..cff0f09 100644
--- a/packages/merchant-backoffice/tests/hooks/swr/order-create.test.tsx
+++ b/packages/merchant-backoffice/tests/hooks/swr/reserve-create.test.tsx
@@ -23,18 +23,25 @@ import { renderHook } from "@testing-library/preact-hooks";
 import { act } from "preact/test-utils";
 import * as backend from "../../../src/context/backend";
 import * as instance from "../../../src/context/instance";
-import { useInstanceOrders, useOrderAPI } from "../../../src/hooks/order";
+import { MerchantBackend } from "../../../src/declaration";
 import {
-  API_CREATE_ORDER,
-  API_LIST_ORDERS,
+  useInstanceReserves,
+  useReservesAPI,
+} from "../../../src/hooks/reserves";
+import {
+  API_CREATE_PRODUCT,
+  API_LIST_PRODUCTS,
+  API_GET_PRODUCT_BY_ID,
   AxiosMockEnvironment,
-  testNoOtherRequestWasMade,
-  testOneRequestToBackend,
+  assertJustExpectedRequestWereMade,
+  API_LIST_RESERVES,
+  API_CREATE_RESERVE,
+  API_GET_RESERVE_BY_ID,
 } from "../../axiosMock";
 
 jest.mock("axios");
 
-describe("order api", () => {
+describe("reserve create api", () => {
   beforeEach(() => {
     jest
       .spyOn(backend, "useBackendContext")
@@ -48,91 +55,98 @@ describe("order api", () => {
       );
   });
 
-  it("should not have problem with cache after an creation", async () => {
+  it("should mutate list cache when creating new reserve", async () => {
     const env = new AxiosMockEnvironment();
-    env.addRequestExpectation(API_LIST_ORDERS, {
-      qparam: { delta: 0, paid: "yes" },
-      response: {
-        orders: [{ order_id: "1" }],
-      },
-    });
 
-    env.addRequestExpectation(API_LIST_ORDERS, {
-      qparam: { delta: -20, paid: "yes" },
+    env.addRequestExpectation(API_LIST_RESERVES, {
       response: {
-        orders: [{ order_id: "2" }],
+        reserves: [
+          {
+            reserve_pub: "11",
+          } as MerchantBackend.Tips.ReserveStatusEntry,
+        ],
       },
     });
 
-    const newDate = (d: Date) => {
-      console.log("new date", d);
-    };
-
     const { result, waitForNextUpdate } = renderHook(() => {
-      const query = useInstanceOrders({ paid: "yes" }, newDate);
-      const api = useOrderAPI();
+      const api = useReservesAPI();
+      const query = useInstanceReserves();
 
       return { query, api };
-    }); // get products -> loading
+    });
 
     if (!result.current) {
       expect(result.current).toBeDefined();
       return;
     }
-
     expect(result.current.query.loading).toBeTruthy();
+
     await waitForNextUpdate();
-    testOneRequestToBackend(env);
-    testOneRequestToBackend(env);
-    testNoOtherRequestWasMade(env);
+
+    assertJustExpectedRequestWereMade(env);
 
     expect(result.current.query.loading).toBeFalsy();
     expect(result.current?.query.ok).toBeTruthy();
     if (!result.current?.query.ok) return;
 
     expect(result.current.query.data).toEqual({
-      orders: [{ order_id: "1" }, { order_id: "2" }],
+      reserves: [{ reserve_pub: "11" }],
     });
 
-    env.addRequestExpectation(API_CREATE_ORDER, {
+    env.addRequestExpectation(API_CREATE_RESERVE, {
       request: {
-        order: { amount: "ARS:12", summary: "pay me" },
+        initial_balance: "ARS:3333",
+        exchange_url: "http://url";,
+        wire_method: "iban",
       },
-      response: { order_id: "3" },
-    });
-
-    env.addRequestExpectation(API_LIST_ORDERS, {
-      qparam: { delta: 0, paid: "yes" },
       response: {
-        orders: [{ order_id: "1" } as any],
+        reserve_pub: "22",
+        payto_uri: "payto",
       },
     });
 
-    env.addRequestExpectation(API_LIST_ORDERS, {
-      qparam: { delta: -20, paid: "yes" },
+    act(async () => {
+      await result.current?.api.createReserve({
+        initial_balance: "ARS:3333",
+        exchange_url: "http://url";,
+        wire_method: "iban",
+      });
+      return;
+    });
+
+    assertJustExpectedRequestWereMade(env);
+
+    env.addRequestExpectation(API_LIST_RESERVES, {
       response: {
-        orders: [{ order_id: "2" } as any, { order_id: "3" } as any],
+        reserves: [
+          {
+            reserve_pub: "11",
+          } as MerchantBackend.Tips.ReserveStatusEntry,
+          {
+            reserve_pub: "22",
+          } as MerchantBackend.Tips.ReserveStatusEntry,
+        ],
       },
     });
 
-    act(async () => {
-      await result.current?.api.createOrder({
-        order: { amount: "ARS:12", summary: "pay me" },
-      } as any);
-    });
+    expect(result.current.query.loading).toBeFalsy();
 
-    testOneRequestToBackend(env); //post
     await waitForNextUpdate();
-    testOneRequestToBackend(env); //get
-    testOneRequestToBackend(env); //get
-    testNoOtherRequestWasMade(env);
+
+    assertJustExpectedRequestWereMade(env);
 
     expect(result.current.query.loading).toBeFalsy();
-    expect(result.current?.query.ok).toBeTruthy();
-    if (!result.current?.query.ok) return;
+    expect(result.current.query.ok).toBeTruthy();
 
     expect(result.current.query.data).toEqual({
-      orders: [{ order_id: "1" }, { order_id: "2" }, { order_id: "3" }],
+      reserves: [
+        {
+          reserve_pub: "11",
+        } as MerchantBackend.Tips.ReserveStatusEntry,
+        {
+          reserve_pub: "22",
+        } as MerchantBackend.Tips.ReserveStatusEntry,
+      ],
     });
   });
 });
diff --git 
a/packages/merchant-backoffice/tests/hooks/swr/order-pagination.test.tsx 
b/packages/merchant-backoffice/tests/hooks/swr/transfer-pagination.test.tsx
similarity index 54%
copy from packages/merchant-backoffice/tests/hooks/swr/order-pagination.test.tsx
copy to 
packages/merchant-backoffice/tests/hooks/swr/transfer-pagination.test.tsx
index d62ead7..34b4ce9 100644
--- a/packages/merchant-backoffice/tests/hooks/swr/order-pagination.test.tsx
+++ b/packages/merchant-backoffice/tests/hooks/swr/transfer-pagination.test.tsx
@@ -22,21 +22,17 @@
 import { act, renderHook } from "@testing-library/preact-hooks";
 import * as backend from "../../../src/context/backend";
 import * as instance from "../../../src/context/instance";
-import { MerchantBackend } from "../../../src/declaration";
-import { setAxiosRequestAsTestingEnvironment } from 
"../../../src/hooks/backend";
-import { useInstanceOrders } from "../../../src/hooks/order";
+import { useInstanceTransfers } from "../../../src/hooks/transfer";
 import {
-  API_LIST_ORDERS,
+  API_LIST_TRANSFERS,
+  assertNextRequest,
+  assertNoMoreRequestWereMade,
   AxiosMockEnvironment,
-  testNoOtherRequestWasMade,
-  testOneRequestToBackend,
 } from "../../axiosMock";
 
-setAxiosRequestAsTestingEnvironment();
-
 jest.mock("axios");
 
-describe("order pagination", () => {
+describe("transfer pagination", () => {
   beforeEach(() => {
     jest
       .spyOn(backend, "useBackendContext")
@@ -52,32 +48,31 @@ describe("order pagination", () => {
 
   it("should change pagination", async () => {
     const env = new AxiosMockEnvironment();
-    env.addRequestExpectation(API_LIST_ORDERS, {
-      qparam: { delta: 20, wired: "yes", date_ms: 12 },
+    env.addRequestExpectation(API_LIST_TRANSFERS, {
+      qparam: { limit: 20, verified: "yes" },
       response: {
-        orders: [{ order_id: "1" } as any],
+        transfers: [{ wtid: "1" } as any],
       },
     });
 
-    env.addRequestExpectation(API_LIST_ORDERS, {
-      qparam: { delta: -20, wired: "yes", date_ms: 13 },
+    env.addRequestExpectation(API_LIST_TRANSFERS, {
+      qparam: { limit: -20, verified: "yes" },
       response: {
-        orders: [{ order_id: "2" } as any],
+        transfers: [{ wtid: "3" } as any],
       },
     });
 
-    const newDate = (d: Date) => {
-      console.log("new date", d);
+    const updatePosition = (d: string) => {
+      console.log("updatePosition", d);
     };
 
-    const date = new Date(12);
     const { result, waitForNextUpdate } = renderHook(() =>
-      useInstanceOrders({ wired: "yes", date }, newDate)
-    ); // get products -> loading
+      useInstanceTransfers({ verified: "yes", position: "" }, updatePosition)
+    );
 
-    testOneRequestToBackend(env);
-    testOneRequestToBackend(env);
-    testNoOtherRequestWasMade(env);
+    assertNextRequest(env);
+    assertNextRequest(env);
+    assertNoMoreRequestWereMade(env);
 
     await waitForNextUpdate(); // get info of every product, -> loading
 
@@ -85,13 +80,13 @@ describe("order pagination", () => {
     if (!result.current?.ok) return;
 
     expect(result.current.data).toEqual({
-      orders: [{ order_id: "1" }, { order_id: "2" }],
+      transfers: [{ wtid: "1" }, { wtid: "3" }],
     });
 
-    env.addRequestExpectation(API_LIST_ORDERS, {
-      qparam: { delta: -40, wired: "yes", date_ms: 13 },
+    env.addRequestExpectation(API_LIST_TRANSFERS, {
+      qparam: { limit: -40, verified: "yes" },
       response: {
-        orders: [{ order_id: "2" } as any, { order_id: "3" } as any],
+        transfers: [{ wtid: "4" } as any, { wtid: "3" } as any],
       },
     });
 
@@ -99,32 +94,27 @@ describe("order pagination", () => {
       if (!result.current?.ok) throw Error("not ok");
       result.current.loadMore();
     });
-    await waitForNextUpdate(); // loading product -> products
-    // await waitForNextUpdate(); // loading product -> products
-    testOneRequestToBackend(env);
-    testNoOtherRequestWasMade(env);
+    await waitForNextUpdate();
+    assertNextRequest(env);
+    assertNoMoreRequestWereMade(env);
 
-    env.addRequestExpectation(API_LIST_ORDERS, {
-      qparam: { delta: 40, wired: "yes", date_ms: 12 },
+    env.addRequestExpectation(API_LIST_TRANSFERS, {
+      qparam: { limit: 40, verified: "yes" },
       response: {
-        orders: [{ order_id: "1" } as any, { order_id: "0" } as any],
+        transfers: [{ wtid: "1" } as any, { wtid: "2" } as any],
       },
     });
+
     await act(() => {
       if (!result.current?.ok) throw Error("not ok");
       result.current.loadMorePrev();
     });
-    await waitForNextUpdate(); // loading product -> products
-    testOneRequestToBackend(env);
-    testNoOtherRequestWasMade(env);
+    await waitForNextUpdate();
+    assertNextRequest(env);
+    assertNoMoreRequestWereMade(env);
 
     expect(result.current.data).toEqual({
-      orders: [
-        { order_id: "0" },
-        { order_id: "1" },
-        { order_id: "2" },
-        { order_id: "3" },
-      ],
+      transfers: [{ wtid: "2" }, { wtid: "1" }, { wtid: "4" }, { wtid: "3" }],
     });
   });
 });

-- 
To stop receiving notification emails like this one, please contact
gnunet@gnunet.org.



reply via email to

[Prev in Thread] Current Thread [Next in Thread]