@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,107 @@
1
+ // src/helper/faker/customFaker.ts
2
+ import { faker as baseFaker } from '@faker-js/faker';
3
+ import { generatePassportNumber } from './modules/passport';
4
+ import { generateMobileNumber } from './modules/mobile';
5
+ import { getValidPostCode } from './modules/postcode';
6
+ import { generatePersonFullName, generateBirthDate } from './modules/person';
7
+ import { generateNRIC,getYearFromNRIC } from './modules/nric';
8
+ import { generateCurrentDateTime, addMonthsToDate } from './modules/dateTime';
9
+
10
+ (baseFaker as any).custom = {
11
+ passport: generatePassportNumber,
12
+ mobile: {
13
+ number: generateMobileNumber
14
+ },
15
+ postcode: {
16
+ get: getValidPostCode
17
+ },
18
+ person: {
19
+ fullName: generatePersonFullName,
20
+ birthDate: generateBirthDate
21
+ },
22
+ nric: {
23
+ generate: generateNRIC,
24
+ getYear: getYearFromNRIC
25
+ },
26
+ datetime: {
27
+ generateCurrentDateTime : generateCurrentDateTime,
28
+ addMonthsToDate: addMonthsToDate
29
+ }
30
+ };
31
+
32
+ export const faker = baseFaker as typeof baseFaker & {
33
+ custom: {
34
+
35
+ passport: (options?: {countryCode?: string}) => string;
36
+
37
+ mobile: {
38
+ number: (options?: {countryCode?: string, dialCodePrefix?: boolean}) => string;
39
+ }
40
+ postcode: {
41
+ get: (options?: {countryCode?: string,stateCode?: string}) => string;
42
+ };
43
+ person: {
44
+ fullName: (options?: { gender?: 'male' | 'female'; withPrefix?: boolean; maxLength?: number;}) => string;
45
+ birthDate: (options?: {min?: number; max?: number; year?: number; format?: | 'DD-MM-YYYY' | 'MM-DD-YYYY' | 'YYYY-MM-DD' | 'DD/MM/YYYY' | 'MM/DD/YYYY' | 'YYYY/MM/DD' | 'DD-MM-YY' | 'MM-DD-YY' | 'YY-MM-DD' | 'DD/MM/YY' | 'MM/DD/YY' | 'YY/MM/DD';}) => string;
46
+ };
47
+ nric: {
48
+ generate: (options?: {prefix?: 'S' | 'T' | 'F' | 'G', yearOfBirth?: number}) => string;
49
+ getYear: (nric: string) => string;
50
+ };
51
+ datetime: {
52
+ /**
53
+ *
54
+ * @param options Eg: {'format': 'DD/MM/YYYY HH:mm:ss'}, {'format': 'YY-MM-DD HH.mm'}
55
+ * @returns
56
+ */
57
+ generateCurrentDateTime : (options?: { format?: string }) => string;
58
+ addMonthsToDate: (
59
+ dateStr: string,
60
+ months: number | string,
61
+ options?: {
62
+ inputFormat?:
63
+ | 'DD-MM-YYYY' | 'MM-DD-YYYY' | 'YYYY-MM-DD'
64
+ | 'DD/MM/YYYY' | 'MM/DD/YYYY' | 'YYYY/MM/DD'
65
+ | 'DD-MM-YY' | 'MM-DD-YY' | 'YY-MM-DD'
66
+ | 'DD/MM/YY' | 'MM/DD/YY' | 'YY/MM/DD';
67
+ outputFormat?:
68
+ | 'DD-MM-YYYY' | 'MM-DD-YYYY' | 'YYYY-MM-DD'
69
+ | 'DD/MM/YYYY' | 'MM/DD/YYYY' | 'YYYY/MM/DD'
70
+ | 'DD-MM-YY' | 'MM-DD-YY' | 'YY-MM-DD'
71
+ | 'DD/MM/YY' | 'MM/DD/YY' | 'YY/MM/DD';
72
+ clampToLastDayOfMonth?: boolean;
73
+ }
74
+ ) => string;
75
+ };
76
+
77
+
78
+
79
+
80
+ };
81
+ // mobile: {
82
+ // number: (countryCode?: string, withCountryCode?: boolean) => string;
83
+ // };
84
+
85
+ // postcode: {
86
+ // valid: {
87
+ // get: (countryCode?: string,stateCode?: string) => string;
88
+ // };
89
+ // };
90
+ };
91
+
92
+
93
+ // // src/helper/faker/customFaker.ts
94
+ // import { faker as baseFaker } from '@faker-js/faker';
95
+ // import { generatePassportNumber } from './modules/passport';
96
+ // import { generateMobileNumber } from './modules/mobile';
97
+
98
+
99
+ // (baseFaker as any).passport = {
100
+ // number: generatePassportNumber
101
+ // };
102
+
103
+ // export const faker = baseFaker as typeof baseFaker & {
104
+ // passport: {
105
+ // number: (countryCode?: string) => string;
106
+ // };
107
+ // };
@@ -0,0 +1,17 @@
1
+ [
2
+ "018937", "049318", "049320", "049712", "059819", "068808", "078867", "089680",
3
+ "098585", "138632", "169208", "178957", "179097", "179098", "188021", "189559",
4
+ "199588", "238882", "238883", "238884", "238885", "238887", "238888",
5
+ "259569", "259571", "259772", "259775", "259776", "259778", "259779",
6
+ "269713", "269716", "269717", "269719", "269720", "269722", "269725", "269726",
7
+ "279116", "279118", "279119", "279121", "279122", "279124", "279125", "279126",
8
+ "307987", "308232", "308275", "308276", "308278", "339511",
9
+ "408600", "408601", "408604", "408605", "408606", "408607",
10
+ "469976", "469977", "469978", "469979", "469980", "469981", "469982", "469983",
11
+ "499936", "499938", "499939", "499941", "499942", "499943",
12
+ "568020", "568021", "568022", "568023", "568024", "568025", "568026", "568027",
13
+ "579799", "579800", "579801", "579804", "579806",
14
+ "608545", "608546", "608547", "608548", "608549", "608550", "608551", "608552",
15
+ "757869", "757870", "757871", "757872", "757873", "757874", "757875", "757876",
16
+ "819642", "819643", "819645", "819646", "819647", "819648", "819649"
17
+ ]
@@ -0,0 +1,121 @@
1
+ import { faker } from '@faker-js/faker';
2
+
3
+
4
+ interface CurrentDateTimeOptions {
5
+ format?: string;
6
+ }
7
+
8
+ export function generateCurrentDateTime(options: CurrentDateTimeOptions = {}): string {
9
+ const { format = 'DD-MM-YYYY HH:mm:ss' } = options;
10
+ const date = new Date();
11
+
12
+ const dd = String(date.getDate()).padStart(2, '0');
13
+ const mm = String(date.getMonth() + 1).padStart(2, '0');
14
+ const yyyy = date.getFullYear();
15
+ const yy = String(yyyy).slice(-2);
16
+ const hh = String(date.getHours()).padStart(2, '0');
17
+ const min = String(date.getMinutes()).padStart(2, '0');
18
+ const ss = String(date.getSeconds()).padStart(2, '0');
19
+
20
+ // Replace tokens in format string
21
+ let result = format;
22
+ result = result.replace(/DD/g, dd)
23
+ .replace(/MM/g, mm)
24
+ .replace(/YYYY/g, String(yyyy))
25
+ .replace(/YY/g, yy)
26
+ .replace(/HH/g, hh)
27
+ .replace(/mm/g, min)
28
+ .replace(/ss/g, ss);
29
+ return result;
30
+ }
31
+
32
+ interface AddMonthsOptions {
33
+ inputFormat?:
34
+ | 'DD-MM-YYYY' | 'MM-DD-YYYY' | 'YYYY-MM-DD'
35
+ | 'DD/MM/YYYY' | 'MM/DD/YYYY' | 'YYYY/MM/DD'
36
+ | 'DD-MM-YY' | 'MM-DD-YY' | 'YY-MM-DD'
37
+ | 'DD/MM/YY' | 'MM/DD/YY' | 'YY/MM/DD';
38
+ outputFormat?:
39
+ | 'DD-MM-YYYY' | 'MM-DD-YYYY' | 'YYYY-MM-DD'
40
+ | 'DD/MM/YYYY' | 'MM/DD/YYYY' | 'YYYY/MM/DD'
41
+ | 'DD-MM-YY' | 'MM-DD-YY' | 'YY-MM-DD'
42
+ | 'DD/MM/YY' | 'MM/DD/YY' | 'YY/MM/DD';
43
+ clampToLastDayOfMonth?: boolean;
44
+ }
45
+
46
+ function parseDate(dateStr: string, format: string): Date {
47
+ const sep = format.includes('/') ? '/' : '-';
48
+ const parts = dateStr.split(sep);
49
+ let day = 1, month = 0, year = 1970;
50
+ switch (format) {
51
+ case 'DD-MM-YYYY': case 'DD/MM/YYYY':
52
+ [day, month, year] = [parseInt(parts[0]), parseInt(parts[1]) - 1, parseInt(parts[2])]; break;
53
+ case 'MM-DD-YYYY': case 'MM/DD/YYYY':
54
+ [month, day, year] = [parseInt(parts[0]) - 1, parseInt(parts[1]), parseInt(parts[2])]; break;
55
+ case 'YYYY-MM-DD': case 'YYYY/MM/DD':
56
+ [year, month, day] = [parseInt(parts[0]), parseInt(parts[1]) - 1, parseInt(parts[2])]; break;
57
+ case 'DD-MM-YY': case 'DD/MM/YY':
58
+ [day, month, year] = [parseInt(parts[0]), parseInt(parts[1]) - 1, 2000 + parseInt(parts[2])]; break;
59
+ case 'MM-DD-YY': case 'MM/DD/YY':
60
+ [month, day, year] = [parseInt(parts[0]) - 1, parseInt(parts[1]), 2000 + parseInt(parts[2])]; break;
61
+ case 'YY-MM-DD': case 'YY/MM/DD':
62
+ [year, month, day] = [2000 + parseInt(parts[0]), parseInt(parts[1]) - 1, parseInt(parts[2])]; break;
63
+ default:
64
+ throw new Error('Unsupported input format');
65
+ }
66
+ return new Date(year, month, day);
67
+ }
68
+
69
+ function formatDate(date: Date, format: string): string {
70
+ const dd = String(date.getDate()).padStart(2, '0');
71
+ const mm = String(date.getMonth() + 1).padStart(2, '0');
72
+ const yyyy = date.getFullYear();
73
+ const yy = String(yyyy).slice(-2);
74
+ switch (format) {
75
+ case 'YYYY-MM-DD': return `${yyyy}-${mm}-${dd}`;
76
+ case 'YYYY/MM/DD': return `${yyyy}/${mm}/${dd}`;
77
+ case 'MM-DD-YYYY': return `${mm}-${dd}-${yyyy}`;
78
+ case 'MM/DD/YYYY': return `${mm}/${dd}/${yyyy}`;
79
+ case 'DD/MM/YYYY': return `${dd}/${mm}/${yyyy}`;
80
+ case 'DD-MM-YYYY': return `${dd}-${mm}-${yyyy}`;
81
+ case 'DD-MM-YY': return `${dd}-${mm}-${yy}`;
82
+ case 'MM-DD-YY': return `${mm}-${dd}-${yy}`;
83
+ case 'YY-MM-DD': return `${yy}-${mm}-${dd}`;
84
+ case 'DD/MM/YY': return `${dd}/${mm}/${yy}`;
85
+ case 'MM/DD/YY': return `${mm}/${dd}/${yy}`;
86
+ case 'YY/MM/DD': return `${yy}/${mm}/${dd}`;
87
+ default: return `${dd}/${mm}/${yy}`;
88
+ }
89
+ }
90
+
91
+ function getLastDayOfMonth(year: number, month: number): number {
92
+ return new Date(year, month + 1, 0).getDate();
93
+ }
94
+
95
+ export function addMonthsToDate(
96
+ dateStr: string,
97
+ months: number | string,
98
+ options: AddMonthsOptions = {}
99
+ ): string {
100
+ const inputFormat = options.inputFormat || 'DD-MM-YY';
101
+ const outputFormat = options.outputFormat || 'DD-MM-YY';
102
+ const clamp = options.clampToLastDayOfMonth || false;
103
+ const date = parseDate(dateStr, inputFormat);
104
+ const originalDay = date.getDate();
105
+ const monthsNum = typeof months === 'string' ? parseInt(months, 10) : months;
106
+ date.setMonth(date.getMonth() + monthsNum);
107
+ if (clamp && date.getDate() !== originalDay) {
108
+ date.setDate(0);
109
+ }
110
+ return formatDate(date, outputFormat);
111
+ }
112
+
113
+ /**
114
+ * Removes leading zeros from both the day and month in a date string of format DD/MM/YYYY.
115
+ * Example: '03/07/2025' => '3/7/2025'
116
+ * @param dateStr - The date string in DD/MM/YYYY format
117
+ * @returns The date string with leading zeros removed from day and month
118
+ */
119
+ export function removeLeadingZeroFromMonthAndDate(dateStr: string): string {
120
+ return dateStr.replace(/\b0(\d)/g, "$1");
121
+ }
@@ -0,0 +1,58 @@
1
+ // src/helper/faker/modules/mobile.ts
2
+ import { faker } from "@faker-js/faker";
3
+
4
+ export function generateMobileNumber(options?: {countryCode?: string, dialCodePrefix?: boolean}): string {
5
+ const {countryCode = 'AU', dialCodePrefix = true } = options || {};
6
+ switch (countryCode.toUpperCase()) {
7
+ case "AU": {
8
+ const prefix = "04";
9
+ const digits = faker.string.numeric(8);
10
+ return dialCodePrefix ? `+61${prefix.slice(1)}${digits}` : `${prefix}${digits}`;
11
+ }
12
+ case "SG": {
13
+ const allowedPrefixes = ["855","955"];
14
+ const prefix = faker.helpers.arrayElement(allowedPrefixes);
15
+ const digits = faker.string.numeric(5);
16
+ return dialCodePrefix ? `+65${prefix}${digits}` : `${prefix}${digits}`;
17
+ }
18
+ case "IN": {
19
+ const allowedPrefixes = ["6", "7", "8", "9"];
20
+ const prefix = faker.helpers.arrayElement(allowedPrefixes);
21
+ const digits = faker.string.numeric(9);
22
+ return dialCodePrefix ? `+91${prefix}${digits}` : `${prefix}${digits}`;
23
+ }
24
+ case "US": {
25
+ const allowedPrefixes = ["2", "3", "4", "5", "6", "7", "8", "9"];
26
+ const prefix = faker.helpers.arrayElement(allowedPrefixes);
27
+ const digits = faker.string.numeric(7);
28
+ return dialCodePrefix ? `+1${prefix}${digits}` : `${prefix}${digits}`;
29
+ }
30
+ case "UK": {
31
+ const allowedPrefixes = ["7", "8", "9"];
32
+ const prefix = faker.helpers.arrayElement(allowedPrefixes);
33
+ const digits = faker.string.numeric(8);
34
+ return dialCodePrefix ? `+44${prefix}${digits}` : `${prefix}${digits}`;
35
+ }
36
+ case "CA": {
37
+ const allowedPrefixes = ["2", "3", "4", "5", "6", "7", "8", "9"];
38
+ const prefix = faker.helpers.arrayElement(allowedPrefixes);
39
+ const digits = faker.string.numeric(7);
40
+ return dialCodePrefix ? `+1${prefix}${digits}` : `${prefix}${digits}`;
41
+ }
42
+ case "NZ": {
43
+ const allowedPrefixes = ["2", "3", "4", "5", "6", "7", "8", "9"];
44
+ const prefix = faker.helpers.arrayElement(allowedPrefixes);
45
+ const digits = faker.string.numeric(7);
46
+ return dialCodePrefix ? `+64${prefix}${digits}` : `${prefix}${digits}`;
47
+ }
48
+ case "PH": {
49
+ const allowedPrefixes = ["8", "9"];
50
+ const prefix = faker.helpers.arrayElement(allowedPrefixes);
51
+ const digits = faker.string.numeric(7);
52
+ return dialCodePrefix ? `+63${prefix}${digits}` : `${prefix}${digits}`;
53
+ }
54
+
55
+ default:
56
+ throw new Error(`Unsupported country code: ${countryCode}`);
57
+ }
58
+ }
@@ -0,0 +1,109 @@
1
+ import { faker } from '@faker-js/faker';
2
+ /**
3
+ * Generate a valid Singapore NRIC or FIN number according to official NRIC/FIN checksum rules.
4
+ *
5
+ * Rules:
6
+ * - The prefix is 'S' or 'T' for Singaporeans/PRs, 'F' or 'G' for foreigners.
7
+ * - 'S' and 'F' are for those registered before 2000, 'T' and 'G' for 2000 and after.
8
+ * - The 7 digits: first two are year of birth/registration, next five are random.
9
+ * - The checksum character is calculated using weights [2,7,6,5,4,3,2] and a modulo-11 algorithm.
10
+ * - For 'T' and 'G', add 4 to the sum before modulo.
11
+ * - The checksum character set differs for citizen/PR ('S','T') and foreigner ('F','G') prefixes.
12
+ * See: https://en.wikipedia.org/wiki/National_Registration_Identity_Card#Structure
13
+ */
14
+ /**
15
+ * Options for NRIC generation.
16
+ */
17
+ export interface NRICOptions {
18
+ prefix?: string;
19
+ yearOfBirth?: number;
20
+ }
21
+ const ST_CHECKSUM_CHARS = ["J", "Z", "I", "H", "G", "F", "E", "D", "C", "B", "A"];
22
+ const FG_CHECKSUM_CHARS = ["X", "W", "U", "T", "R", "Q", "P", "N", "M", "L", "K"];
23
+
24
+ function calculateNRICChecksum(prefix: string, digits: string): string {
25
+ const WEIGHTS = [2, 7, 6, 5, 4, 3, 2];
26
+ const digitArr = digits.split('').map(Number);
27
+ let sum = digitArr.reduce((acc, digit, idx) => acc + digit * WEIGHTS[idx], 0);
28
+ if (prefix === 'T' || prefix === 'G') {
29
+ sum += 4;
30
+ }
31
+ const remainder = sum % 11;
32
+ if (prefix === 'S' || prefix === 'T') {
33
+ return ST_CHECKSUM_CHARS[remainder];
34
+ } else {
35
+ return FG_CHECKSUM_CHARS[remainder];
36
+ }
37
+ }
38
+
39
+ /**
40
+ * Generate a valid Singapore NRIC or FIN number according to official NRIC/FIN checksum rules.
41
+ * @param options - Options for NRIC generation.
42
+ * @returns A valid NRIC string.
43
+ */
44
+ export function generateNRIC(options: NRICOptions = {}): string {
45
+ let { prefix, yearOfBirth } = options;
46
+ yearOfBirth = yearOfBirth ? Number(yearOfBirth) : undefined;
47
+
48
+ if (typeof yearOfBirth === 'number' && yearOfBirth > new Date().getFullYear()) {
49
+ throw new Error(`❌ yearOfBirth ${yearOfBirth} is in the future.`);
50
+ }
51
+
52
+ let resolvedPrefix: string;
53
+
54
+ if (prefix) {
55
+ resolvedPrefix = prefix;
56
+ } else if (typeof yearOfBirth === 'number') {
57
+ resolvedPrefix = yearOfBirth >= 2000 ? 'T' : 'S';
58
+ } else {
59
+ resolvedPrefix = faker.helpers.arrayElement(['S', 'T', 'F', 'G']);
60
+ }
61
+
62
+ if (!['S', 'T', 'F', 'G'].includes(resolvedPrefix)) {
63
+ console.warn(`⚠️ Invalid prefix "${resolvedPrefix}" — choosing random valid prefix.`);
64
+ resolvedPrefix = faker.helpers.arrayElement(['S', 'T', 'F', 'G']);
65
+ }
66
+
67
+ let digits: string;
68
+ if (typeof yearOfBirth === 'number') {
69
+ const yearDigits = String(yearOfBirth).slice(-2);
70
+ const randomDigits = faker.string.numeric({ length: 5, allowLeadingZeros: true });
71
+ digits = `${yearDigits}${randomDigits}`;
72
+ } else {
73
+ digits = faker.string.numeric({ length: 7, allowLeadingZeros: true });
74
+ } const checksum = calculateNRICChecksum(resolvedPrefix, digits);
75
+
76
+ return `${resolvedPrefix}${digits}${checksum}`;
77
+ }
78
+
79
+ /**
80
+ Function to extract the year from an NRIC number
81
+ @param nric - The NRIC number as a string
82
+ @returns The year of birth as a number, or null if the NRIC is invalid
83
+ */
84
+ function getYearFromNRIC(nric: string): number | null {
85
+ if (!/^[STFG]\d{7}[A-Z]$/.test(nric)) {
86
+ console.warn(`❌ Invalid NRIC format: ${nric}`);
87
+ return null;
88
+ }
89
+
90
+ const prefix = nric.charAt(0).toUpperCase();
91
+ const yearDigits = parseInt(nric.slice(1, 3), 10);
92
+
93
+ if (isNaN(yearDigits)) return null;
94
+
95
+ switch (prefix) {
96
+ case "S": // Born before 2000 (Singaporean)
97
+ case "F": // Foreigner before 2000
98
+ return 1900 + yearDigits;
99
+
100
+ case "T": // Born in or after 2000 (Singaporean)
101
+ case "G": // Foreigner in or after 2000
102
+ return 2000 + yearDigits;
103
+
104
+ default:
105
+ return null;
106
+ }
107
+ }
108
+
109
+ export { getYearFromNRIC };
@@ -0,0 +1,34 @@
1
+ // src/helper/faker/modules/passport.ts
2
+ import { faker } from "@faker-js/faker";
3
+
4
+ export function generatePassportNumber(options?: {countryCode?: string}): string {
5
+ const {countryCode = 'AU'} = options;
6
+ switch (countryCode.toUpperCase()) {
7
+ case "IN":
8
+ return `${faker.string.alpha({
9
+ length: 1,
10
+ casing: "upper",
11
+ })}${faker.string.numeric(7)}`;
12
+ case "UK":
13
+ return `${faker.string.alpha({
14
+ length: 2,
15
+ casing: "upper",
16
+ })}${faker.string.numeric(7)}`;
17
+ case "US":
18
+ return faker.string.numeric(9);
19
+ case "AU": {
20
+ const allowedPrefixes = ["PA","PB","PC","PD","PE","PF","PU","PW","PX","PZ"];
21
+ const prefix = faker.helpers.arrayElement(allowedPrefixes);
22
+ const digits = faker.string.numeric(7);
23
+ return `${prefix}${digits}`;
24
+ }
25
+ case "SG": {
26
+ const allowedPrefixes = ["E", "K", "S"];
27
+ const prefix = faker.helpers.arrayElement(allowedPrefixes);
28
+ const digits = faker.string.numeric(7);
29
+ return `${prefix}${digits}`;
30
+ }
31
+ default:
32
+ throw new Error(`Unsupported country code: ${countryCode}`);
33
+ }
34
+ }
@@ -0,0 +1,93 @@
1
+ import { faker } from '@faker-js/faker';
2
+
3
+ interface PersonNameOptions {
4
+ gender?: 'male' | 'female';
5
+ withPrefix?: boolean;
6
+ maxLength?: number;
7
+ }
8
+
9
+ export function generatePersonFullName(options: PersonNameOptions = {}): string {
10
+ const { gender, withPrefix = false, maxLength } = options;
11
+
12
+ let firstName = faker.person.firstName(gender);
13
+ let lastName = faker.person.lastName(gender);
14
+ let fullName = withPrefix
15
+ ? `${faker.person.prefix(gender)} ${firstName} ${lastName}`
16
+ : `${firstName} ${lastName}`;
17
+
18
+ if (maxLength && fullName.length > maxLength) {
19
+ // Try trimming last name first, then first name
20
+ lastName = lastName.slice(0, Math.max(1, Math.floor((maxLength - firstName.length - 1))));
21
+ fullName = withPrefix
22
+ ? `${faker.person.prefix(gender)} ${firstName} ${lastName}`
23
+ : `${firstName} ${lastName}`;
24
+
25
+ if (fullName.length > maxLength) {
26
+ firstName = firstName.slice(0, Math.max(1, maxLength - lastName.length - 1));
27
+ fullName = withPrefix
28
+ ? `${faker.person.prefix(gender)} ${firstName} ${lastName}`
29
+ : `${firstName} ${lastName}`;
30
+ }
31
+ }
32
+
33
+ return fullName.replace(/-/g, ' ');
34
+ }
35
+
36
+ interface BirthDateOptions {
37
+ min?: number;
38
+ max?: number;
39
+ year?: number;
40
+ format?:
41
+ | 'DD-MM-YYYY' | 'MM-DD-YYYY' | 'YYYY-MM-DD'
42
+ | 'DD/MM/YYYY' | 'MM/DD/YYYY' | 'YYYY/MM/DD'
43
+ | 'DD-MM-YY' | 'MM-DD-YY' | 'YY-MM-DD'
44
+ | 'DD/MM/YY' | 'MM/DD/YY' | 'YY/MM/DD';
45
+ }
46
+
47
+ export function generateBirthDate(options: BirthDateOptions = {}): string {
48
+ const { min = 18, max = 65, year, format = 'DD-MM-YYYY' } = options;
49
+ let date: Date;
50
+ // const date = faker.date.birthdate({ min, max, mode: 'age' });
51
+ if (year) {
52
+ // Generate a random date in the given year
53
+ const month = faker.number.int({ min: 0, max: 11 });
54
+ const day = faker.number.int({ min: 1, max: 28 }); // Safe for all months
55
+ date = new Date(year, month, day);
56
+ } else {
57
+ date = faker.date.birthdate({ min, max, mode: 'age' });
58
+ }
59
+
60
+ const dd = String(date.getDate()).padStart(2, '0');
61
+ const mm = String(date.getMonth() + 1).padStart(2, '0');
62
+ const yyyy = date.getFullYear();
63
+ const yy = String(yyyy).slice(-2);
64
+
65
+ switch (format) {
66
+ case 'YYYY-MM-DD':
67
+ return `${yyyy}-${mm}-${dd}`;
68
+ case 'YYYY/MM/DD':
69
+ return `${yyyy}/${mm}/${dd}`;
70
+ case 'MM-DD-YYYY':
71
+ return `${mm}-${dd}-${yyyy}`;
72
+ case 'MM/DD/YYYY':
73
+ return `${mm}/${dd}/${yyyy}`;
74
+ case 'DD/MM/YYYY':
75
+ return `${dd}/${mm}/${yyyy}`;
76
+ case 'DD-MM-YYYY':
77
+ return `${dd}-${mm}-${yyyy}`;
78
+ case 'DD-MM-YY':
79
+ return `${dd}-${mm}-${yy}`;
80
+ case 'MM-DD-YY':
81
+ return `${mm}-${dd}-${yy}`;
82
+ case 'YY-MM-DD':
83
+ return `${yy}-${mm}-${dd}`;
84
+ case 'DD/MM/YY':
85
+ return `${dd}/${mm}/${yy}`;
86
+ case 'MM/DD/YY':
87
+ return `${mm}/${dd}/${yy}`;
88
+ case 'YY/MM/DD':
89
+ return `${yy}/${mm}/${dd}`;
90
+ default:
91
+ return `${dd}-${mm}-${yyyy}`;
92
+ }
93
+ }
@@ -0,0 +1,57 @@
1
+ // src/helper/faker/modules/passport.ts
2
+ import { faker } from "@faker-js/faker";
3
+ import validSGPostcodes from "./data/postcodes_valid_sg.json";
4
+
5
+ interface PostCodeOptions {
6
+ countryCode?: string;
7
+ stateCode?: string;
8
+ }
9
+
10
+
11
+ export function getValidPostCode(options: PostCodeOptions = {}): string {
12
+ // export function getValidPostCode(countryCode: string = "AU", stateCode?: string): string {
13
+ const { countryCode = "AU", stateCode = "" } = options;
14
+
15
+
16
+ switch (countryCode.toUpperCase()) {
17
+ case "SG": {
18
+ return faker.helpers.arrayElement(validSGPostcodes);
19
+ }
20
+
21
+ case "AU":
22
+ const AU_STATE_RANGES: Record<string, [number, number]> = {
23
+ "NSW": [2000, 2999],
24
+ "ACT": [2600, 2639],
25
+ "VIC": [3000, 3999],
26
+ "QLD": [4000, 4999],
27
+ "SA": [5000, 5799],
28
+ "WA": [6000, 6797],
29
+ "TAS": [7000, 7799],
30
+ "NT": [800, 899]
31
+ };
32
+ if (stateCode) {
33
+ const range = AU_STATE_RANGES[stateCode.toUpperCase()];
34
+ if (!range) {
35
+ throw new Error(`Unsupported state code: ${stateCode}`);
36
+ }
37
+ const [min, max] = range;
38
+ const postcodeLength = max.toString().length;
39
+ const postcode = faker.number.int({ min, max }).toString().padStart(postcodeLength, '0');
40
+ return postcode;
41
+ }
42
+ // If no state is specified, choose a random state and generate a postcode
43
+ const randomState = faker.helpers.arrayElement(Object.keys(AU_STATE_RANGES));
44
+ const [min, max] = AU_STATE_RANGES[randomState];
45
+ const postcodeLength = max.toString().length;
46
+ const postcode = faker.number.int({ min, max }).toString().padStart(postcodeLength, '0');
47
+ return postcode;
48
+
49
+
50
+ default:
51
+ throw new Error(`Unsupported country code: ${countryCode}`);
52
+ }
53
+
54
+
55
+
56
+ }
57
+
@@ -0,0 +1,61 @@
1
+ import * as fs from 'fs';
2
+ import * as path from 'path';
3
+
4
+ /**
5
+ * Dynamically builds the `loc` namespace from the consumer project.
6
+ * - Scans PLAYQ_PROJECT_ROOT/resources/locators for *.loc.ts or *.ts files
7
+ * - Imports each module (requires ts-node registration in the child process)
8
+ * - Collects named exports and default object keys into a single namespace
9
+ */
10
+ export function getLocNamespace(): Record<string, any> {
11
+ const base = safeProjectRoot();
12
+ const dir = path.resolve(base, 'resources/locators');
13
+ const out: Record<string, any> = {};
14
+
15
+ if (!fs.existsSync(dir)) {
16
+ // Not an error—project may not provide locators
17
+ return out;
18
+ }
19
+
20
+ const files = fs.readdirSync(dir)
21
+ .filter(f => f.endsWith('.ts') || f.endsWith('.js'))
22
+ .map(f => path.join(dir, f));
23
+
24
+ for (const file of files) {
25
+ try {
26
+ // Clear module cache to reflect changes between runs
27
+ delete require.cache[require.resolve(file)];
28
+ const mod = require(file);
29
+
30
+ // Prefer named exports: export const lambdatest = {...}
31
+ for (const key of Object.keys(mod)) {
32
+ if (key === 'default') continue;
33
+ out[key] = mod[key];
34
+ }
35
+
36
+ // If default export is an object (e.g., { lambdatest: {...} }), merge keys
37
+ const def = mod.default;
38
+ if (def && typeof def === 'object') {
39
+ for (const [k, v] of Object.entries(def)) {
40
+ // Do not overwrite explicitly named exports
41
+ if (!(k in out)) out[k] = v;
42
+ }
43
+ }
44
+ } catch (e: any) {
45
+ console.warn(`⚠️ Failed to load loc module ${file}:`, e?.message || e);
46
+ }
47
+ }
48
+
49
+ return out;
50
+ }
51
+
52
+ function safeProjectRoot(): string {
53
+ if (process.env.PLAYQ_PROJECT_ROOT) return process.env.PLAYQ_PROJECT_ROOT;
54
+ // Walk up to find a package.json as fallback
55
+ let current = process.cwd();
56
+ while (current !== path.dirname(current)) {
57
+ if (fs.existsSync(path.join(current, 'package.json'))) return current;
58
+ current = path.dirname(current);
59
+ }
60
+ return process.cwd();
61
+ }