/* 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 { TalerMerchantApi } from "@gnu-taler/taler-util"; import * as tests from "@gnu-taler/web-util/testing"; import { expect } from "chai"; import { useBackendInstances, useInstanceDetails, } from "./instance.js"; import { ApiMockEnvironment } from "./testing.js"; import { API_CREATE_INSTANCE, API_DELETE_INSTANCE, API_GET_CURRENT_INSTANCE, API_LIST_INSTANCES, API_UPDATE_CURRENT_INSTANCE, API_UPDATE_CURRENT_INSTANCE_AUTH, API_UPDATE_INSTANCE_BY_ID, } from "./urls.js"; import { useMerchantApiContext } from "@gnu-taler/web-util/browser"; describe("instance api interaction with details", () => { it("should evict cache when updating an instance", async () => { const env = new ApiMockEnvironment(); env.addRequestExpectation(API_GET_CURRENT_INSTANCE, { response: { name: "instance_name", } as TalerMerchantApi.QueryInstancesResponse, }); const hookBehavior = await tests.hookBehaveLikeThis( () => { // const api = useInstanceAPI(); const { lib: api } = useMerchantApiContext() const query = useInstanceDetails(); 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({ name: "instance_name", }); env.addRequestExpectation(API_UPDATE_CURRENT_INSTANCE, { request: { name: "other_name", } as TalerMerchantApi.InstanceReconfigurationMessage, }); env.addRequestExpectation(API_GET_CURRENT_INSTANCE, { response: { name: "other_name", } as TalerMerchantApi.QueryInstancesResponse, }); api.management.updateCurrentInstance(undefined, { name: "other_name", } as TalerMerchantApi.InstanceReconfigurationMessage); }, ({ 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({ name: "other_name", }); }, ], env.buildTestingContext(), ); expect(hookBehavior).deep.eq({ result: "ok" }); expect(env.assertJustExpectedRequestWereMade()).deep.eq({ result: "ok" }); }); it("should evict cache when setting the instance's token", async () => { const env = new ApiMockEnvironment(); // env.addRequestExpectation(API_GET_CURRENT_INSTANCE, { // response: { // name: "instance_name", // auth: { // method: "token", // // token: "not-secret", // }, // } as TalerMerchantApi.QueryInstancesResponse, // }); const hookBehavior = await tests.hookBehaveLikeThis( () => { const { lib: api } = useMerchantApiContext() const query = useInstanceDetails(); 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({ name: "instance_name", auth: { method: "token", }, }); env.addRequestExpectation(API_UPDATE_CURRENT_INSTANCE_AUTH, { request: { method: "token", token: "secret", } as TalerMerchantApi.InstanceAuthConfigurationMessage, }); // env.addRequestExpectation(API_NEW_LOGIN, { // auth: "secret", // request: { // scope: "write", // duration: { // "d_us": "forever", // }, // refreshable: true, // }, // }); env.addRequestExpectation(API_GET_CURRENT_INSTANCE, { response: { name: "instance_name", auth: { type: "token", // token: "secret", }, } as TalerMerchantApi.QueryInstancesResponse, }); // api.setNewAccessToken(undefined, "secret" as AccessToken); }, ({ 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({ name: "instance_name", auth: { method: "token", // token: "secret", }, }); }, ], env.buildTestingContext(), ); expect(hookBehavior).deep.eq({ result: "ok" }); expect(env.assertJustExpectedRequestWereMade()).deep.eq({ result: "ok" }); }); it("should evict cache when clearing the instance's token", async () => { const env = new ApiMockEnvironment(); env.addRequestExpectation(API_GET_CURRENT_INSTANCE, { response: { name: "instance_name", auth: { type: "token", // token: "not-secret", }, } as TalerMerchantApi.QueryInstancesResponse, }); const hookBehavior = await tests.hookBehaveLikeThis( () => { const { lib: api } = useMerchantApiContext() const query = useInstanceDetails(); 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({ name: "instance_name", auth: { method: "token", // token: "not-secret", }, }); env.addRequestExpectation(API_UPDATE_CURRENT_INSTANCE_AUTH, { request: { method: "external", } as TalerMerchantApi.InstanceAuthConfigurationMessage, }); env.addRequestExpectation(API_GET_CURRENT_INSTANCE, { response: { name: "instance_name", auth: { type: "external", }, } as TalerMerchantApi.QueryInstancesResponse, }); api.management.updateCurrentInstanceAuthentication(undefined, { method: "external" }); }, ({ 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({ name: "instance_name", auth: { method: "external", }, }); }, ], env.buildTestingContext(), ); expect(hookBehavior).deep.eq({ result: "ok" }); expect(env.assertJustExpectedRequestWereMade()).deep.eq({ result: "ok" }); // const { result, waitForNextUpdate } = renderHook( // () => { // const api = useInstanceAPI(); // const query = useInstanceDetails(); // return { query, api }; // }, // { wrapper: TestingContext } // ); // expect(result.current).not.undefined; // if (!result.current) { // return; // } // expect(result.current.query.loading).true; // await waitForNextUpdate({ timeout: 1 }); // expect(env.assertJustExpectedRequestWereMade()).deep.eq({ result: "ok" }); // expect(result.current.query.loading).false; // expect(result.current?.query.ok).true; // if (!result.current?.query.ok) return; // expect(result.current.query.data).equals({ // name: 'instance_name', // auth: { // method: 'token', // token: 'not-secret', // } // }); // act(async () => { // await result.current?.api.clearToken(); // }); // expect(env.assertJustExpectedRequestWereMade()).deep.eq({ result: "ok" }); // expect(result.current.query.loading).false; // await waitForNextUpdate({ timeout: 1 }); // expect(env.assertJustExpectedRequestWereMade()).deep.eq({ result: "ok" }); // expect(result.current.query.loading).false; // expect(result.current.query.ok).true; // expect(result.current.query.data).equals({ // name: 'instance_name', // auth: { // method: 'external', // } // }); }); }); describe("instance admin api interaction with listing", () => { it("should evict cache when creating a new instance", async () => { const env = new ApiMockEnvironment(); env.addRequestExpectation(API_LIST_INSTANCES, { response: { instances: [ { name: "instance_name", } as TalerMerchantApi.Instance, ], }, }); const hookBehavior = await tests.hookBehaveLikeThis( () => { const { lib: api } = useMerchantApiContext() const query = useBackendInstances(); 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({ instances: [ { name: "instance_name", }, ], }); env.addRequestExpectation(API_CREATE_INSTANCE, { request: { name: "other_name", } as TalerMerchantApi.InstanceConfigurationMessage, }); env.addRequestExpectation(API_LIST_INSTANCES, { response: { instances: [ { name: "instance_name", } as TalerMerchantApi.Instance, { name: "other_name", } as TalerMerchantApi.Instance, ], }, }); api.management.createInstance(undefined, { name: "other_name", } as TalerMerchantApi.InstanceConfigurationMessage) }, ({ 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({ instances: [ { name: "instance_name", }, { name: "other_name", }, ], }); }, ], env.buildTestingContext(), ); expect(hookBehavior).deep.eq({ result: "ok" }); expect(env.assertJustExpectedRequestWereMade()).deep.eq({ result: "ok" }); }); it("should evict cache when deleting an instance", async () => { const env = new ApiMockEnvironment(); env.addRequestExpectation(API_LIST_INSTANCES, { response: { instances: [ { id: "default", name: "instance_name", } as TalerMerchantApi.Instance, { id: "the_id", name: "second_instance", } as TalerMerchantApi.Instance, ], }, }); const hookBehavior = await tests.hookBehaveLikeThis( () => { const { lib: api } = useMerchantApiContext() const query = useBackendInstances(); 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({ instances: [ { id: "default", name: "instance_name", }, { id: "the_id", name: "second_instance", }, ], }); env.addRequestExpectation(API_DELETE_INSTANCE("the_id"), {}); env.addRequestExpectation(API_LIST_INSTANCES, { response: { instances: [ { id: "default", name: "instance_name", } as TalerMerchantApi.Instance, ], }, }); api.management.deleteInstance(undefined, "the_id"); }, ({ 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({ instances: [ { id: "default", name: "instance_name", }, ], }); }, ], env.buildTestingContext(), ); expect(hookBehavior).deep.eq({ result: "ok" }); expect(env.assertJustExpectedRequestWereMade()).deep.eq({ result: "ok" }); // const { result, waitForNextUpdate } = renderHook( // () => { // const api = useAdminAPI(); // const query = useBackendInstances(); // return { query, api }; // }, // { wrapper: TestingContext } // ); // expect(result.current).not.undefined; // if (!result.current) { // return; // } // expect(result.current.query.loading).true; // await waitForNextUpdate({ timeout: 1 }); // expect(env.assertJustExpectedRequestWereMade()).deep.eq({ result: "ok" }); // expect(result.current.query.loading).false; // expect(result.current?.query.ok).true; // if (!result.current?.query.ok) return; // expect(result.current.query.data).equals({ // instances: [{ // id: 'default', // name: 'instance_name' // }, { // id: 'the_id', // name: 'second_instance' // }] // }); // env.addRequestExpectation(API_DELETE_INSTANCE('the_id'), {}); // act(async () => { // await result.current?.api.deleteInstance('the_id'); // }); // expect(env.assertJustExpectedRequestWereMade()).deep.eq({ result: "ok" }); // env.addRequestExpectation(API_LIST_INSTANCES, { // response: { // instances: [{ // id: 'default', // name: 'instance_name' // } as TalerMerchantApi.Instance] // }, // }); // expect(result.current.query.loading).false; // await waitForNextUpdate({ timeout: 1 }); // expect(env.assertJustExpectedRequestWereMade()).deep.eq({ result: "ok" }); // expect(result.current.query.loading).false; // expect(result.current.query.ok).true; // expect(result.current.query.data).equals({ // instances: [{ // id: 'default', // name: 'instance_name' // }] // }); }); it("should evict cache when deleting (purge) an instance", async () => { const env = new ApiMockEnvironment(); env.addRequestExpectation(API_LIST_INSTANCES, { response: { instances: [ { id: "default", name: "instance_name", } as TalerMerchantApi.Instance, { id: "the_id", name: "second_instance", } as TalerMerchantApi.Instance, ], }, }); const hookBehavior = await tests.hookBehaveLikeThis( () => { const { lib: api } = useMerchantApiContext() const query = useBackendInstances(); 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({ instances: [ { id: "default", name: "instance_name", }, { id: "the_id", name: "second_instance", }, ], }); env.addRequestExpectation(API_DELETE_INSTANCE("the_id"), { qparam: { purge: "YES", }, }); env.addRequestExpectation(API_LIST_INSTANCES, { response: { instances: [ { id: "default", name: "instance_name", } as TalerMerchantApi.Instance, ], }, }); api.management.deleteInstance(undefined, "the_id", { purge: 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({ instances: [ { id: "default", name: "instance_name", }, ], }); }, ], env.buildTestingContext(), ); expect(hookBehavior).deep.eq({ result: "ok" }); expect(env.assertJustExpectedRequestWereMade()).deep.eq({ result: "ok" }); }); }); describe("instance management api interaction with listing", () => { it("should evict cache when updating an instance", async () => { const env = new ApiMockEnvironment(); env.addRequestExpectation(API_LIST_INSTANCES, { response: { instances: [ { id: "managed", name: "instance_name", } as TalerMerchantApi.Instance, ], }, }); const hookBehavior = await tests.hookBehaveLikeThis( () => { const { lib: api } = useMerchantApiContext() const query = useBackendInstances(); 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({ instances: [ { id: "managed", name: "instance_name", }, ], }); env.addRequestExpectation(API_UPDATE_INSTANCE_BY_ID("managed"), { request: { name: "other_name", } as TalerMerchantApi.InstanceReconfigurationMessage, }); env.addRequestExpectation(API_LIST_INSTANCES, { response: { instances: [ { id: "managed", name: "other_name", } as TalerMerchantApi.Instance, ], }, }); api.management.updateCurrentInstance(undefined, { name: "other_name", } as TalerMerchantApi.InstanceConfigurationMessage); }, ({ 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({ instances: [ { id: "managed", name: "other_name", }, ], }); }, ], env.buildTestingContext(), ); expect(hookBehavior).deep.eq({ result: "ok" }); expect(env.assertJustExpectedRequestWereMade()).deep.eq({ result: "ok" }); }); });