From fc419ce2ef4a2b69dcced27a1a48c091f861ebbb Mon Sep 17 00:00:00 2001 From: Jonathan Druart Date: Thu, 12 Jun 2025 16:43:12 +0200 Subject: [PATCH] Bug 40173: Make http-client reusable from Cypress tests We will need to call REST API endpoints from Cypress tests, and more specifically from Cypress's tasks. It will be useful to reuse what has been done in http-client.js instead of using the low-level fetch JS function. 1. Add missing get and getAll functions 2. Allow overwrite of return_response and mark_submitting 3. Add a "default" client that will bring flexibility (can call any routes) 4. Add rspack config to generate t/cypress/plugins/dist/api-client.cjs.js that will make it reusable from Cypress's tasks Signed-off-by: Owen Leonard Signed-off-by: Matt Blenkinsop Signed-off-by: Martin Renvoize Signed-off-by: Lucas Gass (cherry picked from commit 0985c64a5404e123c1a99e1526311bd10c8b632a) Signed-off-by: Paul Derscheid --- .../intranet-tmpl/prog/js/fetch/api-client.js | 2 + .../prog/js/fetch/default-api-client.js | 19 ++++++++ .../prog/js/fetch/http-client.js | 46 +++++++++++++++--- .../prog/js/vue/fetch/http-client.js | 48 +++++++++++++------ rspack.config.js | 34 +++++++++++++ 5 files changed, 128 insertions(+), 21 deletions(-) create mode 100644 koha-tmpl/intranet-tmpl/prog/js/fetch/default-api-client.js diff --git a/koha-tmpl/intranet-tmpl/prog/js/fetch/api-client.js b/koha-tmpl/intranet-tmpl/prog/js/fetch/api-client.js index 5b516fa445..2fe5a6dce8 100644 --- a/koha-tmpl/intranet-tmpl/prog/js/fetch/api-client.js +++ b/koha-tmpl/intranet-tmpl/prog/js/fetch/api-client.js @@ -13,6 +13,7 @@ import RecallAPIClient from "./recall-api-client.js"; import SysprefAPIClient from "./system-preferences-api-client.js"; import TicketAPIClient from "./ticket-api-client.js"; import AcquisitionAPIClient from "./acquisition-api-client.js"; +import DefaultAPIClient from "./default-api-client.js"; export const APIClient = { article_request: new ArticleRequestAPIClient(HttpClient), @@ -28,4 +29,5 @@ export const APIClient = { recall: new RecallAPIClient(HttpClient), sysprefs: new SysprefAPIClient(HttpClient), ticket: new TicketAPIClient(HttpClient), + default: new DefaultAPIClient(HttpClient), }; diff --git a/koha-tmpl/intranet-tmpl/prog/js/fetch/default-api-client.js b/koha-tmpl/intranet-tmpl/prog/js/fetch/default-api-client.js new file mode 100644 index 0000000000..714d3a3357 --- /dev/null +++ b/koha-tmpl/intranet-tmpl/prog/js/fetch/default-api-client.js @@ -0,0 +1,19 @@ +export class DefaultAPIClient { + constructor(HttpClient) { + this.httpClient = new HttpClient({ + baseURL: "", + }); + } + + get koha() { + return { + get: params => this.httpClient.get(params), + getAll: params => this.httpClient.getAll(params), + post: params => this.httpClient.post(params), + put: params => this.httpClient.put(params), + delete: params => this.httpClient.delete(params), + }; + } +} + +export default DefaultAPIClient; diff --git a/koha-tmpl/intranet-tmpl/prog/js/fetch/http-client.js b/koha-tmpl/intranet-tmpl/prog/js/fetch/http-client.js index 93194a164b..8f2c3d3ab2 100644 --- a/koha-tmpl/intranet-tmpl/prog/js/fetch/http-client.js +++ b/koha-tmpl/intranet-tmpl/prog/js/fetch/http-client.js @@ -105,6 +105,40 @@ class HttpClient { return res; } + get(params = {}) { + return this._fetchJSON( + params.endpoint, + params.headers, + { + ...params.options, + method: "GET", + }, + params.return_response ?? false, + params.mark_submitting ?? false + ); + } + + getAll(params = {}) { + let url = + params.endpoint + + "?" + + new URLSearchParams({ + _per_page: -1, + ...(params.params && params.params), + ...(params.query && { q: JSON.stringify(params.query) }), + }); + return this._fetchJSON( + url, + params.headers, + { + ...params.options, + method: "GET", + }, + params.return_response ?? false, + params.mark_submitting ?? false + ); + } + post(params = {}) { const body = params.body ? typeof params.body === "string" @@ -121,8 +155,8 @@ class HttpClient { body, method: "POST", }, - false, - true + params.return_response ?? false, + params.mark_submitting ?? true ); } @@ -142,8 +176,8 @@ class HttpClient { body, method: "PUT", }, - false, - true + params.return_response ?? false, + params.mark_submitting ?? true ); } @@ -158,8 +192,8 @@ class HttpClient { ...params.options, method: "DELETE", }, - true, - true + params.return_response ?? true, + params.mark_submitting ?? true ); } } diff --git a/koha-tmpl/intranet-tmpl/prog/js/vue/fetch/http-client.js b/koha-tmpl/intranet-tmpl/prog/js/vue/fetch/http-client.js index ac848c2809..23a2b6b286 100644 --- a/koha-tmpl/intranet-tmpl/prog/js/vue/fetch/http-client.js +++ b/koha-tmpl/intranet-tmpl/prog/js/vue/fetch/http-client.js @@ -59,10 +59,16 @@ class HttpClient { } get(params = {}) { - return this._fetchJSON(params.endpoint, params.headers, { - ...params.options, - method: "GET", - }); + return this._fetchJSON( + params.endpoint, + params.headers, + { + ...params.options, + method: "GET", + }, + params.return_response ?? false, + params.mark_submitting ?? false + ); } getAll(params = {}) { @@ -74,10 +80,16 @@ class HttpClient { ...(params.params && params.params), ...(params.query && { q: JSON.stringify(params.query) }), }); - return this._fetchJSON(url, params.headers, { - ...params.options, - method: "GET", - }); + return this._fetchJSON( + url, + params.headers, + { + ...params.options, + method: "GET", + }, + params.return_response ?? false, + params.mark_submitting ?? false + ); } post(params = {}) { @@ -96,8 +108,8 @@ class HttpClient { body, method: "POST", }, - false, - true + params.return_response ?? false, + params.mark_submitting ?? true ); } @@ -117,8 +129,8 @@ class HttpClient { body, method: "PUT", }, - false, - true + params.return_response ?? false, + params.mark_submitting ?? true ); } @@ -133,14 +145,20 @@ class HttpClient { ...params.options, method: "DELETE", }, - true, - true + params.return_response ?? true, + params.mark_submitting ?? true ); } count(params = {}) { let res; - return this._fetchJSON(params.endpoint, params.headers, {}, 1).then( + return this._fetchJSON( + params.endpoint, + params.headers, + {}, + params.return_response ?? true, + params.mark_submitting ?? false + ).then( response => { if (response) { return response.headers.get("X-Total-Count"); diff --git a/rspack.config.js b/rspack.config.js index 630aa6a513..9b10583d51 100644 --- a/rspack.config.js +++ b/rspack.config.js @@ -161,4 +161,38 @@ module.exports = [ "datatables.net-buttons/js/buttons.colVis": "DataTable", }, }, + { + entry: { + "api-client.cjs": + "./koha-tmpl/intranet-tmpl/prog/js/fetch/api-client.js", + }, + output: { + filename: "[name].js", + path: path.resolve(__dirname, "t/cypress/plugins/dist/"), + library: { + type: "commonjs", + }, + globalObject: "global", + }, + target: "node", + module: { + rules: [ + { + test: /\.js$/, + loader: "builtin:swc-loader", + options: { + jsc: { + parser: { + syntax: "ecmascript", + }, + }, + }, + exclude: [/node_modules/], + type: "javascript/auto", + }, + ], + }, + externals: [], + plugins: [], + }, ];