@dev-blinq/cucumber_client 1.0.1416-dev → 1.0.1417-dev

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.
@@ -452,6 +452,126 @@ this.imports[2].node.source.value
452
452
  let startEnd = this._getVariableStartEnd("elements");
453
453
  this._replaceCode(code, startEnd[0], startEnd[1]);
454
454
  }
455
+ mergeSimilarElements() {
456
+ const elements = this.getVariableDeclarationAsObject("elements");
457
+ if (elements === null) {
458
+ return;
459
+ }
460
+
461
+ const keys = Object.keys(elements);
462
+
463
+ // Ensure each element has element_key
464
+ for (let i = 0; i < keys.length; i++) {
465
+ const key = keys[i];
466
+ if (!elements[key].element_key) {
467
+ elements[key].element_key = key;
468
+ }
469
+ }
470
+
471
+ const replacedKeys = {};
472
+ const mergedElements = {};
473
+
474
+ // Walk from end so "later" keys win (your intended behavior)
475
+ for (let i = keys.length - 1; i >= 0; i--) {
476
+ const currentElement = elements[keys[i]];
477
+ let foundMatch = false;
478
+
479
+ for (let j = i - 1; j >= 0; j--) {
480
+ const nextElement = elements[keys[j]];
481
+
482
+ if (this._isSimilarElement(currentElement, nextElement)) {
483
+ // Keep currentElement, replace earlier key with current's key
484
+ mergedElements[currentElement.element_key] = currentElement;
485
+ replacedKeys[nextElement.element_key] = currentElement.element_key;
486
+ foundMatch = true;
487
+
488
+ // Remove the earlier key so we don't carry it forward
489
+ keys.splice(j, 1);
490
+
491
+ // Since we removed an index before i, adjust i so it still points to currentElement
492
+ i--;
493
+
494
+ // IMPORTANT: compensate for splice so the loop’s j-- lands on the same logical next item
495
+ j++;
496
+ }
497
+ }
498
+
499
+ if (!foundMatch) {
500
+ mergedElements[currentElement.element_key] = currentElement;
501
+ }
502
+ }
503
+
504
+ // If no replacements occurred, nothing else to do
505
+ if (Object.keys(replacedKeys).length === 0) {
506
+ return;
507
+ }
508
+
509
+ // Replace all element references in file content
510
+ for (const key in replacedKeys) {
511
+ const regexp = new RegExp(`elements\\[\\s*["']${key}["']\\s*\\]`, "g");
512
+ this.fileContent = this.fileContent.replace(regexp, () => {
513
+ return `elements["${replacedKeys[key]}"]`;
514
+ });
515
+ }
516
+
517
+ // Save merged elements back
518
+ this.insertElements(mergedElements);
519
+ }
520
+
521
+ //const regexp = new RegExp(`elements\\[\\s*["']${key}["']\\s*\\]`, "g");
522
+ /*
523
+ element shape example:
524
+ {
525
+ locators: [
526
+ { css: 'internal:text="YES Subscription"s', priority: 1 },
527
+ { css: 'internal:text="YES Subscription"i', priority: 1 },
528
+ { css: 'h3 >> internal:has-text="YES Subscription"i', priority: 1 },
529
+ { css: 'h3 >> internal:has-text=/^YES Subscription$/', priority: 1 },
530
+ { css: 'internal:role=heading[name="YES Subscription"s]', priority: 1 },
531
+ ],
532
+ element_name: "YES Subscription heading",
533
+ element_key: "heading_yes_subscription",
534
+ }
535
+ */
536
+
537
+ _isSimilarElement(element1, element2) {
538
+ if (!element1 || !element2) return false;
539
+
540
+ const locs1 = Array.isArray(element1.locators) ? element1.locators : [];
541
+ const locs2 = Array.isArray(element2.locators) ? element2.locators : [];
542
+
543
+ // If both empty, fallback to false (names/keys already handled)
544
+ if (locs1.length === 0 && locs2.length === 0) return false;
545
+ if (locs1.length === 0 || locs2.length === 0) return false;
546
+
547
+ // Decide which set is "less" (subset candidate) and "more" (superset candidate)
548
+ const moreLocatorsElement = locs1.length >= locs2.length ? locs1 : locs2;
549
+ const lessLocatorsElement = locs1.length >= locs2.length ? locs2 : locs1;
550
+
551
+ // Helper: check if all key/value pairs in 'needle' exist identically in 'hay' (superset)
552
+ const locatorIncludes = (hay, needle) => {
553
+ if (hay == null || needle == null) return false;
554
+ // Only consider known keys; ignore undefined values
555
+ // ignore priority
556
+ const KEYS = ["css", "index", "text", "climb"];
557
+ for (const k of KEYS) {
558
+ if (needle[k] !== undefined) {
559
+ if (!(k in hay)) return false;
560
+ // Strict equality comparison for predictability
561
+ if (hay[k] !== needle[k]) return false;
562
+ }
563
+ }
564
+ return true;
565
+ };
566
+
567
+ // For every locator in the smaller set, we require a matching superset locator in the larger set
568
+ for (const less of lessLocatorsElement) {
569
+ const match = moreLocatorsElement.some((more) => locatorIncludes(more, less));
570
+ if (!match) return false;
571
+ }
572
+
573
+ return true;
574
+ }
455
575
  removeUnusedElements() {
456
576
  const usedElementsKeys = this.getUsedElementsKeys();
457
577
  const elements = this.getVariableDeclarationAsObject("elements");
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@dev-blinq/cucumber_client",
3
- "version": "1.0.1416-dev",
3
+ "version": "1.0.1417-dev",
4
4
  "description": " ",
5
5
  "main": "bin/index.js",
6
6
  "types": "bin/index.d.ts",