@duckduckgo/autoconsent 16.51.0 → 16.52.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/workflows/ddg-release.yml +2 -2
- package/AGENTS.md +1 -0
- package/CHANGELOG.md +31 -0
- package/dist/addon-firefox/compact-rules.json +1 -1
- package/dist/addon-firefox/content.bundle.js +4 -1
- package/dist/addon-firefox/manifest.json +1 -1
- package/dist/addon-firefox/rule-index.json +1 -1
- package/dist/addon-firefox/rules.json +1 -1
- package/dist/addon-mv3/compact-rules.json +1 -1
- package/dist/addon-mv3/content.bundle.js +4 -1
- package/dist/addon-mv3/manifest.json +1 -1
- package/dist/addon-mv3/rule-index.json +1 -1
- package/dist/addon-mv3/rules.json +1 -1
- package/dist/autoconsent.cjs.js +4 -1
- package/dist/autoconsent.esm.js +4 -1
- package/dist/autoconsent.playwright.js +4 -1
- package/dist/autoconsent.standalone.js +5 -2
- package/docs/rule-syntax.md +1 -1
- package/lib/dom-actions.ts +5 -1
- package/package.json +1 -1
- package/rules/autoconsent/community.screwfix.com.json +23 -0
- package/rules/autoconsent/la-becanerie.json +13 -0
- package/rules/autoconsent/lta.json +22 -0
- package/rules/autoconsent/mizuno-com.json +13 -0
- package/rules/autoconsent/pigu.json +35 -0
- package/rules/autoconsent/quantcast.json +85 -34
- package/rules/autoconsent/tealium.json +10 -4
- package/rules/compact-rules.json +1 -1
- package/rules/rule-index.json +1 -1
- package/rules/rules.json +1 -1
- package/tests/community.screwfix.com.spec.ts +5 -0
- package/tests/la-becanerie.spec.ts +3 -0
- package/tests/lta.spec.ts +7 -0
- package/tests/mizuno-com.spec.ts +7 -0
- package/tests/pigu.spec.ts +3 -0
- package/tests/quantcast.spec.ts +15 -7
- package/tests/tealium.spec.ts +3 -0
- package/tests-wtr/dom-actions/dom-actions.click.ts +18 -0
- package/Dockerfile +0 -9
package/docs/rule-syntax.md
CHANGED
|
@@ -96,7 +96,7 @@ Waits until element is visible in the page. After `timeout` ms the step fails. T
|
|
|
96
96
|
"all": true | false,
|
|
97
97
|
}
|
|
98
98
|
```
|
|
99
|
-
Click on an element returned by `selector`. If `all` is `true`, all matching elements are clicked. If `all` is `false`, only the first returned value is clicked.
|
|
99
|
+
Click on an element returned by `selector`. If `all` is `true`, all matching elements are clicked one by one, letting the page handle each click before the next one (back-to-back clicks can lose state updates, e.g. on toggle switches). If `all` is `false`, only the first returned value is clicked.
|
|
100
100
|
|
|
101
101
|
## Wait for then click
|
|
102
102
|
```javascript
|
package/lib/dom-actions.ts
CHANGED
|
@@ -26,7 +26,11 @@ export class DomActions implements DomActionsProvider {
|
|
|
26
26
|
|
|
27
27
|
if (elements.length > 0) {
|
|
28
28
|
if (all) {
|
|
29
|
-
|
|
29
|
+
for (const e of elements) {
|
|
30
|
+
e.click();
|
|
31
|
+
// Let the page handle each click first: back-to-back clicks can overwrite each other's state updates.
|
|
32
|
+
await new Promise((resolve) => setTimeout(resolve, 0));
|
|
33
|
+
}
|
|
30
34
|
} else {
|
|
31
35
|
elements[0].click();
|
|
32
36
|
}
|
package/package.json
CHANGED
|
@@ -0,0 +1,23 @@
|
|
|
1
|
+
{
|
|
2
|
+
"name": "community.screwfix.com",
|
|
3
|
+
"vendorUrl": "https://trustarc.com/",
|
|
4
|
+
"comment": "TrustArc banner whose custom CSS adds a full-page #consent-banner::before backdrop that is not removed when the banner closes, leaving the page dimmed and unclickable.",
|
|
5
|
+
"minimumRuleStepVersion": 3,
|
|
6
|
+
"runContext": {
|
|
7
|
+
"main": true,
|
|
8
|
+
"frame": false,
|
|
9
|
+
"urlPattern": "^https?://community\\.screwfix\\.com/"
|
|
10
|
+
},
|
|
11
|
+
"prehideSelectors": ["#consent-banner"],
|
|
12
|
+
"detectCmp": [{ "exists": "#consent-banner #truste-consent-track" }],
|
|
13
|
+
"detectPopup": [{ "visible": "#consent-banner #truste-consent-track" }],
|
|
14
|
+
"optIn": [
|
|
15
|
+
{ "waitForThenClick": "#truste-consent-button" },
|
|
16
|
+
{ "stylesheet": "#consent-banner::before { display: none !important; }", "stylesheetId": "screwfix-backdrop" }
|
|
17
|
+
],
|
|
18
|
+
"optOut": [
|
|
19
|
+
{ "waitForThenClick": "#truste-consent-required" },
|
|
20
|
+
{ "stylesheet": "#consent-banner::before { display: none !important; }", "stylesheetId": "screwfix-backdrop" }
|
|
21
|
+
],
|
|
22
|
+
"test": [{ "cookieContains": "cmapi_cookie_privacy=permit_1_required" }]
|
|
23
|
+
}
|
|
@@ -0,0 +1,13 @@
|
|
|
1
|
+
{
|
|
2
|
+
"name": "la-becanerie",
|
|
3
|
+
"vendorUrl": "https://www.la-becanerie.com/",
|
|
4
|
+
"runContext": {
|
|
5
|
+
"urlPattern": "^https://(www\\.)?la-becanerie\\.com/"
|
|
6
|
+
},
|
|
7
|
+
"prehideSelectors": [".cookieconsent .cc_banner-wrapper"],
|
|
8
|
+
"detectCmp": [{ "exists": ".cookieconsent .cc_banner-wrapper [onclick*='refuseAllCookiesPreferences']" }],
|
|
9
|
+
"detectPopup": [{ "visible": ".cookieconsent .cc_banner" }],
|
|
10
|
+
"optIn": [{ "waitForThenClick": ".cc_banner [onclick*='acceptAllCookiesPreferences']" }],
|
|
11
|
+
"optOut": [{ "waitForThenClick": ".cc_banner [onclick*='refuseAllCookiesPreferences']" }],
|
|
12
|
+
"test": [{ "cookieContains": "_cprefs=%7B%22stats%22%3A1%2C%22fct%22%3A1%2C%22mkt%22%3A1%7D" }]
|
|
13
|
+
}
|
|
@@ -0,0 +1,22 @@
|
|
|
1
|
+
{
|
|
2
|
+
"name": "lta",
|
|
3
|
+
"_metadata": {
|
|
4
|
+
"vendorUrl": "https://www.lta.org.uk/"
|
|
5
|
+
},
|
|
6
|
+
"cosmetic": false,
|
|
7
|
+
"runContext": {
|
|
8
|
+
"main": true,
|
|
9
|
+
"frame": false
|
|
10
|
+
},
|
|
11
|
+
"prehideSelectors": ["#lta-cookies-banner"],
|
|
12
|
+
"detectCmp": [{ "exists": "#lta-cookies-banner" }],
|
|
13
|
+
"detectPopup": [{ "visible": "#lta-cookies-banner" }],
|
|
14
|
+
"optIn": [{ "waitForThenClick": "#lta-cookies-button" }],
|
|
15
|
+
"optOut": [
|
|
16
|
+
{ "waitForThenClick": "#js-lta-cookie-modal-trigger" },
|
|
17
|
+
{ "waitForVisible": "#lta-cookies-modal" },
|
|
18
|
+
{ "click": "#lta-cookies-form input[type=radio][id^=decline-]", "all": true, "optional": true },
|
|
19
|
+
{ "click": "#js-lta-cookie-modal-set" }
|
|
20
|
+
],
|
|
21
|
+
"test": [{ "cookieContains": "%22perf%22:false" }]
|
|
22
|
+
}
|
|
@@ -0,0 +1,13 @@
|
|
|
1
|
+
{
|
|
2
|
+
"name": "mizuno.com",
|
|
3
|
+
"vendorUrl": "https://emea.mizuno.com/",
|
|
4
|
+
"runContext": {
|
|
5
|
+
"urlPattern": "^https?://(\\w+\\.)?mizuno\\.com/"
|
|
6
|
+
},
|
|
7
|
+
"prehideSelectors": ["#consent-tracking"],
|
|
8
|
+
"detectCmp": [{ "exists": "#consent-tracking .btn-necessary" }],
|
|
9
|
+
"detectPopup": [{ "visible": "#consent-tracking" }],
|
|
10
|
+
"optIn": [{ "waitForThenClick": "#consent-tracking .btn-all" }],
|
|
11
|
+
"optOut": [{ "waitForThenClick": "#consent-tracking .btn-necessary" }],
|
|
12
|
+
"test": [{ "cookieContains": "\"marketingCookie\":false" }]
|
|
13
|
+
}
|
|
@@ -0,0 +1,35 @@
|
|
|
1
|
+
{
|
|
2
|
+
"name": "pigu",
|
|
3
|
+
"vendorUrl": "https://pigugroup.eu/",
|
|
4
|
+
"detectCmp": [
|
|
5
|
+
{
|
|
6
|
+
"exists": "#consent_block[widget=\"CookieTracker\"]"
|
|
7
|
+
}
|
|
8
|
+
],
|
|
9
|
+
"detectPopup": [
|
|
10
|
+
{
|
|
11
|
+
"visible": "#consent_block [widget-attachpoint=\"basicAgree\"]"
|
|
12
|
+
}
|
|
13
|
+
],
|
|
14
|
+
"optIn": [
|
|
15
|
+
{
|
|
16
|
+
"waitForThenClick": "#consent_block [widget-attachpoint=\"agree\"]",
|
|
17
|
+
"retry": 10,
|
|
18
|
+
"retryInterval": 500
|
|
19
|
+
}
|
|
20
|
+
],
|
|
21
|
+
"optOut": [
|
|
22
|
+
{
|
|
23
|
+
"waitForThenClick": "#consent_block [widget-attachpoint=\"basicAgree\"]",
|
|
24
|
+
"retry": 10,
|
|
25
|
+
"retryInterval": 500
|
|
26
|
+
}
|
|
27
|
+
],
|
|
28
|
+
"test": [
|
|
29
|
+
{
|
|
30
|
+
"waitForVisible": "#consent_block [widget-attachpoint=\"basicAgree\"]",
|
|
31
|
+
"check": "none",
|
|
32
|
+
"timeout": 2000
|
|
33
|
+
}
|
|
34
|
+
]
|
|
35
|
+
}
|
|
@@ -8,71 +8,122 @@
|
|
|
8
8
|
],
|
|
9
9
|
"detectPopup": [
|
|
10
10
|
{
|
|
11
|
-
"
|
|
11
|
+
"comment": "#qc-cmp2-ui is the GDPR dialog, #qc-cmp2-usp the US 'Do Not Process My Personal Information' (USP/MSPA) dialog",
|
|
12
|
+
"visible": "#qc-cmp2-ui,#qc-cmp2-usp"
|
|
12
13
|
}
|
|
13
14
|
],
|
|
14
15
|
"optOut": [
|
|
15
16
|
{
|
|
17
|
+
"comment": "US dialog: opt out with the toggles, then confirm",
|
|
16
18
|
"if": {
|
|
17
|
-
"exists": "#
|
|
19
|
+
"exists": "#qc-cmp2-usp"
|
|
18
20
|
},
|
|
19
21
|
"then": [
|
|
20
22
|
{
|
|
21
|
-
"
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
|
|
23
|
+
"waitFor": "#qc-cmp2-usp .qc-cmp2-toggle-switch",
|
|
24
|
+
"timeout": 2000,
|
|
25
|
+
"optional": true
|
|
26
|
+
},
|
|
27
|
+
{
|
|
28
|
+
"comment": "each toggle reads 'I want to opt-out of ...', so switching them on is the opt-out",
|
|
29
|
+
"click": "#qc-cmp2-usp .qc-cmp2-toggle-switch > button[aria-checked=\"false\"]",
|
|
30
|
+
"all": true,
|
|
31
|
+
"optional": true
|
|
32
|
+
},
|
|
25
33
|
{
|
|
26
|
-
"
|
|
34
|
+
"waitForThenClick": "#qc-cmp2-usp .qc-usp-ui-form-content button[mode=\"primary\"]",
|
|
27
35
|
"timeout": 2000
|
|
28
36
|
},
|
|
29
37
|
{
|
|
38
|
+
"comment": "confirming opens a success modal that stays until it's closed",
|
|
39
|
+
"waitForThenClick": "#qc-cmp2-mspa-success-modal button",
|
|
40
|
+
"timeout": 2000,
|
|
41
|
+
"optional": true
|
|
42
|
+
}
|
|
43
|
+
],
|
|
44
|
+
"else": [
|
|
45
|
+
{
|
|
46
|
+
"comment": "match the reject button even while it's disabled: falling through to the branch below would click it too early",
|
|
30
47
|
"if": {
|
|
31
|
-
"exists": "
|
|
48
|
+
"exists": "#disagree-btn"
|
|
32
49
|
},
|
|
33
50
|
"then": [
|
|
34
51
|
{
|
|
35
|
-
"
|
|
52
|
+
"comment": "the reject button renders disabled with a loader, and clicks on it are dropped until it's enabled",
|
|
53
|
+
"waitForThenClick": "#disagree-btn:not([disabled])",
|
|
54
|
+
"timeout": 5000
|
|
36
55
|
}
|
|
37
56
|
],
|
|
38
57
|
"else": [
|
|
39
58
|
{
|
|
40
|
-
"
|
|
41
|
-
|
|
42
|
-
{
|
|
43
|
-
"waitForVisible": "#qc-cmp2-ui .qc-cmp2-consent-info"
|
|
44
|
-
},
|
|
45
|
-
{
|
|
46
|
-
"click": ".qc-cmp2-toggle-switch > button[aria-checked=\"true\"]",
|
|
47
|
-
"all": true,
|
|
48
|
-
"optional": true
|
|
49
|
-
},
|
|
50
|
-
{
|
|
51
|
-
"click": [
|
|
52
|
-
".qc-cmp2-main",
|
|
53
|
-
"xpath///button[contains(., 'REJECT ALL') or contains(., 'ALLE VERWERPEN') or contains(., 'ΑΠΟΡΡΙΠΤΩ ΤΑ ΠΑΝΤΑ') or contains(., 'RESPINGERE TOTALĂ') or contains(., 'ALLE ABLEHNEN') or contains(., 'ODRZUCENIE') or contains(., 'BLOQUEAR TODO') or contains(., 'REJEITAR TODOS') or contains(., 'RIFIUTA TUTTO') or contains(., 'TOUT REFUSER') or contains(., 'ОТКЛОНИТЬ ВСЕХ')]"
|
|
54
|
-
],
|
|
55
|
-
"optional": true
|
|
56
|
-
},
|
|
57
|
-
{
|
|
58
|
-
"wait": 500
|
|
59
|
+
"waitFor": ".qc-cmp2-summary-buttons button[mode=\"secondary\"]",
|
|
60
|
+
"timeout": 2000
|
|
59
61
|
},
|
|
60
62
|
{
|
|
63
|
+
"comment": "without #disagree-btn, a secondary button in second place rejects; otherwise reject from the 'more options' screen",
|
|
61
64
|
"if": {
|
|
62
|
-
"exists": ".qc-cmp2-buttons
|
|
65
|
+
"exists": ".qc-cmp2-summary-buttons button[mode=\"secondary\"]:nth-of-type(2)"
|
|
63
66
|
},
|
|
64
67
|
"then": [
|
|
65
68
|
{
|
|
66
|
-
"click": ".qc-cmp2-buttons
|
|
69
|
+
"click": ".qc-cmp2-summary-buttons button[mode=\"secondary\"]:nth-of-type(2)"
|
|
67
70
|
}
|
|
68
71
|
],
|
|
69
72
|
"else": [
|
|
70
73
|
{
|
|
71
|
-
"
|
|
74
|
+
"click": ".qc-cmp2-summary-buttons button[mode=\"secondary\"]:nth-of-type(1)"
|
|
75
|
+
},
|
|
76
|
+
{
|
|
77
|
+
"waitForVisible": "#qc-cmp2-ui .qc-cmp2-consent-info"
|
|
78
|
+
},
|
|
79
|
+
{
|
|
80
|
+
"comment": "turn off the purposes that are switched on by default",
|
|
81
|
+
"click": ".qc-cmp2-toggle-switch > button[aria-checked=\"true\"]",
|
|
82
|
+
"all": true,
|
|
83
|
+
"optional": true
|
|
84
|
+
},
|
|
85
|
+
{
|
|
86
|
+
"comment": "'Reject all' has a localized label",
|
|
87
|
+
"click": [
|
|
72
88
|
".qc-cmp2-main",
|
|
73
|
-
"xpath///button[contains(.,'
|
|
89
|
+
"xpath///button[contains(., 'REJECT ALL') or contains(., 'ALLE VERWERPEN') or contains(., 'ΑΠΟΡΡΙΠΤΩ ΤΑ ΠΑΝΤΑ') or contains(., 'RESPINGERE TOTALĂ') or contains(., 'ALLE ABLEHNEN') or contains(., 'ODRZUCENIE') or contains(., 'BLOQUEAR TODO') or contains(., 'REJEITAR TODOS') or contains(., 'RIFIUTA TUTTO') or contains(., 'TOUT REFUSER') or contains(., 'ОТКЛОНИТЬ ВСЕХ')]"
|
|
74
90
|
],
|
|
75
|
-
"
|
|
91
|
+
"optional": true
|
|
92
|
+
},
|
|
93
|
+
{
|
|
94
|
+
"comment": "'Reject all' can save and close the dialog on its own; give it up to 1s to close before the visibility check",
|
|
95
|
+
"waitForVisible": "#qc-cmp2-ui",
|
|
96
|
+
"check": "none",
|
|
97
|
+
"timeout": 1000,
|
|
98
|
+
"optional": true
|
|
99
|
+
},
|
|
100
|
+
{
|
|
101
|
+
"comment": "only save if 'Reject all' left the dialog open",
|
|
102
|
+
"if": {
|
|
103
|
+
"visible": "#qc-cmp2-ui"
|
|
104
|
+
},
|
|
105
|
+
"then": [
|
|
106
|
+
{
|
|
107
|
+
"comment": "'Save & Exit' is the primary button in the desktop layout; otherwise match its localized label",
|
|
108
|
+
"if": {
|
|
109
|
+
"exists": ".qc-cmp2-buttons-desktop > button[mode=primary]"
|
|
110
|
+
},
|
|
111
|
+
"then": [
|
|
112
|
+
{
|
|
113
|
+
"click": ".qc-cmp2-buttons-desktop > button[mode=primary]"
|
|
114
|
+
}
|
|
115
|
+
],
|
|
116
|
+
"else": [
|
|
117
|
+
{
|
|
118
|
+
"waitForThenClick": [
|
|
119
|
+
".qc-cmp2-main",
|
|
120
|
+
"xpath///button[contains(.,'SAVE & EXIT') or contains(.,'SALVA ED ESCI') or contains(.,'GUARDAR Y SALIR') or contains(.,'SPEICHERN & VERLASSEN')"
|
|
121
|
+
],
|
|
122
|
+
"timeout": 5000
|
|
123
|
+
}
|
|
124
|
+
]
|
|
125
|
+
}
|
|
126
|
+
]
|
|
76
127
|
}
|
|
77
128
|
]
|
|
78
129
|
}
|
|
@@ -83,7 +134,7 @@
|
|
|
83
134
|
],
|
|
84
135
|
"optIn": [
|
|
85
136
|
{
|
|
86
|
-
"click": ".qc-cmp2-summary-buttons
|
|
137
|
+
"click": ".qc-cmp2-summary-buttons button[mode=\"primary\"]"
|
|
87
138
|
}
|
|
88
139
|
]
|
|
89
140
|
}
|
|
@@ -6,11 +6,17 @@
|
|
|
6
6
|
"optOut": [
|
|
7
7
|
{ "eval": "EVAL_TEALIUM_1" },
|
|
8
8
|
{ "eval": "EVAL_TEALIUM_DONOTSELL" },
|
|
9
|
-
{ "hide": "#__tealiumGDPRecModal,#__tealiumGDPRcpPrefs,#__tealiumImplicitmodal" },
|
|
10
9
|
{
|
|
11
|
-
"
|
|
12
|
-
"
|
|
13
|
-
"
|
|
10
|
+
"if": { "exists": "#__tealiumGDPRecModal #rejectAll" },
|
|
11
|
+
"then": [{ "waitForThenClick": "#__tealiumGDPRecModal #rejectAll" }],
|
|
12
|
+
"else": [
|
|
13
|
+
{ "hide": "#__tealiumGDPRecModal,#__tealiumGDPRcpPrefs,#__tealiumImplicitmodal" },
|
|
14
|
+
{
|
|
15
|
+
"waitForThenClick": "#cm-acceptNone,.js-accept-essential-cookies,#continueWithoutAccepting,#no_consent,#consent_prompt_decline,#teal-decline-consent",
|
|
16
|
+
"timeout": 1000,
|
|
17
|
+
"optional": true
|
|
18
|
+
}
|
|
19
|
+
]
|
|
14
20
|
}
|
|
15
21
|
],
|
|
16
22
|
"optIn": [{ "hide": "#__tealiumGDPRecModal,#__tealiumGDPRcpPrefs" }, { "eval": "EVAL_TEALIUM_2" }],
|