@anddone/coretestautomation 1.0.1

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 (72) hide show
  1. package/.github/workflows/npm-release.yml +102 -0
  2. package/dist/api/base.api.d.ts +32 -0
  3. package/dist/api/base.api.d.ts.map +1 -0
  4. package/dist/api/base.api.js +7 -0
  5. package/dist/api/base.api.js.map +1 -0
  6. package/dist/api/headers.d.ts +6 -0
  7. package/dist/api/headers.d.ts.map +1 -0
  8. package/dist/api/headers.js +23 -0
  9. package/dist/api/headers.js.map +1 -0
  10. package/dist/index.d.ts +13 -0
  11. package/dist/index.d.ts.map +1 -0
  12. package/dist/index.js +29 -0
  13. package/dist/index.js.map +1 -0
  14. package/dist/pages/basepage.d.ts +6 -0
  15. package/dist/pages/basepage.d.ts.map +1 -0
  16. package/dist/pages/basepage.js +10 -0
  17. package/dist/pages/basepage.js.map +1 -0
  18. package/dist/testData/api.data.json +6 -0
  19. package/dist/utils/apiUtils.d.ts +123 -0
  20. package/dist/utils/apiUtils.d.ts.map +1 -0
  21. package/dist/utils/apiUtils.js +264 -0
  22. package/dist/utils/apiUtils.js.map +1 -0
  23. package/dist/utils/assertionUtils.d.ts +223 -0
  24. package/dist/utils/assertionUtils.d.ts.map +1 -0
  25. package/dist/utils/assertionUtils.js +400 -0
  26. package/dist/utils/assertionUtils.js.map +1 -0
  27. package/dist/utils/commonUtils.d.ts +590 -0
  28. package/dist/utils/commonUtils.d.ts.map +1 -0
  29. package/dist/utils/commonUtils.js +1292 -0
  30. package/dist/utils/commonUtils.js.map +1 -0
  31. package/dist/utils/fakerStaticData.d.ts +16 -0
  32. package/dist/utils/fakerStaticData.d.ts.map +1 -0
  33. package/dist/utils/fakerStaticData.js +88 -0
  34. package/dist/utils/fakerStaticData.js.map +1 -0
  35. package/dist/utils/fileCommonUtils.d.ts +22 -0
  36. package/dist/utils/fileCommonUtils.d.ts.map +1 -0
  37. package/dist/utils/fileCommonUtils.js +243 -0
  38. package/dist/utils/fileCommonUtils.js.map +1 -0
  39. package/dist/utils/generationUtils.d.ts +424 -0
  40. package/dist/utils/generationUtils.d.ts.map +1 -0
  41. package/dist/utils/generationUtils.js +869 -0
  42. package/dist/utils/generationUtils.js.map +1 -0
  43. package/dist/utils/pageUtils.d.ts +90 -0
  44. package/dist/utils/pageUtils.d.ts.map +1 -0
  45. package/dist/utils/pageUtils.js +214 -0
  46. package/dist/utils/pageUtils.js.map +1 -0
  47. package/dist/utils/tableUtils.d.ts +304 -0
  48. package/dist/utils/tableUtils.d.ts.map +1 -0
  49. package/dist/utils/tableUtils.js +555 -0
  50. package/dist/utils/tableUtils.js.map +1 -0
  51. package/dist/utils/validationUtils.d.ts +80 -0
  52. package/dist/utils/validationUtils.d.ts.map +1 -0
  53. package/dist/utils/validationUtils.js +172 -0
  54. package/dist/utils/validationUtils.js.map +1 -0
  55. package/package.json +23 -0
  56. package/playwright.config.ts +79 -0
  57. package/src/api/base.api.ts +39 -0
  58. package/src/api/headers.ts +17 -0
  59. package/src/index.ts +12 -0
  60. package/src/pages/basepage.ts +11 -0
  61. package/src/testData/api.data.json +6 -0
  62. package/src/types/pdf-parse.d.ts +6 -0
  63. package/src/utils/apiUtils.ts +307 -0
  64. package/src/utils/assertionUtils.ts +455 -0
  65. package/src/utils/commonUtils.ts +1544 -0
  66. package/src/utils/fakerStaticData.ts +91 -0
  67. package/src/utils/fileCommonUtils.ts +239 -0
  68. package/src/utils/generationUtils.ts +929 -0
  69. package/src/utils/pageUtils.ts +224 -0
  70. package/src/utils/tableUtils.ts +715 -0
  71. package/src/utils/validationUtils.ts +179 -0
  72. package/tsconfig.json +19 -0
@@ -0,0 +1,172 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.ValidationUtils = void 0;
4
+ const date_fns_1 = require("date-fns");
5
+ class ValidationUtils {
6
+ /**
7
+ * Checks whether a Date object is valid.
8
+ *
9
+ * @param date Date object
10
+ * @returns true if valid Date, false otherwise
11
+ */
12
+ static isValidDate(date) {
13
+ try {
14
+ return date instanceof Date && (0, date_fns_1.isValid)(date);
15
+ }
16
+ catch {
17
+ return false;
18
+ }
19
+ }
20
+ /**
21
+ * Checks whether two dates fall on the same calendar day.
22
+ *
23
+ * @param date1 First date
24
+ * @param date2 Second date
25
+ * @returns True if date1 is before date2
26
+ */
27
+ static isBefore(date1, date2) {
28
+ try {
29
+ return this.isValidDate(date1) && this.isValidDate(date2) && date1.getTime() < date2.getTime();
30
+ }
31
+ catch {
32
+ return false;
33
+ }
34
+ }
35
+ /**
36
+ * Checks whether two dates fall on the same calendar day.
37
+ *
38
+ * @param date1 First date
39
+ * @param date2 Second date
40
+ * @returns True if date1 is after date2
41
+ */
42
+ static isAfter(date1, date2) {
43
+ try {
44
+ return this.isValidDate(date1) && this.isValidDate(date2) && date1.getTime() > date2.getTime();
45
+ }
46
+ catch {
47
+ return false;
48
+ }
49
+ }
50
+ /**
51
+ * Checks whether two dates fall on the same calendar day.
52
+ *
53
+ * @param date1 First date
54
+ * @param date2 Second date
55
+ * @returns True if both dates are on the same day
56
+ */
57
+ static isSameDay(date1, date2) {
58
+ try {
59
+ if (!this.isValidDate(date1) || !this.isValidDate(date2))
60
+ return false;
61
+ return (date1.getFullYear() === date2.getFullYear() &&
62
+ date1.getMonth() === date2.getMonth() &&
63
+ date1.getDate() === date2.getDate());
64
+ }
65
+ catch {
66
+ return false;
67
+ }
68
+ }
69
+ /**
70
+ * Checks whether a list of dates is in ascending order (oldest → newest).
71
+ *
72
+ * @param dates Array of Date objects
73
+ * @returns true if dates are in ascending order
74
+ */
75
+ static isAscendingDateList(dates) {
76
+ try {
77
+ if (!Array.isArray(dates) || dates.length < 2)
78
+ return true;
79
+ for (let i = 1; i < dates.length; i++) {
80
+ if (!this.isAfter(dates[i], dates[i - 1]) &&
81
+ dates[i].getTime() !== dates[i - 1].getTime()) {
82
+ return false;
83
+ }
84
+ }
85
+ return true;
86
+ }
87
+ catch {
88
+ return false;
89
+ }
90
+ }
91
+ /**
92
+ * Checks whether a list of dates is in descending order (newest → oldest).
93
+ *
94
+ * @param dates Array of Date objects
95
+ * @returns true if dates are in descending order
96
+ */
97
+ static isDescendingDateList(dates) {
98
+ try {
99
+ if (!Array.isArray(dates) || dates.length < 2)
100
+ return true;
101
+ for (let i = 1; i < dates.length; i++) {
102
+ if (!this.isBefore(dates[i], dates[i - 1]) &&
103
+ dates[i].getTime() !== dates[i - 1].getTime()) {
104
+ return false;
105
+ }
106
+ }
107
+ return true;
108
+ }
109
+ catch {
110
+ return false;
111
+ }
112
+ }
113
+ /**
114
+ * Checks whether a date string strictly matches the given date format.
115
+ *
116
+ * @param dateStr input date string
117
+ * @param formatStr expected date format
118
+ * @returns true if date matches the format exactly, false otherwise
119
+ *
120
+ * Example:
121
+ * doesDateMatchFormat("02/10/2003", "dd/MM/yyyy") → true
122
+ * doesDateMatchFormat("2/10/2003", "dd/MM/yyyy") → false
123
+ */
124
+ static isDateMatchFormat(dateStr, formatStr) {
125
+ try {
126
+ if (!dateStr || !formatStr)
127
+ return false;
128
+ const parsedDate = (0, date_fns_1.parse)(dateStr, formatStr, new Date());
129
+ if (!this.isValidDate(parsedDate))
130
+ return false;
131
+ const reformatted = (0, date_fns_1.format)(parsedDate, formatStr);
132
+ return reformatted === dateStr;
133
+ }
134
+ catch {
135
+ return false;
136
+ }
137
+ }
138
+ /**
139
+ * Checks whether a string matches a given regular expression.
140
+ *
141
+ * @param value Input string to test
142
+ * @param pattern Regular expression pattern
143
+ * @returns true if pattern matches, otherwise false
144
+ *
145
+ * Example:
146
+ * matchRegex("test@example.com", /^[^\s@]+@[^\s@]+\.[^\s@]+$/) → true
147
+ */
148
+ static isMatchedRegex(value, pattern) {
149
+ try {
150
+ if (!value || !pattern)
151
+ return false;
152
+ return pattern.test(value);
153
+ }
154
+ catch {
155
+ return false;
156
+ }
157
+ }
158
+ /**
159
+ * Validates whether the actual transaction/payment ID matches
160
+ * the expected partially visible and hidden (masked) pattern.
161
+ * @since 27-01-2026
162
+ * @param actualId String (Full transaction/payment ID)
163
+ * @param expectedId String (Expected masked transaction/payment ID)
164
+ * @returns true if the masked actual ID matches the expected ID, otherwise false
165
+ */
166
+ static isTransactionIdMatchingPartialVisibleHiddenPattern(actualId, expectedId) {
167
+ const maskedActualId = `${actualId.slice(0, 6)}...${actualId.slice(-6)}`;
168
+ return expectedId === maskedActualId;
169
+ }
170
+ }
171
+ exports.ValidationUtils = ValidationUtils;
172
+ //# sourceMappingURL=validationUtils.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"validationUtils.js","sourceRoot":"","sources":["../../src/utils/validationUtils.ts"],"names":[],"mappings":"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"}
package/package.json ADDED
@@ -0,0 +1,23 @@
1
+ {
2
+ "name": "@anddone/coretestautomation",
3
+ "version": "1.0.1",
4
+ "main": "index.js",
5
+ "type": "commonjs",
6
+ "scripts": {
7
+ "clean": "rimraf dist",
8
+ "build": "tsc",
9
+ "prepublishOnly": "npm run build"
10
+ },
11
+ "devDependencies": {
12
+ "@playwright/test": "^1.58.0",
13
+ "@types/node": "^25.1.0",
14
+ "@types/xml2js": "^0.4.14"
15
+ },
16
+ "dependencies": {
17
+ "date-fns": "^4.1.0",
18
+ "date-fns-tz": "^3.2.0",
19
+ "pdf-parse": "^1.1.1",
20
+ "xlsx": "^0.18.5",
21
+ "xml2js": "^0.6.2"
22
+ }
23
+ }
@@ -0,0 +1,79 @@
1
+ import { defineConfig, devices } from '@playwright/test';
2
+
3
+ /**
4
+ * Read environment variables from file.
5
+ * https://github.com/motdotla/dotenv
6
+ */
7
+ // import dotenv from 'dotenv';
8
+ // import path from 'path';
9
+ // dotenv.config({ path: path.resolve(__dirname, '.env') });
10
+
11
+ /**
12
+ * See https://playwright.dev/docs/test-configuration.
13
+ */
14
+ export default defineConfig({
15
+ testDir: './tests',
16
+ /* Run tests in files in parallel */
17
+ fullyParallel: true,
18
+ /* Fail the build on CI if you accidentally left test.only in the source code. */
19
+ forbidOnly: !!process.env.CI,
20
+ /* Retry on CI only */
21
+ retries: process.env.CI ? 2 : 0,
22
+ /* Opt out of parallel tests on CI. */
23
+ workers: process.env.CI ? 1 : undefined,
24
+ /* Reporter to use. See https://playwright.dev/docs/test-reporters */
25
+ reporter: 'html',
26
+ /* Shared settings for all the projects below. See https://playwright.dev/docs/api/class-testoptions. */
27
+ use: {
28
+ /* Base URL to use in actions like `await page.goto('')`. */
29
+ // baseURL: 'http://localhost:3000',
30
+
31
+ /* Collect trace when retrying the failed test. See https://playwright.dev/docs/trace-viewer */
32
+ trace: 'on-first-retry',
33
+ },
34
+
35
+ /* Configure projects for major browsers */
36
+ projects: [
37
+ {
38
+ name: 'chromium',
39
+ use: { ...devices['Desktop Chrome'] },
40
+ },
41
+
42
+ {
43
+ name: 'firefox',
44
+ use: { ...devices['Desktop Firefox'] },
45
+ },
46
+
47
+ {
48
+ name: 'webkit',
49
+ use: { ...devices['Desktop Safari'] },
50
+ },
51
+
52
+ /* Test against mobile viewports. */
53
+ // {
54
+ // name: 'Mobile Chrome',
55
+ // use: { ...devices['Pixel 5'] },
56
+ // },
57
+ // {
58
+ // name: 'Mobile Safari',
59
+ // use: { ...devices['iPhone 12'] },
60
+ // },
61
+
62
+ /* Test against branded browsers. */
63
+ // {
64
+ // name: 'Microsoft Edge',
65
+ // use: { ...devices['Desktop Edge'], channel: 'msedge' },
66
+ // },
67
+ // {
68
+ // name: 'Google Chrome',
69
+ // use: { ...devices['Desktop Chrome'], channel: 'chrome' },
70
+ // },
71
+ ],
72
+
73
+ /* Run your local dev server before starting the tests */
74
+ // webServer: {
75
+ // command: 'npm run start',
76
+ // url: 'http://localhost:3000',
77
+ // reuseExistingServer: !process.env.CI,
78
+ // },
79
+ });
@@ -0,0 +1,39 @@
1
+
2
+ export type Header = {
3
+ origin?: string;
4
+ contentType?: string;
5
+ authorization?: string;
6
+ appKey?: string;
7
+ apiKey?: string;
8
+ xVersion?: string;
9
+ }
10
+
11
+ export type Customer = {
12
+ firstName?: string;
13
+ lastName?: string;
14
+ phone?: string;
15
+ email?: string;
16
+ };
17
+
18
+ export type Reference = {
19
+ referenceType?: string;
20
+ referenceKey?: string;
21
+ referenceNumber?: string;
22
+ };
23
+
24
+ export type Split = {
25
+ virtualAccount?: string;
26
+ amount?: number | string;
27
+ reference?: string;
28
+ chargeIndicator?: string;
29
+ };
30
+
31
+ export type Login = {
32
+ userName?: string;
33
+ password?: string;
34
+ }
35
+
36
+ export class BaseAPI {
37
+
38
+
39
+ }
@@ -0,0 +1,17 @@
1
+ import { Header } from "./base.api";
2
+
3
+ export class Headers {
4
+ static headers: Record<string, string>;
5
+
6
+ static getHeaders(options: Header = {}) {
7
+ this.headers = {};
8
+ if (options.origin) this.headers["Origin"] = options.origin;
9
+ if (options.contentType) this.headers["Content-Type"] = options.contentType;
10
+ if (options.authorization)
11
+ this.headers["Authorization"] = "Bearer " + options.authorization;
12
+ if (options.xVersion) this.headers["x-version"] = options.xVersion;
13
+ if (options.apiKey) this.headers["x-api-key"] = options.apiKey;
14
+ if (options.appKey) this.headers["x-app-key"] = options.appKey;
15
+ return this.headers;
16
+ }
17
+ }
package/src/index.ts ADDED
@@ -0,0 +1,12 @@
1
+ export * from "./pages/basepage";
2
+ export * from "./utils/apiUtils";
3
+ export * from "./utils/assertionUtils";
4
+ export * from "./utils/commonUtils";
5
+ export * from "./utils/fakerStaticData";
6
+ export * from "./utils/fileCommonUtils";
7
+ export * from "./utils/generationUtils";
8
+ export * from "./utils/pageUtils";
9
+ export * from "./utils/tableUtils";
10
+ export * from "./utils/validationUtils";
11
+ export * from "./api/base.api";
12
+ export * from "./api/headers";
@@ -0,0 +1,11 @@
1
+ import { Page } from "@playwright/test";
2
+
3
+ export class BasePage {
4
+
5
+ readonly page: Page;
6
+
7
+ constructor(page: Page) {
8
+ this.page = page;
9
+ }
10
+
11
+ }
@@ -0,0 +1,6 @@
1
+ {
2
+ "login": {
3
+ "method": "POST",
4
+ "path": "/users/sessions"
5
+ }
6
+ }
@@ -0,0 +1,6 @@
1
+ declare module "pdf-parse" {
2
+ const pdfParse: (
3
+ data: ArrayBuffer | Buffer | Uint8Array,
4
+ ) => Promise<{ text: string }>;
5
+ export = pdfParse;
6
+ }
@@ -0,0 +1,307 @@
1
+ import { APIRequestContext, APIResponse } from "@playwright/test";
2
+ import apiData from "../testData/api.data.json";
3
+
4
+ type ApiName = keyof typeof apiData;
5
+
6
+ type RequestOptions = {
7
+ body?: unknown;
8
+ headers?: Record<string, string>;
9
+ queryParams?: Record<string, string | number | boolean>;
10
+ pathParams?: Record<string, string>;
11
+ };
12
+
13
+ export class EmptyApiResponse {
14
+ status() {
15
+ return 0;
16
+ }
17
+ ok() {
18
+ return false;
19
+ }
20
+ url() {
21
+ return "";
22
+ }
23
+ async json() {
24
+ return {};
25
+ }
26
+ async text() {
27
+ return "";
28
+ }
29
+ }
30
+
31
+ export class ApiUtils {
32
+ private static apiLogs = false;
33
+
34
+ private static request: APIRequestContext;
35
+ private static response: APIResponse;
36
+
37
+ private static apiMethod: string;
38
+ private static apiPath: string;
39
+
40
+ private static responseCode: number;
41
+ private static responseBody: any;
42
+
43
+ /**
44
+ * This is private method to print json value in pretty format.
45
+ * @param obj
46
+ * @returns
47
+ */
48
+ private static pretty(obj: unknown) {
49
+ try {
50
+ return JSON.stringify(obj, null, 2);
51
+ } catch {
52
+ return String(obj);
53
+ }
54
+ }
55
+
56
+ /**
57
+ * This method to set APIRequestContext object.
58
+ * @param request APIRequestContext
59
+ */
60
+ static setRequest(request: APIRequestContext) {
61
+ this.request = request;
62
+ }
63
+
64
+ /**
65
+ * This method will returns APIRequestContext object.
66
+ * @returns APIRequestContext
67
+ */
68
+ static getRequest() {
69
+ return this.request;
70
+ }
71
+
72
+ /**
73
+ * This method set apiMethod and apiPath using apiData object of the json file.
74
+ * @param apiName ApiName
75
+ */
76
+ static setApiData(apiName: ApiName) {
77
+ this.apiMethod = apiData[apiName].method;
78
+ this.apiPath = apiData[apiName].path;
79
+ }
80
+
81
+ /**
82
+ * This method is to get api method.
83
+ * @returns string
84
+ */
85
+ static geApiMethod() {
86
+ return this.apiMethod;
87
+ }
88
+
89
+ /**
90
+ * This method is get api path.
91
+ * @returns string
92
+ */
93
+ static getApiPath() {
94
+ return this.apiPath;
95
+ }
96
+
97
+ private static buildPath(
98
+ apiPath: string,
99
+ pathParams?: Record<string, string>,
100
+ ): string {
101
+ if (!pathParams) return apiPath;
102
+ let finalPath = apiPath;
103
+ for (const [key, value] of Object.entries(pathParams)) {
104
+ finalPath = finalPath.replace(
105
+ new RegExp(`{${key}}`, "g"),
106
+ encodeURIComponent(String(value)),
107
+ );
108
+ }
109
+ return finalPath;
110
+ }
111
+
112
+ /**
113
+ * This method to log request details in console if apiLogs flag is true.
114
+ * @param method string | 'GET' | 'POST' | 'PUT' | 'DELETE' | 'PATCH'
115
+ * @param url string
116
+ * @param options RequestOptions
117
+ */
118
+ static logRequest(
119
+ method: string | "GET" | "POST" | "PUT" | "DELETE" | "PATCH",
120
+ url: string,
121
+ options?: RequestOptions,
122
+ ) {
123
+ if (this.apiLogs) {
124
+ console.log("Request:");
125
+ console.log(method, url);
126
+ if (options?.headers)
127
+ console.log("Headers:", this.pretty(options.headers));
128
+ if (options?.body) console.log("Body:", this.pretty(options.body));
129
+ if (options?.queryParams)
130
+ console.log("Query Params:", this.pretty(options.queryParams));
131
+ }
132
+ }
133
+
134
+ /**
135
+ * This method is set APIResponse object along with responseCode and responseBody.
136
+ * Also log response details in console if apiLogs flag is true.
137
+ * @param response APIResponse
138
+ */
139
+ static async setResponse(response: APIResponse) {
140
+ this.response = response;
141
+ try {
142
+ this.responseCode = this.response?.status?.() ?? 0;
143
+ } catch (e) {
144
+ this.responseCode = 0;
145
+ }
146
+ try {
147
+ this.responseBody = await response.json();
148
+ } catch (e) {
149
+ this.responseBody = {};
150
+ }
151
+ this.logResponse();
152
+ }
153
+
154
+ /**
155
+ * This method is get APIResponse object.
156
+ * @returns APIResponse
157
+ */
158
+ static getResponse() {
159
+ return this.response;
160
+ }
161
+
162
+ /**
163
+ * This method is get response code.
164
+ * @returns number
165
+ */
166
+ static getResponseCode(): number {
167
+ return this.responseCode;
168
+ }
169
+
170
+ /**
171
+ * This method is get response body.
172
+ * @returns T = unknown
173
+ */
174
+ static getResponseBody<T = unknown>(): T {
175
+ return this.responseBody;
176
+ }
177
+
178
+ /**
179
+ * This method is log response details in console if apiLogs flag is true.
180
+ */
181
+ static logResponse() {
182
+ if (this.apiLogs) {
183
+ console.log("Response:");
184
+ console.log("Status Code:", this.getResponseCode());
185
+ console.log("Body:", this.pretty(this.getResponseBody()));
186
+ }
187
+ }
188
+
189
+ /**
190
+ * This method is to send respuest as per passed details and return response.
191
+ * @param method string | 'GET' | 'POST' | 'PUT' | 'DELETE' | 'PATCH'
192
+ * @param url string - passed Base Url and endpoint together, example: {BaseUrl}+{ApiPath}
193
+ * @param options RequestOptions - this is optional.
194
+ * @returns @link APIResponse
195
+ *
196
+ * Examples:
197
+ * const response = sendRequest('POST', {BaseUrl}+{ApiPath}, {headers: {...headers}, body: {...payload}});
198
+ */
199
+ static async sendRequest(
200
+ method: string | "GET" | "POST" | "PUT" | "DELETE" | "PATCH",
201
+ url: string,
202
+ options?: RequestOptions,
203
+ ) {
204
+ url = this.buildPath(url, options?.pathParams);
205
+ this.logRequest(method, url, options);
206
+ const reqOptions: {
207
+ headers?: Record<string, string>;
208
+ params?: Record<string, string | number | boolean>;
209
+ data?: unknown;
210
+ } = {};
211
+ if (options?.headers) reqOptions.headers = options.headers;
212
+ if (options?.queryParams) reqOptions.params = options.queryParams;
213
+ if (options?.body) reqOptions.data = options.body;
214
+ try {
215
+ const response = await this.getRequest().fetch(url, {
216
+ method,
217
+ ...reqOptions,
218
+ });
219
+ return response;
220
+ } catch (error) {
221
+ const empty = new EmptyApiResponse() as any;
222
+ await this.setResponse(empty);
223
+ return empty;
224
+ }
225
+ }
226
+
227
+ /**
228
+ * This method is get response object value as per passed path.
229
+ * Also if object value not found then you set return some defaultValue which is optional.
230
+ * @param path string - example 'token', 'intent.paymentTypes', 'customers[0].firstName'
231
+ * @param defaultValue T = any
232
+ * @returns T = any
233
+ */
234
+ static async getResponseValue<T = any>(
235
+ path: string,
236
+ defaultValue?: T,
237
+ ): Promise<T> {
238
+ try {
239
+ const body = (await this.getResponseBody()) as any;
240
+ if (!body || !path) {
241
+ return defaultValue !== undefined ? defaultValue : ("" as any);
242
+ }
243
+ const result = path
244
+ .replace(/\[(\d+)\]/g, ".$1")
245
+ .split(".")
246
+ .reduce((obj, key) => obj?.[key], body);
247
+ if (result === undefined || result === null) {
248
+ return defaultValue !== undefined ? defaultValue : ("" as any);
249
+ }
250
+ return result;
251
+ } catch {
252
+ return defaultValue !== undefined ? defaultValue : ("" as any);
253
+ }
254
+ }
255
+
256
+ /**
257
+ * This method is get response object value as array.
258
+ * @param path string - example 'customers'
259
+ * @returns T = any []
260
+ */
261
+ static async getResponseArray<T = any>(path: string): Promise<T[]> {
262
+ const value = await this.getResponseValue(path, []);
263
+ return Array.isArray(value) ? value : [];
264
+ }
265
+
266
+ /**
267
+ * Finds an object inside an array and returns its id where multiple fields match
268
+ * @param arrayPath Path to array. Example: "data"
269
+ * @param match Object with fields to match. Example: { allyName: "Zbook1201", status: "ACTIVE" }
270
+ * @param objectName Object name of which value return . "id"
271
+ */
272
+ static async getResponseValueFromArray(
273
+ arrayPath: string,
274
+ objectName: string,
275
+ match: Record<string, any>,
276
+ ): Promise<string> {
277
+ try {
278
+ if (!match || typeof match !== "object") {
279
+ return "";
280
+ }
281
+ let arr: any[];
282
+ if (!arrayPath) {
283
+ const body = await this.getResponseBody();
284
+ arr = Array.isArray(body) ? body : [];
285
+ } else {
286
+ arr = await this.getResponseArray<any>(arrayPath);
287
+ }
288
+ if (!Array.isArray(arr) || arr.length === 0) {
289
+ return "";
290
+ }
291
+ const found = arr.find((item) => {
292
+ if (!item || typeof item !== "object") return false;
293
+ return Object.entries(match).every(
294
+ ([key, value]) => item?.[key] === value,
295
+ );
296
+ });
297
+ if (!found || typeof found !== "object") {
298
+ return "";
299
+ }
300
+ const result = found?.[objectName];
301
+ return result !== undefined && result !== null ? String(result) : "";
302
+ } catch (error) {
303
+ // Optional: console.warn("⚠️ getResponseValueFromArray failed:", error);
304
+ return "";
305
+ }
306
+ }
307
+ }