@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,1292 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.CommonUtils = void 0;
4
+ class CommonUtils {
5
+ static resolveOptions(options) {
6
+ return {
7
+ timeout: options?.timeout ?? 15000,
8
+ description: options?.description ?? 'Element',
9
+ };
10
+ }
11
+ /**
12
+ * Highlights a UI element on the page for debugging and visual validation.
13
+ */
14
+ static async highlight(locator) {
15
+ if (!this.isHighlight)
16
+ return;
17
+ try {
18
+ await locator.highlight();
19
+ }
20
+ catch {
21
+ console.warn('⚠ highlight skipped: page/locator not ready');
22
+ }
23
+ }
24
+ /**
25
+ * Waits for a Playwright locator to become visible on the page.
26
+ *
27
+ * @param locator - Playwright Locator to wait for
28
+ * @param options - Optional configuration object
29
+ * @param options.timeout - Maximum wait time in milliseconds (default: 15000)
30
+ * @param options.description - Logical name of the element for logging purposes
31
+ *
32
+ * @example
33
+ * await CommonUtils.waitForVisible(loginButton);
34
+ *
35
+ * @example
36
+ * await CommonUtils.waitForVisible(loginButton, {timeout: 5000,description: 'Login Button'});
37
+ */
38
+ static async waitForVisible(locator, options = {}) {
39
+ const { timeout, description } = this.resolveOptions(options);
40
+ try {
41
+ await locator.waitFor({ state: 'visible', timeout });
42
+ }
43
+ catch {
44
+ console.error(`❌ ${description} not visible after ${timeout}ms`);
45
+ }
46
+ }
47
+ /**
48
+ * Waits for a Playwright locator to become hidden or removed from the DOM.
49
+ *
50
+ * @param locator - Playwright Locator to wait for
51
+ * @param options - Optional configuration object
52
+ * @param options.timeout - Maximum wait time in milliseconds (default: 15000)
53
+ * @param options.description - Logical name of the element for logging purposes
54
+ *
55
+ * @example
56
+ * await CommonUtils.waitForInvisible(loginButton);
57
+ *
58
+ * @example
59
+ * await CommonUtils.waitForInvisible(loginButton, {timeout: 5000,description: 'Login Button'});
60
+ */
61
+ static async waitForInvisible(locator, options = {}) {
62
+ const { timeout, description } = this.resolveOptions(options);
63
+ try {
64
+ await locator.waitFor({ state: 'hidden', timeout });
65
+ }
66
+ catch {
67
+ console.error(`❌ ${description} Element still visible after ${timeout}ms`);
68
+ }
69
+ }
70
+ /**
71
+ * Pauses execution for a specified number of seconds.
72
+ *
73
+ * @param seconds - Number of seconds to wait
74
+ *
75
+ * @example
76
+ * await CommonUtils.waitSeconds(3);
77
+ *
78
+ * @returns Promise<void>
79
+ */
80
+ static async waitSeconds(seconds) {
81
+ try {
82
+ await new Promise(resolve => setTimeout(resolve, seconds * 1000));
83
+ }
84
+ catch (error) {
85
+ console.warn(`⚠ Error during wait:`, error.message);
86
+ }
87
+ }
88
+ /**
89
+ * Clicks on a web element after waiting for it to become visible.
90
+ *
91
+ * If the element is not found or the click fails, the error is logged
92
+ *
93
+ * @param locator - Playwright Locator to be clicked
94
+ * @param options - Optional configuration object
95
+ * @param options.timeout - Maximum wait time for visibility and click (default: 15000 ms)
96
+ * @param options.description - Logical name of the element for logging purposes
97
+ *
98
+ * @example
99
+ * await CommonUtils.click(loginButton);
100
+ *
101
+ * @example
102
+ * await CommonUtils.click(loginButton, {timeout: 5000,description: 'Login Button'});
103
+ */
104
+ static async click(locator, options = {}) {
105
+ const { timeout, description } = this.resolveOptions(options);
106
+ try {
107
+ await this.waitForVisible(locator, options);
108
+ await this.highlight(locator);
109
+ await locator.click({ timeout });
110
+ }
111
+ catch (error) {
112
+ console.warn(`⚠ Click skipped on ${description}: ${error.message}`);
113
+ }
114
+ }
115
+ /**
116
+ * Fills text into an input field after ensuring it is visible.
117
+ *
118
+ * @param locator - Playwright Locator of the input element
119
+ * @param text - Text value to be entered into the field
120
+ * @param options - Optional configuration object
121
+ * @param options.timeout - Maximum wait time for visibility (default: 15000 ms)
122
+ * @param options.description - Logical name of the element for logging purposes
123
+ *
124
+ * @example
125
+ * await CommonUtils.fill(usernameInput, 'admin');
126
+ *
127
+ * @example
128
+ * await CommonUtils.fill(usernameInput, 'admin', {timeout: 5000,description: 'Username Input'
129
+ * });
130
+ */
131
+ static async fill(locator, text, options = {}) {
132
+ const { timeout, description } = this.resolveOptions(options);
133
+ try {
134
+ await this.waitForVisible(locator, options);
135
+ await this.highlight(locator);
136
+ await locator.fill(text, { timeout });
137
+ }
138
+ catch (error) {
139
+ console.warn(`⚠ Fill skipped on ${description}. Reason: ${error.message}`);
140
+ }
141
+ }
142
+ /**
143
+ * Types text into an input or editable element using keyboard events.
144
+ *
145
+ * @param locator - Playwright Locator of the input or editable element
146
+ * @param text - Text to be typed into the element
147
+ * @param options - Optional configuration object
148
+ * @param options.timeout - Maximum wait time for visibility (default: 15000 ms)
149
+ * @param options.description - Logical name of the element for logging purposes
150
+ *
151
+ * @example
152
+ * await CommonUtils.typeText(usernameInput, 'admin');
153
+ *
154
+ * @example
155
+ * await CommonUtils.typeText(passwordInput, 'password123', {
156
+ * timeout: 5000,
157
+ * description: 'Password Input'
158
+ * });
159
+ */
160
+ static async typeText(locator, text, options = {}) {
161
+ const { timeout, description } = this.resolveOptions(options);
162
+ try {
163
+ await this.waitForVisible(locator, options);
164
+ await this.highlight(locator);
165
+ await locator.type(text, { delay: 50, timeout });
166
+ }
167
+ catch (error) {
168
+ console.warn(`⚠ Type skipped on ${description}. Reason: ${error.message}`);
169
+ }
170
+ }
171
+ /**
172
+ * Checks whether a locator is visible within the given timeout.
173
+ *
174
+ * @param locator - Locator of the element to check
175
+ * @param options - Optional configuration (timeout in ms, description)
176
+ * @returns True if the element becomes visible, otherwise false
177
+ *
178
+ * @example
179
+ * const visible = await CommonUtils.isVisible(page.locator('#loginButton'));
180
+ * const visibleWithDesc = await CommonUtils.isVisible(page.locator('#loginButton'), {timeout:5000, description:'Login Button'});
181
+ */
182
+ static async isVisible(locator, options = {}) {
183
+ const { timeout, description } = this.resolveOptions(options);
184
+ try {
185
+ await this.waitForVisible(locator, options);
186
+ await this.highlight(locator);
187
+ return await locator.isVisible();
188
+ }
189
+ catch {
190
+ console.warn(`⚠ ${description} is not visible`);
191
+ return false;
192
+ }
193
+ }
194
+ /**
195
+ * Checks whether a locator is enabled (interactable).
196
+ *
197
+ * @param locator - Locator of the element to check
198
+ * @param options - Optional configuration (timeout in ms, description)
199
+ * @returns True if the element is enabled, otherwise false
200
+ *
201
+ * @example
202
+ * const enabled = await CommonUtils.isEnabled(page.locator('#submitButton'));
203
+ */
204
+ static async isEnabled(locator, options = {}) {
205
+ const { timeout, description } = this.resolveOptions(options);
206
+ try {
207
+ await this.waitForVisible(locator, options);
208
+ await this.highlight(locator);
209
+ return await locator.isEnabled();
210
+ }
211
+ catch {
212
+ console.warn(`⚠ ${description} is not enabled`);
213
+ return false;
214
+ }
215
+ }
216
+ /**
217
+ * Checks whether a locator is disabled.
218
+ *
219
+ * @param locator - Locator of the element to check
220
+ * @param options - Optional configuration (timeout in ms, description)
221
+ * @returns True if the element is disabled or not interactable, otherwise false
222
+ *
223
+ * @example
224
+ * const disabled = await CommonUtils.isDisabled(page.locator('#cancelButton'));
225
+ */
226
+ static async isDisabled(locator, options = {}) {
227
+ const { timeout, description } = this.resolveOptions(options);
228
+ try {
229
+ await this.waitForVisible(locator, options);
230
+ await this.highlight(locator);
231
+ return await locator.isDisabled();
232
+ }
233
+ catch {
234
+ console.warn(`⚠ ${description} is not disabled`);
235
+ return true;
236
+ }
237
+ }
238
+ /**
239
+ * Checks whether a locator is editable.
240
+ *
241
+ * @param locator - Locator of the element to check
242
+ * @param options - Optional configuration (timeout in ms, description)
243
+ * @returns True if the element is editable, otherwise false
244
+ *
245
+ * @example
246
+ * const editable = await CommonUtils.isEditable(page.locator('#nameInput'));
247
+ */
248
+ static async isEditable(locator, options = {}) {
249
+ const { timeout, description } = this.resolveOptions(options);
250
+ try {
251
+ await this.waitForVisible(locator, options);
252
+ await this.highlight(locator);
253
+ return await locator.isEditable();
254
+ }
255
+ catch {
256
+ console.warn(`⚠ ${description} is not editable`);
257
+ return false;
258
+ }
259
+ }
260
+ /**
261
+ * Checks whether a checkbox or radio button is checked.
262
+ *
263
+ * @param locator - Locator of the checkbox or radio element
264
+ * @param options - Optional configuration (timeout in ms, description)
265
+ * @returns True if the element is checked, otherwise false
266
+ *
267
+ * @example
268
+ * const checked = await CommonUtils.isChecked(page.locator('#acceptTerms'));
269
+ */
270
+ static async isChecked(locator, options = {}) {
271
+ const { timeout, description } = this.resolveOptions(options);
272
+ try {
273
+ await this.waitForVisible(locator, options);
274
+ await this.highlight(locator);
275
+ return await locator.isChecked();
276
+ }
277
+ catch {
278
+ console.warn(`⚠ ${description} is not checked`);
279
+ return false;
280
+ }
281
+ }
282
+ /**
283
+ * Checks whether a locator is hidden within the given timeout.
284
+ *
285
+ * @param locator - Locator of the element to check
286
+ * @param options - Optional configuration (timeout in ms, description)
287
+ * @returns True if the element is hidden or not visible, otherwise false
288
+ *
289
+ * @example
290
+ * const hidden = await CommonUtils.isHidden(page.locator('#loadingSpinner'));
291
+ */
292
+ static async isHidden(locator, options = {}) {
293
+ const { description } = this.resolveOptions(options);
294
+ try {
295
+ await this.waitForInvisible(locator, options);
296
+ return true;
297
+ }
298
+ catch {
299
+ console.warn(`⚠ ${description} is not hidden`);
300
+ return false;
301
+ }
302
+ }
303
+ /**
304
+ * Clears the value of an input or editable element.
305
+ *
306
+ * @param locator - Locator of the element to clear
307
+ * @param options - Optional configuration (timeout in ms, description)
308
+ *
309
+ * @example
310
+ * await CommonUtils.clear(page.locator('#searchInput'));
311
+ * await CommonUtils.clear(page.locator('#searchInput'), {timeout: 5000, description: 'Search Input'});
312
+ */
313
+ static async clear(locator, options = {}) {
314
+ const { description } = this.resolveOptions(options);
315
+ try {
316
+ await this.waitForVisible(locator, options);
317
+ await this.highlight(locator);
318
+ await locator.clear();
319
+ }
320
+ catch (error) {
321
+ console.warn(`⚠ Unable to clear ${description}: ${error.message}`);
322
+ }
323
+ }
324
+ /**
325
+ * Retrieves the value of a specified attribute from an element.
326
+ *
327
+ * @param locator - Locator of the element
328
+ * @param attributeName - Name of the attribute to retrieve
329
+ * @param options - Optional configuration (timeout in ms, description)
330
+ * @returns Attribute value or null if not found
331
+ */
332
+ static async getAttributeValue(locator, attributeName, options = {}) {
333
+ const { timeout, description } = this.resolveOptions(options);
334
+ try {
335
+ await locator.waitFor({ state: 'attached', timeout });
336
+ await this.highlight(locator);
337
+ return await locator.getAttribute(attributeName);
338
+ }
339
+ catch (error) {
340
+ console.warn(`⚠ Unable to get attribute "${attributeName}" from ${description}`, error.message);
341
+ return null;
342
+ }
343
+ }
344
+ /**
345
+ * Checks whether an element's attribute value contains the expected text.
346
+ *
347
+ * @param locator - Locator of the element
348
+ * @param attributeName - Attribute to inspect
349
+ * @param expectedValue - Text expected to be contained in the attribute
350
+ * @param options - Optional configuration (timeout in ms, description)
351
+ * @returns True if attribute contains the expected value
352
+ */
353
+ static async isAttributeValueContains(locator, attributeName, expectedValue, options = {}) {
354
+ const { timeout, description } = this.resolveOptions(options);
355
+ try {
356
+ await locator.waitFor({ state: 'attached', timeout });
357
+ await this.highlight(locator);
358
+ const attributeValue = await this.getAttributeValue(locator, attributeName, options);
359
+ return attributeValue?.includes(expectedValue) ?? false;
360
+ }
361
+ catch {
362
+ console.warn(`⚠ Attribute "${attributeName}" of ${description} does not contain "${expectedValue}"`);
363
+ return false;
364
+ }
365
+ }
366
+ /**
367
+ * Retrieves visible text from a Playwright locator.
368
+ *
369
+ * @param locator - Playwright Locator from which text is retrieved
370
+ * @param options - Optional configuration object
371
+ * @param options.timeout - Maximum wait time for visibility (default: 15000 ms)
372
+ * @param options.description - Logical name of the element for logging
373
+ *
374
+ * @returns The extracted text, or an empty string if unavailable
375
+ *
376
+ * @example
377
+ * const header = await CommonUtils.getText(pageHeader);
378
+ *
379
+ * @example
380
+ * const errorMsg = await CommonUtils.getText(errorLabel, {
381
+ * timeout: 5000,
382
+ * description: 'Error Message'
383
+ * });
384
+ */
385
+ static async getText(locator, options = {}) {
386
+ const { description } = this.resolveOptions(options);
387
+ try {
388
+ await this.waitForVisible(locator, options);
389
+ await this.highlight(locator);
390
+ const text = await locator.innerText();
391
+ return text.trim();
392
+ }
393
+ catch (error) {
394
+ console.warn(`⚠ Unable to get text from ${description}. Reason: ${error.message}`);
395
+ return '';
396
+ }
397
+ }
398
+ /**
399
+ * Retrieves the visible innerText of an element.
400
+ *
401
+ * @param locator - Locator of the target element
402
+ * @param options - Optional action settings
403
+ * @param options.timeout - Maximum time to wait for the element to become visible (default: 1500)
404
+ * @param options.description - Description of the element used for logging
405
+ *
406
+ * @example
407
+ * const text = await getInnerText(title);
408
+ *
409
+ * @example
410
+ * const text = await getInnerText(title, {description: 'Page title',timeout: 3000
411
+ * });
412
+ *
413
+ * @returns Trimmed innerText, or empty string if unavailable
414
+ */
415
+ static async getInnerText(locator, options = {}) {
416
+ const { description } = this.resolveOptions(options);
417
+ try {
418
+ const target = locator.first();
419
+ this.waitForVisible(target, options);
420
+ await this.highlight(target);
421
+ return (await target.innerText()).trim();
422
+ }
423
+ catch (error) {
424
+ console.warn(`⚠ Unable to get innerText from ${description}`, error.message);
425
+ return '';
426
+ }
427
+ }
428
+ /**
429
+ * Gets trimmed innerText values from a list of elements.
430
+ *
431
+ * @param locatorList - Locator representing multiple elements
432
+ * @param options - Optional action settings
433
+ * @param options.timeout - Maximum wait time for at least one element to become visible (default: 1500)
434
+ * @param options.description - Description of the element list used for logging
435
+ *
436
+ * @example
437
+ * const texts = await CommonUtils.getAllInnerText(listItems);
438
+ *
439
+ * @example
440
+ * const texts = await CommonUtils.getAllInnerText(listItems, {
441
+ * description: 'Fruit list items',
442
+ * timeout: 5000
443
+ * });
444
+ *
445
+ * @returns Array of trimmed innerText values, or empty array if none found
446
+ */
447
+ static async getAllInnerText(locatorList, options = {}) {
448
+ const { description = 'Element list' } = options;
449
+ try {
450
+ const first = locatorList.first();
451
+ this.waitForVisible(first, options);
452
+ await this.highlight(first);
453
+ const texts = await locatorList.allInnerTexts();
454
+ return texts.map(t => t.trim());
455
+ }
456
+ catch (error) {
457
+ console.warn(`⚠ Unable to get innerText values from ${description}:`, error.message);
458
+ return [];
459
+ }
460
+ }
461
+ /**
462
+ * Gets trimmed textContent values from a list of elements.
463
+ *
464
+ * @param locatorList - Locator representing multiple elements
465
+ * @param options - Optional action settings
466
+ * @param options.timeout - Maximum wait time for at least one element to be attached (default: 1500)
467
+ * @param options.description - Description of the element list used for logging
468
+ *
469
+ * @example
470
+ * const texts = await CommonUtils.getAllText(listItems);
471
+ *
472
+ * @example
473
+ * const texts = await CommonUtils.getAllText(listItems, {
474
+ * description: 'Fruit list items',
475
+ * timeout: 5000
476
+ * });
477
+ *
478
+ * @returns Array of trimmed textContent values, or empty array if none found
479
+ */
480
+ static async getAllText(locatorList, options = {}) {
481
+ const { description = 'Element list' } = options;
482
+ try {
483
+ const first = locatorList.first();
484
+ this.waitForVisible(first, options);
485
+ await this.highlight(first);
486
+ const texts = await locatorList.allTextContents();
487
+ return texts.map(t => t.trim());
488
+ }
489
+ catch (error) {
490
+ console.warn(`⚠ Unable to get textContent values from ${description}:`, error.message);
491
+ return [];
492
+ }
493
+ }
494
+ /**
495
+ * Fetches the trimmed text of a specific child tag inside a locator.
496
+ *
497
+ * @param locator - Locator of the parent element
498
+ * @param tagName - Tag name of the child element to fetch text from (e.g., 'span', 'p')
499
+ * @param options - Optional action settings
500
+ * @param options.timeout - Maximum time to wait for the element (default: 15000)
501
+ * @param options.description - Description of the element used for logging
502
+ *
503
+ * @example
504
+ * const spanText = await CommonUtils.getTextByTag(parentDiv, 'span');
505
+ *
506
+ * @example
507
+ * const spanText = await CommonUtils.getTextByTag(parentDiv, 'span', {
508
+ * description: 'Amount label',
509
+ * timeout: 5000
510
+ * });
511
+ *
512
+ * @returns Trimmed text of the child element, or empty string if not found
513
+ */
514
+ static async getTextByTag(locator, tagName, options = {}) {
515
+ const { timeout, description } = this.resolveOptions(options);
516
+ try {
517
+ await this.waitForVisible(locator, options);
518
+ await this.highlight(locator);
519
+ const child = locator.locator(tagName).first();
520
+ await child.waitFor({ state: 'visible', timeout });
521
+ const text = await child.innerText();
522
+ return text.trim();
523
+ }
524
+ catch (error) {
525
+ console.warn(`⚠ Unable to get text from <${tagName}> of ${description}: ${error.message}`);
526
+ return '';
527
+ }
528
+ }
529
+ /**
530
+ * Finds the index of the first element whose innerText exactly matches the expected value.
531
+ *
532
+ * @param locatorList - Locator representing a list of elements
533
+ * @param expected - Exact text to match against each element's innerText
534
+ * @param options - Optional action settings
535
+ * @param options.timeout - Maximum time to wait for at least one element to become visible (default: 1500)
536
+ * @param options.description - Description of the element list used for logging
537
+ *
538
+ * @example
539
+ * const index = await getIndexOfExpected(listItems, 'Apple');
540
+ *
541
+ * @example
542
+ * const index = await getIndexOfExpected(listItems,'Apple',
543
+ * { description: 'Fruit list items', timeout: 5000 }
544
+ * );
545
+ *
546
+ * @returns Zero-based index of the matched element, or -1 if not found
547
+ */
548
+ static async getIndexOfExpected(locatorList, expected, options = {}) {
549
+ const { timeout, description } = this.resolveOptions(options);
550
+ try {
551
+ await locatorList.first().waitFor({ state: 'visible', timeout });
552
+ const count = await locatorList.count();
553
+ for (let i = 0; i < count; i++) {
554
+ const item = locatorList.nth(i);
555
+ await this.highlight(item);
556
+ const text = await this.getInnerText(item);
557
+ if (text === expected)
558
+ return i;
559
+ }
560
+ console.warn(`⚠ "${expected}" not found in ${description}`);
561
+ return -1;
562
+ }
563
+ catch (error) {
564
+ console.warn(`⚠ Unable to get index for "${expected}" in ${description}`, error.message);
565
+ return -1;
566
+ }
567
+ }
568
+ /**
569
+ * Checks if an element's innerText exactly matches the expected text.
570
+ *
571
+ * @param locator - Locator of the target element
572
+ * @param expected - Expected text to match exactly against the element's innerText
573
+ * @param options - Optional action settings
574
+ * @param options.timeout - Maximum time to wait for the element to become visible (default: 1500)
575
+ * @param options.description - Description of the element used for logging
576
+ *
577
+ * @example
578
+ * const isMatch = await isElementTextMatchInnerText(title, 'Welcome');
579
+ *
580
+ * @example
581
+ * const isMatch = await isElementTextMatchInnerText(title, 'Welcome', {
582
+ * description: 'Page title',
583
+ * timeout: 3000
584
+ * });
585
+ *
586
+ * @returns True if the element's innerText matches the expected text exactly, otherwise false
587
+ */
588
+ static async isElementTextMatchInnerText(locator, expected, options = {}) {
589
+ const { description } = this.resolveOptions(options);
590
+ try {
591
+ await this.waitForVisible(locator, options);
592
+ await this.highlight(locator);
593
+ const actualText = await this.getInnerText(locator);
594
+ return actualText === expected;
595
+ }
596
+ catch {
597
+ console.warn(`⚠ innerText of ${description} does not match "${expected}"`);
598
+ return false;
599
+ }
600
+ }
601
+ /**
602
+ * Checks if an element's innerText contains the expected text.
603
+ *
604
+ * @param locator - Locator of the target element
605
+ * @param expected - Text expected to be contained within the element's innerText
606
+ * @param options - Optional action settings
607
+ * @param options.timeout - Maximum time to wait for the element to become visible (default: 1500)
608
+ * @param options.description - Description of the element used for logging
609
+ *
610
+ * @example
611
+ * const contains = await isElementTextContainsInnerText(message, 'Success');
612
+ *
613
+ * @example
614
+ * const contains = await isElementTextContainsInnerText(message, 'Success', {
615
+ * description: 'Toast message'
616
+ * });
617
+ *
618
+ * @returns True if the element's innerText contains the expected text, otherwise false
619
+ */
620
+ static async isElementTextContainsInnerText(locator, expected, options = {}) {
621
+ const { description } = this.resolveOptions(options);
622
+ try {
623
+ await this.waitForVisible(locator, options);
624
+ await this.highlight(locator);
625
+ const actualText = await this.getInnerText(locator);
626
+ return actualText.includes(expected);
627
+ }
628
+ catch {
629
+ console.warn(`⚠ innerText of ${description} does not contain "${expected}"`);
630
+ return false;
631
+ }
632
+ }
633
+ /**
634
+ * Checks if an element's textContent exactly matches the expected text.
635
+ *
636
+ * @param locator - Locator of the target element
637
+ * @param expected - Expected text to match exactly against the element's textContent
638
+ * @param options - Optional action settings
639
+ * @param options.timeout - Maximum time to wait for the element to become visible (default: 1500)
640
+ * @param options.description - Description of the element used for logging
641
+ *
642
+ * @example
643
+ * const isExact = await isElementTextMatchText(label, 'Username');
644
+ *
645
+ * @example
646
+ * const isExact = await isElementTextMatchText(label, 'Username', {
647
+ * description: 'Username label'
648
+ * });
649
+ *
650
+ * @returns True if the element's textContent matches the expected text exactly, otherwise false
651
+ */
652
+ static async isElementTextMatchText(locator, expected, options = {}) {
653
+ const { description } = this.resolveOptions(options);
654
+ try {
655
+ await this.waitForVisible(locator, options);
656
+ await this.highlight(locator);
657
+ const actualText = await this.getText(locator);
658
+ return actualText === expected;
659
+ }
660
+ catch {
661
+ console.warn(`⚠ textContent of ${description} does not match "${expected}"`);
662
+ return false;
663
+ }
664
+ }
665
+ /**
666
+ * Checks if an element's textContent contains the expected text.
667
+ *
668
+ * @param locator - Locator of the target element
669
+ * @param expected - Text expected to be contained within the element's textContent
670
+ * @param options - Optional action settings
671
+ * @param options.timeout - Maximum time to wait for the element to become visible (default: 1500)
672
+ * @param options.description - Description of the element used for logging
673
+ *
674
+ * @example
675
+ * const contains = await isElementTextContainsText(button, 'Submit');
676
+ *
677
+ * @example
678
+ * const contains = await isElementTextContainsText(button, 'Submit', {description: 'Submit button',
679
+ * timeout: 4000
680
+ * });
681
+ *
682
+ * @returns True if the element's textContent contains the expected text, otherwise false
683
+ */
684
+ static async isElementTextContainsText(locator, expected, options = {}) {
685
+ const { description } = this.resolveOptions(options);
686
+ try {
687
+ await this.waitForVisible(locator, options);
688
+ await this.highlight(locator);
689
+ const actualText = await this.getText(locator);
690
+ return typeof actualText === 'string' && actualText.includes(expected);
691
+ }
692
+ catch {
693
+ console.warn(`⚠ textContent of ${description} does not contain "${expected}"`);
694
+ return false;
695
+ }
696
+ }
697
+ /**
698
+ * Checks if the given list is sorted in ascending order.
699
+ * @param list List of comparable values
700
+ * @returns true if sorted ascending, else false
701
+ */
702
+ static isAscending(list) {
703
+ try {
704
+ if (!list || list.length <= 1)
705
+ return true;
706
+ for (let i = 0; i < list.length - 1; i++) {
707
+ if (list[i] > list[i + 1])
708
+ return false;
709
+ }
710
+ return true;
711
+ }
712
+ catch (error) {
713
+ return false;
714
+ }
715
+ }
716
+ /**
717
+ * Checks if the given list is sorted in descending order.
718
+ * @param list List of comparable values
719
+ * @returns true if sorted descending, else false
720
+ */
721
+ static isDescending(list) {
722
+ try {
723
+ if (!list || list.length <= 1)
724
+ return true;
725
+ for (let i = 0; i < list.length - 1; i++) {
726
+ if (list[i] < list[i + 1])
727
+ return false;
728
+ }
729
+ return true;
730
+ }
731
+ catch (error) {
732
+ return false;
733
+ }
734
+ }
735
+ /**
736
+ * Sorts a list of values in ascending or descending order.
737
+ * @param values Values to sort
738
+ * @param order Sorting order ('asc' or 'desc')
739
+ * @returns Sorted array
740
+ */
741
+ static sortValues(values, order) {
742
+ const sorted = [...values].sort((a, b) => {
743
+ if (a === b)
744
+ return 0;
745
+ if (a > b)
746
+ return 1;
747
+ return -1;
748
+ });
749
+ return order === 'asc' ? sorted : sorted.reverse();
750
+ }
751
+ /**
752
+ * Sort date strings from Newest to Oldest using given format.
753
+ * @param dateStrings Date strings from UI
754
+ * @param format Date format (e.g. 'MMM dd, yyyy HH:mm:s')
755
+ * @returns Sorted date strings (Newest first)
756
+ */
757
+ static sortDateNewestToOldest(dateStrings, format) {
758
+ if (!dateStrings || dateStrings.length === 0)
759
+ return [];
760
+ const dates = dateStrings.map(d => this.parseDateGeneric(d.trim(), format));
761
+ dates.sort((a, b) => b.getTime() - a.getTime());
762
+ return dates.map(d => this.formatDateGeneric(d, format));
763
+ }
764
+ /**
765
+ * Sort date strings from Oldest to Newest using given format.
766
+ * @param dateStrings Date strings from UI
767
+ * @param format Date format (e.g. 'MMM dd, yyyy HH:mm:s')
768
+ * @returns Sorted date strings (Oldest first)
769
+ */
770
+ static sortDateOldestToNewest(dateStrings, format) {
771
+ if (!dateStrings || dateStrings.length === 0)
772
+ return [];
773
+ const dates = dateStrings.map(d => this.parseDateGeneric(d.trim(), format));
774
+ dates.sort((a, b) => a.getTime() - b.getTime());
775
+ return dates.map(d => this.formatDateGeneric(d, format));
776
+ }
777
+ /**
778
+ * Parses a date string into a Date object using a generic format.
779
+ * Supports multiple date tokens like yyyy, MM, MMM, dd, HH, mm, ss.
780
+ * @param dateStr Date string from UI
781
+ * @param format Format of the date string
782
+ * @returns Parsed Date object
783
+ */
784
+ static parseDateGeneric(dateStr, format) {
785
+ const tokenRegex = /(yyyy|MMM|MM|dd|HH|mm|ss|s)/g;
786
+ const formatTokens = format.match(tokenRegex);
787
+ const dateParts = dateStr.match(/\w+/g);
788
+ if (!formatTokens || !dateParts || formatTokens.length !== dateParts.length) {
789
+ throw new Error(`Invalid date or format: ${dateStr}`);
790
+ }
791
+ let year = 1970, month = 0, day = 1;
792
+ let hour = 0, minute = 0, second = 0;
793
+ formatTokens.forEach((token, i) => {
794
+ const value = dateParts[i];
795
+ switch (token) {
796
+ case "yyyy":
797
+ year = Number(value);
798
+ break;
799
+ case "MM":
800
+ month = Number(value) - 1;
801
+ break;
802
+ case "MMM":
803
+ month = this.MONTH_MAP[value];
804
+ break;
805
+ case "dd":
806
+ day = Number(value);
807
+ break;
808
+ case "HH":
809
+ hour = Number(value);
810
+ break;
811
+ case "mm":
812
+ minute = Number(value);
813
+ break;
814
+ case "s":
815
+ case "ss":
816
+ second = Number(value);
817
+ break;
818
+ }
819
+ });
820
+ return new Date(year, month, day, hour, minute, second);
821
+ }
822
+ /**
823
+ * Formats a Date object into a string using the provided format.
824
+ * @param date Date object
825
+ * @param format Desired output format
826
+ * @returns Formatted date string
827
+ */
828
+ static formatDateGeneric(date, format) {
829
+ const pad = (n) => n.toString().padStart(2, "0");
830
+ return format
831
+ .replace("yyyy", date.getFullYear().toString())
832
+ .replace("MMM", Object.keys(this.MONTH_MAP)
833
+ .find(k => this.MONTH_MAP[k] === date.getMonth()))
834
+ .replace("MM", pad(date.getMonth() + 1))
835
+ .replace("dd", pad(date.getDate()))
836
+ .replace("HH", pad(date.getHours()))
837
+ .replace("mm", pad(date.getMinutes()))
838
+ .replace("ss", pad(date.getSeconds()))
839
+ .replace("s", date.getSeconds().toString());
840
+ }
841
+ /**
842
+ * Selects an option from a list of locators based on visible text.
843
+ *
844
+ * @param optionsList - Locator representing list of selectable options
845
+ * @param optionText - Visible text of the option to select
846
+ * @param options - Optional action settings
847
+ * @param options.timeout - Maximum wait time (default: 15000)
848
+ *
849
+ * @returns true if option is clicked successfully, otherwise false
850
+ */
851
+ static async clickOnFilterOptionFromList(optionsList, optionText, options = {}) {
852
+ const { timeout = 15000 } = this.resolveOptions(options);
853
+ try {
854
+ if (!optionText || optionText.trim() === '') {
855
+ console.error('⚠ Option text must be a non-empty string');
856
+ return false;
857
+ }
858
+ const count = await optionsList.count();
859
+ for (let i = 0; i < count; i++) {
860
+ const option = optionsList.nth(i);
861
+ const text = (await option.innerText())
862
+ .replace(/\s+/g, ' ')
863
+ .trim();
864
+ console.log("fileter options:", text);
865
+ if (text.toLowerCase() === (optionText.toLowerCase())) {
866
+ await option.scrollIntoViewIfNeeded();
867
+ await this.click(option, { timeout });
868
+ return true;
869
+ }
870
+ }
871
+ console.error(`⚠ Option "${optionText}" not found in list`);
872
+ return false;
873
+ }
874
+ catch (error) {
875
+ console.error(`⚠ Failed to select option "${optionText}": ${error.message}`);
876
+ return false;
877
+ }
878
+ }
879
+ /**
880
+ * Selects an option from a native <select> dropdown using visible text.
881
+ *
882
+ * @param dropdown - Locator pointing to the <select> element
883
+ * @param optionText - Visible text of the option to select
884
+ * @param options - Optional configuration (timeout, description)
885
+ */
886
+ static async selectByText(dropdown, optionText, options = {}) {
887
+ const { timeout, description } = this.resolveOptions(options);
888
+ try {
889
+ await this.waitForVisible(dropdown, options);
890
+ await this.highlight(dropdown);
891
+ await dropdown.scrollIntoViewIfNeeded();
892
+ await dropdown.selectOption({ label: optionText }, { timeout });
893
+ const selected = await dropdown.inputValue();
894
+ if (!selected) {
895
+ console.warn(`⚠ Option "${optionText}" may not be selected in ${description}`);
896
+ }
897
+ }
898
+ catch (error) {
899
+ console.warn(`⚠ ${description}: Unable to select option "${optionText}". ${error.message}`);
900
+ }
901
+ }
902
+ /**
903
+ * Selects an option from a native <select> dropdown using the option's value attribute.
904
+ *
905
+ * @param dropdown - Locator pointing to the <select> element
906
+ * @param value - Value attribute of the option to select
907
+ * @param options - Optional configuration (timeout, description)
908
+ */
909
+ static async selectByValue(dropdown, value, options = {}) {
910
+ const { timeout, description } = this.resolveOptions(options);
911
+ try {
912
+ await this.waitForVisible(dropdown, options);
913
+ await this.highlight(dropdown);
914
+ await dropdown.scrollIntoViewIfNeeded();
915
+ await dropdown.selectOption({ value }, { timeout });
916
+ const selected = await dropdown.inputValue();
917
+ if (selected !== value) {
918
+ console.warn(`⚠ Value "${value}" may not be selected in ${description}`);
919
+ }
920
+ }
921
+ catch (error) {
922
+ console.warn(`⚠ ${description}: Unable to select value "${value}". ${error.message}`);
923
+ }
924
+ }
925
+ /**
926
+ * Selects an option from a native <select> dropdown using the option index (0-based).
927
+ *
928
+ * @param dropdown - Locator pointing to the <select> element
929
+ * @param index - Index of the option (0-based)
930
+ * @param options - Optional configuration (timeout, description)
931
+ */
932
+ static async selectByIndex(dropdown, index, options = {}) {
933
+ const { timeout, description } = this.resolveOptions(options);
934
+ try {
935
+ await this.waitForVisible(dropdown, options);
936
+ await this.highlight(dropdown);
937
+ await dropdown.scrollIntoViewIfNeeded();
938
+ await dropdown.selectOption({ index }, { timeout });
939
+ const selected = await dropdown.inputValue();
940
+ if (!selected) {
941
+ console.warn(`⚠ Option at index ${index} may not be selected in ${description}`);
942
+ }
943
+ }
944
+ catch (error) {
945
+ console.warn(`⚠ ${description}: Unable to select index ${index}. ${error.message}`);
946
+ }
947
+ }
948
+ /**
949
+ * Selects an option from a custom (non-<select>) dropdown using visible text.
950
+ *
951
+ * @param dropdown - Locator for the dropdown trigger element
952
+ * @param optionsList - Locator representing all dropdown option elements
953
+ * @param value - Visible text of the option to select
954
+ * @param options - Optional configuration (timeout, description)
955
+ */
956
+ static async selectFromCustomDropdown(dropdown, optionsList, value, options = {}) {
957
+ const { timeout, description } = this.resolveOptions(options);
958
+ try {
959
+ await this.waitForVisible(dropdown, options);
960
+ await this.highlight(dropdown);
961
+ await dropdown.click({ timeout });
962
+ const firstOption = optionsList.first();
963
+ await firstOption.waitFor({ state: 'visible', timeout });
964
+ const count = await optionsList.count();
965
+ for (let i = 0; i < count; i++) {
966
+ const option = optionsList.nth(i);
967
+ await this.highlight(option);
968
+ const text = (await option.innerText()).trim();
969
+ if (text === value) {
970
+ await option.click({ timeout });
971
+ return;
972
+ }
973
+ }
974
+ console.warn(`⚠ ${description}: Option "${value}" not found`);
975
+ }
976
+ catch (error) {
977
+ console.warn(`⚠ ${description}: Failed selecting "${value}". ${error.message}`);
978
+ }
979
+ }
980
+ /**
981
+ * Retrieves all visible option texts from a dropdown or options list.
982
+ *
983
+ * @param optionsList - Locator pointing to dropdown option elements
984
+ * @param options - Optional configuration (timeout, description)
985
+ * @returns Array of trimmed option texts or empty array
986
+ */
987
+ static async getAllOptions(optionsList, options = {}) {
988
+ const { timeout, description } = this.resolveOptions(options);
989
+ try {
990
+ const first = optionsList.first();
991
+ await first.waitFor({ state: 'visible', timeout });
992
+ await this.highlight(first);
993
+ const count = await optionsList.count();
994
+ const values = [];
995
+ for (let i = 0; i < count; i++) {
996
+ const option = optionsList.nth(i);
997
+ const text = (await option.innerText()).trim();
998
+ values.push(text);
999
+ }
1000
+ return values;
1001
+ }
1002
+ catch (error) {
1003
+ console.warn(`⚠ ${description}: Unable to fetch dropdown options. ${error.message}`);
1004
+ return [];
1005
+ }
1006
+ }
1007
+ /**
1008
+ * Checks whether a dropdown/options list contains a specific visible option.
1009
+ *
1010
+ * @param optionsList - Locator representing dropdown option elements
1011
+ * @param value - Option text to verify
1012
+ * @param options - Optional configuration (timeout, description)
1013
+ * @returns true if option exists, otherwise false
1014
+ */
1015
+ static async hasOption(optionsList, value, options = {}) {
1016
+ const { timeout, description } = this.resolveOptions(options);
1017
+ try {
1018
+ const first = optionsList.first();
1019
+ await first.waitFor({ state: 'visible', timeout });
1020
+ const count = await optionsList.count();
1021
+ for (let i = 0; i < count; i++) {
1022
+ const option = optionsList.nth(i);
1023
+ const text = (await option.innerText()).trim();
1024
+ if (text === value) {
1025
+ return true;
1026
+ }
1027
+ }
1028
+ return false;
1029
+ }
1030
+ catch (error) {
1031
+ console.warn(`⚠ ${description}: Error while checking option "${value}". ${error.message}`);
1032
+ return false;
1033
+ }
1034
+ }
1035
+ /**
1036
+ * Retrieves the currently selected option text from a native <select> dropdown.
1037
+ *
1038
+ * @param dropdown - Locator for the <select> element
1039
+ * @param options - Optional configuration (timeout, description)
1040
+ * @returns The text of the selected option, or null if none is selected
1041
+ */
1042
+ static async getSelectedOption(dropdown, options = {}) {
1043
+ const { description } = this.resolveOptions(options);
1044
+ try {
1045
+ await this.waitForVisible(dropdown, options);
1046
+ await this.highlight(dropdown);
1047
+ const selectedOptions = await dropdown.evaluate((select) => {
1048
+ const selected = Array.from(select.options).filter(option => option.selected);
1049
+ return selected.map(option => option.text.trim());
1050
+ });
1051
+ if (!selectedOptions || selectedOptions.length === 0) {
1052
+ console.warn(`⚠ ${description}: No option is currently selected`);
1053
+ return null;
1054
+ }
1055
+ return selectedOptions[0];
1056
+ }
1057
+ catch (error) {
1058
+ console.warn(`⚠ ${description}: Unable to get selected option. ${error.message}`);
1059
+ return null;
1060
+ }
1061
+ }
1062
+ //**Pagination Methods */
1063
+ /**
1064
+ * Determines the total number of pages by navigating to the last page
1065
+ * and reading the active page number.
1066
+ *
1067
+ * @param paginationContainer - Locator for the pagination container
1068
+ * @param options - Optional configuration (timeout, description, locators)
1069
+ * @returns Total number of pages, or 0 if it cannot be determined
1070
+ */
1071
+ static async getTotalPaginationCount(paginationContainer, options = {}) {
1072
+ const { timeout = 15000, description = 'Pagination', lastButtonLocator = 'button.pagination-btn-last', activePageLocator = 'button.pagination-btn.active' } = options;
1073
+ try {
1074
+ const page = paginationContainer.page();
1075
+ await this.waitForVisible(paginationContainer, { timeout, description });
1076
+ const activePage = paginationContainer.locator(activePageLocator).first();
1077
+ await this.waitForVisible(activePage, { timeout, description: 'Active Page Button' });
1078
+ const beforeText = (await activePage.innerText()).trim();
1079
+ const lastButton = paginationContainer.locator(lastButtonLocator).first();
1080
+ if ((await lastButton.count()) === 0) {
1081
+ console.warn(`⚠ ${description}: Last page button not found`);
1082
+ return 0;
1083
+ }
1084
+ await this.waitForVisible(lastButton, { timeout, description: 'Last Page Button' });
1085
+ await this.highlight(lastButton);
1086
+ await lastButton.click({ timeout });
1087
+ // Wait until active page number changes
1088
+ const handle = await activePage.elementHandle();
1089
+ if (handle) {
1090
+ await page.waitForFunction(([el, previous]) => el.innerText.trim() !== previous, [handle, beforeText], { timeout });
1091
+ }
1092
+ const finalText = (await activePage.innerText()).trim();
1093
+ const total = Number(finalText);
1094
+ if (Number.isNaN(total)) {
1095
+ console.warn(`⚠ ${description}: Invalid total page number "${finalText}"`);
1096
+ return 0;
1097
+ }
1098
+ return total;
1099
+ }
1100
+ catch (error) {
1101
+ console.warn(`⚠ ${description}: Unable to determine total pagination count. ${error.message}`);
1102
+ return 0;
1103
+ }
1104
+ }
1105
+ /**
1106
+ * Clicks the "Next" button in pagination, if available.
1107
+ *
1108
+ * @param paginationContainer - Locator for the pagination container
1109
+ * @param options - Optional configuration (timeout, description, locators)
1110
+ * @returns True if the next button was clicked, otherwise false
1111
+ */
1112
+ static async clickNextPagination(paginationContainer, options = {}) {
1113
+ const { timeout = 15000, description = 'Pagination Next Button', nextButtonLocator = 'button[data-page="next"]' } = options;
1114
+ try {
1115
+ await this.waitForVisible(paginationContainer, { timeout, description });
1116
+ const nextBtn = paginationContainer.locator(nextButtonLocator).first();
1117
+ if ((await nextBtn.count()) === 0) {
1118
+ console.warn(`⚠ ${description}: Next button not found`);
1119
+ return false;
1120
+ }
1121
+ await this.waitForVisible(nextBtn, { timeout });
1122
+ await this.highlight(nextBtn);
1123
+ await nextBtn.scrollIntoViewIfNeeded();
1124
+ await nextBtn.click({ timeout });
1125
+ return true;
1126
+ }
1127
+ catch (error) {
1128
+ console.warn(`⚠ ${description}: Failed to click next pagination button. ${error.message}`);
1129
+ return false;
1130
+ }
1131
+ }
1132
+ /**
1133
+ * Clicks the "Previous" button in pagination, if available.
1134
+ *
1135
+ * @param paginationContainer - Locator for the pagination container
1136
+ * @param options - Optional configuration (timeout, description, locators)
1137
+ * @returns True if the previous button was clicked, otherwise false
1138
+ */
1139
+ static async clickPrevPagination(paginationContainer, options = {}) {
1140
+ const { timeout = 15000, description = 'Pagination Previous Button', prevButtonLocator = 'button[data-page="prev"]' } = options;
1141
+ try {
1142
+ await this.waitForVisible(paginationContainer, { timeout, description });
1143
+ const prevBtn = paginationContainer.locator(prevButtonLocator).first();
1144
+ if ((await prevBtn.count()) === 0) {
1145
+ console.warn(`⚠ ${description}: Previous button not found`);
1146
+ return false;
1147
+ }
1148
+ await this.waitForVisible(prevBtn, { timeout });
1149
+ await this.highlight(prevBtn);
1150
+ await prevBtn.scrollIntoViewIfNeeded();
1151
+ await prevBtn.click({ timeout });
1152
+ return true;
1153
+ }
1154
+ catch (error) {
1155
+ console.warn(`⚠ ${description}: Failed to click previous pagination button. ${error.message}`);
1156
+ return false;
1157
+ }
1158
+ }
1159
+ /**
1160
+ * Clicks the "Last" page button in pagination.
1161
+ *
1162
+ * @param paginationContainer - Locator for the pagination container
1163
+ * @param options - Optional configuration (timeout, description, locators)
1164
+ * @returns True if the last button was clicked successfully, otherwise false
1165
+ */
1166
+ static async clickLastPagination(paginationContainer, options = {}) {
1167
+ const { timeout = 15000, description = 'Pagination Last Button', lastButtonLocator = 'button[data-page="last"]' } = options;
1168
+ try {
1169
+ await this.waitForVisible(paginationContainer, { timeout, description });
1170
+ const lastBtn = paginationContainer.locator(lastButtonLocator).first();
1171
+ if ((await lastBtn.count()) === 0) {
1172
+ console.warn(`⚠ ${description}: Last button not found`);
1173
+ return false;
1174
+ }
1175
+ await this.waitForVisible(lastBtn, { timeout });
1176
+ await this.highlight(lastBtn);
1177
+ await lastBtn.scrollIntoViewIfNeeded();
1178
+ await lastBtn.click({ timeout });
1179
+ return true;
1180
+ }
1181
+ catch (error) {
1182
+ console.warn(`⚠ ${description}: Failed to click last pagination button. ${error.message}`);
1183
+ return false;
1184
+ }
1185
+ }
1186
+ /**
1187
+ * Retrieves the currently active page number from pagination.
1188
+ *
1189
+ * @param paginationContainer - Locator for the pagination container
1190
+ * @param options - Optional configuration (timeout, description, locators)
1191
+ * @returns Active page number, or 0 if not found or invalid
1192
+ */
1193
+ static async getActivePaginationPage(paginationContainer, options = {}) {
1194
+ const { timeout = 15000, description = 'Active Pagination Page', activePageLocator = 'button.pagination-btn.active' } = options;
1195
+ try {
1196
+ await this.waitForVisible(paginationContainer, { timeout, description });
1197
+ const activeBtn = paginationContainer.locator(activePageLocator).first();
1198
+ if ((await activeBtn.count()) === 0) {
1199
+ console.warn(`⚠ ${description}: Active page button not found`);
1200
+ return 0;
1201
+ }
1202
+ await this.waitForVisible(activeBtn, { timeout });
1203
+ await this.highlight(activeBtn);
1204
+ const text = (await activeBtn.innerText()).trim();
1205
+ const pageNumber = Number(text);
1206
+ if (Number.isNaN(pageNumber)) {
1207
+ console.warn(`⚠ ${description}: Invalid page number text "${text}"`);
1208
+ return 0;
1209
+ }
1210
+ return pageNumber;
1211
+ }
1212
+ catch (error) {
1213
+ console.warn(`⚠ ${description}: Failed to get active pagination page. ${error.message}`);
1214
+ return 0;
1215
+ }
1216
+ }
1217
+ /**
1218
+ * Clicks the "Start" (first page) button in pagination, if available.
1219
+ *
1220
+ * @param paginationContainer - Locator for the pagination container
1221
+ * @param options - Optional configuration (timeout, description, locators)
1222
+ * @returns True if the start button was clicked, otherwise false
1223
+ */
1224
+ static async clickStartPagination(paginationContainer, options = {}) {
1225
+ const { timeout = 15000, description = 'Pagination Start Button', firstButtonLocator = 'button.pagination-btn-start' } = options;
1226
+ try {
1227
+ await this.waitForVisible(paginationContainer, { timeout, description });
1228
+ const startBtn = paginationContainer.locator(firstButtonLocator).first();
1229
+ if ((await startBtn.count()) === 0) {
1230
+ console.warn(`⚠ ${description}: Start button not found`);
1231
+ return false;
1232
+ }
1233
+ await this.waitForVisible(startBtn, { timeout });
1234
+ await this.highlight(startBtn);
1235
+ await startBtn.scrollIntoViewIfNeeded();
1236
+ await startBtn.click({ timeout });
1237
+ return true;
1238
+ }
1239
+ catch (error) {
1240
+ console.warn(`⚠ ${description}: Failed to click start pagination button. ${error.message}`);
1241
+ return false;
1242
+ }
1243
+ }
1244
+ /**
1245
+ * Clicks a specific page number button in pagination.
1246
+ *
1247
+ * @param paginationContainer - Locator for the pagination container
1248
+ * @param pageNumber - Page number to navigate to (1-based)
1249
+ * @param options - Optional configuration (timeout, description, locators)
1250
+ * @returns True if the page number button was clicked, otherwise false
1251
+ */
1252
+ static async clickPaginationPageNumber(paginationContainer, pageNumber, options = {}) {
1253
+ const { timeout = 15000, description = `Pagination Page ${pageNumber} Button`, pageButtonLocator = 'button.pagination-btn' } = options;
1254
+ try {
1255
+ await this.waitForVisible(paginationContainer, { timeout, description });
1256
+ const pageButtons = paginationContainer.locator(pageButtonLocator);
1257
+ const count = await pageButtons.count();
1258
+ if (count === 0) {
1259
+ console.warn(`⚠ ${description}: No pagination buttons found`);
1260
+ return false;
1261
+ }
1262
+ for (let i = 0; i < count; i++) {
1263
+ const btn = pageButtons.nth(i);
1264
+ const text = (await btn.innerText()).trim();
1265
+ if (text === String(pageNumber)) {
1266
+ await this.waitForVisible(btn, { timeout });
1267
+ await this.highlight(btn);
1268
+ await btn.scrollIntoViewIfNeeded();
1269
+ await btn.click({ timeout });
1270
+ return true;
1271
+ }
1272
+ }
1273
+ console.warn(`⚠ ${description}: Page button "${pageNumber}" not found`);
1274
+ return false;
1275
+ }
1276
+ catch (error) {
1277
+ console.warn(`⚠ ${description}: Failed to click page number "${pageNumber}". ${error.message}`);
1278
+ return false;
1279
+ }
1280
+ }
1281
+ }
1282
+ exports.CommonUtils = CommonUtils;
1283
+ CommonUtils.isHighlight = false;
1284
+ /**
1285
+ * Month name to month index mapping for parsing 'MMM' format.
1286
+ */
1287
+ CommonUtils.MONTH_MAP = {
1288
+ Jan: 0, Feb: 1, Mar: 2, Apr: 3,
1289
+ May: 4, Jun: 5, Jul: 6, Aug: 7,
1290
+ Sep: 8, Oct: 9, Nov: 10, Dec: 11
1291
+ };
1292
+ //# sourceMappingURL=commonUtils.js.map