[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]
[taler-merchant-backoffice] branch master updated: test case for orders,
From: |
gnunet |
Subject: |
[taler-merchant-backoffice] branch master updated: test case for orders, products, reserves and transfers |
Date: |
Tue, 14 Dec 2021 20:13:30 +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 58d06f9 test case for orders, products, reserves and transfers
58d06f9 is described below
commit 58d06f9b5eaa41c083c7702d772f174a2048c9c2
Author: Sebastian <sebasjm@gmail.com>
AuthorDate: Tue Dec 14 16:11:53 2021 -0300
test case for orders, products, reserves and transfers
---
.../merchant-backoffice/src/context/backend.ts | 14 +-
packages/merchant-backoffice/src/hooks/backend.ts | 14 +-
packages/merchant-backoffice/src/hooks/index.ts | 4 +-
packages/merchant-backoffice/src/hooks/order.ts | 32 +-
packages/merchant-backoffice/src/hooks/product.ts | 4 +-
packages/merchant-backoffice/src/hooks/reserves.ts | 18 +-
packages/merchant-backoffice/src/hooks/transfer.ts | 36 +-
.../src/utils/switchableAxios.ts | 66 +++
packages/merchant-backoffice/tests/axiosMock.ts | 182 +++++--
.../merchant-backoffice/tests/hooks/swr/index.tsx | 45 ++
.../tests/hooks/swr/order-create.test.tsx | 139 -----
.../tests/hooks/swr/order-pagination.test.tsx | 126 -----
.../tests/hooks/swr/order.test.ts | 567 +++++++++++++++++++++
.../tests/hooks/swr/product-create.test.tsx | 142 ------
.../tests/hooks/swr/product-delete.test.tsx | 120 -----
.../hooks/swr/product-details-update.test.tsx | 113 ----
.../tests/hooks/swr/product-update.test.tsx | 127 -----
.../tests/hooks/swr/product.test.ts | 338 ++++++++++++
.../tests/hooks/swr/reserve.test.ts | 378 +++++++++++++-
.../tests/hooks/swr/transfer-pagination.test.tsx | 120 -----
.../tests/hooks/swr/transfer.test.ts | 268 ++++++++++
21 files changed, 1831 insertions(+), 1022 deletions(-)
diff --git a/packages/merchant-backoffice/src/context/backend.ts
b/packages/merchant-backoffice/src/context/backend.ts
index 9168d32..9ef7bfd 100644
--- a/packages/merchant-backoffice/src/context/backend.ts
+++ b/packages/merchant-backoffice/src/context/backend.ts
@@ -43,10 +43,10 @@ const BackendContext = createContext<BackendContextType>({
updateLoginStatus: () => null,
})
-function useBackendContextState(defaultUrl?:string): BackendContextType {
+function useBackendContextState(defaultUrl?: string, initialToken?: string):
BackendContextType {
const [url, triedToLog, changeBackend, resetBackend] =
useBackendURL(defaultUrl);
- const [token, _updateToken] = useBackendDefaultToken();
- const updateToken = (t?:string) => {
+ const [token, _updateToken] = useBackendDefaultToken(initialToken);
+ const updateToken = (t?: string) => {
_updateToken(t)
}
@@ -73,10 +73,10 @@ function useBackendContextState(defaultUrl?:string):
BackendContextType {
return { url, token, triedToLog, updateLoginStatus, resetBackend,
clearAllTokens, addTokenCleaner: addTokenCleanerMemo }
}
-export const BackendContextProvider = ({children, defaultUrl}:{children:any,
defaultUrl?:string}):VNode => {
- const value = useBackendContextState(defaultUrl)
-
- return h(BackendContext.Provider, {value, children});
+export const BackendContextProvider = ({ children, defaultUrl, initialToken }:
{ children: any, defaultUrl?: string, initialToken?: string }): VNode => {
+ const value = useBackendContextState(defaultUrl, initialToken)
+
+ return h(BackendContext.Provider, { value, children });
}
export const useBackendContext = (): BackendContextType =>
useContext(BackendContext);
diff --git a/packages/merchant-backoffice/src/hooks/backend.ts
b/packages/merchant-backoffice/src/hooks/backend.ts
index 59bd0b6..1b27cfe 100644
--- a/packages/merchant-backoffice/src/hooks/backend.ts
+++ b/packages/merchant-backoffice/src/hooks/backend.ts
@@ -25,6 +25,7 @@ import { MerchantBackend } from "../declaration";
import { useBackendContext } from "../context/backend";
import { useEffect, useState } from "preact/hooks";
import { DEFAULT_REQUEST_TIMEOUT } from "../utils/constants";
+import { axiosHandler, removeAxiosCancelToken } from
"../utils/switchableAxios";
export function useMatchMutate(): (
re: RegExp,
@@ -226,20 +227,11 @@ function buildRequestFailed(
const CancelToken = axios.CancelToken;
let source = CancelToken.source();
-export function cancelPendingRequest() {
+export function cancelPendingRequest(): void {
source.cancel("canceled by the user");
source = CancelToken.source();
}
-let removeAxiosCancelToken = false;
-/**
- * Jest mocking seems to break when using the cancelToken property.
- * Using this workaround when testing while finding the correct solution
- */
-export function setAxiosRequestAsTestingEnvironment() {
- removeAxiosCancelToken = true;
-}
-
export function isAxiosError<T>(
error: AxiosError | any
): error is AxiosError<T> {
@@ -255,7 +247,7 @@ export async function request<T>(
: undefined;
try {
- const res = await axios({
+ const res = await axiosHandler({
url,
responseType: "json",
headers,
diff --git a/packages/merchant-backoffice/src/hooks/index.ts
b/packages/merchant-backoffice/src/hooks/index.ts
index 19d672a..a647e3e 100644
--- a/packages/merchant-backoffice/src/hooks/index.ts
+++ b/packages/merchant-backoffice/src/hooks/index.ts
@@ -43,8 +43,8 @@ export function useBackendURL(url?: string): [string,
boolean, StateUpdater<stri
return [value, !!triedToLog, checkedSetter, resetBackend]
}
-export function useBackendDefaultToken(): [string | undefined,
StateUpdater<string | undefined>] {
- return useLocalStorage('backend-token')
+export function useBackendDefaultToken(initialValue?: string): [string |
undefined, StateUpdater<string | undefined>] {
+ return useLocalStorage('backend-token', initialValue)
}
export function useBackendInstanceToken(id: string): [string | undefined,
StateUpdater<string | undefined>] {
diff --git a/packages/merchant-backoffice/src/hooks/order.ts
b/packages/merchant-backoffice/src/hooks/order.ts
index 883bcef..0f8afce 100644
--- a/packages/merchant-backoffice/src/hooks/order.ts
+++ b/packages/merchant-backoffice/src/hooks/order.ts
@@ -106,7 +106,7 @@ export function useOrderAPI(): OrderAPI {
data: MerchantBackend.Orders.RefundRequest
): Promise<HttpResponseOk<MerchantBackend.Orders.MerchantRefundResponse>> =>
{
mutateAll(/@"\/private\/orders"@/);
- return request<MerchantBackend.Orders.MerchantRefundResponse>(
+ const res = request<MerchantBackend.Orders.MerchantRefundResponse>(
`${url}/private/orders/${orderId}/refund`,
{
method: "post",
@@ -115,7 +115,9 @@ export function useOrderAPI(): OrderAPI {
}
);
- // return res
+ // order list returns refundable information, so we must evict everything
+ await mutateAll(/.*private\/orders.*/);
+ return res
};
const forgetOrder = async (
@@ -123,20 +125,25 @@ export function useOrderAPI(): OrderAPI {
data: MerchantBackend.Orders.ForgetRequest
): Promise<HttpResponseOk<void>> => {
mutateAll(/@"\/private\/orders"@/);
- return request(`${url}/private/orders/${orderId}/forget`, {
+ const res = request<void>(`${url}/private/orders/${orderId}/forget`, {
method: "patch",
token,
data,
});
+ // we may be forgetting some fields that are pare of the listing, so we
must evict everything
+ await mutateAll(/.*private\/orders.*/);
+ return res
};
const deleteOrder = async (
orderId: string
): Promise<HttpResponseOk<void>> => {
mutateAll(/@"\/private\/orders"@/);
- return request(`${url}/private/orders/${orderId}`, {
+ const res = request<void>(`${url}/private/orders/${orderId}`, {
method: "delete",
token,
});
+ await mutateAll(/.*private\/orders.*/);
+ return res
};
const getPaymentURL = async (
@@ -266,18 +273,19 @@ export function useInstanceOrders(
if (beforeData) setLastBefore(beforeData);
}, [afterData, beforeData]);
- // this has problems when there are some ids missing
-
if (beforeError) return beforeError;
if (afterError) return afterError;
+ // if the query returns less that we ask, then we have reach the end or
beginning
+ const isReachingEnd = afterData && afterData.data.orders.length < totalAfter;
+ const isReachingStart = args?.date === undefined ||
+ (beforeData && beforeData.data.orders.length < totalBefore);
+
const pagination = {
- isReachingEnd: afterData && afterData.data.orders.length < totalAfter,
- isReachingStart:
- !args?.date ||
- (beforeData && beforeData.data.orders.length < totalBefore),
+ isReachingEnd,
+ isReachingStart,
loadMore: () => {
- if (!afterData) return;
+ if (!afterData || isReachingEnd) return;
if (afterData.data.orders.length < MAX_RESULT_SIZE) {
setPageAfter(pageAfter + 1);
} else {
@@ -288,7 +296,7 @@ export function useInstanceOrders(
}
},
loadMorePrev: () => {
- if (!beforeData) return;
+ if (!beforeData || isReachingStart) return;
if (beforeData.data.orders.length < MAX_RESULT_SIZE) {
setPageBefore(pageBefore + 1);
} else if (beforeData) {
diff --git a/packages/merchant-backoffice/src/hooks/product.ts
b/packages/merchant-backoffice/src/hooks/product.ts
index 1e6ebf2..c99542b 100644
--- a/packages/merchant-backoffice/src/hooks/product.ts
+++ b/packages/merchant-backoffice/src/hooks/product.ts
@@ -61,7 +61,7 @@ export function useProductAPI(): ProductAPI {
data,
});
- return await mutateAll(/.*private\/products.*/);
+ return await mutateAll(/.*"\/private\/products.*/);
};
const updateProduct = async (
@@ -95,7 +95,7 @@ export function useProductAPI(): ProductAPI {
data,
});
- await mutateAll(/@"\/private\/products"@/);
+ return await mutateAll(/.*"\/private\/products.*/);
};
return { createProduct, updateProduct, deleteProduct, lockProduct };
diff --git a/packages/merchant-backoffice/src/hooks/reserves.ts
b/packages/merchant-backoffice/src/hooks/reserves.ts
index 259bd1c..7a662df 100644
--- a/packages/merchant-backoffice/src/hooks/reserves.ts
+++ b/packages/merchant-backoffice/src/hooks/reserves.ts
@@ -13,7 +13,7 @@
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 useSWR from "swr";
+import useSWR, { useSWRConfig } from "swr";
import { useBackendContext } from "../context/backend";
import { useInstanceContext } from "../context/instance";
import { MerchantBackend } from "../declaration";
@@ -28,6 +28,7 @@ import {
export function useReservesAPI(): ReserveMutateAPI {
const mutateAll = useMatchMutate();
+ const { mutate } = useSWRConfig();
const { url: baseUrl, token: adminToken } = useBackendContext();
const { token: instanceToken, id, admin } = useInstanceContext();
@@ -49,6 +50,7 @@ export function useReservesAPI(): ReserveMutateAPI {
}
);
+ //evict reserve list query
await mutateAll(/.*private\/reserves.*/);
return res;
@@ -66,7 +68,9 @@ export function useReservesAPI(): ReserveMutateAPI {
data,
}
);
- await mutateAll(/@"\/private\/reserves"@/);
+
+ //evict reserve details query
+ await mutate([`/private/reserves/${pub}`, token, url]);
return res;
};
@@ -83,7 +87,8 @@ export function useReservesAPI(): ReserveMutateAPI {
}
);
- await mutateAll(/@"\/private\/reserves"@/);
+ //evict all details query
+ await mutateAll(/.*private\/reserves\/.*/);
return res;
};
@@ -94,7 +99,8 @@ export function useReservesAPI(): ReserveMutateAPI {
token,
});
- await mutateAll(/@"\/private\/reserves"@/);
+ //evict reserve list query
+ await mutateAll(/.*private\/reserves.*/);
return res;
};
@@ -185,7 +191,7 @@ export function useTipDetails(
return { loading: true };
}
-export function reserveDetailFetcher<T>(
+function reserveDetailFetcher<T>(
url: string,
token: string,
backend: string
@@ -198,7 +204,7 @@ export function reserveDetailFetcher<T>(
});
}
-export function tipsDetailFetcher<T>(
+function tipsDetailFetcher<T>(
url: string,
token: string,
backend: string
diff --git a/packages/merchant-backoffice/src/hooks/transfer.ts
b/packages/merchant-backoffice/src/hooks/transfer.ts
index 86ed420..0c12d6d 100644
--- a/packages/merchant-backoffice/src/hooks/transfer.ts
+++ b/packages/merchant-backoffice/src/hooks/transfer.ts
@@ -68,16 +68,15 @@ export function useTransferAPI(): TransferAPI {
): Promise<
HttpResponseOk<MerchantBackend.Transfers.MerchantTrackTransferResponse>
> => {
- mutateAll(/@"\/private\/transfers"@/);
-
- return request<MerchantBackend.Transfers.MerchantTrackTransferResponse>(
- `${url}/private/transfers`,
- {
- method: "post",
- token,
- data,
- }
- );
+ const res = await
request<MerchantBackend.Transfers.MerchantTrackTransferResponse>(
+ `${url}/private/transfers`, {
+ method: "post",
+ token,
+ data,
+ });
+
+ await mutateAll(/.*private\/transfers.*/);
+ return res
};
return { informTransfer };
@@ -165,18 +164,19 @@ export function useInstanceTransfers(
if (beforeData) setLastBefore(beforeData);
}, [afterData, beforeData]);
- // this has problems when there are some ids missing
-
if (beforeError) return beforeError;
if (afterError) return afterError;
+ // if the query returns less that we ask, then we have reach the end or
beginning
+ const isReachingEnd = afterData && afterData.data.transfers.length <
totalAfter;
+ const isReachingStart = args?.position === undefined ||
+ (beforeData && beforeData.data.transfers.length < totalBefore);
+
const pagination = {
- isReachingEnd: afterData && afterData.data.transfers.length < totalAfter,
- isReachingStart:
- !args?.position ||
- (beforeData && beforeData.data.transfers.length < totalBefore),
+ isReachingEnd,
+ isReachingStart,
loadMore: () => {
- if (!afterData) return;
+ if (!afterData || isReachingEnd) return;
if (afterData.data.transfers.length < MAX_RESULT_SIZE) {
setPageAfter(pageAfter + 1);
} else {
@@ -188,7 +188,7 @@ export function useInstanceTransfers(
}
},
loadMorePrev: () => {
- if (!beforeData) return;
+ if (!beforeData || isReachingStart) return;
if (beforeData.data.transfers.length < MAX_RESULT_SIZE) {
setPageBefore(pageBefore + 1);
} else if (beforeData) {
diff --git a/packages/merchant-backoffice/src/utils/switchableAxios.ts
b/packages/merchant-backoffice/src/utils/switchableAxios.ts
new file mode 100644
index 0000000..be7eedd
--- /dev/null
+++ b/packages/merchant-backoffice/src/utils/switchableAxios.ts
@@ -0,0 +1,66 @@
+/*
+ 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/>
+ */
+
+import axios, { AxiosPromise, AxiosRequestConfig } from "axios";
+
+/**
+ *
+ * @author Sebastian Javier Marchano (sebasjm)
+ */
+
+export let removeAxiosCancelToken = false;
+
+export let axiosHandler = function doAxiosRequest(config: AxiosRequestConfig):
AxiosPromise<any> {
+ return axios(config)
+}
+
+/**
+ * Set this backend library to testing mode.
+ * Instead of calling the axios library the @handler will be called
+ *
+ * @param handler callback that will mock axios
+ */
+export function setAxiosRequestAsTestingEnvironment(handler: AxiosHandler):
void {
+ removeAxiosCancelToken = true;
+ axiosHandler = function defaultTestingHandler(config) {
+ const currentHanlder = listOfHandlersToUseOnce.shift()
+ if (!currentHanlder) {
+ return handler(config)
+ }
+
+ return currentHanlder(config)
+ }
+}
+
+type AxiosHandler = (config: AxiosRequestConfig) => AxiosPromise<any>;
+type AxiosArguments = { args: AxiosRequestConfig | undefined }
+
+
+const listOfHandlersToUseOnce = new Array<AxiosHandler>()
+
+/**
+ *
+ * @param handler mock function
+ * @returns savedArgs
+ */
+export function mockAxiosOnce(handler: AxiosHandler): { args:
AxiosRequestConfig | undefined } {
+ const savedArgs: AxiosArguments = { args: undefined }
+ listOfHandlersToUseOnce.push((config: AxiosRequestConfig): AxiosPromise<any>
=> {
+ savedArgs.args = config;
+ return handler(config)
+ })
+ return savedArgs;
+}
diff --git a/packages/merchant-backoffice/tests/axiosMock.ts
b/packages/merchant-backoffice/tests/axiosMock.ts
index a6ecf60..7b33e2a 100644
--- a/packages/merchant-backoffice/tests/axiosMock.ts
+++ b/packages/merchant-backoffice/tests/axiosMock.ts
@@ -20,7 +20,8 @@
*/
import * as axios from 'axios';
import { MerchantBackend } from '../src/declaration';
-import { setAxiosRequestAsTestingEnvironment } from "../src/hooks/backend";
+import { mockAxiosOnce, setAxiosRequestAsTestingEnvironment } from
'../src/utils/switchableAxios';
+// import { mockAxiosOnce, setAxiosRequestAsTestingEnvironment } from
"../src/hooks/backend";
export type Query<Req, Res> = (GetQuery | PostQuery | DeleteQuery |
PatchQuery) & RequestResponse<Req, Res>
@@ -32,29 +33,28 @@ interface PostQuery { post: string }
interface DeleteQuery { delete: string }
interface PatchQuery { patch: string }
-setAxiosRequestAsTestingEnvironment();
const JEST_DEBUG_LOG = process.env['JEST_DEBUG_LOG'] !== undefined
type TestValues = [axios.AxiosRequestConfig | undefined, { query: Query<any,
any>; params?: { request?: any, qparam?: any, response?: any } } | undefined]
-const defaultCallback = (actualQuery?: axios.AxiosRequestConfig) => {
+const defaultCallback = (actualQuery?: axios.AxiosRequestConfig):
axios.AxiosPromise<any> => {
if (JEST_DEBUG_LOG) {
console.log('UNEXPECTED QUERY', actualQuery)
}
+ throw Error('Default Axios mock callback is called, this mean that the test
did a tried to use axios but there was no expectation in place, try using
JEST_DEBUG_LOG env')
}
-export class AxiosMockEnvironment {
- expectations: Array<{ query: Query<any, any>, params?: { request?: any,
qparam?: any, response?: any } } | undefined> = []
- axiosMock: jest.MockedFunction<axios.AxiosStatic>
+setAxiosRequestAsTestingEnvironment(
+ defaultCallback
+);
- constructor() {
- this.axiosMock = (axios.default as
jest.MockedFunction<axios.AxiosStatic>).mockImplementation(defaultCallback as
any)
- }
+export class AxiosMockEnvironment {
+ expectations: Array<{ query: Query<any, any>, params?: { request?: any,
qparam?: any, response?: any }, result: { args: axios.AxiosRequestConfig |
undefined } } | undefined> = []
+ // axiosMock: jest.MockedFunction<axios.AxiosStatic>
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 {
+ const result = mockAxiosOnce(function (actualQuery?:
axios.AxiosRequestConfig): axios.AxiosPromise {
if (JEST_DEBUG_LOG) {
console.log('query to the backend is made', actualQuery)
@@ -91,23 +91,15 @@ export class AxiosMockEnvironment {
})
} as any)
+
+ this.expectations.push(expectedQuery ? { query: expectedQuery, params,
result } : undefined)
}
getLastTestValues(): TestValues {
- const lastCall = this.axiosMock.mock.calls[0]
- if (lastCall === undefined) {
- const expectedQuery = this.expectations.shift()
- return [undefined, expectedQuery]
- }
- const actualQuery = lastCall[0] as axios.AxiosRequestConfig
-
- //Remove values from the last call
const expectedQuery = this.expectations.shift()
- this.axiosMock.mock.calls.shift()
- this.axiosMock.mock.results.shift()
return [
- actualQuery, expectedQuery
+ expectedQuery?.result.args, expectedQuery
]
}
@@ -170,19 +162,25 @@ export function assertNextRequest(env:
AxiosMockEnvironment): void {
}
-export const API_LIST_PRODUCTS: Query<
- unknown,
- MerchantBackend.Products.InventorySummaryResponse
+////////////////////
+// ORDER
+////////////////////
+
+export const API_CREATE_ORDER: Query<
+ MerchantBackend.Orders.PostOrderRequest,
+ MerchantBackend.Orders.PostOrderResponse
> = {
- get: "http://backend/instances/default/private/products";,
+ post: "http://backend/instances/default/private/orders";,
};
-export const API_LIST_RESERVES: Query<
+export const API_GET_ORDER_BY_ID = (
+ id: string
+): Query<
unknown,
- MerchantBackend.Tips.TippingReserveStatus
-> = {
- get: "http://backend/instances/default/private/reserves";,
-};
+ MerchantBackend.Orders.MerchantOrderStatusResponse
+> => ({
+ get: `http://backend/instances/default/private/orders/${id}`,
+});
export const API_LIST_ORDERS: Query<
unknown,
@@ -191,6 +189,37 @@ export const API_LIST_ORDERS: Query<
get: "http://backend/instances/default/private/orders";,
};
+export const API_REFUND_ORDER_BY_ID = (
+ id: string
+): Query<
+ MerchantBackend.Orders.RefundRequest,
+ MerchantBackend.Orders.MerchantRefundResponse
+> => ({
+ post: `http://backend/instances/default/private/orders/${id}/refund`,
+});
+
+export const API_FORGET_ORDER_BY_ID = (
+ id: string
+): Query<
+ MerchantBackend.Orders.ForgetRequest,
+ unknown
+> => ({
+ patch: `http://backend/instances/default/private/orders/${id}/forget`,
+});
+
+export const API_DELETE_ORDER = (
+ id: string
+): Query<
+ MerchantBackend.Orders.ForgetRequest,
+ unknown
+> => ({
+ delete: `http://backend/instances/default/private/orders/${id}`,
+});
+
+////////////////////
+// TRANSFER
+////////////////////
+
export const API_LIST_TRANSFERS: Query<
unknown,
MerchantBackend.Transfers.TransferList
@@ -198,31 +227,29 @@ export const API_LIST_TRANSFERS: Query<
get: "http://backend/instances/default/private/transfers";,
};
+export const API_INFORM_TRANSFERS: Query<
+ MerchantBackend.Transfers.TransferInformation,
+ MerchantBackend.Transfers.MerchantTrackTransferResponse
+> = {
+ post: "http://backend/instances/default/private/transfers";,
+};
+
+////////////////////
+// PRODUCT
+////////////////////
+
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_DELETE_RESERVE: Query<
- MerchantBackend.Tips.ReserveCreateRequest,
- MerchantBackend.Tips.ReserveCreateConfirmation
-> = {
- delete: "http://backend/instances/default/private/reserves";,
-};
-
-export const API_CREATE_ORDER: Query<
- MerchantBackend.Orders.PostOrderRequest,
- MerchantBackend.Orders.PostOrderResponse
+export const API_LIST_PRODUCTS: Query<
+ unknown,
+ MerchantBackend.Products.InventorySummaryResponse
> = {
- post: "http://backend/instances/default/private/orders";,
+ get: "http://backend/instances/default/private/products";,
};
export const API_GET_PRODUCT_BY_ID = (
@@ -234,15 +261,72 @@ export const API_GET_PRODUCT_BY_ID = (
export const API_UPDATE_PRODUCT_BY_ID = (
id: string
): Query<
- Partial<MerchantBackend.Products.ProductPatchDetail>,
+ MerchantBackend.Products.ProductPatchDetail,
MerchantBackend.Products.InventorySummaryResponse
> => ({
patch: `http://backend/instances/default/private/products/${id}`,
});
+export const API_DELETE_PRODUCT = (
+ id: string
+): Query<
+ unknown, unknown
+> => ({
+ delete: `http://backend/instances/default/private/products/${id}`,
+});
+
+////////////////////
+// RESERVES
+////////////////////
+
+export const API_CREATE_RESERVE: Query<
+ MerchantBackend.Tips.ReserveCreateRequest,
+ MerchantBackend.Tips.ReserveCreateConfirmation
+> = {
+ post: "http://backend/instances/default/private/reserves";,
+};
+export const API_LIST_RESERVES: Query<
+ unknown,
+ MerchantBackend.Tips.TippingReserveStatus
+> = {
+ get: "http://backend/instances/default/private/reserves";,
+};
+
export const API_GET_RESERVE_BY_ID = (
pub: string
): Query<unknown, MerchantBackend.Tips.ReserveDetail> => ({
get: `http://backend/instances/default/private/reserves/${pub}`,
});
+export const API_GET_TIP_BY_ID = (
+ pub: string
+): Query<
+ unknown,
+ MerchantBackend.Tips.TipDetails
+> => ({
+ get: `http://backend/instances/default/private/tips/${pub}`,
+});
+
+export const API_AUTHORIZE_TIP_FOR_RESERVE = (
+ pub: string
+): Query<
+ MerchantBackend.Tips.TipCreateRequest,
+ MerchantBackend.Tips.TipCreateConfirmation
+> => ({
+ post:
`http://backend/instances/default/private/reserves/${pub}/authorize-tip`,
+});
+
+export const API_AUTHORIZE_TIP: Query<
+ MerchantBackend.Tips.TipCreateRequest,
+ MerchantBackend.Tips.TipCreateConfirmation
+> = ({
+ post: `http://backend/instances/default/private/tips`,
+});
+
+
+export const API_DELETE_RESERVE = (
+ id: string
+): Query<unknown, unknown> => ({
+ delete: `http://backend/instances/default/private/reserves/${id}`,
+});
+
diff --git a/packages/merchant-backoffice/tests/hooks/swr/index.tsx
b/packages/merchant-backoffice/tests/hooks/swr/index.tsx
new file mode 100644
index 0000000..4451485
--- /dev/null
+++ b/packages/merchant-backoffice/tests/hooks/swr/index.tsx
@@ -0,0 +1,45 @@
+/*
+ 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 { ComponentChildren, h, VNode } from "preact";
+import { SWRConfig } from "swr";
+import { BackendContextProvider } from "../../../src/context/backend";
+import { InstanceContextProvider } from "../../../src/context/instance";
+
+interface TestingContextProps {
+ children?: ComponentChildren;
+}
+export function TestingContext({ children }: TestingContextProps): VNode {
+ return (
+ <BackendContextProvider defaultUrl="http://backend"; initialToken="token">
+ <InstanceContextProvider
+ value={{
+ token: "token",
+ id: "default",
+ admin: true,
+ changeToken: () => null,
+ }}
+ >
+ <SWRConfig value={{ provider: () => new Map() }}>{children}</SWRConfig>
+ </InstanceContextProvider>
+ </BackendContextProvider>
+ );
+}
diff --git a/packages/merchant-backoffice/tests/hooks/swr/order-create.test.tsx
b/packages/merchant-backoffice/tests/hooks/swr/order-create.test.tsx
deleted file mode 100644
index 4563acd..0000000
--- a/packages/merchant-backoffice/tests/hooks/swr/order-create.test.tsx
+++ /dev/null
@@ -1,139 +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 { 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,
- assertNoMoreRequestWereMade,
- assertNextRequest,
-} from "../../axiosMock";
-
-jest.mock("axios");
-
-describe("order api", () => {
- beforeEach(() => {
- jest
- .spyOn(backend, "useBackendContext")
- .mockImplementation(
- () => ({ url: "http://backend";, token: "token" } as any)
- );
- jest
- .spyOn(instance, "useInstanceContext")
- .mockImplementation(
- () => ({ token: "token", id: "default", admin: true } as any)
- );
- });
-
- it("should not have problem with cache after an creation", async () => {
- const env = new AxiosMockEnvironment();
- env.addRequestExpectation(API_LIST_ORDERS, {
- qparam: { delta: 0, paid: "yes" },
- response: {
- orders: [{ order_id: "1" } as
MerchantBackend.Orders.OrderHistoryEntry],
- },
- });
-
- env.addRequestExpectation(API_LIST_ORDERS, {
- qparam: { delta: -20, paid: "yes" },
- response: {
- orders: [{ order_id: "2" } as
MerchantBackend.Orders.OrderHistoryEntry],
- },
- });
-
- const newDate = (d: Date) => {
- console.log("new date", d);
- };
-
- const { result, waitForNextUpdate } = renderHook(() => {
- const query = useInstanceOrders({ paid: "yes" }, newDate);
- const api = useOrderAPI();
-
- return { query, api };
- }); // get products -> loading
-
- if (!result.current) {
- expect(result.current).toBeDefined();
- return;
- }
-
- expect(result.current.query.loading).toBeTruthy();
- await waitForNextUpdate();
- assertNextRequest(env);
- assertNextRequest(env);
- assertNoMoreRequestWereMade(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" }],
- });
-
- env.addRequestExpectation(API_CREATE_ORDER, {
- request: {
- order: { amount: "ARS:12", summary: "pay me" },
- },
- response: { order_id: "3" },
- });
-
- env.addRequestExpectation(API_LIST_ORDERS, {
- qparam: { delta: 0, paid: "yes" },
- response: {
- orders: [{ order_id: "1" } as any],
- },
- });
-
- env.addRequestExpectation(API_LIST_ORDERS, {
- qparam: { delta: -20, paid: "yes" },
- response: {
- orders: [{ order_id: "2" } as any, { order_id: "3" } as any],
- },
- });
-
- act(async () => {
- await result.current?.api.createOrder({
- order: { amount: "ARS:12", summary: "pay me" },
- } as any);
- });
-
- assertNextRequest(env); //post
- await waitForNextUpdate();
- assertNextRequest(env); //get
- assertNextRequest(env); //get
- assertNoMoreRequestWereMade(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" }, { order_id: "3" }],
- });
- });
-});
diff --git
a/packages/merchant-backoffice/tests/hooks/swr/order-pagination.test.tsx
b/packages/merchant-backoffice/tests/hooks/swr/order-pagination.test.tsx
deleted file mode 100644
index b29f057..0000000
--- a/packages/merchant-backoffice/tests/hooks/swr/order-pagination.test.tsx
+++ /dev/null
@@ -1,126 +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 { act, renderHook } from "@testing-library/preact-hooks";
-import * as backend from "../../../src/context/backend";
-import * as instance from "../../../src/context/instance";
-import { useInstanceOrders } from "../../../src/hooks/order";
-import {
- API_LIST_ORDERS,
- AxiosMockEnvironment,
- assertNoMoreRequestWereMade,
- assertNextRequest,
-} from "../../axiosMock";
-
-jest.mock("axios");
-
-describe("order pagination", () => {
- beforeEach(() => {
- jest
- .spyOn(backend, "useBackendContext")
- .mockImplementation(
- () => ({ url: "http://backend";, token: "token" } as any)
- );
- jest
- .spyOn(instance, "useInstanceContext")
- .mockImplementation(
- () => ({ token: "token", id: "default", admin: true } as any)
- );
- });
-
- it("should change pagination", async () => {
- const env = new AxiosMockEnvironment();
- env.addRequestExpectation(API_LIST_ORDERS, {
- qparam: { delta: 20, wired: "yes", date_ms: 12 },
- response: {
- orders: [{ order_id: "1" } as any],
- },
- });
-
- env.addRequestExpectation(API_LIST_ORDERS, {
- qparam: { delta: -20, wired: "yes", date_ms: 13 },
- response: {
- orders: [{ order_id: "2" } as any],
- },
- });
-
- const newDate = (d: Date) => {
- console.log("new date", d);
- };
-
- const date = new Date(12);
- const { result, waitForNextUpdate } = renderHook(() =>
- useInstanceOrders({ wired: "yes", date }, newDate)
- );
-
- assertNextRequest(env);
- assertNextRequest(env);
- assertNoMoreRequestWereMade(env);
-
- await waitForNextUpdate();
-
- expect(result.current?.ok).toBeTruthy();
- if (!result.current?.ok) return;
-
- expect(result.current.data).toEqual({
- orders: [{ order_id: "1" }, { order_id: "2" }],
- });
-
- env.addRequestExpectation(API_LIST_ORDERS, {
- qparam: { delta: -40, wired: "yes", date_ms: 13 },
- response: {
- orders: [{ order_id: "2" } as any, { order_id: "3" } as any],
- },
- });
-
- await act(() => {
- if (!result.current?.ok) throw Error("not ok");
- result.current.loadMore();
- });
- await waitForNextUpdate();
-
- assertNextRequest(env);
- assertNoMoreRequestWereMade(env);
-
- env.addRequestExpectation(API_LIST_ORDERS, {
- qparam: { delta: 40, wired: "yes", date_ms: 12 },
- response: {
- orders: [{ order_id: "1" } as any, { order_id: "0" } as any],
- },
- });
- await act(() => {
- if (!result.current?.ok) throw Error("not ok");
- result.current.loadMorePrev();
- });
- await waitForNextUpdate();
- assertNextRequest(env);
- assertNoMoreRequestWereMade(env);
-
- expect(result.current.data).toEqual({
- orders: [
- { order_id: "0" },
- { order_id: "1" },
- { order_id: "2" },
- { order_id: "3" },
- ],
- });
- });
-});
diff --git a/packages/merchant-backoffice/tests/hooks/swr/order.test.ts
b/packages/merchant-backoffice/tests/hooks/swr/order.test.ts
new file mode 100644
index 0000000..e7f6c93
--- /dev/null
+++ b/packages/merchant-backoffice/tests/hooks/swr/order.test.ts
@@ -0,0 +1,567 @@
+/*
+ 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 } from "@testing-library/preact-hooks";
+import { act } from "preact/test-utils";
+import { TestingContext } from ".";
+import { MerchantBackend } from "../../../src/declaration";
+import { useInstanceOrders, useOrderAPI, useOrderDetails } from
"../../../src/hooks/order";
+import {
+ API_CREATE_ORDER,
+ API_DELETE_ORDER,
+ API_FORGET_ORDER_BY_ID,
+ API_GET_ORDER_BY_ID,
+ API_LIST_ORDERS, API_REFUND_ORDER_BY_ID, assertJustExpectedRequestWereMade,
assertNextRequest, assertNoMoreRequestWereMade, AxiosMockEnvironment
+} from "../../axiosMock";
+
+describe("order api interaction with listing", () => {
+
+ it("should evict cache when creating an order", async () => {
+ const env = new AxiosMockEnvironment();
+
+ env.addRequestExpectation(API_LIST_ORDERS, {
+ qparam: { delta: 0, paid: "yes" },
+ response: {
+ orders: [{ order_id: "1" } as
MerchantBackend.Orders.OrderHistoryEntry],
+ },
+ });
+
+ env.addRequestExpectation(API_LIST_ORDERS, {
+ qparam: { delta: -20, paid: "yes" },
+ response: {
+ orders: [{ order_id: "2" } as
MerchantBackend.Orders.OrderHistoryEntry],
+ },
+ });
+
+
+ const { result, waitForNextUpdate } = renderHook(() => {
+ const newDate = (d: Date) => {
+ console.log("new date", d);
+ };
+ const query = useInstanceOrders({ paid: "yes" }, newDate);
+ const api = useOrderAPI();
+
+ return { query, api };
+ }, { wrapper: TestingContext });
+
+ if (!result.current) {
+ expect(result.current).toBeDefined();
+ return;
+ }
+
+ expect(result.current.query.loading).toBeTruthy();
+ await waitForNextUpdate({ timeout: 1 });
+ 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" }],
+ });
+
+ env.addRequestExpectation(API_CREATE_ORDER, {
+ request: {
+ order: { amount: "ARS:12", summary: "pay me" },
+ },
+ response: { order_id: "3" },
+ });
+
+ env.addRequestExpectation(API_LIST_ORDERS, {
+ qparam: { delta: 0, paid: "yes" },
+ response: {
+ orders: [{ order_id: "1" } as any],
+ },
+ });
+
+ env.addRequestExpectation(API_LIST_ORDERS, {
+ qparam: { delta: -20, paid: "yes" },
+ response: {
+ orders: [{ order_id: "2" } as any, { order_id: "3" } as any],
+ },
+ });
+
+ act(async () => {
+ await result.current?.api.createOrder({
+ order: { amount: "ARS:12", summary: "pay me" },
+ } as any);
+ });
+
+ await waitForNextUpdate({ timeout: 1 });
+ 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" }, { order_id: "3" }],
+ });
+ });
+ it("should evict cache when doing a refund", async () => {
+ const env = new AxiosMockEnvironment();
+
+ env.addRequestExpectation(API_LIST_ORDERS, {
+ qparam: { delta: 0, paid: "yes" },
+ response: {
+ orders: [{ order_id: "1", amount: 'EUR:12', refundable: true } as
MerchantBackend.Orders.OrderHistoryEntry],
+ },
+ });
+
+ env.addRequestExpectation(API_LIST_ORDERS, {
+ qparam: { delta: -20, paid: "yes" },
+ response: { orders: [], },
+ });
+
+
+ const { result, waitForNextUpdate } = renderHook(() => {
+ const newDate = (d: Date) => {
+ console.log("new date", d);
+ };
+ const query = useInstanceOrders({ paid: "yes" }, newDate);
+ const api = useOrderAPI();
+
+ return { query, api };
+ }, { wrapper: TestingContext });
+
+ if (!result.current) {
+ expect(result.current).toBeDefined();
+ return;
+ }
+
+ expect(result.current.query.loading).toBeTruthy();
+ await waitForNextUpdate({ timeout: 1 });
+ 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",
+ amount: 'EUR:12',
+ refundable: true,
+ }],
+ });
+
+ env.addRequestExpectation(API_REFUND_ORDER_BY_ID('1'), {
+ request: {
+ reason: 'double pay',
+ refund: 'EUR:1'
+ },
+ });
+
+ env.addRequestExpectation(API_LIST_ORDERS, {
+ qparam: { delta: 0, paid: "yes" },
+ response: {
+ orders: [{ order_id: "1", amount: 'EUR:12', refundable: false } as
any],
+ },
+ });
+
+ env.addRequestExpectation(API_LIST_ORDERS, {
+ qparam: { delta: -20, paid: "yes" },
+ response: { orders: [], },
+ });
+
+ act(async () => {
+ await result.current?.api.refundOrder('1', {
+ reason: 'double pay',
+ refund: 'EUR:1'
+ });
+ });
+
+ await waitForNextUpdate({ timeout: 1 });
+ 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",
+ amount: 'EUR:12',
+ refundable: false,
+ }],
+ });
+ });
+ it("should evict cache when deleting an order", async () => {
+ const env = new AxiosMockEnvironment();
+
+ env.addRequestExpectation(API_LIST_ORDERS, {
+ qparam: { delta: 0, paid: "yes" },
+ response: {
+ orders: [{ order_id: "1" } as
MerchantBackend.Orders.OrderHistoryEntry],
+ },
+ });
+
+ env.addRequestExpectation(API_LIST_ORDERS, {
+ qparam: { delta: -20, paid: "yes" },
+ response: {
+ orders: [{ order_id: "2" } as
MerchantBackend.Orders.OrderHistoryEntry],
+ },
+ });
+
+
+ const { result, waitForNextUpdate } = renderHook(() => {
+ const newDate = (d: Date) => {
+ console.log("new date", d);
+ };
+ const query = useInstanceOrders({ paid: "yes" }, newDate);
+ const api = useOrderAPI();
+
+ return { query, api };
+ }, { wrapper: TestingContext });
+
+ if (!result.current) {
+ expect(result.current).toBeDefined();
+ return;
+ }
+
+ expect(result.current.query.loading).toBeTruthy();
+ await waitForNextUpdate({ timeout: 1 });
+ 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" }],
+ });
+
+ env.addRequestExpectation(API_DELETE_ORDER('1'), {});
+
+ env.addRequestExpectation(API_LIST_ORDERS, {
+ qparam: { delta: 0, paid: "yes" },
+ response: {
+ orders: [],
+ },
+ });
+
+ env.addRequestExpectation(API_LIST_ORDERS, {
+ qparam: { delta: -20, paid: "yes" },
+ response: {
+ orders: [{ order_id: "2" } as any],
+ },
+ });
+
+ act(async () => {
+ await result.current?.api.deleteOrder('1');
+ });
+
+ await waitForNextUpdate({ timeout: 1 });
+ 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: "2" }],
+ });
+ });
+
+});
+
+describe("order api interaction with details", () => {
+
+ it("should evict cache when doing a refund", async () => {
+ const env = new AxiosMockEnvironment();
+
+ env.addRequestExpectation(API_GET_ORDER_BY_ID('1'), {
+ // qparam: { delta: 0, paid: "yes" },
+ response: {
+ summary: 'description',
+ refund_amount: 'EUR:0',
+ } as unknown as MerchantBackend.Orders.CheckPaymentPaidResponse,
+ });
+
+ const { result, waitForNextUpdate } = renderHook(() => {
+ const query = useOrderDetails('1')
+ const api = useOrderAPI();
+
+ return { query, api };
+ }, { wrapper: TestingContext });
+
+ if (!result.current) {
+ expect(result.current).toBeDefined();
+ return;
+ }
+
+ expect(result.current.query.loading).toBeTruthy();
+ await waitForNextUpdate({ timeout: 1 });
+ 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({
+ summary: 'description',
+ refund_amount: 'EUR:0',
+ });
+
+ env.addRequestExpectation(API_REFUND_ORDER_BY_ID('1'), {
+ request: {
+ reason: 'double pay',
+ refund: 'EUR:1'
+ },
+ });
+
+ env.addRequestExpectation(API_GET_ORDER_BY_ID('1'), {
+ response: {
+ summary: 'description',
+ refund_amount: 'EUR:1',
+ } as unknown as MerchantBackend.Orders.CheckPaymentPaidResponse,
+ });
+
+ act(async () => {
+ await result.current?.api.refundOrder('1', {
+ reason: 'double pay',
+ refund: 'EUR:1'
+ });
+ });
+
+ await waitForNextUpdate({ timeout: 1 });
+ 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({
+ summary: 'description',
+ refund_amount: 'EUR:1',
+ });
+ })
+ it("should evict cache when doing a forget", async () => {
+ const env = new AxiosMockEnvironment();
+
+ env.addRequestExpectation(API_GET_ORDER_BY_ID('1'), {
+ // qparam: { delta: 0, paid: "yes" },
+ response: {
+ summary: 'description',
+ refund_amount: 'EUR:0',
+ } as unknown as MerchantBackend.Orders.CheckPaymentPaidResponse,
+ });
+
+ const { result, waitForNextUpdate } = renderHook(() => {
+ const query = useOrderDetails('1')
+ const api = useOrderAPI();
+
+ return { query, api };
+ }, { wrapper: TestingContext });
+
+ if (!result.current) {
+ expect(result.current).toBeDefined();
+ return;
+ }
+
+ expect(result.current.query.loading).toBeTruthy();
+ await waitForNextUpdate({ timeout: 1 });
+ 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({
+ summary: 'description',
+ refund_amount: 'EUR:0',
+ });
+
+ env.addRequestExpectation(API_FORGET_ORDER_BY_ID('1'), {
+ request: {
+ fields: ['$.summary']
+ },
+ });
+
+ env.addRequestExpectation(API_GET_ORDER_BY_ID('1'), {
+ response: {
+ summary: undefined,
+ } as unknown as MerchantBackend.Orders.CheckPaymentPaidResponse,
+ });
+
+ act(async () => {
+ await result.current?.api.forgetOrder('1', {
+ fields: ['$.summary']
+ });
+ });
+
+ await waitForNextUpdate({ timeout: 1 });
+ 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({
+ summary: undefined,
+ });
+ })
+})
+
+describe("order listing pagination", () => {
+
+ it("should not load more if has reach the end", async () => {
+ const env = new AxiosMockEnvironment();
+ env.addRequestExpectation(API_LIST_ORDERS, {
+ qparam: { delta: 20, wired: "yes", date_ms: 12 },
+ response: {
+ orders: [{ order_id: "1" } as any],
+ },
+ });
+
+ env.addRequestExpectation(API_LIST_ORDERS, {
+ qparam: { delta: -20, wired: "yes", date_ms: 13 },
+ response: {
+ orders: [{ order_id: "2" } as any],
+ },
+ });
+
+
+ const { result, waitForNextUpdate } = renderHook(() => {
+ const newDate = (d: Date) => {
+ console.log("new date", d);
+ };
+ const date = new Date(12);
+ const query = useInstanceOrders({ wired: "yes", date }, newDate)
+ return { query }
+ }, { wrapper: TestingContext });
+
+ assertJustExpectedRequestWereMade(env);
+
+ await waitForNextUpdate();
+
+ 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" }],
+ });
+
+ expect(result.current.query.isReachingEnd).toBeTruthy()
+ expect(result.current.query.isReachingStart).toBeTruthy()
+
+ await act(() => {
+ if (!result.current?.query.ok) throw Error("not ok");
+ result.current.query.loadMore();
+ });
+ assertNoMoreRequestWereMade(env);
+
+ await act(() => {
+ if (!result.current?.query.ok) throw Error("not ok");
+ result.current.query.loadMorePrev();
+ });
+ assertNoMoreRequestWereMade(env);
+
+ expect(result.current.query.data).toEqual({
+ orders: [
+ { order_id: "1" },
+ { order_id: "2" },
+ ],
+ });
+ });
+
+ it("should load more if result brings more that PAGE_SIZE", async () => {
+ const env = new AxiosMockEnvironment();
+
+ const ordersFrom0to20 = Array.from({ length: 20 }).map((e, i) => ({
order_id: String(i) }))
+ const ordersFrom20to40 = Array.from({ length: 20 }).map((e, i) => ({
order_id: String(i + 20) }))
+ const ordersFrom20to0 = [...ordersFrom0to20].reverse()
+
+ env.addRequestExpectation(API_LIST_ORDERS, {
+ qparam: { delta: 20, wired: "yes", date_ms: 12 },
+ response: {
+ orders: ordersFrom0to20,
+ },
+ });
+
+ env.addRequestExpectation(API_LIST_ORDERS, {
+ qparam: { delta: -20, wired: "yes", date_ms: 13 },
+ response: {
+ orders: ordersFrom20to40,
+ },
+ });
+
+ const { result, waitForNextUpdate } = renderHook(() => {
+ const newDate = (d: Date) => {
+ console.log("new date", d);
+ };
+ const date = new Date(12);
+ const query = useInstanceOrders({ wired: "yes", date }, newDate)
+ return { query }
+ }, { wrapper: TestingContext });
+
+ assertJustExpectedRequestWereMade(env);
+
+ await waitForNextUpdate({ timeout: 1 });
+
+ expect(result.current?.query.ok).toBeTruthy();
+ if (!result.current?.query.ok) return;
+
+ expect(result.current.query.data).toEqual({
+ orders: [...ordersFrom20to0, ...ordersFrom20to40],
+ });
+
+ expect(result.current.query.isReachingEnd).toBeFalsy()
+ expect(result.current.query.isReachingStart).toBeFalsy()
+
+ env.addRequestExpectation(API_LIST_ORDERS, {
+ qparam: { delta: -40, wired: "yes", date_ms: 13 },
+ response: {
+ orders: [...ordersFrom20to40, { order_id: '41' }],
+ },
+ });
+
+ await act(() => {
+ if (!result.current?.query.ok) throw Error("not ok");
+ result.current.query.loadMore();
+ });
+ await waitForNextUpdate({ timeout: 1 });
+
+ assertJustExpectedRequestWereMade(env);
+
+ env.addRequestExpectation(API_LIST_ORDERS, {
+ qparam: { delta: 40, wired: "yes", date_ms: 12 },
+ response: {
+ orders: [...ordersFrom0to20, { order_id: '-1' }],
+ },
+ });
+
+ await act(() => {
+ if (!result.current?.query.ok) throw Error("not ok");
+ result.current.query.loadMorePrev();
+ });
+ await waitForNextUpdate({ timeout: 1 });
+ assertJustExpectedRequestWereMade(env);
+
+ expect(result.current.query.data).toEqual({
+ orders: [{ order_id: '-1' }, ...ordersFrom20to0, ...ordersFrom20to40, {
order_id: '41' }],
+ });
+ });
+
+
+});
diff --git
a/packages/merchant-backoffice/tests/hooks/swr/product-create.test.tsx
b/packages/merchant-backoffice/tests/hooks/swr/product-create.test.tsx
deleted file mode 100644
index 8b49b8d..0000000
--- a/packages/merchant-backoffice/tests/hooks/swr/product-create.test.tsx
+++ /dev/null
@@ -1,142 +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 { 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,
- assertJustExpectedRequestWereMade,
-} from "../../axiosMock";
-
-jest.mock("axios");
-
-describe("product create api", () => {
- beforeEach(() => {
- jest
- .spyOn(backend, "useBackendContext")
- .mockImplementation(
- () => ({ url: "http://backend";, token: "token" } as any)
- );
- jest
- .spyOn(instance, "useInstanceContext")
- .mockImplementation(
- () => ({ token: "token", id: "default", admin: true } as any)
- );
- });
-
- it("should not have problem with cache after an creation", async () => {
- const env = new AxiosMockEnvironment();
-
- env.addRequestExpectation(API_LIST_PRODUCTS, {
- response: {
- products: [{ product_id: "1234" }],
- },
- });
-
- env.addRequestExpectation(API_GET_PRODUCT_BY_ID("1234"), {
- response: { price: "ARS:33" } as MerchantBackend.Products.ProductDetail,
- });
-
- const { result, waitForNextUpdate } = renderHook(() => {
- const api = useProductAPI();
- const query = useInstanceProducts();
-
- return { query, api };
- });
- if (!result.current) {
- expect(result.current).toBeDefined();
- return;
- }
- expect(result.current.query.loading).toBeTruthy();
-
- await waitForNextUpdate(); // first query to list products
- expect(result.current.query.loading).toBeTruthy();
-
- await waitForNextUpdate(); // second query to get product details
- 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([
- { id: "1234", price: "ARS:33" },
- ]);
-
- env.addRequestExpectation(API_CREATE_PRODUCT, {
- request: {
- price: "ARS:3333",
- } as MerchantBackend.Products.ProductAddDetail,
- });
-
- act(async () => {
- return await result.current?.api.createProduct({
- price: "ARS:3333",
- } as any);
- });
-
- assertJustExpectedRequestWereMade(env);
-
- env.addRequestExpectation(API_LIST_PRODUCTS, {
- response: {
- products: [{ product_id: "1234" }, { product_id: "2222" }],
- },
- });
-
- env.addRequestExpectation(API_GET_PRODUCT_BY_ID("1234"), {
- response: { price: "ARS:33" } as MerchantBackend.Products.ProductDetail,
- });
- env.addRequestExpectation(API_GET_PRODUCT_BY_ID("1234"), {
- response: { price: "ARS:33" } as MerchantBackend.Products.ProductDetail,
- });
-
- env.addRequestExpectation(API_GET_PRODUCT_BY_ID("2222"), {
- response: { price: "ARS:3333" } as
MerchantBackend.Products.ProductDetail,
- });
- expect(result.current.query.loading).toBeFalsy();
-
- await waitForNextUpdate(); // loading product -> products
- await waitForNextUpdate(); // loading product -> products
-
- assertJustExpectedRequestWereMade(env);
-
- expect(result.current.query.loading).toBeFalsy();
- expect(result.current.query.ok).toBeTruthy();
-
- expect(result.current.query.data).toEqual([
- {
- id: "1234",
- price: "ARS:33",
- },
- {
- id: "2222",
- price: "ARS:3333",
- },
- ]);
- });
-});
diff --git
a/packages/merchant-backoffice/tests/hooks/swr/product-delete.test.tsx
b/packages/merchant-backoffice/tests/hooks/swr/product-delete.test.tsx
deleted file mode 100644
index 7586af4..0000000
--- a/packages/merchant-backoffice/tests/hooks/swr/product-delete.test.tsx
+++ /dev/null
@@ -1,120 +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 { 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,
- assertNextRequest,
- assertJustExpectedRequestWereMade,
-} from "../../axiosMock";
-
-jest.mock("axios");
-
-describe("product delete api", () => {
- beforeEach(() => {
- jest
- .spyOn(backend, "useBackendContext")
- .mockImplementation(
- () => ({ url: "http://backend";, token: "token" } as any)
- );
- jest
- .spyOn(instance, "useInstanceContext")
- .mockImplementation(
- () => ({ token: "token", id: "default", admin: true } as any)
- );
- });
-
- it("should not have problem with cache after a delete", async () => {
- const env = new AxiosMockEnvironment();
-
- env.addRequestExpectation(API_LIST_PRODUCTS, {
- response: {
- products: [{ product_id: "1234" }, { product_id: "2345" }],
- },
- });
-
- env.addRequestExpectation(API_GET_PRODUCT_BY_ID("1234"), {
- response: { price: "ARS:12" } as MerchantBackend.Products.ProductDetail,
- });
-
- env.addRequestExpectation(API_GET_PRODUCT_BY_ID("2345"), {
- response: { price: "ARS:23" } as MerchantBackend.Products.ProductDetail,
- });
-
- const { result, waitForNextUpdate } = renderHook(() => {
- const query = useInstanceProducts();
- const api = useProductAPI();
- return { query, api };
- });
-
- await waitForNextUpdate();
- await waitForNextUpdate();
- assertJustExpectedRequestWereMade(env);
-
- expect(result.current?.query.ok).toBeTruthy();
- if (!result.current?.query.ok) return;
-
- expect(result.current.query.data).toEqual([
- { id: "1234", price: "ARS:12" },
- { id: "2345", price: "ARS:23" },
- ]);
-
- env.addRequestExpectation(
- {
- delete: "http://backend/instances/default/private/products/1234";,
- },
- {}
- );
-
- env.addRequestExpectation(API_LIST_PRODUCTS, {
- response: {
- products: [{ product_id: "2345" }],
- },
- });
-
- env.addRequestExpectation(API_GET_PRODUCT_BY_ID("2345"), {
- response: { price: "ARS:23" } as MerchantBackend.Products.ProductDetail,
- });
-
- act(async () => {
- await result.current?.api.deleteProduct("1234");
- });
-
- assertNextRequest(env);
- await waitForNextUpdate();
- await waitForNextUpdate();
- assertJustExpectedRequestWereMade(env);
-
- expect(result.current.query.data).toEqual([
- {
- id: "2345",
- price: "ARS:23",
- },
- ]);
- });
-});
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
deleted file mode 100644
index 6b43520..0000000
---
a/packages/merchant-backoffice/tests/hooks/swr/product-details-update.test.tsx
+++ /dev/null
@@ -1,113 +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 { renderHook, act } 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 { useProductAPI, useProductDetails } from "../../../src/hooks/product";
-import {
- API_GET_PRODUCT_BY_ID,
- API_UPDATE_PRODUCT_BY_ID,
- AxiosMockEnvironment,
- assertNextRequest,
- assertJustExpectedRequestWereMade,
-} from "../../axiosMock";
-
-jest.mock("axios");
-
-describe("product details api", () => {
- beforeEach(() => {
- jest
- .spyOn(backend, "useBackendContext")
- .mockImplementation(
- () => ({ url: "http://backend";, token: "token" } as any)
- );
- jest
- .spyOn(instance, "useInstanceContext")
- .mockImplementation(
- () => ({ token: "token", id: "default", admin: true } as any)
- );
- });
-
- it("should not have problem with cache after an update", async () => {
- const env = new AxiosMockEnvironment();
-
- env.addRequestExpectation(API_GET_PRODUCT_BY_ID("12"), {
- response: {
- description: "this is a description",
- } as MerchantBackend.Products.ProductDetail,
- });
-
- const { result, waitForNextUpdate } = renderHook(() => {
- const query = useProductDetails("12");
- const api = useProductAPI();
- return { query, api };
- });
-
- if (!result.current) {
- expect(result.current).toBeDefined();
- return;
- }
- expect(result.current.query.loading).toBeTruthy();
- await waitForNextUpdate();
-
- 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({
- description: "this is a description",
- });
-
- env.addRequestExpectation(API_UPDATE_PRODUCT_BY_ID("12"), {
- request: { description: "other description" },
- });
-
- env.addRequestExpectation(API_GET_PRODUCT_BY_ID("12"), {
- response: {
- description: "other description",
- } as MerchantBackend.Products.ProductDetail,
- });
-
- act(async () => {
- return await result.current?.api.updateProduct("12", {
- description: "other description",
- } as any);
- });
-
- assertNextRequest(env);
- await waitForNextUpdate();
-
- 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({
- description: "other description",
- });
- });
-});
diff --git
a/packages/merchant-backoffice/tests/hooks/swr/product-update.test.tsx
b/packages/merchant-backoffice/tests/hooks/swr/product-update.test.tsx
deleted file mode 100644
index ca94367..0000000
--- a/packages/merchant-backoffice/tests/hooks/swr/product-update.test.tsx
+++ /dev/null
@@ -1,127 +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 { 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,
- assertJustExpectedRequestWereMade,
- assertNextRequest,
-} from "../../axiosMock";
-
-jest.mock("axios");
-
-describe("product list api", () => {
- beforeEach(() => {
- jest
- .spyOn(backend, "useBackendContext")
- .mockImplementation(
- () => ({ url: "http://backend";, token: "token" } as any)
- );
- jest
- .spyOn(instance, "useInstanceContext")
- .mockImplementation(
- () => ({ token: "token", id: "default", admin: true } as any)
- );
- });
-
- it("should not have problem with cache after an update", async () => {
- const env = new AxiosMockEnvironment();
-
- env.addRequestExpectation(API_LIST_PRODUCTS, {
- response: {
- products: [{ product_id: "1234" }],
- },
- });
-
- env.addRequestExpectation(API_GET_PRODUCT_BY_ID("1234"), {
- response: { price: "ARS:12" } as MerchantBackend.Products.ProductDetail,
- });
-
- const { result, waitForNextUpdate } = renderHook(() => {
- const query = useInstanceProducts();
- const api = useProductAPI();
- return { api, query };
- }); // get products -> loading
-
- if (!result.current) {
- expect(result.current).toBeDefined();
- return;
- }
- expect(result.current.query.loading).toBeTruthy();
- await waitForNextUpdate();
-
- await waitForNextUpdate();
- 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([
- { id: "1234", price: "ARS:12" },
- ]);
-
- env.addRequestExpectation(API_UPDATE_PRODUCT_BY_ID("1234"), {
- request: { price: "ARS:13" },
- });
-
- env.addRequestExpectation(API_LIST_PRODUCTS, {
- response: {
- products: [{ product_id: "1234" }],
- },
- });
- env.addRequestExpectation(API_GET_PRODUCT_BY_ID("1234"), {
- response: { price: "ARS:13" } as MerchantBackend.Products.ProductDetail,
- });
-
- act(async () => {
- await result.current?.api.updateProduct("1234", {
- price: "ARS:13",
- } as any);
- });
-
- assertNextRequest(env);
- await waitForNextUpdate();
- // await waitForNextUpdate();
-
- assertJustExpectedRequestWereMade(env);
- // await waitForNextUpdate();
-
- expect(result.current.query.loading).toBeFalsy();
- expect(result.current?.query.ok).toBeTruthy();
- if (!result.current?.query.ok) return;
-
- expect(result.current.query.data).toEqual([
- {
- id: "1234",
- price: "ARS:13",
- },
- ]);
- });
-});
diff --git a/packages/merchant-backoffice/tests/hooks/swr/product.test.ts
b/packages/merchant-backoffice/tests/hooks/swr/product.test.ts
new file mode 100644
index 0000000..5d39a7c
--- /dev/null
+++ b/packages/merchant-backoffice/tests/hooks/swr/product.test.ts
@@ -0,0 +1,338 @@
+/*
+ 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 } from "@testing-library/preact-hooks";
+import { act } from "preact/test-utils";
+import { TestingContext } from ".";
+import { MerchantBackend } from "../../../src/declaration";
+import { useInstanceProducts, useProductAPI, useProductDetails } from
"../../../src/hooks/product";
+import {
+ API_CREATE_PRODUCT,
+ API_DELETE_PRODUCT, API_GET_PRODUCT_BY_ID,
+ API_LIST_PRODUCTS,
+ API_UPDATE_PRODUCT_BY_ID,
+ assertJustExpectedRequestWereMade,
+ assertNextRequest,
+ AxiosMockEnvironment
+} from "../../axiosMock";
+
+describe("product api interaction with listing ", () => {
+ it("should evict cache when creating a product", async () => {
+ const env = new AxiosMockEnvironment();
+
+ env.addRequestExpectation(API_LIST_PRODUCTS, {
+ response: {
+ products: [{ product_id: "1234" }],
+ },
+ });
+ env.addRequestExpectation(API_GET_PRODUCT_BY_ID("1234"), {
+ response: { price: "ARS:12" } as MerchantBackend.Products.ProductDetail,
+ });
+
+ const { result, waitForNextUpdate } = renderHook(
+ () => {
+ const query = useInstanceProducts();
+ const api = useProductAPI();
+ return { api, query };
+ },
+ { wrapper: TestingContext }
+ ); // get products -> loading
+
+ if (!result.current) {
+ expect(result.current).toBeDefined();
+ return;
+ }
+ expect(result.current.query.loading).toBeTruthy();
+ await waitForNextUpdate({ timeout: 1 });
+
+ await waitForNextUpdate({ timeout: 1 });
+ 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([
+ { id: "1234", price: "ARS:12" },
+ ]);
+
+ env.addRequestExpectation(API_CREATE_PRODUCT, {
+ request: { price: "ARS:23" } as
MerchantBackend.Products.ProductAddDetail,
+ });
+
+ env.addRequestExpectation(API_LIST_PRODUCTS, {
+ response: {
+ products: [{ product_id: "1234" }, { product_id: "2345" }],
+ },
+ });
+ env.addRequestExpectation(API_GET_PRODUCT_BY_ID("1234"), {
+ response: { price: "ARS:12" } as MerchantBackend.Products.ProductDetail,
+ });
+ env.addRequestExpectation(API_GET_PRODUCT_BY_ID("1234"), {
+ response: { price: "ARS:12" } as MerchantBackend.Products.ProductDetail,
+ });
+ env.addRequestExpectation(API_GET_PRODUCT_BY_ID("2345"), {
+ response: { price: "ARS:23" } as MerchantBackend.Products.ProductDetail,
+ });
+
+ act(async () => {
+ await result.current?.api.createProduct({
+ price: "ARS:23",
+ } as any);
+ });
+
+ assertNextRequest(env);
+ await waitForNextUpdate({ timeout: 1 });
+ await waitForNextUpdate({ timeout: 1 });
+
+ 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([
+ {
+ id: "1234",
+ price: "ARS:12",
+ },
+ {
+ id: "2345",
+ price: "ARS:23",
+ },
+ ]);
+ });
+
+ it("should evict cache when updating a product", async () => {
+ const env = new AxiosMockEnvironment();
+
+ env.addRequestExpectation(API_LIST_PRODUCTS, {
+ response: {
+ products: [{ product_id: "1234" }],
+ },
+ });
+ env.addRequestExpectation(API_GET_PRODUCT_BY_ID("1234"), {
+ response: { price: "ARS:12" } as MerchantBackend.Products.ProductDetail,
+ });
+
+ const { result, waitForNextUpdate } = renderHook(
+ () => {
+ const query = useInstanceProducts();
+ const api = useProductAPI();
+ return { api, query };
+ },
+ { wrapper: TestingContext }
+ ); // get products -> loading
+
+ if (!result.current) {
+ expect(result.current).toBeDefined();
+ return;
+ }
+ expect(result.current.query.loading).toBeTruthy();
+ await waitForNextUpdate({ timeout: 1 });
+
+ await waitForNextUpdate({ timeout: 1 });
+ 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([
+ { id: "1234", price: "ARS:12" },
+ ]);
+
+ env.addRequestExpectation(API_UPDATE_PRODUCT_BY_ID("1234"), {
+ request: { price: "ARS:13" } as
MerchantBackend.Products.ProductPatchDetail,
+ });
+
+ env.addRequestExpectation(API_LIST_PRODUCTS, {
+ response: {
+ products: [{ product_id: "1234" }],
+ },
+ });
+ env.addRequestExpectation(API_GET_PRODUCT_BY_ID("1234"), {
+ response: { price: "ARS:13" } as MerchantBackend.Products.ProductDetail,
+ });
+
+ act(async () => {
+ await result.current?.api.updateProduct("1234", {
+ price: "ARS:13",
+ } as any);
+ });
+
+ assertNextRequest(env);
+ await waitForNextUpdate({ timeout: 1 });
+
+ 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([
+ {
+ id: "1234",
+ price: "ARS:13",
+ },
+ ]);
+ });
+
+ it("should evict cache when deleting a product", async () => {
+ const env = new AxiosMockEnvironment();
+
+ env.addRequestExpectation(API_LIST_PRODUCTS, {
+ response: {
+ products: [{ product_id: "1234" }, { product_id: "2345" }],
+ },
+ });
+ env.addRequestExpectation(API_GET_PRODUCT_BY_ID("1234"), {
+ response: { price: "ARS:12" } as MerchantBackend.Products.ProductDetail,
+ });
+ env.addRequestExpectation(API_GET_PRODUCT_BY_ID("2345"), {
+ response: { price: "ARS:23" } as MerchantBackend.Products.ProductDetail,
+ });
+
+ const { result, waitForNextUpdate } = renderHook(
+ () => {
+ const query = useInstanceProducts();
+ const api = useProductAPI();
+ return { api, query };
+ },
+ { wrapper: TestingContext }
+ ); // get products -> loading
+
+ if (!result.current) {
+ expect(result.current).toBeDefined();
+ return;
+ }
+ expect(result.current.query.loading).toBeTruthy();
+ await waitForNextUpdate({ timeout: 1 });
+
+ await waitForNextUpdate({ timeout: 1 });
+ // await waitForNextUpdate({ timeout: 1 });
+ 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([
+ { id: "1234", price: "ARS:12" },
+ { id: "2345", price: "ARS:23" },
+ ]);
+
+ env.addRequestExpectation(API_DELETE_PRODUCT("2345"), {});
+
+ env.addRequestExpectation(API_LIST_PRODUCTS, {
+ response: {
+ products: [{ product_id: "1234" }],
+ },
+ });
+ env.addRequestExpectation(API_GET_PRODUCT_BY_ID("1234"), {
+ response: { price: "ARS:13" } as MerchantBackend.Products.ProductDetail,
+ });
+
+ act(async () => {
+ await result.current?.api.deleteProduct("2345");
+ });
+
+ assertNextRequest(env);
+ await waitForNextUpdate({ timeout: 1 });
+ await waitForNextUpdate({ timeout: 1 });
+
+ 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([
+ {
+ id: "1234",
+ price: "ARS:13",
+ },
+ ]);
+ });
+
+});
+
+describe("product api interaction with details", () => {
+ it("should evict cache when updating a product", async () => {
+ const env = new AxiosMockEnvironment();
+
+ env.addRequestExpectation(API_GET_PRODUCT_BY_ID("12"), {
+ response: {
+ description: "this is a description",
+ } as MerchantBackend.Products.ProductDetail,
+ });
+
+ const { result, waitForNextUpdate } = renderHook(() => {
+ const query = useProductDetails("12");
+ const api = useProductAPI();
+ return { query, api };
+ }, { wrapper: TestingContext });
+
+ if (!result.current) {
+ expect(result.current).toBeDefined();
+ return;
+ }
+ expect(result.current.query.loading).toBeTruthy();
+ await waitForNextUpdate();
+
+ 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({
+ description: "this is a description",
+ });
+
+ env.addRequestExpectation(API_UPDATE_PRODUCT_BY_ID("12"), {
+ request: { description: "other description" } as
MerchantBackend.Products.ProductPatchDetail,
+ });
+
+ env.addRequestExpectation(API_GET_PRODUCT_BY_ID("12"), {
+ response: {
+ description: "other description",
+ } as MerchantBackend.Products.ProductDetail,
+ });
+
+ act(async () => {
+ return await result.current?.api.updateProduct("12", {
+ description: "other description",
+ } as any);
+ });
+
+ assertNextRequest(env);
+ await waitForNextUpdate();
+
+ 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({
+ description: "other description",
+ });
+ })
+})
\ No newline at end of file
diff --git a/packages/merchant-backoffice/tests/hooks/swr/reserve.test.ts
b/packages/merchant-backoffice/tests/hooks/swr/reserve.test.ts
index 96810d3..c6c8818 100644
--- a/packages/merchant-backoffice/tests/hooks/swr/reserve.test.ts
+++ b/packages/merchant-backoffice/tests/hooks/swr/reserve.test.ts
@@ -21,34 +21,28 @@
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 {
useInstanceReserves,
- useReservesAPI
+ useReserveDetails,
+ useReservesAPI,
+ useTipDetails,
} from "../../../src/hooks/reserves";
import {
- API_CREATE_RESERVE, API_LIST_RESERVES, assertJustExpectedRequestWereMade,
AxiosMockEnvironment
+ API_AUTHORIZE_TIP,
+ API_AUTHORIZE_TIP_FOR_RESERVE,
+ API_CREATE_RESERVE,
+ API_DELETE_RESERVE,
+ API_GET_RESERVE_BY_ID,
+ API_GET_TIP_BY_ID,
+ API_LIST_RESERVES,
+ assertJustExpectedRequestWereMade,
+ AxiosMockEnvironment,
} from "../../axiosMock";
+import { TestingContext } from "./index";
-jest.mock("axios");
-
-describe("reserve api", () => {
- beforeEach(() => {
- jest
- .spyOn(backend, "useBackendContext")
- .mockImplementation(
- () => ({ url: "http://backend";, token: "token" } as any)
- );
- jest
- .spyOn(instance, "useInstanceContext")
- .mockImplementation(
- () => ({ token: "token", id: "default", admin: true } as any)
- );
- });
-
- it("should mutate list cache when creating a reserve", async () => {
+describe("reserve api interaction with listing ", () => {
+ it("should evict cache when creating a reserve", async () => {
const env = new AxiosMockEnvironment();
env.addRequestExpectation(API_LIST_RESERVES, {
@@ -61,12 +55,15 @@ describe("reserve api", () => {
},
});
- const { result, waitForNextUpdate } = renderHook(() => {
- const api = useReservesAPI();
- const query = useInstanceReserves();
+ const { result, waitForNextUpdate } = renderHook(
+ () => {
+ const api = useReservesAPI();
+ const query = useInstanceReserves();
- return { query, api };
- });
+ return { query, api };
+ },
+ { wrapper: TestingContext }
+ );
if (!result.current) {
expect(result.current).toBeDefined();
@@ -74,7 +71,7 @@ describe("reserve api", () => {
}
expect(result.current.query.loading).toBeTruthy();
- await waitForNextUpdate();
+ await waitForNextUpdate({ timeout: 1 });
assertJustExpectedRequestWereMade(env);
@@ -124,7 +121,7 @@ describe("reserve api", () => {
expect(result.current.query.loading).toBeFalsy();
- await waitForNextUpdate();
+ await waitForNextUpdate({ timeout: 1 });
assertJustExpectedRequestWereMade(env);
@@ -143,6 +140,331 @@ describe("reserve api", () => {
});
});
+ it("should evict cache when deleting a reserve", async () => {
+ const env = new AxiosMockEnvironment();
+
+ env.addRequestExpectation(API_LIST_RESERVES, {
+ response: {
+ reserves: [
+ {
+ reserve_pub: "11",
+ } as MerchantBackend.Tips.ReserveStatusEntry,
+ {
+ reserve_pub: "22",
+ } as MerchantBackend.Tips.ReserveStatusEntry,
+ {
+ reserve_pub: "33",
+ } as MerchantBackend.Tips.ReserveStatusEntry,
+ ],
+ },
+ });
+
+ const { result, waitForNextUpdate } = renderHook(
+ () => {
+ const api = useReservesAPI();
+ const query = useInstanceReserves();
+
+ return { query, api };
+ },
+ {
+ wrapper: TestingContext,
+ }
+ );
+
+ if (!result.current) {
+ expect(result.current).toBeDefined();
+ return;
+ }
+ expect(result.current.query.loading).toBeTruthy();
+
+ await waitForNextUpdate({ timeout: 1 });
+
+ 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({
+ reserves: [
+ { reserve_pub: "11" },
+ { reserve_pub: "22" },
+ { reserve_pub: "33" },
+ ],
+ });
+
+ env.addRequestExpectation(API_DELETE_RESERVE("11"), {});
+
+ act(async () => {
+ await result.current?.api.deleteReserve("11");
+ return;
+ });
+
+ assertJustExpectedRequestWereMade(env);
+
+ env.addRequestExpectation(API_LIST_RESERVES, {
+ response: {
+ reserves: [
+ {
+ reserve_pub: "22",
+ } as MerchantBackend.Tips.ReserveStatusEntry,
+ {
+ reserve_pub: "33",
+ } as MerchantBackend.Tips.ReserveStatusEntry,
+ ],
+ },
+ });
+
+ expect(result.current.query.loading).toBeFalsy();
+
+ await waitForNextUpdate({ timeout: 1 });
+
+ assertJustExpectedRequestWereMade(env);
+
+ expect(result.current.query.loading).toBeFalsy();
+ expect(result.current.query.ok).toBeTruthy();
+
+ expect(result.current.query.data).toEqual({
+ reserves: [
+ {
+ reserve_pub: "22",
+ } as MerchantBackend.Tips.ReserveStatusEntry,
+ {
+ reserve_pub: "33",
+ } as MerchantBackend.Tips.ReserveStatusEntry,
+ ],
+ });
+ });
+});
+
+describe("reserve api interaction with details", () => {
+ it("should evict cache when adding a tip for a specific reserve", async ()
=> {
+ const env = new AxiosMockEnvironment();
+
+ env.addRequestExpectation(API_GET_RESERVE_BY_ID("11"), {
+ response: {
+ payto_uri: "payto://here",
+ tips: [{ reason: "why?", tip_id: "id1", total_amount: "USD:10" }],
+ } as MerchantBackend.Tips.ReserveDetail,
+ });
+
+ const { result, waitForNextUpdate } = renderHook(
+ () => {
+ const api = useReservesAPI();
+ const query = useReserveDetails("11");
+
+ return { query, api };
+ },
+ {
+ wrapper: TestingContext,
+ }
+ );
+
+ if (!result.current) {
+ expect(result.current).toBeDefined();
+ return;
+ }
+ expect(result.current.query.loading).toBeTruthy();
+
+ await waitForNextUpdate({ timeout: 1 });
+
+ 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({
+ payto_uri: "payto://here",
+ tips: [{ reason: "why?", tip_id: "id1", total_amount: "USD:10" }],
+ });
+
+ env.addRequestExpectation(API_AUTHORIZE_TIP_FOR_RESERVE("11"), {
+ request: {
+ amount: "USD:12",
+ justification: "not",
+ next_url: "http://taler.net";,
+ },
+ response: {
+ tip_id: "id2",
+ taler_tip_uri: "uri",
+ tip_expiration: { t_ms: 1 },
+ tip_status_url: "url",
+ },
+ });
+
+ act(async () => {
+ await result.current?.api.authorizeTipReserve("11", {
+ amount: "USD:12",
+ justification: "not",
+ next_url: "http://taler.net";,
+ });
+ });
+
+ assertJustExpectedRequestWereMade(env);
+
+ expect(result.current.query.loading).toBeFalsy();
+
+ env.addRequestExpectation(API_GET_RESERVE_BY_ID("11"), {
+ response: {
+ payto_uri: "payto://here",
+ tips: [
+ { reason: "why?", tip_id: "id1", total_amount: "USD:10" },
+ { reason: "not", tip_id: "id2", total_amount: "USD:12" },
+ ],
+ } as MerchantBackend.Tips.ReserveDetail,
+ });
+
+ await waitForNextUpdate({ timeout: 1 });
+
+ assertJustExpectedRequestWereMade(env);
+
+ expect(result.current.query.loading).toBeFalsy();
+ expect(result.current.query.ok).toBeTruthy();
+
+ expect(result.current.query.data).toEqual({
+ payto_uri: "payto://here",
+ tips: [
+ { reason: "why?", tip_id: "id1", total_amount: "USD:10" },
+ { reason: "not", tip_id: "id2", total_amount: "USD:12" },
+ ],
+ });
+ });
+
+ it("should evict cache when adding a tip for a random reserve", async () => {
+ const env = new AxiosMockEnvironment();
+
+ env.addRequestExpectation(API_GET_RESERVE_BY_ID("11"), {
+ response: {
+ payto_uri: "payto://here",
+ tips: [{ reason: "why?", tip_id: "id1", total_amount: "USD:10" }],
+ } as MerchantBackend.Tips.ReserveDetail,
+ });
+
+ const { result, waitForNextUpdate } = renderHook(
+ () => {
+ const api = useReservesAPI();
+ const query = useReserveDetails("11");
+
+ return { query, api };
+ },
+ {
+ wrapper: TestingContext,
+ }
+ );
+
+ if (!result.current) {
+ expect(result.current).toBeDefined();
+ return;
+ }
+ expect(result.current.query.loading).toBeTruthy();
+
+ await waitForNextUpdate({ timeout: 1 });
+ 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({
+ payto_uri: "payto://here",
+ tips: [{ reason: "why?", tip_id: "id1", total_amount: "USD:10" }],
+ });
+
+ env.addRequestExpectation(API_AUTHORIZE_TIP, {
+ request: {
+ amount: "USD:12",
+ justification: "not",
+ next_url: "http://taler.net";,
+ },
+ response: {
+ tip_id: "id2",
+ taler_tip_uri: "uri",
+ tip_expiration: { t_ms: 1 },
+ tip_status_url: "url",
+ },
+ });
+
+ act(async () => {
+ await result.current?.api.authorizeTip({
+ amount: "USD:12",
+ justification: "not",
+ next_url: "http://taler.net";,
+ });
+ });
+
+ assertJustExpectedRequestWereMade(env);
+
+ expect(result.current.query.loading).toBeFalsy();
+
+ env.addRequestExpectation(API_GET_RESERVE_BY_ID("11"), {
+ response: {
+ payto_uri: "payto://here",
+ tips: [
+ { reason: "why?", tip_id: "id1", total_amount: "USD:10" },
+ { reason: "not", tip_id: "id2", total_amount: "USD:12" },
+ ],
+ } as MerchantBackend.Tips.ReserveDetail,
+ });
+
+ await waitForNextUpdate({ timeout: 1 });
+
+ assertJustExpectedRequestWereMade(env);
+
+ expect(result.current.query.loading).toBeFalsy();
+ expect(result.current.query.ok).toBeTruthy();
+
+ expect(result.current.query.data).toEqual({
+ payto_uri: "payto://here",
+ tips: [
+ { reason: "why?", tip_id: "id1", total_amount: "USD:10" },
+ { reason: "not", tip_id: "id2", total_amount: "USD:12" },
+ ],
+ });
+ });
+});
+
+describe("reserve api interaction with tip details", () => {
+ it("should list tips", async () => {
+ const env = new AxiosMockEnvironment();
+
+ env.addRequestExpectation(API_GET_TIP_BY_ID("11"), {
+ response: {
+ total_picked_up: "USD:12",
+ reason: "not",
+ } as MerchantBackend.Tips.TipDetails,
+ });
+
+ const { result, waitForNextUpdate } = renderHook(
+ () => {
+ // const api = useReservesAPI();
+ const query = useTipDetails("11");
+
+ return { query };
+ },
+ {
+ wrapper: TestingContext,
+ }
+ );
+
+ if (!result.current) {
+ expect(result.current).toBeDefined();
+ return;
+ }
+ expect(result.current.query.loading).toBeTruthy();
+
+ await waitForNextUpdate({ timeout: 1 });
+
+ 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({
+ total_picked_up: "USD:12",
+ reason: "not",
+ });
+ });
});
diff --git
a/packages/merchant-backoffice/tests/hooks/swr/transfer-pagination.test.tsx
b/packages/merchant-backoffice/tests/hooks/swr/transfer-pagination.test.tsx
deleted file mode 100644
index 34b4ce9..0000000
--- a/packages/merchant-backoffice/tests/hooks/swr/transfer-pagination.test.tsx
+++ /dev/null
@@ -1,120 +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 { act, renderHook } from "@testing-library/preact-hooks";
-import * as backend from "../../../src/context/backend";
-import * as instance from "../../../src/context/instance";
-import { useInstanceTransfers } from "../../../src/hooks/transfer";
-import {
- API_LIST_TRANSFERS,
- assertNextRequest,
- assertNoMoreRequestWereMade,
- AxiosMockEnvironment,
-} from "../../axiosMock";
-
-jest.mock("axios");
-
-describe("transfer pagination", () => {
- beforeEach(() => {
- jest
- .spyOn(backend, "useBackendContext")
- .mockImplementation(
- () => ({ url: "http://backend";, token: "token" } as any)
- );
- jest
- .spyOn(instance, "useInstanceContext")
- .mockImplementation(
- () => ({ token: "token", id: "default", admin: true } as any)
- );
- });
-
- it("should change pagination", async () => {
- const env = new AxiosMockEnvironment();
- env.addRequestExpectation(API_LIST_TRANSFERS, {
- qparam: { limit: 20, verified: "yes" },
- response: {
- transfers: [{ wtid: "1" } as any],
- },
- });
-
- env.addRequestExpectation(API_LIST_TRANSFERS, {
- qparam: { limit: -20, verified: "yes" },
- response: {
- transfers: [{ wtid: "3" } as any],
- },
- });
-
- const updatePosition = (d: string) => {
- console.log("updatePosition", d);
- };
-
- const { result, waitForNextUpdate } = renderHook(() =>
- useInstanceTransfers({ verified: "yes", position: "" }, updatePosition)
- );
-
- assertNextRequest(env);
- assertNextRequest(env);
- assertNoMoreRequestWereMade(env);
-
- await waitForNextUpdate(); // get info of every product, -> loading
-
- expect(result.current?.ok).toBeTruthy();
- if (!result.current?.ok) return;
-
- expect(result.current.data).toEqual({
- transfers: [{ wtid: "1" }, { wtid: "3" }],
- });
-
- env.addRequestExpectation(API_LIST_TRANSFERS, {
- qparam: { limit: -40, verified: "yes" },
- response: {
- transfers: [{ wtid: "4" } as any, { wtid: "3" } as any],
- },
- });
-
- await act(() => {
- if (!result.current?.ok) throw Error("not ok");
- result.current.loadMore();
- });
- await waitForNextUpdate();
- assertNextRequest(env);
- assertNoMoreRequestWereMade(env);
-
- env.addRequestExpectation(API_LIST_TRANSFERS, {
- qparam: { limit: 40, verified: "yes" },
- response: {
- transfers: [{ wtid: "1" } as any, { wtid: "2" } as any],
- },
- });
-
- await act(() => {
- if (!result.current?.ok) throw Error("not ok");
- result.current.loadMorePrev();
- });
- await waitForNextUpdate();
- assertNextRequest(env);
- assertNoMoreRequestWereMade(env);
-
- expect(result.current.data).toEqual({
- transfers: [{ wtid: "2" }, { wtid: "1" }, { wtid: "4" }, { wtid: "3" }],
- });
- });
-});
diff --git a/packages/merchant-backoffice/tests/hooks/swr/transfer.test.ts
b/packages/merchant-backoffice/tests/hooks/swr/transfer.test.ts
new file mode 100644
index 0000000..612cf88
--- /dev/null
+++ b/packages/merchant-backoffice/tests/hooks/swr/transfer.test.ts
@@ -0,0 +1,268 @@
+/*
+ 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 { act, renderHook } from "@testing-library/preact-hooks";
+import { TestingContext } from "./index";
+import { useInstanceTransfers, useTransferAPI } from
"../../../src/hooks/transfer";
+import {
+ API_INFORM_TRANSFERS,
+ API_LIST_TRANSFERS,
+ assertJustExpectedRequestWereMade,
+ assertNoMoreRequestWereMade,
+ AxiosMockEnvironment,
+} from "../../axiosMock";
+import { MerchantBackend } from "../../../src/declaration";
+
+describe("transfer api interaction with listing", () => {
+
+ it("should evict cache when informing a transfer", async () => {
+ const env = new AxiosMockEnvironment();
+
+ env.addRequestExpectation(API_LIST_TRANSFERS, {
+ qparam: { limit: 0 },
+ response: {
+ transfers: [{ wtid: "2" } as
MerchantBackend.Transfers.TransferDetails],
+ },
+ });
+ // FIXME: is this query really needed? if the hook is rendered without
+ // position argument then then backend is returning the newest and no need
+ // to this second query
+ env.addRequestExpectation(API_LIST_TRANSFERS, {
+ qparam: { limit: -20 },
+ response: {
+ transfers: [],
+ },
+ });
+
+ const { result, waitForNextUpdate } = renderHook(() => {
+ const moveCursor = (d: string) => {
+ console.log("new position", d);
+ };
+ const query = useInstanceTransfers({}, moveCursor);
+ const api = useTransferAPI();
+
+ return { query, api };
+ }, { wrapper: TestingContext });
+
+ if (!result.current) {
+ expect(result.current).toBeDefined();
+ return;
+ }
+
+ expect(result.current.query.loading).toBeTruthy();
+ await waitForNextUpdate({ timeout: 1 });
+ 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({
+ transfers: [{ wtid: "2" }],
+ });
+
+ env.addRequestExpectation(API_INFORM_TRANSFERS, {
+ request: {
+ wtid: '3',
+ credit_amount: 'EUR:1',
+ exchange_url: 'exchange.url',
+ payto_uri: 'payto://'
+ },
+ response: { total: '' } as any,
+ });
+
+ env.addRequestExpectation(API_LIST_TRANSFERS, {
+ qparam: { limit: 0 },
+ response: {
+ transfers: [{ wtid: "2" } as any, { wtid: "3" } as any],
+ },
+ });
+
+ env.addRequestExpectation(API_LIST_TRANSFERS, {
+ qparam: { limit: -20 },
+ response: {
+ transfers: [],
+ },
+ });
+
+ act(async () => {
+ await result.current?.api.informTransfer({
+ wtid: '3',
+ credit_amount: 'EUR:1',
+ exchange_url: 'exchange.url',
+ payto_uri: 'payto://'
+ });
+ });
+
+ await waitForNextUpdate({ timeout: 1 });
+ 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({
+ transfers: [{ wtid: "3" }, { wtid: "2" }],
+ });
+ });
+
+});
+
+describe("transfer listing pagination", () => {
+
+ it("should not load more if has reach the end", async () => {
+ const env = new AxiosMockEnvironment();
+ env.addRequestExpectation(API_LIST_TRANSFERS, {
+ qparam: { limit: 0, payto_uri: 'payto://' },
+ response: {
+ transfers: [{ wtid: "2" } as any],
+ },
+ });
+
+ env.addRequestExpectation(API_LIST_TRANSFERS, {
+ qparam: { limit: -20, payto_uri: 'payto://' },
+ response: {
+ transfers: [{ wtid: "1" } as any],
+ },
+ });
+
+
+ const { result, waitForNextUpdate } = renderHook(() => {
+ const moveCursor = (d: string) => {
+ console.log("new position", d);
+ };
+ const query = useInstanceTransfers({ payto_uri: 'payto://' }, moveCursor)
+ return { query }
+ }, { wrapper: TestingContext });
+
+ assertJustExpectedRequestWereMade(env);
+
+ await waitForNextUpdate();
+
+ expect(result.current?.query.ok).toBeTruthy();
+ if (!result.current?.query.ok) return;
+
+ expect(result.current.query.data).toEqual({
+ transfers: [{ wtid: "2" }, { wtid: "1" }],
+ });
+
+ expect(result.current.query.isReachingEnd).toBeTruthy()
+ expect(result.current.query.isReachingStart).toBeTruthy()
+
+ await act(() => {
+ if (!result.current?.query.ok) throw Error("not ok");
+ result.current.query.loadMore();
+ });
+ assertNoMoreRequestWereMade(env);
+
+ await act(() => {
+ if (!result.current?.query.ok) throw Error("not ok");
+ result.current.query.loadMorePrev();
+ });
+ assertNoMoreRequestWereMade(env);
+
+ expect(result.current.query.data).toEqual({
+ transfers: [
+ { wtid: "2" },
+ { wtid: "1" },
+ ],
+ });
+ });
+
+ it("should load more if result brings more that PAGE_SIZE", async () => {
+ const env = new AxiosMockEnvironment();
+
+ const transfersFrom0to20 = Array.from({ length: 20 }).map((e, i) => ({
wtid: String(i) }))
+ const transfersFrom20to40 = Array.from({ length: 20 }).map((e, i) => ({
wtid: String(i + 20) }))
+ const transfersFrom20to0 = [...transfersFrom0to20].reverse()
+
+ env.addRequestExpectation(API_LIST_TRANSFERS, {
+ qparam: { limit: 20, payto_uri: 'payto://' },
+ response: {
+ transfers: transfersFrom0to20,
+ },
+ });
+
+ env.addRequestExpectation(API_LIST_TRANSFERS, {
+ qparam: { limit: -20, payto_uri: 'payto://' },
+ response: {
+ transfers: transfersFrom20to40,
+ },
+ });
+
+ const { result, waitForNextUpdate } = renderHook(() => {
+ const moveCursor = (d: string) => {
+ console.log("new position", d);
+ };
+ const query = useInstanceTransfers({ payto_uri: 'payto://', position:
'1' }, moveCursor)
+ return { query }
+ }, { wrapper: TestingContext });
+
+ assertJustExpectedRequestWereMade(env);
+
+ await waitForNextUpdate({ timeout: 1 });
+
+ expect(result.current?.query.ok).toBeTruthy();
+ if (!result.current?.query.ok) return;
+
+ expect(result.current.query.data).toEqual({
+ transfers: [...transfersFrom20to0, ...transfersFrom20to40],
+ });
+
+ expect(result.current.query.isReachingEnd).toBeFalsy()
+ expect(result.current.query.isReachingStart).toBeFalsy()
+
+ env.addRequestExpectation(API_LIST_TRANSFERS, {
+ qparam: { limit: -40, payto_uri: 'payto://', offset: "1" },
+ response: {
+ transfers: [...transfersFrom20to40, { wtid: '41' }],
+ },
+ });
+
+ await act(() => {
+ if (!result.current?.query.ok) throw Error("not ok");
+ result.current.query.loadMore();
+ });
+ await waitForNextUpdate({ timeout: 1 });
+
+ assertJustExpectedRequestWereMade(env);
+
+ env.addRequestExpectation(API_LIST_TRANSFERS, {
+ qparam: { limit: 40, payto_uri: 'payto://', offset: "1" },
+ response: {
+ transfers: [...transfersFrom0to20, { wtid: '-1' }],
+ },
+ });
+
+ await act(() => {
+ if (!result.current?.query.ok) throw Error("not ok");
+ result.current.query.loadMorePrev();
+ });
+ await waitForNextUpdate({ timeout: 1 });
+ assertJustExpectedRequestWereMade(env);
+
+ expect(result.current.query.data).toEqual({
+ transfers: [{ wtid: '-1' }, ...transfersFrom20to0,
...transfersFrom20to40, { wtid: '41' }],
+ });
+ });
+
+
+});
--
To stop receiving notification emails like this one, please contact
gnunet@gnunet.org.
[Prev in Thread] |
Current Thread |
[Next in Thread] |
- [taler-merchant-backoffice] branch master updated: test case for orders, products, reserves and transfers,
gnunet <=