commit 7948aee7d14323946b29ccafc838edeb1190963a parent f3fdebec72279cffcb8bc8344857ffa5b56f76ca Author: Sebastian <sebasjm@gmail.com> Date: Thu, 9 Dec 2021 15:03:17 -0300 fixing hook testing Diffstat:
19 files changed, 682 insertions(+), 401 deletions(-)
diff --git a/packages/merchant-backoffice/src/components/product/ProductList.tsx b/packages/merchant-backoffice/src/components/product/ProductList.tsx @@ -13,10 +13,10 @@ 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 { Amounts } from "@gnu-taler/taler-util"; import { h, VNode } from "preact"; -import { MerchantBackend } from "../../declaration"; -import { AmountJson, Amounts } from "@gnu-taler/taler-util"; import emptyImage from "../../assets/empty.png"; +import { MerchantBackend } from "../../declaration"; import { Translate } from "../../i18n"; interface Props { diff --git a/packages/merchant-backoffice/src/hooks/admin.ts b/packages/merchant-backoffice/src/hooks/admin.ts @@ -15,10 +15,11 @@ */ import { MerchantBackend } from "../declaration"; import { useBackendContext } from "../context/backend"; -import { request, mutateAll } from "./backend"; +import { request, useMatchMutate } from "./backend"; export function useAdminAPI(): AdminAPI { const { url, token } = useBackendContext(); + const mutateAll = useMatchMutate(); const createInstance = async ( instance: MerchantBackend.Instances.InstanceConfigurationMessage diff --git a/packages/merchant-backoffice/src/hooks/backend.ts b/packages/merchant-backoffice/src/hooks/backend.ts @@ -19,22 +19,36 @@ * @author Sebastian Javier Marchano (sebasjm) */ -import { mutate, cache } from "swr"; +import { useSWRConfig } from "swr"; import axios, { AxiosError, AxiosResponse } from "axios"; import { MerchantBackend } from "../declaration"; import { useBackendContext } from "../context/backend"; import { useEffect, useState } from "preact/hooks"; import { DEFAULT_REQUEST_TIMEOUT } from "../utils/constants"; -export function mutateAll(re: RegExp, value?: unknown): Array<Promise<any>> { - return cache - .keys() - .filter((key) => { - return re.test(key); - }) - .map((key) => { - return mutate(key, value); +export function useMatchMutate(): ( + re: RegExp, + value?: unknown +) => Promise<any> { + const { cache, mutate } = useSWRConfig(); + + if (!(cache instanceof Map)) { + throw new Error( + "matchMutate requires the cache provider to be a Map instance" + ); + } + + return function matchRegexMutate(re: RegExp, value?: unknown) { + const allKeys = Array.from(cache.keys()); + // console.log(allKeys) + const keys = allKeys.filter((key) => re.test(key)); + // console.log(allKeys.length, keys.length) + const mutations = keys.map((key) => { + // console.log(key) + mutate(key, value, true); }); + return Promise.all(mutations); + }; } export type HttpResponse<T> = @@ -261,6 +275,14 @@ export async function request<T>( } } +export function multiFetcher<T>( + urls: string[], + token: string, + backend: string +): Promise<HttpResponseOk<T>[]> { + return Promise.all(urls.map((url) => fetcher<T>(url, token, backend))); +} + export function fetcher<T>( url: string, token: string, diff --git a/packages/merchant-backoffice/src/hooks/instance.ts b/packages/merchant-backoffice/src/hooks/instance.ts @@ -23,7 +23,7 @@ import { request, SwrError, } from "./backend"; -import useSWR, { mutate } from "swr"; +import useSWR, { useSWRConfig } from "swr"; import { useInstanceContext } from "../context/instance"; interface InstanceAPI { @@ -36,6 +36,7 @@ interface InstanceAPI { } export function useManagementAPI(instanceId: string): InstanceAPI { + const { mutate } = useSWRConfig(); const { url, token } = useBackendContext(); const updateInstance = async ( @@ -83,6 +84,7 @@ export function useManagementAPI(instanceId: string): InstanceAPI { } export function useInstanceAPI(): InstanceAPI { + const { mutate } = useSWRConfig(); const { url: baseUrl, token: adminToken } = useBackendContext(); const { token: instanceToken, id, admin } = useInstanceContext(); diff --git a/packages/merchant-backoffice/src/hooks/order.ts b/packages/merchant-backoffice/src/hooks/order.ts @@ -14,7 +14,7 @@ GNU Taler; see the file COPYING. If not, see <http://www.gnu.org/licenses/> */ import { useEffect, useState } from "preact/hooks"; -import useSWR from "swr"; +import useSWR, { useSWRConfig } from "swr"; import { useBackendContext } from "../context/backend"; import { useInstanceContext } from "../context/instance"; import { MerchantBackend } from "../declaration"; @@ -25,8 +25,8 @@ import { HttpResponse, HttpResponseOk, HttpResponsePaginated, - mutateAll, request, + useMatchMutate, } from "./backend"; export interface OrderAPI { @@ -72,6 +72,8 @@ export function orderFetcher<T>( } export function useOrderAPI(): OrderAPI { + const mutateAll = useMatchMutate(); + // const { mutate } = useSWRConfig(); const { url: baseUrl, token: adminToken } = useBackendContext(); const { token: instanceToken, id, admin } = useInstanceContext(); @@ -96,7 +98,8 @@ export function useOrderAPI(): OrderAPI { data, } ); - await mutateAll(/@"\/private\/orders"@/); + await mutateAll(/.*private\/orders.*/); + // mutate('') return res; }; const refundOrder = async ( diff --git a/packages/merchant-backoffice/src/hooks/product.ts b/packages/merchant-backoffice/src/hooks/product.ts @@ -14,7 +14,8 @@ GNU Taler; see the file COPYING. If not, see <http://www.gnu.org/licenses/> */ import { useEffect } from "preact/hooks"; -import useSWR, { trigger, useSWRInfinite, cache, mutate } from "swr"; +import useSWR, { useSWRConfig } from "swr"; +import useSWRInfinite, { SWRInfiniteConfiguration } from "swr/infinite"; import { useBackendContext } from "../context/backend"; // import { useFetchContext } from '../context/fetch'; import { useInstanceContext } from "../context/instance"; @@ -24,8 +25,9 @@ import { HttpError, HttpResponse, HttpResponseOk, - mutateAll, + multiFetcher, request, + useMatchMutate, } from "./backend"; export interface ProductAPI { @@ -44,6 +46,9 @@ export interface ProductAPI { } export function useProductAPI(): ProductAPI { + const mutateAll = useMatchMutate(); + const { mutate } = useSWRConfig(); + // const { mutate } = SWRInfiniteConfiguration(); const { url: baseUrl, token: adminToken } = useBackendContext(); const { token: instanceToken, id, admin } = useInstanceContext(); @@ -60,13 +65,13 @@ export function useProductAPI(): ProductAPI { const createProduct = async ( data: MerchantBackend.Products.ProductAddDetail ): Promise<void> => { - await request(`${url}/private/products`, { + const res = await request(`${url}/private/products`, { method: "post", token, data, }); - await mutateAll(/@"\/private\/products"@/, null); + return await mutateAll(/.*private\/products.*/); }; const updateProduct = async ( @@ -79,6 +84,10 @@ export function useProductAPI(): ProductAPI { data, }); + // await mutate([`/private/products`, token, url]) + // await mutate([`/private/products/${productId}`, token, url], undefined, true); + return await mutateAll(/.*"\/private\/products.*/); + return Promise.resolve(); /** * There is some inconsistency in how the cache is evicted. * I'm keeping this for later inspection @@ -114,12 +123,12 @@ export function useProductAPI(): ProductAPI { // await mutate([`/private/products/${productId}`, token, url]) // await mutateAll(/@"\/private\/products"@/); - await mutateAll(/@"\/private\/products\/.*"@/); + // await mutateAll(/@"\/private\/products\/.*"@/); // return true // return r // -- FIXME: why this un-break the tests? - return Promise.resolve(); + // return Promise.resolve() }; const deleteProduct = async (productId: string): Promise<void> => { @@ -127,8 +136,7 @@ export function useProductAPI(): ProductAPI { method: "delete", token, }); - - await mutateAll(/@"\/private\/products"@/); + await mutate([`/private/products`, token, url]); }; const lockProduct = async ( @@ -164,11 +172,7 @@ export function useInstanceProducts(): HttpResponse< token: instanceToken, }; - const { - data: list, - error: listError, - isValidating: listLoading, - } = useSWR< + const { data: list, error: listError } = useSWR< HttpResponseOk<MerchantBackend.Products.InventorySummaryResponse>, HttpError >([`/private/products`, token, url], fetcher, { @@ -179,42 +183,48 @@ export function useInstanceProducts(): HttpResponse< refreshWhenOffline: false, }); - const { - data: products, - error: productError, - setSize, - size, - } = useSWRInfinite< - HttpResponseOk<MerchantBackend.Products.ProductDetail>, - HttpError - >( - (pageIndex: number) => { - if (!list?.data || !list.data.products.length || listError || listLoading) - return null; - return [ - `/private/products/${list.data.products[pageIndex].product_id}`, - token, - url, - ]; - }, - fetcher, - { - revalidateAll: true, - } + // const dataLength = list?.data.products.length || 0 + // const prods: Array<MerchantBackend.Products.InventoryEntry>[] = [] + // prods[0] = list?.data.products || [] + + // const { data: products, error: productError, setSize } = useSWRInfinite<HttpResponseOk<MerchantBackend.Products.ProductDetail>, HttpError>((pageIndex: number) => { + // console.log('fetcher', prods[0], pageIndex) + // if (!list?.data || !prods[0].length || listError) return null + + // console.log(`/private/products/${prods[0][pageIndex].product_id}`) + // return [`/private/products/${prods[0][pageIndex].product_id}`, token, url] + // }, fetcher, { + // initialSize: dataLength, + // revalidateAll: true, + // }) + // [`/private/products`] + const paths = (list?.data.products || []).map( + (p) => `/private/products/${p.product_id}` ); + const { data: products, error: productError } = useSWR< + HttpResponseOk<MerchantBackend.Products.ProductDetail>[], + HttpError + >([paths, token, url], multiFetcher, { + refreshInterval: 0, + refreshWhenHidden: false, + revalidateOnFocus: false, + revalidateOnReconnect: false, + refreshWhenOffline: false, + }); - useEffect(() => { - if (list?.data && list.data.products.length > 0) { - setSize(list.data.products.length); - } - }, [list?.data.products.length, listLoading]); + // console.log('data length', dataLength, list?.data) + // useEffect(() => { + // if (dataLength > 0) { + // console.log('set size', dataLength) + // setSize(dataLength) + // } + // }, [dataLength, setSize]) - if (listLoading) return { loading: true, data: [] }; if (listError) return listError; if (productError) return productError; - if (list?.data && list.data.products.length === 0) { - return { ok: true, data: [] }; - } + // if (dataLength === 0) { + // return { ok: true, data: [] } + // } if (products) { const dataWithId = products.map((d) => { //take the id from the queried url @@ -223,6 +233,7 @@ export function useInstanceProducts(): HttpResponse< id: d.info?.url.replace(/.*\/private\/products\//, "") || "", }; }); + // console.log('data with id', dataWithId) return { ok: true, data: dataWithId }; } return { loading: true }; diff --git a/packages/merchant-backoffice/src/hooks/tips.ts b/packages/merchant-backoffice/src/hooks/tips.ts @@ -22,11 +22,12 @@ import { HttpError, HttpResponse, HttpResponseOk, - mutateAll, request, + useMatchMutate, } from "./backend"; export function useReservesAPI(): ReserveMutateAPI { + const mutateAll = useMatchMutate(); const { url: baseUrl, token: adminToken } = useBackendContext(); const { token: instanceToken, id, admin } = useInstanceContext(); diff --git a/packages/merchant-backoffice/src/hooks/transfer.ts b/packages/merchant-backoffice/src/hooks/transfer.ts @@ -17,11 +17,11 @@ import { MerchantBackend } from "../declaration"; import { useBackendContext } from "../context/backend"; import { request, - mutateAll, HttpResponse, HttpError, HttpResponseOk, HttpResponsePaginated, + useMatchMutate, } from "./backend"; import useSWR from "swr"; import { useInstanceContext } from "../context/instance"; @@ -54,6 +54,7 @@ async function transferFetcher<T>( } export function useTransferAPI(): TransferAPI { + const mutateAll = useMatchMutate(); const { url: baseUrl, token: adminToken } = useBackendContext(); const { token: instanceToken, id, admin } = useInstanceContext(); diff --git a/packages/merchant-backoffice/tests/axiosMock.ts b/packages/merchant-backoffice/tests/axiosMock.ts @@ -0,0 +1,216 @@ +/* + 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 * as axios from 'axios'; +import { MerchantBackend } from '../src/declaration'; +import { setAxiosRequestAsTestingEnvironment } from "../src/hooks/backend"; + +export type Query<Req, Res> = (GetQuery | PostQuery | DeleteQuery | PatchQuery) & RequestResponse<Req, Res> + +interface RequestResponse<Req, Res> { + code?: number, +} +interface GetQuery { get: string } +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) => { + if (JEST_DEBUG_LOG) { + console.log('UNEXPECTED QUERY', actualQuery) + } +} + +export class AxiosMockEnvironment { + expectations: Array<{ query: Query<any, any>, params?: { request?: any, qparam?: any, response?: any } } | undefined> = [] + axiosMock: jest.MockedFunction<axios.AxiosStatic> + + constructor() { + this.axiosMock = (axios.default as jest.MockedFunction<axios.AxiosStatic>).mockImplementation(defaultCallback as any) + } + + addRequestExpectation<RequestType, ResponseType>(expectedQuery?: Query<RequestType, ResponseType> | undefined, params?: { request?: RequestType, qparam?: any, response?: ResponseType }): void { + this.expectations.push(expectedQuery ? { query: expectedQuery, params } : undefined) + this.axiosMock = this.axiosMock.mockImplementationOnce(function (actualQuery?: axios.AxiosRequestConfig): axios.AxiosPromise { + + if (JEST_DEBUG_LOG) { + console.log('query to the backend is made', actualQuery) + } + if (!expectedQuery) { + return Promise.reject() + } + if (JEST_DEBUG_LOG) { + console.log('expected query:', params?.request) + console.log('expected qparams:', params?.qparam) + console.log('sending response:', params?.response) + } + + const responseCode = expectedQuery.code || 200 + + //This response is what buildRequestOk is expecting in file hook/backend.ts + if (responseCode >= 200 && responseCode < 300) { + return Promise.resolve({ + data: params?.response, config: { + data: params?.response, + params: actualQuery?.params || {}, + }, request: { params: actualQuery?.params || {} } + } as any); + } + //This response is what buildRequestFailed is expecting in file hook/backend.ts + return Promise.reject({ + response: { + status: responseCode + }, + request: { + data: params?.response, + params: actualQuery?.params || {}, + } + }) + + } as any) + } + + 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 + ] + } + +} + +export function testAllExpectedRequestAndNoMore(env: AxiosMockEnvironment): void { + let size = env.expectations.length + while (size-- > 0) { + testOneRequestToBackend(env) + } + testNoOtherRequestWasMade(env) +} + +export function testNoOtherRequestWasMade(env: AxiosMockEnvironment): void { + const [actualQuery, expectedQuery] = env.getLastTestValues() + + expect(actualQuery).toBeUndefined(); + expect(expectedQuery).toBeUndefined(); +} + +export function testOneRequestToBackend(env: AxiosMockEnvironment): void { + const [actualQuery, expectedQuery] = env.getLastTestValues() + + if (!actualQuery) { + expect(actualQuery).toBe(expectedQuery); + + // throw Error('actual query was undefined'); + return + } + + if (!expectedQuery) { + const errorMessage = 'a query was made to the backend but the test explicitly expected no query'; + if (JEST_DEBUG_LOG) { + console.log(errorMessage, actualQuery) + } + throw Error(errorMessage) + } + if ('get' in expectedQuery.query) { + expect(actualQuery.method).toBe('get'); + expect(actualQuery.url).toBe(expectedQuery.query.get); + } + if ('post' in expectedQuery.query) { + expect(actualQuery.method).toBe('post'); + expect(actualQuery.url).toBe(expectedQuery.query.post); + if (actualQuery.method !== 'post') throw Error('tu vieja') + } + if ('delete' in expectedQuery.query) { + expect(actualQuery.method).toBe('delete'); + expect(actualQuery.url).toBe(expectedQuery.query.delete); + } + if ('patch' in expectedQuery.query) { + expect(actualQuery.method).toBe('patch'); + expect(actualQuery.url).toBe(expectedQuery.query.patch); + } + + if (expectedQuery.params?.request) { + expect(actualQuery.data).toMatchObject(expectedQuery.params.request) + } + if (expectedQuery.params?.qparam) { + expect(actualQuery.params).toMatchObject(expectedQuery.params.qparam) + } + +} + +export const API_LIST_PRODUCTS: Query< + unknown, + MerchantBackend.Products.InventorySummaryResponse +> = { + get: "http://backend/instances/default/private/products", +}; + +export const API_LIST_ORDERS: Query< + unknown, + MerchantBackend.Orders.OrderHistory +> = { + get: "http://backend/instances/default/private/orders", +}; + +export const API_CREATE_PRODUCT: Query< + MerchantBackend.Products.ProductAddDetail, + unknown +> = { + post: "http://backend/instances/default/private/products", +}; + +export const API_CREATE_ORDER: Query< + MerchantBackend.Orders.PostOrderRequest, + MerchantBackend.Orders.PostOrderResponse +> = { + post: "http://backend/instances/default/private/orders", +}; + +export const API_GET_PRODUCT_BY_ID = ( + id: string +): Query<unknown, MerchantBackend.Products.InventorySummaryResponse> => ({ + get: `http://backend/instances/default/private/products/${id}`, +}); + +export const API_UPDATE_PRODUCT_BY_ID = ( + id: string +): Query< + Partial<MerchantBackend.Products.ProductPatchDetail>, + MerchantBackend.Products.InventorySummaryResponse +> => ({ + patch: `http://backend/instances/default/private/products/${id}`, +}); diff --git a/packages/merchant-backoffice/tests/declarations.d.ts b/packages/merchant-backoffice/tests/declarations.d.ts @@ -19,6 +19,10 @@ * @author Sebastian Javier Marchano (sebasjm) */ -// Enable enzyme adapter's integration with TypeScript -// See: https://github.com/preactjs/enzyme-adapter-preact-pure#usage-with-typescript -/// <reference types="enzyme-adapter-preact-pure" /> +declare global { + namespace jest { + interface Matchers<R> { + toBeWithinRange(a: number, b: number): R; + } + } +} diff --git a/packages/merchant-backoffice/tests/header.test.tsx b/packages/merchant-backoffice/tests/header.test.tsx @@ -22,17 +22,27 @@ import { h } from "preact"; import { ProductList } from "../src/components/product/ProductList"; // See: https://github.com/preactjs/enzyme-adapter-preact-pure -import { shallow } from "enzyme"; +// import { shallow } from 'enzyme'; import * as backend from "../src/context/config"; +import { render, findAllByText } from "@testing-library/preact"; +import * as i18n from "../src/context/translation"; + +import * as jedLib from "jed"; +const handler = new jedLib.Jed("en"); describe("Initial Test of the Sidebar", () => { beforeEach(() => { jest .spyOn(backend, "useConfigContext") .mockImplementation(() => ({ version: "", currency: "" })); + jest.spyOn(i18n, "useTranslationContext").mockImplementation(() => ({ + changeLanguage: () => null, + handler, + lang: "en", + })); }); test("Product list renders a table", () => { - const context = shallow( + const context = render( <ProductList list={[ { @@ -47,7 +57,7 @@ describe("Initial Test of the Sidebar", () => { /> ); - expect(context.find("table")).toBeDefined(); + expect(context.findAllByText("description of the product")).toBeDefined(); // expect(context.find('table tr td img').map(img => img.prop('src'))).toEqual(''); }); }); diff --git a/packages/merchant-backoffice/tests/hooks/swr/order-create.test.tsx b/packages/merchant-backoffice/tests/hooks/swr/order-create.test.tsx @@ -20,15 +20,17 @@ */ import { renderHook } from "@testing-library/preact-hooks"; -import * as axios from "axios"; +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 { setAxiosRequestAsTestingEnvironment } from "../../../src/hooks/backend"; import { useInstanceOrders, useOrderAPI } from "../../../src/hooks/order"; -import { simulateBackendResponse } from "../../util"; - -setAxiosRequestAsTestingEnvironment(); +import { + API_CREATE_ORDER, + API_LIST_ORDERS, + AxiosMockEnvironment, + testNoOtherRequestWasMade, + testOneRequestToBackend, +} from "../../axiosMock"; jest.mock("axios"); @@ -47,19 +49,18 @@ describe("order api", () => { }); it("should not have problem with cache after an creation", async () => { - simulateBackendResponse<unknown, MerchantBackend.Orders.OrderHistory>({ - get: "http://backend/instances/default/private/orders", - params: { delta: 0, paid: "yes" }, + const env = new AxiosMockEnvironment(); + env.addRequestExpectation(API_LIST_ORDERS, { + qparam: { delta: 0, paid: "yes" }, response: { - orders: [{ order_id: "1" } as any], + orders: [{ order_id: "1" }], }, }); - simulateBackendResponse<unknown, MerchantBackend.Orders.OrderHistory>({ - get: "http://backend/instances/default/private/orders", - params: { delta: -20, paid: "yes" }, + env.addRequestExpectation(API_LIST_ORDERS, { + qparam: { delta: -20, paid: "yes" }, response: { - orders: [{ order_id: "2" } as any], + orders: [{ order_id: "2" }], }, }); @@ -67,58 +68,70 @@ describe("order api", () => { console.log("new date", d); }; - const { result, waitForNextUpdate } = renderHook(() => - useInstanceOrders({ paid: "yes" }, newDate) - ); // get products -> loading + 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; + } - await waitForNextUpdate(); // get info of every product, -> loading - await waitForNextUpdate(); // loading product -> products - // await waitForNextUpdate(); // loading product -> products + expect(result.current.query.loading).toBeTruthy(); + await waitForNextUpdate(); + testOneRequestToBackend(env); + testOneRequestToBackend(env); + testNoOtherRequestWasMade(env); - expect(result.current?.ok).toBeTruthy(); - if (!result.current?.ok) return; + expect(result.current.query.loading).toBeFalsy(); + expect(result.current?.query.ok).toBeTruthy(); + if (!result.current?.query.ok) return; - expect(result.current.data).toEqual({ + expect(result.current.query.data).toEqual({ orders: [{ order_id: "1" }, { order_id: "2" }], }); - const { createOrder } = useOrderAPI(); - - simulateBackendResponse< - MerchantBackend.Orders.PostOrderRequest, - MerchantBackend.Orders.PostOrderResponse - >({ - post: "http://backend/instances/default/private/orders", + env.addRequestExpectation(API_CREATE_ORDER, { request: { order: { amount: "ARS:12", summary: "pay me" }, }, response: { order_id: "3" }, }); - simulateBackendResponse<unknown, MerchantBackend.Orders.OrderHistory>({ - get: "http://backend/instances/default/private/orders", - params: { delta: 0, paid: "yes" }, + env.addRequestExpectation(API_LIST_ORDERS, { + qparam: { delta: 0, paid: "yes" }, response: { orders: [{ order_id: "1" } as any], }, }); - simulateBackendResponse<unknown, MerchantBackend.Orders.OrderHistory>({ - get: "http://backend/instances/default/private/orders", - params: { delta: -20, paid: "yes" }, + env.addRequestExpectation(API_LIST_ORDERS, { + qparam: { delta: -20, paid: "yes" }, response: { orders: [{ order_id: "2" } as any, { order_id: "3" } as any], }, }); - await createOrder({ - order: { amount: "ARS:12", summary: "pay me" }, - } as any); + act(async () => { + await result.current?.api.createOrder({ + order: { amount: "ARS:12", summary: "pay me" }, + } as any); + }); + + testOneRequestToBackend(env); //post + await waitForNextUpdate(); + testOneRequestToBackend(env); //get + testOneRequestToBackend(env); //get + testNoOtherRequestWasMade(env); - await waitForNextUpdate(); // loading product -> products - await waitForNextUpdate(); // loading product -> products + expect(result.current.query.loading).toBeFalsy(); + expect(result.current?.query.ok).toBeTruthy(); + if (!result.current?.query.ok) return; - expect(result.current.data).toEqual({ + 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 @@ -20,13 +20,17 @@ */ import { act, renderHook } from "@testing-library/preact-hooks"; -import * as axios from "axios"; import * as backend from "../../../src/context/backend"; import * as instance from "../../../src/context/instance"; import { MerchantBackend } from "../../../src/declaration"; import { setAxiosRequestAsTestingEnvironment } from "../../../src/hooks/backend"; import { useInstanceOrders } from "../../../src/hooks/order"; -import { simulateBackendResponse } from "../../util"; +import { + API_LIST_ORDERS, + AxiosMockEnvironment, + testNoOtherRequestWasMade, + testOneRequestToBackend, +} from "../../axiosMock"; setAxiosRequestAsTestingEnvironment(); @@ -47,17 +51,16 @@ describe("order pagination", () => { }); it("should change pagination", async () => { - simulateBackendResponse<unknown, MerchantBackend.Orders.OrderHistory>({ - get: "http://backend/instances/default/private/orders", - params: { delta: 20, wired: "yes", date_ms: 12 }, + const env = new AxiosMockEnvironment(); + env.addRequestExpectation(API_LIST_ORDERS, { + qparam: { delta: 20, wired: "yes", date_ms: 12 }, response: { orders: [{ order_id: "1" } as any], }, }); - simulateBackendResponse<unknown, MerchantBackend.Orders.OrderHistory>({ - get: "http://backend/instances/default/private/orders", - params: { delta: -20, wired: "yes", date_ms: 13 }, + env.addRequestExpectation(API_LIST_ORDERS, { + qparam: { delta: -20, wired: "yes", date_ms: 13 }, response: { orders: [{ order_id: "2" } as any], }, @@ -72,6 +75,10 @@ describe("order pagination", () => { useInstanceOrders({ wired: "yes", date }, newDate) ); // get products -> loading + testOneRequestToBackend(env); + testOneRequestToBackend(env); + testNoOtherRequestWasMade(env); + await waitForNextUpdate(); // get info of every product, -> loading expect(result.current?.ok).toBeTruthy(); @@ -81,23 +88,24 @@ describe("order pagination", () => { orders: [{ order_id: "1" }, { order_id: "2" }], }); - simulateBackendResponse<unknown, MerchantBackend.Orders.OrderHistory>({ - get: "http://backend/instances/default/private/orders", - params: { delta: -40, wired: "yes", date_ms: 13 }, + 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(); // loading product -> products // await waitForNextUpdate(); // loading product -> products + testOneRequestToBackend(env); + testNoOtherRequestWasMade(env); - simulateBackendResponse<unknown, MerchantBackend.Orders.OrderHistory>({ - get: "http://backend/instances/default/private/orders", - params: { delta: 40, wired: "yes", date_ms: 12 }, + 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], }, @@ -107,6 +115,8 @@ describe("order pagination", () => { result.current.loadMorePrev(); }); await waitForNextUpdate(); // loading product -> products + testOneRequestToBackend(env); + testNoOtherRequestWasMade(env); expect(result.current.data).toEqual({ orders: [ diff --git a/packages/merchant-backoffice/tests/hooks/swr/product-create.test.tsx b/packages/merchant-backoffice/tests/hooks/swr/product-create.test.tsx @@ -20,19 +20,21 @@ */ import { renderHook } from "@testing-library/preact-hooks"; -import * as axios from "axios"; +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 { setAxiosRequestAsTestingEnvironment } from "../../../src/hooks/backend"; import { useInstanceProducts, useProductAPI } from "../../../src/hooks/product"; -import { simulateBackendResponse } from "../../util"; - -setAxiosRequestAsTestingEnvironment(); +import { + API_CREATE_PRODUCT, + API_LIST_PRODUCTS, + API_GET_PRODUCT_BY_ID, + AxiosMockEnvironment, + testAllExpectedRequestAndNoMore, +} from "../../axiosMock"; jest.mock("axios"); -describe("product api", () => { +describe("product create api", () => { beforeEach(() => { jest .spyOn(backend, "useBackendContext") @@ -46,76 +48,85 @@ describe("product api", () => { ); }); - it.skip("should not have problem with cache after an creation", async () => { - simulateBackendResponse< - unknown, - MerchantBackend.Products.InventorySummaryResponse - >({ - get: "http://backend/instances/default/private/products", + 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" }], }, }); - simulateBackendResponse< - unknown, - Partial<MerchantBackend.Products.ProductDetail> - >({ - get: "http://backend/instances/default/private/products/1234", + env.addRequestExpectation(API_GET_PRODUCT_BY_ID("1234"), { response: { price: "ARS:33" }, }); - const { result, waitForNextUpdate } = renderHook(() => - useInstanceProducts() - ); // get products -> loading + const { result, waitForNextUpdate } = renderHook(() => { + const api = useProductAPI(); + const query = useInstanceProducts(); - await waitForNextUpdate(); // get info of every product, -> loading - await waitForNextUpdate(); // loading product -> products + return { query, api }; + }); // get products -> loading - expect(result.current?.ok).toBeTruthy(); - if (!result.current?.ok) return; + if (!result.current) { + expect(result.current).toBeDefined(); + return; + } + expect(result.current.query.loading).toBeTruthy(); - expect(result.current.data).toEqual([ - { - id: "1234", - price: "ARS:33", - }, - ]); + await waitForNextUpdate(); // first query to list products + expect(result.current.query.loading).toBeTruthy(); + + await waitForNextUpdate(); // second query to get product details + testAllExpectedRequestAndNoMore(env); + + expect(result.current.query.loading).toBeFalsy(); + expect(result.current?.query.ok).toBeTruthy(); + if (!result.current?.query.ok) return; - const { createProduct } = useProductAPI(); + expect(result.current.query.data).toEqual([ + { id: "1234", price: "ARS:33" }, + ]); - simulateBackendResponse< - Partial<MerchantBackend.Products.ProductAddDetail>, - unknown - >({ - post: "http://backend/instances/default/private/products", + env.addRequestExpectation(API_CREATE_PRODUCT, { request: { price: "ARS:3333" }, }); - simulateBackendResponse< - unknown, - MerchantBackend.Products.InventorySummaryResponse - >({ - get: "http://backend/instances/default/private/products", + act(async () => { + return await result.current?.api.createProduct({ + price: "ARS:3333", + } as any); + }); + + testAllExpectedRequestAndNoMore(env); + + env.addRequestExpectation(API_LIST_PRODUCTS, { response: { products: [{ product_id: "1234" }, { product_id: "2222" }], }, }); - simulateBackendResponse< - unknown, - Partial<MerchantBackend.Products.ProductDetail> - >({ - get: "http://backend/instances/default/private/products/2222", - response: { price: "ARS:3333" }, + + env.addRequestExpectation(API_GET_PRODUCT_BY_ID("1234"), { + response: { price: "ARS:33" }, + }); + env.addRequestExpectation(API_GET_PRODUCT_BY_ID("1234"), { + response: { price: "ARS:33" }, }); - await createProduct({ price: "ARS:3333" } as any); + env.addRequestExpectation(API_GET_PRODUCT_BY_ID("2222"), { + response: { price: "ARS:3333" }, + }); + expect(result.current.query.loading).toBeFalsy(); await waitForNextUpdate(); // loading product -> products await waitForNextUpdate(); // loading product -> products - await waitForNextUpdate(); // loading product -> products - expect(result.current.data).toEqual([ + testAllExpectedRequestAndNoMore(env); + + expect(result.current.query.loading).toBeFalsy(); + expect(result.current.query.ok).toBeTruthy(); + + expect(result.current.query.data).toEqual([ { id: "1234", price: "ARS:33", diff --git a/packages/merchant-backoffice/tests/hooks/swr/product-delete.test.tsx b/packages/merchant-backoffice/tests/hooks/swr/product-delete.test.tsx @@ -20,22 +20,21 @@ */ 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 { simulateBackendResponse } from "../../util"; - -// eslint-disable-next-line @typescript-eslint/no-unused-vars -import * as axios from "axios"; -import { setAxiosRequestAsTestingEnvironment } from "../../../src/hooks/backend"; - -setAxiosRequestAsTestingEnvironment(); +import { + API_LIST_PRODUCTS, + API_GET_PRODUCT_BY_ID, + AxiosMockEnvironment, + testAllExpectedRequestAndNoMore, + testOneRequestToBackend, +} from "../../axiosMock"; jest.mock("axios"); -axios.default; -describe("product api", () => { +describe("product delete api", () => { beforeEach(() => { jest .spyOn(backend, "useBackendContext") @@ -50,89 +49,78 @@ describe("product api", () => { // console.log("CLEAR") }); - it.skip("should not have problem with cache after a delete", async () => { - simulateBackendResponse< - unknown, - MerchantBackend.Products.InventorySummaryResponse - >({ - get: "http://backend/instances/default/private/products", + 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" }], }, }); - simulateBackendResponse< - unknown, - Partial<MerchantBackend.Products.ProductDetail> - >({ - get: "http://backend/instances/default/private/products/1234", + env.addRequestExpectation(API_GET_PRODUCT_BY_ID("1234"), { response: { price: "ARS:12" }, }); - simulateBackendResponse< - unknown, - Partial<MerchantBackend.Products.ProductDetail> - >({ - get: "http://backend/instances/default/private/products/2345", + env.addRequestExpectation(API_GET_PRODUCT_BY_ID("2345"), { response: { price: "ARS:23" }, }); - const { result, waitForNextUpdate } = renderHook(() => - useInstanceProducts() - ); // get products -> loading + // env.addRequestExpectation(API_GET_PRODUCT_BY_ID("1234"), { + // response: { price: "ARS:12" }, + // }); + + // env.addRequestExpectation(API_GET_PRODUCT_BY_ID("2345"), { + // response: { price: "ARS:23" }, + // }); + + const { result, waitForNextUpdate } = renderHook(() => { + const query = useInstanceProducts(); + const api = useProductAPI(); + return { query, api }; + }); // get products -> loading await waitForNextUpdate(); // get info of every product, -> loading await waitForNextUpdate(); // loading product -> products - await waitForNextUpdate(); // loading product -> products + testAllExpectedRequestAndNoMore(env); + // await waitForNextUpdate(); // loading product -> products - expect(result.current?.ok).toBeTruthy(); - if (!result.current?.ok) return; + expect(result.current?.query.ok).toBeTruthy(); + if (!result.current?.query.ok) return; - expect(result.current.data).toEqual([ - { - id: "1234", - price: "ARS:12", - }, - { - id: "2345", - price: "ARS:23", - }, + expect(result.current.query.data).toEqual([ + { id: "1234", price: "ARS:12" }, + { id: "2345", price: "ARS:23" }, ]); - const { deleteProduct } = useProductAPI(); - - simulateBackendResponse({ + env.addRequestExpectation({ delete: "http://backend/instances/default/private/products/1234", }); - simulateBackendResponse< - unknown, - MerchantBackend.Products.InventorySummaryResponse - >({ - get: "http://backend/instances/default/private/products", + env.addRequestExpectation(API_LIST_PRODUCTS, { response: { - products: [ - { - product_id: "2345", - }, - ], + products: [{ product_id: "2345" }], }, }); - simulateBackendResponse< - unknown, - Partial<MerchantBackend.Products.ProductDetail> - >({ - get: "http://backend/instances/default/private/products/2345", + env.addRequestExpectation(API_GET_PRODUCT_BY_ID("2345"), { response: { price: "ARS:23" }, }); - await deleteProduct("1234"); + // env.addRequestExpectation(API_GET_PRODUCT_BY_ID("2345"), { + // response: { price: "ARS:23" }, + // }); + + act(async () => { + await result.current?.api.deleteProduct("1234"); + }); + testOneRequestToBackend(env); await waitForNextUpdate(); await waitForNextUpdate(); + testAllExpectedRequestAndNoMore(env); - expect(result.current.data).toEqual([ + 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 @@ -19,20 +19,23 @@ * @author Sebastian Javier Marchano (sebasjm) */ -import { renderHook } from "@testing-library/preact-hooks"; -import * as axios from "axios"; +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 { setAxiosRequestAsTestingEnvironment } from "../../../src/hooks/backend"; import { useProductAPI, useProductDetails } from "../../../src/hooks/product"; -import { simulateBackendResponse } from "../../util"; - -setAxiosRequestAsTestingEnvironment(); +import { + API_GET_PRODUCT_BY_ID, + API_UPDATE_PRODUCT_BY_ID, + AxiosMockEnvironment, + testAllExpectedRequestAndNoMore, + testOneRequestToBackend, +} from "../../axiosMock"; jest.mock("axios"); -describe("product api", () => { +describe("product details api", () => { beforeEach(() => { jest .spyOn(backend, "useBackendContext") @@ -47,50 +50,59 @@ describe("product api", () => { }); it("should not have problem with cache after an update", async () => { - simulateBackendResponse< - unknown, - Partial<MerchantBackend.Products.ProductDetail> - >({ - get: "http://backend/instances/default/private/products/12", + const env = new AxiosMockEnvironment(); + + env.addRequestExpectation(API_GET_PRODUCT_BY_ID("12"), { response: { description: "this is a description" }, }); - const { result, waitForNextUpdate } = renderHook(() => - useProductDetails("12") - ); // get products -> loading + 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(); - expect(result.current?.ok).toBeTruthy(); - if (!result.current?.ok) return; + testAllExpectedRequestAndNoMore(env); + + expect(result.current.query.loading).toBeFalsy(); + expect(result.current?.query.ok).toBeTruthy(); + if (!result.current?.query.ok) return; - expect(result.current.data).toEqual({ + expect(result.current.query.data).toEqual({ description: "this is a description", }); - const { updateProduct } = useProductAPI(); - - simulateBackendResponse< - unknown, - MerchantBackend.Products.InventorySummaryResponse - >({ - patch: "http://backend/instances/default/private/products/12", + env.addRequestExpectation(API_UPDATE_PRODUCT_BY_ID("12"), { request: { description: "other description" }, }); - simulateBackendResponse< - unknown, - Partial<MerchantBackend.Products.ProductDetail> - >({ - get: "http://backend/instances/default/private/products/12", + env.addRequestExpectation(API_GET_PRODUCT_BY_ID("12"), { response: { description: "other description" }, }); - await updateProduct("12", { description: "other description" } as any); + act(async () => { + return await result.current?.api.updateProduct("12", { + description: "other description", + } as any); + }); + + testOneRequestToBackend(env); + await waitForNextUpdate(); + + testAllExpectedRequestAndNoMore(env); - // await waitForNextUpdate(); + expect(result.current.query.loading).toBeFalsy(); + expect(result.current?.query.ok).toBeTruthy(); + if (!result.current?.query.ok) return; - expect(result.current.data).toEqual({ + 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 @@ -20,19 +20,22 @@ */ import { renderHook } from "@testing-library/preact-hooks"; -import * as axios from "axios"; +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 { setAxiosRequestAsTestingEnvironment } from "../../../src/hooks/backend"; import { useInstanceProducts, useProductAPI } from "../../../src/hooks/product"; -import { simulateBackendResponse } from "../../util"; - -setAxiosRequestAsTestingEnvironment(); +import { + API_GET_PRODUCT_BY_ID, + API_LIST_PRODUCTS, + API_UPDATE_PRODUCT_BY_ID, + AxiosMockEnvironment, + testAllExpectedRequestAndNoMore, + testOneRequestToBackend, +} from "../../axiosMock"; jest.mock("axios"); -describe("product api", () => { +describe("product list api", () => { beforeEach(() => { jest .spyOn(backend, "useBackendContext") @@ -44,66 +47,88 @@ describe("product api", () => { .mockImplementation( () => ({ token: "token", id: "default", admin: true } as any) ); - // console.log("CLEAR") }); it("should not have problem with cache after an update", async () => { - simulateBackendResponse< - unknown, - MerchantBackend.Products.InventorySummaryResponse - >({ - get: "http://backend/instances/default/private/products", + const env = new AxiosMockEnvironment(); + + env.addRequestExpectation(API_LIST_PRODUCTS, { response: { products: [{ product_id: "1234" }], }, }); - simulateBackendResponse< - unknown, - Partial<MerchantBackend.Products.ProductDetail> - >({ - get: "http://backend/instances/default/private/products/1234", + env.addRequestExpectation(API_GET_PRODUCT_BY_ID("1234"), { response: { price: "ARS:12" }, }); - const { result, waitForNextUpdate, waitFor } = renderHook(() => - useInstanceProducts() - ); // get products -> loading + const { result, waitForNextUpdate } = renderHook(() => { + const query = useInstanceProducts(); + const api = useProductAPI(); + return { api, query }; + }); // get products -> loading - await waitForNextUpdate(); // get info of every product, -> loading - await waitForNextUpdate(); // loading product -> products + if (!result.current) { + expect(result.current).toBeDefined(); + return; + } + expect(result.current.query.loading).toBeTruthy(); + await waitForNextUpdate(); - expect(result.current?.ok).toBeTruthy(); - if (!result.current?.ok) return; + await waitForNextUpdate(); + testAllExpectedRequestAndNoMore(env); - expect(result.current.data).toEqual([ - { - id: "1234", - price: "ARS:12", - }, - ]); + expect(result.current.query.loading).toBeFalsy(); + expect(result.current.query.ok).toBeTruthy(); + if (!result.current?.query.ok) return; - const { updateProduct } = useProductAPI(); + expect(result.current.query.data).toEqual([ + { id: "1234", price: "ARS:12" }, + ]); - simulateBackendResponse< - unknown, - MerchantBackend.Products.InventorySummaryResponse - >({ - patch: "http://backend/instances/default/private/products/1234", + env.addRequestExpectation(API_UPDATE_PRODUCT_BY_ID("1234"), { request: { price: "ARS:13" }, }); - simulateBackendResponse< - unknown, - Partial<MerchantBackend.Products.ProductDetail> - >({ - get: "http://backend/instances/default/private/products/1234", + env.addRequestExpectation(API_LIST_PRODUCTS, { + response: { + products: [{ product_id: "1234" }], + }, + }); + env.addRequestExpectation(API_GET_PRODUCT_BY_ID("1234"), { response: { price: "ARS:13" }, }); + // env.addRequestExpectation(API_GET_PRODUCT_BY_ID("1234"), { + // request: { price: "ARS:13" }, + // }); + // env.addRequestExpectation(API_GET_PRODUCT_BY_ID("1234"), { + // request: { price: "ARS:13" }, + // }); + // env.addRequestExpectation(API_GET_PRODUCT_BY_ID("1234"), { + // request: { price: "ARS:13" }, + // }); + // env.addRequestExpectation(API_GET_PRODUCT_BY_ID("1234"), { + // request: { price: "ARS:13" }, + // }); + + act(async () => { + await result.current?.api.updateProduct("1234", { + price: "ARS:13", + } as any); + }); + + testOneRequestToBackend(env); + await waitForNextUpdate(); + // await waitForNextUpdate(); + + // testAllExpectedRequestAndNoMore(env); + // await waitForNextUpdate(); - await updateProduct("1234", { price: "ARS:13" } as any); + expect(result.current.query.loading).toBeFalsy(); + expect(result.current?.query.ok).toBeTruthy(); + if (!result.current?.query.ok) return; - expect(result.current.data).toEqual([ + expect(result.current.query.data).toEqual([ { id: "1234", price: "ARS:13", diff --git a/packages/merchant-backoffice/tests/stories.test.tsx b/packages/merchant-backoffice/tests/stories.test.tsx @@ -18,10 +18,11 @@ * * @author Sebastian Javier Marchano (sebasjm) */ -import { mount } from "enzyme"; -import { h } from "preact"; +import { h, VNode } from "preact"; import * as config from "../src/context/config"; import * as i18n from "../src/context/translation"; +import { cleanup, render as originalRender } from "@testing-library/preact"; +import { SWRConfig } from "swr"; import fs from "fs"; @@ -38,39 +39,51 @@ function getFiles(dir: string, files_: string[] = []) { return files_; } -const re = RegExp(".*.stories.tsx"); +const STORIES_NAME_REGEX = RegExp(".*.stories.tsx"); + +function render(vnode: VNode) { + return originalRender( + <SWRConfig + value={{ + provider: () => new Map(), + }} + > + {vnode} + </SWRConfig> + ); +} import * as jedLib from "jed"; const handler = new jedLib.Jed("en"); -it("render every story", () => { - jest - .spyOn(config, "useConfigContext") - .mockImplementation(() => ({ version: "1.0.0", currency: "EUR" })); - jest - .spyOn(i18n, "useTranslationContext") - .mockImplementation(() => ({ +describe("storybook testing", () => { + it("render every story", () => { + jest + .spyOn(config, "useConfigContext") + .mockImplementation(() => ({ version: "1.0.0", currency: "EUR" })); + jest.spyOn(i18n, "useTranslationContext").mockImplementation(() => ({ changeLanguage: () => null, handler, lang: "en", })); - getFiles("./src") - .filter((f) => re.test(f)) - .map((f) => { - // const f = "./src/paths/instance/transfers/list/List.stories.tsx"; - // eslint-disable-next-line @typescript-eslint/no-var-requires - const s = require(`../${f}`); + getFiles("./src") + .filter((f) => STORIES_NAME_REGEX.test(f)) + .map((f) => { + // const f = "./src/paths/instance/transfers/list/List.stories.tsx"; + // eslint-disable-next-line @typescript-eslint/no-var-requires + const s = require(`../${f}`); - delete s.default; - Object.keys(s).forEach((k) => { - const Component = s[k]; - expect(() => { - mount(<Component {...Component.args} />) - .mount() - .unmount() - .mount(); - }).not.toThrow(); //`problem rendering ${f} example ${k}` + delete s.default; + Object.keys(s).forEach((k) => { + const Component = s[k]; + const vdom = <Component {...Component.args} />; + expect(() => { + const { unmount } = render(vdom); + unmount(); + }).not.toThrow(); //`problem rendering ${f} example ${k}` + cleanup(); + }); }); - }); + }); }); diff --git a/packages/merchant-backoffice/tests/util.ts b/packages/merchant-backoffice/tests/util.ts @@ -1,62 +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 * as axios from 'axios'; - -type Query<Req, Res> = (GetQuery | PostQuery | DeleteQuery | PatchQuery) & RequestResponse<Req, Res> - -interface RequestResponse<Req, Res> { - request?: Req, - params?: any, - response?: Res, -} -interface GetQuery { get: string } -interface PostQuery { post: string } -interface DeleteQuery { delete: string } -interface PatchQuery { patch: string } - -export function simulateBackendResponse<R, T>(query: Query<R, T>): void { - (axios.default as jest.MockedFunction<axios.AxiosStatic>).mockImplementationOnce(function (opt?: axios.AxiosRequestConfig): axios.AxiosPromise { - // console.log(opt, JSON.stringify(query,undefined,2)) - expect(opt).toBeDefined(); - if (!opt) - return Promise.reject(); - - // expect(query.request).toStrictEqual(opt.data); - // expect(query.params).toStrictEqual(opt.params); - if ('get' in query) { - expect(opt.method).toBe('get'); - expect(opt.url).toBe(query.get); - } - if ('post' in query) { - expect(opt.method).toBe('post'); - expect(opt.url).toBe(query.post); - } - if ('delete' in query) { - expect(opt.method).toBe('delete'); - expect(opt.url).toBe(query.delete); - } - if ('patch' in query) { - expect(opt.method).toBe('patch'); - expect(opt.url).toBe(query.patch); - } - return ({ data: query.response, config: {} } as any); - } as any) -}