@duckduckgo/autoconsent 14.0.1 → 14.2.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 (53) hide show
  1. package/.github/actions/setup-release-scripts/action.yml +1 -1
  2. package/.github/workflows/checks.yml +4 -4
  3. package/.github/workflows/release.yml +2 -2
  4. package/.github/workflows/update-filterlist.yml +2 -2
  5. package/CHANGELOG.md +43 -0
  6. package/api.md +1 -0
  7. package/dist/addon-firefox/background.bundle.js +11 -2
  8. package/dist/addon-firefox/content.bundle.js +510 -347
  9. package/dist/addon-firefox/manifest.json +1 -1
  10. package/dist/addon-firefox/rules.json +1 -1
  11. package/dist/addon-mv3/background.bundle.js +11 -2
  12. package/dist/addon-mv3/content.bundle.js +510 -347
  13. package/dist/addon-mv3/manifest.json +1 -1
  14. package/dist/addon-mv3/popup.bundle.js +19 -1
  15. package/dist/addon-mv3/popup.html +14 -0
  16. package/dist/addon-mv3/rules.json +1 -1
  17. package/dist/autoconsent.cjs.js +353 -219
  18. package/dist/autoconsent.esm.js +354 -219
  19. package/dist/autoconsent.extra.cjs.js +519 -347
  20. package/dist/autoconsent.extra.esm.js +520 -347
  21. package/dist/autoconsent.playwright.js +520 -348
  22. package/lib/cmps/admiral.ts +6 -6
  23. package/lib/cmps/base.ts +43 -8
  24. package/lib/cmps/consentmanager.ts +8 -7
  25. package/lib/cmps/cookiebot.ts +4 -4
  26. package/lib/cmps/evidon.ts +2 -2
  27. package/lib/cmps/klaro.ts +8 -8
  28. package/lib/cmps/onetrust.ts +6 -6
  29. package/lib/cmps/sourcepoint-frame.ts +12 -12
  30. package/lib/cmps/tiktok.ts +3 -3
  31. package/lib/cmps/trustarc-frame.ts +11 -11
  32. package/lib/cmps/trustarc-top.ts +2 -6
  33. package/lib/dom-actions.ts +6 -6
  34. package/lib/eval-snippets.ts +6 -1
  35. package/lib/filterlist-engine.ts +2 -2
  36. package/lib/messages.ts +6 -0
  37. package/lib/types.ts +3 -2
  38. package/lib/utils.ts +49 -0
  39. package/lib/web.ts +50 -37
  40. package/package.json +2 -2
  41. package/playwright/runner.ts +1 -1
  42. package/readme.md +1 -1
  43. package/rules/autoconsent/cookie-law-info.json +16 -5
  44. package/rules/autoconsent/cookiehub.json +61 -0
  45. package/rules/autoconsent/eu-cookie-compliance.json +13 -12
  46. package/rules/compact-rules.json +1 -1
  47. package/rules/filterlist.txt +221 -202
  48. package/rules/rules.json +1 -1
  49. package/tests/{cookielawinfo.spec.ts → cookie-law-info.spec.ts} +4 -1
  50. package/tests/cookiehub.spec.ts +8 -0
  51. package/tests/eu-cookie-compliance-banner.spec.ts +1 -1
  52. package/tests-wtr/dom-actions/dom-actions.click.ts +14 -14
  53. package/tests-wtr/utils/highlight.test.ts +166 -0
@@ -4,4 +4,7 @@ generateCMPTests('cookie-law-info', ['https://www.omas-gegen-rechts.org/', 'http
4
4
  skipRegions: ['US', 'GB'],
5
5
  });
6
6
 
7
- generateCMPTests('cookie-law-info', ['https://www.sbid.org/']);
7
+ generateCMPTests('cookie-law-info', [
8
+ 'https://www.sbid.org/',
9
+ 'https://diroots.com/revit-plugins/renumber-revit-elements-using-a-prefix-a-suffix-and-a-multiplier-with-reordering/',
10
+ ]);
@@ -0,0 +1,8 @@
1
+ import generateCMPTests from '../playwright/runner';
2
+
3
+ generateCMPTests('cookiehub', [
4
+ 'https://shorthand.com/',
5
+ 'https://www.semrush.com/',
6
+ 'https://www.nonstopdogwear.com/en/',
7
+ 'https://searchengineland.com/',
8
+ ]);
@@ -1,3 +1,3 @@
1
1
  import generateCMPTests from '../playwright/runner';
2
2
 
3
- generateCMPTests('eu-cookie-compliance-banner', ['https://www.theposh.com/table/226', 'https://publichealth.jhu.edu/']);
3
+ generateCMPTests('eu-cookie-compliance-banner', ['https://publichealth.jhu.edu/', 'https://bibliotheek.be/']);
@@ -7,10 +7,10 @@ describe('click', () => {
7
7
  let clickCounter2: number;
8
8
 
9
9
  before(() => {
10
- document.querySelector('#first > button').addEventListener('click', () => {
10
+ document.querySelector('#first > button')?.addEventListener('click', () => {
11
11
  clickCounter1++;
12
12
  });
13
- document.querySelector('#second > button').addEventListener('click', () => {
13
+ document.querySelector('#second > button')?.addEventListener('click', () => {
14
14
  clickCounter2++;
15
15
  });
16
16
  });
@@ -20,24 +20,24 @@ describe('click', () => {
20
20
  clickCounter2 = 0;
21
21
  });
22
22
 
23
- it('clicks on a button', () => {
23
+ it('clicks on a button', async () => {
24
24
  // Given
25
25
  const domActions = instantiateDomActions();
26
26
 
27
27
  // When
28
- const clickedSuccessfully = domActions.click('#test');
28
+ const clickedSuccessfully = await domActions.click('#test');
29
29
 
30
30
  // Then
31
31
  expect(clickedSuccessfully).true;
32
32
  expect(clickCounter1).to.equal(1);
33
33
  });
34
34
 
35
- it('clicks all upon multiple matches when all=true', () => {
35
+ it('clicks all upon multiple matches when all=true', async () => {
36
36
  // Given
37
37
  const domActions = instantiateDomActions();
38
38
 
39
39
  // When
40
- const clickedSuccessfully = domActions.click('button', true);
40
+ const clickedSuccessfully = await domActions.click('button', true);
41
41
 
42
42
  // Then
43
43
  expect(clickedSuccessfully).true;
@@ -45,12 +45,12 @@ describe('click', () => {
45
45
  expect(clickCounter2).to.equal(1);
46
46
  });
47
47
 
48
- it('clicks only first one upon multiple matches when all=false', () => {
48
+ it('clicks only first one upon multiple matches when all=false', async () => {
49
49
  // Given
50
50
  const domActions = instantiateDomActions();
51
51
 
52
52
  // When
53
- const clickedSuccessfully = domActions.click('button');
53
+ const clickedSuccessfully = await domActions.click('button');
54
54
 
55
55
  // Then
56
56
  expect(clickedSuccessfully).true;
@@ -58,12 +58,12 @@ describe('click', () => {
58
58
  expect(clickCounter2).to.equal(0);
59
59
  });
60
60
 
61
- it('clicks by chained selector', () => {
61
+ it('clicks by chained selector', async () => {
62
62
  // Given
63
63
  const domActions = instantiateDomActions();
64
64
 
65
65
  // When
66
- const clickedSuccessfully = domActions.click(['#second', 'button']);
66
+ const clickedSuccessfully = await domActions.click(['#second', 'button']);
67
67
 
68
68
  // Then
69
69
  expect(clickedSuccessfully).true;
@@ -71,12 +71,12 @@ describe('click', () => {
71
71
  expect(clickCounter2).to.equal(1);
72
72
  });
73
73
 
74
- it('clicks by xpath selector', () => {
74
+ it('clicks by xpath selector', async () => {
75
75
  // Given
76
76
  const domActions = instantiateDomActions();
77
77
 
78
78
  // When
79
- const clickedSuccessfully = domActions.click(['xpath///*[@id="second"]/button']);
79
+ const clickedSuccessfully = await domActions.click(['xpath///*[@id="second"]/button']);
80
80
 
81
81
  // Then
82
82
  expect(clickedSuccessfully).true;
@@ -84,7 +84,7 @@ describe('click', () => {
84
84
  expect(clickCounter2).to.equal(1);
85
85
  });
86
86
 
87
- it('clicks an open shadow dom element', () => {
87
+ it('clicks an open shadow dom element', async () => {
88
88
  // Given
89
89
  const domActions = instantiateDomActions();
90
90
 
@@ -101,7 +101,7 @@ describe('click', () => {
101
101
  });
102
102
 
103
103
  // When
104
- const clickedSuccessfully = domActions.click(['#shadow', 'button']);
104
+ const clickedSuccessfully = await domActions.click(['#shadow', 'button']);
105
105
 
106
106
  // Then
107
107
  expect(clickedSuccessfully).true;
@@ -0,0 +1,166 @@
1
+ import { expect } from '@esm-bundle/chai';
2
+ import { highlightNode, unhighlightNode } from '../../lib/utils.js'; // Assuming utils.ts or TS can resolve .js
3
+
4
+ declare global {
5
+ interface HTMLElement {
6
+ __oldStyles?: string;
7
+ }
8
+ }
9
+
10
+ describe('Node highlighting', () => {
11
+ let testElement: HTMLElement;
12
+ let styleTag: HTMLStyleElement | null;
13
+
14
+ beforeEach(() => {
15
+ // Create a new element for each test
16
+ testElement = document.createElement('div');
17
+ document.body.appendChild(testElement);
18
+ // Remove the style tag if it exists from a previous test
19
+ styleTag = document.getElementById('autoconsent-debug-styles') as HTMLStyleElement | null;
20
+ if (styleTag) {
21
+ styleTag.remove();
22
+ }
23
+ });
24
+
25
+ afterEach(() => {
26
+ // Clean up the element and style tag after each test
27
+ if (testElement.parentNode) {
28
+ testElement.parentNode.removeChild(testElement);
29
+ }
30
+ styleTag = document.getElementById('autoconsent-debug-styles') as HTMLStyleElement | null;
31
+ if (styleTag) {
32
+ styleTag.remove();
33
+ }
34
+ });
35
+
36
+ describe('highlightNode', () => {
37
+ it('should apply highlight styles and add keyframes style tag', () => {
38
+ const originalCssText = testElement.style.cssText;
39
+ highlightNode(testElement);
40
+
41
+ // Check that style was applied (is different from original) and a style attribute exists
42
+ expect(testElement.style.cssText).to.not.equal(originalCssText);
43
+ expect(testElement.hasAttribute('style')).to.be.true;
44
+
45
+ styleTag = document.getElementById('autoconsent-debug-styles') as HTMLStyleElement;
46
+ expect(styleTag).to.not.be.null;
47
+ if (styleTag) {
48
+ // type guard
49
+ expect(styleTag.textContent).to.contain('@keyframes pulsate');
50
+ }
51
+ });
52
+
53
+ it('should store original inline styles if present', () => {
54
+ testElement.style.color = 'blue';
55
+ testElement.style.fontSize = '16px';
56
+ const originalCssText = testElement.style.cssText;
57
+
58
+ highlightNode(testElement);
59
+
60
+ expect(testElement.__oldStyles).to.equal(originalCssText);
61
+ // Check that current styles are different from original
62
+ expect(testElement.style.cssText).to.not.equal(originalCssText);
63
+ });
64
+
65
+ it('should not store original styles if no inline styles are present', () => {
66
+ highlightNode(testElement);
67
+ expect(testElement.__oldStyles).to.be.undefined;
68
+ });
69
+
70
+ it('should do nothing if node has no style property (e.g., not an HTMLElement)', () => {
71
+ const notAnElement = {} as any; // Using any here to test non-HTMLElement behavior
72
+ highlightNode(notAnElement);
73
+ // No error should be thrown, and no properties should be added.
74
+ expect(notAnElement.style).to.be.undefined;
75
+ expect(notAnElement.__oldStyles).to.be.undefined;
76
+
77
+ styleTag = document.getElementById('autoconsent-debug-styles') as HTMLStyleElement | null;
78
+ expect(styleTag).to.be.null; // Style tag should not be added if node.style is undefined
79
+ });
80
+
81
+ it('should handle elements without a pre-existing style attribute', () => {
82
+ highlightNode(testElement);
83
+ expect(testElement.hasAttribute('style')).to.be.true;
84
+ expect(testElement.__oldStyles).to.be.undefined; // No old styles to store
85
+ });
86
+
87
+ it('should handle being called twice on the same element', () => {
88
+ testElement.style.color = 'blue';
89
+ testElement.style.fontSize = '16px';
90
+ const originalCssText = testElement.style.cssText;
91
+
92
+ // First call
93
+ highlightNode(testElement);
94
+ expect(testElement.__oldStyles).to.equal(originalCssText);
95
+ const highlightCssText = testElement.style.cssText;
96
+
97
+ // Second call
98
+ highlightNode(testElement);
99
+
100
+ // Should preserve the original styles, not the first highlight styles
101
+ expect(testElement.__oldStyles).to.equal(originalCssText);
102
+ expect(testElement.__oldStyles).to.not.equal(highlightCssText);
103
+
104
+ // Should still be highlighted (styles should be different from original)
105
+ expect(testElement.style.cssText).to.not.equal(originalCssText);
106
+
107
+ // Should still be highlighted (styles should not have changed)
108
+ expect(testElement.style.cssText).to.equal(highlightCssText);
109
+
110
+ // Should not create a second style tag
111
+ expect(document.querySelectorAll('#autoconsent-debug-styles').length).to.equal(1);
112
+ });
113
+ });
114
+
115
+ describe('unhighlightNode', () => {
116
+ it('should remove highlight styles and restore original styles if they existed', () => {
117
+ testElement.style.color = 'blue';
118
+ const originalCssText = testElement.style.cssText;
119
+ highlightNode(testElement);
120
+ expect(testElement.__oldStyles).to.equal(originalCssText);
121
+ const highlightedCssText = testElement.style.cssText;
122
+
123
+ unhighlightNode(testElement);
124
+
125
+ expect(testElement.style.cssText).to.equal(originalCssText);
126
+ expect(testElement.style.cssText).to.not.equal(highlightedCssText);
127
+ expect(testElement.__oldStyles).to.be.undefined;
128
+ });
129
+
130
+ it('should remove style attribute if no original styles were present', () => {
131
+ highlightNode(testElement);
132
+ expect(testElement.hasAttribute('style')).to.be.true;
133
+ expect(testElement.__oldStyles).to.be.undefined;
134
+
135
+ unhighlightNode(testElement);
136
+
137
+ expect(testElement.hasAttribute('style')).to.be.false;
138
+ });
139
+
140
+ it('should do nothing if node has no style property', () => {
141
+ const notAnElement = {} as any; // Using any here to test non-HTMLElement behavior
142
+ highlightNode(notAnElement);
143
+ unhighlightNode(notAnElement);
144
+ // No error should be thrown, and no properties should be changed or added.
145
+ expect(notAnElement.style).to.be.undefined;
146
+ expect(notAnElement.__oldStyles).to.be.undefined;
147
+ });
148
+
149
+ it('should do nothing if node has no style attribute (e.g., highlight was not called)', () => {
150
+ const initialAttributes = Array.from(testElement.attributes).map((attr) => attr.name);
151
+ unhighlightNode(testElement);
152
+ const finalAttributes = Array.from(testElement.attributes).map((attr) => attr.name);
153
+ expect(finalAttributes).to.deep.equal(initialAttributes);
154
+ });
155
+
156
+ it('should do nothing if node.style exists but no style attribute is set', () => {
157
+ Object.defineProperty(testElement, 'hasAttribute', { value: () => false, configurable: true });
158
+ const initialStyleCssText = testElement.style.cssText; // Should be empty
159
+
160
+ unhighlightNode(testElement);
161
+
162
+ expect(testElement.style.cssText).to.equal(initialStyleCssText);
163
+ expect(testElement.__oldStyles).to.be.undefined;
164
+ });
165
+ });
166
+ });