@duckduckgo/autoconsent 16.27.0 → 16.29.0

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 (51) hide show
  1. package/AGENTS.md +1 -1
  2. package/CHANGELOG.md +40 -0
  3. package/dist/addon-firefox/compact-rules.json +1 -1
  4. package/dist/addon-firefox/content.bundle.js +43 -6
  5. package/dist/addon-firefox/manifest.json +1 -1
  6. package/dist/addon-firefox/rule-index.json +1 -1
  7. package/dist/addon-firefox/rules.json +1 -1
  8. package/dist/addon-mv3/compact-rules.json +1 -1
  9. package/dist/addon-mv3/content.bundle.js +43 -6
  10. package/dist/addon-mv3/manifest.json +1 -1
  11. package/dist/addon-mv3/rule-index.json +1 -1
  12. package/dist/addon-mv3/rules.json +1 -1
  13. package/dist/autoconsent.cjs.js +43 -6
  14. package/dist/autoconsent.esm.js +43 -6
  15. package/dist/autoconsent.playwright.js +43 -6
  16. package/dist/autoconsent.standalone.js +44 -7
  17. package/dist/types/cmps/base.d.ts +2 -1
  18. package/dist/types/dom-actions.d.ts +3 -1
  19. package/dist/types/rules.d.ts +16 -2
  20. package/dist/types/types.d.ts +1 -1
  21. package/dist/types/utils.d.ts +1 -0
  22. package/docs/rule-syntax.md +26 -1
  23. package/lib/cmps/base.ts +10 -3
  24. package/lib/dom-actions.ts +33 -3
  25. package/lib/rules.ts +19 -2
  26. package/lib/types.ts +7 -1
  27. package/lib/utils.ts +16 -0
  28. package/package.json +1 -1
  29. package/rules/autoconsent/amazon-pay.json +13 -0
  30. package/rules/autoconsent/bbva.json +12 -0
  31. package/rules/autoconsent/deliveroo.json +15 -0
  32. package/rules/autoconsent/ebay.json +34 -0
  33. package/rules/autoconsent/ecbeing.json +10 -0
  34. package/rules/autoconsent/stright.json +29 -0
  35. package/rules/autoconsent/theguardian.com.json +13 -3
  36. package/rules/autoconsent/wpconsent.json +30 -0
  37. package/rules/compact-rules.json +1 -1
  38. package/rules/rule-index.json +1 -1
  39. package/rules/rules.json +1 -1
  40. package/tests/amazon-pay.spec.ts +3 -0
  41. package/tests/bbva.spec.ts +4 -0
  42. package/tests/deliveroo.spec.ts +3 -0
  43. package/tests/ecbeing.spec.ts +3 -0
  44. package/tests/stright.spec.ts +8 -0
  45. package/tests/wpconsent.spec.ts +5 -0
  46. package/tests-wtr/dom-actions/dom-actions.stylesheet.html +13 -0
  47. package/tests-wtr/dom-actions/dom-actions.stylesheet.ts +26 -0
  48. package/tests-wtr/dom-actions/dom-actions.wait-for-then-click.html +14 -0
  49. package/tests-wtr/dom-actions/dom-actions.wait-for-then-click.ts +106 -0
  50. package/tests-wtr/utils/append-stylesheet-rule.html +11 -0
  51. package/tests-wtr/utils/append-stylesheet-rule.test.ts +29 -0
@@ -37,7 +37,7 @@ __export(web_exports, {
37
37
  module.exports = __toCommonJS(web_exports);
38
38
 
39
39
  // lib/rules.ts
40
- var SUPPORTED_RULE_STEP_VERSION = 2;
40
+ var SUPPORTED_RULE_STEP_VERSION = 3;
41
41
 
42
42
  // lib/random.ts
43
43
  function getRandomID() {
@@ -116,6 +116,20 @@ function hideElements(styleEl, selector, method = "display") {
116
116
  }
117
117
  return false;
118
118
  }
119
+ function appendStylesheetRule(styleEl, cssRule, marker) {
120
+ if (!(styleEl instanceof HTMLStyleElement) || cssRule.length === 0) {
121
+ return false;
122
+ }
123
+ const markerComment = marker ? `/* autoconsent:${marker} */` : "";
124
+ if (markerComment && styleEl.innerText.includes(markerComment)) {
125
+ return true;
126
+ }
127
+ if (!markerComment && styleEl.innerText.includes(cssRule.trim())) {
128
+ return true;
129
+ }
130
+ styleEl.innerText += `${markerComment}${markerComment ? " " : ""}${cssRule} `;
131
+ return true;
132
+ }
119
133
  async function waitFor(predicate, maxTimes, interval) {
120
134
  const result = await predicate();
121
135
  if (!result && maxTimes > 0) {
@@ -1484,12 +1498,12 @@ var AutoConsentCMPBase = class {
1484
1498
  waitForVisible(selector, timeout, check) {
1485
1499
  return this.autoconsent.domActions.waitForVisible(selector, timeout, check);
1486
1500
  }
1487
- async waitForThenClick(selector, timeout, all) {
1501
+ async waitForThenClick(selector, timeout, all, retries, retryInterval) {
1488
1502
  if (this.autoconsent.config.visualTest) {
1489
1503
  await this.highlightElements(this.elementSelector(selector), all);
1490
1504
  }
1491
1505
  this.autoconsent.updateState({ clicks: this.autoconsent.state.clicks + 1 });
1492
- return this.autoconsent.domActions.waitForThenClick(selector, timeout, all);
1506
+ return this.autoconsent.domActions.waitForThenClick(selector, timeout, all, retries, retryInterval);
1493
1507
  }
1494
1508
  wait(ms) {
1495
1509
  return this.autoconsent.domActions.wait(ms);
@@ -1497,6 +1511,9 @@ var AutoConsentCMPBase = class {
1497
1511
  hide(selector, method) {
1498
1512
  return this.autoconsent.domActions.hide(selector, method);
1499
1513
  }
1514
+ stylesheet(cssRule, stylesheetId) {
1515
+ return this.autoconsent.domActions.stylesheet(cssRule, stylesheetId);
1516
+ }
1500
1517
  removeClass(selector, className) {
1501
1518
  return this.autoconsent.domActions.removeClass(selector, className);
1502
1519
  }
@@ -1610,7 +1627,7 @@ var AutoConsentCMP = class extends AutoConsentCMPBase {
1610
1627
  results.push(this.click(rule.click, rule.all));
1611
1628
  }
1612
1629
  if (rule.waitForThenClick) {
1613
- results.push(this.waitForThenClick(rule.waitForThenClick, rule.timeout, rule.all));
1630
+ results.push(this.waitForThenClick(rule.waitForThenClick, rule.timeout, rule.all, rule.retry, rule.retryInterval));
1614
1631
  }
1615
1632
  if (rule.wait) {
1616
1633
  results.push(this.wait(rule.wait));
@@ -1618,6 +1635,9 @@ var AutoConsentCMP = class extends AutoConsentCMPBase {
1618
1635
  if (rule.hide) {
1619
1636
  results.push(this.hide(rule.hide, rule.method));
1620
1637
  }
1638
+ if (rule.stylesheet !== void 0) {
1639
+ results.push(this.stylesheet(rule.stylesheet, rule.stylesheetId));
1640
+ }
1621
1641
  if (rule.removeClass !== void 0) {
1622
1642
  results.push(rule.selector ? this.removeClass(rule.selector, rule.removeClass) : false);
1623
1643
  }
@@ -2569,6 +2589,8 @@ var dynamicCMPs = [
2569
2589
  ];
2570
2590
 
2571
2591
  // lib/dom-actions.ts
2592
+ var DEFAULT_CLICK_RETRY_INTERVAL = 300;
2593
+ var CLICK_RETRY_POLL_INTERVAL = 50;
2572
2594
  var DomActions = class {
2573
2595
  constructor(autoconsentInstance) {
2574
2596
  this.autoconsentInstance = autoconsentInstance;
@@ -2624,9 +2646,19 @@ var DomActions = class {
2624
2646
  this.autoconsentInstance.config.logs.rulesteps && console.log("[waitForVisible]", selector);
2625
2647
  return waitFor(() => this.elementVisible(selector, check), times, interval);
2626
2648
  }
2627
- async waitForThenClick(selector, timeout = 1e4, all = false) {
2649
+ async waitForThenClick(selector, timeout = 1e4, all = false, retries = 0, retryInterval = DEFAULT_CLICK_RETRY_INTERVAL) {
2628
2650
  await this.waitForElement(selector, timeout);
2629
- return await this.click(selector, all);
2651
+ let clicked = await this.click(selector, all);
2652
+ for (let attempt = 0; clicked && attempt < retries; attempt++) {
2653
+ const pollTimes = Math.ceil(retryInterval / CLICK_RETRY_POLL_INTERVAL);
2654
+ const isGone = await waitFor(() => !this.elementVisible(selector, "any"), pollTimes, CLICK_RETRY_POLL_INTERVAL);
2655
+ if (isGone) {
2656
+ break;
2657
+ }
2658
+ this.autoconsentInstance.config.logs.rulesteps && console.log("[waitForThenClick] retrying click", selector);
2659
+ clicked = await this.click(selector, all);
2660
+ }
2661
+ return clicked;
2630
2662
  }
2631
2663
  wait(ms) {
2632
2664
  this.autoconsentInstance.config.logs.rulesteps && this.autoconsentInstance.config.logs.waits && console.log("[wait]", ms);
@@ -2644,6 +2676,11 @@ var DomActions = class {
2644
2676
  const styleEl = getStyleElement();
2645
2677
  return hideElements(styleEl, selector, method);
2646
2678
  }
2679
+ stylesheet(cssRule, stylesheetId) {
2680
+ this.autoconsentInstance.config.logs.rulesteps && console.log("[stylesheet]", cssRule, stylesheetId);
2681
+ const styleEl = getStyleElement();
2682
+ return appendStylesheetRule(styleEl, cssRule, stylesheetId);
2683
+ }
2647
2684
  removeClass(selector, className) {
2648
2685
  const elements = this.elementSelector(selector);
2649
2686
  this.autoconsentInstance.config.logs.rulesteps && console.log("[removeClass]", selector, className, elements);
@@ -7,7 +7,7 @@ var __privateAdd = (obj, member, value) => member.has(obj) ? __typeError("Cannot
7
7
  var __privateSet = (obj, member, value, setter) => (__accessCheck(obj, member, "write to private field"), setter ? setter.call(obj, value) : member.set(obj, value), value);
8
8
 
9
9
  // lib/rules.ts
10
- var SUPPORTED_RULE_STEP_VERSION = 2;
10
+ var SUPPORTED_RULE_STEP_VERSION = 3;
11
11
 
12
12
  // lib/random.ts
13
13
  function getRandomID() {
@@ -86,6 +86,20 @@ function hideElements(styleEl, selector, method = "display") {
86
86
  }
87
87
  return false;
88
88
  }
89
+ function appendStylesheetRule(styleEl, cssRule, marker) {
90
+ if (!(styleEl instanceof HTMLStyleElement) || cssRule.length === 0) {
91
+ return false;
92
+ }
93
+ const markerComment = marker ? `/* autoconsent:${marker} */` : "";
94
+ if (markerComment && styleEl.innerText.includes(markerComment)) {
95
+ return true;
96
+ }
97
+ if (!markerComment && styleEl.innerText.includes(cssRule.trim())) {
98
+ return true;
99
+ }
100
+ styleEl.innerText += `${markerComment}${markerComment ? " " : ""}${cssRule} `;
101
+ return true;
102
+ }
89
103
  async function waitFor(predicate, maxTimes, interval) {
90
104
  const result = await predicate();
91
105
  if (!result && maxTimes > 0) {
@@ -1454,12 +1468,12 @@ var AutoConsentCMPBase = class {
1454
1468
  waitForVisible(selector, timeout, check) {
1455
1469
  return this.autoconsent.domActions.waitForVisible(selector, timeout, check);
1456
1470
  }
1457
- async waitForThenClick(selector, timeout, all) {
1471
+ async waitForThenClick(selector, timeout, all, retries, retryInterval) {
1458
1472
  if (this.autoconsent.config.visualTest) {
1459
1473
  await this.highlightElements(this.elementSelector(selector), all);
1460
1474
  }
1461
1475
  this.autoconsent.updateState({ clicks: this.autoconsent.state.clicks + 1 });
1462
- return this.autoconsent.domActions.waitForThenClick(selector, timeout, all);
1476
+ return this.autoconsent.domActions.waitForThenClick(selector, timeout, all, retries, retryInterval);
1463
1477
  }
1464
1478
  wait(ms) {
1465
1479
  return this.autoconsent.domActions.wait(ms);
@@ -1467,6 +1481,9 @@ var AutoConsentCMPBase = class {
1467
1481
  hide(selector, method) {
1468
1482
  return this.autoconsent.domActions.hide(selector, method);
1469
1483
  }
1484
+ stylesheet(cssRule, stylesheetId) {
1485
+ return this.autoconsent.domActions.stylesheet(cssRule, stylesheetId);
1486
+ }
1470
1487
  removeClass(selector, className) {
1471
1488
  return this.autoconsent.domActions.removeClass(selector, className);
1472
1489
  }
@@ -1580,7 +1597,7 @@ var AutoConsentCMP = class extends AutoConsentCMPBase {
1580
1597
  results.push(this.click(rule.click, rule.all));
1581
1598
  }
1582
1599
  if (rule.waitForThenClick) {
1583
- results.push(this.waitForThenClick(rule.waitForThenClick, rule.timeout, rule.all));
1600
+ results.push(this.waitForThenClick(rule.waitForThenClick, rule.timeout, rule.all, rule.retry, rule.retryInterval));
1584
1601
  }
1585
1602
  if (rule.wait) {
1586
1603
  results.push(this.wait(rule.wait));
@@ -1588,6 +1605,9 @@ var AutoConsentCMP = class extends AutoConsentCMPBase {
1588
1605
  if (rule.hide) {
1589
1606
  results.push(this.hide(rule.hide, rule.method));
1590
1607
  }
1608
+ if (rule.stylesheet !== void 0) {
1609
+ results.push(this.stylesheet(rule.stylesheet, rule.stylesheetId));
1610
+ }
1591
1611
  if (rule.removeClass !== void 0) {
1592
1612
  results.push(rule.selector ? this.removeClass(rule.selector, rule.removeClass) : false);
1593
1613
  }
@@ -2539,6 +2559,8 @@ var dynamicCMPs = [
2539
2559
  ];
2540
2560
 
2541
2561
  // lib/dom-actions.ts
2562
+ var DEFAULT_CLICK_RETRY_INTERVAL = 300;
2563
+ var CLICK_RETRY_POLL_INTERVAL = 50;
2542
2564
  var DomActions = class {
2543
2565
  constructor(autoconsentInstance) {
2544
2566
  this.autoconsentInstance = autoconsentInstance;
@@ -2594,9 +2616,19 @@ var DomActions = class {
2594
2616
  this.autoconsentInstance.config.logs.rulesteps && console.log("[waitForVisible]", selector);
2595
2617
  return waitFor(() => this.elementVisible(selector, check), times, interval);
2596
2618
  }
2597
- async waitForThenClick(selector, timeout = 1e4, all = false) {
2619
+ async waitForThenClick(selector, timeout = 1e4, all = false, retries = 0, retryInterval = DEFAULT_CLICK_RETRY_INTERVAL) {
2598
2620
  await this.waitForElement(selector, timeout);
2599
- return await this.click(selector, all);
2621
+ let clicked = await this.click(selector, all);
2622
+ for (let attempt = 0; clicked && attempt < retries; attempt++) {
2623
+ const pollTimes = Math.ceil(retryInterval / CLICK_RETRY_POLL_INTERVAL);
2624
+ const isGone = await waitFor(() => !this.elementVisible(selector, "any"), pollTimes, CLICK_RETRY_POLL_INTERVAL);
2625
+ if (isGone) {
2626
+ break;
2627
+ }
2628
+ this.autoconsentInstance.config.logs.rulesteps && console.log("[waitForThenClick] retrying click", selector);
2629
+ clicked = await this.click(selector, all);
2630
+ }
2631
+ return clicked;
2600
2632
  }
2601
2633
  wait(ms) {
2602
2634
  this.autoconsentInstance.config.logs.rulesteps && this.autoconsentInstance.config.logs.waits && console.log("[wait]", ms);
@@ -2614,6 +2646,11 @@ var DomActions = class {
2614
2646
  const styleEl = getStyleElement();
2615
2647
  return hideElements(styleEl, selector, method);
2616
2648
  }
2649
+ stylesheet(cssRule, stylesheetId) {
2650
+ this.autoconsentInstance.config.logs.rulesteps && console.log("[stylesheet]", cssRule, stylesheetId);
2651
+ const styleEl = getStyleElement();
2652
+ return appendStylesheetRule(styleEl, cssRule, stylesheetId);
2653
+ }
2617
2654
  removeClass(selector, className) {
2618
2655
  const elements = this.elementSelector(selector);
2619
2656
  this.autoconsentInstance.config.logs.rulesteps && console.log("[removeClass]", selector, className, elements);
@@ -9,7 +9,7 @@
9
9
  var __privateSet = (obj, member, value, setter) => (__accessCheck(obj, member, "write to private field"), setter ? setter.call(obj, value) : member.set(obj, value), value);
10
10
 
11
11
  // lib/rules.ts
12
- var SUPPORTED_RULE_STEP_VERSION = 2;
12
+ var SUPPORTED_RULE_STEP_VERSION = 3;
13
13
 
14
14
  // lib/random.ts
15
15
  function getRandomID() {
@@ -88,6 +88,20 @@
88
88
  }
89
89
  return false;
90
90
  }
91
+ function appendStylesheetRule(styleEl, cssRule, marker) {
92
+ if (!(styleEl instanceof HTMLStyleElement) || cssRule.length === 0) {
93
+ return false;
94
+ }
95
+ const markerComment = marker ? `/* autoconsent:${marker} */` : "";
96
+ if (markerComment && styleEl.innerText.includes(markerComment)) {
97
+ return true;
98
+ }
99
+ if (!markerComment && styleEl.innerText.includes(cssRule.trim())) {
100
+ return true;
101
+ }
102
+ styleEl.innerText += `${markerComment}${markerComment ? " " : ""}${cssRule} `;
103
+ return true;
104
+ }
91
105
  async function waitFor(predicate, maxTimes, interval) {
92
106
  const result = await predicate();
93
107
  if (!result && maxTimes > 0) {
@@ -1456,12 +1470,12 @@
1456
1470
  waitForVisible(selector, timeout, check) {
1457
1471
  return this.autoconsent.domActions.waitForVisible(selector, timeout, check);
1458
1472
  }
1459
- async waitForThenClick(selector, timeout, all) {
1473
+ async waitForThenClick(selector, timeout, all, retries, retryInterval) {
1460
1474
  if (this.autoconsent.config.visualTest) {
1461
1475
  await this.highlightElements(this.elementSelector(selector), all);
1462
1476
  }
1463
1477
  this.autoconsent.updateState({ clicks: this.autoconsent.state.clicks + 1 });
1464
- return this.autoconsent.domActions.waitForThenClick(selector, timeout, all);
1478
+ return this.autoconsent.domActions.waitForThenClick(selector, timeout, all, retries, retryInterval);
1465
1479
  }
1466
1480
  wait(ms) {
1467
1481
  return this.autoconsent.domActions.wait(ms);
@@ -1469,6 +1483,9 @@
1469
1483
  hide(selector, method) {
1470
1484
  return this.autoconsent.domActions.hide(selector, method);
1471
1485
  }
1486
+ stylesheet(cssRule, stylesheetId) {
1487
+ return this.autoconsent.domActions.stylesheet(cssRule, stylesheetId);
1488
+ }
1472
1489
  removeClass(selector, className) {
1473
1490
  return this.autoconsent.domActions.removeClass(selector, className);
1474
1491
  }
@@ -1582,7 +1599,7 @@
1582
1599
  results.push(this.click(rule.click, rule.all));
1583
1600
  }
1584
1601
  if (rule.waitForThenClick) {
1585
- results.push(this.waitForThenClick(rule.waitForThenClick, rule.timeout, rule.all));
1602
+ results.push(this.waitForThenClick(rule.waitForThenClick, rule.timeout, rule.all, rule.retry, rule.retryInterval));
1586
1603
  }
1587
1604
  if (rule.wait) {
1588
1605
  results.push(this.wait(rule.wait));
@@ -1590,6 +1607,9 @@
1590
1607
  if (rule.hide) {
1591
1608
  results.push(this.hide(rule.hide, rule.method));
1592
1609
  }
1610
+ if (rule.stylesheet !== void 0) {
1611
+ results.push(this.stylesheet(rule.stylesheet, rule.stylesheetId));
1612
+ }
1593
1613
  if (rule.removeClass !== void 0) {
1594
1614
  results.push(rule.selector ? this.removeClass(rule.selector, rule.removeClass) : false);
1595
1615
  }
@@ -2541,6 +2561,8 @@
2541
2561
  ];
2542
2562
 
2543
2563
  // lib/dom-actions.ts
2564
+ var DEFAULT_CLICK_RETRY_INTERVAL = 300;
2565
+ var CLICK_RETRY_POLL_INTERVAL = 50;
2544
2566
  var DomActions = class {
2545
2567
  constructor(autoconsentInstance) {
2546
2568
  this.autoconsentInstance = autoconsentInstance;
@@ -2596,9 +2618,19 @@
2596
2618
  this.autoconsentInstance.config.logs.rulesteps && console.log("[waitForVisible]", selector);
2597
2619
  return waitFor(() => this.elementVisible(selector, check), times, interval);
2598
2620
  }
2599
- async waitForThenClick(selector, timeout = 1e4, all = false) {
2621
+ async waitForThenClick(selector, timeout = 1e4, all = false, retries = 0, retryInterval = DEFAULT_CLICK_RETRY_INTERVAL) {
2600
2622
  await this.waitForElement(selector, timeout);
2601
- return await this.click(selector, all);
2623
+ let clicked = await this.click(selector, all);
2624
+ for (let attempt = 0; clicked && attempt < retries; attempt++) {
2625
+ const pollTimes = Math.ceil(retryInterval / CLICK_RETRY_POLL_INTERVAL);
2626
+ const isGone = await waitFor(() => !this.elementVisible(selector, "any"), pollTimes, CLICK_RETRY_POLL_INTERVAL);
2627
+ if (isGone) {
2628
+ break;
2629
+ }
2630
+ this.autoconsentInstance.config.logs.rulesteps && console.log("[waitForThenClick] retrying click", selector);
2631
+ clicked = await this.click(selector, all);
2632
+ }
2633
+ return clicked;
2602
2634
  }
2603
2635
  wait(ms) {
2604
2636
  this.autoconsentInstance.config.logs.rulesteps && this.autoconsentInstance.config.logs.waits && console.log("[wait]", ms);
@@ -2616,6 +2648,11 @@
2616
2648
  const styleEl = getStyleElement();
2617
2649
  return hideElements(styleEl, selector, method);
2618
2650
  }
2651
+ stylesheet(cssRule, stylesheetId) {
2652
+ this.autoconsentInstance.config.logs.rulesteps && console.log("[stylesheet]", cssRule, stylesheetId);
2653
+ const styleEl = getStyleElement();
2654
+ return appendStylesheetRule(styleEl, cssRule, stylesheetId);
2655
+ }
2619
2656
  removeClass(selector, className) {
2620
2657
  const elements = this.elementSelector(selector);
2621
2658
  this.autoconsentInstance.config.logs.rulesteps && console.log("[removeClass]", selector, className, elements);