@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.
- package/.github/actions/setup-release-scripts/action.yml +1 -1
- package/.github/workflows/checks.yml +4 -4
- package/.github/workflows/release.yml +2 -2
- package/.github/workflows/update-filterlist.yml +2 -2
- package/CHANGELOG.md +43 -0
- package/api.md +1 -0
- package/dist/addon-firefox/background.bundle.js +11 -2
- package/dist/addon-firefox/content.bundle.js +510 -347
- package/dist/addon-firefox/manifest.json +1 -1
- package/dist/addon-firefox/rules.json +1 -1
- package/dist/addon-mv3/background.bundle.js +11 -2
- package/dist/addon-mv3/content.bundle.js +510 -347
- package/dist/addon-mv3/manifest.json +1 -1
- package/dist/addon-mv3/popup.bundle.js +19 -1
- package/dist/addon-mv3/popup.html +14 -0
- package/dist/addon-mv3/rules.json +1 -1
- package/dist/autoconsent.cjs.js +353 -219
- package/dist/autoconsent.esm.js +354 -219
- package/dist/autoconsent.extra.cjs.js +519 -347
- package/dist/autoconsent.extra.esm.js +520 -347
- package/dist/autoconsent.playwright.js +520 -348
- package/lib/cmps/admiral.ts +6 -6
- package/lib/cmps/base.ts +43 -8
- package/lib/cmps/consentmanager.ts +8 -7
- package/lib/cmps/cookiebot.ts +4 -4
- package/lib/cmps/evidon.ts +2 -2
- package/lib/cmps/klaro.ts +8 -8
- package/lib/cmps/onetrust.ts +6 -6
- package/lib/cmps/sourcepoint-frame.ts +12 -12
- package/lib/cmps/tiktok.ts +3 -3
- package/lib/cmps/trustarc-frame.ts +11 -11
- package/lib/cmps/trustarc-top.ts +2 -6
- package/lib/dom-actions.ts +6 -6
- package/lib/eval-snippets.ts +6 -1
- package/lib/filterlist-engine.ts +2 -2
- package/lib/messages.ts +6 -0
- package/lib/types.ts +3 -2
- package/lib/utils.ts +49 -0
- package/lib/web.ts +50 -37
- package/package.json +2 -2
- package/playwright/runner.ts +1 -1
- package/readme.md +1 -1
- package/rules/autoconsent/cookie-law-info.json +16 -5
- package/rules/autoconsent/cookiehub.json +61 -0
- package/rules/autoconsent/eu-cookie-compliance.json +13 -12
- package/rules/compact-rules.json +1 -1
- package/rules/filterlist.txt +221 -202
- package/rules/rules.json +1 -1
- package/tests/{cookielawinfo.spec.ts → cookie-law-info.spec.ts} +4 -1
- package/tests/cookiehub.spec.ts +8 -0
- package/tests/eu-cookie-compliance-banner.spec.ts +1 -1
- package/tests-wtr/dom-actions/dom-actions.click.ts +14 -14
- 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', [
|
|
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
|
+
]);
|
|
@@ -1,3 +1,3 @@
|
|
|
1
1
|
import generateCMPTests from '../playwright/runner';
|
|
2
2
|
|
|
3
|
-
generateCMPTests('eu-cookie-compliance-banner', ['https://
|
|
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')
|
|
10
|
+
document.querySelector('#first > button')?.addEventListener('click', () => {
|
|
11
11
|
clickCounter1++;
|
|
12
12
|
});
|
|
13
|
-
document.querySelector('#second > button')
|
|
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
|
+
});
|