@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,80 @@
1
+ import { Given, When, Then } from "@cucumber/cucumber";
2
+ import { api, vars } from "../../global";
3
+
4
+ /**
5
+ * API Step Definitions
6
+ *
7
+ * Cucumber step patterns for API request and validation actions.
8
+ * Mirrors the functions in apiRequestActions.ts and apiValidationActions.ts.
9
+ */
10
+
11
+
12
+ Given("Api: Call api -action: {param} -config: {param} -baseUrl: {param} -options: {param}", async function (action: string, config: string, baseUrl: string, options?: string) {
13
+ await api.callApi(action, config, baseUrl, options);
14
+ });
15
+
16
+ Given("Api: Get -action: {param} -config: {param} -baseUrl: {param} -options: {param}", async function (action: string, config: string, baseUrl: string, options?: string) {
17
+ await api.get(action, config, baseUrl, options);
18
+ });
19
+
20
+ Given("Api: Post -action: {param} -config: {param} -baseUrl: {param} -options: {param}", async function (action: string, config: string, baseUrl: string, options?: string) {
21
+ await api.post(action, config, baseUrl, options);
22
+ });
23
+
24
+ Given("Api: Request -action: {param} -config: {param} -baseUrl: {param} -options: {param}", async function (action: string, config: string, baseUrl: string, options?: string) {
25
+ await api.request(action, config, baseUrl, options);
26
+ });
27
+
28
+ Given("Api: Put -action: {param} -config: {param} -baseUrl: {param} -options: {param}", async function (action: string, config: string, baseUrl: string, options?: string) {
29
+ await api.put(action, config, baseUrl, options);
30
+ });
31
+
32
+ Given("Api: Patch -action: {param} -config: {param} -baseUrl: {param} -options: {param}", async function (action: string, config: string, baseUrl: string, options?: string) {
33
+ await api.patch(action, config, baseUrl, options);
34
+ });
35
+
36
+ Given("Api: Delete -action: {param} -config: {param} -baseUrl: {param} -options: {param}", async function (action: string, config: string, baseUrl: string, options?: string) {
37
+ await api.del(action, config, baseUrl, options);
38
+ });
39
+
40
+ Given("Api: Send request -method: {param} -action: {param} -config: {param} -baseUrl: {param} -options: {param}", async function (method: string, action: string, config: string, baseUrl: string, options?: string) {
41
+ await api.sendRequest(method, action, config, baseUrl, options);
42
+ });
43
+
44
+ Given("Api: Verify value -actual: {param} -expected: {param} -options: {param}", async function (actual: string, expected: string, options?: string) {
45
+ await api.verifyValue(actual, expected, options);
46
+ });
47
+
48
+ Given("Api: Assert value -actual: {param} -expected: {param} -options: {param}", async function (actual: string, expected: string, options?: string) {
49
+ await api.assertValue(actual, expected, options);
50
+ });
51
+
52
+ Given("Api: Verify api path value in last response -path: {param} -expected: {param} -options: {param}", async function (path: string, expected: string, options?: string) {
53
+ await api.verifyPathValue(path, expected, options);
54
+ });
55
+
56
+ Given("Api: Assert api path value -path: {param} -expected: {param} -options: {param}", async function (path: string, expected: string, options?: string) {
57
+ await api.assertPathValue(path, expected, options);
58
+ });
59
+
60
+ Given("Api: Get last response JSON path value -path: {param} -storeTo: {param}", async function (pathExpr: string, varName: string) {
61
+ const value = await api.getLastResponseJsonPathValue(pathExpr);
62
+ if (value !== undefined && value !== null) {
63
+ vars.setValue(varName, String(value));
64
+ }
65
+ });
66
+
67
+ Given("Api: Store last response JSON paths to variables -paths: {param} -vars: {param}", async function (paths: string, varsCsv: string) {
68
+ await api.storeLastResponseJsonPathsToVariables(paths, varsCsv);
69
+ });
70
+
71
+ Given("Api: Get path value from last response -path: {param} -storeTo: {param}", async function (pathExpr: string, varName: string) {
72
+ const value = await api.getPathValueFromLastResponse(pathExpr);
73
+ if (value !== undefined && value !== null) {
74
+ vars.setValue(varName, String(value));
75
+ }
76
+ });
77
+
78
+ Given("Api: Store paths -paths: {param} -vars: {param}", async function (paths: string, varsCsv: string) {
79
+ await api.storePaths(paths, varsCsv);
80
+ });
@@ -0,0 +1,165 @@
1
+ import { vars, webFixture, logFixture } from "../../../global";
2
+ import { parseLooseJson } from '../../bundle/vars';
3
+ import * as allure from "allure-js-commons";
4
+
5
+ function isPlaywrightRunner() { return process.env.TEST_RUNNER === 'playwright'; }
6
+ function isCucumberRunner() { return process.env.TEST_RUNNER === 'cucumber'; }
7
+
8
+ const __allureAny_comm: any = allure as any;
9
+ if (typeof __allureAny_comm.step !== 'function') {
10
+ __allureAny_comm.step = async (_name: string, fn: any) => await fn();
11
+ }
12
+
13
+ /**
14
+ * Comm: Comment -text: {param}
15
+ *
16
+ * Logs a comment with variable substitution to the console.
17
+ * Useful for adding contextual information to the test log.
18
+ *
19
+ * Variables inside the message string (e.g., ${var.username}) will be replaced using `vars.replaceVariables`.
20
+ *
21
+ * @param message - The comment or message to log.
22
+ *
23
+ * @throws Error if `message` is not a non-empty string.
24
+ *
25
+ * @example
26
+ * Comm: Comment -text: "LAMBDA TEST COMPLETE"
27
+ */
28
+ export async function comment(message: string) {
29
+ if (typeof message !== 'string' || message.trim().length === 0) {
30
+ throw new Error('❌ comment: message must be a non-empty string.');
31
+ }
32
+ const formattedMessage = vars.replaceVariables(message);
33
+
34
+ if (isPlaywrightRunner()) {
35
+ await __allureAny_comm.step(
36
+ `Comm: Comment -text: ${formattedMessage}`,
37
+ async () => {
38
+ console.log(`💬 Comment: ${formattedMessage}`);
39
+ }
40
+ );
41
+ } else {
42
+ console.log(`💬 Comment: ${formattedMessage}`);
43
+ }
44
+ }
45
+
46
+ /**
47
+ * Comm: Store -value: {param} in -variable: {param} -options: {param}
48
+ *
49
+ * Stores a value (with optional variable substitution) into a runtime variable.
50
+ *
51
+ * Variables inside the value string (e.g., ${var.username}) will be resolved using `vars.replaceVariables`.
52
+ *
53
+ * @param value - The value to store (can include variable references).
54
+ * @param varName - The name of the variable to store the resolved value into.
55
+ * @param options - Optional string or object with additional parameters (parsed if string). Currently unused but reserved for future logic.
56
+ *
57
+ * @throws Error if `varName` is not a non-empty string or `value` is undefined/null.
58
+ *
59
+ * @example
60
+ * Store -value: "${faker.string.alphanumeric({length:4})}" in -variable: "var.centre.code" -options: ""
61
+ */
62
+ export async function storeValue(value: string, varName: string, options?: string | Record<string, any>) {
63
+ const options_json = typeof options === 'string' ? parseLooseJson(options) : (options || {});
64
+ if (typeof varName !== 'string' || varName.trim().length === 0) {
65
+ throw new Error('❌ storeValue: varName must be a non-empty string.');
66
+ }
67
+ if (value === undefined || value === null) {
68
+ throw new Error('❌ storeValue: value must be provided.');
69
+ }
70
+ const resolvedValue = vars.replaceVariables(value);
71
+
72
+ if (isPlaywrightRunner()) {
73
+ await __allureAny_comm.step(
74
+ `Comm: Store -value: ${resolvedValue} in -variable: ${varName} -options: ${JSON.stringify(options_json)}`,
75
+ async () => {
76
+ vars.setValue(varName, resolvedValue);
77
+ }
78
+ );
79
+ } else {
80
+ vars.setValue(varName, resolvedValue);
81
+ }
82
+ }
83
+
84
+ /**
85
+ * Comm: Attach-Log -message: {param} -mimeType: {param} -msgType: {param}
86
+ *
87
+ * Attach log or message to the test context (Cucumber or Playwright runner).
88
+ * @param message The message or buffer to attach
89
+ * @param mimeType The mime type (default: text/plain)
90
+ * @param msgType Optional label for the attachment (default: "Log").
91
+ *
92
+ * If `message` is empty or undefined, a warning is logged and no attachment is made.
93
+ */
94
+ export async function attachLog(
95
+ message: string | Buffer,
96
+ mimeType?: string,
97
+ msgType?: string
98
+
99
+ ) {
100
+ if (message === undefined || message === null || (typeof message === 'string' && message.length === 0)) {
101
+ console.warn('⚠️ attachLog: empty message provided; skipping attachment');
102
+ return;
103
+ }
104
+ if (!mimeType) mimeType = "text/plain";
105
+ if (!msgType) msgType = "Log";
106
+
107
+
108
+ if (isCucumberRunner()) {
109
+ const world = webFixture.getWorld();
110
+ if (world?.attach) {
111
+ await world.attach(message, mimeType);
112
+ } else {
113
+ console.warn("⚠️ No World.attach() available in Cucumber context");
114
+ }
115
+ } else if (isPlaywrightRunner()) {
116
+ try {
117
+ const anyAllure: any = allure as any;
118
+ if (typeof anyAllure.attachment === 'function') {
119
+ anyAllure.attachment(msgType, message, mimeType);
120
+ } else if (typeof anyAllure.attach === 'function') {
121
+ anyAllure.attach(msgType || 'Log', message, mimeType);
122
+ } else {
123
+ if (typeof message === 'string') console.log(message);
124
+ }
125
+ } catch {
126
+ if (typeof message === 'string') console.log(message);
127
+ }
128
+ // await playwrightTest
129
+ // .info()
130
+ // .attach("Log", { body: message, contentType: mimeType });
131
+ } else {
132
+ console.warn("⚠️ attachLog: Unknown runner type");
133
+ }
134
+ }
135
+
136
+ /**
137
+ * Comm: Wait-In-Milli-Seconds -seconds: {param}
138
+ *
139
+ * Pauses execution for a given number of milliseconds.
140
+ * Logs a message using the test logger if available.
141
+ *
142
+ * @param ms - The number of milliseconds to wait.
143
+ *
144
+ * @throws Error if `ms` is not a finite number or is negative.
145
+ *
146
+ * @example
147
+ * Comm: Wait-In-Milli-Seconds -seconds: "1000"
148
+ */
149
+ export async function waitInMilliSeconds(ms: number) {
150
+ if (typeof ms !== 'number' || !isFinite(ms) || ms < 0) {
151
+ throw new Error('❌ waitInMilliSeconds: ms must be a non-negative number.');
152
+ }
153
+ const logger = logFixture.getLogger?.();
154
+ const doWait = async () => {
155
+ logger?.info?.(`⏳ Waiting for ${ms} ms`);
156
+ await new Promise((resolve) => setTimeout(resolve, ms));
157
+ };
158
+ if (isPlaywrightRunner()) {
159
+ await __allureAny_comm.step(`Comm: Wait-In-Milli-Seconds -seconds: ${ms}`, async () => {
160
+ await doWait();
161
+ });
162
+ } else {
163
+ await doWait();
164
+ }
165
+ }
@@ -0,0 +1,344 @@
1
+ import * as fs from 'fs';
2
+ import * as path from 'path';
3
+ import * as allure from 'allure-js-commons';
4
+ import { vars, comm } from '../../../global';
5
+ import * as crypto from '../../util/utilities/cryptoUtil';
6
+ import { TOTPHelper } from '../../util/totp/totpHelper';
7
+
8
+ function isPlaywrightRunner() { return process.env.TEST_RUNNER === 'playwright'; }
9
+ const __allureAny_comm: any = allure as any;
10
+ if (typeof __allureAny_comm.step !== 'function') {
11
+ __allureAny_comm.step = async (_name: string, fn: any) => await fn();
12
+ }
13
+
14
+ /**
15
+ * Comm: Encrypt-Password -text: {param} -options: {param}
16
+ *
17
+ * Encrypts the given text as a password and returns it with a "pwd." prefix.
18
+ *
19
+ * @param encryptText - The text to encrypt.
20
+ * @param options - Optional string or object of additional options (parsed if string).
21
+ * @returns A string prefixed with "pwd." followed by the encrypted value.
22
+ *
23
+ * @throws Error if `encryptText` is not a non-empty string.
24
+ *
25
+ */
26
+ export async function encryptPassword(encryptText: string, options?: string | Record<string, any>) {
27
+ const options_json = typeof options === 'string' ? vars.parseLooseJson(options) : (options || {});
28
+ if (typeof encryptText !== 'string' || encryptText.length === 0) {
29
+ throw new Error('❌ encryptPassword: encryptText must be a non-empty string.');
30
+ }
31
+ const doEncrypt = async () => {
32
+ const encryptedText = crypto.encrypt(encryptText);
33
+ console.log('🔐 Encrypted Password:', 'pwd.' + encryptedText);
34
+ return 'pwd.' + encryptedText;
35
+ };
36
+ if (isPlaywrightRunner()) {
37
+ return await __allureAny_comm.step(
38
+ `Comm: Encrypt-Password -text: [redacted] -options: ${JSON.stringify(options_json)}`,
39
+ async () => await doEncrypt()
40
+ );
41
+ }
42
+ return await doEncrypt();
43
+ }
44
+
45
+ /**
46
+ * Comm: Encrypt-Text -text: {param} -options: {param}
47
+ *
48
+ * Encrypts the given text and returns it with an "enc." prefix.
49
+ *
50
+ * @param encryptText - The text to encrypt.
51
+ * @param options - Optional string or object of additional options (parsed if string).
52
+ * @returns A string prefixed with "enc." followed by the encrypted value.
53
+ *
54
+ * @throws Error if `encryptText` is not a non-empty string.
55
+ *
56
+ */
57
+ export async function encryptText(encryptText: string, options?: string | Record<string, any>) {
58
+ const options_json = typeof options === 'string' ? vars.parseLooseJson(options) : (options || {});
59
+ if (typeof encryptText !== 'string' || encryptText.length === 0) {
60
+ throw new Error('❌ encryptText: encryptText must be a non-empty string.');
61
+ }
62
+ const doEncrypt = async () => {
63
+ const encryptedText = crypto.encrypt(encryptText);
64
+ console.log('🔐 Encrypted Text:', 'enc.' + encryptedText);
65
+ return 'enc.' + encryptedText;
66
+ };
67
+ if (isPlaywrightRunner()) {
68
+ return await __allureAny_comm.step(
69
+ `Comm: Encrypt-Text -text: [redacted] -options: ${JSON.stringify(options_json)}`,
70
+ async () => await doEncrypt()
71
+ );
72
+ }
73
+ return await doEncrypt();
74
+ }
75
+
76
+ /**
77
+ * Comm: Encrypt-Password -text: {param} and store in -variable: {param} -options: {param}
78
+ *
79
+ * Encrypts the given password, prefixes it with "pwd.", and stores it in a variable.
80
+ *
81
+ * @param encryptText - The plain text password to encrypt.
82
+ * @param varNameToStore - The name of the variable to store the encrypted password.
83
+ * @param options - Optional string or object of additional options (parsed if string).
84
+ *
85
+ * @throws Error if `encryptText` or `varNameToStore` are not non-empty strings.
86
+ *
87
+ */
88
+ export async function encryptPasswordAndStore(encryptText: string, varNameToStore: string, options?: string | Record<string, any>) {
89
+ const options_json = typeof options === 'string' ? vars.parseLooseJson(options) : (options || {});
90
+ if (typeof encryptText !== 'string' || encryptText.length === 0) {
91
+ throw new Error('❌ encryptPasswordAndStore: encryptText must be a non-empty string.');
92
+ }
93
+ if (typeof varNameToStore !== 'string' || varNameToStore.trim().length === 0) {
94
+ throw new Error('❌ encryptPasswordAndStore: varNameToStore must be a non-empty string.');
95
+ }
96
+ const doEncryptAndStore = async () => {
97
+ const encryptedText = crypto.encrypt(encryptText);
98
+ console.log('🔐 Encrypted Text:', 'pwd.' + encryptedText);
99
+ vars.setValue(varNameToStore, 'pwd.' + encryptedText);
100
+ await comm.attachLog(`✅ Encrypted password stored in "${varNameToStore}"`, 'text/plain');
101
+ };
102
+ if (isPlaywrightRunner()) {
103
+ await __allureAny_comm.step(
104
+ `Comm: Encrypt-Password and store -variable: ${varNameToStore} -options: ${JSON.stringify(options_json)}`,
105
+ async () => await doEncryptAndStore()
106
+ );
107
+ } else {
108
+ await doEncryptAndStore();
109
+ }
110
+ }
111
+
112
+ /**
113
+ * Comm: Encrypt -text: {param} and store in -variable: {param} -options: {param}
114
+ *
115
+ * Encrypts the given text, prefixes it with "enc.", and stores it in a variable.
116
+ *
117
+ * @param encryptText - The text to encrypt.
118
+ * @param varNameToStore - The variable name to store the encrypted text.
119
+ * @param options - Optional string or object of additional options (parsed if string).
120
+ *
121
+ * @throws Error if `encryptText` or `varNameToStore` are not non-empty strings.
122
+ *
123
+ */
124
+ export async function encryptTextAndStore(encryptText: string, varNameToStore: string, options?: string | Record<string, any>) {
125
+ const options_json = typeof options === 'string' ? vars.parseLooseJson(options) : (options || {});
126
+ if (typeof encryptText !== 'string' || encryptText.length === 0) {
127
+ throw new Error('❌ encryptTextAndStore: encryptText must be a non-empty string.');
128
+ }
129
+ if (typeof varNameToStore !== 'string' || varNameToStore.trim().length === 0) {
130
+ throw new Error('❌ encryptTextAndStore: varNameToStore must be a non-empty string.');
131
+ }
132
+ const doEncryptAndStore = async () => {
133
+ const encryptedText = crypto.encrypt(encryptText);
134
+ console.log('🔐 Encrypted Text:', 'enc.' + encryptedText);
135
+ vars.setValue(varNameToStore, 'enc.' + encryptedText);
136
+ await comm.attachLog(`✅ Encrypted text stored in "${varNameToStore}"`, 'text/plain');
137
+ };
138
+ if (isPlaywrightRunner()) {
139
+ await __allureAny_comm.step(
140
+ `Comm: Encrypt-Text and store -variable: ${varNameToStore} -options: ${JSON.stringify(options_json)}`,
141
+ async () => await doEncryptAndStore()
142
+ );
143
+ } else {
144
+ await doEncryptAndStore();
145
+ }
146
+ }
147
+
148
+ /**
149
+ * Comm: Decrypt -text: {param} and store in -variable: {param} -options: {param}
150
+ *
151
+ * Decrypts the given encrypted text and stores the result in a variable.
152
+ *
153
+ * @param encryptedText - The encrypted value to decrypt.
154
+ * @param varName - The variable name to store the decrypted result.
155
+ * @param options - Optional string or object of additional options (parsed if string).
156
+ *
157
+ * @throws Error if `encryptedText` or `varName` are not non-empty strings.
158
+ *
159
+ */
160
+ export async function decrypt(encryptedText: string, varName: string, options?: string | Record<string, any>) {
161
+ const options_json = typeof options === 'string' ? vars.parseLooseJson(options) : (options || {});
162
+ if (typeof encryptedText !== 'string' || encryptedText.length === 0) {
163
+ throw new Error('❌ decrypt: encryptedText must be a non-empty string.');
164
+ }
165
+ if (typeof varName !== 'string' || varName.trim().length === 0) {
166
+ throw new Error('❌ decrypt: varName must be a non-empty string.');
167
+ }
168
+ const doDecryptAndStore = async () => {
169
+ const decryptedText = crypto.decrypt(encryptedText);
170
+ vars.setValue(varName, decryptedText);
171
+ await comm.attachLog(`✅ Decrypted value stored in "${varName}"`, 'text/plain');
172
+ };
173
+ if (isPlaywrightRunner()) {
174
+ await __allureAny_comm.step(
175
+ `Comm: Decrypt -text: [redacted] and store in -variable: ${varName} -options: ${JSON.stringify(options_json)}`,
176
+ async () => await doDecryptAndStore()
177
+ );
178
+ } else {
179
+ await doDecryptAndStore();
180
+ }
181
+ }
182
+
183
+ /**
184
+ * Comm: Get-Random-From-List -arrayList: {param}
185
+ *
186
+ * Selects and returns a random item from a given non-empty array.
187
+ *
188
+ * @template T
189
+ * @param list - The array to select a random item from.
190
+ * @returns A randomly selected item from the array.
191
+ *
192
+ * @throws Error if the list is not a non-empty array.
193
+ *
194
+ */
195
+ export async function getRandomFromList<T>(list: T[]): Promise<T> {
196
+ if (!Array.isArray(list) || list.length === 0) {
197
+ throw new Error("⚠️ getRandomFromList: list must be a non-empty array.");
198
+ }
199
+ const index = Math.floor(Math.random() * list.length);
200
+ return list[index];
201
+ }
202
+
203
+ /**
204
+ * Comm: Remove-Leading-Zero-From-Date -text: {param}
205
+ *
206
+ * Removes leading zeros from both the day and month in a date string of format DD/MM/YYYY.
207
+ * Example: '03/07/2025' => '3/7/2025'
208
+ * @param dateStr - The date string in DD/MM/YYYY format
209
+ * @returns The date string with leading zeros removed from day and month
210
+ *
211
+ * @throws Error if `dateStr` is not a non-empty string.
212
+ */
213
+ export async function removeLeadingZeroFromMonthAndDate(dateStr: string): Promise<string> {
214
+ if (typeof dateStr !== 'string' || dateStr.length === 0) {
215
+ throw new Error('❌ removeLeadingZeroFromMonthAndDate: dateStr must be a non-empty string.');
216
+ }
217
+ return dateStr.replace(/\b0(\d)/g, "$1");
218
+ }
219
+
220
+ interface WriteJsonOptions {
221
+ override?: boolean;
222
+ append?: boolean;
223
+ toArray?: boolean;
224
+ }
225
+
226
+ /**
227
+ * Comm: Write-JSON-To-File -filePath: {param} -data: {param} -options: {param}
228
+ *
229
+ * Writes JSON data to a file with options to override, append, or wrap in array.
230
+ *
231
+ * @param filePath - The destination file path.
232
+ * @param data - The JSON data to write (object or array).
233
+ * @param options - { override, append, toArray }
234
+ *
235
+ * @throws Error if `filePath` is empty, if append mode file content is not a JSON array, or if both `override` and `append` are false.
236
+ */
237
+ export async function writeJsonToFile(
238
+ filePath: string,
239
+ data: any,
240
+ options: WriteJsonOptions = { override: true, append: false, toArray: false }
241
+ ): Promise<void> {
242
+ const defaultOptions = { override: true, append: false, toArray: false };
243
+ const opts = { ...defaultOptions, ...options };
244
+ if (typeof filePath !== 'string' || filePath.trim().length === 0) {
245
+ throw new Error('❌ writeJsonToFile: filePath must be a non-empty string.');
246
+ }
247
+ const absPath = path.resolve(filePath);
248
+
249
+ if (opts.append) {
250
+ // Only works if file contains an array
251
+ let arr: any[] = [];
252
+ if (fs.existsSync(absPath)) {
253
+ const fileContent = fs.readFileSync(absPath, 'utf-8');
254
+ try {
255
+ arr = JSON.parse(fileContent);
256
+ if (!Array.isArray(arr)) throw new Error('File does not contain a JSON array.');
257
+ } catch {
258
+ throw new Error('File is not a valid JSON array.');
259
+ }
260
+ }
261
+ arr.push(data);
262
+ fs.writeFileSync(absPath, JSON.stringify(arr, null, 2), 'utf-8');
263
+ await comm.attachLog(`✅ JSON appended to file: ${absPath}`, 'text/plain');
264
+ } else if (opts.override) {
265
+ // Overwrite or create new file
266
+ let out = data;
267
+ if (opts.toArray) {
268
+ out = Array.isArray(data) ? data : [data];
269
+ }
270
+ fs.writeFileSync(absPath, JSON.stringify(out, null, 2), 'utf-8');
271
+ await comm.attachLog(`✅ JSON written to file: ${absPath}`, 'text/plain');
272
+ } else {
273
+ throw new Error('Either override or append must be true.');
274
+ }
275
+ }
276
+
277
+ /**
278
+ * Ensures the value is formatted as a currency string: $<amount>.00
279
+ * @param value - The input value (number or string)
280
+ * @returns {string} - Formatted as $<amount>.00
281
+ */
282
+ export function toDollarAmount(value: string | number): string {
283
+ // Remove any non-numeric except dot
284
+ let num = typeof value === 'number'
285
+ ? value
286
+ : parseFloat(String(value).replace(/[^0-9.]/g, ''));
287
+ if (isNaN(num)) num = 0;
288
+ return `$${num.toFixed(2)}`;
289
+ }
290
+
291
+ /**
292
+ * Comm: Generate TOTP Token to variable -varName: {param} -options: {param}
293
+ *
294
+ * Generates a TOTP (Time-based One-Time Password) token using the provided secret and stores it in a variable.
295
+ *
296
+ * @param varName - The name of the variable to store the generated TOTP token.
297
+ * @param options - Optional string or object containing:
298
+ * - secret: [string] The TOTP secret key (default: process.env.PLAYQ_TOTP_SECRET_KEY).
299
+ *
300
+ * @example
301
+ * Comm: Generate TOTP Token to variable -varName: "var.otp" -options: '{"secret":"MYSECRET"}'
302
+ */
303
+ export async function generateTotpTokenToVariable(
304
+ varName: string,
305
+ options?: string | Record<string, any>
306
+ ) {
307
+ const options_json = typeof options === "string" ? vars.parseLooseJson(options) : options || {};
308
+ const { secret, step = 30, digits = 6, algorithm = "SHA-1" } = options_json;
309
+
310
+ if (isPlaywrightRunner()) {
311
+ await __allureAny_comm.step(
312
+ `Comm: Generate TOTP Token to variable -varName: ${varName} -options: ${JSON.stringify(options_json)}`,
313
+ async () => {
314
+ await doGenerateTotpTokenToVariable();
315
+ }
316
+ );
317
+ } else {
318
+ await doGenerateTotpTokenToVariable();
319
+ }
320
+
321
+ async function doGenerateTotpTokenToVariable() {
322
+ let secretKey = process.env.PLAYQ_TOTP_SECRET_KEY || secret;
323
+
324
+ if (!secretKey) {
325
+ throw new Error('❌ PLAYQ_TOTP_SECRET_KEY not found in environment variables or in options');
326
+ }
327
+
328
+ if (secretKey.startsWith("enc.")) {
329
+ secretKey = vars.replaceVariables(`#{${secretKey}}`);
330
+ }
331
+ const totpHelper = new TOTPHelper(secretKey);
332
+ // Generate and return token
333
+ const token = totpHelper.generateToken();
334
+ vars.setValue(varName, token);
335
+ }
336
+ }
337
+
338
+ /**
339
+ * Alias: wait
340
+ * Wrapper to maintain compatibility for step names mapping.
341
+ */
342
+ export async function wait(ms: number) {
343
+ await new Promise((resolve) => setTimeout(resolve, ms));
344
+ }
@@ -0,0 +1,18 @@
1
+ /**
2
+ * @file commActions.ts
3
+ *
4
+ * Communication actions gateway for logging, attachments, and utilities.
5
+ * Exposes a stable public surface while implementations live under ./comm/*.
6
+ *
7
+ * Key Features:
8
+ * - Allure-friendly logging and attachment helpers
9
+ * - Error context utilities for diagnostics
10
+ * - Backward-compatible re-exports via gateway
11
+ *
12
+ * Authors: Renish Kozhithottathil [Lead Automation Principal, NCS]
13
+ * Version: v1.0.0
14
+ *
15
+ * Note: This file adheres to the PlayQ Enterprise Automation Standards.
16
+ */
17
+ export * from './comm/commonActions';
18
+ export * from './comm/utilityActions';
@@ -0,0 +1,72 @@
1
+ import { Given, When, Then } from "@cucumber/cucumber";
2
+ import { warn } from "winston";
3
+ import { comm } from "../../global";
4
+
5
+ // commonActions.ts
6
+
7
+ Given("Comm: Wait for milliseconds -seconds: {param}", async function (seconds) {
8
+ await comm.waitInMilliSeconds(parseInt(seconds));
9
+ });
10
+
11
+ Given("Comm: Comment -text: {param}", async function (comment) {
12
+ await comm.comment(comment);
13
+ });
14
+
15
+ Given("Comm: Encrypt password -text: {param} -options: {param}", async function (encryptedText, options) {
16
+ await comm.encryptPassword(encryptedText, options);
17
+ });
18
+
19
+ Given("Comm: Encrypt text -text: {param} -options: {param}", async function (encryptedText, options) {
20
+ await comm.encryptText(encryptedText, options);
21
+ });
22
+
23
+ Given("Comm: Encrypt password -text: {param} and store in -variable: {param} -options: {param}", async function (textToEncrypt, varToStore, options) {
24
+ await comm.encryptPasswordAndStore(textToEncrypt, varToStore, options);
25
+ });
26
+
27
+ Given("Comm: Encrypt text -text: {param} and store in -variable: {param} -options: {param}", async function (textToEncrypt, varToStore, options) {
28
+ console.log('Text to encrypt:', textToEncrypt);
29
+ await comm.encryptTextAndStore(textToEncrypt, varToStore, options);
30
+ });
31
+
32
+ Given("Comm: Decrypt -text: {param} and store in -variable: {param} -options: {param}", async function (encryptedText, varName, options) {
33
+ await comm.decrypt(encryptedText, varName, options);
34
+ });
35
+
36
+ Given("Comm: Get random from list -arrayList: {param}", async function (list) {
37
+ const arrayList = JSON.parse(list);
38
+ await comm.getRandomFromList(arrayList);
39
+ });
40
+
41
+ Given("Comm: Remove leading zero from date -text: {param}", async function (dateText) {
42
+ await comm.removeLeadingZeroFromMonthAndDate(dateText);
43
+ });
44
+
45
+ Given("Comm: Write JSON to file -filePath: {param} -data: {param} -options: {param}", async function (filePath, data, options) {
46
+ await comm.writeJsonToFile(filePath, data, options);
47
+ });
48
+
49
+ Given("Comm: Attach log -message: {param} -mimeType: {param} -msgType: {param}", async function (message, mimeType, msgType) {
50
+ await comm.attachLog(message, mimeType, msgType);
51
+ });
52
+
53
+ Given("Comm: Store -value: {param} in -variable: {param} -options: {param}", async function (value, varName, options) {
54
+ await comm.storeValue(value, varName, options);
55
+ });
56
+
57
+ // utilityActions.ts
58
+ Given("Comm: To Dollar Amount -value: {param}", async function (value) {
59
+ const formatted = await comm.toDollarAmount(Number(value));
60
+ await comm.attachLog(`Formatted dollars: ${formatted}`, 'text/plain', 'COMM');
61
+ });
62
+
63
+ // TOTP token generation
64
+ Given("Comm: Generate TOTP Token to variable -varName: {param} -options: {param}", async function (varName, options) {
65
+ await comm.generateTotpTokenToVariable(varName, options);
66
+ });
67
+
68
+ // utilityActions.ts (alias wait)
69
+ Given("Comm: Wait -ms: {param}", async function (ms) {
70
+ const value = parseInt(String(ms));
71
+ await comm.wait(value);
72
+ });