@playq/core 0.2.77

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (225) hide show
  1. package/README.md +41 -0
  2. package/bin/playq.js +175 -0
  3. package/cucumber.js +10 -0
  4. package/dist/exec/featureFileCache.d.ts +21 -0
  5. package/dist/exec/featureFileCache.js +124 -0
  6. package/dist/exec/featureFilePreProcess.d.ts +12 -0
  7. package/dist/exec/featureFilePreProcess.js +208 -0
  8. package/dist/exec/preLoader.d.ts +1 -0
  9. package/dist/exec/preLoader.js +72 -0
  10. package/dist/exec/preProcessEntry.d.ts +1 -0
  11. package/dist/exec/preProcessEntry.js +83 -0
  12. package/dist/exec/preProcess_old_todelete.d.ts +1 -0
  13. package/dist/exec/preProcess_old_todelete.js +258 -0
  14. package/dist/exec/runner.d.ts +1 -0
  15. package/dist/exec/runner.js +221 -0
  16. package/dist/exec/runner_orchestrator.d.ts +1 -0
  17. package/dist/exec/runner_orchestrator.js +85 -0
  18. package/dist/exec/sgGenerator.d.ts +11 -0
  19. package/dist/exec/sgGenerator.js +310 -0
  20. package/dist/global.d.ts +15 -0
  21. package/dist/global.js +185 -0
  22. package/dist/helper/actions/api/apiRequestActions.d.ts +117 -0
  23. package/dist/helper/actions/api/apiRequestActions.js +374 -0
  24. package/dist/helper/actions/api/apiValidationActions.d.ts +119 -0
  25. package/dist/helper/actions/api/apiValidationActions.js +615 -0
  26. package/dist/helper/actions/apiActions.d.ts +18 -0
  27. package/dist/helper/actions/apiActions.js +34 -0
  28. package/dist/helper/actions/apiStepDefs.d.ts +1 -0
  29. package/dist/helper/actions/apiStepDefs.js +64 -0
  30. package/dist/helper/actions/comm/commonActions.d.ts +58 -0
  31. package/dist/helper/actions/comm/commonActions.js +198 -0
  32. package/dist/helper/actions/comm/utilityActions.d.ts +131 -0
  33. package/dist/helper/actions/comm/utilityActions.js +351 -0
  34. package/dist/helper/actions/commActions.d.ts +18 -0
  35. package/dist/helper/actions/commActions.js +34 -0
  36. package/dist/helper/actions/commStepDefs.d.ts +1 -0
  37. package/dist/helper/actions/commStepDefs.js +57 -0
  38. package/dist/helper/actions/stepGroupStepDefs.d.ts +1 -0
  39. package/dist/helper/actions/stepGroupStepDefs.js +15 -0
  40. package/dist/helper/actions/web/alertActions.d.ts +61 -0
  41. package/dist/helper/actions/web/alertActions.js +224 -0
  42. package/dist/helper/actions/web/cookieActions.d.ts +45 -0
  43. package/dist/helper/actions/web/cookieActions.js +186 -0
  44. package/dist/helper/actions/web/downloadActions.d.ts +40 -0
  45. package/dist/helper/actions/web/downloadActions.js +153 -0
  46. package/dist/helper/actions/web/elementReaderActions.d.ts +95 -0
  47. package/dist/helper/actions/web/elementReaderActions.js +326 -0
  48. package/dist/helper/actions/web/formActions.d.ts +122 -0
  49. package/dist/helper/actions/web/formActions.js +423 -0
  50. package/dist/helper/actions/web/iframeActions.d.ts +23 -0
  51. package/dist/helper/actions/web/iframeActions.js +108 -0
  52. package/dist/helper/actions/web/javascriptActions.d.ts +14 -0
  53. package/dist/helper/actions/web/javascriptActions.js +77 -0
  54. package/dist/helper/actions/web/keyboardActions.d.ts +35 -0
  55. package/dist/helper/actions/web/keyboardActions.js +118 -0
  56. package/dist/helper/actions/web/localStorageActions.d.ts +51 -0
  57. package/dist/helper/actions/web/localStorageActions.js +163 -0
  58. package/dist/helper/actions/web/mouseActions.d.ts +240 -0
  59. package/dist/helper/actions/web/mouseActions.js +609 -0
  60. package/dist/helper/actions/web/reportingActions.d.ts +34 -0
  61. package/dist/helper/actions/web/reportingActions.js +58 -0
  62. package/dist/helper/actions/web/screenshotActions.d.ts +34 -0
  63. package/dist/helper/actions/web/screenshotActions.js +151 -0
  64. package/dist/helper/actions/web/testDataActions.d.ts +21 -0
  65. package/dist/helper/actions/web/testDataActions.js +211 -0
  66. package/dist/helper/actions/web/validationActions.d.ts +547 -0
  67. package/dist/helper/actions/web/validationActions.js +1754 -0
  68. package/dist/helper/actions/web/waitActions.d.ts +191 -0
  69. package/dist/helper/actions/web/waitActions.js +589 -0
  70. package/dist/helper/actions/web/webNavigation.d.ts +104 -0
  71. package/dist/helper/actions/web/webNavigation.js +288 -0
  72. package/dist/helper/actions/webActions.d.ts +32 -0
  73. package/dist/helper/actions/webActions.js +48 -0
  74. package/dist/helper/actions/webStepDefs.d.ts +1 -0
  75. package/dist/helper/actions/webStepDefs.js +455 -0
  76. package/dist/helper/browsers/browserManager.d.ts +1 -0
  77. package/dist/helper/browsers/browserManager.js +56 -0
  78. package/dist/helper/bundle/defaultEntries.d.ts +6 -0
  79. package/dist/helper/bundle/defaultEntries.js +200 -0
  80. package/dist/helper/bundle/env.d.ts +1 -0
  81. package/dist/helper/bundle/env.js +157 -0
  82. package/dist/helper/bundle/vars.d.ts +9 -0
  83. package/dist/helper/bundle/vars.js +375 -0
  84. package/dist/helper/faker/customFaker.d.ts +55 -0
  85. package/dist/helper/faker/customFaker.js +45 -0
  86. package/dist/helper/faker/modules/data/postcodes_valid_sg.json +17 -0
  87. package/dist/helper/faker/modules/dateTime.d.ts +18 -0
  88. package/dist/helper/faker/modules/dateTime.js +106 -0
  89. package/dist/helper/faker/modules/mobile.d.ts +4 -0
  90. package/dist/helper/faker/modules/mobile.js +59 -0
  91. package/dist/helper/faker/modules/nric.d.ts +32 -0
  92. package/dist/helper/faker/modules/nric.js +84 -0
  93. package/dist/helper/faker/modules/passport.d.ts +3 -0
  94. package/dist/helper/faker/modules/passport.js +36 -0
  95. package/dist/helper/faker/modules/person.d.ts +14 -0
  96. package/dist/helper/faker/modules/person.js +73 -0
  97. package/dist/helper/faker/modules/postcode.d.ts +6 -0
  98. package/dist/helper/faker/modules/postcode.js +47 -0
  99. package/dist/helper/fixtures/locAggregate.d.ts +7 -0
  100. package/dist/helper/fixtures/locAggregate.js +94 -0
  101. package/dist/helper/fixtures/logFixture.d.ts +8 -0
  102. package/dist/helper/fixtures/logFixture.js +56 -0
  103. package/dist/helper/fixtures/webFixture.d.ts +19 -0
  104. package/dist/helper/fixtures/webFixture.js +186 -0
  105. package/dist/helper/fixtures/webLocFixture.d.ts +2 -0
  106. package/dist/helper/fixtures/webLocFixture.js +144 -0
  107. package/dist/helper/report/allureStepLogger.d.ts +0 -0
  108. package/dist/helper/report/allureStepLogger.js +25 -0
  109. package/dist/helper/report/customiseReport.d.ts +1 -0
  110. package/dist/helper/report/customiseReport.js +55 -0
  111. package/dist/helper/report/init.d.ts +1 -0
  112. package/dist/helper/report/init.js +14 -0
  113. package/dist/helper/report/report.d.ts +1 -0
  114. package/dist/helper/report/report.js +102 -0
  115. package/dist/helper/util/dataLoader.d.ts +10 -0
  116. package/dist/helper/util/dataLoader.js +73 -0
  117. package/dist/helper/util/logger.d.ts +4 -0
  118. package/dist/helper/util/logger.js +61 -0
  119. package/dist/helper/util/session/sessionUtil.d.ts +26 -0
  120. package/dist/helper/util/session/sessionUtil.js +729 -0
  121. package/dist/helper/util/stepHelpers.d.ts +2 -0
  122. package/dist/helper/util/stepHelpers.js +16 -0
  123. package/dist/helper/util/test-data/dataLoader.d.ts +7 -0
  124. package/dist/helper/util/test-data/dataLoader.js +145 -0
  125. package/dist/helper/util/test-data/dataTest.d.ts +10 -0
  126. package/dist/helper/util/test-data/dataTest.js +216 -0
  127. package/dist/helper/util/totp/totpHelper.d.ts +38 -0
  128. package/dist/helper/util/totp/totpHelper.js +117 -0
  129. package/dist/helper/util/utilities/cryptoUtil.d.ts +2 -0
  130. package/dist/helper/util/utilities/cryptoUtil.js +53 -0
  131. package/dist/helper/util/utilities/schemaGeneratorUtil.d.ts +2 -0
  132. package/dist/helper/util/utilities/schemaGeneratorUtil.js +129 -0
  133. package/dist/helper/util/utils.d.ts +2 -0
  134. package/dist/helper/util/utils.js +22 -0
  135. package/dist/helper/wrapper/PlaywrightWrappers.d.ts +8 -0
  136. package/dist/helper/wrapper/PlaywrightWrappers.js +26 -0
  137. package/dist/helper/wrapper/assert.d.ts +9 -0
  138. package/dist/helper/wrapper/assert.js +23 -0
  139. package/dist/index.d.ts +7 -0
  140. package/dist/index.js +57 -0
  141. package/dist/scripts/get-versions.d.ts +1 -0
  142. package/dist/scripts/get-versions.js +98 -0
  143. package/dist/scripts/posttest.d.ts +1 -0
  144. package/dist/scripts/posttest.js +29 -0
  145. package/dist/scripts/pretest.d.ts +1 -0
  146. package/dist/scripts/pretest.js +57 -0
  147. package/dist/scripts/util.d.ts +1 -0
  148. package/dist/scripts/util.js +376 -0
  149. package/package.json +68 -0
  150. package/src/exec/featureFileCache.ts +80 -0
  151. package/src/exec/featureFilePreProcess.ts +239 -0
  152. package/src/exec/preLoader.ts +72 -0
  153. package/src/exec/preProcessEntry.ts +59 -0
  154. package/src/exec/preProcess_old_todelete.ts +289 -0
  155. package/src/exec/runner.ts +241 -0
  156. package/src/exec/runnerCuke.js +90 -0
  157. package/src/exec/runner_orchestrator.ts +91 -0
  158. package/src/exec/sgGenerator.ts +373 -0
  159. package/src/global.ts +130 -0
  160. package/src/helper/actions/api/apiRequestActions.ts +362 -0
  161. package/src/helper/actions/api/apiValidationActions.ts +594 -0
  162. package/src/helper/actions/apiActions.ts +18 -0
  163. package/src/helper/actions/apiStepDefs.ts +80 -0
  164. package/src/helper/actions/comm/commonActions.ts +165 -0
  165. package/src/helper/actions/comm/utilityActions.ts +344 -0
  166. package/src/helper/actions/commActions.ts +18 -0
  167. package/src/helper/actions/commStepDefs.ts +72 -0
  168. package/src/helper/actions/stepGroupStepDefs.ts +17 -0
  169. package/src/helper/actions/web/alertActions.ts +179 -0
  170. package/src/helper/actions/web/cookieActions.ts +124 -0
  171. package/src/helper/actions/web/downloadActions.ts +129 -0
  172. package/src/helper/actions/web/elementReaderActions.ts +323 -0
  173. package/src/helper/actions/web/formActions.ts +469 -0
  174. package/src/helper/actions/web/iframeActions.ts +67 -0
  175. package/src/helper/actions/web/javascriptActions.ts +38 -0
  176. package/src/helper/actions/web/keyboardActions.ts +101 -0
  177. package/src/helper/actions/web/localStorageActions.ts +109 -0
  178. package/src/helper/actions/web/mouseActions.ts +864 -0
  179. package/src/helper/actions/web/reportingActions.ts +53 -0
  180. package/src/helper/actions/web/screenshotActions.ts +124 -0
  181. package/src/helper/actions/web/testDataActions.ts +162 -0
  182. package/src/helper/actions/web/validationActions.ts +2287 -0
  183. package/src/helper/actions/web/waitActions.ts +757 -0
  184. package/src/helper/actions/web/webNavigation.ts +313 -0
  185. package/src/helper/actions/webActions.ts +33 -0
  186. package/src/helper/actions/webStepDefs.ts +505 -0
  187. package/src/helper/browsers/browserManager.ts +23 -0
  188. package/src/helper/bundle/defaultEntries.ts +208 -0
  189. package/src/helper/bundle/env.ts +119 -0
  190. package/src/helper/bundle/vars.ts +368 -0
  191. package/src/helper/faker/customFaker.ts +107 -0
  192. package/src/helper/faker/modules/data/postcodes_valid_sg.json +17 -0
  193. package/src/helper/faker/modules/dateTime.ts +121 -0
  194. package/src/helper/faker/modules/mobile.ts +58 -0
  195. package/src/helper/faker/modules/nric.ts +109 -0
  196. package/src/helper/faker/modules/passport.ts +34 -0
  197. package/src/helper/faker/modules/person.ts +93 -0
  198. package/src/helper/faker/modules/postcode.ts +57 -0
  199. package/src/helper/fixtures/locAggregate.ts +61 -0
  200. package/src/helper/fixtures/logFixture.ts +57 -0
  201. package/src/helper/fixtures/webFixture.ts +206 -0
  202. package/src/helper/fixtures/webLocFixture.ts +143 -0
  203. package/src/helper/report/allureStepLogger.ts +26 -0
  204. package/src/helper/report/customiseReport.ts +61 -0
  205. package/src/helper/report/init.ts +18 -0
  206. package/src/helper/report/report.ts +72 -0
  207. package/src/helper/util/dataLoader.ts +42 -0
  208. package/src/helper/util/logger.ts +32 -0
  209. package/src/helper/util/session/sessionUtil.ts +839 -0
  210. package/src/helper/util/stepHelpers.ts +14 -0
  211. package/src/helper/util/test-data/dataLoader.ts +108 -0
  212. package/src/helper/util/test-data/dataTest.ts +191 -0
  213. package/src/helper/util/test-data/registerUser.json +7 -0
  214. package/src/helper/util/totp/totpHelper.ts +102 -0
  215. package/src/helper/util/utilities/cryptoUtil.ts +53 -0
  216. package/src/helper/util/utilities/schemaGeneratorUtil.ts +143 -0
  217. package/src/helper/util/utils.ts +28 -0
  218. package/src/helper/wrapper/PlaywrightWrappers.ts +28 -0
  219. package/src/helper/wrapper/assert.ts +25 -0
  220. package/src/index.ts +17 -0
  221. package/src/scripts/get-versions.ts +68 -0
  222. package/src/scripts/posttest.ts +32 -0
  223. package/src/scripts/pretest.ts +48 -0
  224. package/src/scripts/util.ts +406 -0
  225. package/tsconfig.json +30 -0
@@ -0,0 +1,362 @@
1
+ /**
2
+ * @file apiRequestActions.ts
3
+ *
4
+ * Provides a unified API for API actions in Playwright and Cucumber frameworks.
5
+ * Supports dynamic config-driven requests, variable interpolation, and assertions.
6
+ *
7
+ * Key Features:
8
+ * - Hybrid context support: Playwright runner and Cucumber world.
9
+ * - Rich options for redirects, timeouts, auth, and type conversions.
10
+ * - Robust error handling and logging aligned with PlayQ standards.
11
+ *
12
+ * Authors: Renish Kozhithottathil [Lead Automation Principal, NCS]
13
+ * Date: 2025-07-01
14
+ * Version: v1.0.0
15
+ *
16
+ * Note: This file adheres to the PlayQ Enterprise Automation Standards.
17
+ */
18
+ import axios from "axios";
19
+ import type { AxiosResponse } from "axios";
20
+ import * as allure from "allure-js-commons";
21
+ import path from "path";
22
+ import fs from "fs";
23
+ import { vars, comm } from "../../../global";
24
+ import { test } from "@playwright/test";
25
+
26
+ // Inline runner helpers
27
+ function isPlaywrightRunner() { return process.env.TEST_RUNNER === 'playwright'; }
28
+ function isCucumberRunner() { return process.env.TEST_RUNNER === 'cucumber'; }
29
+ const __allureAny_api: any = allure as any;
30
+ if (typeof __allureAny_api.step !== 'function') {
31
+ __allureAny_api.step = async (_name: string, fn: any) => await fn();
32
+ }
33
+
34
+ /**
35
+ * Api: Call api -action: {param} -config: {param} -baseUrl: {param} -options: {param}
36
+ *
37
+ * Calls a predefined API action using configuration from a resource file, supporting dynamic variable replacement,
38
+ * custom headers, body, parameters, authentication, and assertion of expected status codes.
39
+ *
40
+ * This function is designed for hybrid Playwright/Cucumber test frameworks, enabling enterprise-grade API testing
41
+ * with robust error handling and flexible options.
42
+ *
43
+ * @param action - The API action name (corresponds to a file in `resources/api/{action}.api.ts`).
44
+ * @param config - The configuration key within the API module (e.g., "success", "errorCase").
45
+ * @param baseUrl - The base URL for the API endpoint.
46
+ * @param options - Optional. Additional options as a JSON string or object. Supports:
47
+ * - `maxUrlRedirects`: Maximum number of redirects (default: from config or 5).
48
+ * - `maxTimeout`: Request timeout in milliseconds (default: from config or 10000).
49
+ * - `auth`: Axios authentication object.
50
+ * - Any other Axios request config options.
51
+ *
52
+ * @throws Error if the API config is not found or if the response status does not match `expectedStatus` in config.
53
+ *
54
+ * @example
55
+ * // Example API config file: resources/api/user.api.ts
56
+ * export const api = {
57
+ * getUser: {
58
+ * path: "/users/{userId}",
59
+ * method: "GET",
60
+ * headers: { "Authorization": "Bearer ${token}" },
61
+ * expectedStatus: "200"
62
+ * }
63
+ * };
64
+ *
65
+ * // Usage in test:
66
+ * await callApi(
67
+ * "user",
68
+ * "getUser",
69
+ * "https://api.example.com",
70
+ * { userId: "123", token: "abc123" }
71
+ * );
72
+ *
73
+ * @example
74
+ * // With options as a JSON string:
75
+ * await callApi(
76
+ * "user",
77
+ * "getUser",
78
+ * "https://api.example.com",
79
+ * '{"userId":"123","token":"abc123","maxTimeout":5000}'
80
+ * );
81
+ *
82
+ * @example
83
+ * // With custom authentication:
84
+ * await callApi(
85
+ * "user",
86
+ * "getUser",
87
+ * "https://api.example.com",
88
+ * { auth: { username: "admin", password: "secret" } }
89
+ * );
90
+ */
91
+ export async function callApi(action: string, config: string, baseUrl: string, options?: string | Record<string, any>) {
92
+ const options_json =
93
+ typeof options === "string" ? vars.parseLooseJson(options) : options || {};
94
+ const {
95
+ maxUrlRedirects = Number(vars.getConfigValue("apiTest.maxUrlRedirects")) || 5, // Axios defalt is 5
96
+ maxTimeout = Number(vars.getConfigValue("apiTest.timeout")) || 10000,
97
+ auth,
98
+ toNumber = undefined,
99
+ toBoolean = undefined,
100
+ } = options_json ?? {};
101
+
102
+ // Input validation
103
+ if (!action || typeof action !== 'string') {
104
+ throw new Error("Action must be a non-empty string.");
105
+ }
106
+ if (!config || typeof config !== 'string') {
107
+ throw new Error("Config must be a non-empty string.");
108
+ }
109
+ if (!baseUrl || typeof baseUrl !== 'string') {
110
+ throw new Error("Base URL must be a non-empty string.");
111
+ }
112
+
113
+ const stepName = `Api: Call api -action: ${action} -config: ${config} -baseUrl: ${baseUrl} -options: ${JSON.stringify(options_json)}`;
114
+
115
+ if (isPlaywrightRunner()) {
116
+ await test.step(stepName, async () => {
117
+ await doCallApi();
118
+ });
119
+ } else {
120
+ await doCallApi();
121
+ }
122
+
123
+ async function doCallApi() {
124
+ // Dynamic import of the module
125
+ vars.setValue("internal.api.last.resStatus", "");
126
+ vars.setValue("internal.api.last.resStatusText", "");
127
+ vars.setValue("internal.api.last.resHeader", "");
128
+ vars.setValue("internal.api.last.resBody", "");
129
+ const projectRoot = process.env.PLAYQ_PROJECT_ROOT || process.cwd();
130
+ const candidateTs = path.resolve(projectRoot, 'resources', 'api', `${action}.api.ts`);
131
+ const candidateJs = path.resolve(projectRoot, 'resources', 'api', `${action}.api.js`);
132
+ let actionPath: string;
133
+ if (fs.existsSync(candidateTs)) {
134
+ actionPath = candidateTs;
135
+ } else if (fs.existsSync(candidateJs)) {
136
+ actionPath = candidateJs;
137
+ } else {
138
+ throw new Error(`API config file not found for action '${action}'. Looked for: ${candidateTs} and ${candidateJs}`);
139
+ }
140
+
141
+ // const actionPath = require.resolve(`../../../resources/api/${action}.api.ts`);
142
+
143
+ const apiModule = await require(actionPath);
144
+ const apiConfig = apiModule.api[config];
145
+
146
+ if (!apiConfig) {
147
+ throw new Error(`Config '${config}' not found in ${actionPath}`);
148
+ }
149
+
150
+ const reqUrl = vars.replaceVariables(`${baseUrl}${apiConfig.path ?? ""}`);
151
+ const reqMethod = vars.replaceVariables(apiConfig.method ?? "");
152
+ if (!reqMethod || typeof reqMethod !== 'string') {
153
+ throw new Error(`API config '${config}' must specify a valid 'method'.`);
154
+ }
155
+ const reqHeaders = apiConfig.headers
156
+ ? JSON.parse(vars.replaceVariables(JSON.stringify(apiConfig.headers)))
157
+ : {};
158
+ const reqBody = apiConfig.body
159
+ ? JSON.parse(vars.replaceVariables(JSON.stringify(apiConfig.body)))
160
+ : undefined;
161
+ const reqParams = apiConfig.params
162
+ ? JSON.parse(vars.replaceVariables(JSON.stringify(apiConfig.params)))
163
+ : undefined;
164
+
165
+
166
+ if (reqBody && toNumber) convertJsonNodes(reqBody, "toNumber", toNumber);
167
+ if (reqBody && toBoolean) convertJsonNodes(reqBody, "toBoolean", toBoolean);
168
+
169
+ // Attach request details for traceability
170
+ try {
171
+ const reqInfo = {
172
+ method: reqMethod,
173
+ url: reqUrl,
174
+ headers: reqHeaders,
175
+ params: reqParams,
176
+ body: reqBody
177
+ };
178
+ await comm.attachLog(`API Request: ${JSON.stringify(reqInfo)}`, "application/json", "API Request");
179
+ } catch { }
180
+
181
+ let response: AxiosResponse;
182
+ if (reqMethod.toUpperCase().trim() == 'GET') {
183
+ response = await axios({
184
+ method: reqMethod,
185
+ url: reqUrl,
186
+ headers: reqHeaders,
187
+ params: reqParams,
188
+ maxRedirects: maxUrlRedirects,
189
+ timeout: maxTimeout,
190
+ validateStatus: () => true,
191
+ auth
192
+ });
193
+ } else {
194
+ response = await axios({
195
+ method: reqMethod,
196
+ url: reqUrl,
197
+ headers: reqHeaders,
198
+ data: reqBody,
199
+ maxRedirects: maxUrlRedirects,
200
+ timeout: maxTimeout,
201
+ validateStatus: () => true,
202
+ auth
203
+ });
204
+ }
205
+
206
+ const resStatus = (await response).status.toString();
207
+ const resStatusText = (await response).statusText;
208
+ const resHeader = JSON.stringify((await response).headers);
209
+ const resBody = JSON.stringify((await response).data);
210
+
211
+ vars.setValue("playq.api.last.resStatus", resStatus);
212
+ vars.setValue("playq.api.last.resStatusText", resStatusText);
213
+ vars.setValue("playq.api.last.resHeader", resHeader);
214
+ vars.setValue("playq.api.last.resBody", resBody);
215
+
216
+ // This console is to show the api response.
217
+ console.log("API Response:", {
218
+ status: resStatus,
219
+ statusText: resStatusText,
220
+ headers: resHeader,
221
+ body: resBody
222
+ });
223
+
224
+ // Attach response details
225
+ try {
226
+ await comm.attachLog(
227
+ `API Response: ${JSON.stringify({ status: resStatus, statusText: resStatusText })}`,
228
+ "text/plain",
229
+ "API Response"
230
+ );
231
+ // Attach compact body header snapshots to avoid huge logs
232
+ await comm.attachLog(resHeader, "application/json", "API Response Headers");
233
+ await comm.attachLog(resBody, "application/json", "API Response Body");
234
+ } catch { }
235
+
236
+ if (apiConfig.expectedStatus) {
237
+ if (apiConfig.expectedStatus != resStatus) {
238
+ await comm.attachLog(
239
+ `❌ Status mismatch for '${config}' Expected: '${apiConfig.expectedStatus}' Actual: '${resStatus}'`,
240
+ "text/plain",
241
+ "API Verification"
242
+ );
243
+ throw new Error(
244
+ `Api Response for '${config}' Expected: '${apiConfig.expectedStatus}' Actual: '${resStatus}'`
245
+ );
246
+ } else {
247
+ await comm.attachLog(
248
+ `✅ Status matched for '${config}': '${resStatus}'`,
249
+ "text/plain",
250
+ "API Verification"
251
+ );
252
+ }
253
+ }
254
+ }
255
+ }
256
+
257
+ /**
258
+ * Converts specific JSON node values within an object based on provided keys.
259
+ * Supports nested keys using dot notation, e.g., "payment.arreasFlag".
260
+ *
261
+ * @param obj - The JSON object to mutate (in-place). If undefined, no-op.
262
+ * @param type - Conversion type: "toNumber" or "toBoolean".
263
+ * @param keys - Comma-separated list of keys to convert.
264
+ */
265
+ function convertJsonNodes(obj: any, type: "toNumber" | "toBoolean", keys: string) {
266
+ if (!obj || !keys || typeof keys !== 'string') return;
267
+ const keyList = keys.split(',').map(k => k.trim());
268
+ for (const key of keyList) {
269
+ // Support nested keys like "payment.arreasFlag"
270
+ const path = key.split('.');
271
+ let ref = obj;
272
+ for (let i = 0; i < path.length - 1; i++) {
273
+ if (ref[path[i]] === undefined) break;
274
+ ref = ref[path[i]];
275
+ }
276
+ const lastKey = path[path.length - 1];
277
+ if (ref && ref[lastKey] !== undefined) {
278
+ if (type === "toNumber") ref[lastKey] = Number(ref[lastKey]);
279
+ if (type === "toBoolean") ref[lastKey] = ref[lastKey] === "true" || ref[lastKey] === true;
280
+ }
281
+ }
282
+ }
283
+
284
+ /**
285
+ * Api: Get -action: {param} -config: {param} -baseUrl: {param} -options: {param}
286
+ *
287
+ * Sends a GET-style request using an API config. Alias of `callApi`.
288
+ *
289
+ * @param action - API action name.
290
+ * @param config - Config key within the action module.
291
+ * @param baseUrl - Base URL for the request.
292
+ * @param options - Additional options forwarded to `callApi`.
293
+ */
294
+ export async function get(action: string, config: string, baseUrl: string, options?: string | Record<string, any>) {
295
+ return callApi(action, config, baseUrl, options);
296
+ }
297
+
298
+ /**
299
+ * Api: Post -action: {param} -config: {param} -baseUrl: {param} -options: {param}
300
+ *
301
+ * Sends a POST-style request using an API config. Alias of `callApi`.
302
+ *
303
+ * @param action - API action name.
304
+ * @param config - Config key within the action module.
305
+ * @param baseUrl - Base URL for the request.
306
+ * @param options - Additional options forwarded to `callApi`.
307
+ */
308
+ export async function post(action: string, config: string, baseUrl: string, options?: string | Record<string, any>) {
309
+ return callApi(action, config, baseUrl, options);
310
+ }
311
+
312
+ /**
313
+ * Api: Request -action: {param} -config: {param} -baseUrl: {param} -options: {param}
314
+ *
315
+ * Sends a request (generic wrapper). Alias of `callApi`.
316
+ *
317
+ * @param action - API action name.
318
+ * @param config - Config key within the action module.
319
+ * @param baseUrl - Base URL for the request.
320
+ * @param options - Additional options forwarded to `callApi`.
321
+ */
322
+ export async function request(action: string, config: string, baseUrl: string, options?: string | Record<string, any>) {
323
+ return callApi(action, config, baseUrl, options);
324
+ }
325
+
326
+ /**
327
+ * Api: Put -action: {param} -config: {param} -baseUrl: {param} -options: {param}
328
+ * Sends a PUT-style request using an API config. Alias of callApi.
329
+ */
330
+ export async function put(action: string, config: string, baseUrl: string, options?: string | Record<string, any>) {
331
+ return callApi(action, config, baseUrl, { ...(typeof options === 'string' ? vars.parseLooseJson(options) : options || {}), method: 'PUT' });
332
+ }
333
+
334
+ /**
335
+ * Api: Patch -action: {param} -config: {param} -baseUrl: {param} -options: {param}
336
+ * Sends a PATCH-style request using an API config. Alias of callApi.
337
+ */
338
+ export async function patch(action: string, config: string, baseUrl: string, options?: string | Record<string, any>) {
339
+ return callApi(action, config, baseUrl, { ...(typeof options === 'string' ? vars.parseLooseJson(options) : options || {}), method: 'PATCH' });
340
+ }
341
+
342
+ /**
343
+ * Api: Delete -action: {param} -config: {param} -baseUrl: {param} -options: {param}
344
+ * Sends a DELETE-style request using an API config. Alias of callApi.
345
+ */
346
+ export async function del(action: string, config: string, baseUrl: string, options?: string | Record<string, any>) {
347
+ return callApi(action, config, baseUrl, { ...(typeof options === 'string' ? vars.parseLooseJson(options) : options || {}), method: 'DELETE' });
348
+ }
349
+
350
+ /**
351
+ * Api: Send request -method: {param} -action: {param} -config: {param} -baseUrl: {param} -options: {param}
352
+ *
353
+ * Sends an HTTP request using the specified method and API config.
354
+ * @param method - HTTP method (GET, POST, PUT, PATCH, DELETE, etc.)
355
+ * @param action - API action name.
356
+ * @param config - Config key within the action module.
357
+ * @param baseUrl - Base URL for the request.
358
+ * @param options - Additional options forwarded to callApi.
359
+ */
360
+ export async function sendRequest(method: string, action: string, config: string, baseUrl: string, options?: string | Record<string, any>) {
361
+ return callApi(action, config, baseUrl, { ...(typeof options === 'string' ? vars.parseLooseJson(options) : options || {}), method });
362
+ }