/* This file is part of GNU Taler (C) 2021-2024 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 */ /** * * @author Sebastian Javier Marchano (sebasjm) */ import { AbsoluteTime, AmountString, TalerMerchantApi } from "@gnu-taler/taler-util"; import * as tests from "@gnu-taler/web-util/testing"; import { expect } from "chai"; import { useInstanceOrders, useOrderDetails } from "./order.js"; import { ApiMockEnvironment } from "./testing.js"; 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, } from "./urls.js"; import { useMerchantApiContext } from "@gnu-taler/web-util/browser"; describe("order api interaction with listing", () => { it("should evict cache when creating an order", async () => { const env = new ApiMockEnvironment(); env.addRequestExpectation(API_LIST_ORDERS, { qparam: { delta: -20, paid: "yes" }, response: { orders: [{ order_id: "1" }, { order_id: "2" } as TalerMerchantApi.OrderHistoryEntry], }, }); const newDate = (_d: string | undefined) => { //console.log("new date", d); }; const hookBehavior = await tests.hookBehaveLikeThis( () => { const query = useInstanceOrders({ paid: true }, newDate); const { lib: api } = useMerchantApiContext() return { query, api }; }, {}, [ ({ query }) => { expect(query).undefined; }, ({ query, api }) => { expect(env.assertJustExpectedRequestWereMade()).deep.eq({ result: "ok", }); // expect(query.loading).undefined; // expect(query.ok).true; // if (!query.ok) return; // expect(query.data).deep.equals({ // orders: [{ order_id: "1" }, { order_id: "2" }], // }); env.addRequestExpectation(API_CREATE_ORDER, { request: { order: { amount: "ARS:12" as AmountString, summary: "pay me" }, lock_uuids: [] }, response: { order_id: "3" }, }); env.addRequestExpectation(API_LIST_ORDERS, { qparam: { delta: -20, paid: "yes" }, response: { orders: [{ order_id: "1" }, { order_id: "2" } as any, { order_id: "3" } as any], }, }); api.instance.createOrder(undefined, { order: { amount: "ARS:12" as AmountString, summary: "pay me" }, }) }, ({ query, api }) => { expect(env.assertJustExpectedRequestWereMade()).deep.eq({ result: "ok", }); // expect(query.loading).undefined; // expect(query.ok).true; // if (!query.ok) return; // expect(query.data).deep.equals({ // orders: [{ order_id: "1" }, { order_id: "2" }, { order_id: "3" }], // }); }, ], env.buildTestingContext(), ); expect(hookBehavior).deep.eq({ result: "ok" }); expect(env.assertJustExpectedRequestWereMade()).deep.eq({ result: "ok" }); }); it("should evict cache when doing a refund", async () => { const env = new ApiMockEnvironment(); env.addRequestExpectation(API_LIST_ORDERS, { qparam: { delta: -20, paid: "yes" }, response: { orders: [{ order_id: "1", amount: "EUR:12", refundable: true, } as TalerMerchantApi.OrderHistoryEntry] }, }); const newDate = (_d: string | undefined) => { //console.log("new date", d); }; const hookBehavior = await tests.hookBehaveLikeThis( () => { const query = useInstanceOrders({ paid: true }, newDate); const { lib: api } = useMerchantApiContext() return { query, api }; }, {}, [ ({ query, api }) => { // expect(query.loading).true; }, ({ query, api }) => { expect(env.assertJustExpectedRequestWereMade()).deep.eq({ result: "ok", }); // expect(query.loading).undefined; // expect(query.ok).true; // if (!query.ok) return; // expect(query.data).deep.equals({ // 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: -20, paid: "yes" }, response: { orders: [ { order_id: "1", amount: "EUR:12", refundable: false } as any, ] }, }); api.instance.addRefund(undefined, "1", { reason: "double pay", refund: "EUR:1" as AmountString, }) }, ({ query, api }) => { expect(env.assertJustExpectedRequestWereMade()).deep.eq({ result: "ok", }); // expect(query.loading).undefined; // expect(query.ok).true; // if (!query.ok) return; // expect(query.data).deep.equals({ // orders: [ // { // order_id: "1", // amount: "EUR:12", // refundable: false, // }, // ], // }); }, ], env.buildTestingContext(), ); expect(hookBehavior).deep.eq({ result: "ok" }); expect(env.assertJustExpectedRequestWereMade()).deep.eq({ result: "ok" }); }); it("should evict cache when deleting an order", async () => { const env = new ApiMockEnvironment(); env.addRequestExpectation(API_LIST_ORDERS, { qparam: { delta: -20, paid: "yes" }, response: { orders: [{ order_id: "1" }, { order_id: "2" } as TalerMerchantApi.OrderHistoryEntry], }, }); const newDate = (_d: string | undefined) => { //console.log("new date", d); }; const hookBehavior = await tests.hookBehaveLikeThis( () => { const query = useInstanceOrders({ paid: true }, newDate); const { lib: api } = useMerchantApiContext() return { query, api }; }, {}, [ ({ query, api }) => { // expect(query.loading).true; }, ({ query, api }) => { expect(env.assertJustExpectedRequestWereMade()).deep.eq({ result: "ok", }); // expect(query.loading).undefined; // expect(query.ok).true; // if (!query.ok) return; // expect(query.data).deep.equals({ // orders: [{ order_id: "1" }, { order_id: "2" }], // }); env.addRequestExpectation(API_DELETE_ORDER("1"), {}); env.addRequestExpectation(API_LIST_ORDERS, { qparam: { delta: -20, paid: "yes" }, response: { orders: [{ order_id: "2" } as any], }, }); api.instance.deleteOrder(undefined, "1") }, ({ query, api }) => { expect(env.assertJustExpectedRequestWereMade()).deep.eq({ result: "ok", }); // expect(query.loading).undefined; // expect(query.ok).true; // if (!query.ok) return; // expect(query.data).deep.equals({ // orders: [{ order_id: "2" }], // }); }, ], env.buildTestingContext(), ); expect(hookBehavior).deep.eq({ result: "ok" }); expect(env.assertJustExpectedRequestWereMade()).deep.eq({ result: "ok" }); }); }); describe("order api interaction with details", () => { it("should evict cache when doing a refund", async () => { const env = new ApiMockEnvironment(); env.addRequestExpectation(API_GET_ORDER_BY_ID("1"), { // qparam: { delta: 0, paid: "yes" }, response: { summary: "description", refund_amount: "EUR:0", } as unknown as TalerMerchantApi.CheckPaymentPaidResponse, }); const hookBehavior = await tests.hookBehaveLikeThis( () => { const query = useOrderDetails("1"); const { lib: api } = useMerchantApiContext() return { query, api }; }, {}, [ ({ query, api }) => { // expect(query.loading).true; }, ({ query, api }) => { expect(env.assertJustExpectedRequestWereMade()).deep.eq({ result: "ok", }); // expect(query.loading).false; // expect(query.ok).true; // if (!query.ok) return; // expect(query.data).deep.equals({ // 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 TalerMerchantApi.CheckPaymentPaidResponse, }); api.instance.addRefund(undefined, "1", { reason: "double pay", refund: "EUR:1" as AmountString, }) }, ({ query, api }) => { expect(env.assertJustExpectedRequestWereMade()).deep.eq({ result: "ok", }); // expect(query.loading).false; // expect(query.ok).true; // if (!query.ok) return; // expect(query.data).deep.equals({ // summary: "description", // refund_amount: "EUR:1", // }); }, ], env.buildTestingContext(), ); expect(hookBehavior).deep.eq({ result: "ok" }); expect(env.assertJustExpectedRequestWereMade()).deep.eq({ result: "ok" }); }); it("should evict cache when doing a forget", async () => { const env = new ApiMockEnvironment(); env.addRequestExpectation(API_GET_ORDER_BY_ID("1"), { // qparam: { delta: 0, paid: "yes" }, response: { summary: "description", refund_amount: "EUR:0", } as unknown as TalerMerchantApi.CheckPaymentPaidResponse, }); const hookBehavior = await tests.hookBehaveLikeThis( () => { const query = useOrderDetails("1"); const { lib: api } = useMerchantApiContext() return { query, api }; }, {}, [ ({ query, api }) => { // expect(query.loading).true; }, ({ query, api }) => { expect(env.assertJustExpectedRequestWereMade()).deep.eq({ result: "ok", }); // expect(query.loading).false; // expect(query.ok).true; // if (!query.ok) return; // expect(query.data).deep.equals({ // 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 TalerMerchantApi.CheckPaymentPaidResponse, }); api.instance.forgetOrder(undefined, "1", { fields: ["$.summary"], }) }, ({ query, api }) => { expect(env.assertJustExpectedRequestWereMade()).deep.eq({ result: "ok", }); // expect(query.loading).false; // expect(query.ok).true; // if (!query.ok) return; // expect(query.data).deep.equals({ // summary: undefined, // }); }, ], env.buildTestingContext(), ); expect(hookBehavior).deep.eq({ result: "ok" }); expect(env.assertJustExpectedRequestWereMade()).deep.eq({ result: "ok" }); }); }); describe("order listing pagination", () => { it("should not load more if has reach the end", async () => { const env = new ApiMockEnvironment(); env.addRequestExpectation(API_LIST_ORDERS, { qparam: { delta: 20, wired: "yes", date_s: 12 }, response: { orders: [{ order_id: "1" } as any], }, }); env.addRequestExpectation(API_LIST_ORDERS, { qparam: { delta: -20, wired: "yes", date_s: 13 }, response: { orders: [{ order_id: "2" } as any], }, }); const newDate = (_d: string | undefined) => { //console.log("new date", d); }; const hookBehavior = await tests.hookBehaveLikeThis( () => { const date = new Date(12000); const query = useInstanceOrders({ wired: true, date: AbsoluteTime.fromMilliseconds(date.getTime()) }, newDate); const { lib: api } = useMerchantApiContext() return { query, api }; }, {}, [ ({ query, api }) => { // expect(query.loading).true; }, ({ query, api }) => { expect(env.assertJustExpectedRequestWereMade()).deep.eq({ result: "ok", }); // expect(query.loading).undefined; // expect(query.ok).true; // if (!query.ok) return; // expect(query.data).deep.equals({ // orders: [{ order_id: "1" }, { order_id: "2" }], // }); // expect(query.isReachingEnd).true; // expect(query.isReachingStart).true; }, ], env.buildTestingContext(), ); expect(hookBehavior).deep.eq({ result: "ok" }); expect(env.assertJustExpectedRequestWereMade()).deep.eq({ result: "ok" }); }); it("should load more if result brings more that PAGINATED_LIST_REQUEST", async () => { const env = new ApiMockEnvironment(); 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), })); env.addRequestExpectation(API_LIST_ORDERS, { qparam: { delta: 20, wired: "yes", date_s: 12 }, response: { orders: ordersFrom0to20, }, }); env.addRequestExpectation(API_LIST_ORDERS, { qparam: { delta: -20, wired: "yes", date_s: 13 }, response: { orders: ordersFrom20to40, }, }); const newDate = (_d: string | undefined) => { //console.log("new date", d); }; const hookBehavior = await tests.hookBehaveLikeThis( () => { const date = new Date(12000); const query = useInstanceOrders({ wired: true, date: AbsoluteTime.fromMilliseconds(date.getTime()) }, newDate); const { lib: api } = useMerchantApiContext() return { query, api }; }, {}, [ ({ query, api }) => { // expect(query.loading).true; }, ({ query, api }) => { expect(env.assertJustExpectedRequestWereMade()).deep.eq({ result: "ok", }); // expect(query.loading).undefined; // expect(query.ok).true; // if (!query.ok) return; // expect(query.data).deep.equals({ // orders: [...ordersFrom20to0, ...ordersFrom20to40], // }); // expect(query.isReachingEnd).false; // expect(query.isReachingStart).false; env.addRequestExpectation(API_LIST_ORDERS, { qparam: { delta: -40, wired: "yes", date_s: 13 }, response: { orders: [...ordersFrom20to40, { order_id: "41" }], }, }); // query.loadMore(); }, ({ query, api }) => { expect(env.assertJustExpectedRequestWereMade()).deep.eq({ result: "ok", }); // expect(query.loading).true; }, ({ query, api }) => { // expect(query.loading).undefined; // expect(query.ok).true; // if (!query.ok) return; // expect(query.data).deep.equals({ // orders: [ // ...ordersFrom20to0, // ...ordersFrom20to40, // { order_id: "41" }, // ], // }); env.addRequestExpectation(API_LIST_ORDERS, { qparam: { delta: 40, wired: "yes", date_s: 12 }, response: { orders: [...ordersFrom0to20, { order_id: "-1" }], }, }); // query.loadMorePrev(); }, ({ query, api }) => { expect(env.assertJustExpectedRequestWereMade()).deep.eq({ result: "ok", }); // expect(query.loading).true; }, ({ query, api }) => { // expect(query.loading).undefined; // expect(query.ok).true; // if (!query.ok) return; // expect(query.data).deep.equals({ // orders: [ // { order_id: "-1" }, // ...ordersFrom20to0, // ...ordersFrom20to40, // { order_id: "41" }, // ], // }); }, ], env.buildTestingContext(), ); expect(hookBehavior).deep.eq({ result: "ok" }); expect(env.assertJustExpectedRequestWereMade()).deep.eq({ result: "ok" }); }); });